You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

265 lines
7.8 KiB

  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. // Package gomock is a mock framework for Go.
  15. //
  16. // Standard usage:
  17. // (1) Define an interface that you wish to mock.
  18. // type MyInterface interface {
  19. // SomeMethod(x int64, y string)
  20. // }
  21. // (2) Use mockgen to generate a mock from the interface.
  22. // (3) Use the mock in a test:
  23. // func TestMyThing(t *testing.T) {
  24. // mockCtrl := gomock.NewController(t)
  25. // defer mockCtrl.Finish()
  26. //
  27. // mockObj := something.NewMockMyInterface(mockCtrl)
  28. // mockObj.EXPECT().SomeMethod(4, "blah")
  29. // // pass mockObj to a real object and play with it.
  30. // }
  31. //
  32. // By default, expected calls are not enforced to run in any particular order.
  33. // Call order dependency can be enforced by use of InOrder and/or Call.After.
  34. // Call.After can create more varied call order dependencies, but InOrder is
  35. // often more convenient.
  36. //
  37. // The following examples create equivalent call order dependencies.
  38. //
  39. // Example of using Call.After to chain expected call order:
  40. //
  41. // firstCall := mockObj.EXPECT().SomeMethod(1, "first")
  42. // secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
  43. // mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
  44. //
  45. // Example of using InOrder to declare expected call order:
  46. //
  47. // gomock.InOrder(
  48. // mockObj.EXPECT().SomeMethod(1, "first"),
  49. // mockObj.EXPECT().SomeMethod(2, "second"),
  50. // mockObj.EXPECT().SomeMethod(3, "third"),
  51. // )
  52. //
  53. // TODO:
  54. // - Handle different argument/return types (e.g. ..., chan, map, interface).
  55. package gomock
  56. import (
  57. "context"
  58. "fmt"
  59. "reflect"
  60. "runtime"
  61. "sync"
  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.
  65. type TestReporter interface {
  66. Errorf(format string, args ...interface{})
  67. Fatalf(format string, args ...interface{})
  68. }
  69. // TestHelper is a TestReporter that has the Helper method. It is satisfied
  70. // by the standard library's *testing.T.
  71. type TestHelper interface {
  72. TestReporter
  73. Helper()
  74. }
  75. // A Controller represents the top-level control of a mock ecosystem. It
  76. // defines the scope and lifetime of mock objects, as well as their
  77. // expectations. It is safe to call Controller's methods from multiple
  78. // goroutines. Each test should create a new Controller and invoke Finish via
  79. // defer.
  80. //
  81. // func TestFoo(t *testing.T) {
  82. // ctrl := gomock.NewController(st)
  83. // defer ctrl.Finish()
  84. // // ..
  85. // }
  86. //
  87. // func TestBar(t *testing.T) {
  88. // t.Run("Sub-Test-1", st) {
  89. // ctrl := gomock.NewController(st)
  90. // defer ctrl.Finish()
  91. // // ..
  92. // })
  93. // t.Run("Sub-Test-2", st) {
  94. // ctrl := gomock.NewController(st)
  95. // defer ctrl.Finish()
  96. // // ..
  97. // })
  98. // })
  99. type Controller struct {
  100. // T should only be called within a generated mock. It is not intended to
  101. // be used in user code and may be changed in future versions. T is the
  102. // TestReporter passed in when creating the Controller via NewController.
  103. // If the TestReporter does not implment a TestHelper it will be wrapped
  104. // with a nopTestHelper.
  105. T TestHelper
  106. mu sync.Mutex
  107. expectedCalls *callSet
  108. finished bool
  109. }
  110. // NewController returns a new Controller. It is the preferred way to create a
  111. // Controller.
  112. func NewController(t TestReporter) *Controller {
  113. h, ok := t.(TestHelper)
  114. if !ok {
  115. h = nopTestHelper{t}
  116. }
  117. return &Controller{
  118. T: h,
  119. expectedCalls: newCallSet(),
  120. }
  121. }
  122. type cancelReporter struct {
  123. TestHelper
  124. cancel func()
  125. }
  126. func (r *cancelReporter) Errorf(format string, args ...interface{}) {
  127. r.TestHelper.Errorf(format, args...)
  128. }
  129. func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
  130. defer r.cancel()
  131. r.TestHelper.Fatalf(format, args...)
  132. }
  133. // WithContext returns a new Controller and a Context, which is cancelled on any
  134. // fatal failure.
  135. func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
  136. h, ok := t.(TestHelper)
  137. if !ok {
  138. h = nopTestHelper{t}
  139. }
  140. ctx, cancel := context.WithCancel(ctx)
  141. return NewController(&cancelReporter{h, cancel}), ctx
  142. }
  143. type nopTestHelper struct {
  144. TestReporter
  145. }
  146. func (h nopTestHelper) Helper() {}
  147. // RecordCall is called by a mock. It should not be called by user code.
  148. func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
  149. ctrl.T.Helper()
  150. recv := reflect.ValueOf(receiver)
  151. for i := 0; i < recv.Type().NumMethod(); i++ {
  152. if recv.Type().Method(i).Name == method {
  153. return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
  154. }
  155. }
  156. ctrl.T.Fatalf("gomock: failed finding method %s on %T", method, receiver)
  157. panic("unreachable")
  158. }
  159. // RecordCallWithMethodType is called by a mock. It should not be called by user code.
  160. func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
  161. ctrl.T.Helper()
  162. call := newCall(ctrl.T, receiver, method, methodType, args...)
  163. ctrl.mu.Lock()
  164. defer ctrl.mu.Unlock()
  165. ctrl.expectedCalls.Add(call)
  166. return call
  167. }
  168. // Call is called by a mock. It should not be called by user code.
  169. func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
  170. ctrl.T.Helper()
  171. // Nest this code so we can use defer to make sure the lock is released.
  172. actions := func() []func([]interface{}) []interface{} {
  173. ctrl.T.Helper()
  174. ctrl.mu.Lock()
  175. defer ctrl.mu.Unlock()
  176. expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
  177. if err != nil {
  178. origin := callerInfo(2)
  179. ctrl.T.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
  180. }
  181. // Two things happen here:
  182. // * the matching call no longer needs to check prerequite calls,
  183. // * and the prerequite calls are no longer expected, so remove them.
  184. preReqCalls := expected.dropPrereqs()
  185. for _, preReqCall := range preReqCalls {
  186. ctrl.expectedCalls.Remove(preReqCall)
  187. }
  188. actions := expected.call(args)
  189. if expected.exhausted() {
  190. ctrl.expectedCalls.Remove(expected)
  191. }
  192. return actions
  193. }()
  194. var rets []interface{}
  195. for _, action := range actions {
  196. if r := action(args); r != nil {
  197. rets = r
  198. }
  199. }
  200. return rets
  201. }
  202. // Finish checks to see if all the methods that were expected to be called
  203. // were called. It should be invoked for each Controller. It is not idempotent
  204. // and therefore can only be invoked once.
  205. func (ctrl *Controller) Finish() {
  206. ctrl.T.Helper()
  207. ctrl.mu.Lock()
  208. defer ctrl.mu.Unlock()
  209. if ctrl.finished {
  210. ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.")
  211. }
  212. ctrl.finished = true
  213. // If we're currently panicking, probably because this is a deferred call,
  214. // pass through the panic.
  215. if err := recover(); err != nil {
  216. panic(err)
  217. }
  218. // Check that all remaining expected calls are satisfied.
  219. failures := ctrl.expectedCalls.Failures()
  220. for _, call := range failures {
  221. ctrl.T.Errorf("missing call(s) to %v", call)
  222. }
  223. if len(failures) != 0 {
  224. ctrl.T.Fatalf("aborting test due to missing call(s)")
  225. }
  226. }
  227. func callerInfo(skip int) string {
  228. if _, file, line, ok := runtime.Caller(skip + 1); ok {
  229. return fmt.Sprintf("%s:%d", file, line)
  230. }
  231. return "unknown file"
  232. }