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