blob: 41649d26792461a0e999695e0c91a15d72b5898a [file] [log] [blame]
Holger Hildebrandtda7758b2020-03-16 11:30:03 +00001package assert
2
3import (
4 "fmt"
5 "reflect"
6)
7
mpagenkoaf801632020-07-03 10:00:42 +00008type CompareType int
9
10const (
11 compareLess CompareType = iota - 1
12 compareEqual
13 compareGreater
14)
15
khenaidoo7d3c5582021-08-11 18:09:44 -040016var (
17 intType = reflect.TypeOf(int(1))
18 int8Type = reflect.TypeOf(int8(1))
19 int16Type = reflect.TypeOf(int16(1))
20 int32Type = reflect.TypeOf(int32(1))
21 int64Type = reflect.TypeOf(int64(1))
22
23 uintType = reflect.TypeOf(uint(1))
24 uint8Type = reflect.TypeOf(uint8(1))
25 uint16Type = reflect.TypeOf(uint16(1))
26 uint32Type = reflect.TypeOf(uint32(1))
27 uint64Type = reflect.TypeOf(uint64(1))
28
29 float32Type = reflect.TypeOf(float32(1))
30 float64Type = reflect.TypeOf(float64(1))
31
32 stringType = reflect.TypeOf("")
33)
34
mpagenkoaf801632020-07-03 10:00:42 +000035func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
khenaidoo7d3c5582021-08-11 18:09:44 -040036 obj1Value := reflect.ValueOf(obj1)
37 obj2Value := reflect.ValueOf(obj2)
38
39 // throughout this switch we try and avoid calling .Convert() if possible,
40 // as this has a pretty big performance impact
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000041 switch kind {
42 case reflect.Int:
43 {
khenaidoo7d3c5582021-08-11 18:09:44 -040044 intobj1, ok := obj1.(int)
45 if !ok {
46 intobj1 = obj1Value.Convert(intType).Interface().(int)
47 }
48 intobj2, ok := obj2.(int)
49 if !ok {
50 intobj2 = obj2Value.Convert(intType).Interface().(int)
51 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000052 if intobj1 > intobj2 {
mpagenkoaf801632020-07-03 10:00:42 +000053 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000054 }
55 if intobj1 == intobj2 {
mpagenkoaf801632020-07-03 10:00:42 +000056 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000057 }
58 if intobj1 < intobj2 {
mpagenkoaf801632020-07-03 10:00:42 +000059 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000060 }
61 }
62 case reflect.Int8:
63 {
khenaidoo7d3c5582021-08-11 18:09:44 -040064 int8obj1, ok := obj1.(int8)
65 if !ok {
66 int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
67 }
68 int8obj2, ok := obj2.(int8)
69 if !ok {
70 int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
71 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000072 if int8obj1 > int8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000073 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000074 }
75 if int8obj1 == int8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000076 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000077 }
78 if int8obj1 < int8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000079 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000080 }
81 }
82 case reflect.Int16:
83 {
khenaidoo7d3c5582021-08-11 18:09:44 -040084 int16obj1, ok := obj1.(int16)
85 if !ok {
86 int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
87 }
88 int16obj2, ok := obj2.(int16)
89 if !ok {
90 int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
91 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000092 if int16obj1 > int16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000093 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000094 }
95 if int16obj1 == int16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000096 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +000097 }
98 if int16obj1 < int16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +000099 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000100 }
101 }
102 case reflect.Int32:
103 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400104 int32obj1, ok := obj1.(int32)
105 if !ok {
106 int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
107 }
108 int32obj2, ok := obj2.(int32)
109 if !ok {
110 int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
111 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000112 if int32obj1 > int32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000113 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000114 }
115 if int32obj1 == int32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000116 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000117 }
118 if int32obj1 < int32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000119 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000120 }
121 }
122 case reflect.Int64:
123 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400124 int64obj1, ok := obj1.(int64)
125 if !ok {
126 int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
127 }
128 int64obj2, ok := obj2.(int64)
129 if !ok {
130 int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
131 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000132 if int64obj1 > int64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000133 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000134 }
135 if int64obj1 == int64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000136 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000137 }
138 if int64obj1 < int64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000139 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000140 }
141 }
142 case reflect.Uint:
143 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400144 uintobj1, ok := obj1.(uint)
145 if !ok {
146 uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
147 }
148 uintobj2, ok := obj2.(uint)
149 if !ok {
150 uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
151 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000152 if uintobj1 > uintobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000153 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000154 }
155 if uintobj1 == uintobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000156 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000157 }
158 if uintobj1 < uintobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000159 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000160 }
161 }
162 case reflect.Uint8:
163 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400164 uint8obj1, ok := obj1.(uint8)
165 if !ok {
166 uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
167 }
168 uint8obj2, ok := obj2.(uint8)
169 if !ok {
170 uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
171 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000172 if uint8obj1 > uint8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000173 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000174 }
175 if uint8obj1 == uint8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000176 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000177 }
178 if uint8obj1 < uint8obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000179 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000180 }
181 }
182 case reflect.Uint16:
183 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400184 uint16obj1, ok := obj1.(uint16)
185 if !ok {
186 uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
187 }
188 uint16obj2, ok := obj2.(uint16)
189 if !ok {
190 uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
191 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000192 if uint16obj1 > uint16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000193 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000194 }
195 if uint16obj1 == uint16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000196 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000197 }
198 if uint16obj1 < uint16obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000199 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000200 }
201 }
202 case reflect.Uint32:
203 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400204 uint32obj1, ok := obj1.(uint32)
205 if !ok {
206 uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
207 }
208 uint32obj2, ok := obj2.(uint32)
209 if !ok {
210 uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
211 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000212 if uint32obj1 > uint32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000213 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000214 }
215 if uint32obj1 == uint32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000216 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000217 }
218 if uint32obj1 < uint32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000219 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000220 }
221 }
222 case reflect.Uint64:
223 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400224 uint64obj1, ok := obj1.(uint64)
225 if !ok {
226 uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
227 }
228 uint64obj2, ok := obj2.(uint64)
229 if !ok {
230 uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
231 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000232 if uint64obj1 > uint64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000233 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000234 }
235 if uint64obj1 == uint64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000236 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000237 }
238 if uint64obj1 < uint64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000239 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000240 }
241 }
242 case reflect.Float32:
243 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400244 float32obj1, ok := obj1.(float32)
245 if !ok {
246 float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
247 }
248 float32obj2, ok := obj2.(float32)
249 if !ok {
250 float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
251 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000252 if float32obj1 > float32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000253 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000254 }
255 if float32obj1 == float32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000256 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000257 }
258 if float32obj1 < float32obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000259 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000260 }
261 }
262 case reflect.Float64:
263 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400264 float64obj1, ok := obj1.(float64)
265 if !ok {
266 float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
267 }
268 float64obj2, ok := obj2.(float64)
269 if !ok {
270 float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
271 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000272 if float64obj1 > float64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000273 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000274 }
275 if float64obj1 == float64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000276 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000277 }
278 if float64obj1 < float64obj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000279 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000280 }
281 }
282 case reflect.String:
283 {
khenaidoo7d3c5582021-08-11 18:09:44 -0400284 stringobj1, ok := obj1.(string)
285 if !ok {
286 stringobj1 = obj1Value.Convert(stringType).Interface().(string)
287 }
288 stringobj2, ok := obj2.(string)
289 if !ok {
290 stringobj2 = obj2Value.Convert(stringType).Interface().(string)
291 }
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000292 if stringobj1 > stringobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000293 return compareGreater, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000294 }
295 if stringobj1 == stringobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000296 return compareEqual, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000297 }
298 if stringobj1 < stringobj2 {
mpagenkoaf801632020-07-03 10:00:42 +0000299 return compareLess, true
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000300 }
301 }
302 }
303
mpagenkoaf801632020-07-03 10:00:42 +0000304 return compareEqual, false
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000305}
306
307// Greater asserts that the first element is greater than the second
308//
309// assert.Greater(t, 2, 1)
310// assert.Greater(t, float64(2), float64(1))
311// assert.Greater(t, "b", "a")
312func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
mpagenkoaf801632020-07-03 10:00:42 +0000313 return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000314}
315
316// GreaterOrEqual asserts that the first element is greater than or equal to the second
317//
318// assert.GreaterOrEqual(t, 2, 1)
319// assert.GreaterOrEqual(t, 2, 2)
320// assert.GreaterOrEqual(t, "b", "a")
321// assert.GreaterOrEqual(t, "b", "b")
322func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
mpagenkoaf801632020-07-03 10:00:42 +0000323 return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000324}
325
326// Less asserts that the first element is less than the second
327//
328// assert.Less(t, 1, 2)
329// assert.Less(t, float64(1), float64(2))
330// assert.Less(t, "a", "b")
331func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
mpagenkoaf801632020-07-03 10:00:42 +0000332 return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000333}
334
335// LessOrEqual asserts that the first element is less than or equal to the second
336//
337// assert.LessOrEqual(t, 1, 2)
338// assert.LessOrEqual(t, 2, 2)
339// assert.LessOrEqual(t, "a", "b")
340// assert.LessOrEqual(t, "b", "b")
341func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
mpagenkoaf801632020-07-03 10:00:42 +0000342 return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
343}
344
khenaidoo7d3c5582021-08-11 18:09:44 -0400345// Positive asserts that the specified element is positive
346//
347// assert.Positive(t, 1)
348// assert.Positive(t, 1.23)
349func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
350 zero := reflect.Zero(reflect.TypeOf(e))
351 return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs)
352}
353
354// Negative asserts that the specified element is negative
355//
356// assert.Negative(t, -1)
357// assert.Negative(t, -1.23)
358func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
359 zero := reflect.Zero(reflect.TypeOf(e))
360 return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs)
361}
362
mpagenkoaf801632020-07-03 10:00:42 +0000363func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000364 if h, ok := t.(tHelper); ok {
365 h.Helper()
366 }
367
368 e1Kind := reflect.ValueOf(e1).Kind()
369 e2Kind := reflect.ValueOf(e2).Kind()
370 if e1Kind != e2Kind {
371 return Fail(t, "Elements should be the same type", msgAndArgs...)
372 }
373
mpagenkoaf801632020-07-03 10:00:42 +0000374 compareResult, isComparable := compare(e1, e2, e1Kind)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000375 if !isComparable {
376 return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
377 }
378
mpagenkoaf801632020-07-03 10:00:42 +0000379 if !containsValue(allowedComparesResults, compareResult) {
380 return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
Holger Hildebrandtda7758b2020-03-16 11:30:03 +0000381 }
382
383 return true
384}
mpagenkoaf801632020-07-03 10:00:42 +0000385
386func containsValue(values []CompareType, value CompareType) bool {
387 for _, v := range values {
388 if v == value {
389 return true
390 }
391 }
392
393 return false
394}