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