vendor: bump ginkgo, gover

Signed-off-by: Casey Callendrello <cdc@redhat.com>
This commit is contained in:
Casey Callendrello
2020-12-08 14:51:48 +01:00
parent 509d645ee9
commit b47d178ae0
408 changed files with 194680 additions and 1961 deletions

View File

@@ -57,8 +57,7 @@ func (m *AndMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
}
}
return false // none of were going to change
} else {
// one of the matchers failed.. it must be able to change in order to affect the result
return oraclematcher.MatchMayChangeInTheFuture(m.firstFailedMatcher, actual)
}
// one of the matchers failed.. it must be able to change in order to affect the result
return oraclematcher.MatchMayChangeInTheFuture(m.firstFailedMatcher, actual)
}

View File

@@ -1,3 +1,5 @@
// untested sections: 2
package matchers
import (
@@ -12,8 +14,12 @@ type AssignableToTypeOfMatcher struct {
}
func (matcher *AssignableToTypeOfMatcher) Match(actual interface{}) (success bool, err error) {
if actual == nil || matcher.Expected == nil {
if actual == nil && matcher.Expected == nil {
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
} else if matcher.Expected == nil {
return false, fmt.Errorf("Refusing to compare type to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
} else if actual == nil {
return false, nil
}
actualType := reflect.TypeOf(actual)

View File

@@ -0,0 +1,14 @@
package matchers
import (
"encoding/xml"
"strings"
)
type attributesSlice []xml.Attr
func (attrs attributesSlice) Len() int { return len(attrs) }
func (attrs attributesSlice) Less(i, j int) bool {
return strings.Compare(attrs[i].Name.Local, attrs[j].Name.Local) == -1
}
func (attrs attributesSlice) Swap(i, j int) { attrs[i], attrs[j] = attrs[j], attrs[i] }

View File

@@ -1,3 +1,5 @@
// untested sections: 5
package matchers
import (

View File

@@ -1,3 +1,5 @@
// untested sections: 5
package matchers
import (

View File

@@ -1,3 +1,5 @@
// untested sections: 3
package matchers
import (

View File

@@ -1,9 +1,12 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type BeClosedMatcher struct {
@@ -22,8 +25,8 @@ func (matcher *BeClosedMatcher) Match(actual interface{}) (success bool, err err
}
winnerIndex, _, open := reflect.Select([]reflect.SelectCase{
reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue},
reflect.SelectCase{Dir: reflect.SelectDefault},
{Dir: reflect.SelectRecv, Chan: channelValue},
{Dir: reflect.SelectDefault},
})
var closed bool

View File

@@ -0,0 +1,57 @@
// untested sections: 1
package matchers
import (
"fmt"
"reflect"
"github.com/onsi/gomega/format"
)
type BeElementOfMatcher struct {
Elements []interface{}
}
func (matcher *BeElementOfMatcher) Match(actual interface{}) (success bool, err error) {
if reflect.TypeOf(actual) == nil {
return false, fmt.Errorf("BeElement matcher expects actual to be typed")
}
length := len(matcher.Elements)
valueAt := func(i int) interface{} {
return matcher.Elements[i]
}
// Special handling of a single element of type Array or Slice
if length == 1 && isArrayOrSlice(valueAt(0)) {
element := valueAt(0)
value := reflect.ValueOf(element)
length = value.Len()
valueAt = func(i int) interface{} {
return value.Index(i).Interface()
}
}
var lastError error
for i := 0; i < length; i++ {
matcher := &EqualMatcher{Expected: valueAt(i)}
success, err := matcher.Match(actual)
if err != nil {
lastError = err
continue
}
if success {
return true, nil
}
}
return false, lastError
}
func (matcher *BeElementOfMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, "to be an element of", matcher.Elements)
}
func (matcher *BeElementOfMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to be an element of", matcher.Elements)
}

View File

@@ -1,7 +1,10 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)

View File

@@ -1,9 +1,12 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type BeEquivalentToMatcher struct {

View File

@@ -1,7 +1,10 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)

View File

@@ -0,0 +1,39 @@
// untested sections: 2
package matchers
import (
"fmt"
"runtime"
"github.com/onsi/gomega/format"
)
type BeIdenticalToMatcher struct {
Expected interface{}
}
func (matcher *BeIdenticalToMatcher) Match(actual interface{}) (success bool, matchErr error) {
if actual == nil && matcher.Expected == nil {
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
}
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
success = false
matchErr = nil
}
}
}()
return actual == matcher.Expected, nil
}
func (matcher *BeIdenticalToMatcher) FailureMessage(actual interface{}) string {
return format.Message(actual, "to be identical to", matcher.Expected)
}
func (matcher *BeIdenticalToMatcher) NegatedFailureMessage(actual interface{}) string {
return format.Message(actual, "not to be identical to", matcher.Expected)
}

View File

@@ -1,3 +1,5 @@
// untested sections: 2
package matchers
import "github.com/onsi/gomega/format"

View File

@@ -1,9 +1,12 @@
// untested sections: 4
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"math"
"github.com/onsi/gomega/format"
)
type BeNumericallyMatcher struct {
@@ -12,11 +15,23 @@ type BeNumericallyMatcher struct {
}
func (matcher *BeNumericallyMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, fmt.Sprintf("to be %s", matcher.Comparator), matcher.CompareTo[0])
return matcher.FormatFailureMessage(actual, false)
}
func (matcher *BeNumericallyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Comparator), matcher.CompareTo[0])
return matcher.FormatFailureMessage(actual, true)
}
func (matcher *BeNumericallyMatcher) FormatFailureMessage(actual interface{}, negated bool) (message string) {
if len(matcher.CompareTo) == 1 {
message = fmt.Sprintf("to be %s", matcher.Comparator)
} else {
message = fmt.Sprintf("to be within %v of %s", matcher.CompareTo[1], matcher.Comparator)
}
if negated {
message = "not " + message
}
return format.Message(actual, message, matcher.CompareTo[0])
}
func (matcher *BeNumericallyMatcher) Match(actual interface{}) (success bool, err error) {

View File

@@ -1,3 +1,5 @@
// untested sections: 3
package matchers
import (
@@ -42,8 +44,8 @@ func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error
}()
winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{
reflect.SelectCase{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue},
reflect.SelectCase{Dir: reflect.SelectDefault},
{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue},
{Dir: reflect.SelectDefault},
})
var didSend bool

View File

@@ -1,9 +1,12 @@
// untested sections: 3
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"time"
"github.com/onsi/gomega/format"
)
type BeTemporallyMatcher struct {

View File

@@ -1,7 +1,10 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)

View File

@@ -1,8 +1,9 @@
package matchers
import (
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type BeZeroMatcher struct {

View File

@@ -1,3 +1,5 @@
// untested sections: 3
package matchers
import (
@@ -9,7 +11,9 @@ import (
)
type ConsistOfMatcher struct {
Elements []interface{}
Elements []interface{}
missingElements []interface{}
extraElements []interface{}
}
func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err error) {
@@ -17,44 +21,63 @@ func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err er
return false, fmt.Errorf("ConsistOf matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
}
elements := matcher.Elements
if len(matcher.Elements) == 1 && isArrayOrSlice(matcher.Elements[0]) {
elements = []interface{}{}
value := reflect.ValueOf(matcher.Elements[0])
for i := 0; i < value.Len(); i++ {
elements = append(elements, value.Index(i).Interface())
}
}
matchers := []interface{}{}
for _, element := range elements {
matcher, isMatcher := element.(omegaMatcher)
if !isMatcher {
matcher = &EqualMatcher{Expected: element}
}
matchers = append(matchers, matcher)
}
values := matcher.valuesOf(actual)
if len(values) != len(matchers) {
return false, nil
}
neighbours := func(v, m interface{}) (bool, error) {
match, err := m.(omegaMatcher).Match(v)
return match && err == nil, nil
}
matchers := matchers(matcher.Elements)
values := valuesOf(actual)
bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours)
if err != nil {
return false, err
}
return len(bipartiteGraph.LargestMatching()) == len(values), nil
edges := bipartiteGraph.LargestMatching()
if len(edges) == len(values) && len(edges) == len(matchers) {
return true, nil
}
var missingMatchers []interface{}
matcher.extraElements, missingMatchers = bipartiteGraph.FreeLeftRight(edges)
matcher.missingElements = equalMatchersToElements(missingMatchers)
return false, nil
}
func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} {
func neighbours(value, matcher interface{}) (bool, error) {
match, err := matcher.(omegaMatcher).Match(value)
return match && err == nil, nil
}
func equalMatchersToElements(matchers []interface{}) (elements []interface{}) {
for _, matcher := range matchers {
equalMatcher, ok := matcher.(*EqualMatcher)
if ok {
matcher = equalMatcher.Expected
}
elements = append(elements, matcher)
}
return
}
func matchers(expectedElems []interface{}) (matchers []interface{}) {
elems := expectedElems
if len(expectedElems) == 1 && isArrayOrSlice(expectedElems[0]) {
elems = []interface{}{}
value := reflect.ValueOf(expectedElems[0])
for i := 0; i < value.Len(); i++ {
elems = append(elems, value.Index(i).Interface())
}
}
for _, e := range elems {
matcher, isMatcher := e.(omegaMatcher)
if !isMatcher {
matcher = &EqualMatcher{Expected: e}
}
matchers = append(matchers, matcher)
}
return
}
func valuesOf(actual interface{}) []interface{} {
value := reflect.ValueOf(actual)
values := []interface{}{}
if isMap(actual) {
@@ -72,7 +95,21 @@ func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} {
}
func (matcher *ConsistOfMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, "to consist of", matcher.Elements)
message = format.Message(actual, "to consist of", matcher.Elements)
message = appendMissingElements(message, matcher.missingElements)
if len(matcher.extraElements) > 0 {
message = fmt.Sprintf("%s\nthe extra elements were\n%s", message,
format.Object(matcher.extraElements, 1))
}
return
}
func appendMissingElements(message string, missingElements []interface{}) string {
if len(missingElements) == 0 {
return message
}
return fmt.Sprintf("%s\nthe missing elements were\n%s", message,
format.Object(missingElements, 1))
}
func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) {

View File

@@ -1,3 +1,5 @@
// untested sections: 2
package matchers
import (
@@ -22,19 +24,21 @@ func (matcher *ContainElementMatcher) Match(actual interface{}) (success bool, e
}
value := reflect.ValueOf(actual)
var keys []reflect.Value
var valueAt func(int) interface{}
if isMap(actual) {
keys = value.MapKeys()
keys := value.MapKeys()
valueAt = func(i int) interface{} {
return value.MapIndex(keys[i]).Interface()
}
} else {
valueAt = func(i int) interface{} {
return value.Index(i).Interface()
}
}
var lastError error
for i := 0; i < value.Len(); i++ {
var success bool
var err error
if isMap(actual) {
success, err = elemMatcher.Match(value.MapIndex(keys[i]).Interface())
} else {
success, err = elemMatcher.Match(value.Index(i).Interface())
}
success, err := elemMatcher.Match(valueAt(i))
if err != nil {
lastError = err
continue

View File

@@ -0,0 +1,44 @@
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/matchers/support/goraph/bipartitegraph"
)
type ContainElementsMatcher struct {
Elements []interface{}
missingElements []interface{}
}
func (matcher *ContainElementsMatcher) Match(actual interface{}) (success bool, err error) {
if !isArrayOrSlice(actual) && !isMap(actual) {
return false, fmt.Errorf("ContainElements matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
}
matchers := matchers(matcher.Elements)
bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(valuesOf(actual), matchers, neighbours)
if err != nil {
return false, err
}
edges := bipartiteGraph.LargestMatching()
if len(edges) == len(matchers) {
return true, nil
}
_, missingMatchers := bipartiteGraph.FreeLeftRight(edges)
matcher.missingElements = equalMatchersToElements(missingMatchers)
return false, nil
}
func (matcher *ContainElementsMatcher) FailureMessage(actual interface{}) (message string) {
message = format.Message(actual, "to contain elements", matcher.Elements)
return appendMissingElements(message, matcher.missingElements)
}
func (matcher *ContainElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to contain elements", matcher.Elements)
}

View File

@@ -1,9 +1,12 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"strings"
"github.com/onsi/gomega/format"
)
type ContainSubstringMatcher struct {

View File

@@ -1,6 +1,7 @@
package matchers
import (
"bytes"
"fmt"
"reflect"
@@ -15,10 +16,24 @@ func (matcher *EqualMatcher) Match(actual interface{}) (success bool, err error)
if actual == nil && matcher.Expected == nil {
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
}
// Shortcut for byte slices.
// Comparing long byte slices with reflect.DeepEqual is very slow,
// so use bytes.Equal if actual and expected are both byte slices.
if actualByteSlice, ok := actual.([]byte); ok {
if expectedByteSlice, ok := matcher.Expected.([]byte); ok {
return bytes.Equal(actualByteSlice, expectedByteSlice), nil
}
}
return reflect.DeepEqual(actual, matcher.Expected), nil
}
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

@@ -0,0 +1,30 @@
// untested sections: 2
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)
type HaveCapMatcher struct {
Count int
}
func (matcher *HaveCapMatcher) Match(actual interface{}) (success bool, err error) {
length, ok := capOf(actual)
if !ok {
return false, fmt.Errorf("HaveCap matcher expects a array/channel/slice. Got:\n%s", format.Object(actual, 1))
}
return length == matcher.Count, nil
}
func (matcher *HaveCapMatcher) FailureMessage(actual interface{}) (message string) {
return fmt.Sprintf("Expected\n%s\nto have capacity %d", format.Object(actual, 1), matcher.Count)
}
func (matcher *HaveCapMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return fmt.Sprintf("Expected\n%s\nnot to have capacity %d", format.Object(actual, 1), matcher.Count)
}

View File

@@ -0,0 +1,42 @@
package matchers
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/onsi/gomega/format"
)
type HaveHTTPStatusMatcher struct {
Expected interface{}
}
func (matcher *HaveHTTPStatusMatcher) Match(actual interface{}) (success bool, err error) {
var resp *http.Response
switch a := actual.(type) {
case *http.Response:
resp = a
case *httptest.ResponseRecorder:
resp = a.Result()
default:
return false, fmt.Errorf("HaveHTTPStatus matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1))
}
switch e := matcher.Expected.(type) {
case int:
return resp.StatusCode == e, nil
case string:
return resp.Status == e, nil
}
return false, fmt.Errorf("HaveHTTPStatus matcher must be passed an int or a string. Got:\n%s", format.Object(matcher.Expected, 1))
}
func (matcher *HaveHTTPStatusMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, "to have HTTP status", matcher.Expected)
}
func (matcher *HaveHTTPStatusMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to have HTTP status", matcher.Expected)
}

View File

@@ -1,9 +1,12 @@
// untested sections: 6
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type HaveKeyMatcher struct {

View File

@@ -1,9 +1,12 @@
// untested sections:10
package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type HaveKeyWithValueMatcher struct {

View File

@@ -2,6 +2,7 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)

View File

@@ -1,3 +1,5 @@
// untested sections: 2
package matchers
import (
@@ -10,15 +12,18 @@ type HaveOccurredMatcher struct {
}
func (matcher *HaveOccurredMatcher) Match(actual interface{}) (success bool, err error) {
if isNil(actual) {
// is purely nil?
if actual == nil {
return false, nil
}
if isError(actual) {
return true, nil
// must be an 'error' type
if !isError(actual) {
return false, fmt.Errorf("Expected an error-type. Got:\n%s", format.Object(actual, 1))
}
return false, fmt.Errorf("Expected an error. Got:\n%s", format.Object(actual, 1))
// must be non-nil (or a pointer to a non-nil)
return !isNil(actual), nil
}
func (matcher *HaveOccurredMatcher) FailureMessage(actual interface{}) (message string) {
@@ -26,5 +31,5 @@ func (matcher *HaveOccurredMatcher) FailureMessage(actual interface{}) (message
}
func (matcher *HaveOccurredMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return fmt.Sprintf("Expected error:\n%s\n%s\n%s", format.Object(actual, 1), format.IndentString(actual.(error).Error(), 1), "not to have occurred")
return fmt.Sprintf("Unexpected error:\n%s\n%s\n%s", format.Object(actual, 1), format.IndentString(actual.(error).Error(), 1), "occurred")
}

View File

@@ -2,6 +2,7 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)

View File

@@ -2,6 +2,7 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
)
@@ -16,7 +17,7 @@ func (matcher *HaveSuffixMatcher) Match(actual interface{}) (success bool, err e
return false, fmt.Errorf("HaveSuffix matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1))
}
suffix := matcher.suffix()
return len(actualString) >= len(suffix) && actualString[len(actualString) - len(suffix):] == suffix, nil
return len(actualString) >= len(suffix) && actualString[len(actualString)-len(suffix):] == suffix, nil
}
func (matcher *HaveSuffixMatcher) suffix() string {

View File

@@ -2,8 +2,10 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
"golang.org/x/xerrors"
)
type MatchErrorMatcher struct {
@@ -20,25 +22,28 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e
}
actualErr := actual.(error)
expected := matcher.Expected
if isString(matcher.Expected) {
return reflect.DeepEqual(actualErr.Error(), matcher.Expected), nil
if isError(expected) {
return reflect.DeepEqual(actualErr, expected) || xerrors.Is(actualErr, expected.(error)), nil
}
if isError(matcher.Expected) {
return reflect.DeepEqual(actualErr, matcher.Expected), nil
if isString(expected) {
return actualErr.Error() == expected, nil
}
var subMatcher omegaMatcher
var hasSubMatcher bool
if matcher.Expected != nil {
subMatcher, hasSubMatcher = (matcher.Expected).(omegaMatcher)
if expected != nil {
subMatcher, hasSubMatcher = (expected).(omegaMatcher)
if hasSubMatcher {
return subMatcher.Match(actualErr.Error())
}
}
return false, fmt.Errorf("MatchError must be passed an error, string, or Matcher that can match on strings. Got:\n%s", format.Object(matcher.Expected, 1))
return false, fmt.Errorf(
"MatchError must be passed an error, a string, or a Matcher that can match on strings. Got:\n%s",
format.Object(expected, 1))
}
func (matcher *MatchErrorMatcher) FailureMessage(actual interface{}) (message string) {

View File

@@ -4,12 +4,13 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/onsi/gomega/format"
"reflect"
)
type MatchJSONMatcher struct {
JSONToMatch interface{}
JSONToMatch interface{}
firstFailurePath []interface{}
}
func (matcher *MatchJSONMatcher) Match(actual interface{}) (success bool, err error) {
@@ -24,37 +25,40 @@ func (matcher *MatchJSONMatcher) Match(actual interface{}) (success bool, err er
// this is guarded by prettyPrint
json.Unmarshal([]byte(actualString), &aval)
json.Unmarshal([]byte(expectedString), &eval)
return reflect.DeepEqual(aval, eval), nil
var equal bool
equal, matcher.firstFailurePath = deepEqual(aval, eval)
return equal, nil
}
func (matcher *MatchJSONMatcher) FailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.prettyPrint(actual)
return format.Message(actualString, "to match JSON of", expectedString)
return formattedMessage(format.Message(actualString, "to match JSON of", expectedString), matcher.firstFailurePath)
}
func (matcher *MatchJSONMatcher) NegatedFailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.prettyPrint(actual)
return format.Message(actualString, "not to match JSON of", expectedString)
return formattedMessage(format.Message(actualString, "not to match JSON of", expectedString), matcher.firstFailurePath)
}
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)
ebuf := new(bytes.Buffer)
if err := json.Indent(abuf, []byte(actualString), "", " "); err != nil {
return "", "", err
return "", "", fmt.Errorf("Actual '%s' should be valid JSON, but it is not.\nUnderlying error:%s", actualString, err)
}
if err := json.Indent(ebuf, []byte(expectedString), "", " "); err != nil {
return "", "", err
return "", "", fmt.Errorf("Expected '%s' should be valid JSON, but it is not.\nUnderlying error:%s", expectedString, err)
}
return abuf.String(), ebuf.String(), nil

View File

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

View File

@@ -0,0 +1,134 @@
package matchers
import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"io"
"reflect"
"sort"
"strings"
"github.com/onsi/gomega/format"
"golang.org/x/net/html/charset"
)
type MatchXMLMatcher struct {
XMLToMatch interface{}
}
func (matcher *MatchXMLMatcher) Match(actual interface{}) (success bool, err error) {
actualString, expectedString, err := matcher.formattedPrint(actual)
if err != nil {
return false, err
}
aval, err := parseXmlContent(actualString)
if err != nil {
return false, fmt.Errorf("Actual '%s' should be valid XML, but it is not.\nUnderlying error:%s", actualString, err)
}
eval, err := parseXmlContent(expectedString)
if err != nil {
return false, fmt.Errorf("Expected '%s' should be valid XML, but it is not.\nUnderlying error:%s", expectedString, err)
}
return reflect.DeepEqual(aval, eval), nil
}
func (matcher *MatchXMLMatcher) FailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.formattedPrint(actual)
return fmt.Sprintf("Expected\n%s\nto match XML of\n%s", actualString, expectedString)
}
func (matcher *MatchXMLMatcher) NegatedFailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.formattedPrint(actual)
return fmt.Sprintf("Expected\n%s\nnot to match XML of\n%s", actualString, expectedString)
}
func (matcher *MatchXMLMatcher) formattedPrint(actual interface{}) (actualString, expectedString string, err error) {
var ok bool
actualString, ok = toString(actual)
if !ok {
return "", "", fmt.Errorf("MatchXMLMatcher matcher requires a string, stringer, or []byte. Got actual:\n%s", format.Object(actual, 1))
}
expectedString, ok = toString(matcher.XMLToMatch)
if !ok {
return "", "", fmt.Errorf("MatchXMLMatcher matcher requires a string, stringer, or []byte. Got expected:\n%s", format.Object(matcher.XMLToMatch, 1))
}
return actualString, expectedString, nil
}
func parseXmlContent(content string) (*xmlNode, error) {
allNodes := []*xmlNode{}
dec := newXmlDecoder(strings.NewReader(content))
for {
tok, err := dec.Token()
if err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("failed to decode next token: %v", err) // untested section
}
lastNodeIndex := len(allNodes) - 1
var lastNode *xmlNode
if len(allNodes) > 0 {
lastNode = allNodes[lastNodeIndex]
} else {
lastNode = &xmlNode{}
}
switch tok := tok.(type) {
case xml.StartElement:
attrs := attributesSlice(tok.Attr)
sort.Sort(attrs)
allNodes = append(allNodes, &xmlNode{XMLName: tok.Name, XMLAttr: tok.Attr})
case xml.EndElement:
if len(allNodes) > 1 {
allNodes[lastNodeIndex-1].Nodes = append(allNodes[lastNodeIndex-1].Nodes, lastNode)
allNodes = allNodes[:lastNodeIndex]
}
case xml.CharData:
lastNode.Content = append(lastNode.Content, tok.Copy()...)
case xml.Comment:
lastNode.Comments = append(lastNode.Comments, tok.Copy()) // untested section
case xml.ProcInst:
lastNode.ProcInsts = append(lastNode.ProcInsts, tok.Copy())
}
}
if len(allNodes) == 0 {
return nil, errors.New("found no nodes")
}
firstNode := allNodes[0]
trimParentNodesContentSpaces(firstNode)
return firstNode, nil
}
func newXmlDecoder(reader io.Reader) *xml.Decoder {
dec := xml.NewDecoder(reader)
dec.CharsetReader = charset.NewReaderLabel
return dec
}
func trimParentNodesContentSpaces(node *xmlNode) {
if len(node.Nodes) > 0 {
node.Content = bytes.TrimSpace(node.Content)
for _, childNode := range node.Nodes {
trimParentNodesContentSpaces(childNode)
}
}
}
type xmlNode struct {
XMLName xml.Name
Comments []xml.Comment
ProcInsts []xml.ProcInst
XMLAttr []xml.Attr
Content []byte
Nodes []*xmlNode
}

View File

@@ -0,0 +1,76 @@
package matchers
import (
"fmt"
"strings"
"github.com/onsi/gomega/format"
"gopkg.in/yaml.v2"
)
type MatchYAMLMatcher struct {
YAMLToMatch interface{}
firstFailurePath []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)
}
var equal bool
equal, matcher.firstFailurePath = deepEqual(aval, eval)
return equal, nil
}
func (matcher *MatchYAMLMatcher) FailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.toNormalisedStrings(actual)
return formattedMessage(format.Message(actualString, "to match YAML of", expectedString), matcher.firstFailurePath)
}
func (matcher *MatchYAMLMatcher) NegatedFailureMessage(actual interface{}) (message string) {
actualString, expectedString, _ := matcher.toNormalisedStrings(actual)
return formattedMessage(format.Message(actualString, "not to match YAML of", expectedString), matcher.firstFailurePath)
}
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) // unreachable since Match already calls Unmarshal
}
output, err := yaml.Marshal(val)
if err != nil {
panic(err) // untested section, unreachable since we Unmarshal above
}
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

@@ -2,11 +2,15 @@ package matchers
import (
"fmt"
"github.com/onsi/gomega/format"
"reflect"
"github.com/onsi/gomega/format"
)
type PanicMatcher struct{}
type PanicMatcher struct {
Expected interface{}
object interface{}
}
func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error) {
if actual == nil {
@@ -24,7 +28,22 @@ func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error)
success = false
defer func() {
if e := recover(); e != nil {
success = true
matcher.object = e
if matcher.Expected == nil {
success = true
return
}
valueMatcher, valueIsMatcher := matcher.Expected.(omegaMatcher)
if !valueIsMatcher {
valueMatcher = &EqualMatcher{Expected: matcher.Expected}
}
success, err = valueMatcher.Match(e)
if err != nil {
err = fmt.Errorf("PanicMatcher's value matcher failed with:\n%s%s", format.Indent, err.Error())
}
}
}()
@@ -34,9 +53,62 @@ func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error)
}
func (matcher *PanicMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, "to panic")
if matcher.Expected == nil {
// We wanted any panic to occur, but none did.
return format.Message(actual, "to panic")
}
if matcher.object == nil {
// We wanted a panic with a specific value to occur, but none did.
switch matcher.Expected.(type) {
case omegaMatcher:
return format.Message(actual, "to panic with a value matching", matcher.Expected)
default:
return format.Message(actual, "to panic with", matcher.Expected)
}
}
// We got a panic, but the value isn't what we expected.
switch matcher.Expected.(type) {
case omegaMatcher:
return format.Message(
actual,
fmt.Sprintf(
"to panic with a value matching\n%s\nbut panicked with\n%s",
format.Object(matcher.Expected, 1),
format.Object(matcher.object, 1),
),
)
default:
return format.Message(
actual,
fmt.Sprintf(
"to panic with\n%s\nbut panicked with\n%s",
format.Object(matcher.Expected, 1),
format.Object(matcher.object, 1),
),
)
}
}
func (matcher *PanicMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, "not to panic")
if matcher.Expected == nil {
// We didn't want any panic to occur, but one did.
return format.Message(actual, fmt.Sprintf("not to panic, but panicked with\n%s", format.Object(matcher.object, 1)))
}
// We wanted a to ensure a panic with a specific value did not occur, but it did.
switch matcher.Expected.(type) {
case omegaMatcher:
return format.Message(
actual,
fmt.Sprintf(
"not to panic with a value matching\n%s\nbut panicked with\n%s",
format.Object(matcher.Expected, 1),
format.Object(matcher.object, 1),
),
)
default:
return format.Message(actual, "not to panic with", matcher.Expected)
}
}

View File

@@ -1,3 +1,5 @@
// untested sections: 3
package matchers
import (
@@ -35,17 +37,12 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
if argType.Kind() != reflect.Ptr {
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(matcher.Arg, 1))
}
assignable := channelType.Elem().AssignableTo(argType.Elem())
if !assignable {
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(matcher.Arg, 1))
}
}
}
winnerIndex, value, open := reflect.Select([]reflect.SelectCase{
reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue},
reflect.SelectCase{Dir: reflect.SelectDefault},
{Dir: reflect.SelectRecv, Chan: channelValue},
{Dir: reflect.SelectDefault},
})
var closed bool
@@ -64,21 +61,30 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro
if didReceive {
matcher.receivedValue = value
return subMatcher.Match(matcher.receivedValue.Interface())
} else {
return false, nil
}
return false, nil
}
if didReceive {
if matcher.Arg != nil {
outValue := reflect.ValueOf(matcher.Arg)
reflect.Indirect(outValue).Set(value)
if value.Type().AssignableTo(outValue.Elem().Type()) {
outValue.Elem().Set(value)
return true, nil
}
if value.Type().Kind() == reflect.Interface && value.Elem().Type().AssignableTo(outValue.Elem().Type()) {
outValue.Elem().Set(value.Elem())
return true, nil
} else {
return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nType:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(value.Interface(), 1), format.Object(matcher.Arg, 1))
}
}
return true, nil
} else {
return false, nil
}
return false, nil
}
func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message string) {
@@ -94,9 +100,8 @@ func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message strin
return subMatcher.FailureMessage(matcher.receivedValue.Interface())
}
return "When passed a matcher, ReceiveMatcher's channel *must* receive something."
} else {
return format.Message(actual, "to receive something."+closedAddendum)
}
return format.Message(actual, "to receive something."+closedAddendum)
}
func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (message string) {
@@ -112,9 +117,8 @@ func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (messag
return subMatcher.NegatedFailureMessage(matcher.receivedValue.Interface())
}
return "When passed a matcher, ReceiveMatcher's channel *must* receive something."
} else {
return format.Message(actual, "not to receive anything."+closedAddendum)
}
return format.Message(actual, "not to receive anything."+closedAddendum)
}
func (matcher *ReceiveMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {

View File

@@ -0,0 +1,94 @@
// untested sections: 5
package matchers
import (
"fmt"
"reflect"
"strings"
)
func formattedMessage(comparisonMessage string, failurePath []interface{}) string {
var diffMessage string
if len(failurePath) == 0 {
diffMessage = ""
} else {
diffMessage = fmt.Sprintf("\n\nfirst mismatched key: %s", formattedFailurePath(failurePath))
}
return fmt.Sprintf("%s%s", comparisonMessage, diffMessage)
}
func formattedFailurePath(failurePath []interface{}) string {
formattedPaths := []string{}
for i := len(failurePath) - 1; i >= 0; i-- {
switch p := failurePath[i].(type) {
case int:
formattedPaths = append(formattedPaths, fmt.Sprintf(`[%d]`, p))
default:
if i != len(failurePath)-1 {
formattedPaths = append(formattedPaths, ".")
}
formattedPaths = append(formattedPaths, fmt.Sprintf(`"%s"`, p))
}
}
return strings.Join(formattedPaths, "")
}
func deepEqual(a interface{}, b interface{}) (bool, []interface{}) {
var errorPath []interface{}
if reflect.TypeOf(a) != reflect.TypeOf(b) {
return false, errorPath
}
switch a.(type) {
case []interface{}:
if len(a.([]interface{})) != len(b.([]interface{})) {
return false, errorPath
}
for i, v := range a.([]interface{}) {
elementEqual, keyPath := deepEqual(v, b.([]interface{})[i])
if !elementEqual {
return false, append(keyPath, i)
}
}
return true, errorPath
case map[interface{}]interface{}:
if len(a.(map[interface{}]interface{})) != len(b.(map[interface{}]interface{})) {
return false, errorPath
}
for k, v1 := range a.(map[interface{}]interface{}) {
v2, ok := b.(map[interface{}]interface{})[k]
if !ok {
return false, errorPath
}
elementEqual, keyPath := deepEqual(v1, v2)
if !elementEqual {
return false, append(keyPath, k)
}
}
return true, errorPath
case map[string]interface{}:
if len(a.(map[string]interface{})) != len(b.(map[string]interface{})) {
return false, errorPath
}
for k, v1 := range a.(map[string]interface{}) {
v2, ok := b.(map[string]interface{})[k]
if !ok {
return false, errorPath
}
elementEqual, keyPath := deepEqual(v1, v2)
if !elementEqual {
return false, append(keyPath, k)
}
}
return true, errorPath
default:
return a == b, errorPath
}
}

View File

@@ -10,15 +10,18 @@ type SucceedMatcher struct {
}
func (matcher *SucceedMatcher) Match(actual interface{}) (success bool, err error) {
// is purely nil?
if actual == nil {
return true, nil
}
if isError(actual) {
return false, nil
// must be an 'error' type
if !isError(actual) {
return false, fmt.Errorf("Expected an error-type. Got:\n%s", format.Object(actual, 1))
}
return false, fmt.Errorf("Expected an error-type. Got:\n%s", format.Object(actual, 1))
// must be nil (or a pointer to a nil)
return isNil(actual), nil
}
func (matcher *SucceedMatcher) FailureMessage(actual interface{}) (message string) {

View File

@@ -1,6 +1,5 @@
package bipartitegraph
import "errors"
import "fmt"
import . "github.com/onsi/gomega/matchers/support/goraph/node"
@@ -14,13 +13,13 @@ type BipartiteGraph struct {
func NewBipartiteGraph(leftValues, rightValues []interface{}, neighbours func(interface{}, interface{}) (bool, error)) (*BipartiteGraph, error) {
left := NodeOrderedSet{}
for i, _ := range leftValues {
left = append(left, Node{i})
for i, v := range leftValues {
left = append(left, Node{ID: i, Value: v})
}
right := NodeOrderedSet{}
for j, _ := range rightValues {
right = append(right, Node{j + len(left)})
for j, v := range rightValues {
right = append(right, Node{ID: j + len(left), Value: v})
}
edges := EdgeSet{}
@@ -28,14 +27,30 @@ func NewBipartiteGraph(leftValues, rightValues []interface{}, neighbours func(in
for j, rightValue := range rightValues {
neighbours, err := neighbours(leftValue, rightValue)
if err != nil {
return nil, errors.New(fmt.Sprintf("error determining adjacency for %v and %v: %s", leftValue, rightValue, err.Error()))
return nil, fmt.Errorf("error determining adjacency for %v and %v: %s", leftValue, rightValue, err.Error())
}
if neighbours {
edges = append(edges, Edge{left[i], right[j]})
edges = append(edges, Edge{Node1: left[i].ID, Node2: right[j].ID})
}
}
}
return &BipartiteGraph{left, right, edges}, nil
}
// FreeLeftRight returns left node values and right node values
// of the BipartiteGraph's nodes which are not part of the given edges.
func (bg *BipartiteGraph) FreeLeftRight(edges EdgeSet) (leftValues, rightValues []interface{}) {
for _, node := range bg.Left {
if edges.Free(node) {
leftValues = append(leftValues, node.Value)
}
}
for _, node := range bg.Right {
if edges.Free(node) {
rightValues = append(rightValues, node.Value)
}
}
return
}

View File

@@ -1,9 +1,14 @@
package bipartitegraph
import . "github.com/onsi/gomega/matchers/support/goraph/node"
import . "github.com/onsi/gomega/matchers/support/goraph/edge"
import "github.com/onsi/gomega/matchers/support/goraph/util"
import (
. "github.com/onsi/gomega/matchers/support/goraph/edge"
. "github.com/onsi/gomega/matchers/support/goraph/node"
"github.com/onsi/gomega/matchers/support/goraph/util"
)
// LargestMatching implements the HopcroftKarp algorithm taking as input a bipartite graph
// and outputting a maximum cardinality matching, i.e. a set of as many edges as possible
// with the property that no two edges share an endpoint.
func (bg *BipartiteGraph) LargestMatching() (matching EdgeSet) {
paths := bg.maximalDisjointSLAPCollection(matching)
@@ -23,7 +28,7 @@ func (bg *BipartiteGraph) maximalDisjointSLAPCollection(matching EdgeSet) (resul
return
}
used := make(map[Node]bool)
used := make(map[int]bool)
for _, u := range guideLayers[len(guideLayers)-1] {
slap, found := bg.findDisjointSLAP(u, matching, guideLayers, used)
@@ -43,7 +48,7 @@ func (bg *BipartiteGraph) findDisjointSLAP(
start Node,
matching EdgeSet,
guideLayers []NodeOrderedSet,
used map[Node]bool,
used map[int]bool,
) ([]Edge, bool) {
return bg.findDisjointSLAPHelper(start, EdgeSet{}, len(guideLayers)-1, matching, guideLayers, used)
}
@@ -54,16 +59,16 @@ func (bg *BipartiteGraph) findDisjointSLAPHelper(
currentLevel int,
matching EdgeSet,
guideLayers []NodeOrderedSet,
used map[Node]bool,
used map[int]bool,
) (EdgeSet, bool) {
used[currentNode] = true
used[currentNode.ID] = true
if currentLevel == 0 {
return currentSLAP, true
}
for _, nextNode := range guideLayers[currentLevel-1] {
if used[nextNode] {
if used[nextNode.ID] {
continue
}
@@ -84,26 +89,25 @@ func (bg *BipartiteGraph) findDisjointSLAPHelper(
currentSLAP = currentSLAP[:len(currentSLAP)-1]
}
used[currentNode] = false
used[currentNode.ID] = false
return nil, false
}
func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers []NodeOrderedSet) {
used := make(map[Node]bool)
used := make(map[int]bool)
currentLayer := NodeOrderedSet{}
for _, node := range bg.Left {
if matching.Free(node) {
used[node] = true
used[node.ID] = true
currentLayer = append(currentLayer, node)
}
}
if len(currentLayer) == 0 {
return []NodeOrderedSet{}
} else {
guideLayers = append(guideLayers, currentLayer)
}
guideLayers = append(guideLayers, currentLayer)
done := false
@@ -114,7 +118,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
if util.Odd(len(guideLayers)) {
for _, leftNode := range lastLayer {
for _, rightNode := range bg.Right {
if used[rightNode] {
if used[rightNode.ID] {
continue
}
@@ -124,7 +128,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
}
currentLayer = append(currentLayer, rightNode)
used[rightNode] = true
used[rightNode.ID] = true
if matching.Free(rightNode) {
done = true
@@ -134,7 +138,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
} else {
for _, rightNode := range lastLayer {
for _, leftNode := range bg.Left {
if used[leftNode] {
if used[leftNode.ID] {
continue
}
@@ -144,7 +148,7 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
}
currentLayer = append(currentLayer, leftNode)
used[leftNode] = true
used[leftNode.ID] = true
}
}
@@ -152,9 +156,8 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
if len(currentLayer) == 0 {
return []NodeOrderedSet{}
} else {
guideLayers = append(guideLayers, currentLayer)
}
guideLayers = append(guideLayers, currentLayer)
}
return

View File

@@ -3,15 +3,15 @@ package edge
import . "github.com/onsi/gomega/matchers/support/goraph/node"
type Edge struct {
Node1 Node
Node2 Node
Node1 int
Node2 int
}
type EdgeSet []Edge
func (ec EdgeSet) Free(node Node) bool {
for _, e := range ec {
if e.Node1 == node || e.Node2 == node {
if e.Node1 == node.ID || e.Node2 == node.ID {
return false
}
}
@@ -31,7 +31,7 @@ func (ec EdgeSet) Contains(edge Edge) bool {
func (ec EdgeSet) FindByNodes(node1, node2 Node) (Edge, bool) {
for _, e := range ec {
if (e.Node1 == node1 && e.Node2 == node2) || (e.Node1 == node2 && e.Node2 == node1) {
if (e.Node1 == node1.ID && e.Node2 == node2.ID) || (e.Node1 == node2.ID && e.Node2 == node1.ID) {
return e, true
}
}

View File

@@ -1,7 +1,8 @@
package node
type Node struct {
Id int
ID int
Value interface{}
}
type NodeOrderedSet []Node

View File

@@ -3,5 +3,5 @@ package util
import "math"
func Odd(n int) bool {
return math.Mod(float64(n), 2.0) == 1.0
}
return math.Mod(float64(n), 2.0) == 1.0
}

View File

@@ -6,9 +6,13 @@ See the docs for Gomega for documentation on the matchers
http://onsi.github.io/gomega/
*/
// untested sections: 11
package matchers
import (
"encoding/json"
"fmt"
"reflect"
)
@@ -53,9 +57,8 @@ func toInteger(a interface{}) int64 {
return int64(reflect.ValueOf(a).Uint())
} else if isFloat(a) {
return int64(reflect.ValueOf(a).Float())
} else {
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
func toUnsignedInteger(a interface{}) uint64 {
@@ -65,9 +68,8 @@ func toUnsignedInteger(a interface{}) uint64 {
return reflect.ValueOf(a).Uint()
} else if isFloat(a) {
return uint64(reflect.ValueOf(a).Float())
} else {
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
func toFloat(a interface{}) float64 {
@@ -77,9 +79,8 @@ func toFloat(a interface{}) float64 {
return float64(reflect.ValueOf(a).Uint())
} else if isFloat(a) {
return reflect.ValueOf(a).Float()
} else {
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a))
}
func isError(a interface{}) bool {
@@ -136,6 +137,11 @@ func toString(a interface{}) (string, bool) {
return aStringer.String(), true
}
aJSONRawMessage, isJSONRawMessage := a.(json.RawMessage)
if isJSONRawMessage {
return string(aJSONRawMessage), true
}
return "", false
}
@@ -150,6 +156,17 @@ func lengthOf(a interface{}) (int, bool) {
return 0, false
}
}
func capOf(a interface{}) (int, bool) {
if a == nil {
return 0, false
}
switch reflect.TypeOf(a).Kind() {
case reflect.Array, reflect.Chan, reflect.Slice:
return reflect.ValueOf(a).Cap(), true
default:
return 0, false
}
}
func isNil(a interface{}) bool {
if a == nil {