Update vendor dir and Godeps.json with new Godep
This commit is contained in:
98
vendor/github.com/onsi/ginkgo/extensions/table/table.go
generated
vendored
98
vendor/github.com/onsi/ginkgo/extensions/table/table.go
generated
vendored
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
|
||||
Table provides a simple DSL for Ginkgo-native Table-Driven Tests
|
||||
|
||||
The godoc documentation describes Table's API. More comprehensive documentation (with examples!) is available at http://onsi.github.io/ginkgo#table-driven-tests
|
||||
|
||||
*/
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
/*
|
||||
DescribeTable describes a table-driven test.
|
||||
|
||||
For example:
|
||||
|
||||
DescribeTable("a simple table",
|
||||
func(x int, y int, expected bool) {
|
||||
Ω(x > y).Should(Equal(expected))
|
||||
},
|
||||
Entry("x > y", 1, 0, true),
|
||||
Entry("x == y", 0, 0, false),
|
||||
Entry("x < y", 0, 1, false),
|
||||
)
|
||||
|
||||
The first argument to `DescribeTable` is a string description.
|
||||
The second argument is a function that will be run for each table entry. Your assertions go here - the function is equivalent to a Ginkgo It.
|
||||
The subsequent arguments must be of type `TableEntry`. We recommend using the `Entry` convenience constructors.
|
||||
|
||||
The `Entry` constructor takes a string description followed by an arbitrary set of parameters. These parameters are passed into your function.
|
||||
|
||||
Under the hood, `DescribeTable` simply generates a new Ginkgo `Describe`. Each `Entry` is turned into an `It` within the `Describe`.
|
||||
|
||||
It's important to understand that the `Describe`s and `It`s are generated at evaluation time (i.e. when Ginkgo constructs the tree of tests and before the tests run).
|
||||
|
||||
Individual Entries can be focused (with FEntry) or marked pending (with PEntry or XEntry). In addition, the entire table can be focused or marked pending with FDescribeTable and PDescribeTable/XDescribeTable.
|
||||
*/
|
||||
func DescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, false, false)
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`.
|
||||
*/
|
||||
func FDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, false, true)
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a table as pending with `PDescribeTable`. This is equivalent to `PDescribe`.
|
||||
*/
|
||||
func PDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, true, false)
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a table as pending with `XDescribeTable`. This is equivalent to `XDescribe`.
|
||||
*/
|
||||
func XDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, true, false)
|
||||
return true
|
||||
}
|
||||
|
||||
func describeTable(description string, itBody interface{}, entries []TableEntry, pending bool, focused bool) {
|
||||
itBodyValue := reflect.ValueOf(itBody)
|
||||
if itBodyValue.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("DescribeTable expects a function, got %#v", itBody))
|
||||
}
|
||||
|
||||
if pending {
|
||||
ginkgo.PDescribe(description, func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
} else if focused {
|
||||
ginkgo.FDescribe(description, func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ginkgo.Describe(description, func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
81
vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
generated
vendored
81
vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
generated
vendored
@@ -1,81 +0,0 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
/*
|
||||
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
|
||||
*/
|
||||
type TableEntry struct {
|
||||
Description string
|
||||
Parameters []interface{}
|
||||
Pending bool
|
||||
Focused bool
|
||||
}
|
||||
|
||||
func (t TableEntry) generateIt(itBody reflect.Value) {
|
||||
if t.Pending {
|
||||
ginkgo.PIt(t.Description)
|
||||
return
|
||||
}
|
||||
|
||||
values := []reflect.Value{}
|
||||
for i, param := range t.Parameters {
|
||||
var value reflect.Value
|
||||
|
||||
if param == nil {
|
||||
inType := itBody.Type().In(i)
|
||||
value = reflect.Zero(inType)
|
||||
} else {
|
||||
value = reflect.ValueOf(param)
|
||||
}
|
||||
|
||||
values = append(values, value)
|
||||
}
|
||||
|
||||
body := func() {
|
||||
itBody.Call(values)
|
||||
}
|
||||
|
||||
if t.Focused {
|
||||
ginkgo.FIt(t.Description, body)
|
||||
} else {
|
||||
ginkgo.It(t.Description, body)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Entry constructs a TableEntry.
|
||||
|
||||
The first argument is a required description (this becomes the content of the generated Ginkgo `It`).
|
||||
Subsequent parameters are saved off and sent to the callback passed in to `DescribeTable`.
|
||||
|
||||
Each Entry ends up generating an individual Ginkgo It.
|
||||
*/
|
||||
func Entry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, false, false}
|
||||
}
|
||||
|
||||
/*
|
||||
You can focus a particular entry with FEntry. This is equivalent to FIt.
|
||||
*/
|
||||
func FEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, false, true}
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a particular entry as pending with PEntry. This is equivalent to PIt.
|
||||
*/
|
||||
func PEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, true, false}
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a particular entry as pending with XEntry. This is equivalent to XIt.
|
||||
*/
|
||||
func XEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, true, false}
|
||||
}
|
1
vendor/github.com/onsi/ginkgo/integration/integration.go
generated
vendored
1
vendor/github.com/onsi/ginkgo/integration/integration.go
generated
vendored
@@ -1 +0,0 @@
|
||||
package integration
|
229
vendor/github.com/onsi/gomega/gbytes/buffer.go
generated
vendored
229
vendor/github.com/onsi/gomega/gbytes/buffer.go
generated
vendored
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
Package gbytes provides a buffer that supports incrementally detecting input.
|
||||
|
||||
You use gbytes.Buffer with the gbytes.Say matcher. When Say finds a match, it fastforwards the buffer's read cursor to the end of that match.
|
||||
|
||||
Subsequent matches against the buffer will only operate against data that appears *after* the read cursor.
|
||||
|
||||
The read cursor is an opaque implementation detail that you cannot access. You should use the Say matcher to sift through the buffer. You can always
|
||||
access the entire buffer's contents with Contents().
|
||||
|
||||
*/
|
||||
package gbytes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
gbytes.Buffer implements an io.Writer and can be used with the gbytes.Say matcher.
|
||||
|
||||
You should only use a gbytes.Buffer in test code. It stores all writes in an in-memory buffer - behavior that is inappropriate for production code!
|
||||
*/
|
||||
type Buffer struct {
|
||||
contents []byte
|
||||
readCursor uint64
|
||||
lock *sync.Mutex
|
||||
detectCloser chan interface{}
|
||||
closed bool
|
||||
}
|
||||
|
||||
/*
|
||||
NewBuffer returns a new gbytes.Buffer
|
||||
*/
|
||||
func NewBuffer() *Buffer {
|
||||
return &Buffer{
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BufferWithBytes returns a new gbytes.Buffer seeded with the passed in bytes
|
||||
*/
|
||||
func BufferWithBytes(bytes []byte) *Buffer {
|
||||
return &Buffer{
|
||||
lock: &sync.Mutex{},
|
||||
contents: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Write implements the io.Writer interface
|
||||
*/
|
||||
func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.closed {
|
||||
return 0, errors.New("attempt to write to closed buffer")
|
||||
}
|
||||
|
||||
b.contents = append(b.contents, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
/*
|
||||
Read implements the io.Reader interface. It advances the
|
||||
cursor as it reads.
|
||||
|
||||
Returns an error if called after Close.
|
||||
*/
|
||||
func (b *Buffer) Read(d []byte) (int, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.closed {
|
||||
return 0, errors.New("attempt to read from closed buffer")
|
||||
}
|
||||
|
||||
if uint64(len(b.contents)) <= b.readCursor {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := copy(d, b.contents[b.readCursor:])
|
||||
b.readCursor += uint64(n)
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Close signifies that the buffer will no longer be written to
|
||||
*/
|
||||
func (b *Buffer) Close() error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.closed = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
Closed returns true if the buffer has been closed
|
||||
*/
|
||||
func (b *Buffer) Closed() bool {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
return b.closed
|
||||
}
|
||||
|
||||
/*
|
||||
Contents returns all data ever written to the buffer.
|
||||
*/
|
||||
func (b *Buffer) Contents() []byte {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
contents := make([]byte, len(b.contents))
|
||||
copy(contents, b.contents)
|
||||
return contents
|
||||
}
|
||||
|
||||
/*
|
||||
Detect takes a regular expression and returns a channel.
|
||||
|
||||
The channel will receive true the first time data matching the regular expression is written to the buffer.
|
||||
The channel is subsequently closed and the buffer's read-cursor is fast-forwarded to just after the matching region.
|
||||
|
||||
You typically don't need to use Detect and should use the ghttp.Say matcher instead. Detect is useful, however, in cases where your code must
|
||||
be branch and handle different outputs written to the buffer.
|
||||
|
||||
For example, consider a buffer hooked up to the stdout of a client library. You may (or may not, depending on state outside of your control) need to authenticate the client library.
|
||||
|
||||
You could do something like:
|
||||
|
||||
select {
|
||||
case <-buffer.Detect("You are not logged in"):
|
||||
//log in
|
||||
case <-buffer.Detect("Success"):
|
||||
//carry on
|
||||
case <-time.After(time.Second):
|
||||
//welp
|
||||
}
|
||||
buffer.CancelDetects()
|
||||
|
||||
You should always call CancelDetects after using Detect. This will close any channels that have not detected and clean up the goroutines that were spawned to support them.
|
||||
|
||||
Finally, you can pass detect a format string followed by variadic arguments. This will construct the regexp using fmt.Sprintf.
|
||||
*/
|
||||
func (b *Buffer) Detect(desired string, args ...interface{}) chan bool {
|
||||
formattedRegexp := desired
|
||||
if len(args) > 0 {
|
||||
formattedRegexp = fmt.Sprintf(desired, args...)
|
||||
}
|
||||
re := regexp.MustCompile(formattedRegexp)
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.detectCloser == nil {
|
||||
b.detectCloser = make(chan interface{})
|
||||
}
|
||||
|
||||
closer := b.detectCloser
|
||||
response := make(chan bool)
|
||||
go func() {
|
||||
ticker := time.NewTicker(10 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
defer close(response)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
b.lock.Lock()
|
||||
data, cursor := b.contents[b.readCursor:], b.readCursor
|
||||
loc := re.FindIndex(data)
|
||||
b.lock.Unlock()
|
||||
|
||||
if loc != nil {
|
||||
response <- true
|
||||
b.lock.Lock()
|
||||
newCursorPosition := cursor + uint64(loc[1])
|
||||
if newCursorPosition >= b.readCursor {
|
||||
b.readCursor = newCursorPosition
|
||||
}
|
||||
b.lock.Unlock()
|
||||
return
|
||||
}
|
||||
case <-closer:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
/*
|
||||
CancelDetects cancels any pending detects and cleans up their goroutines. You should always call this when you're done with a set of Detect channels.
|
||||
*/
|
||||
func (b *Buffer) CancelDetects() {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
close(b.detectCloser)
|
||||
b.detectCloser = nil
|
||||
}
|
||||
|
||||
func (b *Buffer) didSay(re *regexp.Regexp) (bool, []byte) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
unreadBytes := b.contents[b.readCursor:]
|
||||
copyOfUnreadBytes := make([]byte, len(unreadBytes))
|
||||
copy(copyOfUnreadBytes, unreadBytes)
|
||||
|
||||
loc := re.FindIndex(unreadBytes)
|
||||
|
||||
if loc != nil {
|
||||
b.readCursor += uint64(loc[1])
|
||||
return true, copyOfUnreadBytes
|
||||
} else {
|
||||
return false, copyOfUnreadBytes
|
||||
}
|
||||
}
|
105
vendor/github.com/onsi/gomega/gbytes/say_matcher.go
generated
vendored
105
vendor/github.com/onsi/gomega/gbytes/say_matcher.go
generated
vendored
@@ -1,105 +0,0 @@
|
||||
package gbytes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
//Objects satisfying the BufferProvider can be used with the Say matcher.
|
||||
type BufferProvider interface {
|
||||
Buffer() *Buffer
|
||||
}
|
||||
|
||||
/*
|
||||
Say is a Gomega matcher that operates on gbytes.Buffers:
|
||||
|
||||
Ω(buffer).Should(Say("something"))
|
||||
|
||||
will succeed if the unread portion of the buffer matches the regular expression "something".
|
||||
|
||||
When Say succeeds, it fast forwards the gbytes.Buffer's read cursor to just after the succesful match.
|
||||
Thus, subsequent calls to Say will only match against the unread portion of the buffer
|
||||
|
||||
Say pairs very well with Eventually. To asser that a buffer eventually receives data matching "[123]-star" within 3 seconds you can:
|
||||
|
||||
Eventually(buffer, 3).Should(Say("[123]-star"))
|
||||
|
||||
Ditto with consistently. To assert that a buffer does not receive data matching "never-see-this" for 1 second you can:
|
||||
|
||||
Consistently(buffer, 1).ShouldNot(Say("never-see-this"))
|
||||
|
||||
In addition to bytes.Buffers, Say can operate on objects that implement the gbytes.BufferProvider interface.
|
||||
In such cases, Say simply operates on the *gbytes.Buffer returned by Buffer()
|
||||
|
||||
If the buffer is closed, the Say matcher will tell Eventually to abort.
|
||||
*/
|
||||
func Say(expected string, args ...interface{}) *sayMatcher {
|
||||
formattedRegexp := expected
|
||||
if len(args) > 0 {
|
||||
formattedRegexp = fmt.Sprintf(expected, args...)
|
||||
}
|
||||
return &sayMatcher{
|
||||
re: regexp.MustCompile(formattedRegexp),
|
||||
}
|
||||
}
|
||||
|
||||
type sayMatcher struct {
|
||||
re *regexp.Regexp
|
||||
receivedSayings []byte
|
||||
}
|
||||
|
||||
func (m *sayMatcher) buffer(actual interface{}) (*Buffer, bool) {
|
||||
var buffer *Buffer
|
||||
|
||||
switch x := actual.(type) {
|
||||
case *Buffer:
|
||||
buffer = x
|
||||
case BufferProvider:
|
||||
buffer = x.Buffer()
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return buffer, true
|
||||
}
|
||||
|
||||
func (m *sayMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
buffer, ok := m.buffer(actual)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("Say must be passed a *gbytes.Buffer or BufferProvider. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
didSay, sayings := buffer.didSay(m.re)
|
||||
m.receivedSayings = sayings
|
||||
|
||||
return didSay, nil
|
||||
}
|
||||
|
||||
func (m *sayMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return fmt.Sprintf(
|
||||
"Got stuck at:\n%s\nWaiting for:\n%s",
|
||||
format.IndentString(string(m.receivedSayings), 1),
|
||||
format.IndentString(m.re.String(), 1),
|
||||
)
|
||||
}
|
||||
|
||||
func (m *sayMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return fmt.Sprintf(
|
||||
"Saw:\n%s\nWhich matches the unexpected:\n%s",
|
||||
format.IndentString(string(m.receivedSayings), 1),
|
||||
format.IndentString(m.re.String(), 1),
|
||||
)
|
||||
}
|
||||
|
||||
func (m *sayMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
switch x := actual.(type) {
|
||||
case *Buffer:
|
||||
return !x.Closed()
|
||||
case BufferProvider:
|
||||
return !x.Buffer().Closed()
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
78
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
78
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
@@ -1,78 +0,0 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var tmpDir string
|
||||
|
||||
/*
|
||||
Build uses go build to compile the package at packagePath. The resulting binary is saved off in a temporary directory.
|
||||
A path pointing to this binary is returned.
|
||||
|
||||
Build uses the $GOPATH set in your environment. It passes the variadic args on to `go build`.
|
||||
*/
|
||||
func Build(packagePath string, args ...string) (compiledPath string, err error) {
|
||||
return BuildIn(os.Getenv("GOPATH"), packagePath, args...)
|
||||
}
|
||||
|
||||
/*
|
||||
BuildIn is identical to Build but allows you to specify a custom $GOPATH (the first argument).
|
||||
*/
|
||||
func BuildIn(gopath string, packagePath string, args ...string) (compiledPath string, err error) {
|
||||
tmpDir, err := temporaryDirectory()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(gopath) == 0 {
|
||||
return "", errors.New("$GOPATH not provided when building " + packagePath)
|
||||
}
|
||||
|
||||
executable := filepath.Join(tmpDir, path.Base(packagePath))
|
||||
if runtime.GOOS == "windows" {
|
||||
executable = executable + ".exe"
|
||||
}
|
||||
|
||||
cmdArgs := append([]string{"build"}, args...)
|
||||
cmdArgs = append(cmdArgs, "-o", executable, packagePath)
|
||||
|
||||
build := exec.Command("go", cmdArgs...)
|
||||
build.Env = append([]string{"GOPATH=" + gopath}, os.Environ()...)
|
||||
|
||||
output, err := build.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to build %s:\n\nError:\n%s\n\nOutput:\n%s", packagePath, err, string(output))
|
||||
}
|
||||
|
||||
return executable, nil
|
||||
}
|
||||
|
||||
/*
|
||||
You should call CleanupBuildArtifacts before your test ends to clean up any temporary artifacts generated by
|
||||
gexec. In Ginkgo this is typically done in an AfterSuite callback.
|
||||
*/
|
||||
func CleanupBuildArtifacts() {
|
||||
if tmpDir != "" {
|
||||
os.RemoveAll(tmpDir)
|
||||
}
|
||||
}
|
||||
|
||||
func temporaryDirectory() (string, error) {
|
||||
var err error
|
||||
if tmpDir == "" {
|
||||
tmpDir, err = ioutil.TempDir("", "gexec_artifacts")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return ioutil.TempDir(tmpDir, "g")
|
||||
}
|
88
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
88
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
@@ -1,88 +0,0 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
/*
|
||||
The Exit matcher operates on a session:
|
||||
|
||||
Ω(session).Should(Exit(<optional status code>))
|
||||
|
||||
Exit passes if the session has already exited.
|
||||
|
||||
If no status code is provided, then Exit will succeed if the session has exited regardless of exit code.
|
||||
Otherwise, Exit will only succeed if the process has exited with the provided status code.
|
||||
|
||||
Note that the process must have already exited. To wait for a process to exit, use Eventually:
|
||||
|
||||
Eventually(session, 3).Should(Exit(0))
|
||||
*/
|
||||
func Exit(optionalExitCode ...int) *exitMatcher {
|
||||
exitCode := -1
|
||||
if len(optionalExitCode) > 0 {
|
||||
exitCode = optionalExitCode[0]
|
||||
}
|
||||
|
||||
return &exitMatcher{
|
||||
exitCode: exitCode,
|
||||
}
|
||||
}
|
||||
|
||||
type exitMatcher struct {
|
||||
exitCode int
|
||||
didExit bool
|
||||
actualExitCode int
|
||||
}
|
||||
|
||||
type Exiter interface {
|
||||
ExitCode() int
|
||||
}
|
||||
|
||||
func (m *exitMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
exiter, ok := actual.(Exiter)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("Exit must be passed a gexec.Exiter (Missing method ExitCode() int) Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
m.actualExitCode = exiter.ExitCode()
|
||||
|
||||
if m.actualExitCode == -1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if m.exitCode == -1 {
|
||||
return true, nil
|
||||
}
|
||||
return m.exitCode == m.actualExitCode, nil
|
||||
}
|
||||
|
||||
func (m *exitMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
if m.actualExitCode == -1 {
|
||||
return "Expected process to exit. It did not."
|
||||
} else {
|
||||
return format.Message(m.actualExitCode, "to match exit code:", m.exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *exitMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
if m.actualExitCode == -1 {
|
||||
return "you really shouldn't be able to see this!"
|
||||
} else {
|
||||
if m.exitCode == -1 {
|
||||
return "Expected process not to exit. It did."
|
||||
} else {
|
||||
return format.Message(m.actualExitCode, "not to match exit code:", m.exitCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *exitMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
session, ok := actual.(*Session)
|
||||
if ok {
|
||||
return session.ExitCode() == -1
|
||||
}
|
||||
return true
|
||||
}
|
53
vendor/github.com/onsi/gomega/gexec/prefixed_writer.go
generated
vendored
53
vendor/github.com/onsi/gomega/gexec/prefixed_writer.go
generated
vendored
@@ -1,53 +0,0 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
/*
|
||||
PrefixedWriter wraps an io.Writer, emiting the passed in prefix at the beginning of each new line.
|
||||
This can be useful when running multiple gexec.Sessions concurrently - you can prefix the log output of each
|
||||
session by passing in a PrefixedWriter:
|
||||
|
||||
gexec.Start(cmd, NewPrefixedWriter("[my-cmd] ", GinkgoWriter), NewPrefixedWriter("[my-cmd] ", GinkgoWriter))
|
||||
*/
|
||||
type PrefixedWriter struct {
|
||||
prefix []byte
|
||||
writer io.Writer
|
||||
lock *sync.Mutex
|
||||
atStartOfLine bool
|
||||
}
|
||||
|
||||
func NewPrefixedWriter(prefix string, writer io.Writer) *PrefixedWriter {
|
||||
return &PrefixedWriter{
|
||||
prefix: []byte(prefix),
|
||||
writer: writer,
|
||||
lock: &sync.Mutex{},
|
||||
atStartOfLine: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *PrefixedWriter) Write(b []byte) (int, error) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
|
||||
toWrite := []byte{}
|
||||
|
||||
for _, c := range b {
|
||||
if w.atStartOfLine {
|
||||
toWrite = append(toWrite, w.prefix...)
|
||||
}
|
||||
|
||||
toWrite = append(toWrite, c)
|
||||
|
||||
w.atStartOfLine = c == '\n'
|
||||
}
|
||||
|
||||
_, err := w.writer.Write(toWrite)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(b), nil
|
||||
}
|
214
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
214
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
Package gexec provides support for testing external processes.
|
||||
*/
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gbytes"
|
||||
)
|
||||
|
||||
const INVALID_EXIT_CODE = 254
|
||||
|
||||
type Session struct {
|
||||
//The wrapped command
|
||||
Command *exec.Cmd
|
||||
|
||||
//A *gbytes.Buffer connected to the command's stdout
|
||||
Out *gbytes.Buffer
|
||||
|
||||
//A *gbytes.Buffer connected to the command's stderr
|
||||
Err *gbytes.Buffer
|
||||
|
||||
//A channel that will close when the command exits
|
||||
Exited <-chan struct{}
|
||||
|
||||
lock *sync.Mutex
|
||||
exitCode int
|
||||
}
|
||||
|
||||
/*
|
||||
Start starts the passed-in *exec.Cmd command. It wraps the command in a *gexec.Session.
|
||||
|
||||
The session pipes the command's stdout and stderr to two *gbytes.Buffers available as properties on the session: session.Out and session.Err.
|
||||
These buffers can be used with the gbytes.Say matcher to match against unread output:
|
||||
|
||||
Ω(session.Out).Should(gbytes.Say("foo-out"))
|
||||
Ω(session.Err).Should(gbytes.Say("foo-err"))
|
||||
|
||||
In addition, Session satisfies the gbytes.BufferProvider interface and provides the stdout *gbytes.Buffer. This allows you to replace the first line, above, with:
|
||||
|
||||
Ω(session).Should(gbytes.Say("foo-out"))
|
||||
|
||||
When outWriter and/or errWriter are non-nil, the session will pipe stdout and/or stderr output both into the session *gybtes.Buffers and to the passed-in outWriter/errWriter.
|
||||
This is useful for capturing the process's output or logging it to screen. In particular, when using Ginkgo it can be convenient to direct output to the GinkgoWriter:
|
||||
|
||||
session, err := Start(command, GinkgoWriter, GinkgoWriter)
|
||||
|
||||
This will log output when running tests in verbose mode, but - otherwise - will only log output when a test fails.
|
||||
|
||||
The session wrapper is responsible for waiting on the *exec.Cmd command. You *should not* call command.Wait() yourself.
|
||||
Instead, to assert that the command has exited you can use the gexec.Exit matcher:
|
||||
|
||||
Ω(session).Should(gexec.Exit())
|
||||
|
||||
When the session exits it closes the stdout and stderr gbytes buffers. This will short circuit any
|
||||
Eventuallys waiting fo the buffers to Say something.
|
||||
*/
|
||||
func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) {
|
||||
exited := make(chan struct{})
|
||||
|
||||
session := &Session{
|
||||
Command: command,
|
||||
Out: gbytes.NewBuffer(),
|
||||
Err: gbytes.NewBuffer(),
|
||||
Exited: exited,
|
||||
lock: &sync.Mutex{},
|
||||
exitCode: -1,
|
||||
}
|
||||
|
||||
var commandOut, commandErr io.Writer
|
||||
|
||||
commandOut, commandErr = session.Out, session.Err
|
||||
|
||||
if outWriter != nil && !reflect.ValueOf(outWriter).IsNil() {
|
||||
commandOut = io.MultiWriter(commandOut, outWriter)
|
||||
}
|
||||
|
||||
if errWriter != nil && !reflect.ValueOf(errWriter).IsNil() {
|
||||
commandErr = io.MultiWriter(commandErr, errWriter)
|
||||
}
|
||||
|
||||
command.Stdout = commandOut
|
||||
command.Stderr = commandErr
|
||||
|
||||
err := command.Start()
|
||||
if err == nil {
|
||||
go session.monitorForExit(exited)
|
||||
}
|
||||
|
||||
return session, err
|
||||
}
|
||||
|
||||
/*
|
||||
Buffer implements the gbytes.BufferProvider interface and returns s.Out
|
||||
This allows you to make gbytes.Say matcher assertions against stdout without having to reference .Out:
|
||||
|
||||
Eventually(session).Should(gbytes.Say("foo"))
|
||||
*/
|
||||
func (s *Session) Buffer() *gbytes.Buffer {
|
||||
return s.Out
|
||||
}
|
||||
|
||||
/*
|
||||
ExitCode returns the wrapped command's exit code. If the command hasn't exited yet, ExitCode returns -1.
|
||||
|
||||
To assert that the command has exited it is more convenient to use the Exit matcher:
|
||||
|
||||
Eventually(s).Should(gexec.Exit())
|
||||
|
||||
When the process exits because it has received a particular signal, the exit code will be 128+signal-value
|
||||
(See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html)
|
||||
|
||||
*/
|
||||
func (s *Session) ExitCode() int {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
return s.exitCode
|
||||
}
|
||||
|
||||
/*
|
||||
Wait waits until the wrapped command exits. It can be passed an optional timeout.
|
||||
If the command does not exit within the timeout, Wait will trigger a test failure.
|
||||
|
||||
Wait returns the session, making it possible to chain:
|
||||
|
||||
session.Wait().Out.Contents()
|
||||
|
||||
will wait for the command to exit then return the entirety of Out's contents.
|
||||
|
||||
Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does.
|
||||
*/
|
||||
func (s *Session) Wait(timeout ...interface{}) *Session {
|
||||
EventuallyWithOffset(1, s, timeout...).Should(Exit())
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
Kill sends the running command a SIGKILL signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Kill returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Kill() *Session {
|
||||
if s.ExitCode() != -1 {
|
||||
return s
|
||||
}
|
||||
s.Command.Process.Kill()
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
Interrupt sends the running command a SIGINT signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Interrupt returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Interrupt() *Session {
|
||||
return s.Signal(syscall.SIGINT)
|
||||
}
|
||||
|
||||
/*
|
||||
Terminate sends the running command a SIGTERM signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Terminate returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Terminate() *Session {
|
||||
return s.Signal(syscall.SIGTERM)
|
||||
}
|
||||
|
||||
/*
|
||||
Terminate sends the running command the passed in signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Signal returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Signal(signal os.Signal) *Session {
|
||||
if s.ExitCode() != -1 {
|
||||
return s
|
||||
}
|
||||
s.Command.Process.Signal(signal)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) monitorForExit(exited chan<- struct{}) {
|
||||
err := s.Command.Wait()
|
||||
s.lock.Lock()
|
||||
s.Out.Close()
|
||||
s.Err.Close()
|
||||
status := s.Command.ProcessState.Sys().(syscall.WaitStatus)
|
||||
if status.Signaled() {
|
||||
s.exitCode = 128 + int(status.Signal())
|
||||
} else {
|
||||
exitStatus := status.ExitStatus()
|
||||
if exitStatus == -1 && err != nil {
|
||||
s.exitCode = INVALID_EXIT_CODE
|
||||
}
|
||||
s.exitCode = exitStatus
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
close(exited)
|
||||
}
|
313
vendor/github.com/onsi/gomega/ghttp/handlers.go
generated
vendored
313
vendor/github.com/onsi/gomega/ghttp/handlers.go
generated
vendored
@@ -1,313 +0,0 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
//CombineHandler takes variadic list of handlers and produces one handler
|
||||
//that calls each handler in order.
|
||||
func CombineHandlers(handlers ...http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
for _, handler := range handlers {
|
||||
handler(w, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyRequest returns a handler that verifies that a request uses the specified method to connect to the specified path
|
||||
//You may also pass in an optional rawQuery string which is tested against the request's `req.URL.RawQuery`
|
||||
//
|
||||
//For path, you may pass in a string, in which case strict equality will be applied
|
||||
//Alternatively you can pass in a matcher (ContainSubstring("/foo") and MatchRegexp("/foo/[a-f0-9]+") for example)
|
||||
func VerifyRequest(method string, path interface{}, rawQuery ...string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
Ω(req.Method).Should(Equal(method), "Method mismatch")
|
||||
switch p := path.(type) {
|
||||
case types.GomegaMatcher:
|
||||
Ω(req.URL.Path).Should(p, "Path mismatch")
|
||||
default:
|
||||
Ω(req.URL.Path).Should(Equal(path), "Path mismatch")
|
||||
}
|
||||
if len(rawQuery) > 0 {
|
||||
values, err := url.ParseQuery(rawQuery[0])
|
||||
Ω(err).ShouldNot(HaveOccurred(), "Expected RawQuery is malformed")
|
||||
|
||||
Ω(req.URL.Query()).Should(Equal(values), "RawQuery mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyContentType returns a handler that verifies that a request has a Content-Type header set to the
|
||||
//specified value
|
||||
func VerifyContentType(contentType string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
Ω(req.Header.Get("Content-Type")).Should(Equal(contentType))
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyBasicAuth returns a handler that verifies the request contains a BasicAuth Authorization header
|
||||
//matching the passed in username and password
|
||||
func VerifyBasicAuth(username string, password string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
auth := req.Header.Get("Authorization")
|
||||
Ω(auth).ShouldNot(Equal(""), "Authorization header must be specified")
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(auth[6:])
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Ω(string(decoded)).Should(Equal(fmt.Sprintf("%s:%s", username, password)), "Authorization mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyHeader returns a handler that verifies the request contains the passed in headers.
|
||||
//The passed in header keys are first canonicalized via http.CanonicalHeaderKey.
|
||||
//
|
||||
//The request must contain *all* the passed in headers, but it is allowed to have additional headers
|
||||
//beyond the passed in set.
|
||||
func VerifyHeader(header http.Header) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
for key, values := range header {
|
||||
key = http.CanonicalHeaderKey(key)
|
||||
Ω(req.Header[key]).Should(Equal(values), "Header mismatch for key: %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyHeaderKV returns a handler that verifies the request contains a header matching the passed in key and values
|
||||
//(recall that a `http.Header` is a mapping from string (key) to []string (values))
|
||||
//It is a convenience wrapper around `VerifyHeader` that allows you to avoid having to create an `http.Header` object.
|
||||
func VerifyHeaderKV(key string, values ...string) http.HandlerFunc {
|
||||
return VerifyHeader(http.Header{key: values})
|
||||
}
|
||||
|
||||
//VerifyBody returns a handler that verifies that the body of the request matches the passed in byte array.
|
||||
//It does this using Equal().
|
||||
func VerifyBody(expectedBody []byte) http.HandlerFunc {
|
||||
return CombineHandlers(
|
||||
func(w http.ResponseWriter, req *http.Request) {
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
req.Body.Close()
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(body).Should(Equal(expectedBody), "Body Mismatch")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
//VerifyJSON returns a handler that verifies that the body of the request is a valid JSON representation
|
||||
//matching the passed in JSON string. It does this using Gomega's MatchJSON method
|
||||
//
|
||||
//VerifyJSON also verifies that the request's content type is application/json
|
||||
func VerifyJSON(expectedJSON string) http.HandlerFunc {
|
||||
return CombineHandlers(
|
||||
VerifyContentType("application/json"),
|
||||
func(w http.ResponseWriter, req *http.Request) {
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
req.Body.Close()
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(body).Should(MatchJSON(expectedJSON), "JSON Mismatch")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
//VerifyJSONRepresenting is similar to VerifyJSON. Instead of taking a JSON string, however, it
|
||||
//takes an arbitrary JSON-encodable object and verifies that the requests's body is a JSON representation
|
||||
//that matches the object
|
||||
func VerifyJSONRepresenting(object interface{}) http.HandlerFunc {
|
||||
data, err := json.Marshal(object)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
return CombineHandlers(
|
||||
VerifyContentType("application/json"),
|
||||
VerifyJSON(string(data)),
|
||||
)
|
||||
}
|
||||
|
||||
//VerifyForm returns a handler that verifies a request contains the specified form values.
|
||||
//
|
||||
//The request must contain *all* of the specified values, but it is allowed to have additional
|
||||
//form values beyond the passed in set.
|
||||
func VerifyForm(values url.Values) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
for key, vals := range values {
|
||||
Ω(r.Form[key]).Should(Equal(vals), "Form mismatch for key: %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//VerifyFormKV returns a handler that verifies a request contains a form key with the specified values.
|
||||
//
|
||||
//It is a convenience wrapper around `VerifyForm` that lets you avoid having to create a `url.Values` object.
|
||||
func VerifyFormKV(key string, values ...string) http.HandlerFunc {
|
||||
return VerifyForm(url.Values{key: values})
|
||||
}
|
||||
|
||||
//VerifyProtoRepresenting returns a handler that verifies that the body of the request is a valid protobuf
|
||||
//representation of the passed message.
|
||||
//
|
||||
//VerifyProtoRepresenting also verifies that the request's content type is application/x-protobuf
|
||||
func VerifyProtoRepresenting(expected proto.Message) http.HandlerFunc {
|
||||
return CombineHandlers(
|
||||
VerifyContentType("application/x-protobuf"),
|
||||
func(w http.ResponseWriter, req *http.Request) {
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
req.Body.Close()
|
||||
|
||||
expectedType := reflect.TypeOf(expected)
|
||||
actualValuePtr := reflect.New(expectedType.Elem())
|
||||
|
||||
actual, ok := actualValuePtr.Interface().(proto.Message)
|
||||
Ω(ok).Should(BeTrue(), "Message value is not a proto.Message")
|
||||
|
||||
err = proto.Unmarshal(body, actual)
|
||||
Ω(err).ShouldNot(HaveOccurred(), "Failed to unmarshal protobuf")
|
||||
|
||||
Ω(actual).Should(Equal(expected), "ProtoBuf Mismatch")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func copyHeader(src http.Header, dst http.Header) {
|
||||
for key, value := range src {
|
||||
dst[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RespondWith returns a handler that responds to a request with the specified status code and body
|
||||
|
||||
Body may be a string or []byte
|
||||
|
||||
Also, RespondWith can be given an optional http.Header. The headers defined therein will be added to the response headers.
|
||||
*/
|
||||
func RespondWith(statusCode int, body interface{}, optionalHeader ...http.Header) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
if len(optionalHeader) == 1 {
|
||||
copyHeader(optionalHeader[0], w.Header())
|
||||
}
|
||||
w.WriteHeader(statusCode)
|
||||
switch x := body.(type) {
|
||||
case string:
|
||||
w.Write([]byte(x))
|
||||
case []byte:
|
||||
w.Write(x)
|
||||
default:
|
||||
Ω(body).Should(BeNil(), "Invalid type for body. Should be string or []byte.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RespondWithPtr returns a handler that responds to a request with the specified status code and body
|
||||
|
||||
Unlike RespondWith, you pass RepondWithPtr a pointer to the status code and body allowing different tests
|
||||
to share the same setup but specify different status codes and bodies.
|
||||
|
||||
Also, RespondWithPtr can be given an optional http.Header. The headers defined therein will be added to the response headers.
|
||||
Since the http.Header can be mutated after the fact you don't need to pass in a pointer.
|
||||
*/
|
||||
func RespondWithPtr(statusCode *int, body interface{}, optionalHeader ...http.Header) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
if len(optionalHeader) == 1 {
|
||||
copyHeader(optionalHeader[0], w.Header())
|
||||
}
|
||||
w.WriteHeader(*statusCode)
|
||||
if body != nil {
|
||||
switch x := (body).(type) {
|
||||
case *string:
|
||||
w.Write([]byte(*x))
|
||||
case *[]byte:
|
||||
w.Write(*x)
|
||||
default:
|
||||
Ω(body).Should(BeNil(), "Invalid type for body. Should be string or []byte.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RespondWithJSONEncoded returns a handler that responds to a request with the specified status code and a body
|
||||
containing the JSON-encoding of the passed in object
|
||||
|
||||
Also, RespondWithJSONEncoded can be given an optional http.Header. The headers defined therein will be added to the response headers.
|
||||
*/
|
||||
func RespondWithJSONEncoded(statusCode int, object interface{}, optionalHeader ...http.Header) http.HandlerFunc {
|
||||
data, err := json.Marshal(object)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
|
||||
var headers http.Header
|
||||
if len(optionalHeader) == 1 {
|
||||
headers = optionalHeader[0]
|
||||
} else {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
if _, found := headers["Content-Type"]; !found {
|
||||
headers["Content-Type"] = []string{"application/json"}
|
||||
}
|
||||
return RespondWith(statusCode, string(data), headers)
|
||||
}
|
||||
|
||||
/*
|
||||
RespondWithJSONEncodedPtr behaves like RespondWithJSONEncoded but takes a pointer
|
||||
to a status code and object.
|
||||
|
||||
This allows different tests to share the same setup but specify different status codes and JSON-encoded
|
||||
objects.
|
||||
|
||||
Also, RespondWithJSONEncodedPtr can be given an optional http.Header. The headers defined therein will be added to the response headers.
|
||||
Since the http.Header can be mutated after the fact you don't need to pass in a pointer.
|
||||
*/
|
||||
func RespondWithJSONEncodedPtr(statusCode *int, object interface{}, optionalHeader ...http.Header) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
data, err := json.Marshal(object)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
var headers http.Header
|
||||
if len(optionalHeader) == 1 {
|
||||
headers = optionalHeader[0]
|
||||
} else {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
if _, found := headers["Content-Type"]; !found {
|
||||
headers["Content-Type"] = []string{"application/json"}
|
||||
}
|
||||
copyHeader(headers, w.Header())
|
||||
w.WriteHeader(*statusCode)
|
||||
w.Write(data)
|
||||
}
|
||||
}
|
||||
|
||||
//RespondWithProto returns a handler that responds to a request with the specified status code and a body
|
||||
//containing the protobuf serialization of the provided message.
|
||||
//
|
||||
//Also, RespondWithProto can be given an optional http.Header. The headers defined therein will be added to the response headers.
|
||||
func RespondWithProto(statusCode int, message proto.Message, optionalHeader ...http.Header) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
data, err := proto.Marshal(message)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
|
||||
var headers http.Header
|
||||
if len(optionalHeader) == 1 {
|
||||
headers = optionalHeader[0]
|
||||
} else {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
if _, found := headers["Content-Type"]; !found {
|
||||
headers["Content-Type"] = []string{"application/x-protobuf"}
|
||||
}
|
||||
copyHeader(headers, w.Header())
|
||||
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(data)
|
||||
}
|
||||
}
|
3
vendor/github.com/onsi/gomega/ghttp/protobuf/protobuf.go
generated
vendored
3
vendor/github.com/onsi/gomega/ghttp/protobuf/protobuf.go
generated
vendored
@@ -1,3 +0,0 @@
|
||||
package protobuf
|
||||
|
||||
//go:generate protoc --go_out=. simple_message.proto
|
55
vendor/github.com/onsi/gomega/ghttp/protobuf/simple_message.pb.go
generated
vendored
55
vendor/github.com/onsi/gomega/ghttp/protobuf/simple_message.pb.go
generated
vendored
@@ -1,55 +0,0 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: simple_message.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package protobuf is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
simple_message.proto
|
||||
|
||||
It has these top-level messages:
|
||||
SimpleMessage
|
||||
*/
|
||||
package protobuf
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type SimpleMessage struct {
|
||||
Description *string `protobuf:"bytes,1,req,name=description" json:"description,omitempty"`
|
||||
Id *int32 `protobuf:"varint,2,req,name=id" json:"id,omitempty"`
|
||||
Metadata *string `protobuf:"bytes,3,opt,name=metadata" json:"metadata,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SimpleMessage) Reset() { *m = SimpleMessage{} }
|
||||
func (m *SimpleMessage) String() string { return proto.CompactTextString(m) }
|
||||
func (*SimpleMessage) ProtoMessage() {}
|
||||
|
||||
func (m *SimpleMessage) GetDescription() string {
|
||||
if m != nil && m.Description != nil {
|
||||
return *m.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SimpleMessage) GetId() int32 {
|
||||
if m != nil && m.Id != nil {
|
||||
return *m.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SimpleMessage) GetMetadata() string {
|
||||
if m != nil && m.Metadata != nil {
|
||||
return *m.Metadata
|
||||
}
|
||||
return ""
|
||||
}
|
9
vendor/github.com/onsi/gomega/ghttp/protobuf/simple_message.proto
generated
vendored
9
vendor/github.com/onsi/gomega/ghttp/protobuf/simple_message.proto
generated
vendored
@@ -1,9 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package protobuf;
|
||||
|
||||
message SimpleMessage {
|
||||
required string description = 1;
|
||||
required int32 id = 2;
|
||||
optional string metadata = 3;
|
||||
}
|
379
vendor/github.com/onsi/gomega/ghttp/test_server.go
generated
vendored
379
vendor/github.com/onsi/gomega/ghttp/test_server.go
generated
vendored
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
Package ghttp supports testing HTTP clients by providing a test server (simply a thin wrapper around httptest's server) that supports
|
||||
registering multiple handlers. Incoming requests are not routed between the different handlers
|
||||
- rather it is merely the order of the handlers that matters. The first request is handled by the first
|
||||
registered handler, the second request by the second handler, etc.
|
||||
|
||||
The intent here is to have each handler *verify* that the incoming request is valid. To accomplish, ghttp
|
||||
also provides a collection of bite-size handlers that each perform one aspect of request verification. These can
|
||||
be composed together and registered with a ghttp server. The result is an expressive language for describing
|
||||
the requests generated by the client under test.
|
||||
|
||||
Here's a simple example, note that the server handler is only defined in one BeforeEach and then modified, as required, by the nested BeforeEaches.
|
||||
A more comprehensive example is available at https://onsi.github.io/gomega/#_testing_http_clients
|
||||
|
||||
var _ = Describe("A Sprockets Client", func() {
|
||||
var server *ghttp.Server
|
||||
var client *SprocketClient
|
||||
BeforeEach(func() {
|
||||
server = ghttp.NewServer()
|
||||
client = NewSprocketClient(server.URL(), "skywalker", "tk427")
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
server.Close()
|
||||
})
|
||||
|
||||
Describe("fetching sprockets", func() {
|
||||
var statusCode int
|
||||
var sprockets []Sprocket
|
||||
BeforeEach(func() {
|
||||
statusCode = http.StatusOK
|
||||
sprockets = []Sprocket{}
|
||||
server.AppendHandlers(ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", "/sprockets"),
|
||||
ghttp.VerifyBasicAuth("skywalker", "tk427"),
|
||||
ghttp.RespondWithJSONEncodedPtr(&statusCode, &sprockets),
|
||||
))
|
||||
})
|
||||
|
||||
Context("when requesting all sprockets", func() {
|
||||
Context("when the response is succesful", func() {
|
||||
BeforeEach(func() {
|
||||
sprockets = []Sprocket{
|
||||
NewSprocket("Alfalfa"),
|
||||
NewSprocket("Banana"),
|
||||
}
|
||||
})
|
||||
|
||||
It("should return the returned sprockets", func() {
|
||||
Ω(client.Sprockets()).Should(Equal(sprockets))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the response is missing", func() {
|
||||
BeforeEach(func() {
|
||||
statusCode = http.StatusNotFound
|
||||
})
|
||||
|
||||
It("should return an empty list of sprockets", func() {
|
||||
Ω(client.Sprockets()).Should(BeEmpty())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the response fails to authenticate", func() {
|
||||
BeforeEach(func() {
|
||||
statusCode = http.StatusUnauthorized
|
||||
})
|
||||
|
||||
It("should return an AuthenticationError error", func() {
|
||||
sprockets, err := client.Sprockets()
|
||||
Ω(sprockets).Should(BeEmpty())
|
||||
Ω(err).Should(MatchError(AuthenticationError))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the response is a server failure", func() {
|
||||
BeforeEach(func() {
|
||||
statusCode = http.StatusInternalServerError
|
||||
})
|
||||
|
||||
It("should return an InternalError error", func() {
|
||||
sprockets, err := client.Sprockets()
|
||||
Ω(sprockets).Should(BeEmpty())
|
||||
Ω(err).Should(MatchError(InternalError))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when requesting some sprockets", func() {
|
||||
BeforeEach(func() {
|
||||
sprockets = []Sprocket{
|
||||
NewSprocket("Alfalfa"),
|
||||
NewSprocket("Banana"),
|
||||
}
|
||||
|
||||
server.WrapHandler(0, ghttp.VerifyRequest("GET", "/sprockets", "filter=FOOD"))
|
||||
})
|
||||
|
||||
It("should make the request with a filter", func() {
|
||||
Ω(client.Sprockets("food")).Should(Equal(sprockets))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
*/
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func new() *Server {
|
||||
return &Server{
|
||||
AllowUnhandledRequests: false,
|
||||
UnhandledRequestStatusCode: http.StatusInternalServerError,
|
||||
writeLock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
type routedHandler struct {
|
||||
method string
|
||||
pathRegexp *regexp.Regexp
|
||||
path string
|
||||
handler http.HandlerFunc
|
||||
}
|
||||
|
||||
// NewServer returns a new `*ghttp.Server` that wraps an `httptest` server. The server is started automatically.
|
||||
func NewServer() *Server {
|
||||
s := new()
|
||||
s.HTTPTestServer = httptest.NewServer(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewUnstartedServer return a new, unstarted, `*ghttp.Server`. Useful for specifying a custom listener on `server.HTTPTestServer`.
|
||||
func NewUnstartedServer() *Server {
|
||||
s := new()
|
||||
s.HTTPTestServer = httptest.NewUnstartedServer(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewTLSServer returns a new `*ghttp.Server` that wraps an `httptest` TLS server. The server is started automatically.
|
||||
func NewTLSServer() *Server {
|
||||
s := new()
|
||||
s.HTTPTestServer = httptest.NewTLSServer(s)
|
||||
return s
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
//The underlying httptest server
|
||||
HTTPTestServer *httptest.Server
|
||||
|
||||
//Defaults to false. If set to true, the Server will allow more requests than there are registered handlers.
|
||||
AllowUnhandledRequests bool
|
||||
|
||||
//The status code returned when receiving an unhandled request.
|
||||
//Defaults to http.StatusInternalServerError.
|
||||
//Only applies if AllowUnhandledRequests is true
|
||||
UnhandledRequestStatusCode int
|
||||
|
||||
//If provided, ghttp will log about each request received to the provided io.Writer
|
||||
//Defaults to nil
|
||||
//If you're using Ginkgo, set this to GinkgoWriter to get improved output during failures
|
||||
Writer io.Writer
|
||||
|
||||
receivedRequests []*http.Request
|
||||
requestHandlers []http.HandlerFunc
|
||||
routedHandlers []routedHandler
|
||||
|
||||
writeLock *sync.Mutex
|
||||
calls int
|
||||
}
|
||||
|
||||
//Start() starts an unstarted ghttp server. It is a catastrophic error to call Start more than once (thanks, httptest).
|
||||
func (s *Server) Start() {
|
||||
s.HTTPTestServer.Start()
|
||||
}
|
||||
|
||||
//URL() returns a url that will hit the server
|
||||
func (s *Server) URL() string {
|
||||
return s.HTTPTestServer.URL
|
||||
}
|
||||
|
||||
//Addr() returns the address on which the server is listening.
|
||||
func (s *Server) Addr() string {
|
||||
return s.HTTPTestServer.Listener.Addr().String()
|
||||
}
|
||||
|
||||
//Close() should be called at the end of each test. It spins down and cleans up the test server.
|
||||
func (s *Server) Close() {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
server := s.HTTPTestServer
|
||||
s.HTTPTestServer = nil
|
||||
server.Close()
|
||||
}
|
||||
|
||||
//ServeHTTP() makes Server an http.Handler
|
||||
//When the server receives a request it handles the request in the following order:
|
||||
//
|
||||
//1. If the request matches a handler registered with RouteToHandler, that handler is called.
|
||||
//2. Otherwise, if there are handlers registered via AppendHandlers, those handlers are called in order.
|
||||
//3. If all registered handlers have been called then:
|
||||
// a) If AllowUnhandledRequests is true, the request will be handled with response code of UnhandledRequestStatusCode
|
||||
// b) If AllowUnhandledRequests is false, the request will not be handled and the current test will be marked as failed.
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s.writeLock.Lock()
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
//If the handler panics GHTTP will silently succeed. This is bad™.
|
||||
//To catch this case we need to fail the test if the handler has panicked.
|
||||
//However, if the handler is panicking because Ginkgo's causing it to panic (i.e. an asswertion failed)
|
||||
//then we shouldn't double-report the error as this will confuse people.
|
||||
|
||||
//So: step 1, if this is a Ginkgo panic - do nothing, Ginkgo's aware of the failure
|
||||
eAsString, ok := e.(string)
|
||||
if ok && strings.Contains(eAsString, "defer GinkgoRecover()") {
|
||||
return
|
||||
}
|
||||
|
||||
//If we're here, we have to do step 2: assert that the error is nil. This assertion will
|
||||
//allow us to fail the test suite (note: we can't call Fail since Gomega is not allowed to import Ginkgo).
|
||||
//Since a failed assertion throws a panic, and we are likely in a goroutine, we need to defer within our defer!
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
Ω(e).Should(BeNil(), "Handler Panicked")
|
||||
}()
|
||||
|
||||
if s.Writer != nil {
|
||||
s.Writer.Write([]byte(fmt.Sprintf("GHTTP Received Request: %s - %s\n", req.Method, req.URL)))
|
||||
}
|
||||
|
||||
s.receivedRequests = append(s.receivedRequests, req)
|
||||
if routedHandler, ok := s.handlerForRoute(req.Method, req.URL.Path); ok {
|
||||
s.writeLock.Unlock()
|
||||
routedHandler(w, req)
|
||||
} else if s.calls < len(s.requestHandlers) {
|
||||
h := s.requestHandlers[s.calls]
|
||||
s.calls++
|
||||
s.writeLock.Unlock()
|
||||
h(w, req)
|
||||
} else {
|
||||
s.writeLock.Unlock()
|
||||
if s.AllowUnhandledRequests {
|
||||
ioutil.ReadAll(req.Body)
|
||||
req.Body.Close()
|
||||
w.WriteHeader(s.UnhandledRequestStatusCode)
|
||||
} else {
|
||||
Ω(req).Should(BeNil(), "Received Unhandled Request")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ReceivedRequests is an array containing all requests received by the server (both handled and unhandled requests)
|
||||
func (s *Server) ReceivedRequests() []*http.Request {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
return s.receivedRequests
|
||||
}
|
||||
|
||||
//RouteToHandler can be used to register handlers that will always handle requests that match
|
||||
//the passed in method and path.
|
||||
//
|
||||
//The path may be either a string object or a *regexp.Regexp.
|
||||
func (s *Server) RouteToHandler(method string, path interface{}, handler http.HandlerFunc) {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
rh := routedHandler{
|
||||
method: method,
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
switch p := path.(type) {
|
||||
case *regexp.Regexp:
|
||||
rh.pathRegexp = p
|
||||
case string:
|
||||
rh.path = p
|
||||
default:
|
||||
panic("path must be a string or a regular expression")
|
||||
}
|
||||
|
||||
for i, existingRH := range s.routedHandlers {
|
||||
if existingRH.method == method &&
|
||||
reflect.DeepEqual(existingRH.pathRegexp, rh.pathRegexp) &&
|
||||
existingRH.path == rh.path {
|
||||
s.routedHandlers[i] = rh
|
||||
return
|
||||
}
|
||||
}
|
||||
s.routedHandlers = append(s.routedHandlers, rh)
|
||||
}
|
||||
|
||||
func (s *Server) handlerForRoute(method string, path string) (http.HandlerFunc, bool) {
|
||||
for _, rh := range s.routedHandlers {
|
||||
if rh.method == method {
|
||||
if rh.pathRegexp != nil {
|
||||
if rh.pathRegexp.Match([]byte(path)) {
|
||||
return rh.handler, true
|
||||
}
|
||||
} else if rh.path == path {
|
||||
return rh.handler, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
//AppendHandlers will appends http.HandlerFuncs to the server's list of registered handlers. The first incoming request is handled by the first handler, the second by the second, etc...
|
||||
func (s *Server) AppendHandlers(handlers ...http.HandlerFunc) {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
s.requestHandlers = append(s.requestHandlers, handlers...)
|
||||
}
|
||||
|
||||
//SetHandler overrides the registered handler at the passed in index with the passed in handler
|
||||
//This is useful, for example, when a server has been set up in a shared context, but must be tweaked
|
||||
//for a particular test.
|
||||
func (s *Server) SetHandler(index int, handler http.HandlerFunc) {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
s.requestHandlers[index] = handler
|
||||
}
|
||||
|
||||
//GetHandler returns the handler registered at the passed in index.
|
||||
func (s *Server) GetHandler(index int) http.HandlerFunc {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
return s.requestHandlers[index]
|
||||
}
|
||||
|
||||
func (s *Server) Reset() {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
s.HTTPTestServer.CloseClientConnections()
|
||||
s.calls = 0
|
||||
s.receivedRequests = nil
|
||||
s.requestHandlers = nil
|
||||
s.routedHandlers = nil
|
||||
}
|
||||
|
||||
//WrapHandler combines the passed in handler with the handler registered at the passed in index.
|
||||
//This is useful, for example, when a server has been set up in a shared context but must be tweaked
|
||||
//for a particular test.
|
||||
//
|
||||
//If the currently registered handler is A, and the new passed in handler is B then
|
||||
//WrapHandler will generate a new handler that first calls A, then calls B, and assign it to index
|
||||
func (s *Server) WrapHandler(index int, handler http.HandlerFunc) {
|
||||
existingHandler := s.GetHandler(index)
|
||||
s.SetHandler(index, CombineHandlers(existingHandler, handler))
|
||||
}
|
||||
|
||||
func (s *Server) CloseClientConnections() {
|
||||
s.writeLock.Lock()
|
||||
defer s.writeLock.Unlock()
|
||||
|
||||
s.HTTPTestServer.CloseClientConnections()
|
||||
}
|
23
vendor/github.com/onsi/gomega/internal/fakematcher/fake_matcher.go
generated
vendored
23
vendor/github.com/onsi/gomega/internal/fakematcher/fake_matcher.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
package fakematcher
|
||||
|
||||
import "fmt"
|
||||
|
||||
type FakeMatcher struct {
|
||||
ReceivedActual interface{}
|
||||
MatchesToReturn bool
|
||||
ErrToReturn error
|
||||
}
|
||||
|
||||
func (matcher *FakeMatcher) Match(actual interface{}) (bool, error) {
|
||||
matcher.ReceivedActual = actual
|
||||
|
||||
return matcher.MatchesToReturn, matcher.ErrToReturn
|
||||
}
|
||||
|
||||
func (matcher *FakeMatcher) FailureMessage(actual interface{}) string {
|
||||
return fmt.Sprintf("positive: %v", actual)
|
||||
}
|
||||
|
||||
func (matcher *FakeMatcher) NegatedFailureMessage(actual interface{}) string {
|
||||
return fmt.Sprintf("negative: %v", actual)
|
||||
}
|
20
vendor/github.com/onsi/gomega/matchers/support/goraph/MIT.LICENSE
generated
vendored
20
vendor/github.com/onsi/gomega/matchers/support/goraph/MIT.LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 Amit Kumar Gupta
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Reference in New Issue
Block a user