1// Copyright 2010 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package gomock is a mock framework for Go.
16//
17// Standard usage:
18//   (1) Define an interface that you wish to mock.
19//         type MyInterface interface {
20//           SomeMethod(x int64, y string)
21//         }
22//   (2) Use mockgen to generate a mock from the interface.
23//   (3) Use the mock in a test:
24//         func TestMyThing(t *testing.T) {
25//           mockCtrl := gomock.NewController(t)
26//           defer mockCtrl.Finish()
27//
28//           mockObj := something.NewMockMyInterface(mockCtrl)
29//           mockObj.EXPECT().SomeMethod(4, "blah")
30//           // pass mockObj to a real object and play with it.
31//         }
32//
33// By default, expected calls are not enforced to run in any particular order.
34// Call order dependency can be enforced by use of InOrder and/or Call.After.
35// Call.After can create more varied call order dependencies, but InOrder is
36// often more convenient.
37//
38// The following examples create equivalent call order dependencies.
39//
40// Example of using Call.After to chain expected call order:
41//
42//     firstCall := mockObj.EXPECT().SomeMethod(1, "first")
43//     secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
44//     mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
45//
46// Example of using InOrder to declare expected call order:
47//
48//     gomock.InOrder(
49//         mockObj.EXPECT().SomeMethod(1, "first"),
50//         mockObj.EXPECT().SomeMethod(2, "second"),
51//         mockObj.EXPECT().SomeMethod(3, "third"),
52//     )
53package gomock
54
55import (
56	"context"
57	"fmt"
58	"reflect"
59	"runtime"
60	"sync"
61)
62
63// A TestReporter is something that can be used to report test failures.  It
64// is satisfied by the standard library's *testing.T.
65type TestReporter interface {
66	Errorf(format string, args ...interface{})
67	Fatalf(format string, args ...interface{})
68}
69
70// TestHelper is a TestReporter that has the Helper method.  It is satisfied
71// by the standard library's *testing.T.
72type TestHelper interface {
73	TestReporter
74	Helper()
75}
76
77// cleanuper is used to check if TestHelper also has the `Cleanup` method. A
78// common pattern is to pass in a `*testing.T` to
79// `NewController(t TestReporter)`. In Go 1.14+, `*testing.T` has a cleanup
80// method. This can be utilized to call `Finish()` so the caller of this library
81// does not have to.
82type cleanuper interface {
83	Cleanup(func())
84}
85
86// A Controller represents the top-level control of a mock ecosystem.  It
87// defines the scope and lifetime of mock objects, as well as their
88// expectations.  It is safe to call Controller's methods from multiple
89// goroutines. Each test should create a new Controller and invoke Finish via
90// defer.
91//
92//   func TestFoo(t *testing.T) {
93//     ctrl := gomock.NewController(t)
94//     defer ctrl.Finish()
95//     // ..
96//   }
97//
98//   func TestBar(t *testing.T) {
99//     t.Run("Sub-Test-1", st) {
100//       ctrl := gomock.NewController(st)
101//       defer ctrl.Finish()
102//       // ..
103//     })
104//     t.Run("Sub-Test-2", st) {
105//       ctrl := gomock.NewController(st)
106//       defer ctrl.Finish()
107//       // ..
108//     })
109//   })
110type Controller struct {
111	// T should only be called within a generated mock. It is not intended to
112	// be used in user code and may be changed in future versions. T is the
113	// TestReporter passed in when creating the Controller via NewController.
114	// If the TestReporter does not implement a TestHelper it will be wrapped
115	// with a nopTestHelper.
116	T             TestHelper
117	mu            sync.Mutex
118	expectedCalls *callSet
119	finished      bool
120}
121
122// NewController returns a new Controller. It is the preferred way to create a
123// Controller.
124//
125// New in go1.14+, if you are passing a *testing.T into this function you no
126// longer need to call ctrl.Finish() in your test methods.
127func NewController(t TestReporter) *Controller {
128	h, ok := t.(TestHelper)
129	if !ok {
130		h = &nopTestHelper{t}
131	}
132	ctrl := &Controller{
133		T:             h,
134		expectedCalls: newCallSet(),
135	}
136	if c, ok := isCleanuper(ctrl.T); ok {
137		c.Cleanup(func() {
138			ctrl.T.Helper()
139			ctrl.finish(true, nil)
140		})
141	}
142
143	return ctrl
144}
145
146type cancelReporter struct {
147	t      TestHelper
148	cancel func()
149}
150
151func (r *cancelReporter) Errorf(format string, args ...interface{}) {
152	r.t.Errorf(format, args...)
153}
154func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
155	defer r.cancel()
156	r.t.Fatalf(format, args...)
157}
158
159func (r *cancelReporter) Helper() {
160	r.t.Helper()
161}
162
163// WithContext returns a new Controller and a Context, which is cancelled on any
164// fatal failure.
165func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
166	h, ok := t.(TestHelper)
167	if !ok {
168		h = &nopTestHelper{t: t}
169	}
170
171	ctx, cancel := context.WithCancel(ctx)
172	return NewController(&cancelReporter{t: h, cancel: cancel}), ctx
173}
174
175type nopTestHelper struct {
176	t TestReporter
177}
178
179func (h *nopTestHelper) Errorf(format string, args ...interface{}) {
180	h.t.Errorf(format, args...)
181}
182func (h *nopTestHelper) Fatalf(format string, args ...interface{}) {
183	h.t.Fatalf(format, args...)
184}
185
186func (h nopTestHelper) Helper() {}
187
188// RecordCall is called by a mock. It should not be called by user code.
189func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
190	ctrl.T.Helper()
191
192	recv := reflect.ValueOf(receiver)
193	for i := 0; i < recv.Type().NumMethod(); i++ {
194		if recv.Type().Method(i).Name == method {
195			return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
196		}
197	}
198	ctrl.T.Fatalf("gomock: failed finding method %s on %T", method, receiver)
199	panic("unreachable")
200}
201
202// RecordCallWithMethodType is called by a mock. It should not be called by user code.
203func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
204	ctrl.T.Helper()
205
206	call := newCall(ctrl.T, receiver, method, methodType, args...)
207
208	ctrl.mu.Lock()
209	defer ctrl.mu.Unlock()
210	ctrl.expectedCalls.Add(call)
211
212	return call
213}
214
215// Call is called by a mock. It should not be called by user code.
216func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
217	ctrl.T.Helper()
218
219	// Nest this code so we can use defer to make sure the lock is released.
220	actions := func() []func([]interface{}) []interface{} {
221		ctrl.T.Helper()
222		ctrl.mu.Lock()
223		defer ctrl.mu.Unlock()
224
225		expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
226		if err != nil {
227			// callerInfo's skip should be updated if the number of calls between the user's test
228			// and this line changes, i.e. this code is wrapped in another anonymous function.
229			// 0 is us, 1 is controller.Call(), 2 is the generated mock, and 3 is the user's test.
230			origin := callerInfo(3)
231			ctrl.T.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
232		}
233
234		// Two things happen here:
235		// * the matching call no longer needs to check prerequite calls,
236		// * and the prerequite calls are no longer expected, so remove them.
237		preReqCalls := expected.dropPrereqs()
238		for _, preReqCall := range preReqCalls {
239			ctrl.expectedCalls.Remove(preReqCall)
240		}
241
242		actions := expected.call()
243		if expected.exhausted() {
244			ctrl.expectedCalls.Remove(expected)
245		}
246		return actions
247	}()
248
249	var rets []interface{}
250	for _, action := range actions {
251		if r := action(args); r != nil {
252			rets = r
253		}
254	}
255
256	return rets
257}
258
259// Finish checks to see if all the methods that were expected to be called
260// were called. It should be invoked for each Controller. It is not idempotent
261// and therefore can only be invoked once.
262//
263// New in go1.14+, if you are passing a *testing.T into NewController function you no
264// longer need to call ctrl.Finish() in your test methods.
265func (ctrl *Controller) Finish() {
266	// If we're currently panicking, probably because this is a deferred call.
267	// This must be recovered in the deferred function.
268	err := recover()
269	ctrl.finish(false, err)
270}
271
272func (ctrl *Controller) finish(cleanup bool, panicErr interface{}) {
273	ctrl.T.Helper()
274
275	ctrl.mu.Lock()
276	defer ctrl.mu.Unlock()
277
278	if ctrl.finished {
279		if _, ok := isCleanuper(ctrl.T); !ok {
280			ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.")
281		}
282		return
283	}
284	ctrl.finished = true
285
286	// Short-circuit, pass through the panic.
287	if panicErr != nil {
288		panic(panicErr)
289	}
290
291	// Check that all remaining expected calls are satisfied.
292	failures := ctrl.expectedCalls.Failures()
293	for _, call := range failures {
294		ctrl.T.Errorf("missing call(s) to %v", call)
295	}
296	if len(failures) != 0 {
297		if !cleanup {
298			ctrl.T.Fatalf("aborting test due to missing call(s)")
299			return
300		}
301		ctrl.T.Errorf("aborting test due to missing call(s)")
302	}
303}
304
305// callerInfo returns the file:line of the call site. skip is the number
306// of stack frames to skip when reporting. 0 is callerInfo's call site.
307func callerInfo(skip int) string {
308	if _, file, line, ok := runtime.Caller(skip + 1); ok {
309		return fmt.Sprintf("%s:%d", file, line)
310	}
311	return "unknown file"
312}
313
314// isCleanuper checks it if t's base TestReporter has a Cleanup method.
315func isCleanuper(t TestReporter) (cleanuper, bool) {
316	tr := unwrapTestReporter(t)
317	c, ok := tr.(cleanuper)
318	return c, ok
319}
320
321// unwrapTestReporter unwraps TestReporter to the base implementation.
322func unwrapTestReporter(t TestReporter) TestReporter {
323	tr := t
324	switch nt := t.(type) {
325	case *cancelReporter:
326		tr = nt.t
327		if h, check := tr.(*nopTestHelper); check {
328			tr = h.t
329		}
330	case *nopTestHelper:
331		tr = nt.t
332	default:
333		// not wrapped
334	}
335	return tr
336}
337