func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err error) { if isNil(actual) { return false, fmt.Errorf("Expected an error, got nil") } if !isError(actual) { return false, fmt.Errorf("Expected an error. Got:\n%s", format.Object(actual, 1)) } actualErr := actual.(error) if isString(matcher.Expected) { return reflect.DeepEqual(actualErr.Error(), matcher.Expected), nil } if isError(matcher.Expected) { return reflect.DeepEqual(actualErr, matcher.Expected), nil } var subMatcher omegaMatcher var hasSubMatcher bool if matcher.Expected != nil { subMatcher, hasSubMatcher = (matcher.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)) }
func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) { if !isBool(actual) { return false, fmt.Errorf("Expected a boolean. Got:\n%s", format.Object(actual, 1)) } return actual.(bool), nil }
func (matcher *BeClosedMatcher) Match(actual interface{}) (success bool, err error) { if !isChan(actual) { return false, fmt.Errorf("BeClosed matcher expects a channel. Got:\n%s", format.Object(actual, 1)) } channelType := reflect.TypeOf(actual) channelValue := reflect.ValueOf(actual) if channelType.ChanDir() == reflect.SendDir { return false, fmt.Errorf("BeClosed matcher cannot determine if a send-only channel is closed or open. Got:\n%s", format.Object(actual, 1)) } winnerIndex, _, open := reflect.Select([]reflect.SelectCase{ reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue}, reflect.SelectCase{Dir: reflect.SelectDefault}, }) var closed bool if winnerIndex == 0 { closed = !open } else if winnerIndex == 1 { closed = false } return closed, nil }
func (matcher *HaveKeyWithValueMatcher) Match(actual interface{}) (success bool, err error) { if !isMap(actual) { return false, fmt.Errorf("HaveKeyWithValue matcher expects a map. Got:%s", format.Object(actual, 1)) } keyMatcher, keyIsMatcher := matcher.Key.(omegaMatcher) if !keyIsMatcher { keyMatcher = &EqualMatcher{Expected: matcher.Key} } valueMatcher, valueIsMatcher := matcher.Value.(omegaMatcher) if !valueIsMatcher { valueMatcher = &EqualMatcher{Expected: matcher.Value} } keys := reflect.ValueOf(actual).MapKeys() for i := 0; i < len(keys); i++ { success, err := keyMatcher.Match(keys[i].Interface()) if err != nil { return false, fmt.Errorf("HaveKeyWithValue's key matcher failed with:\n%s%s", format.Indent, err.Error()) } if success { actualValue := reflect.ValueOf(actual).MapIndex(keys[i]) success, err := valueMatcher.Match(actualValue.Interface()) if err != nil { return false, fmt.Errorf("HaveKeyWithValue's value matcher failed with:\n%s%s", format.Indent, err.Error()) } return success, nil } } return false, nil }
func (matcher *BeNumericallyMatcher) Match(actual interface{}) (success bool, err error) { if len(matcher.CompareTo) == 0 || len(matcher.CompareTo) > 2 { return false, fmt.Errorf("BeNumerically requires 1 or 2 CompareTo arguments. Got:\n%s", format.Object(matcher.CompareTo, 1)) } if !isNumber(actual) { return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(actual, 1)) } if !isNumber(matcher.CompareTo[0]) { return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) } if len(matcher.CompareTo) == 2 && !isNumber(matcher.CompareTo[1]) { return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) } switch matcher.Comparator { case "==", "~", ">", ">=", "<", "<=": default: return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator) } if isFloat(actual) || isFloat(matcher.CompareTo[0]) { var secondOperand float64 = 1e-8 if len(matcher.CompareTo) == 2 { secondOperand = toFloat(matcher.CompareTo[1]) } success = matcher.matchFloats(toFloat(actual), toFloat(matcher.CompareTo[0]), secondOperand) } else if isInteger(actual) { var secondOperand int64 = 0 if len(matcher.CompareTo) == 2 { secondOperand = toInteger(matcher.CompareTo[1]) } success = matcher.matchIntegers(toInteger(actual), toInteger(matcher.CompareTo[0]), secondOperand) } else if isUnsignedInteger(actual) { var secondOperand uint64 = 0 if len(matcher.CompareTo) == 2 { secondOperand = toUnsignedInteger(matcher.CompareTo[1]) } success = matcher.matchUnsignedIntegers(toUnsignedInteger(actual), toUnsignedInteger(matcher.CompareTo[0]), secondOperand) } else { return false, fmt.Errorf("Failed to compare:\n%s\n%s:\n%s", format.Object(actual, 1), matcher.Comparator, format.Object(matcher.CompareTo[0], 1)) } return success, nil }
func (matcher *SucceedMatcher) Match(actual interface{}) (success bool, err error) { if actual == nil { return true, nil } if isError(actual) { return false, nil } return false, fmt.Errorf("Expected an error-type. Got:\n%s", format.Object(actual, 1)) }
func (matcher *HaveOccurredMatcher) Match(actual interface{}) (success bool, err error) { if isNil(actual) { return false, nil } if isError(actual) { return true, nil } return false, fmt.Errorf("Expected an error. Got:\n%s", format.Object(actual, 1)) }
func (matcher *MatchRegexpMatcher) Match(actual interface{}) (success bool, err error) { actualString, ok := toString(actual) if !ok { return false, fmt.Errorf("RegExp matcher requires a string or stringer.\nGot:%s", format.Object(actual, 1)) } match, err := regexp.Match(matcher.regexp(), []byte(actualString)) if err != nil { return false, fmt.Errorf("RegExp match failed to compile with error:\n\t%s", err.Error()) } return match, nil }
func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) { if !isChan(actual) { return false, fmt.Errorf("BeSent expects a channel. Got:\n%s", format.Object(actual, 1)) } channelType := reflect.TypeOf(actual) channelValue := reflect.ValueOf(actual) if channelType.ChanDir() == reflect.RecvDir { return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel. Got:\n%s", format.Object(actual, 1)) } argType := reflect.TypeOf(matcher.Arg) assignable := argType.AssignableTo(channelType.Elem()) if !assignable { return false, fmt.Errorf("Cannot pass:\n%s to the channel:\n%s\nThe types don't match.", format.Object(matcher.Arg, 1), format.Object(actual, 1)) } argValue := reflect.ValueOf(matcher.Arg) defer func() { if e := recover(); e != nil { success = false err = fmt.Errorf("Cannot send to a closed channel") matcher.channelClosed = true } }() winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{ reflect.SelectCase{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue}, reflect.SelectCase{Dir: reflect.SelectDefault}, }) var didSend bool if winnerIndex == 0 { didSend = true } return didSend, nil }
func (matcher *BeTemporallyMatcher) Match(actual interface{}) (bool, error) { // predicate to test for time.Time type isTime := func(t interface{}) bool { _, ok := t.(time.Time) return ok } if !isTime(actual) { return false, fmt.Errorf("Expected a time.Time. Got:\n%s", format.Object(actual, 1)) } switch matcher.Comparator { case "==", "~", ">", ">=", "<", "<=": default: return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator) } var threshold = time.Millisecond if len(matcher.Threshold) == 1 { threshold = matcher.Threshold[0] } return matcher.matchTimes(actual.(time.Time), matcher.CompareTo, threshold), nil }
func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error) { if actual == nil { return false, fmt.Errorf("PanicMatcher expects a non-nil actual.") } actualType := reflect.TypeOf(actual) if actualType.Kind() != reflect.Func { return false, fmt.Errorf("PanicMatcher expects a function. Got:\n%s", format.Object(actual, 1)) } if !(actualType.NumIn() == 0 && actualType.NumOut() == 0) { return false, fmt.Errorf("PanicMatcher expects a function with no arguments and no return value. Got:\n%s", format.Object(actual, 1)) } success = false defer func() { if e := recover(); e != nil { success = true } }() reflect.ValueOf(actual).Call([]reflect.Value{}) return }
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)) } abuf := new(bytes.Buffer) ebuf := new(bytes.Buffer) if err := json.Indent(abuf, []byte(actualString), "", " "); err != nil { return "", "", err } if err := json.Indent(ebuf, []byte(expectedString), "", " "); err != nil { return "", "", err } return abuf.String(), ebuf.String(), nil }
func (matcher *HaveSuffixMatcher) Match(actual interface{}) (success bool, err error) { actualString, ok := toString(actual) if !ok { 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 }
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") }
func (matcher *HaveOccurredMatcher) FailureMessage(actual interface{}) (message string) { return fmt.Sprintf("Expected an error to have occured. Got:\n%s", format.Object(actual, 1)) }
func (matcher *HaveLenMatcher) Match(actual interface{}) (success bool, err error) { length, ok := lengthOf(actual) if !ok { return false, fmt.Errorf("HaveLen matcher expects a string/array/map/channel/slice. Got:\n%s", format.Object(actual, 1)) } return length == matcher.Count, nil }
func (matcher *ContainSubstringMatcher) Match(actual interface{}) (success bool, err error) { actualString, ok := toString(actual) if !ok { return false, fmt.Errorf("ContainSubstring matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1)) } return strings.Contains(actualString, matcher.stringToMatch()), nil }
func (m *sayMatcher) Match(actual interface{}) (success bool, err error) { buffer, ok := m.buffer(actual) if !ok { return false, fmt.Errorf("Say must be passed a *gbytes.Buffer or BufferProvider. Got:\n%s", format.Object(actual, 1)) } didSay, sayings := buffer.didSay(m.re) m.receivedSayings = sayings return didSay, nil }
func (matcher *ContainElementMatcher) Match(actual interface{}) (success bool, err error) { if !isArrayOrSlice(actual) && !isMap(actual) { return false, fmt.Errorf("ContainElement matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1)) } elemMatcher, elementIsMatcher := matcher.Element.(omegaMatcher) if !elementIsMatcher { elemMatcher = &EqualMatcher{Expected: matcher.Element} } value := reflect.ValueOf(actual) var keys []reflect.Value if isMap(actual) { keys = value.MapKeys() } 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()) } if err != nil { lastError = err continue } if success { return true, nil } } return false, lastError }
func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err error) { if !isArrayOrSlice(actual) && !isMap(actual) { 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 } bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours) if err != nil { return false, err } return len(bipartiteGraph.LargestMatching()) == len(values), nil }
func (matcher *HaveLenMatcher) NegatedFailureMessage(actual interface{}) (message string) { return fmt.Sprintf("Expected\n%s\nnot to have length %d", format.Object(actual, 1), matcher.Count) }
func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err error) { if !isChan(actual) { return false, fmt.Errorf("ReceiveMatcher expects a channel. Got:\n%s", format.Object(actual, 1)) } channelType := reflect.TypeOf(actual) channelValue := reflect.ValueOf(actual) if channelType.ChanDir() == reflect.SendDir { return false, fmt.Errorf("ReceiveMatcher matcher cannot be passed a send-only channel. Got:\n%s", format.Object(actual, 1)) } var subMatcher omegaMatcher var hasSubMatcher bool if matcher.Arg != nil { subMatcher, hasSubMatcher = (matcher.Arg).(omegaMatcher) if !hasSubMatcher { argType := reflect.TypeOf(matcher.Arg) 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}, }) var closed bool var didReceive bool if winnerIndex == 0 { closed = !open didReceive = open } matcher.channelClosed = closed if closed { return false, nil } if hasSubMatcher { if didReceive { matcher.receivedValue = value return subMatcher.Match(matcher.receivedValue.Interface()) } else { return false, nil } } if didReceive { if matcher.Arg != nil { outValue := reflect.ValueOf(matcher.Arg) reflect.Indirect(outValue).Set(value) } return true, nil } else { return false, nil } }
func (matcher *SucceedMatcher) FailureMessage(actual interface{}) (message string) { return fmt.Sprintf("Expected success, but got an error:\n%s\n%s", format.Object(actual, 1), format.IndentString(actual.(error).Error(), 1)) }