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}