uassert_test.gno
12.31 Kb ยท 508 lines
1package uassert_test
2
3import (
4 "errors"
5 "fmt"
6 "std"
7 "testing"
8
9 "gno.land/p/demo/uassert"
10 "gno.land/r/demo/tests"
11)
12
13var _ uassert.TestingT = (*testing.T)(nil)
14
15func TestMock(t *testing.T) {
16 mockT := new(mockTestingT)
17 mockT.empty(t)
18 uassert.NoError(mockT, errors.New("foo"))
19 mockT.equals(t, "error: unexpected error: foo")
20 uassert.NoError(mockT, errors.New("foo"), "custom message")
21 mockT.equals(t, "error: unexpected error: foo - custom message")
22 uassert.NoError(mockT, errors.New("foo"), "custom", "message")
23 mockT.equals(t, "error: unexpected error: foo - custom message")
24}
25
26func TestNoError(t *testing.T) {
27 mockT := new(mockTestingT)
28 uassert.True(t, uassert.NoError(mockT, nil))
29 mockT.empty(t)
30 uassert.False(t, uassert.NoError(mockT, errors.New("foo bar")))
31 mockT.equals(t, "error: unexpected error: foo bar")
32}
33
34func TestError(t *testing.T) {
35 mockT := new(mockTestingT)
36 uassert.True(t, uassert.Error(mockT, errors.New("foo bar")))
37 mockT.empty(t)
38 uassert.False(t, uassert.Error(mockT, nil))
39 mockT.equals(t, "error: an error is expected but got nil")
40}
41
42func TestErrorContains(t *testing.T) {
43 mockT := new(mockTestingT)
44
45 // nil error
46 var err error
47 uassert.False(t, uassert.ErrorContains(mockT, err, ""), "ErrorContains should return false for nil arg")
48}
49
50func TestTrue(t *testing.T) {
51 mockT := new(mockTestingT)
52 if !uassert.True(mockT, true) {
53 t.Error("True should return true")
54 }
55 mockT.empty(t)
56 if uassert.True(mockT, false) {
57 t.Error("True should return false")
58 }
59 mockT.equals(t, "error: should be true")
60}
61
62func TestFalse(t *testing.T) {
63 mockT := new(mockTestingT)
64 if !uassert.False(mockT, false) {
65 t.Error("False should return true")
66 }
67 mockT.empty(t)
68 if uassert.False(mockT, true) {
69 t.Error("False should return false")
70 }
71 mockT.equals(t, "error: should be false")
72}
73
74func TestPanicsWithMessage(t *testing.T) {
75 mockT := new(mockTestingT)
76 if !uassert.PanicsWithMessage(mockT, "panic", func() {
77 panic(errors.New("panic"))
78 }) {
79 t.Error("PanicsWithMessage should return true")
80 }
81 mockT.empty(t)
82
83 if uassert.PanicsWithMessage(mockT, "Panic!", func() {
84 // noop
85 }) {
86 t.Error("PanicsWithMessage should return false")
87 }
88 mockT.equals(t, "error: func should panic\n\tPanic value:\tnil")
89
90 if uassert.PanicsWithMessage(mockT, "at the disco", func() {
91 panic(errors.New("panic"))
92 }) {
93 t.Error("PanicsWithMessage should return false")
94 }
95 mockT.equals(t, "error: func should panic with message:\t\"at the disco\"\n\tActual panic value:\t\"panic\"")
96
97 if uassert.PanicsWithMessage(mockT, "Panic!", func() {
98 panic("panic")
99 }) {
100 t.Error("PanicsWithMessage should return false")
101 }
102 mockT.equals(t, "error: func should panic with message:\t\"Panic!\"\n\tActual panic value:\t\"panic\"")
103}
104
105func TestAbortsWithMessage(t *testing.T) {
106 mockT := new(mockTestingT)
107 if !uassert.AbortsWithMessage(mockT, "abort message", func() {
108 tests.ExecSwitch(cross, func() {
109 panic("abort message")
110 })
111 panic("dontcare")
112 }) {
113 t.Error("AbortsWithMessage should return true")
114 }
115 mockT.empty(t)
116
117 if uassert.AbortsWithMessage(mockT, "Abort!", func() {
118 // noop
119 }) {
120 t.Error("AbortsWithMessage should return false")
121 }
122 mockT.equals(t, "error: func should abort")
123
124 if uassert.AbortsWithMessage(mockT, "at the disco", func() {
125 tests.ExecSwitch(cross, func() {
126 panic("abort message")
127 })
128 panic("dontcare")
129 }) {
130 t.Error("AbortsWithMessage should return false (wrong message)")
131 }
132 mockT.equals(t, "error: func should abort with message:\t\"at the disco\"\n\tActual abort value:\t\"abort message\"")
133
134 // Test that non-crossing panics don't count as abort.
135 uassert.PanicsWithMessage(mockT, "non-abort panic", func() {
136 uassert.AbortsWithMessage(mockT, "dontcare2", func() {
137 panic("non-abort panic")
138 })
139 t.Error("AbortsWithMessage should not have caught non-abort panic")
140 }, "non-abort panic")
141 mockT.empty(t)
142
143 // Test case where abort value is not a string
144 if uassert.AbortsWithMessage(mockT, "doesn't matter", func() {
145 tests.ExecSwitch(cross, func() {
146 panic(123) // abort with an integer
147 })
148 panic("dontcare")
149 }) {
150 t.Error("AbortsWithMessage should return false when abort value is not a string")
151 }
152 mockT.equals(t, "error: func should abort with message:\t\"doesn't matter\"\n\tActual abort value:\t\"123\"")
153
154 // XXX: test with Error
155}
156
157func TestNotAborts(t *testing.T) {
158 mockT := new(mockTestingT)
159
160 if !uassert.NotPanics(mockT, func() {
161 // noop
162 }) {
163 t.Error("NotAborts should return true")
164 }
165 mockT.empty(t)
166
167 if uassert.NotPanics(mockT, func() {
168 tests.ExecSwitch(cross, func() {
169 panic("Abort!")
170 })
171 panic("dontcare")
172 }) {
173 t.Error("NotAborts should return false")
174 }
175 mockT.equals(t, "error: func should not abort\n\tAbort value:\tAbort!")
176}
177
178func TestNotPanics(t *testing.T) {
179 mockT := new(mockTestingT)
180
181 if !uassert.NotPanics(mockT, func() {
182 // noop
183 }) {
184 t.Error("NotPanics should return true")
185 }
186 mockT.empty(t)
187
188 if uassert.NotPanics(mockT, func() {
189 panic("Panic!")
190 }) {
191 t.Error("NotPanics should return false")
192 }
193 mockT.equals(t, "error: func should not panic\n\tPanic value:\tPanic!")
194}
195
196func TestEqual(t *testing.T) {
197 mockT := new(mockTestingT)
198
199 cases := []struct {
200 expected any
201 actual any
202 result bool
203 remark string
204 }{
205 // expected to be equal
206 {"Hello World", "Hello World", true, ""},
207 {123, 123, true, ""},
208 {123.5, 123.5, true, ""},
209 {nil, nil, true, ""},
210 {int32(123), int32(123), true, ""},
211 {uint64(123), uint64(123), true, ""},
212 {std.Address("g12345"), std.Address("g12345"), true, ""},
213 // XXX: continue
214
215 // not expected to be equal
216 {"Hello World", 42, false, ""},
217 {41, 42, false, ""},
218 {10, uint(10), false, ""},
219 // XXX: continue
220
221 // expected to raise errors
222 // XXX: todo
223 }
224
225 for _, c := range cases {
226 name := fmt.Sprintf("Equal(%v, %v)", c.expected, c.actual)
227 t.Run(name, func(t *testing.T) {
228 res := uassert.Equal(mockT, c.expected, c.actual)
229
230 if res != c.result {
231 t.Errorf("%s should return %v: %s - %s", name, c.result, c.remark, mockT.actualString())
232 }
233 })
234 }
235}
236
237func TestNotEqual(t *testing.T) {
238 mockT := new(mockTestingT)
239
240 cases := []struct {
241 expected any
242 actual any
243 result bool
244 remark string
245 }{
246 // expected to be not equal
247 {"Hello World", "Hello", true, ""},
248 {123, 124, true, ""},
249 {123.5, 123.6, true, ""},
250 {nil, 123, true, ""},
251 {int32(123), int32(124), true, ""},
252 {uint64(123), uint64(124), true, ""},
253 {std.Address("g12345"), std.Address("g67890"), true, ""},
254 // XXX: continue
255
256 // not expected to be not equal
257 {"Hello World", "Hello World", false, ""},
258 {123, 123, false, ""},
259 {123.5, 123.5, false, ""},
260 {nil, nil, false, ""},
261 {int32(123), int32(123), false, ""},
262 {uint64(123), uint64(123), false, ""},
263 {std.Address("g12345"), std.Address("g12345"), false, ""},
264 // XXX: continue
265
266 // expected to raise errors
267 // XXX: todo
268 }
269
270 for _, c := range cases {
271 name := fmt.Sprintf("NotEqual(%v, %v)", c.expected, c.actual)
272 t.Run(name, func(t *testing.T) {
273 res := uassert.NotEqual(mockT, c.expected, c.actual)
274
275 if res != c.result {
276 t.Errorf("%s should return %v: %s - %s", name, c.result, c.remark, mockT.actualString())
277 }
278 })
279 }
280}
281
282type myStruct struct {
283 S string
284 I int
285}
286
287func TestEmpty(t *testing.T) {
288 mockT := new(mockTestingT)
289
290 cases := []struct {
291 obj any
292 expectedEmpty bool
293 }{
294 // expected to be empty
295 {"", true},
296 {0, true},
297 {int(0), true},
298 {int32(0), true},
299 {int64(0), true},
300 {uint(0), true},
301 // XXX: continue
302
303 // not expected to be empty
304 {"Hello World", false},
305 {1, false},
306 {int32(1), false},
307 {uint64(1), false},
308 {std.Address("g12345"), false},
309
310 // unsupported
311 {nil, false},
312 {myStruct{}, false},
313 {&myStruct{}, false},
314 }
315
316 for _, c := range cases {
317 name := fmt.Sprintf("Empty(%v)", c.obj)
318 t.Run(name, func(t *testing.T) {
319 res := uassert.Empty(mockT, c.obj)
320
321 if res != c.expectedEmpty {
322 t.Errorf("%s should return %v: %s", name, c.expectedEmpty, mockT.actualString())
323 }
324 })
325 }
326}
327
328func TestEqualWithStringDiff(t *testing.T) {
329 cases := []struct {
330 name string
331 expected string
332 actual string
333 shouldPass bool
334 expectedMsg string
335 }{
336 {
337 name: "Identical strings",
338 expected: "Hello, world!",
339 actual: "Hello, world!",
340 shouldPass: true,
341 expectedMsg: "",
342 },
343 {
344 name: "Different strings - simple",
345 expected: "Hello, world!",
346 actual: "Hello, World!",
347 shouldPass: false,
348 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: Hello, [-w][+W]orld!",
349 },
350 {
351 name: "Different strings - complex",
352 expected: "The quick brown fox jumps over the lazy dog",
353 actual: "The quick brown cat jumps over the lazy dog",
354 shouldPass: false,
355 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: The quick brown [-fox][+cat] jumps over the lazy dog",
356 },
357 {
358 name: "Different strings - prefix",
359 expected: "prefix_string",
360 actual: "string",
361 shouldPass: false,
362 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: [-prefix_]string",
363 },
364 {
365 name: "Different strings - suffix",
366 expected: "string",
367 actual: "string_suffix",
368 shouldPass: false,
369 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: string[+_suffix]",
370 },
371 {
372 name: "Empty string vs non-empty string",
373 expected: "",
374 actual: "non-empty",
375 shouldPass: false,
376 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: [+non-empty]",
377 },
378 {
379 name: "Non-empty string vs empty string",
380 expected: "non-empty",
381 actual: "",
382 shouldPass: false,
383 expectedMsg: "error: uassert.Equal: strings are different\n\tDiff: [-non-empty]",
384 },
385 }
386
387 for _, tc := range cases {
388 t.Run(tc.name, func(t *testing.T) {
389 mockT := &mockTestingT{}
390 result := uassert.Equal(mockT, tc.expected, tc.actual)
391
392 if result != tc.shouldPass {
393 t.Errorf("Expected Equal to return %v, but got %v", tc.shouldPass, result)
394 }
395
396 if tc.shouldPass {
397 mockT.empty(t)
398 } else {
399 mockT.equals(t, tc.expectedMsg)
400 }
401 })
402 }
403}
404
405func TestNotEmpty(t *testing.T) {
406 mockT := new(mockTestingT)
407
408 cases := []struct {
409 obj any
410 expectedNotEmpty bool
411 }{
412 // expected to be empty
413 {"", false},
414 {0, false},
415 {int(0), false},
416 {int32(0), false},
417 {int64(0), false},
418 {uint(0), false},
419 {std.Address(""), false},
420
421 // not expected to be empty
422 {"Hello World", true},
423 {1, true},
424 {int32(1), true},
425 {uint64(1), true},
426 {std.Address("g12345"), true},
427
428 // unsupported
429 {nil, false},
430 {myStruct{}, false},
431 {&myStruct{}, false},
432 }
433
434 for _, c := range cases {
435 name := fmt.Sprintf("NotEmpty(%v)", c.obj)
436 t.Run(name, func(t *testing.T) {
437 res := uassert.NotEmpty(mockT, c.obj)
438
439 if res != c.expectedNotEmpty {
440 t.Errorf("%s should return %v: %s", name, c.expectedNotEmpty, mockT.actualString())
441 }
442 })
443 }
444}
445
446func TestNil(t *testing.T) {
447 mockT := new(mockTestingT)
448 if !uassert.Nil(mockT, nil) {
449 t.Error("Nil should return true")
450 }
451 mockT.empty(t)
452 if uassert.Nil(mockT, 0) {
453 t.Error("Nil should return false")
454 }
455 mockT.equals(t, "error: should be nil")
456 if uassert.Nil(mockT, (*int)(nil)) {
457 t.Error("Nil should return false")
458 }
459 mockT.equals(t, "error: should be nil")
460}
461
462func TestNotNil(t *testing.T) {
463 mockT := new(mockTestingT)
464 if uassert.NotNil(mockT, nil) {
465 t.Error("NotNil should return false")
466 }
467 mockT.equals(t, "error: should not be nil")
468 if !uassert.NotNil(mockT, 0) {
469 t.Error("NotNil should return true")
470 }
471 mockT.empty(t)
472 if !uassert.NotNil(mockT, (*int)(nil)) {
473 t.Error("NotNil should return true")
474 }
475 mockT.empty(t)
476}
477
478func TestTypedNil(t *testing.T) {
479 mockT := new(mockTestingT)
480 if uassert.TypedNil(mockT, nil) {
481 t.Error("TypedNil should return false")
482 }
483 mockT.equals(t, "error: should be typed-nil but got nil instead")
484 if uassert.TypedNil(mockT, 0) {
485 t.Error("TypedNil should return false")
486 }
487 mockT.equals(t, "error: should be typed-nil")
488 if !uassert.TypedNil(mockT, (*int)(nil)) {
489 t.Error("TypedNil should return true")
490 }
491 mockT.empty(t)
492}
493
494func TestNotTypedNil(t *testing.T) {
495 mockT := new(mockTestingT)
496 if !uassert.NotTypedNil(mockT, nil) {
497 t.Error("NotTypedNil should return true")
498 }
499 mockT.empty(t)
500 if !uassert.NotTypedNil(mockT, 0) {
501 t.Error("NotTypedNil should return true")
502 }
503 mockT.empty(t)
504 if uassert.NotTypedNil(mockT, (*int)(nil)) {
505 t.Error("NotTypedNil should return false")
506 }
507 mockT.equals(t, "error: should not be typed-nil")
508}