vendor: Mega update all dependencies

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4080
This commit is contained in:
Jakob Borg
2017-04-05 14:34:41 +00:00
parent 49c1527724
commit a1bcc15458
1354 changed files with 55066 additions and 797850 deletions

View File

@@ -1,70 +0,0 @@
## HEAD
Improvements:
- Added `BeSent` which attempts to send a value down a channel and fails if the attempt blocks. Can be paired with `Eventually` to safely send a value down a channel with a timeout.
- `Ω`, `Expect`, `Eventually`, and `Consistently` now immediately `panic` if there is no registered fail handler. This is always a mistake that can hide failing tests.
- `Receive()` no longer errors when passed a closed channel, it's perfectly fine to attempt to read from a closed channel so Ω(c).Should(Receive()) always fails and Ω(c).ShoudlNot(Receive()) always passes with a closed channel.
- Added `HavePrefix` and `HaveSuffix` matchers.
- `ghttp` can now handle concurrent requests.
- Added `Succeed` which allows one to write `Ω(MyFunction()).Should(Succeed())`.
- Improved `ghttp`'s behavior around failing assertions and panics:
- If a registered handler makes a failing assertion `ghttp` will return `500`.
- If a registered handler panics, `ghttp` will return `500` *and* fail the test. This is new behavior that may cause existing code to break. This code is almost certainly incorrect and creating a false positive.
- `ghttp` servers can take an `io.Writer`. `ghttp` will write a line to the writer when each request arrives.
- Added `WithTransform` matcher to allow munging input data before feeding into the relevant matcher
- Added boolean `And`, `Or`, and `Not` matchers to allow creating composite matchers
Bug Fixes:
- gexec: `session.Wait` now uses `EventuallyWithOffset` to get the right line number in the failure.
- `ContainElement` no longer bails if a passed-in matcher errors.
## 1.0 (8/2/2014)
No changes. Dropping "beta" from the version number.
## 1.0.0-beta (7/8/2014)
Breaking Changes:
- Changed OmegaMatcher interface. Instead of having `Match` return failure messages, two new methods `FailureMessage` and `NegatedFailureMessage` are called instead.
- Moved and renamed OmegaFailHandler to types.GomegaFailHandler and OmegaMatcher to types.GomegaMatcher. Any references to OmegaMatcher in any custom matchers will need to be changed to point to types.GomegaMatcher
New Test-Support Features:
- `ghttp`: supports testing http clients
- Provides a flexible fake http server
- Provides a collection of chainable http handlers that perform assertions.
- `gbytes`: supports making ordered assertions against streams of data
- Provides a `gbytes.Buffer`
- Provides a `Say` matcher to perform ordered assertions against output data
- `gexec`: supports testing external processes
- Provides support for building Go binaries
- Wraps and starts `exec.Cmd` commands
- Makes it easy to assert against stdout and stderr
- Makes it easy to send signals and wait for processes to exit
- Provides an `Exit` matcher to assert against exit code.
DSL Changes:
- `Eventually` and `Consistently` can accept `time.Duration` interval and polling inputs.
- The default timeouts for `Eventually` and `Consistently` are now configurable.
New Matchers:
- `ConsistOf`: order-independent assertion against the elements of an array/slice or keys of a map.
- `BeTemporally`: like `BeNumerically` but for `time.Time`
- `HaveKeyWithValue`: asserts a map has a given key with the given value.
Updated Matchers:
- `Receive` matcher can take a matcher as an argument and passes only if the channel under test receives an objet that satisfies the passed-in matcher.
- Matchers that implement `MatchMayChangeInTheFuture(actual interface{}) bool` can inform `Eventually` and/or `Consistently` when a match has no chance of changing status in the future. For example, `Receive` returns `false` when a channel is closed.
Misc:
- Start using semantic versioning
- Start maintaining changelog
Major refactor:
- Pull out Gomega's internal to `internal`

View File

@@ -1,17 +0,0 @@
![Gomega: Ginkgo's Preferred Matcher Library](http://onsi.github.io/gomega/images/gomega.png)
[![Build Status](https://travis-ci.org/onsi/gomega.png)](https://travis-ci.org/onsi/gomega)
Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers).
To discuss Gomega and get updates, join the [google group](https://groups.google.com/d/forum/ginkgo-and-gomega).
## [Ginkgo](http://github.com/onsi/ginkgo): a BDD Testing Framework for Golang
Learn more about Ginkgo [here](http://onsi.github.io/ginkgo/)
## License
Gomega is MIT-Licensed
The `ConsistOf` matcher uses [goraph](https://github.com/amitkgupta/goraph) which is embedded in the source to simplify distribution. goraph has an MIT license.

View File

@@ -6,7 +6,9 @@ package format
import (
"fmt"
"reflect"
"strconv"
"strings"
"time"
)
// Use MaxDepth to set the maximum recursion depth when printing deeply nested objects
@@ -21,6 +23,25 @@ Note that GoString and String don't always have all the information you need to
*/
var UseStringerRepresentation = false
/*
Print the content of context objects. By default it will be suppressed.
Set PrintContextObjects = true to enable printing of the context internals.
*/
var PrintContextObjects = false
// Ctx interface defined here to keep backwards compatability with go < 1.7
// It matches the context.Context interface
type Ctx interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
var contextType = reflect.TypeOf((*Ctx)(nil)).Elem()
var timeType = reflect.TypeOf(time.Time{})
//The default indentation string emitted by the format package
var Indent = " "
@@ -48,6 +69,81 @@ func Message(actual interface{}, message string, expected ...interface{}) string
}
}
/*
Generates a nicely formatted matcher success / failure message
Much like Message(...), but it attempts to pretty print diffs in strings
Expected
<string>: "...aaaaabaaaaa..."
to equal |
<string>: "...aaaaazaaaaa..."
*/
func MessageWithDiff(actual, message, expected string) string {
if len(actual) >= truncateThreshold && len(expected) >= truncateThreshold {
diffPoint := findFirstMismatch(actual, expected)
formattedActual := truncateAndFormat(actual, diffPoint)
formattedExpected := truncateAndFormat(expected, diffPoint)
spacesBeforeFormattedMismatch := findFirstMismatch(formattedActual, formattedExpected)
tabLength := 4
spaceFromMessageToActual := tabLength + len("<string>: ") - len(message)
padding := strings.Repeat(" ", spaceFromMessageToActual+spacesBeforeFormattedMismatch) + "|"
return Message(formattedActual, message+padding, formattedExpected)
}
return Message(actual, message, expected)
}
func truncateAndFormat(str string, index int) string {
leftPadding := `...`
rightPadding := `...`
start := index - charactersAroundMismatchToInclude
if start < 0 {
start = 0
leftPadding = ""
}
// slice index must include the mis-matched character
lengthOfMismatchedCharacter := 1
end := index + charactersAroundMismatchToInclude + lengthOfMismatchedCharacter
if end > len(str) {
end = len(str)
rightPadding = ""
}
return fmt.Sprintf("\"%s\"", leftPadding+str[start:end]+rightPadding)
}
func findFirstMismatch(a, b string) int {
aSlice := strings.Split(a, "")
bSlice := strings.Split(b, "")
for index, str := range aSlice {
if index > len(b) - 1 {
return index
}
if str != bSlice[index] {
return index
}
}
if len(b) > len(a) {
return len(a) + 1
}
return 0
}
const (
truncateThreshold = 50
charactersAroundMismatchToInclude = 5
)
/*
Pretty prints the passed in object at the passed in indentation level.
@@ -56,6 +152,8 @@ Object recurses into deeply nested objects emitting pretty-printed representatio
Modify format.MaxDepth to control how deep the recursion is allowed to go
Set format.UseStringerRepresentation to true to return object.GoString() or object.String() when available instead of
recursing into the object.
Set PrintContextObjects to true to print the content of objects implementing context.Context
*/
func Object(object interface{}, indentation uint) string {
indent := strings.Repeat(Indent, int(indentation))
@@ -123,6 +221,12 @@ func formatValue(value reflect.Value, indentation uint) string {
}
}
if !PrintContextObjects {
if value.Type().Implements(contextType) && indentation > 1 {
return "<suppressed context>"
}
}
switch value.Kind() {
case reflect.Bool:
return fmt.Sprintf("%v", value.Bool())
@@ -143,9 +247,6 @@ func formatValue(value reflect.Value, indentation uint) string {
case reflect.Ptr:
return formatValue(value.Elem(), indentation)
case reflect.Slice:
if value.Type().Elem().Kind() == reflect.Uint8 {
return formatString(value.Bytes(), indentation)
}
return formatSlice(value, indentation)
case reflect.String:
return formatString(value.String(), indentation)
@@ -154,6 +255,10 @@ func formatValue(value reflect.Value, indentation uint) string {
case reflect.Map:
return formatMap(value, indentation)
case reflect.Struct:
if value.Type() == timeType && value.CanInterface() {
t, _ := value.Interface().(time.Time)
return t.Format(time.RFC3339Nano)
}
return formatStruct(value, indentation)
case reflect.Interface:
return formatValue(value.Elem(), indentation)
@@ -189,6 +294,10 @@ func formatString(object interface{}, indentation uint) string {
}
func formatSlice(v reflect.Value, indentation uint) string {
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 && isPrintableString(string(v.Bytes())) {
return formatString(v.Bytes(), indentation)
}
l := v.Len()
result := make([]string, l)
longest := 0
@@ -214,7 +323,7 @@ func formatMap(v reflect.Value, indentation uint) string {
longest := 0
for i, key := range v.MapKeys() {
value := v.MapIndex(key)
result[i] = fmt.Sprintf("%s: %s", formatValue(key, 0), formatValue(value, indentation+1))
result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1), formatValue(value, indentation+1))
if len(result[i]) > longest {
longest = len(result[i])
}
@@ -262,15 +371,14 @@ func isNilValue(a reflect.Value) bool {
return false
}
func isNil(a interface{}) bool {
if a == nil {
return true
/*
Returns true when the string is entirely made of printable runes, false otherwise.
*/
func isPrintableString(str string) bool {
for _, runeValue := range str {
if !strconv.IsPrint(runeValue) {
return false
}
}
switch reflect.TypeOf(a).Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return reflect.ValueOf(a).IsNil()
}
return false
return true
}

View File

@@ -1,13 +0,0 @@
package format_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestFormat(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Format Suite")
}

View File

@@ -1,449 +0,0 @@
package format_test
import (
"fmt"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/format"
"github.com/onsi/gomega/types"
"strings"
)
//recursive struct
type StringAlias string
type ByteAlias []byte
type IntAlias int
type AStruct struct {
Exported string
}
type SimpleStruct struct {
Name string
Enumeration int
Veritas bool
Data []byte
secret uint32
}
type ComplexStruct struct {
Strings []string
SimpleThings []*SimpleStruct
DataMaps map[int]ByteAlias
}
type SecretiveStruct struct {
boolValue bool
intValue int
uintValue uint
uintptrValue uintptr
floatValue float32
complexValue complex64
chanValue chan bool
funcValue func()
pointerValue *int
sliceValue []string
byteSliceValue []byte
stringValue string
arrValue [3]int
byteArrValue [3]byte
mapValue map[string]int
structValue AStruct
interfaceValue interface{}
}
type GoStringer struct {
}
func (g GoStringer) GoString() string {
return "go-string"
}
func (g GoStringer) String() string {
return "string"
}
type Stringer struct {
}
func (g Stringer) String() string {
return "string"
}
var _ = Describe("Format", func() {
match := func(typeRepresentation string, valueRepresentation string, args ...interface{}) types.GomegaMatcher {
if len(args) > 0 {
valueRepresentation = fmt.Sprintf(valueRepresentation, args...)
}
return Equal(fmt.Sprintf("%s<%s>: %s", Indent, typeRepresentation, valueRepresentation))
}
matchRegexp := func(typeRepresentation string, valueRepresentation string, args ...interface{}) types.GomegaMatcher {
if len(args) > 0 {
valueRepresentation = fmt.Sprintf(valueRepresentation, args...)
}
return MatchRegexp(fmt.Sprintf("%s<%s>: %s", Indent, typeRepresentation, valueRepresentation))
}
hashMatchingRegexp := func(entries ...string) string {
entriesSwitch := "(" + strings.Join(entries, "|") + ")"
arr := make([]string, len(entries))
for i := range arr {
arr[i] = entriesSwitch
}
return "{" + strings.Join(arr, ", ") + "}"
}
Describe("Message", func() {
Context("with only an actual value", func() {
It("should print out an indented formatted representation of the value and the message", func() {
Ω(Message(3, "to be three.")).Should(Equal("Expected\n <int>: 3\nto be three."))
})
})
Context("with an actual and an expected value", func() {
It("should print out an indented formatted representatino of both values, and the message", func() {
Ω(Message(3, "to equal", 4)).Should(Equal("Expected\n <int>: 3\nto equal\n <int>: 4"))
})
})
})
Describe("IndentString", func() {
It("should indent the string", func() {
Ω(IndentString("foo\n bar\nbaz", 2)).Should(Equal(" foo\n bar\n baz"))
})
})
Describe("Object", func() {
Describe("formatting boolean values", func() {
It("should give the type and format values correctly", func() {
Ω(Object(true, 1)).Should(match("bool", "true"))
Ω(Object(false, 1)).Should(match("bool", "false"))
})
})
Describe("formatting numbers", func() {
It("should give the type and format values correctly", func() {
Ω(Object(int(3), 1)).Should(match("int", "3"))
Ω(Object(int8(3), 1)).Should(match("int8", "3"))
Ω(Object(int16(3), 1)).Should(match("int16", "3"))
Ω(Object(int32(3), 1)).Should(match("int32", "3"))
Ω(Object(int64(3), 1)).Should(match("int64", "3"))
Ω(Object(uint(3), 1)).Should(match("uint", "3"))
Ω(Object(uint8(3), 1)).Should(match("uint8", "3"))
Ω(Object(uint16(3), 1)).Should(match("uint16", "3"))
Ω(Object(uint32(3), 1)).Should(match("uint32", "3"))
Ω(Object(uint64(3), 1)).Should(match("uint64", "3"))
})
It("should handle uintptr differently", func() {
Ω(Object(uintptr(3), 1)).Should(match("uintptr", "0x3"))
})
})
Describe("formatting channels", func() {
It("should give the type and format values correctly", func() {
c := make(chan<- bool, 3)
c <- true
c <- false
Ω(Object(c, 1)).Should(match("chan<- bool | len:2, cap:3", "%v", c))
})
})
Describe("formatting strings", func() {
It("should give the type and format values correctly", func() {
s := "a\nb\nc"
Ω(Object(s, 1)).Should(match("string", `a
b
c`))
})
})
Describe("formatting []byte slices", func() {
It("should present them as strings", func() {
b := []byte("a\nb\nc")
Ω(Object(b, 1)).Should(matchRegexp(`\[\]uint8 \| len:5, cap:\d+`, `a
b
c`))
})
})
Describe("formatting functions", func() {
It("should give the type and format values correctly", func() {
f := func(a string, b []int) ([]byte, error) {
return []byte("abc"), nil
}
Ω(Object(f, 1)).Should(match("func(string, []int) ([]uint8, error)", "%v", f))
})
})
Describe("formatting pointers", func() {
It("should give the type and dereference the value to format it correctly", func() {
a := 3
Ω(Object(&a, 1)).Should(match(fmt.Sprintf("*int | %p", &a), "3"))
})
Context("when there are pointers to pointers...", func() {
It("should recursively deference the pointer until it gets to a value", func() {
a := 3
var b *int
var c **int
var d ***int
b = &a
c = &b
d = &c
Ω(Object(d, 1)).Should(match(fmt.Sprintf("***int | %p", d), "3"))
})
})
Context("when the pointer points to nil", func() {
It("should say nil and not explode", func() {
var a *AStruct
Ω(Object(a, 1)).Should(match("*format_test.AStruct | 0x0", "nil"))
})
})
})
Describe("formatting arrays", func() {
It("should give the type and format values correctly", func() {
w := [3]string{"Jed Bartlet", "Toby Ziegler", "CJ Cregg"}
Ω(Object(w, 1)).Should(match("[3]string", `["Jed Bartlet", "Toby Ziegler", "CJ Cregg"]`))
})
Context("with byte arrays", func() {
It("should give the type and format values correctly", func() {
w := [3]byte{17, 28, 19}
Ω(Object(w, 1)).Should(match("[3]uint8", `[17, 28, 19]`))
})
})
})
Describe("formatting slices", func() {
It("should include the length and capacity in the type information", func() {
s := make([]bool, 3, 4)
Ω(Object(s, 1)).Should(match("[]bool | len:3, cap:4", "[false, false, false]"))
})
Context("when the slice contains long entries", func() {
It("should format the entries with newlines", func() {
w := []string{"Josiah Edward Bartlet", "Toby Ziegler", "CJ Cregg"}
expected := `[
"Josiah Edward Bartlet",
"Toby Ziegler",
"CJ Cregg",
]`
Ω(Object(w, 1)).Should(match("[]string | len:3, cap:3", expected))
})
})
})
Describe("formatting maps", func() {
It("should include the length in the type information", func() {
m := make(map[int]bool, 5)
m[3] = true
m[4] = false
Ω(Object(m, 1)).Should(matchRegexp(`map\[int\]bool \| len:2`, hashMatchingRegexp("3: true", "4: false")))
})
Context("when the slice contains long entries", func() {
It("should format the entries with newlines", func() {
m := map[string][]byte{}
m["Josiah Edward Bartlet"] = []byte("Martin Sheen")
m["Toby Ziegler"] = []byte("Richard Schiff")
m["CJ Cregg"] = []byte("Allison Janney")
expected := `{
("Josiah Edward Bartlet": "Martin Sheen"|"Toby Ziegler": "Richard Schiff"|"CJ Cregg": "Allison Janney"),
("Josiah Edward Bartlet": "Martin Sheen"|"Toby Ziegler": "Richard Schiff"|"CJ Cregg": "Allison Janney"),
("Josiah Edward Bartlet": "Martin Sheen"|"Toby Ziegler": "Richard Schiff"|"CJ Cregg": "Allison Janney"),
}`
Ω(Object(m, 1)).Should(matchRegexp(`map\[string\]\[\]uint8 \| len:3`, expected))
})
})
})
Describe("formatting structs", func() {
It("should include the struct name and the field names", func() {
s := SimpleStruct{
Name: "Oswald",
Enumeration: 17,
Veritas: true,
Data: []byte("datum"),
secret: 1983,
}
Ω(Object(s, 1)).Should(match("format_test.SimpleStruct", `{Name: "Oswald", Enumeration: 17, Veritas: true, Data: "datum", secret: 1983}`))
})
Context("when the struct contains long entries", func() {
It("should format the entries with new lines", func() {
s := &SimpleStruct{
Name: "Mithrandir Gandalf Greyhame",
Enumeration: 2021,
Veritas: true,
Data: []byte("wizard"),
secret: 3,
}
Ω(Object(s, 1)).Should(match(fmt.Sprintf("*format_test.SimpleStruct | %p", s), `{
Name: "Mithrandir Gandalf Greyhame",
Enumeration: 2021,
Veritas: true,
Data: "wizard",
secret: 3,
}`))
})
})
})
Describe("formatting nil values", func() {
It("should print out nil", func() {
Ω(Object(nil, 1)).Should(match("nil", "nil"))
var typedNil *AStruct
Ω(Object(typedNil, 1)).Should(match("*format_test.AStruct | 0x0", "nil"))
var c chan<- bool
Ω(Object(c, 1)).Should(match("chan<- bool | len:0, cap:0", "nil"))
var s []string
Ω(Object(s, 1)).Should(match("[]string | len:0, cap:0", "nil"))
var m map[string]bool
Ω(Object(m, 1)).Should(match("map[string]bool | len:0", "nil"))
})
})
Describe("formatting aliased types", func() {
It("should print out the correct alias type", func() {
Ω(Object(StringAlias("alias"), 1)).Should(match("format_test.StringAlias", `alias`))
Ω(Object(ByteAlias("alias"), 1)).Should(matchRegexp(`format_test\.ByteAlias \| len:5, cap:\d+`, `alias`))
Ω(Object(IntAlias(3), 1)).Should(match("format_test.IntAlias", "3"))
})
})
Describe("handling nested things", func() {
It("should produce a correctly nested representation", func() {
s := ComplexStruct{
Strings: []string{"lots", "of", "short", "strings"},
SimpleThings: []*SimpleStruct{
{"short", 7, true, []byte("succinct"), 17},
{"something longer", 427, true, []byte("designed to wrap around nicely"), 30},
},
DataMaps: map[int]ByteAlias{
17: ByteAlias("some substantially longer chunks of data"),
1138: ByteAlias("that should make things wrap"),
},
}
expected := `{
Strings: \["lots", "of", "short", "strings"\],
SimpleThings: \[
{Name: "short", Enumeration: 7, Veritas: true, Data: "succinct", secret: 17},
{
Name: "something longer",
Enumeration: 427,
Veritas: true,
Data: "designed to wrap around nicely",
secret: 30,
},
\],
DataMaps: {
(17: "some substantially longer chunks of data"|1138: "that should make things wrap"),
(17: "some substantially longer chunks of data"|1138: "that should make things wrap"),
},
}`
Ω(Object(s, 1)).Should(matchRegexp(`format_test\.ComplexStruct`, expected))
})
})
})
Describe("Handling unexported fields in structs", func() {
It("should handle all the various types correctly", func() {
a := int(5)
s := SecretiveStruct{
boolValue: true,
intValue: 3,
uintValue: 4,
uintptrValue: 5,
floatValue: 6.0,
complexValue: complex(5.0, 3.0),
chanValue: make(chan bool, 2),
funcValue: func() {},
pointerValue: &a,
sliceValue: []string{"string", "slice"},
byteSliceValue: []byte("bytes"),
stringValue: "a string",
arrValue: [3]int{11, 12, 13},
byteArrValue: [3]byte{17, 20, 32},
mapValue: map[string]int{"a key": 20, "b key": 30},
structValue: AStruct{"exported"},
interfaceValue: map[string]int{"a key": 17},
}
expected := fmt.Sprintf(`{
boolValue: true,
intValue: 3,
uintValue: 4,
uintptrValue: 0x5,
floatValue: 6,
complexValue: \(5\+3i\),
chanValue: %p,
funcValue: %p,
pointerValue: 5,
sliceValue: \["string", "slice"\],
byteSliceValue: "bytes",
stringValue: "a string",
arrValue: \[11, 12, 13\],
byteArrValue: \[17, 20, 32\],
mapValue: %s,
structValue: {Exported: "exported"},
interfaceValue: {"a key": 17},
}`, s.chanValue, s.funcValue, hashMatchingRegexp(`"a key": 20`, `"b key": 30`))
Ω(Object(s, 1)).Should(matchRegexp(`format_test\.SecretiveStruct`, expected))
})
})
Describe("Handling interfaces", func() {
It("should unpack the interface", func() {
outerHash := map[string]interface{}{}
innerHash := map[string]int{}
innerHash["inner"] = 3
outerHash["integer"] = 2
outerHash["map"] = innerHash
expected := hashMatchingRegexp(`"integer": 2`, `"map": {"inner": 3}`)
Ω(Object(outerHash, 1)).Should(matchRegexp(`map\[string\]interface {} \| len:2`, expected))
})
})
Describe("Handling recursive things", func() {
It("should not go crazy...", func() {
m := map[string]interface{}{}
m["integer"] = 2
m["map"] = m
Ω(Object(m, 1)).Should(ContainSubstring("..."))
})
})
Describe("When instructed to use the Stringer representation", func() {
BeforeEach(func() {
UseStringerRepresentation = true
})
AfterEach(func() {
UseStringerRepresentation = false
})
Context("when passed a GoStringer", func() {
It("should use what GoString() returns", func() {
Ω(Object(GoStringer{}, 1)).Should(ContainSubstring("<format_test.GoStringer>: go-string"))
})
})
Context("when passed a stringer", func() {
It("should use what String() returns", func() {
Ω(Object(Stringer{}, 1)).Should(ContainSubstring("<format_test.Stringer>: string"))
})
})
})
})

View File

@@ -1,158 +0,0 @@
package gbytes_test
import (
"io"
"time"
. "github.com/onsi/gomega/gbytes"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Buffer", func() {
var buffer *Buffer
BeforeEach(func() {
buffer = NewBuffer()
})
Describe("dumping the entire contents of the buffer", func() {
It("should return everything that's been written", func() {
buffer.Write([]byte("abc"))
buffer.Write([]byte("def"))
Ω(buffer.Contents()).Should(Equal([]byte("abcdef")))
Ω(buffer).Should(Say("bcd"))
Ω(buffer.Contents()).Should(Equal([]byte("abcdef")))
})
})
Describe("creating a buffer with bytes", func() {
It("should create the buffer with the cursor set to the beginning", func() {
buffer := BufferWithBytes([]byte("abcdef"))
Ω(buffer.Contents()).Should(Equal([]byte("abcdef")))
Ω(buffer).Should(Say("abc"))
Ω(buffer).ShouldNot(Say("abc"))
Ω(buffer).Should(Say("def"))
})
})
Describe("reading from a buffer", func() {
It("should read the current contents of the buffer", func() {
buffer := BufferWithBytes([]byte("abcde"))
dest := make([]byte, 3)
n, err := buffer.Read(dest)
Ω(err).ShouldNot(HaveOccurred())
Ω(n).Should(Equal(3))
Ω(string(dest)).Should(Equal("abc"))
dest = make([]byte, 3)
n, err = buffer.Read(dest)
Ω(err).ShouldNot(HaveOccurred())
Ω(n).Should(Equal(2))
Ω(string(dest[:n])).Should(Equal("de"))
n, err = buffer.Read(dest)
Ω(err).Should(Equal(io.EOF))
Ω(n).Should(Equal(0))
})
Context("after the buffer has been closed", func() {
It("returns an error", func() {
buffer := BufferWithBytes([]byte("abcde"))
buffer.Close()
dest := make([]byte, 3)
n, err := buffer.Read(dest)
Ω(err).Should(HaveOccurred())
Ω(n).Should(Equal(0))
})
})
})
Describe("detecting regular expressions", func() {
It("should fire the appropriate channel when the passed in pattern matches, then close it", func(done Done) {
go func() {
time.Sleep(10 * time.Millisecond)
buffer.Write([]byte("abcde"))
}()
A := buffer.Detect("%s", "a.c")
B := buffer.Detect("def")
var gotIt bool
select {
case gotIt = <-A:
case <-B:
Fail("should not have gotten here")
}
Ω(gotIt).Should(BeTrue())
Eventually(A).Should(BeClosed())
buffer.Write([]byte("f"))
Eventually(B).Should(Receive())
Eventually(B).Should(BeClosed())
close(done)
})
It("should fast-forward the buffer upon detection", func(done Done) {
buffer.Write([]byte("abcde"))
<-buffer.Detect("abc")
Ω(buffer).ShouldNot(Say("abc"))
Ω(buffer).Should(Say("de"))
close(done)
})
It("should only fast-forward the buffer when the channel is read, and only if doing so would not rewind it", func(done Done) {
buffer.Write([]byte("abcde"))
A := buffer.Detect("abc")
time.Sleep(20 * time.Millisecond) //give the goroutine a chance to detect and write to the channel
Ω(buffer).Should(Say("abcd"))
<-A
Ω(buffer).ShouldNot(Say("d"))
Ω(buffer).Should(Say("e"))
Eventually(A).Should(BeClosed())
close(done)
})
It("should be possible to cancel a detection", func(done Done) {
A := buffer.Detect("abc")
B := buffer.Detect("def")
buffer.CancelDetects()
buffer.Write([]byte("abcdef"))
Eventually(A).Should(BeClosed())
Eventually(B).Should(BeClosed())
Ω(buffer).Should(Say("bcde"))
<-buffer.Detect("f")
close(done)
})
})
Describe("closing the buffer", func() {
It("should error when further write attempts are made", func() {
_, err := buffer.Write([]byte("abc"))
Ω(err).ShouldNot(HaveOccurred())
buffer.Close()
_, err = buffer.Write([]byte("def"))
Ω(err).Should(HaveOccurred())
Ω(buffer.Contents()).Should(Equal([]byte("abc")))
})
It("should be closed", func() {
Ω(buffer.Closed()).Should(BeFalse())
buffer.Close()
Ω(buffer.Closed()).Should(BeTrue())
})
})
})

View File

@@ -1,13 +0,0 @@
package gbytes_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestGbytes(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Gbytes Suite")
}

View File

@@ -22,7 +22,7 @@ will succeed if the unread portion of the buffer matches the regular expression
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:
Say pairs very well with Eventually. To assert that a buffer eventually receives data matching "[123]-star" within 3 seconds you can:
Eventually(buffer, 3).Should(Say("[123]-star"))

View File

@@ -1,163 +0,0 @@
package gbytes_test
import (
. "github.com/onsi/gomega/gbytes"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type speaker struct {
buffer *Buffer
}
func (s *speaker) Buffer() *Buffer {
return s.buffer
}
var _ = Describe("SayMatcher", func() {
var buffer *Buffer
BeforeEach(func() {
buffer = NewBuffer()
buffer.Write([]byte("abc"))
})
Context("when actual is not a gexec Buffer, or a BufferProvider", func() {
It("should error", func() {
failures := InterceptGomegaFailures(func() {
Ω("foo").Should(Say("foo"))
})
Ω(failures[0]).Should(ContainSubstring("*gbytes.Buffer"))
})
})
Context("when a match is found", func() {
It("should succeed", func() {
Ω(buffer).Should(Say("abc"))
})
It("should support printf-like formatting", func() {
Ω(buffer).Should(Say("a%sc", "b"))
})
It("should use a regular expression", func() {
Ω(buffer).Should(Say("a.c"))
})
It("should fastforward the buffer", func() {
buffer.Write([]byte("def"))
Ω(buffer).Should(Say("abcd"))
Ω(buffer).Should(Say("ef"))
Ω(buffer).ShouldNot(Say("[a-z]"))
})
})
Context("when no match is found", func() {
It("should not error", func() {
Ω(buffer).ShouldNot(Say("def"))
})
Context("when the buffer is closed", func() {
BeforeEach(func() {
buffer.Close()
})
It("should abort an eventually", func() {
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(buffer).Should(Say("def"))
})
Eventually(buffer).ShouldNot(Say("def"))
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
Ω(failures).Should(HaveLen(1))
t = time.Now()
Eventually(buffer).Should(Say("abc"))
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
})
It("should abort a consistently", func() {
t := time.Now()
Consistently(buffer, 2.0).ShouldNot(Say("def"))
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
})
It("should not error with a synchronous matcher", func() {
Ω(buffer).ShouldNot(Say("def"))
Ω(buffer).Should(Say("abc"))
})
})
})
Context("when a positive match fails", func() {
It("should report where it got stuck", func() {
Ω(buffer).Should(Say("abc"))
buffer.Write([]byte("def"))
failures := InterceptGomegaFailures(func() {
Ω(buffer).Should(Say("abc"))
})
Ω(failures[0]).Should(ContainSubstring("Got stuck at:"))
Ω(failures[0]).Should(ContainSubstring("def"))
})
})
Context("when a negative match fails", func() {
It("should report where it got stuck", func() {
failures := InterceptGomegaFailures(func() {
Ω(buffer).ShouldNot(Say("abc"))
})
Ω(failures[0]).Should(ContainSubstring("Saw:"))
Ω(failures[0]).Should(ContainSubstring("Which matches the unexpected:"))
Ω(failures[0]).Should(ContainSubstring("abc"))
})
})
Context("when a match is not found", func() {
It("should not fastforward the buffer", func() {
Ω(buffer).ShouldNot(Say("def"))
Ω(buffer).Should(Say("abc"))
})
})
Context("a nice real-life example", func() {
It("should behave well", func() {
Ω(buffer).Should(Say("abc"))
go func() {
time.Sleep(10 * time.Millisecond)
buffer.Write([]byte("def"))
}()
Ω(buffer).ShouldNot(Say("def"))
Eventually(buffer).Should(Say("def"))
})
})
Context("when actual is a BufferProvider", func() {
It("should use actual's buffer", func() {
s := &speaker{
buffer: NewBuffer(),
}
Ω(s).ShouldNot(Say("abc"))
s.Buffer().Write([]byte("abc"))
Ω(s).Should(Say("abc"))
})
It("should abort an eventually", func() {
s := &speaker{
buffer: NewBuffer(),
}
s.buffer.Close()
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(s).Should(Say("def"))
})
Ω(failures).Should(HaveLen(1))
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
})
})
})

View File

@@ -1,36 +0,0 @@
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
var outQuote = "We've done the impossible, and that makes us mighty."
var errQuote = "Ah, curse your sudden but inevitable betrayal!"
var randomQuotes = []string{
"Can we maybe vote on the whole murdering people issue?",
"I swear by my pretty floral bonnet, I will end you.",
"My work's illegal, but at least it's honest.",
}
func main() {
fmt.Fprintln(os.Stdout, outQuote)
fmt.Fprintln(os.Stderr, errQuote)
randomIndex := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(randomQuotes))
time.Sleep(100 * time.Millisecond)
fmt.Fprintln(os.Stdout, randomQuotes[randomIndex])
if len(os.Args) == 2 {
exitCode, _ := strconv.Atoi(os.Args[1])
os.Exit(exitCode)
} else {
os.Exit(randomIndex)
}
}

View File

@@ -9,9 +9,13 @@ import (
"path"
"path/filepath"
"runtime"
"sync"
)
var tmpDir string
var (
mu sync.Mutex
tmpDir string
)
/*
Build uses go build to compile the package at packagePath. The resulting binary is saved off in a temporary directory.
@@ -20,13 +24,24 @@ 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...)
return doBuild(os.Getenv("GOPATH"), packagePath, nil, args...)
}
/*
BuildWithEnvironment is identical to Build but allows you to specify env vars to be set at build time.
*/
func BuildWithEnvironment(packagePath string, env []string, args ...string) (compiledPath string, err error) {
return doBuild(os.Getenv("GOPATH"), packagePath, env, 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) {
return doBuild(gopath, packagePath, nil, args...)
}
func doBuild(gopath, packagePath string, env []string, args ...string) (compiledPath string, err error) {
tmpDir, err := temporaryDirectory()
if err != nil {
return "", err
@@ -46,6 +61,7 @@ func BuildIn(gopath string, packagePath string, args ...string) (compiledPath st
build := exec.Command("go", cmdArgs...)
build.Env = append([]string{"GOPATH=" + gopath}, os.Environ()...)
build.Env = append(build.Env, env...)
output, err := build.CombinedOutput()
if err != nil {
@@ -60,13 +76,18 @@ You should call CleanupBuildArtifacts before your test ends to clean up any temp
gexec. In Ginkgo this is typically done in an AfterSuite callback.
*/
func CleanupBuildArtifacts() {
mu.Lock()
defer mu.Unlock()
if tmpDir != "" {
os.RemoveAll(tmpDir)
tmpDir = ""
}
}
func temporaryDirectory() (string, error) {
var err error
mu.Lock()
defer mu.Unlock()
if tmpDir == "" {
tmpDir, err = ioutil.TempDir("", "gexec_artifacts")
if err != nil {

View File

@@ -1,113 +0,0 @@
package gexec_test
import (
. "github.com/onsi/gomega/gexec"
"os/exec"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type NeverExits struct{}
func (e NeverExits) ExitCode() int {
return -1
}
var _ = Describe("ExitMatcher", func() {
var command *exec.Cmd
var session *Session
BeforeEach(func() {
var err error
command = exec.Command(fireflyPath, "0")
session, err = Start(command, nil, nil)
Ω(err).ShouldNot(HaveOccurred())
})
Describe("when passed something that is an Exiter", func() {
It("should act normally", func() {
failures := InterceptGomegaFailures(func() {
Ω(NeverExits{}).Should(Exit())
})
Ω(failures[0]).Should(ContainSubstring("Expected process to exit. It did not."))
})
})
Describe("when passed something that is not an Exiter", func() {
It("should error", func() {
failures := InterceptGomegaFailures(func() {
Ω("aardvark").Should(Exit())
})
Ω(failures[0]).Should(ContainSubstring("Exit must be passed a gexec.Exiter"))
})
})
Context("with no exit code", func() {
It("should say the right things when it fails", func() {
Ω(session).ShouldNot(Exit())
failures := InterceptGomegaFailures(func() {
Ω(session).Should(Exit())
})
Ω(failures[0]).Should(ContainSubstring("Expected process to exit. It did not."))
Eventually(session).Should(Exit())
Ω(session).Should(Exit())
failures = InterceptGomegaFailures(func() {
Ω(session).ShouldNot(Exit())
})
Ω(failures[0]).Should(ContainSubstring("Expected process not to exit. It did."))
})
})
Context("with an exit code", func() {
It("should say the right things when it fails", func() {
Ω(session).ShouldNot(Exit(0))
Ω(session).ShouldNot(Exit(1))
failures := InterceptGomegaFailures(func() {
Ω(session).Should(Exit(0))
})
Ω(failures[0]).Should(ContainSubstring("Expected process to exit. It did not."))
Eventually(session).Should(Exit(0))
Ω(session).Should(Exit(0))
failures = InterceptGomegaFailures(func() {
Ω(session).Should(Exit(1))
})
Ω(failures[0]).Should(ContainSubstring("to match exit code:"))
Ω(session).ShouldNot(Exit(1))
failures = InterceptGomegaFailures(func() {
Ω(session).ShouldNot(Exit(0))
})
Ω(failures[0]).Should(ContainSubstring("not to match exit code:"))
})
})
Describe("bailing out early", func() {
It("should bail out early once the process exits", func() {
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(session).Should(Exit(1))
})
Ω(time.Since(t)).Should(BeNumerically("<=", 500*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
})
})

View File

@@ -1,26 +0,0 @@
package gexec_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
"testing"
)
var fireflyPath string
func TestGexec(t *testing.T) {
BeforeSuite(func() {
var err error
fireflyPath, err = gexec.Build("./_fixture/firefly")
Ω(err).ShouldNot(HaveOccurred())
})
AfterSuite(func() {
gexec.CleanupBuildArtifacts()
})
RegisterFailHandler(Fail)
RunSpecs(t, "Gexec Suite")
}

View File

@@ -1,43 +0,0 @@
package gexec_test
import (
"bytes"
. "github.com/onsi/gomega/gexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("PrefixedWriter", func() {
var buffer *bytes.Buffer
var writer *PrefixedWriter
BeforeEach(func() {
buffer = &bytes.Buffer{}
writer = NewPrefixedWriter("[p]", buffer)
})
It("should emit the prefix on newlines", func() {
writer.Write([]byte("abc"))
writer.Write([]byte("def\n"))
writer.Write([]byte("hij\n"))
writer.Write([]byte("\n\n"))
writer.Write([]byte("klm\n\nnop"))
writer.Write([]byte(""))
writer.Write([]byte("qrs"))
writer.Write([]byte("\ntuv\nwx"))
writer.Write([]byte("yz\n\n"))
Ω(buffer.String()).Should(Equal(`[p]abcdef
[p]hij
[p]
[p]
[p]klm
[p]
[p]nopqrs
[p]tuv
[p]wxyz
[p]
`))
})
})

View File

@@ -60,7 +60,7 @@ Instead, to assert that the command has exited you can use the gexec.Exit matche
Ω(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.
Eventuallys waiting for the buffers to Say something.
*/
func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) {
exited := make(chan struct{})
@@ -92,6 +92,9 @@ func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Sessio
err := command.Start()
if err == nil {
go session.monitorForExit(exited)
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
trackedSessions = append(trackedSessions, session)
}
return session, err
@@ -179,7 +182,7 @@ func (s *Session) Terminate() *Session {
}
/*
Terminate sends the running command the passed in signal. It does not wait for the process to exit.
Signal 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.
@@ -212,3 +215,91 @@ func (s *Session) monitorForExit(exited chan<- struct{}) {
close(exited)
}
var trackedSessions = []*Session{}
var trackedSessionsMutex = &sync.Mutex{}
/*
Kill sends a SIGKILL signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.
If any of the processes already exited, KillAndWait returns silently.
*/
func KillAndWait(timeout ...interface{}) {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Kill().Wait(timeout...)
}
trackedSessions = []*Session{}
}
/*
Kill sends a SIGTERM signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.
If any of the processes already exited, TerminateAndWait returns silently.
*/
func TerminateAndWait(timeout ...interface{}) {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Terminate().Wait(timeout...)
}
}
/*
Kill sends a SIGKILL signal to all the processes started by Run.
It does not wait for the processes to exit.
If any of the processes already exited, Kill returns silently.
*/
func Kill() {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Kill()
}
}
/*
Terminate sends a SIGTERM signal to all the processes started by Run.
It does not wait for the processes to exit.
If any of the processes already exited, Terminate returns silently.
*/
func Terminate() {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Terminate()
}
}
/*
Signal sends the passed in signal to all the processes started by Run.
It does not wait for the processes to exit.
If any of the processes already exited, Signal returns silently.
*/
func Signal(signal os.Signal) {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Signal(signal)
}
}
/*
Interrupt sends the SIGINT signal to all the processes started by Run.
It does not wait for the processes to exit.
If any of the processes already exited, Interrupt returns silently.
*/
func Interrupt() {
trackedSessionsMutex.Lock()
defer trackedSessionsMutex.Unlock()
for _, session := range trackedSessions {
session.Interrupt()
}
}

View File

@@ -1,178 +0,0 @@
package gexec_test
import (
"os/exec"
"syscall"
"time"
. "github.com/onsi/gomega/gbytes"
. "github.com/onsi/gomega/gexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Session", func() {
var command *exec.Cmd
var session *Session
var outWriter, errWriter *Buffer
BeforeEach(func() {
outWriter = nil
errWriter = nil
})
JustBeforeEach(func() {
command = exec.Command(fireflyPath)
var err error
session, err = Start(command, outWriter, errWriter)
Ω(err).ShouldNot(HaveOccurred())
})
Context("running a command", func() {
It("should start the process", func() {
Ω(command.Process).ShouldNot(BeNil())
})
It("should wrap the process's stdout and stderr with gbytes buffers", func(done Done) {
Eventually(session.Out).Should(Say("We've done the impossible, and that makes us mighty"))
Eventually(session.Err).Should(Say("Ah, curse your sudden but inevitable betrayal!"))
defer session.Out.CancelDetects()
select {
case <-session.Out.Detect("Can we maybe vote on the whole murdering people issue"):
Eventually(session).Should(Exit(0))
case <-session.Out.Detect("I swear by my pretty floral bonnet, I will end you."):
Eventually(session).Should(Exit(1))
case <-session.Out.Detect("My work's illegal, but at least it's honest."):
Eventually(session).Should(Exit(2))
}
close(done)
})
It("should satisfy the gbytes.BufferProvider interface, passing Stdout", func() {
Eventually(session).Should(Say("We've done the impossible, and that makes us mighty"))
Eventually(session).Should(Exit())
})
})
Describe("providing the exit code", func() {
It("should provide the app's exit code", func() {
Ω(session.ExitCode()).Should(Equal(-1))
Eventually(session).Should(Exit())
Ω(session.ExitCode()).Should(BeNumerically(">=", 0))
Ω(session.ExitCode()).Should(BeNumerically("<", 3))
})
})
Describe("wait", func() {
It("should wait till the command exits", func() {
Ω(session.ExitCode()).Should(Equal(-1))
Ω(session.Wait().ExitCode()).Should(BeNumerically(">=", 0))
Ω(session.Wait().ExitCode()).Should(BeNumerically("<", 3))
})
})
Describe("exited", func() {
It("should close when the command exits", func() {
Eventually(session.Exited).Should(BeClosed())
Ω(session.ExitCode()).ShouldNot(Equal(-1))
})
})
Describe("kill", func() {
It("should kill the command and wait for it to exit", func() {
session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter)
Ω(err).ShouldNot(HaveOccurred())
session.Kill()
Ω(session).ShouldNot(Exit(), "Should not exit immediately...")
Eventually(session).Should(Exit(128 + 9))
})
})
Describe("interrupt", func() {
It("should interrupt the command", func() {
session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter)
Ω(err).ShouldNot(HaveOccurred())
session.Interrupt()
Ω(session).ShouldNot(Exit(), "Should not exit immediately...")
Eventually(session).Should(Exit(128 + 2))
})
})
Describe("terminate", func() {
It("should terminate the command", func() {
session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter)
Ω(err).ShouldNot(HaveOccurred())
session.Terminate()
Ω(session).ShouldNot(Exit(), "Should not exit immediately...")
Eventually(session).Should(Exit(128 + 15))
})
})
Describe("signal", func() {
It("should send the signal to the command", func() {
session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter)
Ω(err).ShouldNot(HaveOccurred())
session.Signal(syscall.SIGABRT)
Ω(session).ShouldNot(Exit(), "Should not exit immediately...")
Eventually(session).Should(Exit(128 + 6))
})
})
Context("when the command exits", func() {
It("should close the buffers", func() {
Eventually(session).Should(Exit())
Ω(session.Out.Closed()).Should(BeTrue())
Ω(session.Err.Closed()).Should(BeTrue())
Ω(session.Out).Should(Say("We've done the impossible, and that makes us mighty"))
})
var So = It
So("this means that eventually should short circuit", func() {
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(session).Should(Say("blah blah blah blah blah"))
})
Ω(time.Since(t)).Should(BeNumerically("<=", 500*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
})
Context("when wrapping out and err", func() {
BeforeEach(func() {
outWriter = NewBuffer()
errWriter = NewBuffer()
})
It("should route to both the provided writers and the gbytes buffers", func() {
Eventually(session.Out).Should(Say("We've done the impossible, and that makes us mighty"))
Eventually(session.Err).Should(Say("Ah, curse your sudden but inevitable betrayal!"))
Ω(outWriter.Contents()).Should(ContainSubstring("We've done the impossible, and that makes us mighty"))
Ω(errWriter.Contents()).Should(ContainSubstring("Ah, curse your sudden but inevitable betrayal!"))
Eventually(session).Should(Exit())
Ω(outWriter.Contents()).Should(Equal(session.Out.Contents()))
Ω(errWriter.Contents()).Should(Equal(session.Err.Contents()))
})
})
Describe("when the command fails to start", func() {
It("should return an error", func() {
_, err := Start(exec.Command("agklsjdfas"), nil, nil)
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,9 +0,0 @@
syntax = "proto2";
package protobuf;
message SimpleMessage {
required string description = 1;
required int32 id = 2;
optional string metadata = 3;
}

View File

@@ -198,11 +198,13 @@ func (s *Server) 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()
s.writeLock.Unlock()
if server != nil {
server.Close()
}
}
//ServeHTTP() makes Server an http.Handler
@@ -223,7 +225,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
//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)
//However, if the handler is panicking because Ginkgo's causing it to panic (i.e. an assertion 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

View File

@@ -1,13 +0,0 @@
package ghttp_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestGHTTP(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "GHTTP Suite")
}

File diff suppressed because it is too large Load Diff

145
vendor/github.com/onsi/gomega/gstruct/elements.go generated vendored Normal file
View File

@@ -0,0 +1,145 @@
package gstruct
import (
"errors"
"fmt"
"reflect"
"runtime/debug"
"github.com/onsi/gomega/format"
errorsutil "github.com/onsi/gomega/gstruct/errors"
"github.com/onsi/gomega/types"
)
//MatchAllElements succeeds if every element of a slice matches the element matcher it maps to
//through the id function, and every element matcher is matched.
// Expect([]string{"a", "b"}).To(MatchAllElements(idFn, matchers.Elements{
// "a": BeEqual("a"),
// "b": BeEqual("b"),
// })
func MatchAllElements(identifier Identifier, elements Elements) types.GomegaMatcher {
return &ElementsMatcher{
Identifier: identifier,
Elements: elements,
}
}
//MatchElements succeeds if each element of a slice matches the element matcher it maps to
//through the id function. It can ignore extra elements and/or missing elements.
// Expect([]string{"a", "c"}).To(MatchElements(idFn, IgnoreMissing|IgnoreExtra, matchers.Elements{
// "a": BeEqual("a")
// "b": BeEqual("b"),
// })
func MatchElements(identifier Identifier, options Options, elements Elements) types.GomegaMatcher {
return &ElementsMatcher{
Identifier: identifier,
Elements: elements,
IgnoreExtras: options&IgnoreExtras != 0,
IgnoreMissing: options&IgnoreMissing != 0,
AllowDuplicates: options&AllowDuplicates != 0,
}
}
// ElementsMatcher is a NestingMatcher that applies custom matchers to each element of a slice mapped
// by the Identifier function.
// TODO: Extend this to work with arrays & maps (map the key) as well.
type ElementsMatcher struct {
// Matchers for each element.
Elements Elements
// Function mapping an element to the string key identifying its matcher.
Identifier Identifier
// Whether to ignore extra elements or consider it an error.
IgnoreExtras bool
// Whether to ignore missing elements or consider it an error.
IgnoreMissing bool
// Whether to key duplicates when matching IDs.
AllowDuplicates bool
// State.
failures []error
}
// Element ID to matcher.
type Elements map[string]types.GomegaMatcher
// Function for identifying (mapping) elements.
type Identifier func(element interface{}) string
func (m *ElementsMatcher) Match(actual interface{}) (success bool, err error) {
if reflect.TypeOf(actual).Kind() != reflect.Slice {
return false, fmt.Errorf("%v is type %T, expected slice", actual, actual)
}
m.failures = m.matchElements(actual)
if len(m.failures) > 0 {
return false, nil
}
return true, nil
}
func (m *ElementsMatcher) matchElements(actual interface{}) (errs []error) {
// Provide more useful error messages in the case of a panic.
defer func() {
if err := recover(); err != nil {
errs = append(errs, fmt.Errorf("panic checking %+v: %v\n%s", actual, err, debug.Stack()))
}
}()
val := reflect.ValueOf(actual)
elements := map[string]bool{}
for i := 0; i < val.Len(); i++ {
element := val.Index(i).Interface()
id := m.Identifier(element)
if elements[id] {
if !m.AllowDuplicates {
errs = append(errs, fmt.Errorf("found duplicate element ID %s", id))
continue
}
}
elements[id] = true
matcher, expected := m.Elements[id]
if !expected {
if !m.IgnoreExtras {
errs = append(errs, fmt.Errorf("unexpected element %s", id))
}
continue
}
match, err := matcher.Match(element)
if match {
continue
}
if err == nil {
if nesting, ok := matcher.(errorsutil.NestingMatcher); ok {
err = errorsutil.AggregateError(nesting.Failures())
} else {
err = errors.New(matcher.FailureMessage(element))
}
}
errs = append(errs, errorsutil.Nest(fmt.Sprintf("[%s]", id), err))
}
for id := range m.Elements {
if !elements[id] && !m.IgnoreMissing {
errs = append(errs, fmt.Errorf("missing expected element %s", id))
}
}
return errs
}
func (m *ElementsMatcher) FailureMessage(actual interface{}) (message string) {
failure := errorsutil.AggregateError(m.failures)
return format.Message(actual, fmt.Sprintf("to match elements: %v", failure))
}
func (m *ElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to match elements")
}
func (m *ElementsMatcher) Failures() []error {
return m.failures
}

View File

@@ -0,0 +1,72 @@
package errors
import (
"fmt"
"strings"
"github.com/onsi/gomega/types"
)
// A stateful matcher that nests other matchers within it and preserves the error types of the
// nested matcher failures.
type NestingMatcher interface {
types.GomegaMatcher
// Returns the failures of nested matchers.
Failures() []error
}
// An error type for labeling errors on deeply nested matchers.
type NestedError struct {
Path string
Err error
}
func (e *NestedError) Error() string {
// Indent Errors.
indented := strings.Replace(e.Err.Error(), "\n", "\n\t", -1)
return fmt.Sprintf("%s:\n\t%v", e.Path, indented)
}
// Create a NestedError with the given path.
// If err is a NestedError, prepend the path to it.
// If err is an AggregateError, recursively Nest each error.
func Nest(path string, err error) error {
if ag, ok := err.(AggregateError); ok {
var errs AggregateError
for _, e := range ag {
errs = append(errs, Nest(path, e))
}
return errs
}
if ne, ok := err.(*NestedError); ok {
return &NestedError{
Path: path + ne.Path,
Err: ne.Err,
}
}
return &NestedError{
Path: path,
Err: err,
}
}
// An error type for treating multiple errors as a single error.
type AggregateError []error
// Error is part of the error interface.
func (err AggregateError) Error() string {
if len(err) == 0 {
// This should never happen, really.
return ""
}
if len(err) == 1 {
return err[0].Error()
}
result := fmt.Sprintf("[%s", err[0].Error())
for i := 1; i < len(err); i++ {
result += fmt.Sprintf(", %s", err[i].Error())
}
result += "]"
return result
}

141
vendor/github.com/onsi/gomega/gstruct/fields.go generated vendored Normal file
View File

@@ -0,0 +1,141 @@
package gstruct
import (
"errors"
"fmt"
"reflect"
"runtime/debug"
"strings"
"github.com/onsi/gomega/format"
errorsutil "github.com/onsi/gomega/gstruct/errors"
"github.com/onsi/gomega/types"
)
//MatchAllFields succeeds if every field of a struct matches the field matcher associated with
//it, and every element matcher is matched.
// Expect([]string{"a", "b"}).To(MatchAllFields(idFn, gstruct.Fields{
// "a": BeEqual("a"),
// "b": BeEqual("b"),
// })
func MatchAllFields(fields Fields) types.GomegaMatcher {
return &FieldsMatcher{
Fields: fields,
}
}
//MatchFields succeeds if each element of a struct matches the field matcher associated with
//it. It can ignore extra fields and/or missing fields.
// Expect([]string{"a", "c"}).To(MatchFields(idFn, IgnoreMissing|IgnoreExtra, gstruct.Fields{
// "a": BeEqual("a")
// "b": BeEqual("b"),
// })
func MatchFields(options Options, fields Fields) types.GomegaMatcher {
return &FieldsMatcher{
Fields: fields,
IgnoreExtras: options&IgnoreExtras != 0,
IgnoreMissing: options&IgnoreMissing != 0,
}
}
type FieldsMatcher struct {
// Matchers for each field.
Fields Fields
// Whether to ignore extra elements or consider it an error.
IgnoreExtras bool
// Whether to ignore missing elements or consider it an error.
IgnoreMissing bool
// State.
failures []error
}
// Field name to matcher.
type Fields map[string]types.GomegaMatcher
func (m *FieldsMatcher) Match(actual interface{}) (success bool, err error) {
if reflect.TypeOf(actual).Kind() != reflect.Struct {
return false, fmt.Errorf("%v is type %T, expected struct", actual, actual)
}
m.failures = m.matchFields(actual)
if len(m.failures) > 0 {
return false, nil
}
return true, nil
}
func (m *FieldsMatcher) matchFields(actual interface{}) (errs []error) {
val := reflect.ValueOf(actual)
typ := val.Type()
fields := map[string]bool{}
for i := 0; i < val.NumField(); i++ {
fieldName := typ.Field(i).Name
fields[fieldName] = true
err := func() (err error) {
// This test relies heavily on reflect, which tends to panic.
// Recover here to provide more useful error messages in that case.
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic checking %+v: %v\n%s", actual, r, debug.Stack())
}
}()
matcher, expected := m.Fields[fieldName]
if !expected {
if !m.IgnoreExtras {
return fmt.Errorf("unexpected field %s: %+v", fieldName, actual)
}
return nil
}
var field interface{}
if val.Field(i).IsValid() {
field = val.Field(i).Interface()
} else {
field = reflect.Zero(typ.Field(i).Type)
}
match, err := matcher.Match(field)
if err != nil {
return err
} else if !match {
if nesting, ok := matcher.(errorsutil.NestingMatcher); ok {
return errorsutil.AggregateError(nesting.Failures())
}
return errors.New(matcher.FailureMessage(field))
}
return nil
}()
if err != nil {
errs = append(errs, errorsutil.Nest("."+fieldName, err))
}
}
for field := range m.Fields {
if !fields[field] && !m.IgnoreMissing {
errs = append(errs, fmt.Errorf("missing expected field %s", field))
}
}
return errs
}
func (m *FieldsMatcher) FailureMessage(actual interface{}) (message string) {
failures := make([]string, len(m.failures))
for i := range m.failures {
failures[i] = m.failures[i].Error()
}
return format.Message(reflect.TypeOf(actual).Name(),
fmt.Sprintf("to match fields: {\n%v\n}\n", strings.Join(failures, "\n")))
}
func (m *FieldsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to match fields")
}
func (m *FieldsMatcher) Failures() []error {
return m.failures
}

37
vendor/github.com/onsi/gomega/gstruct/ignore.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package gstruct
import (
"github.com/onsi/gomega/types"
)
//Ignore ignores the actual value and always succeeds.
// Expect(nil).To(Ignore())
// Expect(true).To(Ignore())
func Ignore() types.GomegaMatcher {
return &IgnoreMatcher{true}
}
//Reject ignores the actual value and always fails. It can be used in conjunction with IgnoreMissing
//to catch problematic elements, or to verify tests are running.
// Expect(nil).NotTo(Reject())
// Expect(true).NotTo(Reject())
func Reject() types.GomegaMatcher {
return &IgnoreMatcher{false}
}
// A matcher that either always succeeds or always fails.
type IgnoreMatcher struct {
Succeed bool
}
func (m *IgnoreMatcher) Match(actual interface{}) (bool, error) {
return m.Succeed, nil
}
func (m *IgnoreMatcher) FailureMessage(_ interface{}) (message string) {
return "Unconditional failure"
}
func (m *IgnoreMatcher) NegatedFailureMessage(_ interface{}) (message string) {
return "Unconditional success"
}

56
vendor/github.com/onsi/gomega/gstruct/pointer.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package gstruct
import (
"fmt"
"reflect"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/types"
)
//PointTo applies the given matcher to the value pointed to by actual. It fails if the pointer is
//nil.
// actual := 5
// Expect(&actual).To(PointTo(Equal(5)))
func PointTo(matcher types.GomegaMatcher) types.GomegaMatcher {
return &PointerMatcher{
Matcher: matcher,
}
}
type PointerMatcher struct {
Matcher types.GomegaMatcher
// Failure message.
failure string
}
func (m *PointerMatcher) Match(actual interface{}) (bool, error) {
val := reflect.ValueOf(actual)
// return error if actual type is not a pointer
if val.Kind() != reflect.Ptr {
return false, fmt.Errorf("PointerMatcher expects a pointer but we have '%s'", val.Kind())
}
if !val.IsValid() || val.IsNil() {
m.failure = format.Message(actual, "not to be <nil>")
return false, nil
}
// Forward the value.
elem := val.Elem().Interface()
match, err := m.Matcher.Match(elem)
if !match {
m.failure = m.Matcher.FailureMessage(elem)
}
return match, err
}
func (m *PointerMatcher) FailureMessage(_ interface{}) (message string) {
return m.failure
}
func (m *PointerMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return m.Matcher.NegatedFailureMessage(actual)
}

15
vendor/github.com/onsi/gomega/gstruct/types.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
package gstruct
//Options is the type for options passed to some matchers.
type Options int
const (
//IgnoreExtras tells the matcher to ignore extra elements or fields, rather than triggering a failure.
IgnoreExtras Options = 1 << iota
//IgnoreMissing tells the matcher to ignore missing elements or fields, rather than triggering a failure.
IgnoreMissing
//AllowDuplicates tells the matcher to permit multiple members of the slice to produce the same ID when
//considered by the indentifier function. All members that map to a given key must still match successfully
//with the matcher that is provided for that key.
AllowDuplicates
)

View File

@@ -1,13 +0,0 @@
package assertion_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestAssertion(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Assertion Suite")
}

View File

@@ -1,252 +0,0 @@
package assertion_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/internal/assertion"
"github.com/onsi/gomega/internal/fakematcher"
)
var _ = Describe("Assertion", func() {
var (
a *Assertion
failureMessage string
failureCallerSkip int
matcher *fakematcher.FakeMatcher
)
input := "The thing I'm testing"
var fakeFailHandler = func(message string, callerSkip ...int) {
failureMessage = message
if len(callerSkip) == 1 {
failureCallerSkip = callerSkip[0]
}
}
BeforeEach(func() {
matcher = &fakematcher.FakeMatcher{}
failureMessage = ""
failureCallerSkip = 0
a = New(input, fakeFailHandler, 1)
})
Context("when called", func() {
It("should pass the provided input value to the matcher", func() {
a.Should(matcher)
Ω(matcher.ReceivedActual).Should(Equal(input))
matcher.ReceivedActual = ""
a.ShouldNot(matcher)
Ω(matcher.ReceivedActual).Should(Equal(input))
matcher.ReceivedActual = ""
a.To(matcher)
Ω(matcher.ReceivedActual).Should(Equal(input))
matcher.ReceivedActual = ""
a.ToNot(matcher)
Ω(matcher.ReceivedActual).Should(Equal(input))
matcher.ReceivedActual = ""
a.NotTo(matcher)
Ω(matcher.ReceivedActual).Should(Equal(input))
})
})
Context("when the matcher succeeds", func() {
BeforeEach(func() {
matcher.MatchesToReturn = true
matcher.ErrToReturn = nil
})
Context("and a positive assertion is being made", func() {
It("should not call the failure callback", func() {
a.Should(matcher)
Ω(failureMessage).Should(Equal(""))
})
It("should be true", func() {
Ω(a.Should(matcher)).Should(BeTrue())
})
})
Context("and a negative assertion is being made", func() {
It("should call the failure callback", func() {
a.ShouldNot(matcher)
Ω(failureMessage).Should(Equal("negative: The thing I'm testing"))
Ω(failureCallerSkip).Should(Equal(3))
})
It("should be false", func() {
Ω(a.ShouldNot(matcher)).Should(BeFalse())
})
})
})
Context("when the matcher fails", func() {
BeforeEach(func() {
matcher.MatchesToReturn = false
matcher.ErrToReturn = nil
})
Context("and a positive assertion is being made", func() {
It("should call the failure callback", func() {
a.Should(matcher)
Ω(failureMessage).Should(Equal("positive: The thing I'm testing"))
Ω(failureCallerSkip).Should(Equal(3))
})
It("should be false", func() {
Ω(a.Should(matcher)).Should(BeFalse())
})
})
Context("and a negative assertion is being made", func() {
It("should not call the failure callback", func() {
a.ShouldNot(matcher)
Ω(failureMessage).Should(Equal(""))
})
It("should be true", func() {
Ω(a.ShouldNot(matcher)).Should(BeTrue())
})
})
})
Context("When reporting a failure", func() {
BeforeEach(func() {
matcher.MatchesToReturn = false
matcher.ErrToReturn = nil
})
Context("and there is an optional description", func() {
It("should append the description to the failure message", func() {
a.Should(matcher, "A description")
Ω(failureMessage).Should(Equal("A description\npositive: The thing I'm testing"))
Ω(failureCallerSkip).Should(Equal(3))
})
})
Context("and there are multiple arguments to the optional description", func() {
It("should append the formatted description to the failure message", func() {
a.Should(matcher, "A description of [%d]", 3)
Ω(failureMessage).Should(Equal("A description of [3]\npositive: The thing I'm testing"))
Ω(failureCallerSkip).Should(Equal(3))
})
})
})
Context("When the matcher returns an error", func() {
BeforeEach(func() {
matcher.ErrToReturn = errors.New("Kaboom!")
})
Context("and a positive assertion is being made", func() {
It("should call the failure callback", func() {
matcher.MatchesToReturn = true
a.Should(matcher)
Ω(failureMessage).Should(Equal("Kaboom!"))
Ω(failureCallerSkip).Should(Equal(3))
})
})
Context("and a negative assertion is being made", func() {
It("should call the failure callback", func() {
matcher.MatchesToReturn = false
a.ShouldNot(matcher)
Ω(failureMessage).Should(Equal("Kaboom!"))
Ω(failureCallerSkip).Should(Equal(3))
})
})
It("should always be false", func() {
Ω(a.Should(matcher)).Should(BeFalse())
Ω(a.ShouldNot(matcher)).Should(BeFalse())
})
})
Context("when there are extra parameters", func() {
It("(a simple example)", func() {
Ω(func() (string, int, error) {
return "foo", 0, nil
}()).Should(Equal("foo"))
})
Context("when the parameters are all nil or zero", func() {
It("should invoke the matcher", func() {
matcher.MatchesToReturn = true
matcher.ErrToReturn = nil
var typedNil []string
a = New(input, fakeFailHandler, 1, 0, nil, typedNil)
result := a.Should(matcher)
Ω(result).Should(BeTrue())
Ω(matcher.ReceivedActual).Should(Equal(input))
Ω(failureMessage).Should(BeZero())
})
})
Context("when any of the parameters are not nil or zero", func() {
It("should call the failure callback", func() {
matcher.MatchesToReturn = false
matcher.ErrToReturn = nil
a = New(input, fakeFailHandler, 1, errors.New("foo"))
result := a.Should(matcher)
Ω(result).Should(BeFalse())
Ω(matcher.ReceivedActual).Should(BeZero(), "The matcher doesn't even get called")
Ω(failureMessage).Should(ContainSubstring("foo"))
failureMessage = ""
a = New(input, fakeFailHandler, 1, nil, 1)
result = a.ShouldNot(matcher)
Ω(result).Should(BeFalse())
Ω(failureMessage).Should(ContainSubstring("1"))
failureMessage = ""
a = New(input, fakeFailHandler, 1, nil, 0, []string{"foo"})
result = a.To(matcher)
Ω(result).Should(BeFalse())
Ω(failureMessage).Should(ContainSubstring("foo"))
failureMessage = ""
a = New(input, fakeFailHandler, 1, nil, 0, []string{"foo"})
result = a.ToNot(matcher)
Ω(result).Should(BeFalse())
Ω(failureMessage).Should(ContainSubstring("foo"))
failureMessage = ""
a = New(input, fakeFailHandler, 1, nil, 0, []string{"foo"})
result = a.NotTo(matcher)
Ω(result).Should(BeFalse())
Ω(failureMessage).Should(ContainSubstring("foo"))
Ω(failureCallerSkip).Should(Equal(3))
})
})
})
Context("Making an assertion without a registered fail handler", func() {
It("should panic", func() {
defer func() {
e := recover()
RegisterFailHandler(Fail)
if e == nil {
Fail("expected a panic to have occurred")
}
}()
RegisterFailHandler(nil)
Ω(true).Should(BeTrue())
})
})
})

View File

@@ -1,13 +0,0 @@
package asyncassertion_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestAsyncAssertion(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "AsyncAssertion Suite")
}

View File

@@ -1,345 +0,0 @@
package asyncassertion_test
import (
"errors"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/internal/asyncassertion"
)
var _ = Describe("Async Assertion", func() {
var (
failureMessage string
callerSkip int
)
var fakeFailHandler = func(message string, skip ...int) {
failureMessage = message
callerSkip = skip[0]
}
BeforeEach(func() {
failureMessage = ""
callerSkip = 0
})
Describe("Eventually", func() {
Context("the positive case", func() {
It("should poll the function and matcher", func() {
counter := 0
a := New(AsyncAssertionTypeEventually, func() int {
counter++
return counter
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(BeNumerically("==", 5))
Ω(failureMessage).Should(BeZero())
})
It("should continue when the matcher errors", func() {
counter := 0
a := New(AsyncAssertionTypeEventually, func() interface{} {
counter++
if counter == 5 {
return "not-a-number" //this should cause the matcher to error
}
return counter
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(BeNumerically("==", 5), "My description %d", 2)
Ω(failureMessage).Should(ContainSubstring("Timed out after"))
Ω(failureMessage).Should(ContainSubstring("My description 2"))
Ω(callerSkip).Should(Equal(4))
})
It("should be able to timeout", func() {
counter := 0
a := New(AsyncAssertionTypeEventually, func() int {
counter++
return counter
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(BeNumerically(">", 100), "My description %d", 2)
Ω(counter).Should(BeNumerically(">", 8))
Ω(counter).Should(BeNumerically("<=", 10))
Ω(failureMessage).Should(ContainSubstring("Timed out after"))
Ω(failureMessage).Should(MatchRegexp(`\<int\>: \d`), "Should pass the correct value to the matcher message formatter.")
Ω(failureMessage).Should(ContainSubstring("My description 2"))
Ω(callerSkip).Should(Equal(4))
})
})
Context("the negative case", func() {
It("should poll the function and matcher", func() {
counter := 0
a := New(AsyncAssertionTypeEventually, func() int {
counter += 1
return counter
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(BeNumerically("<", 3))
Ω(counter).Should(Equal(3))
Ω(failureMessage).Should(BeZero())
})
It("should timeout when the matcher errors", func() {
a := New(AsyncAssertionTypeEventually, func() interface{} {
return 0 //this should cause the matcher to error
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(HaveLen(0), "My description %d", 2)
Ω(failureMessage).Should(ContainSubstring("Timed out after"))
Ω(failureMessage).Should(ContainSubstring("Error:"))
Ω(failureMessage).Should(ContainSubstring("My description 2"))
Ω(callerSkip).Should(Equal(4))
})
It("should be able to timeout", func() {
a := New(AsyncAssertionTypeEventually, func() int {
return 0
}, fakeFailHandler, time.Duration(0.1*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(Equal(0), "My description %d", 2)
Ω(failureMessage).Should(ContainSubstring("Timed out after"))
Ω(failureMessage).Should(ContainSubstring("<int>: 0"), "Should pass the correct value to the matcher message formatter.")
Ω(failureMessage).Should(ContainSubstring("My description 2"))
Ω(callerSkip).Should(Equal(4))
})
})
Context("with a function that returns multiple values", func() {
It("should eventually succeed if the additional arguments are nil", func() {
i := 0
Eventually(func() (int, error) {
i++
return i, nil
}).Should(Equal(10))
})
It("should eventually timeout if the additional arguments are not nil", func() {
i := 0
a := New(AsyncAssertionTypeEventually, func() (int, error) {
i++
return i, errors.New("bam")
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(Equal(2))
Ω(failureMessage).Should(ContainSubstring("Timed out after"))
Ω(failureMessage).Should(ContainSubstring("Error:"))
Ω(failureMessage).Should(ContainSubstring("bam"))
Ω(callerSkip).Should(Equal(4))
})
})
Context("Making an assertion without a registered fail handler", func() {
It("should panic", func() {
defer func() {
e := recover()
RegisterFailHandler(Fail)
if e == nil {
Fail("expected a panic to have occurred")
}
}()
RegisterFailHandler(nil)
c := make(chan bool, 1)
c <- true
Eventually(c).Should(Receive())
})
})
})
Describe("Consistently", func() {
Describe("The positive case", func() {
Context("when the matcher consistently passes for the duration", func() {
It("should pass", func() {
calls := 0
a := New(AsyncAssertionTypeConsistently, func() string {
calls++
return "foo"
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(Equal("foo"))
Ω(calls).Should(BeNumerically(">", 8))
Ω(calls).Should(BeNumerically("<=", 10))
Ω(failureMessage).Should(BeZero())
})
})
Context("when the matcher fails at some point", func() {
It("should fail", func() {
calls := 0
a := New(AsyncAssertionTypeConsistently, func() interface{} {
calls++
if calls > 5 {
return "bar"
}
return "foo"
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(Equal("foo"))
Ω(failureMessage).Should(ContainSubstring("to equal"))
Ω(callerSkip).Should(Equal(4))
})
})
Context("when the matcher errors at some point", func() {
It("should fail", func() {
calls := 0
a := New(AsyncAssertionTypeConsistently, func() interface{} {
calls++
if calls > 5 {
return 3
}
return []int{1, 2, 3}
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(HaveLen(3))
Ω(failureMessage).Should(ContainSubstring("HaveLen matcher expects"))
Ω(callerSkip).Should(Equal(4))
})
})
})
Describe("The negative case", func() {
Context("when the matcher consistently passes for the duration", func() {
It("should pass", func() {
c := make(chan bool)
a := New(AsyncAssertionTypeConsistently, c, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(Receive())
Ω(failureMessage).Should(BeZero())
})
})
Context("when the matcher fails at some point", func() {
It("should fail", func() {
c := make(chan bool)
go func() {
time.Sleep(time.Duration(100 * time.Millisecond))
c <- true
}()
a := New(AsyncAssertionTypeConsistently, c, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(Receive())
Ω(failureMessage).Should(ContainSubstring("not to receive anything"))
})
})
Context("when the matcher errors at some point", func() {
It("should fail", func() {
calls := 0
a := New(AsyncAssertionTypeConsistently, func() interface{} {
calls++
return calls
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.ShouldNot(BeNumerically(">", 5))
Ω(failureMessage).Should(ContainSubstring("not to be >"))
Ω(callerSkip).Should(Equal(4))
})
})
})
Context("with a function that returns multiple values", func() {
It("should consistently succeed if the additional arguments are nil", func() {
i := 2
Consistently(func() (int, error) {
i++
return i, nil
}).Should(BeNumerically(">=", 2))
})
It("should eventually timeout if the additional arguments are not nil", func() {
i := 2
a := New(AsyncAssertionTypeEventually, func() (int, error) {
i++
return i, errors.New("bam")
}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1)
a.Should(BeNumerically(">=", 2))
Ω(failureMessage).Should(ContainSubstring("Error:"))
Ω(failureMessage).Should(ContainSubstring("bam"))
Ω(callerSkip).Should(Equal(4))
})
})
Context("Making an assertion without a registered fail handler", func() {
It("should panic", func() {
defer func() {
e := recover()
RegisterFailHandler(Fail)
if e == nil {
Fail("expected a panic to have occurred")
}
}()
RegisterFailHandler(nil)
c := make(chan bool)
Consistently(c).ShouldNot(Receive())
})
})
})
Context("when passed a function with the wrong # or arguments & returns", func() {
It("should panic", func() {
Ω(func() {
New(AsyncAssertionTypeEventually, func() {}, fakeFailHandler, 0, 0, 1)
}).Should(Panic())
Ω(func() {
New(AsyncAssertionTypeEventually, func(a string) int { return 0 }, fakeFailHandler, 0, 0, 1)
}).Should(Panic())
Ω(func() {
New(AsyncAssertionTypeEventually, func() int { return 0 }, fakeFailHandler, 0, 0, 1)
}).ShouldNot(Panic())
Ω(func() {
New(AsyncAssertionTypeEventually, func() (int, error) { return 0, nil }, fakeFailHandler, 0, 0, 1)
}).ShouldNot(Panic())
})
})
Describe("bailing early", func() {
Context("when actual is a value", func() {
It("Eventually should bail out and fail early if the matcher says to", func() {
c := make(chan bool)
close(c)
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(c, 0.1).Should(Receive())
})
Ω(time.Since(t)).Should(BeNumerically("<", 90*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
})
Context("when actual is a function", func() {
It("should never bail early", func() {
c := make(chan bool)
close(c)
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(func() chan bool {
return c
}, 0.1).Should(Receive())
})
Ω(time.Since(t)).Should(BeNumerically(">=", 90*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
})
})
})

View File

@@ -1,12 +0,0 @@
package testingtsupport_test
import (
. "github.com/onsi/gomega"
"testing"
)
func TestTestingT(t *testing.T) {
RegisterTestingT(t)
Ω(true).Should(BeTrue())
}

View File

@@ -176,7 +176,7 @@ func MatchRegexp(regexp string, args ...interface{}) types.GomegaMatcher {
}
//ContainSubstring succeeds if actual is a string or stringer that contains the
//passed-in regexp. Optional arguments can be provided to construct the substring
//passed-in substring. Optional arguments can be provided to construct the substring
//via fmt.Sprintf().
func ContainSubstring(substr string, args ...interface{}) types.GomegaMatcher {
return &matchers.ContainSubstringMatcher{
@@ -214,6 +214,15 @@ func MatchJSON(json interface{}) types.GomegaMatcher {
}
}
//MatchYAML succeeds if actual is a string or stringer of YAML that matches
//the expected YAML. The YAML's are decoded and the resulting objects are compared via
//reflect.DeepEqual so things like key-ordering and whitespace shouldn't matter.
func MatchYAML(yaml interface{}) types.GomegaMatcher {
return &matchers.MatchYAMLMatcher{
YAMLToMatch: yaml,
}
}
//BeEmpty succeeds if actual is empty. Actual must be of type string, array, map, chan, or slice.
func BeEmpty() types.GomegaMatcher {
return &matchers.BeEmptyMatcher{}

View File

@@ -1,103 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
"github.com/onsi/gomega/types"
)
// sample data
var (
// example input
input = "hi"
// some matchers that succeed against the input
true1 = HaveLen(2)
true2 = Equal("hi")
true3 = MatchRegexp("hi")
// some matchers that fail against the input.
false1 = HaveLen(1)
false2 = Equal("hip")
false3 = MatchRegexp("hope")
)
// verifyFailureMessage expects the matcher to fail with the given input, and verifies the failure message.
func verifyFailureMessage(m types.GomegaMatcher, input string, expectedFailureMsgFragment string) {
Expect(m.Match(input)).To(BeFalse())
Expect(m.FailureMessage(input)).To(Equal(
"Expected\n <string>: " + input + "\n" + expectedFailureMsgFragment))
}
var _ = Describe("AndMatcher", func() {
It("works with positive cases", func() {
Expect(input).To(And())
Expect(input).To(And(true1))
Expect(input).To(And(true1, true2))
Expect(input).To(And(true1, true2, true3))
// use alias
Expect(input).To(SatisfyAll(true1, true2, true3))
})
It("works with negative cases", func() {
Expect(input).ToNot(And(false1, false2))
Expect(input).ToNot(And(true1, true2, false3))
Expect(input).ToNot(And(true1, false2, false3))
Expect(input).ToNot(And(false1, true1, true2))
})
Context("failure messages", func() {
Context("when match fails", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(And(false1, true1), input, "to have length 1")
verifyFailureMessage(And(true1, false2), input, "to equal\n <string>: hip")
verifyFailureMessage(And(true1, true2, false3), input, "to match regular expression\n <string>: hope")
})
})
Context("when match succeeds, but expected it to fail", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(Not(And(true1, true2)), input,
`To not satisfy all of these matchers: [%!s(*matchers.HaveLenMatcher=&{2}) %!s(*matchers.EqualMatcher=&{hi})]`)
})
})
})
Context("MatchMayChangeInTheFuture", func() {
Context("Match returned false", func() {
Context("returns value of the failed matcher", func() {
It("false if failed matcher not going to change", func() {
// 3 matchers: 1st returns true, 2nd returns false and is not going to change, 3rd is never called
m := And(Not(BeNil()), Or(), Equal(1))
Expect(m.Match("hi")).To(BeFalse())
Expect(m.(*AndMatcher).MatchMayChangeInTheFuture("hi")).To(BeFalse()) // empty Or() indicates not going to change
})
It("true if failed matcher indicates it might change", func() {
// 3 matchers: 1st returns true, 2nd returns false and "might" change, 3rd is never called
m := And(Not(BeNil()), Equal(5), Equal(1))
Expect(m.Match("hi")).To(BeFalse())
Expect(m.(*AndMatcher).MatchMayChangeInTheFuture("hi")).To(BeTrue()) // Equal(5) indicates it might change
})
})
})
Context("Match returned true", func() {
It("returns true if any of the matchers could change", func() {
// 3 matchers, all return true, and all could change
m := And(Not(BeNil()), Equal("hi"), HaveLen(2))
Expect(m.Match("hi")).To(BeTrue())
Expect(m.(*AndMatcher).MatchMayChangeInTheFuture("hi")).To(BeTrue()) // all 3 of these matchers default to 'true'
})
It("returns false if none of the matchers could change", func() {
// empty And() has the property of always matching, and never can change since there are no sub-matchers that could change
m := And()
Expect(m.Match("anything")).To(BeTrue())
Expect(m.(*AndMatcher).MatchMayChangeInTheFuture("anything")).To(BeFalse())
// And() with 3 sub-matchers that return true, and can't change
m = And(And(), And(), And())
Expect(m.Match("hi")).To(BeTrue())
Expect(m.(*AndMatcher).MatchMayChangeInTheFuture("hi")).To(BeFalse()) // the 3 empty And()'s won't change
})
})
})
})

View File

@@ -1,30 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("AssignableToTypeOf", func() {
Context("When asserting assignability between types", func() {
It("should do the right thing", func() {
Ω(0).Should(BeAssignableToTypeOf(0))
Ω(5).Should(BeAssignableToTypeOf(-1))
Ω("foo").Should(BeAssignableToTypeOf("bar"))
Ω(struct{ Foo string }{}).Should(BeAssignableToTypeOf(struct{ Foo string }{}))
Ω(0).ShouldNot(BeAssignableToTypeOf("bar"))
Ω(5).ShouldNot(BeAssignableToTypeOf(struct{ Foo string }{}))
Ω("foo").ShouldNot(BeAssignableToTypeOf(42))
})
})
Context("When asserting nil values", func() {
It("should error", func() {
success, err := (&AssignableToTypeOfMatcher{Expected: nil}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,40 +0,0 @@
package matchers_test
import (
"io/ioutil"
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeADirectoryMatcher", func() {
Context("when passed a string", func() {
It("should do the right thing", func() {
Ω("/dne/test").ShouldNot(BeADirectory())
tmpFile, err := ioutil.TempFile("", "gomega-test-tempfile")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpFile.Name())
Ω(tmpFile.Name()).ShouldNot(BeADirectory())
tmpDir, err := ioutil.TempDir("", "gomega-test-tempdir")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpDir)
Ω(tmpDir).Should(BeADirectory())
})
})
Context("when passed something else", func() {
It("should error", func() {
success, err := (&BeADirectoryMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeADirectoryMatcher{}).Match(true)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,40 +0,0 @@
package matchers_test
import (
"io/ioutil"
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeARegularFileMatcher", func() {
Context("when passed a string", func() {
It("should do the right thing", func() {
Ω("/dne/test").ShouldNot(BeARegularFile())
tmpFile, err := ioutil.TempFile("", "gomega-test-tempfile")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpFile.Name())
Ω(tmpFile.Name()).Should(BeARegularFile())
tmpDir, err := ioutil.TempDir("", "gomega-test-tempdir")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpDir)
Ω(tmpDir).ShouldNot(BeARegularFile())
})
})
Context("when passed something else", func() {
It("should error", func() {
success, err := (&BeARegularFileMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeARegularFileMatcher{}).Match(true)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,40 +0,0 @@
package matchers_test
import (
"io/ioutil"
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeAnExistingFileMatcher", func() {
Context("when passed a string", func() {
It("should do the right thing", func() {
Ω("/dne/test").ShouldNot(BeAnExistingFile())
tmpFile, err := ioutil.TempFile("", "gomega-test-tempfile")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpFile.Name())
Ω(tmpFile.Name()).Should(BeAnExistingFile())
tmpDir, err := ioutil.TempDir("", "gomega-test-tempdir")
Ω(err).ShouldNot(HaveOccurred())
defer os.Remove(tmpDir)
Ω(tmpDir).Should(BeAnExistingFile())
})
})
Context("when passed something else", func() {
It("should error", func() {
success, err := (&BeAnExistingFileMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeAnExistingFileMatcher{}).Match(true)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,70 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeClosedMatcher", func() {
Context("when passed a channel", func() {
It("should do the right thing", func() {
openChannel := make(chan bool)
Ω(openChannel).ShouldNot(BeClosed())
var openReaderChannel <-chan bool
openReaderChannel = openChannel
Ω(openReaderChannel).ShouldNot(BeClosed())
closedChannel := make(chan bool)
close(closedChannel)
Ω(closedChannel).Should(BeClosed())
var closedReaderChannel <-chan bool
closedReaderChannel = closedChannel
Ω(closedReaderChannel).Should(BeClosed())
})
})
Context("when passed a send-only channel", func() {
It("should error", func() {
openChannel := make(chan bool)
var openWriterChannel chan<- bool
openWriterChannel = openChannel
success, err := (&BeClosedMatcher{}).Match(openWriterChannel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
closedChannel := make(chan bool)
close(closedChannel)
var closedWriterChannel chan<- bool
closedWriterChannel = closedChannel
success, err = (&BeClosedMatcher{}).Match(closedWriterChannel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed something else", func() {
It("should error", func() {
var nilChannel chan bool
success, err := (&BeClosedMatcher{}).Match(nilChannel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeClosedMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeClosedMatcher{}).Match(7)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,52 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeEmpty", func() {
Context("when passed a supported type", func() {
It("should do the right thing", func() {
Ω("").Should(BeEmpty())
Ω(" ").ShouldNot(BeEmpty())
Ω([0]int{}).Should(BeEmpty())
Ω([1]int{1}).ShouldNot(BeEmpty())
Ω([]int{}).Should(BeEmpty())
Ω([]int{1}).ShouldNot(BeEmpty())
Ω(map[string]int{}).Should(BeEmpty())
Ω(map[string]int{"a": 1}).ShouldNot(BeEmpty())
c := make(chan bool, 1)
Ω(c).Should(BeEmpty())
c <- true
Ω(c).ShouldNot(BeEmpty())
})
})
Context("when passed a correctly typed nil", func() {
It("should be true", func() {
var nilSlice []int
Ω(nilSlice).Should(BeEmpty())
var nilMap map[int]string
Ω(nilMap).Should(BeEmpty())
})
})
Context("when passed an unsupported type", func() {
It("should error", func() {
success, err := (&BeEmptyMatcher{}).Match(0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeEmptyMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,50 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeEquivalentTo", func() {
Context("when asserting that nil is equivalent to nil", func() {
It("should error", func() {
success, err := (&BeEquivalentToMatcher{Expected: nil}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("When asserting on nil", func() {
It("should do the right thing", func() {
Ω("foo").ShouldNot(BeEquivalentTo(nil))
Ω(nil).ShouldNot(BeEquivalentTo(3))
Ω([]int{1, 2}).ShouldNot(BeEquivalentTo(nil))
})
})
Context("When asserting on type aliases", func() {
It("should the right thing", func() {
Ω(StringAlias("foo")).Should(BeEquivalentTo("foo"))
Ω("foo").Should(BeEquivalentTo(StringAlias("foo")))
Ω(StringAlias("foo")).ShouldNot(BeEquivalentTo("bar"))
Ω("foo").ShouldNot(BeEquivalentTo(StringAlias("bar")))
})
})
Context("When asserting on numbers", func() {
It("should convert actual to expected and do the right thing", func() {
Ω(5).Should(BeEquivalentTo(5))
Ω(5.0).Should(BeEquivalentTo(5.0))
Ω(5).Should(BeEquivalentTo(5.0))
Ω(5).ShouldNot(BeEquivalentTo("5"))
Ω(5).ShouldNot(BeEquivalentTo(3))
//Here be dragons!
Ω(5.1).Should(BeEquivalentTo(5))
Ω(5).ShouldNot(BeEquivalentTo(5.1))
})
})
})

View File

@@ -1,20 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeFalse", func() {
It("should handle true and false correctly", func() {
Ω(true).ShouldNot(BeFalse())
Ω(false).Should(BeFalse())
})
It("should only support booleans", func() {
success, err := (&BeFalseMatcher{}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})

View File

@@ -1,61 +0,0 @@
package matchers_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeIdenticalTo", func() {
Context("when asserting that nil equals nil", func() {
It("should error", func() {
success, err := (&BeIdenticalToMatcher{Expected: nil}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
It("should treat the same pointer to a struct as identical", func() {
mySpecialStruct := myCustomType{}
Ω(&mySpecialStruct).Should(BeIdenticalTo(&mySpecialStruct))
Ω(&myCustomType{}).ShouldNot(BeIdenticalTo(&mySpecialStruct))
})
It("should be strict about types", func() {
Ω(5).ShouldNot(BeIdenticalTo("5"))
Ω(5).ShouldNot(BeIdenticalTo(5.0))
Ω(5).ShouldNot(BeIdenticalTo(3))
})
It("should treat primtives as identical", func() {
Ω("5").Should(BeIdenticalTo("5"))
Ω("5").ShouldNot(BeIdenticalTo("55"))
Ω(5.55).Should(BeIdenticalTo(5.55))
Ω(5.55).ShouldNot(BeIdenticalTo(6.66))
Ω(5).Should(BeIdenticalTo(5))
Ω(5).ShouldNot(BeIdenticalTo(55))
})
It("should treat the same pointers to a slice as identical", func() {
mySlice := []int{1, 2}
Ω(&mySlice).Should(BeIdenticalTo(&mySlice))
Ω(&mySlice).ShouldNot(BeIdenticalTo(&[]int{1, 2}))
})
It("should treat the same pointers to a map as identical", func() {
myMap := map[string]string{"a": "b", "c": "d"}
Ω(&myMap).Should(BeIdenticalTo(&myMap))
Ω(myMap).ShouldNot(BeIdenticalTo(map[string]string{"a": "b", "c": "d"}))
})
It("should treat the same pointers to an error as identical", func() {
myError := errors.New("foo")
Ω(&myError).Should(BeIdenticalTo(&myError))
Ω(errors.New("foo")).ShouldNot(BeIdenticalTo(errors.New("bar")))
})
})

View File

@@ -1,28 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("BeNil", func() {
It("should succeed when passed nil", func() {
Ω(nil).Should(BeNil())
})
It("should succeed when passed a typed nil", func() {
var a []int
Ω(a).Should(BeNil())
})
It("should succeed when passing nil pointer", func() {
var f *struct{}
Ω(f).Should(BeNil())
})
It("should not succeed when not passed nil", func() {
Ω(0).ShouldNot(BeNil())
Ω(false).ShouldNot(BeNil())
Ω("").ShouldNot(BeNil())
})
})

View File

@@ -2,8 +2,9 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"math"
"github.com/onsi/gomega/format"
)
type BeNumericallyMatcher struct {

View File

@@ -1,148 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeNumerically", func() {
Context("when passed a number", func() {
It("should support ==", func() {
Ω(uint32(5)).Should(BeNumerically("==", 5))
Ω(float64(5.0)).Should(BeNumerically("==", 5))
Ω(int8(5)).Should(BeNumerically("==", 5))
})
It("should not have false positives", func() {
Ω(5.1).ShouldNot(BeNumerically("==", 5))
Ω(5).ShouldNot(BeNumerically("==", 5.1))
})
It("should support >", func() {
Ω(uint32(5)).Should(BeNumerically(">", 4))
Ω(float64(5.0)).Should(BeNumerically(">", 4.9))
Ω(int8(5)).Should(BeNumerically(">", 4))
Ω(uint32(5)).ShouldNot(BeNumerically(">", 5))
Ω(float64(5.0)).ShouldNot(BeNumerically(">", 5.0))
Ω(int8(5)).ShouldNot(BeNumerically(">", 5))
})
It("should support <", func() {
Ω(uint32(5)).Should(BeNumerically("<", 6))
Ω(float64(5.0)).Should(BeNumerically("<", 5.1))
Ω(int8(5)).Should(BeNumerically("<", 6))
Ω(uint32(5)).ShouldNot(BeNumerically("<", 5))
Ω(float64(5.0)).ShouldNot(BeNumerically("<", 5.0))
Ω(int8(5)).ShouldNot(BeNumerically("<", 5))
})
It("should support >=", func() {
Ω(uint32(5)).Should(BeNumerically(">=", 4))
Ω(float64(5.0)).Should(BeNumerically(">=", 4.9))
Ω(int8(5)).Should(BeNumerically(">=", 4))
Ω(uint32(5)).Should(BeNumerically(">=", 5))
Ω(float64(5.0)).Should(BeNumerically(">=", 5.0))
Ω(int8(5)).Should(BeNumerically(">=", 5))
Ω(uint32(5)).ShouldNot(BeNumerically(">=", 6))
Ω(float64(5.0)).ShouldNot(BeNumerically(">=", 5.1))
Ω(int8(5)).ShouldNot(BeNumerically(">=", 6))
})
It("should support <=", func() {
Ω(uint32(5)).Should(BeNumerically("<=", 6))
Ω(float64(5.0)).Should(BeNumerically("<=", 5.1))
Ω(int8(5)).Should(BeNumerically("<=", 6))
Ω(uint32(5)).Should(BeNumerically("<=", 5))
Ω(float64(5.0)).Should(BeNumerically("<=", 5.0))
Ω(int8(5)).Should(BeNumerically("<=", 5))
Ω(uint32(5)).ShouldNot(BeNumerically("<=", 4))
Ω(float64(5.0)).ShouldNot(BeNumerically("<=", 4.9))
Ω(int8(5)).Should(BeNumerically("<=", 5))
})
Context("when passed ~", func() {
Context("when passed a float", func() {
Context("and there is no precision parameter", func() {
It("should default to 1e-8", func() {
Ω(5.00000001).Should(BeNumerically("~", 5.00000002))
Ω(5.00000001).ShouldNot(BeNumerically("~", 5.0000001))
})
})
Context("and there is a precision parameter", func() {
It("should use the precision parameter", func() {
Ω(5.1).Should(BeNumerically("~", 5.19, 0.1))
Ω(5.1).Should(BeNumerically("~", 5.01, 0.1))
Ω(5.1).ShouldNot(BeNumerically("~", 5.22, 0.1))
Ω(5.1).ShouldNot(BeNumerically("~", 4.98, 0.1))
})
})
})
Context("when passed an int/uint", func() {
Context("and there is no precision parameter", func() {
It("should just do strict equality", func() {
Ω(5).Should(BeNumerically("~", 5))
Ω(5).ShouldNot(BeNumerically("~", 6))
Ω(uint(5)).ShouldNot(BeNumerically("~", 6))
})
})
Context("and there is a precision parameter", func() {
It("should use precision paramter", func() {
Ω(5).Should(BeNumerically("~", 6, 2))
Ω(5).ShouldNot(BeNumerically("~", 8, 2))
Ω(uint(5)).Should(BeNumerically("~", 6, 1))
})
})
})
})
})
Context("when passed a non-number", func() {
It("should error", func() {
success, err := (&BeNumericallyMatcher{Comparator: "==", CompareTo: []interface{}{5}}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "=="}).Match(5)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "~", CompareTo: []interface{}{3.0, "foo"}}).Match(5.0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "==", CompareTo: []interface{}{"bar"}}).Match(5)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "==", CompareTo: []interface{}{"bar"}}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "==", CompareTo: []interface{}{nil}}).Match(0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeNumericallyMatcher{Comparator: "==", CompareTo: []interface{}{0}}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed an unsupported comparator", func() {
It("should error", func() {
success, err := (&BeNumericallyMatcher{Comparator: "!=", CompareTo: []interface{}{5}}).Match(4)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,106 +0,0 @@
package matchers_test
import (
. "github.com/onsi/gomega/matchers"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("BeSent", func() {
Context("when passed a channel and a matching type", func() {
Context("when the channel is ready to receive", func() {
It("should succeed and send the value down the channel", func() {
c := make(chan string)
d := make(chan string)
go func() {
val := <-c
d <- val
}()
time.Sleep(10 * time.Millisecond)
Ω(c).Should(BeSent("foo"))
Eventually(d).Should(Receive(Equal("foo")))
})
It("should succeed (with a buffered channel)", func() {
c := make(chan string, 1)
Ω(c).Should(BeSent("foo"))
Ω(<-c).Should(Equal("foo"))
})
})
Context("when the channel is not ready to receive", func() {
It("should fail and not send down the channel", func() {
c := make(chan string)
Ω(c).ShouldNot(BeSent("foo"))
Consistently(c).ShouldNot(Receive())
})
})
Context("when the channel is eventually ready to receive", func() {
It("should succeed", func() {
c := make(chan string)
d := make(chan string)
go func() {
time.Sleep(30 * time.Millisecond)
val := <-c
d <- val
}()
Eventually(c).Should(BeSent("foo"))
Eventually(d).Should(Receive(Equal("foo")))
})
})
Context("when the channel is closed", func() {
It("should error", func() {
c := make(chan string)
close(c)
success, err := (&BeSentMatcher{Arg: "foo"}).Match(c)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
It("should short-circuit Eventually", func() {
c := make(chan string)
close(c)
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(c, 10.0).Should(BeSent("foo"))
})
Ω(failures).Should(HaveLen(1))
Ω(time.Since(t)).Should(BeNumerically("<", time.Second))
})
})
})
Context("when passed a channel and a non-matching type", func() {
It("should error", func() {
success, err := (&BeSentMatcher{Arg: "foo"}).Match(make(chan int, 1))
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed a receive-only channel", func() {
It("should error", func() {
var c <-chan string
c = make(chan string, 1)
success, err := (&BeSentMatcher{Arg: "foo"}).Match(c)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed a nonchannel", func() {
It("should error", func() {
success, err := (&BeSentMatcher{Arg: "foo"}).Match("bar")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,98 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
"time"
)
var _ = Describe("BeTemporally", func() {
var t0, t1, t2 time.Time
BeforeEach(func() {
t0 = time.Now()
t1 = t0.Add(time.Second)
t2 = t0.Add(-time.Second)
})
Context("When comparing times", func() {
It("should support ==", func() {
Ω(t0).Should(BeTemporally("==", t0))
Ω(t1).ShouldNot(BeTemporally("==", t0))
Ω(t0).ShouldNot(BeTemporally("==", t1))
Ω(t0).ShouldNot(BeTemporally("==", time.Time{}))
})
It("should support >", func() {
Ω(t0).Should(BeTemporally(">", t2))
Ω(t0).ShouldNot(BeTemporally(">", t0))
Ω(t2).ShouldNot(BeTemporally(">", t0))
})
It("should support <", func() {
Ω(t0).Should(BeTemporally("<", t1))
Ω(t0).ShouldNot(BeTemporally("<", t0))
Ω(t1).ShouldNot(BeTemporally("<", t0))
})
It("should support >=", func() {
Ω(t0).Should(BeTemporally(">=", t2))
Ω(t0).Should(BeTemporally(">=", t0))
Ω(t0).ShouldNot(BeTemporally(">=", t1))
})
It("should support <=", func() {
Ω(t0).Should(BeTemporally("<=", t1))
Ω(t0).Should(BeTemporally("<=", t0))
Ω(t0).ShouldNot(BeTemporally("<=", t2))
})
Context("when passed ~", func() {
Context("and there is no precision parameter", func() {
BeforeEach(func() {
t1 = t0.Add(time.Millisecond / 2)
t2 = t0.Add(-2 * time.Millisecond)
})
It("should approximate", func() {
Ω(t0).Should(BeTemporally("~", t0))
Ω(t0).Should(BeTemporally("~", t1))
Ω(t0).ShouldNot(BeTemporally("~", t2))
})
})
Context("and there is a precision parameter", func() {
BeforeEach(func() {
t2 = t0.Add(3 * time.Second)
})
It("should use precision paramter", func() {
d := 2 * time.Second
Ω(t0).Should(BeTemporally("~", t0, d))
Ω(t0).Should(BeTemporally("~", t1, d))
Ω(t0).ShouldNot(BeTemporally("~", t2, d))
})
})
})
})
Context("when passed a non-time", func() {
It("should error", func() {
success, err := (&BeTemporallyMatcher{Comparator: "==", CompareTo: t0}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&BeTemporallyMatcher{Comparator: "=="}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed an unsupported comparator", func() {
It("should error", func() {
success, err := (&BeTemporallyMatcher{Comparator: "!=", CompareTo: t0}).Match(t2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,20 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("BeTrue", func() {
It("should handle true and false correctly", func() {
Ω(true).Should(BeTrue())
Ω(false).ShouldNot(BeTrue())
})
It("should only support booleans", func() {
success, err := (&BeTrueMatcher{}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})

View File

@@ -1,30 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("BeZero", func() {
It("should succeed if the passed in object is the zero value for its type", func() {
Ω(nil).Should(BeZero())
Ω("").Should(BeZero())
Ω(" ").ShouldNot(BeZero())
Ω(0).Should(BeZero())
Ω(1).ShouldNot(BeZero())
Ω(0.0).Should(BeZero())
Ω(0.1).ShouldNot(BeZero())
// Ω([]int{}).Should(BeZero())
Ω([]int{1}).ShouldNot(BeZero())
// Ω(map[string]int{}).Should(BeZero())
Ω(map[string]int{"a": 1}).ShouldNot(BeZero())
Ω(myCustomType{}).Should(BeZero())
Ω(myCustomType{s: "a"}).ShouldNot(BeZero())
})
})

View File

@@ -1,75 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("ConsistOf", func() {
Context("with a slice", func() {
It("should do the right thing", func() {
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf("foo", "bar", "baz"))
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf("foo", "bar", "baz"))
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf("baz", "bar", "foo"))
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("baz", "bar", "foo", "foo"))
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("baz", "foo"))
})
})
Context("with an array", func() {
It("should do the right thing", func() {
Ω([3]string{"foo", "bar", "baz"}).Should(ConsistOf("foo", "bar", "baz"))
Ω([3]string{"foo", "bar", "baz"}).Should(ConsistOf("baz", "bar", "foo"))
Ω([3]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("baz", "bar", "foo", "foo"))
Ω([3]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("baz", "foo"))
})
})
Context("with a map", func() {
It("should apply to the values", func() {
Ω(map[int]string{1: "foo", 2: "bar", 3: "baz"}).Should(ConsistOf("foo", "bar", "baz"))
Ω(map[int]string{1: "foo", 2: "bar", 3: "baz"}).Should(ConsistOf("baz", "bar", "foo"))
Ω(map[int]string{1: "foo", 2: "bar", 3: "baz"}).ShouldNot(ConsistOf("baz", "bar", "foo", "foo"))
Ω(map[int]string{1: "foo", 2: "bar", 3: "baz"}).ShouldNot(ConsistOf("baz", "foo"))
})
})
Context("with anything else", func() {
It("should error", func() {
failures := InterceptGomegaFailures(func() {
Ω("foo").Should(ConsistOf("f", "o", "o"))
})
Ω(failures).Should(HaveLen(1))
})
})
Context("when passed matchers", func() {
It("should pass if the matchers pass", func() {
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf("foo", MatchRegexp("^ba"), "baz"))
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("foo", MatchRegexp("^ba")))
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("foo", MatchRegexp("^ba"), MatchRegexp("foo")))
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf("foo", MatchRegexp("^ba"), MatchRegexp("^ba")))
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf("foo", MatchRegexp("^ba"), MatchRegexp("turducken")))
})
It("should not depend on the order of the matchers", func() {
Ω([][]int{[]int{1, 2}, []int{2}}).Should(ConsistOf(ContainElement(1), ContainElement(2)))
Ω([][]int{[]int{1, 2}, []int{2}}).Should(ConsistOf(ContainElement(2), ContainElement(1)))
})
Context("when a matcher errors", func() {
It("should soldier on", func() {
Ω([]string{"foo", "bar", "baz"}).ShouldNot(ConsistOf(BeFalse(), "foo", "bar"))
Ω([]interface{}{"foo", "bar", false}).Should(ConsistOf(BeFalse(), ContainSubstring("foo"), "bar"))
})
})
})
Context("when passed exactly one argument, and that argument is a slice", func() {
It("should match against the elements of that argument", func() {
Ω([]string{"foo", "bar", "baz"}).Should(ConsistOf([]string{"foo", "bar", "baz"}))
})
})
})

View File

@@ -1,76 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("ContainElement", func() {
Context("when passed a supported type", func() {
Context("and expecting a non-matcher", func() {
It("should do the right thing", func() {
Ω([2]int{1, 2}).Should(ContainElement(2))
Ω([2]int{1, 2}).ShouldNot(ContainElement(3))
Ω([]int{1, 2}).Should(ContainElement(2))
Ω([]int{1, 2}).ShouldNot(ContainElement(3))
Ω(map[string]int{"foo": 1, "bar": 2}).Should(ContainElement(2))
Ω(map[int]int{3: 1, 4: 2}).ShouldNot(ContainElement(3))
arr := make([]myCustomType, 2)
arr[0] = myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}
arr[1] = myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "c"}}
Ω(arr).Should(ContainElement(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}))
Ω(arr).ShouldNot(ContainElement(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"b", "c"}}))
})
})
Context("and expecting a matcher", func() {
It("should pass each element through the matcher", func() {
Ω([]int{1, 2, 3}).Should(ContainElement(BeNumerically(">=", 3)))
Ω([]int{1, 2, 3}).ShouldNot(ContainElement(BeNumerically(">", 3)))
Ω(map[string]int{"foo": 1, "bar": 2}).Should(ContainElement(BeNumerically(">=", 2)))
Ω(map[string]int{"foo": 1, "bar": 2}).ShouldNot(ContainElement(BeNumerically(">", 2)))
})
It("should power through even if the matcher ever fails", func() {
Ω([]interface{}{1, 2, "3", 4}).Should(ContainElement(BeNumerically(">=", 3)))
})
It("should fail if the matcher fails", func() {
actual := []interface{}{1, 2, "3", "4"}
success, err := (&ContainElementMatcher{Element: BeNumerically(">=", 3)}).Match(actual)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})
Context("when passed a correctly typed nil", func() {
It("should operate succesfully on the passed in value", func() {
var nilSlice []int
Ω(nilSlice).ShouldNot(ContainElement(1))
var nilMap map[int]string
Ω(nilMap).ShouldNot(ContainElement("foo"))
})
})
Context("when passed an unsupported type", func() {
It("should error", func() {
success, err := (&ContainElementMatcher{Element: 0}).Match(0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&ContainElementMatcher{Element: 0}).Match("abc")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&ContainElementMatcher{Element: 0}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,36 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("ContainSubstringMatcher", func() {
Context("when actual is a string", func() {
It("should match against the string", func() {
Ω("Marvelous").Should(ContainSubstring("rve"))
Ω("Marvelous").ShouldNot(ContainSubstring("boo"))
})
})
Context("when the matcher is called with multiple arguments", func() {
It("should pass the string and arguments to sprintf", func() {
Ω("Marvelous3").Should(ContainSubstring("velous%d", 3))
})
})
Context("when actual is a stringer", func() {
It("should call the stringer and match agains the returned string", func() {
Ω(&myStringer{a: "Abc3"}).Should(ContainSubstring("bc3"))
})
})
Context("when actual is neither a string nor a stringer", func() {
It("should error", func() {
success, err := (&ContainSubstringMatcher{Substr: "2"}).Match(2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -19,6 +19,12 @@ func (matcher *EqualMatcher) Match(actual interface{}) (success bool, err error)
}
func (matcher *EqualMatcher) FailureMessage(actual interface{}) (message string) {
actualString, actualOK := actual.(string)
expectedString, expectedOK := matcher.Expected.(string)
if actualOK && expectedOK {
return format.MessageWithDiff(actualString, "to equal", expectedString)
}
return format.Message(actual, "to equal", matcher.Expected)
}

View File

@@ -1,44 +0,0 @@
package matchers_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("Equal", func() {
Context("when asserting that nil equals nil", func() {
It("should error", func() {
success, err := (&EqualMatcher{Expected: nil}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("When asserting equality between objects", func() {
It("should do the right thing", func() {
Ω(5).Should(Equal(5))
Ω(5.0).Should(Equal(5.0))
Ω(5).ShouldNot(Equal("5"))
Ω(5).ShouldNot(Equal(5.0))
Ω(5).ShouldNot(Equal(3))
Ω("5").Should(Equal("5"))
Ω([]int{1, 2}).Should(Equal([]int{1, 2}))
Ω([]int{1, 2}).ShouldNot(Equal([]int{2, 1}))
Ω(map[string]string{"a": "b", "c": "d"}).Should(Equal(map[string]string{"a": "b", "c": "d"}))
Ω(map[string]string{"a": "b", "c": "d"}).ShouldNot(Equal(map[string]string{"a": "b", "c": "e"}))
Ω(errors.New("foo")).Should(Equal(errors.New("foo")))
Ω(errors.New("foo")).ShouldNot(Equal(errors.New("bar")))
Ω(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).Should(Equal(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}))
Ω(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Equal(myCustomType{s: "bar", n: 3, f: 2.0, arr: []string{"a", "b"}}))
Ω(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Equal(myCustomType{s: "foo", n: 2, f: 2.0, arr: []string{"a", "b"}}))
Ω(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Equal(myCustomType{s: "foo", n: 3, f: 3.0, arr: []string{"a", "b"}}))
Ω(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b"}}).ShouldNot(Equal(myCustomType{s: "foo", n: 3, f: 2.0, arr: []string{"a", "b", "c"}}))
})
})
})

View File

@@ -1,50 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HaveCap", func() {
Context("when passed a supported type", func() {
It("should do the right thing", func() {
Ω([0]int{}).Should(HaveCap(0))
Ω([2]int{1}).Should(HaveCap(2))
Ω([]int{}).Should(HaveCap(0))
Ω([]int{1, 2, 3, 4, 5}[:2]).Should(HaveCap(5))
Ω(make([]int, 0, 5)).Should(HaveCap(5))
c := make(chan bool, 3)
Ω(c).Should(HaveCap(3))
c <- true
c <- true
Ω(c).Should(HaveCap(3))
Ω(make(chan bool)).Should(HaveCap(0))
})
})
Context("when passed a correctly typed nil", func() {
It("should operate succesfully on the passed in value", func() {
var nilSlice []int
Ω(nilSlice).Should(HaveCap(0))
var nilChan chan int
Ω(nilChan).Should(HaveCap(0))
})
})
Context("when passed an unsupported type", func() {
It("should error", func() {
success, err := (&HaveCapMatcher{Count: 0}).Match(0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&HaveCapMatcher{Count: 0}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,73 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HaveKey", func() {
var (
stringKeys map[string]int
intKeys map[int]string
objKeys map[*myCustomType]string
customA *myCustomType
customB *myCustomType
)
BeforeEach(func() {
stringKeys = map[string]int{"foo": 2, "bar": 3}
intKeys = map[int]string{2: "foo", 3: "bar"}
customA = &myCustomType{s: "a", n: 2, f: 2.3, arr: []string{"ice", "cream"}}
customB = &myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"cake"}}
objKeys = map[*myCustomType]string{customA: "aardvark", customB: "kangaroo"}
})
Context("when passed a map", func() {
It("should do the right thing", func() {
Ω(stringKeys).Should(HaveKey("foo"))
Ω(stringKeys).ShouldNot(HaveKey("baz"))
Ω(intKeys).Should(HaveKey(2))
Ω(intKeys).ShouldNot(HaveKey(4))
Ω(objKeys).Should(HaveKey(customA))
Ω(objKeys).Should(HaveKey(&myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"cake"}}))
Ω(objKeys).ShouldNot(HaveKey(&myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"apple", "pie"}}))
})
})
Context("when passed a correctly typed nil", func() {
It("should operate succesfully on the passed in value", func() {
var nilMap map[int]string
Ω(nilMap).ShouldNot(HaveKey("foo"))
})
})
Context("when the passed in key is actually a matcher", func() {
It("should pass each element through the matcher", func() {
Ω(stringKeys).Should(HaveKey(ContainSubstring("oo")))
Ω(stringKeys).ShouldNot(HaveKey(ContainSubstring("foobar")))
})
It("should fail if the matcher ever fails", func() {
actual := map[int]string{1: "a", 3: "b", 2: "c"}
success, err := (&HaveKeyMatcher{Key: ContainSubstring("ar")}).Match(actual)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed something that is not a map", func() {
It("should error", func() {
success, err := (&HaveKeyMatcher{Key: "foo"}).Match([]string{"foo"})
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&HaveKeyMatcher{Key: "foo"}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,82 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HaveKeyWithValue", func() {
var (
stringKeys map[string]int
intKeys map[int]string
objKeys map[*myCustomType]*myCustomType
customA *myCustomType
customB *myCustomType
)
BeforeEach(func() {
stringKeys = map[string]int{"foo": 2, "bar": 3}
intKeys = map[int]string{2: "foo", 3: "bar"}
customA = &myCustomType{s: "a", n: 2, f: 2.3, arr: []string{"ice", "cream"}}
customB = &myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"cake"}}
objKeys = map[*myCustomType]*myCustomType{customA: customA, customB: customA}
})
Context("when passed a map", func() {
It("should do the right thing", func() {
Ω(stringKeys).Should(HaveKeyWithValue("foo", 2))
Ω(stringKeys).ShouldNot(HaveKeyWithValue("foo", 1))
Ω(stringKeys).ShouldNot(HaveKeyWithValue("baz", 2))
Ω(stringKeys).ShouldNot(HaveKeyWithValue("baz", 1))
Ω(intKeys).Should(HaveKeyWithValue(2, "foo"))
Ω(intKeys).ShouldNot(HaveKeyWithValue(4, "foo"))
Ω(intKeys).ShouldNot(HaveKeyWithValue(2, "baz"))
Ω(objKeys).Should(HaveKeyWithValue(customA, customA))
Ω(objKeys).Should(HaveKeyWithValue(&myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"cake"}}, &myCustomType{s: "a", n: 2, f: 2.3, arr: []string{"ice", "cream"}}))
Ω(objKeys).ShouldNot(HaveKeyWithValue(&myCustomType{s: "b", n: 4, f: 3.1, arr: []string{"apple", "pie"}}, customA))
})
})
Context("when passed a correctly typed nil", func() {
It("should operate succesfully on the passed in value", func() {
var nilMap map[int]string
Ω(nilMap).ShouldNot(HaveKeyWithValue("foo", "bar"))
})
})
Context("when the passed in key or value is actually a matcher", func() {
It("should pass each element through the matcher", func() {
Ω(stringKeys).Should(HaveKeyWithValue(ContainSubstring("oo"), 2))
Ω(intKeys).Should(HaveKeyWithValue(2, ContainSubstring("oo")))
Ω(stringKeys).ShouldNot(HaveKeyWithValue(ContainSubstring("foobar"), 2))
})
It("should fail if the matcher ever fails", func() {
actual := map[int]string{1: "a", 3: "b", 2: "c"}
success, err := (&HaveKeyWithValueMatcher{Key: ContainSubstring("ar"), Value: 2}).Match(actual)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
otherActual := map[string]int{"a": 1, "b": 2, "c": 3}
success, err = (&HaveKeyWithValueMatcher{Key: "a", Value: ContainSubstring("1")}).Match(otherActual)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed something that is not a map", func() {
It("should error", func() {
success, err := (&HaveKeyWithValueMatcher{Key: "foo", Value: "bar"}).Match([]string{"foo"})
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&HaveKeyWithValueMatcher{Key: "foo", Value: "bar"}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,53 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HaveLen", func() {
Context("when passed a supported type", func() {
It("should do the right thing", func() {
Ω("").Should(HaveLen(0))
Ω("AA").Should(HaveLen(2))
Ω([0]int{}).Should(HaveLen(0))
Ω([2]int{1, 2}).Should(HaveLen(2))
Ω([]int{}).Should(HaveLen(0))
Ω([]int{1, 2, 3}).Should(HaveLen(3))
Ω(map[string]int{}).Should(HaveLen(0))
Ω(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4}).Should(HaveLen(4))
c := make(chan bool, 3)
Ω(c).Should(HaveLen(0))
c <- true
c <- true
Ω(c).Should(HaveLen(2))
})
})
Context("when passed a correctly typed nil", func() {
It("should operate succesfully on the passed in value", func() {
var nilSlice []int
Ω(nilSlice).Should(HaveLen(0))
var nilMap map[int]string
Ω(nilMap).Should(HaveLen(0))
})
})
Context("when passed an unsupported type", func() {
It("should error", func() {
success, err := (&HaveLenMatcher{Count: 0}).Match(0)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&HaveLenMatcher{Count: 0}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,58 +0,0 @@
package matchers_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
type CustomErr struct {
msg string
}
func (e *CustomErr) Error() string {
return e.msg
}
var _ = Describe("HaveOccurred", func() {
It("should succeed if matching an error", func() {
Ω(errors.New("Foo")).Should(HaveOccurred())
})
It("should not succeed with nil", func() {
Ω(nil).ShouldNot(HaveOccurred())
})
It("should only support errors and nil", func() {
success, err := (&HaveOccurredMatcher{}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&HaveOccurredMatcher{}).Match("")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
It("doesn't support non-error type", func() {
success, err := (&HaveOccurredMatcher{}).Match(AnyType{})
Ω(success).Should(BeFalse())
Ω(err).Should(MatchError("Expected an error-type. Got:\n <matchers_test.AnyType>: {}"))
})
It("doesn't support non-error pointer type", func() {
success, err := (&HaveOccurredMatcher{}).Match(&AnyType{})
Ω(success).Should(BeFalse())
Ω(err).Should(MatchError(MatchRegexp(`Expected an error-type. Got:\n <*matchers_test.AnyType | 0x[[:xdigit:]]+>: {}`)))
})
It("should succeed with pointer types that conform to error interface", func() {
err := &CustomErr{"ohai"}
Ω(err).Should(HaveOccurred())
})
It("should not succeed with nil pointers to types that conform to error interface", func() {
var err *CustomErr = nil
Ω(err).ShouldNot(HaveOccurred())
})
})

View File

@@ -1,36 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HavePrefixMatcher", func() {
Context("when actual is a string", func() {
It("should match a string prefix", func() {
Ω("Ab").Should(HavePrefix("A"))
Ω("A").ShouldNot(HavePrefix("Ab"))
})
})
Context("when the matcher is called with multiple arguments", func() {
It("should pass the string and arguments to sprintf", func() {
Ω("C3PO").Should(HavePrefix("C%dP", 3))
})
})
Context("when actual is a stringer", func() {
It("should call the stringer and match against the returned string", func() {
Ω(&myStringer{a: "Ab"}).Should(HavePrefix("A"))
})
})
Context("when actual is neither a string nor a stringer", func() {
It("should error", func() {
success, err := (&HavePrefixMatcher{Prefix: "2"}).Match(2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,36 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("HaveSuffixMatcher", func() {
Context("when actual is a string", func() {
It("should match a string suffix", func() {
Ω("Ab").Should(HaveSuffix("b"))
Ω("A").ShouldNot(HaveSuffix("Ab"))
})
})
Context("when the matcher is called with multiple arguments", func() {
It("should pass the string and arguments to sprintf", func() {
Ω("C3PO").Should(HaveSuffix("%dPO", 3))
})
})
Context("when actual is a stringer", func() {
It("should call the stringer and match against the returned string", func() {
Ω(&myStringer{a: "Ab"}).Should(HaveSuffix("b"))
})
})
Context("when actual is neither a string nor a stringer", func() {
It("should error", func() {
success, err := (&HaveSuffixMatcher{Suffix: "2"}).Match(2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,93 +0,0 @@
package matchers_test
import (
"errors"
"fmt"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
type CustomError struct {
}
func (c CustomError) Error() string {
return "an error"
}
var _ = Describe("MatchErrorMatcher", func() {
Context("When asserting against an error", func() {
It("should succeed when matching with an error", func() {
err := errors.New("an error")
fmtErr := fmt.Errorf("an error")
customErr := CustomError{}
Ω(err).Should(MatchError(errors.New("an error")))
Ω(err).ShouldNot(MatchError(errors.New("another error")))
Ω(fmtErr).Should(MatchError(errors.New("an error")))
Ω(customErr).Should(MatchError(CustomError{}))
})
It("should succeed when matching with a string", func() {
err := errors.New("an error")
fmtErr := fmt.Errorf("an error")
customErr := CustomError{}
Ω(err).Should(MatchError("an error"))
Ω(err).ShouldNot(MatchError("another error"))
Ω(fmtErr).Should(MatchError("an error"))
Ω(customErr).Should(MatchError("an error"))
})
Context("when passed a matcher", func() {
It("should pass if the matcher passes against the error string", func() {
err := errors.New("error 123 abc")
Ω(err).Should(MatchError(MatchRegexp(`\d{3}`)))
})
It("should fail if the matcher fails against the error string", func() {
err := errors.New("no digits")
Ω(err).ShouldNot(MatchError(MatchRegexp(`\d`)))
})
})
It("should fail when passed anything else", func() {
actualErr := errors.New("an error")
_, err := (&MatchErrorMatcher{
Expected: []byte("an error"),
}).Match(actualErr)
Ω(err).Should(HaveOccurred())
_, err = (&MatchErrorMatcher{
Expected: 3,
}).Match(actualErr)
Ω(err).Should(HaveOccurred())
})
})
Context("when passed nil", func() {
It("should fail", func() {
_, err := (&MatchErrorMatcher{
Expected: "an error",
}).Match(nil)
Ω(err).Should(HaveOccurred())
})
})
Context("when passed a non-error", func() {
It("should fail", func() {
_, err := (&MatchErrorMatcher{
Expected: "an error",
}).Match("an error")
Ω(err).Should(HaveOccurred())
_, err = (&MatchErrorMatcher{
Expected: "an error",
}).Match(3)
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -40,11 +40,13 @@ func (matcher *MatchJSONMatcher) NegatedFailureMessage(actual interface{}) (mess
}
func (matcher *MatchJSONMatcher) prettyPrint(actual interface{}) (actualFormatted, expectedFormatted string, err error) {
actualString, aok := toString(actual)
expectedString, eok := toString(matcher.JSONToMatch)
if !(aok && eok) {
return "", "", fmt.Errorf("MatchJSONMatcher matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1))
actualString, ok := toString(actual)
if !ok {
return "", "", fmt.Errorf("MatchJSONMatcher matcher requires a string, stringer, or []byte. Got actual:\n%s", format.Object(actual, 1))
}
expectedString, ok := toString(matcher.JSONToMatch)
if !ok {
return "", "", fmt.Errorf("MatchJSONMatcher matcher requires a string, stringer, or []byte. Got expected:\n%s", format.Object(matcher.JSONToMatch, 1))
}
abuf := new(bytes.Buffer)

View File

@@ -1,65 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("MatchJSONMatcher", func() {
Context("When passed stringifiables", func() {
It("should succeed if the JSON matches", func() {
Ω("{}").Should(MatchJSON("{}"))
Ω(`{"a":1}`).Should(MatchJSON(`{"a":1}`))
Ω(`{
"a":1
}`).Should(MatchJSON(`{"a":1}`))
Ω(`{"a":1, "b":2}`).Should(MatchJSON(`{"b":2, "a":1}`))
Ω(`{"a":1}`).ShouldNot(MatchJSON(`{"b":2, "a":1}`))
})
It("should work with byte arrays", func() {
Ω([]byte("{}")).Should(MatchJSON([]byte("{}")))
Ω("{}").Should(MatchJSON([]byte("{}")))
Ω([]byte("{}")).Should(MatchJSON("{}"))
})
})
Context("when the expected is not valid JSON", func() {
It("should error and explain why", func() {
success, err := (&MatchJSONMatcher{JSONToMatch: `{}`}).Match(`oops`)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
Ω(err.Error()).Should(ContainSubstring("Actual 'oops' should be valid JSON"))
})
})
Context("when the actual is not valid JSON", func() {
It("should error and explain why", func() {
success, err := (&MatchJSONMatcher{JSONToMatch: `oops`}).Match(`{}`)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
Ω(err.Error()).Should(ContainSubstring("Expected 'oops' should be valid JSON"))
})
})
Context("when either side is neither a string nor a stringer", func() {
It("should error", func() {
success, err := (&MatchJSONMatcher{JSONToMatch: "{}"}).Match(2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&MatchJSONMatcher{JSONToMatch: 2}).Match("{}")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&MatchJSONMatcher{JSONToMatch: nil}).Match("{}")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&MatchJSONMatcher{JSONToMatch: 2}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -1,44 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("MatchRegexp", func() {
Context("when actual is a string", func() {
It("should match against the string", func() {
Ω(" a2!bla").Should(MatchRegexp(`\d!`))
Ω(" a2!bla").ShouldNot(MatchRegexp(`[A-Z]`))
})
})
Context("when actual is a stringer", func() {
It("should call the stringer and match agains the returned string", func() {
Ω(&myStringer{a: "Abc3"}).Should(MatchRegexp(`[A-Z][a-z]+\d`))
})
})
Context("when the matcher is called with multiple arguments", func() {
It("should pass the string and arguments to sprintf", func() {
Ω(" a23!bla").Should(MatchRegexp(`\d%d!`, 3))
})
})
Context("when actual is neither a string nor a stringer", func() {
It("should error", func() {
success, err := (&MatchRegexpMatcher{Regexp: `\d`}).Match(2)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when the passed in regexp fails to compile", func() {
It("should error", func() {
success, err := (&MatchRegexpMatcher{Regexp: "("}).Match("Foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})

View File

@@ -0,0 +1,74 @@
package matchers
import (
"fmt"
"reflect"
"strings"
"github.com/onsi/gomega/format"
"gopkg.in/yaml.v2"
)
type MatchYAMLMatcher struct {
YAMLToMatch interface{}
}
func (matcher *MatchYAMLMatcher) Match(actual interface{}) (success bool, err error) {
actualString, expectedString, err := matcher.toStrings(actual)
if err != nil {
return false, err
}
var aval interface{}
var eval interface{}
if err := yaml.Unmarshal([]byte(actualString), &aval); err != nil {
return false, fmt.Errorf("Actual '%s' should be valid YAML, but it is not.\nUnderlying error:%s", actualString, err)
}
if err := yaml.Unmarshal([]byte(expectedString), &eval); err != nil {
return false, fmt.Errorf("Expected '%s' should be valid YAML, but it is not.\nUnderlying error:%s", expectedString, err)
}
return reflect.DeepEqual(aval, eval), nil
}
func (matcher *MatchYAMLMatcher) FailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.toNormalisedStrings(actual)
return format.Message(actualString, "to match YAML of", expectedString)
}
func (matcher *MatchYAMLMatcher) NegatedFailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.toNormalisedStrings(actual)
return format.Message(actualString, "not to match YAML of", expectedString)
}
func (matcher *MatchYAMLMatcher) toNormalisedStrings(actual interface{}) (actualFormatted, expectedFormatted string, err error) {
actualString, expectedString, err := matcher.toStrings(actual)
return normalise(actualString), normalise(expectedString), err
}
func normalise(input string) string {
var val interface{}
err := yaml.Unmarshal([]byte(input), &val)
if err != nil {
panic(err) // guarded by Match
}
output, err := yaml.Marshal(val)
if err != nil {
panic(err) // guarded by Unmarshal
}
return strings.TrimSpace(string(output))
}
func (matcher *MatchYAMLMatcher) toStrings(actual interface{}) (actualFormatted, expectedFormatted string, err error) {
actualString, ok := toString(actual)
if !ok {
return "", "", fmt.Errorf("MatchYAMLMatcher matcher requires a string, stringer, or []byte. Got actual:\n%s", format.Object(actual, 1))
}
expectedString, ok := toString(matcher.YAMLToMatch)
if !ok {
return "", "", fmt.Errorf("MatchYAMLMatcher matcher requires a string, stringer, or []byte. Got expected:\n%s", format.Object(matcher.YAMLToMatch, 1))
}
return actualString, expectedString, nil
}

View File

@@ -1,30 +0,0 @@
package matchers_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
type myStringer struct {
a string
}
func (s *myStringer) String() string {
return s.a
}
type StringAlias string
type myCustomType struct {
s string
n int
f float32
arr []string
}
func Test(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Gomega Matchers")
}

View File

@@ -1,57 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("NotMatcher", func() {
Context("basic examples", func() {
It("works", func() {
Expect(input).To(Not(false1))
Expect(input).To(Not(Not(true2)))
Expect(input).ToNot(Not(true3))
Expect(input).ToNot(Not(Not(false1)))
Expect(input).To(Not(Not(Not(false2))))
})
})
Context("De Morgan's laws", func() {
It("~(A && B) == ~A || ~B", func() {
Expect(input).To(Not(And(false1, false2)))
Expect(input).To(Or(Not(false1), Not(false2)))
})
It("~(A || B) == ~A && ~B", func() {
Expect(input).To(Not(Or(false1, false2)))
Expect(input).To(And(Not(false1), Not(false2)))
})
})
Context("failure messages are opposite of original matchers' failure messages", func() {
Context("when match fails", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(Not(HaveLen(2)), input, "not to have length 2")
})
})
Context("when match succeeds, but expected it to fail", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(Not(Not(HaveLen(3))), input, "to have length 3")
})
})
})
Context("MatchMayChangeInTheFuture()", func() {
It("Propagates value from wrapped matcher", func() {
m := Not(Or()) // an empty Or() always returns false, and indicates it cannot change
Expect(m.Match("anything")).To(BeTrue())
Expect(m.(*NotMatcher).MatchMayChangeInTheFuture("anything")).To(BeFalse())
})
It("Defaults to true", func() {
m := Not(Equal(1)) // Equal does not have this method
Expect(m.Match(2)).To(BeTrue())
Expect(m.(*NotMatcher).MatchMayChangeInTheFuture(2)).To(BeTrue()) // defaults to true
})
})
})

View File

@@ -1,85 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("OrMatcher", func() {
It("works with positive cases", func() {
Expect(input).To(Or(true1))
Expect(input).To(Or(true1, true2))
Expect(input).To(Or(true1, false1))
Expect(input).To(Or(false1, true2))
Expect(input).To(Or(true1, true2, true3))
Expect(input).To(Or(true1, true2, false3))
Expect(input).To(Or(true1, false2, true3))
Expect(input).To(Or(false1, true2, true3))
Expect(input).To(Or(true1, false2, false3))
Expect(input).To(Or(false1, false2, true3))
// use alias
Expect(input).To(SatisfyAny(false1, false2, true3))
})
It("works with negative cases", func() {
Expect(input).ToNot(Or())
Expect(input).ToNot(Or(false1))
Expect(input).ToNot(Or(false1, false2))
Expect(input).ToNot(Or(false1, false2, false3))
})
Context("failure messages", func() {
Context("when match fails", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(Or(false1, false2), input,
"To satisfy at least one of these matchers: [%!s(*matchers.HaveLenMatcher=&{1}) %!s(*matchers.EqualMatcher=&{hip})]")
})
})
Context("when match succeeds, but expected it to fail", func() {
It("gives a descriptive message", func() {
verifyFailureMessage(Not(Or(true1, true2)), input, `not to have length 2`)
})
})
})
Context("MatchMayChangeInTheFuture", func() {
Context("Match returned false", func() {
It("returns true if any of the matchers could change", func() {
// 3 matchers, all return false, and all could change
m := Or(BeNil(), Equal("hip"), HaveLen(1))
Expect(m.Match("hi")).To(BeFalse())
Expect(m.(*OrMatcher).MatchMayChangeInTheFuture("hi")).To(BeTrue()) // all 3 of these matchers default to 'true'
})
It("returns false if none of the matchers could change", func() {
// empty Or() has the property of never matching, and never can change since there are no sub-matchers that could change
m := Or()
Expect(m.Match("anything")).To(BeFalse())
Expect(m.(*OrMatcher).MatchMayChangeInTheFuture("anything")).To(BeFalse())
// Or() with 3 sub-matchers that return false, and can't change
m = Or(Or(), Or(), Or())
Expect(m.Match("hi")).To(BeFalse())
Expect(m.(*OrMatcher).MatchMayChangeInTheFuture("hi")).To(BeFalse()) // the 3 empty Or()'s won't change
})
})
Context("Match returned true", func() {
Context("returns value of the successful matcher", func() {
It("false if successful matcher not going to change", func() {
// 3 matchers: 1st returns false, 2nd returns true and is not going to change, 3rd is never called
m := Or(BeNil(), And(), Equal(1))
Expect(m.Match("hi")).To(BeTrue())
Expect(m.(*OrMatcher).MatchMayChangeInTheFuture("hi")).To(BeFalse())
})
It("true if successful matcher indicates it might change", func() {
// 3 matchers: 1st returns false, 2nd returns true and "might" change, 3rd is never called
m := Or(Not(BeNil()), Equal("hi"), Equal(1))
Expect(m.Match("hi")).To(BeTrue())
Expect(m.(*OrMatcher).MatchMayChangeInTheFuture("hi")).To(BeTrue()) // Equal("hi") indicates it might change
})
})
})
})
})

View File

@@ -2,11 +2,14 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type PanicMatcher struct{}
type PanicMatcher struct {
object interface{}
}
func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error) {
if actual == nil {
@@ -24,6 +27,7 @@ func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error)
success = false
defer func() {
if e := recover(); e != nil {
matcher.object = e
success = true
}
}()
@@ -38,5 +42,5 @@ func (matcher *PanicMatcher) FailureMessage(actual interface{}) (message string)
}
func (matcher *PanicMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to panic")
return format.Message(actual, fmt.Sprintf("not to panic, but panicked with\n%s", format.Object(matcher.object, 1)))
}

View File

@@ -1,36 +0,0 @@
package matchers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("Panic", func() {
Context("when passed something that's not a function that takes zero arguments and returns nothing", func() {
It("should error", func() {
success, err := (&PanicMatcher{}).Match("foo")
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&PanicMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&PanicMatcher{}).Match(func(foo string) {})
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&PanicMatcher{}).Match(func() string { return "bar" })
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when passed a function of the correct type", func() {
It("should call the function and pass if the function panics", func() {
Ω(func() { panic("ack!") }).Should(Panic())
Ω(func() {}).ShouldNot(Panic())
})
})
})

View File

@@ -1,280 +0,0 @@
package matchers_test
import (
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
type kungFuActor interface {
DrunkenMaster() bool
}
type jackie struct {
name string
}
func (j *jackie) DrunkenMaster() bool {
return true
}
var _ = Describe("ReceiveMatcher", func() {
Context("with no argument", func() {
Context("for a buffered channel", func() {
It("should succeed", func() {
channel := make(chan bool, 1)
Ω(channel).ShouldNot(Receive())
channel <- true
Ω(channel).Should(Receive())
})
})
Context("for an unbuffered channel", func() {
It("should succeed (eventually)", func() {
channel := make(chan bool)
Ω(channel).ShouldNot(Receive())
go func() {
time.Sleep(10 * time.Millisecond)
channel <- true
}()
Eventually(channel).Should(Receive())
})
})
})
Context("with a pointer argument", func() {
Context("of the correct type", func() {
It("should write the value received on the channel to the pointer", func() {
channel := make(chan int, 1)
var value int
Ω(channel).ShouldNot(Receive(&value))
Ω(value).Should(BeZero())
channel <- 17
Ω(channel).Should(Receive(&value))
Ω(value).Should(Equal(17))
})
})
Context("to various types of objects", func() {
It("should work", func() {
//channels of strings
stringChan := make(chan string, 1)
stringChan <- "foo"
var s string
Ω(stringChan).Should(Receive(&s))
Ω(s).Should(Equal("foo"))
//channels of slices
sliceChan := make(chan []bool, 1)
sliceChan <- []bool{true, true, false}
var sl []bool
Ω(sliceChan).Should(Receive(&sl))
Ω(sl).Should(Equal([]bool{true, true, false}))
//channels of channels
chanChan := make(chan chan bool, 1)
c := make(chan bool)
chanChan <- c
var receivedC chan bool
Ω(chanChan).Should(Receive(&receivedC))
Ω(receivedC).Should(Equal(c))
//channels of interfaces
jackieChan := make(chan kungFuActor, 1)
aJackie := &jackie{name: "Jackie Chan"}
jackieChan <- aJackie
var theJackie kungFuActor
Ω(jackieChan).Should(Receive(&theJackie))
Ω(theJackie).Should(Equal(aJackie))
})
})
Context("of the wrong type", func() {
It("should error", func() {
channel := make(chan int)
var incorrectType bool
success, err := (&ReceiveMatcher{Arg: &incorrectType}).Match(channel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
var notAPointer int
success, err = (&ReceiveMatcher{Arg: notAPointer}).Match(channel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
})
Context("with a matcher", func() {
It("should defer to the underlying matcher", func() {
intChannel := make(chan int, 1)
intChannel <- 3
Ω(intChannel).Should(Receive(Equal(3)))
intChannel <- 2
Ω(intChannel).ShouldNot(Receive(Equal(3)))
stringChannel := make(chan []string, 1)
stringChannel <- []string{"foo", "bar", "baz"}
Ω(stringChannel).Should(Receive(ContainElement(ContainSubstring("fo"))))
stringChannel <- []string{"foo", "bar", "baz"}
Ω(stringChannel).ShouldNot(Receive(ContainElement(ContainSubstring("archipelago"))))
})
It("should defer to the underlying matcher for the message", func() {
matcher := Receive(Equal(3))
channel := make(chan int, 1)
channel <- 2
matcher.Match(channel)
Ω(matcher.FailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 2\s+to equal\s+<int>: 3`))
channel <- 3
matcher.Match(channel)
Ω(matcher.NegatedFailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 3\s+not to equal\s+<int>: 3`))
})
It("should work just fine with Eventually", func() {
stringChannel := make(chan string)
go func() {
time.Sleep(5 * time.Millisecond)
stringChannel <- "A"
time.Sleep(5 * time.Millisecond)
stringChannel <- "B"
}()
Eventually(stringChannel).Should(Receive(Equal("B")))
})
Context("if the matcher errors", func() {
It("should error", func() {
channel := make(chan int, 1)
channel <- 3
success, err := (&ReceiveMatcher{Arg: ContainSubstring("three")}).Match(channel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("if nothing is received", func() {
It("should fail", func() {
channel := make(chan int, 1)
success, err := (&ReceiveMatcher{Arg: Equal(1)}).Match(channel)
Ω(success).Should(BeFalse())
Ω(err).ShouldNot(HaveOccurred())
})
})
})
Context("When actual is a *closed* channel", func() {
Context("for a buffered channel", func() {
It("should work until it hits the end of the buffer", func() {
channel := make(chan bool, 1)
channel <- true
close(channel)
Ω(channel).Should(Receive())
Ω(channel).ShouldNot(Receive())
})
})
Context("for an unbuffered channel", func() {
It("should always fail", func() {
channel := make(chan bool)
close(channel)
Ω(channel).ShouldNot(Receive())
})
})
})
Context("When actual is a send-only channel", func() {
It("should error", func() {
channel := make(chan bool)
var writerChannel chan<- bool
writerChannel = channel
success, err := (&ReceiveMatcher{}).Match(writerChannel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Context("when acutal is a non-channel", func() {
It("should error", func() {
var nilChannel chan bool
success, err := (&ReceiveMatcher{}).Match(nilChannel)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&ReceiveMatcher{}).Match(nil)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
success, err = (&ReceiveMatcher{}).Match(3)
Ω(success).Should(BeFalse())
Ω(err).Should(HaveOccurred())
})
})
Describe("when used with eventually and a custom matcher", func() {
It("should return the matcher's error when a failing value is received on the channel, instead of the must receive something failure", func() {
failures := InterceptGomegaFailures(func() {
c := make(chan string, 0)
Eventually(c, 0.01).Should(Receive(Equal("hello")))
})
Ω(failures[0]).Should(ContainSubstring("When passed a matcher, ReceiveMatcher's channel *must* receive something."))
failures = InterceptGomegaFailures(func() {
c := make(chan string, 1)
c <- "hi"
Eventually(c, 0.01).Should(Receive(Equal("hello")))
})
Ω(failures[0]).Should(ContainSubstring("<string>: hello"))
})
})
Describe("Bailing early", func() {
It("should bail early when passed a closed channel", func() {
c := make(chan bool)
close(c)
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(c).Should(Receive())
})
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
It("should bail early when passed a non-channel", func() {
t := time.Now()
failures := InterceptGomegaFailures(func() {
Eventually(3).Should(Receive())
})
Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
Ω(failures).Should(HaveLen(1))
})
})
})

View File

@@ -1,62 +0,0 @@
package matchers_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
func Erroring() error {
return errors.New("bam")
}
func NotErroring() error {
return nil
}
type AnyType struct{}
func Invalid() *AnyType {
return nil
}
var _ = Describe("Succeed", func() {
It("should succeed if the function succeeds", func() {
Ω(NotErroring()).Should(Succeed())
})
It("should succeed (in the negated) if the function errored", func() {
Ω(Erroring()).ShouldNot(Succeed())
})
It("should not if passed a non-error", func() {
success, err := (&SucceedMatcher{}).Match(Invalid())
Ω(success).Should(BeFalse())
Ω(err).Should(MatchError("Expected an error-type. Got:\n <*matchers_test.AnyType | 0x0>: nil"))
})
It("doesn't support non-error type", func() {
success, err := (&SucceedMatcher{}).Match(AnyType{})
Ω(success).Should(BeFalse())
Ω(err).Should(MatchError("Expected an error-type. Got:\n <matchers_test.AnyType>: {}"))
})
It("doesn't support non-error pointer type", func() {
success, err := (&SucceedMatcher{}).Match(&AnyType{})
Ω(success).Should(BeFalse())
Ω(err).Should(MatchError(MatchRegexp(`Expected an error-type. Got:\n <*matchers_test.AnyType | 0x[[:xdigit:]]+>: {}`)))
})
It("should not succeed with pointer types that conform to error interface", func() {
err := &CustomErr{"ohai"}
Ω(err).ShouldNot(Succeed())
})
It("should succeed with nil pointers to types that conform to error interface", func() {
var err *CustomErr = nil
Ω(err).Should(Succeed())
})
})

View File

@@ -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.

View File

@@ -1,102 +0,0 @@
package matchers_test
import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/matchers"
)
var _ = Describe("WithTransformMatcher", func() {
var plus1 = func(i int) int { return i + 1 }
Context("Panic if transform function invalid", func() {
panicsWithTransformer := func(transform interface{}) {
ExpectWithOffset(1, func() { WithTransform(transform, nil) }).To(Panic())
}
It("nil", func() {
panicsWithTransformer(nil)
})
Context("Invalid number of args, but correct return value count", func() {
It("zero", func() {
panicsWithTransformer(func() int { return 5 })
})
It("two", func() {
panicsWithTransformer(func(i, j int) int { return 5 })
})
})
Context("Invalid number of return values, but correct number of arguments", func() {
It("zero", func() {
panicsWithTransformer(func(i int) {})
})
It("two", func() {
panicsWithTransformer(func(i int) (int, int) { return 5, 6 })
})
})
})
It("works with positive cases", func() {
Expect(1).To(WithTransform(plus1, Equal(2)))
Expect(1).To(WithTransform(plus1, WithTransform(plus1, Equal(3))))
Expect(1).To(WithTransform(plus1, And(Equal(2), BeNumerically(">", 1))))
// transform expects custom type
type S struct {
A int
B string
}
transformer := func(s S) string { return s.B }
Expect(S{1, "hi"}).To(WithTransform(transformer, Equal("hi")))
// transform expects interface
errString := func(e error) string { return e.Error() }
Expect(errors.New("abc")).To(WithTransform(errString, Equal("abc")))
})
It("works with negative cases", func() {
Expect(1).ToNot(WithTransform(plus1, Equal(3)))
Expect(1).ToNot(WithTransform(plus1, WithTransform(plus1, Equal(2))))
})
Context("failure messages", func() {
Context("when match fails", func() {
It("gives a descriptive message", func() {
m := WithTransform(plus1, Equal(3))
Expect(m.Match(1)).To(BeFalse())
Expect(m.FailureMessage(1)).To(Equal("Expected\n <int>: 2\nto equal\n <int>: 3"))
})
})
Context("when match succeeds, but expected it to fail", func() {
It("gives a descriptive message", func() {
m := Not(WithTransform(plus1, Equal(3)))
Expect(m.Match(2)).To(BeFalse())
Expect(m.FailureMessage(2)).To(Equal("Expected\n <int>: 3\nnot to equal\n <int>: 3"))
})
})
Context("actual value is incompatible with transform function's argument type", func() {
It("gracefully fails if transform cannot be performed", func() {
m := WithTransform(plus1, Equal(3))
result, err := m.Match("hi") // give it a string but transform expects int; doesn't panic
Expect(result).To(BeFalse())
Expect(err).To(MatchError("Transform function expects 'int' but we have 'string'"))
})
})
})
Context("MatchMayChangeInTheFuture()", func() {
It("Propagates value from wrapped matcher on the transformed value", func() {
m := WithTransform(plus1, Or()) // empty Or() always returns false, and indicates it cannot change
Expect(m.Match(1)).To(BeFalse())
Expect(m.(*WithTransformMatcher).MatchMayChangeInTheFuture(1)).To(BeFalse()) // empty Or() indicates cannot change
})
It("Defaults to true", func() {
m := WithTransform(plus1, Equal(2)) // Equal does not have this method
Expect(m.Match(1)).To(BeTrue())
Expect(m.(*WithTransformMatcher).MatchMayChangeInTheFuture(1)).To(BeTrue()) // defaults to true
})
})
})