blob: 7345f6540f6a3855e4e50d618e361cea3a2e91f6 [file] [log] [blame]
vinokumaf7605fc2023-06-02 18:08:01 +05301// 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
15package gomock
16
17import (
18 "fmt"
19 "reflect"
20 "strconv"
21 "strings"
22)
23
24// Call represents an expected call to a mock.
25type Call struct {
26 t TestHelper // for triggering test failures on invalid call setup
27
28 receiver interface{} // the receiver of the method call
29 method string // the name of the method
30 methodType reflect.Type // the type of the method
31 args []Matcher // the args
32 origin string // file and line number of call setup
33
34 preReqs []*Call // prerequisite calls
35
36 // Expectations
37 minCalls, maxCalls int
38
39 numCalls int // actual number made
40
41 // actions are called when this Call is called. Each action gets the args and
42 // can set the return values by returning a non-nil slice. Actions run in the
43 // order they are created.
44 actions []func([]interface{}) []interface{}
45}
46
47// newCall creates a *Call. It requires the method type in order to support
48// unexported methods.
49func newCall(t TestHelper, receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
50 t.Helper()
51
52 // TODO: check arity, types.
53 margs := make([]Matcher, len(args))
54 for i, arg := range args {
55 if m, ok := arg.(Matcher); ok {
56 margs[i] = m
57 } else if arg == nil {
58 // Handle nil specially so that passing a nil interface value
59 // will match the typed nils of concrete args.
60 margs[i] = Nil()
61 } else {
62 margs[i] = Eq(arg)
63 }
64 }
65
66 origin := callerInfo(3)
67 actions := []func([]interface{}) []interface{}{func([]interface{}) []interface{} {
68 // Synthesize the zero value for each of the return args' types.
69 rets := make([]interface{}, methodType.NumOut())
70 for i := 0; i < methodType.NumOut(); i++ {
71 rets[i] = reflect.Zero(methodType.Out(i)).Interface()
72 }
73 return rets
74 }}
75 return &Call{t: t, receiver: receiver, method: method, methodType: methodType,
76 args: margs, origin: origin, minCalls: 1, maxCalls: 1, actions: actions}
77}
78
79// AnyTimes allows the expectation to be called 0 or more times
80func (c *Call) AnyTimes() *Call {
81 c.minCalls, c.maxCalls = 0, 1e8 // close enough to infinity
82 return c
83}
84
85// MinTimes requires the call to occur at least n times. If AnyTimes or MaxTimes have not been called or if MaxTimes
86// was previously called with 1, MinTimes also sets the maximum number of calls to infinity.
87func (c *Call) MinTimes(n int) *Call {
88 c.minCalls = n
89 if c.maxCalls == 1 {
90 c.maxCalls = 1e8
91 }
92 return c
93}
94
95// MaxTimes limits the number of calls to n times. If AnyTimes or MinTimes have not been called or if MinTimes was
96// previously called with 1, MaxTimes also sets the minimum number of calls to 0.
97func (c *Call) MaxTimes(n int) *Call {
98 c.maxCalls = n
99 if c.minCalls == 1 {
100 c.minCalls = 0
101 }
102 return c
103}
104
105// DoAndReturn declares the action to run when the call is matched.
106// The return values from this function are returned by the mocked function.
107// It takes an interface{} argument to support n-arity functions.
108func (c *Call) DoAndReturn(f interface{}) *Call {
109 // TODO: Check arity and types here, rather than dying badly elsewhere.
110 v := reflect.ValueOf(f)
111
112 c.addAction(func(args []interface{}) []interface{} {
113 vargs := make([]reflect.Value, len(args))
114 ft := v.Type()
115 for i := 0; i < len(args); i++ {
116 if args[i] != nil {
117 vargs[i] = reflect.ValueOf(args[i])
118 } else {
119 // Use the zero value for the arg.
120 vargs[i] = reflect.Zero(ft.In(i))
121 }
122 }
123 vrets := v.Call(vargs)
124 rets := make([]interface{}, len(vrets))
125 for i, ret := range vrets {
126 rets[i] = ret.Interface()
127 }
128 return rets
129 })
130 return c
131}
132
133// Do declares the action to run when the call is matched. The function's
134// return values are ignored to retain backward compatibility. To use the
135// return values call DoAndReturn.
136// It takes an interface{} argument to support n-arity functions.
137func (c *Call) Do(f interface{}) *Call {
138 // TODO: Check arity and types here, rather than dying badly elsewhere.
139 v := reflect.ValueOf(f)
140
141 c.addAction(func(args []interface{}) []interface{} {
142 vargs := make([]reflect.Value, len(args))
143 ft := v.Type()
144 for i := 0; i < len(args); i++ {
145 if args[i] != nil {
146 vargs[i] = reflect.ValueOf(args[i])
147 } else {
148 // Use the zero value for the arg.
149 vargs[i] = reflect.Zero(ft.In(i))
150 }
151 }
152 v.Call(vargs)
153 return nil
154 })
155 return c
156}
157
158// Return declares the values to be returned by the mocked function call.
159func (c *Call) Return(rets ...interface{}) *Call {
160 c.t.Helper()
161
162 mt := c.methodType
163 if len(rets) != mt.NumOut() {
164 c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
165 c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
166 }
167 for i, ret := range rets {
168 if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
169 // Identical types; nothing to do.
170 } else if got == nil {
171 // Nil needs special handling.
172 switch want.Kind() {
173 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
174 // ok
175 default:
176 c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
177 i, c.receiver, c.method, want, c.origin)
178 }
179 } else if got.AssignableTo(want) {
180 // Assignable type relation. Make the assignment now so that the generated code
181 // can return the values with a type assertion.
182 v := reflect.New(want).Elem()
183 v.Set(reflect.ValueOf(ret))
184 rets[i] = v.Interface()
185 } else {
186 c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
187 i, c.receiver, c.method, got, want, c.origin)
188 }
189 }
190
191 c.addAction(func([]interface{}) []interface{} {
192 return rets
193 })
194
195 return c
196}
197
198// Times declares the exact number of times a function call is expected to be executed.
199func (c *Call) Times(n int) *Call {
200 c.minCalls, c.maxCalls = n, n
201 return c
202}
203
204// SetArg declares an action that will set the nth argument's value,
205// indirected through a pointer. Or, in the case of a slice, SetArg
206// will copy value's elements into the nth argument.
207func (c *Call) SetArg(n int, value interface{}) *Call {
208 c.t.Helper()
209
210 mt := c.methodType
211 // TODO: This will break on variadic methods.
212 // We will need to check those at invocation time.
213 if n < 0 || n >= mt.NumIn() {
214 c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
215 n, mt.NumIn(), c.origin)
216 }
217 // Permit setting argument through an interface.
218 // In the interface case, we don't (nay, can't) check the type here.
219 at := mt.In(n)
220 switch at.Kind() {
221 case reflect.Ptr:
222 dt := at.Elem()
223 if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
224 c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
225 n, vt, dt, c.origin)
226 }
227 case reflect.Interface:
228 // nothing to do
229 case reflect.Slice:
230 // nothing to do
231 default:
232 c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
233 n, at, c.origin)
234 }
235
236 c.addAction(func(args []interface{}) []interface{} {
237 v := reflect.ValueOf(value)
238 switch reflect.TypeOf(args[n]).Kind() {
239 case reflect.Slice:
240 setSlice(args[n], v)
241 default:
242 reflect.ValueOf(args[n]).Elem().Set(v)
243 }
244 return nil
245 })
246 return c
247}
248
249// isPreReq returns true if other is a direct or indirect prerequisite to c.
250func (c *Call) isPreReq(other *Call) bool {
251 for _, preReq := range c.preReqs {
252 if other == preReq || preReq.isPreReq(other) {
253 return true
254 }
255 }
256 return false
257}
258
259// After declares that the call may only match after preReq has been exhausted.
260func (c *Call) After(preReq *Call) *Call {
261 c.t.Helper()
262
263 if c == preReq {
264 c.t.Fatalf("A call isn't allowed to be its own prerequisite")
265 }
266 if preReq.isPreReq(c) {
267 c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
268 }
269
270 c.preReqs = append(c.preReqs, preReq)
271 return c
272}
273
274// Returns true if the minimum number of calls have been made.
275func (c *Call) satisfied() bool {
276 return c.numCalls >= c.minCalls
277}
278
279// Returns true if the maximum number of calls have been made.
280func (c *Call) exhausted() bool {
281 return c.numCalls >= c.maxCalls
282}
283
284func (c *Call) String() string {
285 args := make([]string, len(c.args))
286 for i, arg := range c.args {
287 args[i] = arg.String()
288 }
289 arguments := strings.Join(args, ", ")
290 return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
291}
292
293// Tests if the given call matches the expected call.
294// If yes, returns nil. If no, returns error with message explaining why it does not match.
295func (c *Call) matches(args []interface{}) error {
296 if !c.methodType.IsVariadic() {
297 if len(args) != len(c.args) {
298 return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
299 c.origin, len(args), len(c.args))
300 }
301
302 for i, m := range c.args {
303 if !m.Matches(args[i]) {
304 got := fmt.Sprintf("%v", args[i])
305 if gs, ok := m.(GotFormatter); ok {
306 got = gs.Got(args[i])
307 }
308
309 return fmt.Errorf(
310 "expected call at %s doesn't match the argument at index %d.\nGot: %v\nWant: %v",
311 c.origin, i, got, m,
312 )
313 }
314 }
315 } else {
316 if len(c.args) < c.methodType.NumIn()-1 {
317 return fmt.Errorf("expected call at %s has the wrong number of matchers. Got: %d, want: %d",
318 c.origin, len(c.args), c.methodType.NumIn()-1)
319 }
320 if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
321 return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
322 c.origin, len(args), len(c.args))
323 }
324 if len(args) < len(c.args)-1 {
325 return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
326 c.origin, len(args), len(c.args)-1)
327 }
328
329 for i, m := range c.args {
330 if i < c.methodType.NumIn()-1 {
331 // Non-variadic args
332 if !m.Matches(args[i]) {
333 return fmt.Errorf("expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
334 c.origin, strconv.Itoa(i), args[i], m)
335 }
336 continue
337 }
338 // The last arg has a possibility of a variadic argument, so let it branch
339
340 // sample: Foo(a int, b int, c ...int)
341 if i < len(c.args) && i < len(args) {
342 if m.Matches(args[i]) {
343 // Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
344 // Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
345 // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
346 // Got Foo(a, b) want Foo(matcherA, matcherB)
347 // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
348 continue
349 }
350 }
351
352 // The number of actual args don't match the number of matchers,
353 // or the last matcher is a slice and the last arg is not.
354 // If this function still matches it is because the last matcher
355 // matches all the remaining arguments or the lack of any.
356 // Convert the remaining arguments, if any, into a slice of the
357 // expected type.
358 vargsType := c.methodType.In(c.methodType.NumIn() - 1)
359 vargs := reflect.MakeSlice(vargsType, 0, len(args)-i)
360 for _, arg := range args[i:] {
361 vargs = reflect.Append(vargs, reflect.ValueOf(arg))
362 }
363 if m.Matches(vargs.Interface()) {
364 // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
365 // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
366 // Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
367 // Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
368 break
369 }
370 // Wrong number of matchers or not match. Fail.
371 // Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
372 // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
373 // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
374 // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
375 // Got Foo(a, b, c) want Foo(matcherA, matcherB)
376 return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
377 c.origin, strconv.Itoa(i), args[i:], c.args[i])
378
379 }
380 }
381
382 // Check that all prerequisite calls have been satisfied.
383 for _, preReqCall := range c.preReqs {
384 if !preReqCall.satisfied() {
385 return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
386 c.origin, preReqCall, c)
387 }
388 }
389
390 // Check that the call is not exhausted.
391 if c.exhausted() {
392 return fmt.Errorf("expected call at %s has already been called the max number of times", c.origin)
393 }
394
395 return nil
396}
397
398// dropPrereqs tells the expected Call to not re-check prerequisite calls any
399// longer, and to return its current set.
400func (c *Call) dropPrereqs() (preReqs []*Call) {
401 preReqs = c.preReqs
402 c.preReqs = nil
403 return
404}
405
406func (c *Call) call() []func([]interface{}) []interface{} {
407 c.numCalls++
408 return c.actions
409}
410
411// InOrder declares that the given calls should occur in order.
412func InOrder(calls ...*Call) {
413 for i := 1; i < len(calls); i++ {
414 calls[i].After(calls[i-1])
415 }
416}
417
418func setSlice(arg interface{}, v reflect.Value) {
419 va := reflect.ValueOf(arg)
420 for i := 0; i < v.Len(); i++ {
421 va.Index(i).Set(v.Index(i))
422 }
423}
424
425func (c *Call) addAction(action func([]interface{}) []interface{}) {
426 c.actions = append(c.actions, action)
427}