equality.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package assertions
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "reflect"
  8. "strings"
  9. "github.com/smartystreets/assertions/internal/go-render/render"
  10. "github.com/smartystreets/assertions/internal/oglematchers"
  11. )
  12. // ShouldEqual receives exactly two parameters and does an equality check
  13. // using the following semantics:
  14. // 1. If the expected and actual values implement an Equal method in the form
  15. // `func (this T) Equal(that T) bool` then call the method. If true, they are equal.
  16. // 2. The expected and actual values are judged equal or not by oglematchers.Equals.
  17. func ShouldEqual(actual interface{}, expected ...interface{}) string {
  18. if message := need(1, expected); message != success {
  19. return message
  20. }
  21. return shouldEqual(actual, expected[0])
  22. }
  23. func shouldEqual(actual, expected interface{}) (message string) {
  24. defer func() {
  25. if r := recover(); r != nil {
  26. message = serializer.serialize(expected, actual, composeEqualityMismatchMessage(expected, actual))
  27. }
  28. }()
  29. if spec := newEqualityMethodSpecification(expected, actual); spec.IsSatisfied() && spec.AreEqual() {
  30. return success
  31. } else if matchError := oglematchers.Equals(expected).Matches(actual); matchError == nil {
  32. return success
  33. }
  34. return serializer.serialize(expected, actual, composeEqualityMismatchMessage(expected, actual))
  35. }
  36. func composeEqualityMismatchMessage(expected, actual interface{}) string {
  37. var (
  38. renderedExpected = fmt.Sprintf("%v", expected)
  39. renderedActual = fmt.Sprintf("%v", actual)
  40. )
  41. if renderedExpected != renderedActual {
  42. return fmt.Sprintf(shouldHaveBeenEqual+composePrettyDiff(renderedExpected, renderedActual), expected, actual)
  43. } else if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
  44. return fmt.Sprintf(shouldHaveBeenEqualTypeMismatch, expected, expected, actual, actual)
  45. } else {
  46. return fmt.Sprintf(shouldHaveBeenEqualNoResemblance, renderedExpected)
  47. }
  48. }
  49. // ShouldNotEqual receives exactly two parameters and does an inequality check.
  50. // See ShouldEqual for details on how equality is determined.
  51. func ShouldNotEqual(actual interface{}, expected ...interface{}) string {
  52. if fail := need(1, expected); fail != success {
  53. return fail
  54. } else if ShouldEqual(actual, expected[0]) == success {
  55. return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0])
  56. }
  57. return success
  58. }
  59. // ShouldAlmostEqual makes sure that two parameters are close enough to being equal.
  60. // The acceptable delta may be specified with a third argument,
  61. // or a very small default delta will be used.
  62. func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string {
  63. actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)
  64. if err != "" {
  65. return err
  66. }
  67. if math.Abs(actualFloat-expectedFloat) <= deltaFloat {
  68. return success
  69. } else {
  70. return fmt.Sprintf(shouldHaveBeenAlmostEqual, actualFloat, expectedFloat)
  71. }
  72. }
  73. // ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual
  74. func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string {
  75. actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)
  76. if err != "" {
  77. return err
  78. }
  79. if math.Abs(actualFloat-expectedFloat) > deltaFloat {
  80. return success
  81. } else {
  82. return fmt.Sprintf(shouldHaveNotBeenAlmostEqual, actualFloat, expectedFloat)
  83. }
  84. }
  85. func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64, float64, float64, string) {
  86. deltaFloat := 0.0000000001
  87. if len(expected) == 0 {
  88. return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided neither)"
  89. } else if len(expected) == 2 {
  90. delta, err := getFloat(expected[1])
  91. if err != nil {
  92. return 0.0, 0.0, 0.0, "The delta value " + err.Error()
  93. }
  94. deltaFloat = delta
  95. } else if len(expected) > 2 {
  96. return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided more values)"
  97. }
  98. actualFloat, err := getFloat(actual)
  99. if err != nil {
  100. return 0.0, 0.0, 0.0, "The actual value " + err.Error()
  101. }
  102. expectedFloat, err := getFloat(expected[0])
  103. if err != nil {
  104. return 0.0, 0.0, 0.0, "The comparison value " + err.Error()
  105. }
  106. return actualFloat, expectedFloat, deltaFloat, ""
  107. }
  108. // returns the float value of any real number, or error if it is not a numerical type
  109. func getFloat(num interface{}) (float64, error) {
  110. numValue := reflect.ValueOf(num)
  111. numKind := numValue.Kind()
  112. if numKind == reflect.Int ||
  113. numKind == reflect.Int8 ||
  114. numKind == reflect.Int16 ||
  115. numKind == reflect.Int32 ||
  116. numKind == reflect.Int64 {
  117. return float64(numValue.Int()), nil
  118. } else if numKind == reflect.Uint ||
  119. numKind == reflect.Uint8 ||
  120. numKind == reflect.Uint16 ||
  121. numKind == reflect.Uint32 ||
  122. numKind == reflect.Uint64 {
  123. return float64(numValue.Uint()), nil
  124. } else if numKind == reflect.Float32 ||
  125. numKind == reflect.Float64 {
  126. return numValue.Float(), nil
  127. } else {
  128. return 0.0, errors.New("must be a numerical type, but was: " + numKind.String())
  129. }
  130. }
  131. // ShouldEqualJSON receives exactly two parameters and does an equality check by marshalling to JSON
  132. func ShouldEqualJSON(actual interface{}, expected ...interface{}) string {
  133. if message := need(1, expected); message != success {
  134. return message
  135. }
  136. expectedString, expectedErr := remarshal(expected[0].(string))
  137. if expectedErr != nil {
  138. return "Expected value not valid JSON: " + expectedErr.Error()
  139. }
  140. actualString, actualErr := remarshal(actual.(string))
  141. if actualErr != nil {
  142. return "Actual value not valid JSON: " + actualErr.Error()
  143. }
  144. return ShouldEqual(actualString, expectedString)
  145. }
  146. func remarshal(value string) (string, error) {
  147. var structured interface{}
  148. err := json.Unmarshal([]byte(value), &structured)
  149. if err != nil {
  150. return "", err
  151. }
  152. canonical, _ := json.Marshal(structured)
  153. return string(canonical), nil
  154. }
  155. // ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual)
  156. func ShouldResemble(actual interface{}, expected ...interface{}) string {
  157. if message := need(1, expected); message != success {
  158. return message
  159. }
  160. if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil {
  161. renderedExpected, renderedActual := render.Render(expected[0]), render.Render(actual)
  162. message := fmt.Sprintf(shouldHaveResembled, renderedExpected, renderedActual) +
  163. composePrettyDiff(renderedExpected, renderedActual)
  164. return serializer.serializeDetailed(expected[0], actual, message)
  165. }
  166. return success
  167. }
  168. // ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual)
  169. func ShouldNotResemble(actual interface{}, expected ...interface{}) string {
  170. if message := need(1, expected); message != success {
  171. return message
  172. } else if ShouldResemble(actual, expected[0]) == success {
  173. return fmt.Sprintf(shouldNotHaveResembled, render.Render(actual), render.Render(expected[0]))
  174. }
  175. return success
  176. }
  177. // ShouldPointTo receives exactly two parameters and checks to see that they point to the same address.
  178. func ShouldPointTo(actual interface{}, expected ...interface{}) string {
  179. if message := need(1, expected); message != success {
  180. return message
  181. }
  182. return shouldPointTo(actual, expected[0])
  183. }
  184. func shouldPointTo(actual, expected interface{}) string {
  185. actualValue := reflect.ValueOf(actual)
  186. expectedValue := reflect.ValueOf(expected)
  187. if ShouldNotBeNil(actual) != success {
  188. return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil")
  189. } else if ShouldNotBeNil(expected) != success {
  190. return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil")
  191. } else if actualValue.Kind() != reflect.Ptr {
  192. return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not")
  193. } else if expectedValue.Kind() != reflect.Ptr {
  194. return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not")
  195. } else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success {
  196. actualAddress := reflect.ValueOf(actual).Pointer()
  197. expectedAddress := reflect.ValueOf(expected).Pointer()
  198. return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo,
  199. actual, actualAddress,
  200. expected, expectedAddress))
  201. }
  202. return success
  203. }
  204. // ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess.
  205. func ShouldNotPointTo(actual interface{}, expected ...interface{}) string {
  206. if message := need(1, expected); message != success {
  207. return message
  208. }
  209. compare := ShouldPointTo(actual, expected[0])
  210. if strings.HasPrefix(compare, shouldBePointers) {
  211. return compare
  212. } else if compare == success {
  213. return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer())
  214. }
  215. return success
  216. }
  217. // ShouldBeNil receives a single parameter and ensures that it is nil.
  218. func ShouldBeNil(actual interface{}, expected ...interface{}) string {
  219. if fail := need(0, expected); fail != success {
  220. return fail
  221. } else if actual == nil {
  222. return success
  223. } else if interfaceHasNilValue(actual) {
  224. return success
  225. }
  226. return fmt.Sprintf(shouldHaveBeenNil, actual)
  227. }
  228. func interfaceHasNilValue(actual interface{}) bool {
  229. value := reflect.ValueOf(actual)
  230. kind := value.Kind()
  231. nilable := kind == reflect.Slice ||
  232. kind == reflect.Chan ||
  233. kind == reflect.Func ||
  234. kind == reflect.Ptr ||
  235. kind == reflect.Map
  236. // Careful: reflect.Value.IsNil() will panic unless it's an interface, chan, map, func, slice, or ptr
  237. // Reference: http://golang.org/pkg/reflect/#Value.IsNil
  238. return nilable && value.IsNil()
  239. }
  240. // ShouldNotBeNil receives a single parameter and ensures that it is not nil.
  241. func ShouldNotBeNil(actual interface{}, expected ...interface{}) string {
  242. if fail := need(0, expected); fail != success {
  243. return fail
  244. } else if ShouldBeNil(actual) == success {
  245. return fmt.Sprintf(shouldNotHaveBeenNil, actual)
  246. }
  247. return success
  248. }
  249. // ShouldBeTrue receives a single parameter and ensures that it is true.
  250. func ShouldBeTrue(actual interface{}, expected ...interface{}) string {
  251. if fail := need(0, expected); fail != success {
  252. return fail
  253. } else if actual != true {
  254. return fmt.Sprintf(shouldHaveBeenTrue, actual)
  255. }
  256. return success
  257. }
  258. // ShouldBeFalse receives a single parameter and ensures that it is false.
  259. func ShouldBeFalse(actual interface{}, expected ...interface{}) string {
  260. if fail := need(0, expected); fail != success {
  261. return fail
  262. } else if actual != false {
  263. return fmt.Sprintf(shouldHaveBeenFalse, actual)
  264. }
  265. return success
  266. }
  267. // ShouldBeZeroValue receives a single parameter and ensures that it is
  268. // the Go equivalent of the default value, or "zero" value.
  269. func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string {
  270. if fail := need(0, expected); fail != success {
  271. return fail
  272. }
  273. zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface()
  274. if !reflect.DeepEqual(zeroVal, actual) {
  275. return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual))
  276. }
  277. return success
  278. }
  279. // ShouldBeZeroValue receives a single parameter and ensures that it is NOT
  280. // the Go equivalent of the default value, or "zero" value.
  281. func ShouldNotBeZeroValue(actual interface{}, expected ...interface{}) string {
  282. if fail := need(0, expected); fail != success {
  283. return fail
  284. }
  285. zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface()
  286. if reflect.DeepEqual(zeroVal, actual) {
  287. return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldNotHaveBeenZeroValue, actual))
  288. }
  289. return success
  290. }