equality.go 9.1 KB

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