Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}