equality.go 9.1 KB

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