equality.go 9.0 KB

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