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}