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