vinokuma | f7605fc | 2023-06-02 18:08:01 +0530 | [diff] [blame] | 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 |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "reflect" |
| 20 | "strconv" |
| 21 | "strings" |
| 22 | ) |
| 23 | |
| 24 | // Call represents an expected call to a mock. |
| 25 | type 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. |
| 49 | func 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 |
| 80 | func (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. |
| 87 | func (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. |
| 97 | func (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. |
| 108 | func (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. |
| 137 | func (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. |
| 159 | func (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. |
| 199 | func (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. |
| 207 | func (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. |
| 250 | func (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. |
| 260 | func (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. |
| 275 | func (c *Call) satisfied() bool { |
| 276 | return c.numCalls >= c.minCalls |
| 277 | } |
| 278 | |
| 279 | // Returns true if the maximum number of calls have been made. |
| 280 | func (c *Call) exhausted() bool { |
| 281 | return c.numCalls >= c.maxCalls |
| 282 | } |
| 283 | |
| 284 | func (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. |
| 295 | func (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. |
| 400 | func (c *Call) dropPrereqs() (preReqs []*Call) { |
| 401 | preReqs = c.preReqs |
| 402 | c.preReqs = nil |
| 403 | return |
| 404 | } |
| 405 | |
| 406 | func (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. |
| 412 | func InOrder(calls ...*Call) { |
| 413 | for i := 1; i < len(calls); i++ { |
| 414 | calls[i].After(calls[i-1]) |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | func 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 | |
| 425 | func (c *Call) addAction(action func([]interface{}) []interface{}) { |
| 426 | c.actions = append(c.actions, action) |
| 427 | } |