list_test.gno
10.54 Kb ยท 491 lines
1package list
2
3import (
4 "testing"
5
6 "gno.land/p/nt/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_Tree(t *testing.T) {
225 var l List
226 l.Append(1, 2, 3)
227
228 rotree := l.Tree()
229 expected := 3
230
231 // Reverse iterate through the ReadOnlyTree
232 rotree.ReverseIterateByOffset(0, rotree.Size(), func(key string, value any) bool {
233 intValue := value.(int)
234 if intValue != expected {
235 t.Errorf("ReadOnlyTree expected %d, got %d", expected, intValue)
236 }
237 expected--
238 return false
239 })
240}
241
242func TestList_EmptyOperations(t *testing.T) {
243 var l List
244
245 // Operations on empty list
246 if v := l.Get(0); v != nil {
247 t.Errorf("Get(0) on empty list = %v; want nil", v)
248 }
249
250 // Set should work at index 0 for empty list (append case)
251 if ok := l.Set(0, 1); !ok {
252 t.Error("Set(0,1) on empty list = false; want true")
253 }
254 if v := l.Get(0); v != 1 {
255 t.Errorf("Get(0) after Set = %v; want 1", v)
256 }
257
258 l = List{} // Reset to empty list
259 if v, ok := l.Delete(0); ok || v != nil {
260 t.Errorf("Delete(0) on empty list = %v, %v; want nil, false", v, ok)
261 }
262 if values := l.Slice(0, 1); values != nil {
263 t.Errorf("Range(0,1) on empty list = %v; want nil", values)
264 }
265}
266
267func TestList_DifferentTypes(t *testing.T) {
268 var l List
269
270 // Test with different types
271 l.Append(42, "hello", true, 3.14)
272
273 if v := l.Get(0).(int); v != 42 {
274 t.Errorf("Get(0) = %v; want 42", v)
275 }
276 if v := l.Get(1).(string); v != "hello" {
277 t.Errorf("Get(1) = %v; want 'hello'", v)
278 }
279 if v := l.Get(2).(bool); !v {
280 t.Errorf("Get(2) = %v; want true", v)
281 }
282 if v := l.Get(3).(float64); v != 3.14 {
283 t.Errorf("Get(3) = %v; want 3.14", v)
284 }
285}
286
287func TestList_LargeOperations(t *testing.T) {
288 var l List
289
290 // Test with larger number of elements
291 n := 1000
292 for i := 0; i < n; i++ {
293 l.Append(i)
294 }
295
296 if l.Len() != n {
297 t.Errorf("Len() = %d; want %d", l.Len(), n)
298 }
299
300 // Test range on large list
301 values := l.Slice(n-3, n)
302 expected := []any{n - 3, n - 2, n - 1}
303 if !sliceEqual(values, expected) {
304 t.Errorf("Range(%d,%d) = %v; want %v", n-3, n, values, expected)
305 }
306
307 // Test large range deletion
308 deleted := l.DeleteRange(100, 900)
309 if deleted != 800 {
310 t.Errorf("DeleteRange(100,900) = %d; want 800", deleted)
311 }
312 if l.Len() != 200 {
313 t.Errorf("Len() after large delete = %d; want 200", l.Len())
314 }
315}
316
317func TestList_ChainedOperations(t *testing.T) {
318 var l List
319
320 // Test sequence of operations
321 l.Append(1, 2, 3)
322 l.Delete(1)
323 l.Append(4)
324 l.Set(1, 5)
325
326 expected := []any{1, 5, 4}
327 for i, want := range expected {
328 if got := l.Get(i); got != want {
329 t.Errorf("index %d = %v; want %v", i, got, want)
330 }
331 }
332}
333
334func TestList_RangeEdgeCases(t *testing.T) {
335 var l List
336 l.Append(1, 2, 3, 4, 5)
337
338 // Test various edge cases for Range
339 cases := []struct {
340 start, end int
341 want []any
342 }{
343 {-10, 2, []any{1, 2}},
344 {3, 10, []any{4, 5}},
345 {0, 0, nil},
346 {5, 5, nil},
347 {4, 3, nil},
348 {-1, -1, nil},
349 }
350
351 for _, tc := range cases {
352 got := l.Slice(tc.start, tc.end)
353 if !sliceEqual(got, tc.want) {
354 t.Errorf("Slice(%d,%d) = %v; want %v", tc.start, tc.end, got, tc.want)
355 }
356 }
357}
358
359func TestList_IndexConsistency(t *testing.T) {
360 var l List
361
362 // Initial additions
363 l.Append(1, 2, 3, 4, 5) // [1,2,3,4,5]
364
365 // Delete from middle
366 l.Delete(2) // [1,2,4,5]
367
368 // Add more elements
369 l.Append(6, 7) // [1,2,4,5,6,7]
370
371 // Delete range from middle
372 l.DeleteRange(1, 4) // [1,6,7]
373
374 // Add more elements
375 l.Append(8, 9, 10) // [1,6,7,8,9,10]
376
377 // Verify sequence is continuous
378 expected := []any{1, 6, 7, 8, 9, 10}
379 for i, want := range expected {
380 if got := l.Get(i); got != want {
381 t.Errorf("index %d = %v; want %v", i, got, want)
382 }
383 }
384
385 // Verify no extra elements exist
386 if l.Len() != len(expected) {
387 t.Errorf("length = %d; want %d", l.Len(), len(expected))
388 }
389
390 // Verify all indices are accessible
391 allValues := l.Slice(0, l.Len())
392 if !sliceEqual(allValues, expected) {
393 t.Errorf("Slice(0, Len()) = %v; want %v", allValues, expected)
394 }
395
396 // Verify no gaps in iteration
397 var iteratedValues []any
398 var indices []int
399 l.ForEach(func(index int, value any) bool {
400 iteratedValues = append(iteratedValues, value)
401 indices = append(indices, index)
402 return false
403 })
404
405 // Check values from iteration
406 if !sliceEqual(iteratedValues, expected) {
407 t.Errorf("ForEach values = %v; want %v", iteratedValues, expected)
408 }
409
410 // Check indices are sequential
411 for i, idx := range indices {
412 if idx != i {
413 t.Errorf("ForEach index %d = %d; want %d", i, idx, i)
414 }
415 }
416}
417
418func TestList_RecursiveSafety(t *testing.T) {
419 // Create a new list
420 l := &List{}
421
422 // Add some initial values
423 l.Append("id1")
424 l.Append("id2")
425 l.Append("id3")
426
427 // Test deep list traversal
428 found := false
429 l.ForEach(func(i int, v any) bool {
430 if str, ok := v.(string); ok {
431 if str == "id2" {
432 found = true
433 return true // stop iteration
434 }
435 }
436 return false // continue iteration
437 })
438
439 if !found {
440 t.Error("Failed to find expected value in list")
441 }
442
443 short := testing.Short()
444
445 // Test recursive safety by performing multiple operations
446 for i := 0; i < 1000; i++ {
447 // Add new value
448 l.Append(ufmt.Sprintf("id%d", i+4))
449
450 if !short {
451 // Search for a value
452 var lastFound bool
453 l.ForEach(func(j int, v any) bool {
454 if str, ok := v.(string); ok {
455 if str == ufmt.Sprintf("id%d", i+3) {
456 lastFound = true
457 return true
458 }
459 }
460 return false
461 })
462
463 if !lastFound {
464 t.Errorf("Failed to find value id%d after insertion", i+3)
465 }
466 }
467 }
468
469 // Verify final length
470 expectedLen := 1003 // 3 initial + 1000 added
471 if l.Len() != expectedLen {
472 t.Errorf("Expected length %d, got %d", expectedLen, l.Len())
473 }
474
475 if short {
476 t.Skip("skipping extended recursive safety test in short mode")
477 }
478}
479
480// Helper function to compare slices
481func sliceEqual(a, b []any) bool {
482 if len(a) != len(b) {
483 return false
484 }
485 for i := range a {
486 if a[i] != b[i] {
487 return false
488 }
489 }
490 return true
491}