From 621e49bb465f500cc46d47e39e828cf76d6381d7 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 24 Jul 2018 14:35:44 +0200 Subject: update vendor --- vendor/github.com/golang/mock/gomock/call.go | 306 ++++++++++++++++----- vendor/github.com/golang/mock/gomock/call_test.go | 6 +- vendor/github.com/golang/mock/gomock/callset.go | 108 +++++--- .../github.com/golang/mock/gomock/callset_test.go | 76 +++++ vendor/github.com/golang/mock/gomock/controller.go | 144 ++++++---- .../golang/mock/gomock/controller_test.go | 245 ++++++++++++++++- .../mock/gomock/mock_matcher/mock_matcher.go | 57 ++++ 7 files changed, 776 insertions(+), 166 deletions(-) create mode 100644 vendor/github.com/golang/mock/gomock/callset_test.go create mode 100644 vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go (limited to 'vendor/github.com/golang/mock/gomock') diff --git a/vendor/github.com/golang/mock/gomock/call.go b/vendor/github.com/golang/mock/gomock/call.go index cc8dfff..a3fa1ae 100644 --- a/vendor/github.com/golang/mock/gomock/call.go +++ b/vendor/github.com/golang/mock/gomock/call.go @@ -17,6 +17,7 @@ package gomock import ( "fmt" "reflect" + "strconv" "strings" ) @@ -24,11 +25,11 @@ import ( type Call struct { t TestReporter // for triggering test failures on invalid call setup - receiver interface{} // the receiver of the method call - method string // the name of the method - methodType reflect.Type // the type of the method - args []Matcher // the args - rets []interface{} // the return values (if any) + receiver interface{} // the receiver of the method call + method string // the name of the method + methodType reflect.Type // the type of the method + args []Matcher // the args + origin string // file and line number of call setup preReqs []*Call // prerequisite calls @@ -37,9 +38,44 @@ type Call struct { numCalls int // actual number made - // Actions - doFunc reflect.Value - setArgs map[int]reflect.Value + // actions are called when this Call is called. Each action gets the args and + // can set the return values by returning a non-nil slice. Actions run in the + // order they are created. + actions []func([]interface{}) []interface{} +} + +// newCall creates a *Call. It requires the method type in order to support +// unexported methods. +func newCall(t TestReporter, receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call { + if h, ok := t.(testHelper); ok { + h.Helper() + } + + // TODO: check arity, types. + margs := make([]Matcher, len(args)) + for i, arg := range args { + if m, ok := arg.(Matcher); ok { + margs[i] = m + } else if arg == nil { + // Handle nil specially so that passing a nil interface value + // will match the typed nils of concrete args. + margs[i] = Nil() + } else { + margs[i] = Eq(arg) + } + } + + origin := callerInfo(3) + actions := []func([]interface{}) []interface{}{func([]interface{}) []interface{} { + // Synthesize the zero value for each of the return args' types. + rets := make([]interface{}, methodType.NumOut()) + for i := 0; i < methodType.NumOut(); i++ { + rets[i] = reflect.Zero(methodType.Out(i)).Interface() + } + return rets + }} + return &Call{t: t, receiver: receiver, method: method, methodType: methodType, + args: margs, origin: origin, minCalls: 1, maxCalls: 1, actions: actions} } // AnyTimes allows the expectation to be called 0 or more times @@ -68,19 +104,69 @@ func (c *Call) MaxTimes(n int) *Call { return c } -// Do declares the action to run when the call is matched. +// DoAndReturn declares the action to run when the call is matched. +// The return values from this function are returned by the mocked function. +// It takes an interface{} argument to support n-arity functions. +func (c *Call) DoAndReturn(f interface{}) *Call { + // TODO: Check arity and types here, rather than dying badly elsewhere. + v := reflect.ValueOf(f) + + c.addAction(func(args []interface{}) []interface{} { + vargs := make([]reflect.Value, len(args)) + ft := v.Type() + for i := 0; i < len(args); i++ { + if args[i] != nil { + vargs[i] = reflect.ValueOf(args[i]) + } else { + // Use the zero value for the arg. + vargs[i] = reflect.Zero(ft.In(i)) + } + } + vrets := v.Call(vargs) + rets := make([]interface{}, len(vrets)) + for i, ret := range vrets { + rets[i] = ret.Interface() + } + return rets + }) + return c +} + +// Do declares the action to run when the call is matched. The function's +// return values are ignored to retain backward compatibility. To use the +// return values call DoAndReturn. // It takes an interface{} argument to support n-arity functions. func (c *Call) Do(f interface{}) *Call { // TODO: Check arity and types here, rather than dying badly elsewhere. - c.doFunc = reflect.ValueOf(f) + v := reflect.ValueOf(f) + + c.addAction(func(args []interface{}) []interface{} { + vargs := make([]reflect.Value, len(args)) + ft := v.Type() + for i := 0; i < len(args); i++ { + if args[i] != nil { + vargs[i] = reflect.ValueOf(args[i]) + } else { + // Use the zero value for the arg. + vargs[i] = reflect.Zero(ft.In(i)) + } + } + v.Call(vargs) + return nil + }) return c } +// Return declares the values to be returned by the mocked function call. func (c *Call) Return(rets ...interface{}) *Call { + if h, ok := c.t.(testHelper); ok { + h.Helper() + } + mt := c.methodType if len(rets) != mt.NumOut() { - c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d", - c.receiver, c.method, len(rets), mt.NumOut()) + c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]", + c.receiver, c.method, len(rets), mt.NumOut(), c.origin) } for i, ret := range rets { if got, want := reflect.TypeOf(ret), mt.Out(i); got == want { @@ -91,8 +177,8 @@ func (c *Call) Return(rets ...interface{}) *Call { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: // ok default: - c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable", - i, c.receiver, c.method, want) + c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]", + i, c.receiver, c.method, want, c.origin) } } else if got.AssignableTo(want) { // Assignable type relation. Make the assignment now so that the generated code @@ -101,31 +187,38 @@ func (c *Call) Return(rets ...interface{}) *Call { v.Set(reflect.ValueOf(ret)) rets[i] = v.Interface() } else { - c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v", - i, c.receiver, c.method, got, want) + c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]", + i, c.receiver, c.method, got, want, c.origin) } } - c.rets = rets + c.addAction(func([]interface{}) []interface{} { + return rets + }) + return c } +// Times declares the exact number of times a function call is expected to be executed. func (c *Call) Times(n int) *Call { c.minCalls, c.maxCalls = n, n return c } // SetArg declares an action that will set the nth argument's value, -// indirected through a pointer. +// indirected through a pointer. Or, in the case of a slice, SetArg +// will copy value's elements into the nth argument. func (c *Call) SetArg(n int, value interface{}) *Call { - if c.setArgs == nil { - c.setArgs = make(map[int]reflect.Value) + if h, ok := c.t.(testHelper); ok { + h.Helper() } + mt := c.methodType // TODO: This will break on variadic methods. // We will need to check those at invocation time. if n < 0 || n >= mt.NumIn() { - c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn()) + c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]", + n, mt.NumIn(), c.origin) } // Permit setting argument through an interface. // In the interface case, we don't (nay, can't) check the type here. @@ -134,14 +227,28 @@ func (c *Call) SetArg(n int, value interface{}) *Call { case reflect.Ptr: dt := at.Elem() if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) { - c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt) + c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]", + n, vt, dt, c.origin) } case reflect.Interface: // nothing to do + case reflect.Slice: + // nothing to do default: - c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at) + c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]", + n, at, c.origin) } - c.setArgs[n] = reflect.ValueOf(value) + + c.addAction(func(args []interface{}) []interface{} { + v := reflect.ValueOf(value) + switch reflect.TypeOf(args[n]).Kind() { + case reflect.Slice: + setSlice(args[n], v) + default: + reflect.ValueOf(args[n]).Elem().Set(v) + } + return nil + }) return c } @@ -157,8 +264,12 @@ func (c *Call) isPreReq(other *Call) bool { // After declares that the call may only match after preReq has been exhausted. func (c *Call) After(preReq *Call) *Call { + if h, ok := c.t.(testHelper); ok { + h.Helper() + } + if c == preReq { - c.t.Fatalf("A call isn't allowed to be it's own prerequisite") + c.t.Fatalf("A call isn't allowed to be its own prerequisite") } if preReq.isPreReq(c) { c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq) @@ -168,7 +279,7 @@ func (c *Call) After(preReq *Call) *Call { return c } -// Returns true iff the minimum number of calls have been made. +// Returns true if the minimum number of calls have been made. func (c *Call) satisfied() bool { return c.numCalls >= c.minCalls } @@ -184,31 +295,108 @@ func (c *Call) String() string { args[i] = arg.String() } arguments := strings.Join(args, ", ") - return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments) + return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin) } // Tests if the given call matches the expected call. -func (c *Call) matches(args []interface{}) bool { - if len(args) != len(c.args) { - return false - } - for i, m := range c.args { - if !m.Matches(args[i]) { - return false +// If yes, returns nil. If no, returns error with message explaining why it does not match. +func (c *Call) matches(args []interface{}) error { + if !c.methodType.IsVariadic() { + if len(args) != len(c.args) { + return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d", + c.origin, len(args), len(c.args)) + } + + for i, m := range c.args { + if !m.Matches(args[i]) { + return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v", + c.origin, strconv.Itoa(i), args[i], m) + } + } + } else { + if len(c.args) < c.methodType.NumIn()-1 { + return fmt.Errorf("Expected call at %s has the wrong number of matchers. Got: %d, want: %d", + c.origin, len(c.args), c.methodType.NumIn()-1) + } + if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) { + return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d", + c.origin, len(args), len(c.args)) + } + if len(args) < len(c.args)-1 { + return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d", + c.origin, len(args), len(c.args)-1) + } + + for i, m := range c.args { + if i < c.methodType.NumIn()-1 { + // Non-variadic args + if !m.Matches(args[i]) { + return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v", + c.origin, strconv.Itoa(i), args[i], m) + } + continue + } + // The last arg has a possibility of a variadic argument, so let it branch + + // sample: Foo(a int, b int, c ...int) + if i < len(c.args) && i < len(args) { + if m.Matches(args[i]) { + // Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any()) + // Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher) + // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC) + // Got Foo(a, b) want Foo(matcherA, matcherB) + // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD) + continue + } + } + + // The number of actual args don't match the number of matchers, + // or the last matcher is a slice and the last arg is not. + // If this function still matches it is because the last matcher + // matches all the remaining arguments or the lack of any. + // Convert the remaining arguments, if any, into a slice of the + // expected type. + vargsType := c.methodType.In(c.methodType.NumIn() - 1) + vargs := reflect.MakeSlice(vargsType, 0, len(args)-i) + for _, arg := range args[i:] { + vargs = reflect.Append(vargs, reflect.ValueOf(arg)) + } + if m.Matches(vargs.Interface()) { + // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any()) + // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher) + // Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any()) + // Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher) + break + } + // Wrong number of matchers or not match. Fail. + // Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD) + // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD) + // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE) + // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD) + // Got Foo(a, b, c) want Foo(matcherA, matcherB) + return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v", + c.origin, strconv.Itoa(i), args[i:], c.args[i]) + } } // Check that all prerequisite calls have been satisfied. for _, preReqCall := range c.preReqs { if !preReqCall.satisfied() { - return false + return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v", + c.origin, preReqCall, c) } } - return true + // Check that the call is not exhausted. + if c.exhausted() { + return fmt.Errorf("Expected call at %s has already been called the max number of times.", c.origin) + } + + return nil } -// dropPrereqs tells the expected Call to not re-check prerequite calls any +// dropPrereqs tells the expected Call to not re-check prerequisite calls any // longer, and to return its current set. func (c *Call) dropPrereqs() (preReqs []*Call) { preReqs = c.preReqs @@ -216,38 +404,9 @@ func (c *Call) dropPrereqs() (preReqs []*Call) { return } -func (c *Call) call(args []interface{}) (rets []interface{}, action func()) { +func (c *Call) call(args []interface{}) []func([]interface{}) []interface{} { c.numCalls++ - - // Actions - if c.doFunc.IsValid() { - doArgs := make([]reflect.Value, len(args)) - ft := c.doFunc.Type() - for i := 0; i < len(args); i++ { - if args[i] != nil { - doArgs[i] = reflect.ValueOf(args[i]) - } else { - // Use the zero value for the arg. - doArgs[i] = reflect.Zero(ft.In(i)) - } - } - action = func() { c.doFunc.Call(doArgs) } - } - for n, v := range c.setArgs { - reflect.ValueOf(args[n]).Elem().Set(v) - } - - rets = c.rets - if rets == nil { - // Synthesize the zero value for each of the return args' types. - mt := c.methodType - rets = make([]interface{}, mt.NumOut()) - for i := 0; i < mt.NumOut(); i++ { - rets[i] = reflect.Zero(mt.Out(i)).Interface() - } - } - - return + return c.actions } // InOrder declares that the given calls should occur in order. @@ -256,3 +415,14 @@ func InOrder(calls ...*Call) { calls[i].After(calls[i-1]) } } + +func setSlice(arg interface{}, v reflect.Value) { + va := reflect.ValueOf(arg) + for i := 0; i < v.Len(); i++ { + va.Index(i).Set(v.Index(i)) + } +} + +func (c *Call) addAction(action func([]interface{}) []interface{}) { + c.actions = append(c.actions, action) +} diff --git a/vendor/github.com/golang/mock/gomock/call_test.go b/vendor/github.com/golang/mock/gomock/call_test.go index 3ae7263..3a8315b 100644 --- a/vendor/github.com/golang/mock/gomock/call_test.go +++ b/vendor/github.com/golang/mock/gomock/call_test.go @@ -1,6 +1,8 @@ package gomock -import "testing" +import ( + "testing" +) type mockTestReporter struct { errorCalls int @@ -15,6 +17,8 @@ func (o *mockTestReporter) Fatalf(format string, args ...interface{}) { o.fatalCalls++ } +func (o *mockTestReporter) Helper() {} + func TestCall_After(t *testing.T) { t.Run("SelfPrereqCallsFatalf", func(t *testing.T) { tr1 := &mockTestReporter{} diff --git a/vendor/github.com/golang/mock/gomock/callset.go b/vendor/github.com/golang/mock/gomock/callset.go index 1b7de4c..c44a8a5 100644 --- a/vendor/github.com/golang/mock/gomock/callset.go +++ b/vendor/github.com/golang/mock/gomock/callset.go @@ -14,63 +14,95 @@ package gomock +import ( + "bytes" + "fmt" +) + // callSet represents a set of expected calls, indexed by receiver and method // name. -type callSet map[interface{}]map[string][]*Call +type callSet struct { + // Calls that are still expected. + expected map[callSetKey][]*Call + // Calls that have been exhausted. + exhausted map[callSetKey][]*Call +} + +// callSetKey is the key in the maps in callSet +type callSetKey struct { + receiver interface{} + fname string +} + +func newCallSet() *callSet { + return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)} +} // Add adds a new expected call. func (cs callSet) Add(call *Call) { - methodMap, ok := cs[call.receiver] - if !ok { - methodMap = make(map[string][]*Call) - cs[call.receiver] = methodMap + key := callSetKey{call.receiver, call.method} + m := cs.expected + if call.exhausted() { + m = cs.exhausted } - methodMap[call.method] = append(methodMap[call.method], call) + m[key] = append(m[key], call) } // Remove removes an expected call. func (cs callSet) Remove(call *Call) { - methodMap, ok := cs[call.receiver] - if !ok { - return - } - sl := methodMap[call.method] - for i, c := range sl { + key := callSetKey{call.receiver, call.method} + calls := cs.expected[key] + for i, c := range calls { if c == call { - // quick removal; we don't need to maintain call order - if len(sl) > 1 { - sl[i] = sl[len(sl)-1] - } - methodMap[call.method] = sl[:len(sl)-1] + // maintain order for remaining calls + cs.expected[key] = append(calls[:i], calls[i+1:]...) + cs.exhausted[key] = append(cs.exhausted[key], call) break } } } -// FindMatch searches for a matching call. Returns nil if no call matched. -func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) *Call { - methodMap, ok := cs[receiver] - if !ok { - return nil - } - calls, ok := methodMap[method] - if !ok { - return nil - } +// FindMatch searches for a matching call. Returns error with explanation message if no call matched. +func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) { + key := callSetKey{receiver, method} - // Search through the unordered set of calls expected on a method on a - // receiver. - for _, call := range calls { - // A call should not normally still be here if exhausted, - // but it can happen if, for instance, .Times(0) was used. - // Pretend the call doesn't match. - if call.exhausted() { - continue + // Search through the expected calls. + expected := cs.expected[key] + var callsErrors bytes.Buffer + for _, call := range expected { + err := call.matches(args) + if err != nil { + fmt.Fprintf(&callsErrors, "\n%v", err) + } else { + return call, nil } - if call.matches(args) { - return call + } + + // If we haven't found a match then search through the exhausted calls so we + // get useful error messages. + exhausted := cs.exhausted[key] + for _, call := range exhausted { + if err := call.matches(args); err != nil { + fmt.Fprintf(&callsErrors, "\n%v", err) } } - return nil + if len(expected)+len(exhausted) == 0 { + fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method) + } + + return nil, fmt.Errorf(callsErrors.String()) +} + +// Failures returns the calls that are not satisfied. +func (cs callSet) Failures() []*Call { + failures := make([]*Call, 0, len(cs.expected)) + for _, calls := range cs.expected { + for _, call := range calls { + if !call.satisfied() { + failures = append(failures, call) + } + } + } + return failures } diff --git a/vendor/github.com/golang/mock/gomock/callset_test.go b/vendor/github.com/golang/mock/gomock/callset_test.go new file mode 100644 index 0000000..7fc711a --- /dev/null +++ b/vendor/github.com/golang/mock/gomock/callset_test.go @@ -0,0 +1,76 @@ +// Copyright 2011 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gomock + +import ( + "reflect" + "testing" +) + +type receiverType struct{} + +func (receiverType) Func() {} + +func TestCallSetAdd(t *testing.T) { + method := "TestMethod" + var receiver interface{} = "TestReceiver" + cs := newCallSet() + + numCalls := 10 + for i := 0; i < numCalls; i++ { + cs.Add(newCall(t, receiver, method, reflect.TypeOf(receiverType{}.Func))) + } + + call, err := cs.FindMatch(receiver, method, []interface{}{}) + if err != nil { + t.Fatalf("FindMatch: %v", err) + } + if call == nil { + t.Fatalf("FindMatch: Got nil, want non-nil *Call") + } +} + +func TestCallSetRemove(t *testing.T) { + method := "TestMethod" + var receiver interface{} = "TestReceiver" + + cs := newCallSet() + ourCalls := []*Call{} + + numCalls := 10 + for i := 0; i < numCalls; i++ { + // NOTE: abuse the `numCalls` value to convey initial ordering of mocked calls + generatedCall := &Call{receiver: receiver, method: method, numCalls: i} + cs.Add(generatedCall) + ourCalls = append(ourCalls, generatedCall) + } + + // validateOrder validates that the calls in the array are ordered as they were added + validateOrder := func(calls []*Call) { + // lastNum tracks the last `numCalls` (call order) value seen + lastNum := -1 + for _, c := range calls { + if lastNum >= c.numCalls { + t.Errorf("found call %d after call %d", c.numCalls, lastNum) + } + lastNum = c.numCalls + } + } + + for _, c := range ourCalls { + validateOrder(cs.expected[callSetKey{receiver, method}]) + cs.Remove(c) + } +} diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go index 6bff78d..a7b7918 100644 --- a/vendor/github.com/golang/mock/gomock/controller.go +++ b/vendor/github.com/golang/mock/gomock/controller.go @@ -57,7 +57,9 @@ package gomock import ( "fmt" + "golang.org/x/net/context" "reflect" + "runtime" "sync" ) @@ -74,17 +76,40 @@ type TestReporter interface { type Controller struct { mu sync.Mutex t TestReporter - expectedCalls callSet + expectedCalls *callSet + finished bool } func NewController(t TestReporter) *Controller { return &Controller{ t: t, - expectedCalls: make(callSet), + expectedCalls: newCallSet(), } } +type cancelReporter struct { + t TestReporter + cancel func() +} + +func (r *cancelReporter) Errorf(format string, args ...interface{}) { r.t.Errorf(format, args...) } +func (r *cancelReporter) Fatalf(format string, args ...interface{}) { + defer r.cancel() + r.t.Fatalf(format, args...) +} + +// WithContext returns a new Controller and a Context, which is cancelled on any +// fatal failure. +func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) { + ctx, cancel := context.WithCancel(ctx) + return NewController(&cancelReporter{t, cancel}), ctx +} + func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call { + if h, ok := ctrl.t.(testHelper); ok { + h.Helper() + } + recv := reflect.ValueOf(receiver) for i := 0; i < recv.Type().NumMethod(); i++ { if recv.Type().Method(i).Name == method { @@ -92,73 +117,77 @@ func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ... } } ctrl.t.Fatalf("gomock: failed finding method %s on %T", method, receiver) - // In case t.Fatalf does not panic. - panic(fmt.Sprintf("gomock: failed finding method %s on %T", method, receiver)) + panic("unreachable") } func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call { - // TODO: check arity, types. - margs := make([]Matcher, len(args)) - for i, arg := range args { - if m, ok := arg.(Matcher); ok { - margs[i] = m - } else if arg == nil { - // Handle nil specially so that passing a nil interface value - // will match the typed nils of concrete args. - margs[i] = Nil() - } else { - margs[i] = Eq(arg) - } + if h, ok := ctrl.t.(testHelper); ok { + h.Helper() } + call := newCall(ctrl.t, receiver, method, methodType, args...) + ctrl.mu.Lock() defer ctrl.mu.Unlock() - - call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, minCalls: 1, maxCalls: 1} - ctrl.expectedCalls.Add(call) + return call } func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - - expected := ctrl.expectedCalls.FindMatch(receiver, method, args) - if expected == nil { - ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args) + if h, ok := ctrl.t.(testHelper); ok { + h.Helper() } - // Two things happen here: - // * the matching call no longer needs to check prerequite calls, - // * and the prerequite calls are no longer expected, so remove them. - preReqCalls := expected.dropPrereqs() - for _, preReqCall := range preReqCalls { - ctrl.expectedCalls.Remove(preReqCall) - } + // Nest this code so we can use defer to make sure the lock is released. + actions := func() []func([]interface{}) []interface{} { + ctrl.mu.Lock() + defer ctrl.mu.Unlock() - rets, action := expected.call(args) - if expected.exhausted() { - ctrl.expectedCalls.Remove(expected) - } + expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args) + if err != nil { + origin := callerInfo(2) + ctrl.t.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err) + } - // Don't hold the lock while doing the call's action (if any) - // so that actions may execute concurrently. - // We use the deferred Unlock to capture any panics that happen above; - // here we add a deferred Lock to balance it. - ctrl.mu.Unlock() - defer ctrl.mu.Lock() - if action != nil { - action() + // Two things happen here: + // * the matching call no longer needs to check prerequite calls, + // * and the prerequite calls are no longer expected, so remove them. + preReqCalls := expected.dropPrereqs() + for _, preReqCall := range preReqCalls { + ctrl.expectedCalls.Remove(preReqCall) + } + + actions := expected.call(args) + if expected.exhausted() { + ctrl.expectedCalls.Remove(expected) + } + return actions + }() + + var rets []interface{} + for _, action := range actions { + if r := action(args); r != nil { + rets = r + } } return rets } func (ctrl *Controller) Finish() { + if h, ok := ctrl.t.(testHelper); ok { + h.Helper() + } + ctrl.mu.Lock() defer ctrl.mu.Unlock() + if ctrl.finished { + ctrl.t.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.") + } + ctrl.finished = true + // If we're currently panicking, probably because this is a deferred call, // pass through the panic. if err := recover(); err != nil { @@ -166,18 +195,23 @@ func (ctrl *Controller) Finish() { } // Check that all remaining expected calls are satisfied. - failures := false - for _, methodMap := range ctrl.expectedCalls { - for _, calls := range methodMap { - for _, call := range calls { - if !call.satisfied() { - ctrl.t.Errorf("missing call(s) to %v", call) - failures = true - } - } - } + failures := ctrl.expectedCalls.Failures() + for _, call := range failures { + ctrl.t.Errorf("missing call(s) to %v", call) } - if failures { + if len(failures) != 0 { ctrl.t.Fatalf("aborting test due to missing call(s)") } } + +func callerInfo(skip int) string { + if _, file, line, ok := runtime.Caller(skip + 1); ok { + return fmt.Sprintf("%s:%d", file, line) + } + return "unknown file" +} + +type testHelper interface { + TestReporter + Helper() +} diff --git a/vendor/github.com/golang/mock/gomock/controller_test.go b/vendor/github.com/golang/mock/gomock/controller_test.go index 57f7957..b3bb4de 100644 --- a/vendor/github.com/golang/mock/gomock/controller_test.go +++ b/vendor/github.com/golang/mock/gomock/controller_test.go @@ -19,6 +19,8 @@ import ( "reflect" "testing" + "strings" + "github.com/golang/mock/gomock" ) @@ -53,7 +55,7 @@ func (e *ErrorReporter) assertFail(msg string) { } // Use to check that code triggers a fatal test failure. -func (e *ErrorReporter) assertFatal(fn func()) { +func (e *ErrorReporter) assertFatal(fn func(), expectedErrMsgs ...string) { defer func() { err := recover() if err == nil { @@ -66,6 +68,18 @@ func (e *ErrorReporter) assertFatal(fn func()) { e.t.Error("Expected fatal failure, but got a", actual) } else if token, ok := err.(*struct{}); ok && token == &e.fatalToken { // This is okay - the panic is from Fatalf(). + if expectedErrMsgs != nil { + // assert that the actual error message + // contains expectedErrMsgs + + // check the last actualErrMsg, because the previous messages come from previous errors + actualErrMsg := e.log[len(e.log)-1] + for _, expectedErrMsg := range expectedErrMsgs { + if !strings.Contains(actualErrMsg, expectedErrMsg) { + e.t.Errorf("Error message:\ngot: %q\nwant to contain: %q\n", actualErrMsg, expectedErrMsg) + } + } + } return } else { // Some other panic. @@ -119,6 +133,20 @@ func (s *Subject) BarMethod(arg string) int { return 0 } +func (s *Subject) VariadicMethod(arg int, vararg ...string) {} + +// A type purely for ActOnTestStructMethod +type TestStruct struct { + Number int + Message string +} + +func (s *Subject) ActOnTestStructMethod(arg TestStruct, arg1 int) int { + return 0 +} + +func (s *Subject) SetArgMethod(sliceArg []byte, ptrArg *int) {} + func assertEqual(t *testing.T, expected interface{}, actual interface{}) { if !reflect.DeepEqual(expected, actual) { t.Errorf("Expected %+v, but got %+v", expected, actual) @@ -140,6 +168,31 @@ func TestNoCalls(t *testing.T) { reporter.assertPass("No calls expected or made.") } +func TestNoRecordedCallsForAReceiver(t *testing.T) { + reporter, ctrl := createFixtures(t) + subject := new(Subject) + + reporter.assertFatal(func() { + ctrl.Call(subject, "NotRecordedMethod", "argument") + }, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver") + ctrl.Finish() +} + +func TestNoRecordedMatchingMethodNameForAReceiver(t *testing.T) { + reporter, ctrl := createFixtures(t) + subject := new(Subject) + + ctrl.RecordCall(subject, "FooMethod", "argument") + reporter.assertFatal(func() { + ctrl.Call(subject, "NotRecordedMethod", "argument") + }, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver") + reporter.assertFatal(func() { + // The expected call wasn't made. + ctrl.Finish() + }) +} + +// This tests that a call with an arguments of some primitive type matches a recorded call. func TestExpectedMethodCall(t *testing.T) { reporter, ctrl := createFixtures(t) subject := new(Subject) @@ -187,11 +240,68 @@ func TestUnexpectedArgCount(t *testing.T) { reporter.assertFatal(func() { // This call is made with the wrong number of arguments... ctrl.Call(subject, "FooMethod", "argument", "extra_argument") - }) + }, "Unexpected call to", "wrong number of arguments", "Got: 2, want: 1") reporter.assertFatal(func() { // ... so is this. ctrl.Call(subject, "FooMethod") + }, "Unexpected call to", "wrong number of arguments", "Got: 0, want: 1") + reporter.assertFatal(func() { + // The expected call wasn't made. + ctrl.Finish() + }) +} + +// This tests that a call with complex arguments (a struct and some primitive type) matches a recorded call. +func TestExpectedMethodCall_CustomStruct(t *testing.T) { + reporter, ctrl := createFixtures(t) + subject := new(Subject) + + expectedArg0 := TestStruct{Number: 123, Message: "hello"} + ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15) + ctrl.Call(subject, "ActOnTestStructMethod", expectedArg0, 15) + + reporter.assertPass("Expected method call made.") +} + +func TestUnexpectedArgValue_FirstArg(t *testing.T) { + reporter, ctrl := createFixtures(t) + defer reporter.recoverUnexpectedFatal() + subject := new(Subject) + + expectedArg0 := TestStruct{Number: 123, Message: "hello"} + ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15) + + reporter.assertFatal(func() { + // the method argument (of TestStruct type) has 1 unexpected value (for the Message field) + ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "no message"}, 15) + }, "Unexpected call to", "doesn't match the argument at index 0", + "Got: {123 no message}\nWant: is equal to {123 hello}") + + reporter.assertFatal(func() { + // the method argument (of TestStruct type) has 2 unexpected values (for both fields) + ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 11, Message: "no message"}, 15) + }, "Unexpected call to", "doesn't match the argument at index 0", + "Got: {11 no message}\nWant: is equal to {123 hello}") + + reporter.assertFatal(func() { + // The expected call wasn't made. + ctrl.Finish() }) +} + +func TestUnexpectedArgValue_SecondtArg(t *testing.T) { + reporter, ctrl := createFixtures(t) + defer reporter.recoverUnexpectedFatal() + subject := new(Subject) + + expectedArg0 := TestStruct{Number: 123, Message: "hello"} + ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15) + + reporter.assertFatal(func() { + ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3) + }, "Unexpected call to", "doesn't match the argument at index 1", + "Got: 3\nWant: is equal to 15") + reporter.assertFatal(func() { // The expected call wasn't made. ctrl.Finish() @@ -317,6 +427,74 @@ func TestDo(t *testing.T) { ctrl.Finish() } +func TestDoAndReturn(t *testing.T) { + _, ctrl := createFixtures(t) + subject := new(Subject) + + doCalled := false + var argument string + ctrl.RecordCall(subject, "FooMethod", "argument").DoAndReturn( + func(arg string) int { + doCalled = true + argument = arg + return 5 + }) + if doCalled { + t.Error("Do() callback called too early.") + } + + rets := ctrl.Call(subject, "FooMethod", "argument") + + if !doCalled { + t.Error("Do() callback not called.") + } + if "argument" != argument { + t.Error("Do callback received wrong argument.") + } + if len(rets) != 1 { + t.Fatalf("Return values from Call: got %d, want 1", len(rets)) + } + if ret, ok := rets[0].(int); !ok { + t.Fatalf("Return value is not an int") + } else if ret != 5 { + t.Errorf("DoAndReturn return value: got %d, want 5", ret) + } + + ctrl.Finish() +} + +func TestSetArgSlice(t *testing.T) { + _, ctrl := createFixtures(t) + subject := new(Subject) + + var in = []byte{4, 5, 6} + var set = []byte{1, 2, 3} + ctrl.RecordCall(subject, "SetArgMethod", in, nil).SetArg(0, set) + ctrl.Call(subject, "SetArgMethod", in, nil) + + if !reflect.DeepEqual(in, set) { + t.Error("Expected SetArg() to modify input slice argument") + } + + ctrl.Finish() +} + +func TestSetArgPtr(t *testing.T) { + _, ctrl := createFixtures(t) + subject := new(Subject) + + var in int = 43 + const set = 42 + ctrl.RecordCall(subject, "SetArgMethod", nil, &in).SetArg(1, set) + ctrl.Call(subject, "SetArgMethod", nil, &in) + + if in != set { + t.Error("Expected SetArg() to modify value pointed to by argument") + } + + ctrl.Finish() +} + func TestReturn(t *testing.T) { _, ctrl := createFixtures(t) subject := new(Subject) @@ -393,11 +571,12 @@ func TestOrderedCallsInCorrect(t *testing.T) { ctrl.Call(subjectOne, "FooMethod", "1") reporter.assertFatal(func() { + // FooMethod(2) should be called before BarMethod(3) ctrl.Call(subjectTwo, "BarMethod", "3") - }) + }, "Unexpected call to", "Subject.BarMethod([3])", "doesn't have a prerequisite call satisfied") } -// Test that calls that are prerequites to other calls but have maxCalls > +// Test that calls that are prerequisites to other calls but have maxCalls > // minCalls are removed from the expected call set. func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) { reporter, ctrl, subjectOne, subjectTwo := commonTestOrderedCalls(t) @@ -473,3 +652,61 @@ func TestTimes0(t *testing.T) { ctrl.Call(s, "FooMethod", "arg") }) } + +func TestVariadicMatching(t *testing.T) { + rep, ctrl := createFixtures(t) + defer rep.recoverUnexpectedFatal() + + s := new(Subject) + ctrl.RecordCall(s, "VariadicMethod", 0, "1", "2") + ctrl.Call(s, "VariadicMethod", 0, "1", "2") + ctrl.Finish() + rep.assertPass("variadic matching works") +} + +func TestVariadicNoMatch(t *testing.T) { + rep, ctrl := createFixtures(t) + defer rep.recoverUnexpectedFatal() + + s := new(Subject) + ctrl.RecordCall(s, "VariadicMethod", 0) + rep.assertFatal(func() { + ctrl.Call(s, "VariadicMethod", 1) + }, "Expected call at", "doesn't match the argument at index 0", + "Got: 1\nWant: is equal to 0") + ctrl.Call(s, "VariadicMethod", 0) + ctrl.Finish() +} + +func TestVariadicMatchingWithSlice(t *testing.T) { + testCases := [][]string{ + {"1"}, + {"1", "2"}, + } + for _, tc := range testCases { + t.Run(fmt.Sprintf("%d arguments", len(tc)), func(t *testing.T) { + rep, ctrl := createFixtures(t) + defer rep.recoverUnexpectedFatal() + + s := new(Subject) + ctrl.RecordCall(s, "VariadicMethod", 1, tc) + args := make([]interface{}, len(tc)+1) + args[0] = 1 + for i, arg := range tc { + args[i+1] = arg + } + ctrl.Call(s, "VariadicMethod", args...) + ctrl.Finish() + rep.assertPass("slices can be used as matchers for variadic arguments") + }) + } +} + +func TestDuplicateFinishCallFails(t *testing.T) { + rep, ctrl := createFixtures(t) + + ctrl.Finish() + rep.assertPass("the first Finish call should succeed") + + rep.assertFatal(ctrl.Finish, "Controller.Finish was called more than once. It has to be called exactly once.") +} diff --git a/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go b/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go new file mode 100644 index 0000000..7e4b4c8 --- /dev/null +++ b/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go @@ -0,0 +1,57 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/golang/mock/gomock (interfaces: Matcher) + +// Package mock_gomock is a generated GoMock package. +package mock_gomock + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockMatcher is a mock of Matcher interface +type MockMatcher struct { + ctrl *gomock.Controller + recorder *MockMatcherMockRecorder +} + +// MockMatcherMockRecorder is the mock recorder for MockMatcher +type MockMatcherMockRecorder struct { + mock *MockMatcher +} + +// NewMockMatcher creates a new mock instance +func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher { + mock := &MockMatcher{ctrl: ctrl} + mock.recorder = &MockMatcherMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockMatcher) EXPECT() *MockMatcherMockRecorder { + return m.recorder +} + +// Matches mocks base method +func (m *MockMatcher) Matches(arg0 interface{}) bool { + ret := m.ctrl.Call(m, "Matches", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// Matches indicates an expected call of Matches +func (mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0) +} + +// String mocks base method +func (m *MockMatcher) String() string { + ret := m.ctrl.Call(m, "String") + ret0, _ := ret[0].(string) + return ret0 +} + +// String indicates an expected call of String +func (mr *MockMatcherMockRecorder) String() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String)) +} -- cgit v1.2.3