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