assertion_compare.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. package assert
  2. import (
  3. "bytes"
  4. "fmt"
  5. "reflect"
  6. "time"
  7. )
  8. type CompareType int
  9. const (
  10. compareLess CompareType = iota - 1
  11. compareEqual
  12. compareGreater
  13. )
  14. var (
  15. intType = reflect.TypeOf(int(1))
  16. int8Type = reflect.TypeOf(int8(1))
  17. int16Type = reflect.TypeOf(int16(1))
  18. int32Type = reflect.TypeOf(int32(1))
  19. int64Type = reflect.TypeOf(int64(1))
  20. uintType = reflect.TypeOf(uint(1))
  21. uint8Type = reflect.TypeOf(uint8(1))
  22. uint16Type = reflect.TypeOf(uint16(1))
  23. uint32Type = reflect.TypeOf(uint32(1))
  24. uint64Type = reflect.TypeOf(uint64(1))
  25. uintptrType = reflect.TypeOf(uintptr(1))
  26. float32Type = reflect.TypeOf(float32(1))
  27. float64Type = reflect.TypeOf(float64(1))
  28. stringType = reflect.TypeOf("")
  29. timeType = reflect.TypeOf(time.Time{})
  30. bytesType = reflect.TypeOf([]byte{})
  31. )
  32. func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
  33. obj1Value := reflect.ValueOf(obj1)
  34. obj2Value := reflect.ValueOf(obj2)
  35. // throughout this switch we try and avoid calling .Convert() if possible,
  36. // as this has a pretty big performance impact
  37. switch kind {
  38. case reflect.Int:
  39. {
  40. intobj1, ok := obj1.(int)
  41. if !ok {
  42. intobj1 = obj1Value.Convert(intType).Interface().(int)
  43. }
  44. intobj2, ok := obj2.(int)
  45. if !ok {
  46. intobj2 = obj2Value.Convert(intType).Interface().(int)
  47. }
  48. if intobj1 > intobj2 {
  49. return compareGreater, true
  50. }
  51. if intobj1 == intobj2 {
  52. return compareEqual, true
  53. }
  54. if intobj1 < intobj2 {
  55. return compareLess, true
  56. }
  57. }
  58. case reflect.Int8:
  59. {
  60. int8obj1, ok := obj1.(int8)
  61. if !ok {
  62. int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
  63. }
  64. int8obj2, ok := obj2.(int8)
  65. if !ok {
  66. int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
  67. }
  68. if int8obj1 > int8obj2 {
  69. return compareGreater, true
  70. }
  71. if int8obj1 == int8obj2 {
  72. return compareEqual, true
  73. }
  74. if int8obj1 < int8obj2 {
  75. return compareLess, true
  76. }
  77. }
  78. case reflect.Int16:
  79. {
  80. int16obj1, ok := obj1.(int16)
  81. if !ok {
  82. int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
  83. }
  84. int16obj2, ok := obj2.(int16)
  85. if !ok {
  86. int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
  87. }
  88. if int16obj1 > int16obj2 {
  89. return compareGreater, true
  90. }
  91. if int16obj1 == int16obj2 {
  92. return compareEqual, true
  93. }
  94. if int16obj1 < int16obj2 {
  95. return compareLess, true
  96. }
  97. }
  98. case reflect.Int32:
  99. {
  100. int32obj1, ok := obj1.(int32)
  101. if !ok {
  102. int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
  103. }
  104. int32obj2, ok := obj2.(int32)
  105. if !ok {
  106. int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
  107. }
  108. if int32obj1 > int32obj2 {
  109. return compareGreater, true
  110. }
  111. if int32obj1 == int32obj2 {
  112. return compareEqual, true
  113. }
  114. if int32obj1 < int32obj2 {
  115. return compareLess, true
  116. }
  117. }
  118. case reflect.Int64:
  119. {
  120. int64obj1, ok := obj1.(int64)
  121. if !ok {
  122. int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
  123. }
  124. int64obj2, ok := obj2.(int64)
  125. if !ok {
  126. int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
  127. }
  128. if int64obj1 > int64obj2 {
  129. return compareGreater, true
  130. }
  131. if int64obj1 == int64obj2 {
  132. return compareEqual, true
  133. }
  134. if int64obj1 < int64obj2 {
  135. return compareLess, true
  136. }
  137. }
  138. case reflect.Uint:
  139. {
  140. uintobj1, ok := obj1.(uint)
  141. if !ok {
  142. uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
  143. }
  144. uintobj2, ok := obj2.(uint)
  145. if !ok {
  146. uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
  147. }
  148. if uintobj1 > uintobj2 {
  149. return compareGreater, true
  150. }
  151. if uintobj1 == uintobj2 {
  152. return compareEqual, true
  153. }
  154. if uintobj1 < uintobj2 {
  155. return compareLess, true
  156. }
  157. }
  158. case reflect.Uint8:
  159. {
  160. uint8obj1, ok := obj1.(uint8)
  161. if !ok {
  162. uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
  163. }
  164. uint8obj2, ok := obj2.(uint8)
  165. if !ok {
  166. uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
  167. }
  168. if uint8obj1 > uint8obj2 {
  169. return compareGreater, true
  170. }
  171. if uint8obj1 == uint8obj2 {
  172. return compareEqual, true
  173. }
  174. if uint8obj1 < uint8obj2 {
  175. return compareLess, true
  176. }
  177. }
  178. case reflect.Uint16:
  179. {
  180. uint16obj1, ok := obj1.(uint16)
  181. if !ok {
  182. uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
  183. }
  184. uint16obj2, ok := obj2.(uint16)
  185. if !ok {
  186. uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
  187. }
  188. if uint16obj1 > uint16obj2 {
  189. return compareGreater, true
  190. }
  191. if uint16obj1 == uint16obj2 {
  192. return compareEqual, true
  193. }
  194. if uint16obj1 < uint16obj2 {
  195. return compareLess, true
  196. }
  197. }
  198. case reflect.Uint32:
  199. {
  200. uint32obj1, ok := obj1.(uint32)
  201. if !ok {
  202. uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
  203. }
  204. uint32obj2, ok := obj2.(uint32)
  205. if !ok {
  206. uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
  207. }
  208. if uint32obj1 > uint32obj2 {
  209. return compareGreater, true
  210. }
  211. if uint32obj1 == uint32obj2 {
  212. return compareEqual, true
  213. }
  214. if uint32obj1 < uint32obj2 {
  215. return compareLess, true
  216. }
  217. }
  218. case reflect.Uint64:
  219. {
  220. uint64obj1, ok := obj1.(uint64)
  221. if !ok {
  222. uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
  223. }
  224. uint64obj2, ok := obj2.(uint64)
  225. if !ok {
  226. uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
  227. }
  228. if uint64obj1 > uint64obj2 {
  229. return compareGreater, true
  230. }
  231. if uint64obj1 == uint64obj2 {
  232. return compareEqual, true
  233. }
  234. if uint64obj1 < uint64obj2 {
  235. return compareLess, true
  236. }
  237. }
  238. case reflect.Float32:
  239. {
  240. float32obj1, ok := obj1.(float32)
  241. if !ok {
  242. float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
  243. }
  244. float32obj2, ok := obj2.(float32)
  245. if !ok {
  246. float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
  247. }
  248. if float32obj1 > float32obj2 {
  249. return compareGreater, true
  250. }
  251. if float32obj1 == float32obj2 {
  252. return compareEqual, true
  253. }
  254. if float32obj1 < float32obj2 {
  255. return compareLess, true
  256. }
  257. }
  258. case reflect.Float64:
  259. {
  260. float64obj1, ok := obj1.(float64)
  261. if !ok {
  262. float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
  263. }
  264. float64obj2, ok := obj2.(float64)
  265. if !ok {
  266. float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
  267. }
  268. if float64obj1 > float64obj2 {
  269. return compareGreater, true
  270. }
  271. if float64obj1 == float64obj2 {
  272. return compareEqual, true
  273. }
  274. if float64obj1 < float64obj2 {
  275. return compareLess, true
  276. }
  277. }
  278. case reflect.String:
  279. {
  280. stringobj1, ok := obj1.(string)
  281. if !ok {
  282. stringobj1 = obj1Value.Convert(stringType).Interface().(string)
  283. }
  284. stringobj2, ok := obj2.(string)
  285. if !ok {
  286. stringobj2 = obj2Value.Convert(stringType).Interface().(string)
  287. }
  288. if stringobj1 > stringobj2 {
  289. return compareGreater, true
  290. }
  291. if stringobj1 == stringobj2 {
  292. return compareEqual, true
  293. }
  294. if stringobj1 < stringobj2 {
  295. return compareLess, true
  296. }
  297. }
  298. // Check for known struct types we can check for compare results.
  299. case reflect.Struct:
  300. {
  301. // All structs enter here. We're not interested in most types.
  302. if !obj1Value.CanConvert(timeType) {
  303. break
  304. }
  305. // time.Time can be compared!
  306. timeObj1, ok := obj1.(time.Time)
  307. if !ok {
  308. timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
  309. }
  310. timeObj2, ok := obj2.(time.Time)
  311. if !ok {
  312. timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
  313. }
  314. return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
  315. }
  316. case reflect.Slice:
  317. {
  318. // We only care about the []byte type.
  319. if !obj1Value.CanConvert(bytesType) {
  320. break
  321. }
  322. // []byte can be compared!
  323. bytesObj1, ok := obj1.([]byte)
  324. if !ok {
  325. bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
  326. }
  327. bytesObj2, ok := obj2.([]byte)
  328. if !ok {
  329. bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
  330. }
  331. return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
  332. }
  333. case reflect.Uintptr:
  334. {
  335. uintptrObj1, ok := obj1.(uintptr)
  336. if !ok {
  337. uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
  338. }
  339. uintptrObj2, ok := obj2.(uintptr)
  340. if !ok {
  341. uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
  342. }
  343. if uintptrObj1 > uintptrObj2 {
  344. return compareGreater, true
  345. }
  346. if uintptrObj1 == uintptrObj2 {
  347. return compareEqual, true
  348. }
  349. if uintptrObj1 < uintptrObj2 {
  350. return compareLess, true
  351. }
  352. }
  353. }
  354. return compareEqual, false
  355. }
  356. // Greater asserts that the first element is greater than the second
  357. //
  358. // assert.Greater(t, 2, 1)
  359. // assert.Greater(t, float64(2), float64(1))
  360. // assert.Greater(t, "b", "a")
  361. func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
  362. if h, ok := t.(tHelper); ok {
  363. h.Helper()
  364. }
  365. return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
  366. }
  367. // GreaterOrEqual asserts that the first element is greater than or equal to the second
  368. //
  369. // assert.GreaterOrEqual(t, 2, 1)
  370. // assert.GreaterOrEqual(t, 2, 2)
  371. // assert.GreaterOrEqual(t, "b", "a")
  372. // assert.GreaterOrEqual(t, "b", "b")
  373. func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
  374. if h, ok := t.(tHelper); ok {
  375. h.Helper()
  376. }
  377. return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
  378. }
  379. // Less asserts that the first element is less than the second
  380. //
  381. // assert.Less(t, 1, 2)
  382. // assert.Less(t, float64(1), float64(2))
  383. // assert.Less(t, "a", "b")
  384. func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
  385. if h, ok := t.(tHelper); ok {
  386. h.Helper()
  387. }
  388. return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
  389. }
  390. // LessOrEqual asserts that the first element is less than or equal to the second
  391. //
  392. // assert.LessOrEqual(t, 1, 2)
  393. // assert.LessOrEqual(t, 2, 2)
  394. // assert.LessOrEqual(t, "a", "b")
  395. // assert.LessOrEqual(t, "b", "b")
  396. func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
  397. if h, ok := t.(tHelper); ok {
  398. h.Helper()
  399. }
  400. return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
  401. }
  402. // Positive asserts that the specified element is positive
  403. //
  404. // assert.Positive(t, 1)
  405. // assert.Positive(t, 1.23)
  406. func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
  407. if h, ok := t.(tHelper); ok {
  408. h.Helper()
  409. }
  410. zero := reflect.Zero(reflect.TypeOf(e))
  411. return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
  412. }
  413. // Negative asserts that the specified element is negative
  414. //
  415. // assert.Negative(t, -1)
  416. // assert.Negative(t, -1.23)
  417. func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
  418. if h, ok := t.(tHelper); ok {
  419. h.Helper()
  420. }
  421. zero := reflect.Zero(reflect.TypeOf(e))
  422. return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
  423. }
  424. func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
  425. if h, ok := t.(tHelper); ok {
  426. h.Helper()
  427. }
  428. e1Kind := reflect.ValueOf(e1).Kind()
  429. e2Kind := reflect.ValueOf(e2).Kind()
  430. if e1Kind != e2Kind {
  431. return Fail(t, "Elements should be the same type", msgAndArgs...)
  432. }
  433. compareResult, isComparable := compare(e1, e2, e1Kind)
  434. if !isComparable {
  435. return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
  436. }
  437. if !containsValue(allowedComparesResults, compareResult) {
  438. return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
  439. }
  440. return true
  441. }
  442. func containsValue(values []CompareType, value CompareType) bool {
  443. for _, v := range values {
  444. if v == value {
  445. return true
  446. }
  447. }
  448. return false
  449. }