mock.go 23 KB

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