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.

886 lines
25 KiB

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