summaryrefslogtreecommitdiff
path: root/vendor/github.com/golang/mock/gomock/controller.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/golang/mock/gomock/controller.go')
-rw-r--r--vendor/github.com/golang/mock/gomock/controller.go183
1 files changed, 183 insertions, 0 deletions
diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go
new file mode 100644
index 0000000..6bff78d
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/controller.go
@@ -0,0 +1,183 @@
+// Copyright 2010 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.
+
+// GoMock - a mock framework for Go.
+//
+// Standard usage:
+// (1) Define an interface that you wish to mock.
+// type MyInterface interface {
+// SomeMethod(x int64, y string)
+// }
+// (2) Use mockgen to generate a mock from the interface.
+// (3) Use the mock in a test:
+// func TestMyThing(t *testing.T) {
+// mockCtrl := gomock.NewController(t)
+// defer mockCtrl.Finish()
+//
+// mockObj := something.NewMockMyInterface(mockCtrl)
+// mockObj.EXPECT().SomeMethod(4, "blah")
+// // pass mockObj to a real object and play with it.
+// }
+//
+// By default, expected calls are not enforced to run in any particular order.
+// Call order dependency can be enforced by use of InOrder and/or Call.After.
+// Call.After can create more varied call order dependencies, but InOrder is
+// often more convenient.
+//
+// The following examples create equivalent call order dependencies.
+//
+// Example of using Call.After to chain expected call order:
+//
+// firstCall := mockObj.EXPECT().SomeMethod(1, "first")
+// secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
+// mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
+//
+// Example of using InOrder to declare expected call order:
+//
+// gomock.InOrder(
+// mockObj.EXPECT().SomeMethod(1, "first"),
+// mockObj.EXPECT().SomeMethod(2, "second"),
+// mockObj.EXPECT().SomeMethod(3, "third"),
+// )
+//
+// TODO:
+// - Handle different argument/return types (e.g. ..., chan, map, interface).
+package gomock
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+)
+
+// A TestReporter is something that can be used to report test failures.
+// It is satisfied by the standard library's *testing.T.
+type TestReporter interface {
+ Errorf(format string, args ...interface{})
+ Fatalf(format string, args ...interface{})
+}
+
+// A Controller represents the top-level control of a mock ecosystem.
+// It defines the scope and lifetime of mock objects, as well as their expectations.
+// It is safe to call Controller's methods from multiple goroutines.
+type Controller struct {
+ mu sync.Mutex
+ t TestReporter
+ expectedCalls callSet
+}
+
+func NewController(t TestReporter) *Controller {
+ return &Controller{
+ t: t,
+ expectedCalls: make(callSet),
+ }
+}
+
+func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
+ recv := reflect.ValueOf(receiver)
+ for i := 0; i < recv.Type().NumMethod(); i++ {
+ if recv.Type().Method(i).Name == method {
+ return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), 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))
+}
+
+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)
+ }
+ }
+
+ 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)
+ }
+
+ // 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)
+ }
+
+ rets, action := expected.call(args)
+ if expected.exhausted() {
+ ctrl.expectedCalls.Remove(expected)
+ }
+
+ // 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()
+ }
+
+ return rets
+}
+
+func (ctrl *Controller) Finish() {
+ ctrl.mu.Lock()
+ defer ctrl.mu.Unlock()
+
+ // If we're currently panicking, probably because this is a deferred call,
+ // pass through the panic.
+ if err := recover(); err != nil {
+ panic(err)
+ }
+
+ // 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
+ }
+ }
+ }
+ }
+ if failures {
+ ctrl.t.Fatalf("aborting test due to missing call(s)")
+ }
+}