list_test.gno

10.16 Kb ยท 473 lines
  1package list
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/demo/ufmt"
  7)
  8
  9func TestList_Basic(t *testing.T) {
 10	var l List
 11
 12	// Test empty list
 13	if l.Len() != 0 {
 14		t.Errorf("new list should be empty, got len %d", l.Len())
 15	}
 16
 17	// Test append and length
 18	l.Append(1, 2, 3)
 19	if l.Len() != 3 {
 20		t.Errorf("expected len 3, got %d", l.Len())
 21	}
 22
 23	// Test get
 24	if v := l.Get(0); v != 1 {
 25		t.Errorf("expected 1 at index 0, got %v", v)
 26	}
 27	if v := l.Get(1); v != 2 {
 28		t.Errorf("expected 2 at index 1, got %v", v)
 29	}
 30	if v := l.Get(2); v != 3 {
 31		t.Errorf("expected 3 at index 2, got %v", v)
 32	}
 33
 34	// Test out of bounds
 35	if v := l.Get(-1); v != nil {
 36		t.Errorf("expected nil for negative index, got %v", v)
 37	}
 38	if v := l.Get(3); v != nil {
 39		t.Errorf("expected nil for out of bounds index, got %v", v)
 40	}
 41}
 42
 43func TestList_Set(t *testing.T) {
 44	var l List
 45	l.Append(1, 2, 3)
 46
 47	// Test valid set within bounds
 48	if ok := l.Set(1, 42); !ok {
 49		t.Error("Set should return true for valid index")
 50	}
 51	if v := l.Get(1); v != 42 {
 52		t.Errorf("expected 42 after Set, got %v", v)
 53	}
 54
 55	// Test set at size (append)
 56	if ok := l.Set(3, 4); !ok {
 57		t.Error("Set should return true when appending at size")
 58	}
 59	if v := l.Get(3); v != 4 {
 60		t.Errorf("expected 4 after Set at size, got %v", v)
 61	}
 62
 63	// Test invalid sets
 64	if ok := l.Set(-1, 10); ok {
 65		t.Error("Set should return false for negative index")
 66	}
 67	if ok := l.Set(5, 10); ok {
 68		t.Error("Set should return false for index > size")
 69	}
 70
 71	// Verify list state hasn't changed after invalid operations
 72	expected := []any{1, 42, 3, 4}
 73	for i, want := range expected {
 74		if got := l.Get(i); got != want {
 75			t.Errorf("index %d = %v; want %v", i, got, want)
 76		}
 77	}
 78}
 79
 80func TestList_Delete(t *testing.T) {
 81	var l List
 82	l.Append(1, 2, 3)
 83
 84	// Test valid delete
 85	if v, ok := l.Delete(1); !ok || v != 2 {
 86		t.Errorf("Delete(1) = %v, %v; want 2, true", v, ok)
 87	}
 88	if l.Len() != 2 {
 89		t.Errorf("expected len 2 after delete, got %d", l.Len())
 90	}
 91	if v := l.Get(1); v != 3 {
 92		t.Errorf("expected 3 at index 1 after delete, got %v", v)
 93	}
 94
 95	// Test invalid delete
 96	if v, ok := l.Delete(-1); ok || v != nil {
 97		t.Errorf("Delete(-1) = %v, %v; want nil, false", v, ok)
 98	}
 99	if v, ok := l.Delete(2); ok || v != nil {
100		t.Errorf("Delete(2) = %v, %v; want nil, false", v, ok)
101	}
102}
103
104func TestList_Slice(t *testing.T) {
105	var l List
106	l.Append(1, 2, 3, 4, 5)
107
108	// Test valid ranges
109	values := l.Slice(1, 4)
110	expected := []any{2, 3, 4}
111	if !sliceEqual(values, expected) {
112		t.Errorf("Slice(1,4) = %v; want %v", values, expected)
113	}
114
115	// Test edge cases
116	if values := l.Slice(-1, 2); !sliceEqual(values, []any{1, 2}) {
117		t.Errorf("Slice(-1,2) = %v; want [1 2]", values)
118	}
119	if values := l.Slice(3, 10); !sliceEqual(values, []any{4, 5}) {
120		t.Errorf("Slice(3,10) = %v; want [4 5]", values)
121	}
122	if values := l.Slice(3, 2); values != nil {
123		t.Errorf("Slice(3,2) = %v; want nil", values)
124	}
125}
126
127func TestList_ForEach(t *testing.T) {
128	var l List
129	l.Append(1, 2, 3)
130
131	sum := 0
132	l.ForEach(func(index int, value any) bool {
133		sum += value.(int)
134		return false
135	})
136
137	if sum != 6 {
138		t.Errorf("ForEach sum = %d; want 6", sum)
139	}
140
141	// Test early termination
142	count := 0
143	l.ForEach(func(index int, value any) bool {
144		count++
145		return true // stop after first item
146	})
147
148	if count != 1 {
149		t.Errorf("ForEach early termination count = %d; want 1", count)
150	}
151}
152
153func TestList_Clone(t *testing.T) {
154	var l List
155	l.Append(1, 2, 3)
156
157	clone := l.Clone()
158
159	// Test same length
160	if clone.Len() != l.Len() {
161		t.Errorf("clone.Len() = %d; want %d", clone.Len(), l.Len())
162	}
163
164	// Test same values
165	for i := 0; i < l.Len(); i++ {
166		if clone.Get(i) != l.Get(i) {
167			t.Errorf("clone.Get(%d) = %v; want %v", i, clone.Get(i), l.Get(i))
168		}
169	}
170
171	// Test independence
172	l.Set(0, 42)
173	if clone.Get(0) == l.Get(0) {
174		t.Error("clone should be independent of original")
175	}
176}
177
178func TestList_DeleteRange(t *testing.T) {
179	var l List
180	l.Append(1, 2, 3, 4, 5)
181
182	// Test valid range delete
183	deleted := l.DeleteRange(1, 4)
184	if deleted != 3 {
185		t.Errorf("DeleteRange(1,4) deleted %d elements; want 3", deleted)
186	}
187	if l.Len() != 2 {
188		t.Errorf("after DeleteRange(1,4) len = %d; want 2", l.Len())
189	}
190	expected := []any{1, 5}
191	for i, want := range expected {
192		if got := l.Get(i); got != want {
193			t.Errorf("after DeleteRange(1,4) index %d = %v; want %v", i, got, want)
194		}
195	}
196
197	// Test edge cases
198	l = List{}
199	l.Append(1, 2, 3)
200
201	// Delete with negative start
202	if deleted := l.DeleteRange(-1, 2); deleted != 2 {
203		t.Errorf("DeleteRange(-1,2) deleted %d elements; want 2", deleted)
204	}
205
206	// Delete with end > length
207	l = List{}
208	l.Append(1, 2, 3)
209	if deleted := l.DeleteRange(1, 5); deleted != 2 {
210		t.Errorf("DeleteRange(1,5) deleted %d elements; want 2", deleted)
211	}
212
213	// Delete invalid range
214	if deleted := l.DeleteRange(2, 1); deleted != 0 {
215		t.Errorf("DeleteRange(2,1) deleted %d elements; want 0", deleted)
216	}
217
218	// Delete empty range
219	if deleted := l.DeleteRange(1, 1); deleted != 0 {
220		t.Errorf("DeleteRange(1,1) deleted %d elements; want 0", deleted)
221	}
222}
223
224func TestList_EmptyOperations(t *testing.T) {
225	var l List
226
227	// Operations on empty list
228	if v := l.Get(0); v != nil {
229		t.Errorf("Get(0) on empty list = %v; want nil", v)
230	}
231
232	// Set should work at index 0 for empty list (append case)
233	if ok := l.Set(0, 1); !ok {
234		t.Error("Set(0,1) on empty list = false; want true")
235	}
236	if v := l.Get(0); v != 1 {
237		t.Errorf("Get(0) after Set = %v; want 1", v)
238	}
239
240	l = List{} // Reset to empty list
241	if v, ok := l.Delete(0); ok || v != nil {
242		t.Errorf("Delete(0) on empty list = %v, %v; want nil, false", v, ok)
243	}
244	if values := l.Slice(0, 1); values != nil {
245		t.Errorf("Range(0,1) on empty list = %v; want nil", values)
246	}
247}
248
249func TestList_DifferentTypes(t *testing.T) {
250	var l List
251
252	// Test with different types
253	l.Append(42, "hello", true, 3.14)
254
255	if v := l.Get(0).(int); v != 42 {
256		t.Errorf("Get(0) = %v; want 42", v)
257	}
258	if v := l.Get(1).(string); v != "hello" {
259		t.Errorf("Get(1) = %v; want 'hello'", v)
260	}
261	if v := l.Get(2).(bool); !v {
262		t.Errorf("Get(2) = %v; want true", v)
263	}
264	if v := l.Get(3).(float64); v != 3.14 {
265		t.Errorf("Get(3) = %v; want 3.14", v)
266	}
267}
268
269func TestList_LargeOperations(t *testing.T) {
270	var l List
271
272	// Test with larger number of elements
273	n := 1000
274	for i := 0; i < n; i++ {
275		l.Append(i)
276	}
277
278	if l.Len() != n {
279		t.Errorf("Len() = %d; want %d", l.Len(), n)
280	}
281
282	// Test range on large list
283	values := l.Slice(n-3, n)
284	expected := []any{n - 3, n - 2, n - 1}
285	if !sliceEqual(values, expected) {
286		t.Errorf("Range(%d,%d) = %v; want %v", n-3, n, values, expected)
287	}
288
289	// Test large range deletion
290	deleted := l.DeleteRange(100, 900)
291	if deleted != 800 {
292		t.Errorf("DeleteRange(100,900) = %d; want 800", deleted)
293	}
294	if l.Len() != 200 {
295		t.Errorf("Len() after large delete = %d; want 200", l.Len())
296	}
297}
298
299func TestList_ChainedOperations(t *testing.T) {
300	var l List
301
302	// Test sequence of operations
303	l.Append(1, 2, 3)
304	l.Delete(1)
305	l.Append(4)
306	l.Set(1, 5)
307
308	expected := []any{1, 5, 4}
309	for i, want := range expected {
310		if got := l.Get(i); got != want {
311			t.Errorf("index %d = %v; want %v", i, got, want)
312		}
313	}
314}
315
316func TestList_RangeEdgeCases(t *testing.T) {
317	var l List
318	l.Append(1, 2, 3, 4, 5)
319
320	// Test various edge cases for Range
321	cases := []struct {
322		start, end int
323		want       []any
324	}{
325		{-10, 2, []any{1, 2}},
326		{3, 10, []any{4, 5}},
327		{0, 0, nil},
328		{5, 5, nil},
329		{4, 3, nil},
330		{-1, -1, nil},
331	}
332
333	for _, tc := range cases {
334		got := l.Slice(tc.start, tc.end)
335		if !sliceEqual(got, tc.want) {
336			t.Errorf("Slice(%d,%d) = %v; want %v", tc.start, tc.end, got, tc.want)
337		}
338	}
339}
340
341func TestList_IndexConsistency(t *testing.T) {
342	var l List
343
344	// Initial additions
345	l.Append(1, 2, 3, 4, 5) // [1,2,3,4,5]
346
347	// Delete from middle
348	l.Delete(2) // [1,2,4,5]
349
350	// Add more elements
351	l.Append(6, 7) // [1,2,4,5,6,7]
352
353	// Delete range from middle
354	l.DeleteRange(1, 4) // [1,6,7]
355
356	// Add more elements
357	l.Append(8, 9, 10) // [1,6,7,8,9,10]
358
359	// Verify sequence is continuous
360	expected := []any{1, 6, 7, 8, 9, 10}
361	for i, want := range expected {
362		if got := l.Get(i); got != want {
363			t.Errorf("index %d = %v; want %v", i, got, want)
364		}
365	}
366
367	// Verify no extra elements exist
368	if l.Len() != len(expected) {
369		t.Errorf("length = %d; want %d", l.Len(), len(expected))
370	}
371
372	// Verify all indices are accessible
373	allValues := l.Slice(0, l.Len())
374	if !sliceEqual(allValues, expected) {
375		t.Errorf("Slice(0, Len()) = %v; want %v", allValues, expected)
376	}
377
378	// Verify no gaps in iteration
379	var iteratedValues []any
380	var indices []int
381	l.ForEach(func(index int, value any) bool {
382		iteratedValues = append(iteratedValues, value)
383		indices = append(indices, index)
384		return false
385	})
386
387	// Check values from iteration
388	if !sliceEqual(iteratedValues, expected) {
389		t.Errorf("ForEach values = %v; want %v", iteratedValues, expected)
390	}
391
392	// Check indices are sequential
393	for i, idx := range indices {
394		if idx != i {
395			t.Errorf("ForEach index %d = %d; want %d", i, idx, i)
396		}
397	}
398}
399
400func TestList_RecursiveSafety(t *testing.T) {
401	// Create a new list
402	l := &List{}
403
404	// Add some initial values
405	l.Append("id1")
406	l.Append("id2")
407	l.Append("id3")
408
409	// Test deep list traversal
410	found := false
411	l.ForEach(func(i int, v any) bool {
412		if str, ok := v.(string); ok {
413			if str == "id2" {
414				found = true
415				return true // stop iteration
416			}
417		}
418		return false // continue iteration
419	})
420
421	if !found {
422		t.Error("Failed to find expected value in list")
423	}
424
425	short := testing.Short()
426
427	// Test recursive safety by performing multiple operations
428	for i := 0; i < 1000; i++ {
429		// Add new value
430		l.Append(ufmt.Sprintf("id%d", i+4))
431
432		if !short {
433			// Search for a value
434			var lastFound bool
435			l.ForEach(func(j int, v any) bool {
436				if str, ok := v.(string); ok {
437					if str == ufmt.Sprintf("id%d", i+3) {
438						lastFound = true
439						return true
440					}
441				}
442				return false
443			})
444
445			if !lastFound {
446				t.Errorf("Failed to find value id%d after insertion", i+3)
447			}
448		}
449	}
450
451	// Verify final length
452	expectedLen := 1003 // 3 initial + 1000 added
453	if l.Len() != expectedLen {
454		t.Errorf("Expected length %d, got %d", expectedLen, l.Len())
455	}
456
457	if short {
458		t.Skip("skipping extended recursive safety test in short mode")
459	}
460}
461
462// Helper function to compare slices
463func sliceEqual(a, b []any) bool {
464	if len(a) != len(b) {
465		return false
466	}
467	for i := range a {
468		if a[i] != b[i] {
469			return false
470		}
471	}
472	return true
473}