blob: e4e85d602f89bf3a3a424a39889799f72bd5b7a2 [file] [log] [blame]
ssiddiquif076cb82021-04-23 10:47:04 +05301// Copyright 2011 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 "bytes"
19 "fmt"
20)
21
22// callSet represents a set of expected calls, indexed by receiver and method
23// name.
24type callSet struct {
25 // Calls that are still expected.
26 expected map[callSetKey][]*Call
27 // Calls that have been exhausted.
28 exhausted map[callSetKey][]*Call
29}
30
31// callSetKey is the key in the maps in callSet
32type callSetKey struct {
33 receiver interface{}
34 fname string
35}
36
37func newCallSet() *callSet {
38 return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)}
39}
40
41// Add adds a new expected call.
42func (cs callSet) Add(call *Call) {
43 key := callSetKey{call.receiver, call.method}
44 m := cs.expected
45 if call.exhausted() {
46 m = cs.exhausted
47 }
48 m[key] = append(m[key], call)
49}
50
51// Remove removes an expected call.
52func (cs callSet) Remove(call *Call) {
53 key := callSetKey{call.receiver, call.method}
54 calls := cs.expected[key]
55 for i, c := range calls {
56 if c == call {
57 // maintain order for remaining calls
58 cs.expected[key] = append(calls[:i], calls[i+1:]...)
59 cs.exhausted[key] = append(cs.exhausted[key], call)
60 break
61 }
62 }
63}
64
65// FindMatch searches for a matching call. Returns error with explanation message if no call matched.
66func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) {
67 key := callSetKey{receiver, method}
68
69 // Search through the expected calls.
70 expected := cs.expected[key]
71 var callsErrors bytes.Buffer
72 for _, call := range expected {
73 err := call.matches(args)
74 if err != nil {
75 _, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
76 } else {
77 return call, nil
78 }
79 }
80
81 // If we haven't found a match then search through the exhausted calls so we
82 // get useful error messages.
83 exhausted := cs.exhausted[key]
84 for _, call := range exhausted {
85 if err := call.matches(args); err != nil {
86 _, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
87 continue
88 }
89 _, _ = fmt.Fprintf(
90 &callsErrors, "all expected calls for method %q have been exhausted", method,
91 )
92 }
93
94 if len(expected)+len(exhausted) == 0 {
95 _, _ = fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
96 }
97
98 return nil, fmt.Errorf(callsErrors.String())
99}
100
101// Failures returns the calls that are not satisfied.
102func (cs callSet) Failures() []*Call {
103 failures := make([]*Call, 0, len(cs.expected))
104 for _, calls := range cs.expected {
105 for _, call := range calls {
106 if !call.satisfied() {
107 failures = append(failures, call)
108 }
109 }
110 }
111 return failures
112}