mock.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. package mock
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. "regexp"
  7. "runtime"
  8. "strings"
  9. "sync"
  10. "time"
  11. "github.com/davecgh/go-spew/spew"
  12. "github.com/pmezard/go-difflib/difflib"
  13. "github.com/stretchr/objx"
  14. "github.com/stretchr/testify/assert"
  15. )
  16. // TestingT is an interface wrapper around *testing.T
  17. type TestingT interface {
  18. Logf(format string, args ...interface{})
  19. Errorf(format string, args ...interface{})
  20. FailNow()
  21. }
  22. /*
  23. Call
  24. */
  25. // Call represents a method call and is used for setting expectations,
  26. // as well as recording activity.
  27. type Call struct {
  28. Parent *Mock
  29. // The name of the method that was or will be called.
  30. Method string
  31. // Holds the arguments of the method.
  32. Arguments Arguments
  33. // Holds the arguments that should be returned when
  34. // this method is called.
  35. ReturnArguments Arguments
  36. // Holds the caller info for the On() call
  37. callerInfo []string
  38. // The number of times to return the return arguments when setting
  39. // expectations. 0 means to always return the value.
  40. Repeatability int
  41. // Amount of times this call has been called
  42. totalCalls int
  43. // Call to this method can be optional
  44. optional bool
  45. // Holds a channel that will be used to block the Return until it either
  46. // receives a message or is closed. nil means it returns immediately.
  47. WaitFor <-chan time.Time
  48. waitTime time.Duration
  49. // Holds a handler used to manipulate arguments content that are passed by
  50. // reference. It's useful when mocking methods such as unmarshalers or
  51. // decoders.
  52. RunFn func(Arguments)
  53. }
  54. func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
  55. return &Call{
  56. Parent: parent,
  57. Method: methodName,
  58. Arguments: methodArguments,
  59. ReturnArguments: make([]interface{}, 0),
  60. callerInfo: callerInfo,
  61. Repeatability: 0,
  62. WaitFor: nil,
  63. RunFn: nil,
  64. }
  65. }
  66. func (c *Call) lock() {
  67. c.Parent.mutex.Lock()
  68. }
  69. func (c *Call) unlock() {
  70. c.Parent.mutex.Unlock()
  71. }
  72. // Return specifies the return arguments for the expectation.
  73. //
  74. // Mock.On("DoSomething").Return(errors.New("failed"))
  75. func (c *Call) Return(returnArguments ...interface{}) *Call {
  76. c.lock()
  77. defer c.unlock()
  78. c.ReturnArguments = returnArguments
  79. return c
  80. }
  81. // Once indicates that that the mock should only return the value once.
  82. //
  83. // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
  84. func (c *Call) Once() *Call {
  85. return c.Times(1)
  86. }
  87. // Twice indicates that that the mock should only return the value twice.
  88. //
  89. // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
  90. func (c *Call) Twice() *Call {
  91. return c.Times(2)
  92. }
  93. // Times indicates that that the mock should only return the indicated number
  94. // of times.
  95. //
  96. // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
  97. func (c *Call) Times(i int) *Call {
  98. c.lock()
  99. defer c.unlock()
  100. c.Repeatability = i
  101. return c
  102. }
  103. // WaitUntil sets the channel that will block the mock's return until its closed
  104. // or a message is received.
  105. //
  106. // Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
  107. func (c *Call) WaitUntil(w <-chan time.Time) *Call {
  108. c.lock()
  109. defer c.unlock()
  110. c.WaitFor = w
  111. return c
  112. }
  113. // After sets how long to block until the call returns
  114. //
  115. // Mock.On("MyMethod", arg1, arg2).After(time.Second)
  116. func (c *Call) After(d time.Duration) *Call {
  117. c.lock()
  118. defer c.unlock()
  119. c.waitTime = d
  120. return c
  121. }
  122. // Run sets a handler to be called before returning. It can be used when
  123. // mocking a method such as unmarshalers that takes a pointer to a struct and
  124. // sets properties in such struct
  125. //
  126. // Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) {
  127. // arg := args.Get(0).(*map[string]interface{})
  128. // arg["foo"] = "bar"
  129. // })
  130. func (c *Call) Run(fn func(args Arguments)) *Call {
  131. c.lock()
  132. defer c.unlock()
  133. c.RunFn = fn
  134. return c
  135. }
  136. // Maybe allows the method call to be optional. Not calling an optional method
  137. // will not cause an error while asserting expectations
  138. func (c *Call) Maybe() *Call {
  139. c.lock()
  140. defer c.unlock()
  141. c.optional = true
  142. return c
  143. }
  144. // On chains a new expectation description onto the mocked interface. This
  145. // allows syntax like.
  146. //
  147. // Mock.
  148. // On("MyMethod", 1).Return(nil).
  149. // On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
  150. func (c *Call) On(methodName string, arguments ...interface{}) *Call {
  151. return c.Parent.On(methodName, arguments...)
  152. }
  153. // Mock is the workhorse used to track activity on another object.
  154. // For an example of its usage, refer to the "Example Usage" section at the top
  155. // of this document.
  156. type Mock struct {
  157. // Represents the calls that are expected of
  158. // an object.
  159. ExpectedCalls []*Call
  160. // Holds the calls that were made to this mocked object.
  161. Calls []Call
  162. // test is An optional variable that holds the test struct, to be used when an
  163. // invalid mock call was made.
  164. test TestingT
  165. // TestData holds any data that might be useful for testing. Testify ignores
  166. // this data completely allowing you to do whatever you like with it.
  167. testData objx.Map
  168. mutex sync.Mutex
  169. }
  170. // TestData holds any data that might be useful for testing. Testify ignores
  171. // this data completely allowing you to do whatever you like with it.
  172. func (m *Mock) TestData() objx.Map {
  173. if m.testData == nil {
  174. m.testData = make(objx.Map)
  175. }
  176. return m.testData
  177. }
  178. /*
  179. Setting expectations
  180. */
  181. // Test sets the test struct variable of the mock object
  182. func (m *Mock) Test(t TestingT) {
  183. m.mutex.Lock()
  184. defer m.mutex.Unlock()
  185. m.test = t
  186. }
  187. // fail fails the current test with the given formatted format and args.
  188. // In case that a test was defined, it uses the test APIs for failing a test,
  189. // otherwise it uses panic.
  190. func (m *Mock) fail(format string, args ...interface{}) {
  191. m.mutex.Lock()
  192. defer m.mutex.Unlock()
  193. if m.test == nil {
  194. panic(fmt.Sprintf(format, args...))
  195. }
  196. m.test.Errorf(format, args...)
  197. m.test.FailNow()
  198. }
  199. // On starts a description of an expectation of the specified method
  200. // being called.
  201. //
  202. // Mock.On("MyMethod", arg1, arg2)
  203. func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
  204. for _, arg := range arguments {
  205. if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
  206. panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
  207. }
  208. }
  209. m.mutex.Lock()
  210. defer m.mutex.Unlock()
  211. c := newCall(m, methodName, assert.CallerInfo(), arguments...)
  212. m.ExpectedCalls = append(m.ExpectedCalls, c)
  213. return c
  214. }
  215. // /*
  216. // Recording and responding to activity
  217. // */
  218. func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
  219. for i, call := range m.ExpectedCalls {
  220. if call.Method == method && call.Repeatability > -1 {
  221. _, diffCount := call.Arguments.Diff(arguments)
  222. if diffCount == 0 {
  223. return i, call
  224. }
  225. }
  226. }
  227. return -1, nil
  228. }
  229. func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
  230. var diffCount int
  231. var closestCall *Call
  232. var err string
  233. for _, call := range m.expectedCalls() {
  234. if call.Method == method {
  235. errInfo, tempDiffCount := call.Arguments.Diff(arguments)
  236. if tempDiffCount < diffCount || diffCount == 0 {
  237. diffCount = tempDiffCount
  238. closestCall = call
  239. err = errInfo
  240. }
  241. }
  242. }
  243. return closestCall, err
  244. }
  245. func callString(method string, arguments Arguments, includeArgumentValues bool) string {
  246. var argValsString string
  247. if includeArgumentValues {
  248. var argVals []string
  249. for argIndex, arg := range arguments {
  250. argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
  251. }
  252. argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
  253. }
  254. return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString)
  255. }
  256. // Called tells the mock object that a method has been called, and gets an array
  257. // of arguments to return. Panics if the call is unexpected (i.e. not preceded by
  258. // appropriate .On .Return() calls)
  259. // If Call.WaitFor is set, blocks until the channel is closed or receives a message.
  260. func (m *Mock) Called(arguments ...interface{}) Arguments {
  261. // get the calling function's name
  262. pc, _, _, ok := runtime.Caller(1)
  263. if !ok {
  264. panic("Couldn't get the caller information")
  265. }
  266. functionPath := runtime.FuncForPC(pc).Name()
  267. //Next four lines are required to use GCCGO function naming conventions.
  268. //For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
  269. //uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
  270. //With GCCGO we need to remove interface information starting from pN<dd>.
  271. re := regexp.MustCompile("\\.pN\\d+_")
  272. if re.MatchString(functionPath) {
  273. functionPath = re.Split(functionPath, -1)[0]
  274. }
  275. parts := strings.Split(functionPath, ".")
  276. functionName := parts[len(parts)-1]
  277. return m.MethodCalled(functionName, arguments...)
  278. }
  279. // MethodCalled tells the mock object that the given method has been called, and gets
  280. // an array of arguments to return. Panics if the call is unexpected (i.e. not preceded
  281. // by appropriate .On .Return() calls)
  282. // If Call.WaitFor is set, blocks until the channel is closed or receives a message.
  283. func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
  284. m.mutex.Lock()
  285. //TODO: could combine expected and closes in single loop
  286. found, call := m.findExpectedCall(methodName, arguments...)
  287. if found < 0 {
  288. // we have to fail here - because we don't know what to do
  289. // as the return arguments. This is because:
  290. //
  291. // a) this is a totally unexpected call to this method,
  292. // b) the arguments are not what was expected, or
  293. // c) the developer has forgotten to add an accompanying On...Return pair.
  294. closestCall, mismatch := m.findClosestCall(methodName, arguments...)
  295. m.mutex.Unlock()
  296. if closestCall != nil {
  297. m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
  298. callString(methodName, arguments, true),
  299. callString(methodName, closestCall.Arguments, true),
  300. diffArguments(closestCall.Arguments, arguments),
  301. strings.TrimSpace(mismatch),
  302. )
  303. } else {
  304. m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
  305. }
  306. }
  307. if call.Repeatability == 1 {
  308. call.Repeatability = -1
  309. } else if call.Repeatability > 1 {
  310. call.Repeatability--
  311. }
  312. call.totalCalls++
  313. // add the call
  314. m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...))
  315. m.mutex.Unlock()
  316. // block if specified
  317. if call.WaitFor != nil {
  318. <-call.WaitFor
  319. } else {
  320. time.Sleep(call.waitTime)
  321. }
  322. m.mutex.Lock()
  323. runFn := call.RunFn
  324. m.mutex.Unlock()
  325. if runFn != nil {
  326. runFn(arguments)
  327. }
  328. m.mutex.Lock()
  329. returnArgs := call.ReturnArguments
  330. m.mutex.Unlock()
  331. return returnArgs
  332. }
  333. /*
  334. Assertions
  335. */
  336. type assertExpectationser interface {
  337. AssertExpectations(TestingT) bool
  338. }
  339. // AssertExpectationsForObjects asserts that everything specified with On and Return
  340. // of the specified objects was in fact called as expected.
  341. //
  342. // Calls may have occurred in any order.
  343. func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
  344. if h, ok := t.(tHelper); ok {
  345. h.Helper()
  346. }
  347. for _, obj := range testObjects {
  348. if m, ok := obj.(Mock); ok {
  349. t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
  350. obj = &m
  351. }
  352. m := obj.(assertExpectationser)
  353. if !m.AssertExpectations(t) {
  354. t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
  355. return false
  356. }
  357. }
  358. return true
  359. }
  360. // AssertExpectations asserts that everything specified with On and Return was
  361. // in fact called as expected. Calls may have occurred in any order.
  362. func (m *Mock) AssertExpectations(t TestingT) bool {
  363. if h, ok := t.(tHelper); ok {
  364. h.Helper()
  365. }
  366. m.mutex.Lock()
  367. defer m.mutex.Unlock()
  368. var somethingMissing bool
  369. var failedExpectations int
  370. // iterate through each expectation
  371. expectedCalls := m.expectedCalls()
  372. for _, expectedCall := range expectedCalls {
  373. if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
  374. somethingMissing = true
  375. failedExpectations++
  376. t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
  377. } else {
  378. if expectedCall.Repeatability > 0 {
  379. somethingMissing = true
  380. failedExpectations++
  381. t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
  382. } else {
  383. t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
  384. }
  385. }
  386. }
  387. if somethingMissing {
  388. t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
  389. }
  390. return !somethingMissing
  391. }
  392. // AssertNumberOfCalls asserts that the method was called expectedCalls times.
  393. func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
  394. if h, ok := t.(tHelper); ok {
  395. h.Helper()
  396. }
  397. m.mutex.Lock()
  398. defer m.mutex.Unlock()
  399. var actualCalls int
  400. for _, call := range m.calls() {
  401. if call.Method == methodName {
  402. actualCalls++
  403. }
  404. }
  405. return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
  406. }
  407. // AssertCalled asserts that the method was called.
  408. // It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
  409. func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
  410. if h, ok := t.(tHelper); ok {
  411. h.Helper()
  412. }
  413. m.mutex.Lock()
  414. defer m.mutex.Unlock()
  415. if !m.methodWasCalled(methodName, arguments) {
  416. var calledWithArgs []string
  417. for _, call := range m.calls() {
  418. calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments))
  419. }
  420. if len(calledWithArgs) == 0 {
  421. return assert.Fail(t, "Should have called with given arguments",
  422. fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments))
  423. }
  424. return assert.Fail(t, "Should have called with given arguments",
  425. fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n")))
  426. }
  427. return true
  428. }
  429. // AssertNotCalled asserts that the method was not called.
  430. // It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
  431. func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
  432. if h, ok := t.(tHelper); ok {
  433. h.Helper()
  434. }
  435. m.mutex.Lock()
  436. defer m.mutex.Unlock()
  437. if m.methodWasCalled(methodName, arguments) {
  438. return assert.Fail(t, "Should not have called with given arguments",
  439. fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments))
  440. }
  441. return true
  442. }
  443. func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
  444. for _, call := range m.calls() {
  445. if call.Method == methodName {
  446. _, differences := Arguments(expected).Diff(call.Arguments)
  447. if differences == 0 {
  448. // found the expected call
  449. return true
  450. }
  451. }
  452. }
  453. // we didn't find the expected call
  454. return false
  455. }
  456. func (m *Mock) expectedCalls() []*Call {
  457. return append([]*Call{}, m.ExpectedCalls...)
  458. }
  459. func (m *Mock) calls() []Call {
  460. return append([]Call{}, m.Calls...)
  461. }
  462. /*
  463. Arguments
  464. */
  465. // Arguments holds an array of method arguments or return values.
  466. type Arguments []interface{}
  467. const (
  468. // Anything is used in Diff and Assert when the argument being tested
  469. // shouldn't be taken into consideration.
  470. Anything = "mock.Anything"
  471. )
  472. // AnythingOfTypeArgument is a string that contains the type of an argument
  473. // for use when type checking. Used in Diff and Assert.
  474. type AnythingOfTypeArgument string
  475. // AnythingOfType returns an AnythingOfTypeArgument object containing the
  476. // name of the type to check for. Used in Diff and Assert.
  477. //
  478. // For example:
  479. // Assert(t, AnythingOfType("string"), AnythingOfType("int"))
  480. func AnythingOfType(t string) AnythingOfTypeArgument {
  481. return AnythingOfTypeArgument(t)
  482. }
  483. // argumentMatcher performs custom argument matching, returning whether or
  484. // not the argument is matched by the expectation fixture function.
  485. type argumentMatcher struct {
  486. // fn is a function which accepts one argument, and returns a bool.
  487. fn reflect.Value
  488. }
  489. func (f argumentMatcher) Matches(argument interface{}) bool {
  490. expectType := f.fn.Type().In(0)
  491. expectTypeNilSupported := false
  492. switch expectType.Kind() {
  493. case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr:
  494. expectTypeNilSupported = true
  495. }
  496. argType := reflect.TypeOf(argument)
  497. var arg reflect.Value
  498. if argType == nil {
  499. arg = reflect.New(expectType).Elem()
  500. } else {
  501. arg = reflect.ValueOf(argument)
  502. }
  503. if argType == nil && !expectTypeNilSupported {
  504. panic(errors.New("attempting to call matcher with nil for non-nil expected type"))
  505. }
  506. if argType == nil || argType.AssignableTo(expectType) {
  507. result := f.fn.Call([]reflect.Value{arg})
  508. return result[0].Bool()
  509. }
  510. return false
  511. }
  512. func (f argumentMatcher) String() string {
  513. return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name())
  514. }
  515. // MatchedBy can be used to match a mock call based on only certain properties
  516. // from a complex struct or some calculation. It takes a function that will be
  517. // evaluated with the called argument and will return true when there's a match
  518. // and false otherwise.
  519. //
  520. // Example:
  521. // m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" }))
  522. //
  523. // |fn|, must be a function accepting a single argument (of the expected type)
  524. // which returns a bool. If |fn| doesn't match the required signature,
  525. // MatchedBy() panics.
  526. func MatchedBy(fn interface{}) argumentMatcher {
  527. fnType := reflect.TypeOf(fn)
  528. if fnType.Kind() != reflect.Func {
  529. panic(fmt.Sprintf("assert: arguments: %s is not a func", fn))
  530. }
  531. if fnType.NumIn() != 1 {
  532. panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn))
  533. }
  534. if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool {
  535. panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn))
  536. }
  537. return argumentMatcher{fn: reflect.ValueOf(fn)}
  538. }
  539. // Get Returns the argument at the specified index.
  540. func (args Arguments) Get(index int) interface{} {
  541. if index+1 > len(args) {
  542. panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args)))
  543. }
  544. return args[index]
  545. }
  546. // Is gets whether the objects match the arguments specified.
  547. func (args Arguments) Is(objects ...interface{}) bool {
  548. for i, obj := range args {
  549. if obj != objects[i] {
  550. return false
  551. }
  552. }
  553. return true
  554. }
  555. // Diff gets a string describing the differences between the arguments
  556. // and the specified objects.
  557. //
  558. // Returns the diff string and number of differences found.
  559. func (args Arguments) Diff(objects []interface{}) (string, int) {
  560. //TODO: could return string as error and nil for No difference
  561. var output = "\n"
  562. var differences int
  563. var maxArgCount = len(args)
  564. if len(objects) > maxArgCount {
  565. maxArgCount = len(objects)
  566. }
  567. for i := 0; i < maxArgCount; i++ {
  568. var actual, expected interface{}
  569. var actualFmt, expectedFmt string
  570. if len(objects) <= i {
  571. actual = "(Missing)"
  572. actualFmt = "(Missing)"
  573. } else {
  574. actual = objects[i]
  575. actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
  576. }
  577. if len(args) <= i {
  578. expected = "(Missing)"
  579. expectedFmt = "(Missing)"
  580. } else {
  581. expected = args[i]
  582. expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
  583. }
  584. if matcher, ok := expected.(argumentMatcher); ok {
  585. if matcher.Matches(actual) {
  586. output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
  587. } else {
  588. differences++
  589. output = fmt.Sprintf("%s\t%d: PASS: %s not matched by %s\n", output, i, actualFmt, matcher)
  590. }
  591. } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
  592. // type checking
  593. if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
  594. // not match
  595. differences++
  596. output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
  597. }
  598. } else {
  599. // normal checking
  600. if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
  601. // match
  602. output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
  603. } else {
  604. // not match
  605. differences++
  606. output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
  607. }
  608. }
  609. }
  610. if differences == 0 {
  611. return "No differences.", differences
  612. }
  613. return output, differences
  614. }
  615. // Assert compares the arguments with the specified objects and fails if
  616. // they do not exactly match.
  617. func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
  618. if h, ok := t.(tHelper); ok {
  619. h.Helper()
  620. }
  621. // get the differences
  622. diff, diffCount := args.Diff(objects)
  623. if diffCount == 0 {
  624. return true
  625. }
  626. // there are differences... report them...
  627. t.Logf(diff)
  628. t.Errorf("%sArguments do not match.", assert.CallerInfo())
  629. return false
  630. }
  631. // String gets the argument at the specified index. Panics if there is no argument, or
  632. // if the argument is of the wrong type.
  633. //
  634. // If no index is provided, String() returns a complete string representation
  635. // of the arguments.
  636. func (args Arguments) String(indexOrNil ...int) string {
  637. if len(indexOrNil) == 0 {
  638. // normal String() method - return a string representation of the args
  639. var argsStr []string
  640. for _, arg := range args {
  641. argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg)))
  642. }
  643. return strings.Join(argsStr, ",")
  644. } else if len(indexOrNil) == 1 {
  645. // Index has been specified - get the argument at that index
  646. var index = indexOrNil[0]
  647. var s string
  648. var ok bool
  649. if s, ok = args.Get(index).(string); !ok {
  650. panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index)))
  651. }
  652. return s
  653. }
  654. panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
  655. }
  656. // Int gets the argument at the specified index. Panics if there is no argument, or
  657. // if the argument is of the wrong type.
  658. func (args Arguments) Int(index int) int {
  659. var s int
  660. var ok bool
  661. if s, ok = args.Get(index).(int); !ok {
  662. panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
  663. }
  664. return s
  665. }
  666. // Error gets the argument at the specified index. Panics if there is no argument, or
  667. // if the argument is of the wrong type.
  668. func (args Arguments) Error(index int) error {
  669. obj := args.Get(index)
  670. var s error
  671. var ok bool
  672. if obj == nil {
  673. return nil
  674. }
  675. if s, ok = obj.(error); !ok {
  676. panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
  677. }
  678. return s
  679. }
  680. // Bool gets the argument at the specified index. Panics if there is no argument, or
  681. // if the argument is of the wrong type.
  682. func (args Arguments) Bool(index int) bool {
  683. var s bool
  684. var ok bool
  685. if s, ok = args.Get(index).(bool); !ok {
  686. panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
  687. }
  688. return s
  689. }
  690. func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
  691. t := reflect.TypeOf(v)
  692. k := t.Kind()
  693. if k == reflect.Ptr {
  694. t = t.Elem()
  695. k = t.Kind()
  696. }
  697. return t, k
  698. }
  699. func diffArguments(expected Arguments, actual Arguments) string {
  700. if len(expected) != len(actual) {
  701. return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual))
  702. }
  703. for x := range expected {
  704. if diffString := diff(expected[x], actual[x]); diffString != "" {
  705. return fmt.Sprintf("Difference found in argument %v:\n\n%s", x, diffString)
  706. }
  707. }
  708. return ""
  709. }
  710. // diff returns a diff of both values as long as both are of the same type and
  711. // are a struct, map, slice or array. Otherwise it returns an empty string.
  712. func diff(expected interface{}, actual interface{}) string {
  713. if expected == nil || actual == nil {
  714. return ""
  715. }
  716. et, ek := typeAndKind(expected)
  717. at, _ := typeAndKind(actual)
  718. if et != at {
  719. return ""
  720. }
  721. if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
  722. return ""
  723. }
  724. e := spewConfig.Sdump(expected)
  725. a := spewConfig.Sdump(actual)
  726. diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
  727. A: difflib.SplitLines(e),
  728. B: difflib.SplitLines(a),
  729. FromFile: "Expected",
  730. FromDate: "",
  731. ToFile: "Actual",
  732. ToDate: "",
  733. Context: 1,
  734. })
  735. return diff
  736. }
  737. var spewConfig = spew.ConfigState{
  738. Indent: " ",
  739. DisablePointerAddresses: true,
  740. DisableCapacities: true,
  741. SortKeys: true,
  742. }
  743. type tHelper interface {
  744. Helper()
  745. }