ulist_test.gno

27.10 Kb ยท 1422 lines
   1package ulist
   2
   3import (
   4	"testing"
   5
   6	"gno.land/p/demo/uassert"
   7	"gno.land/p/demo/ufmt"
   8	"gno.land/p/moul/typeutil"
   9)
  10
  11func TestNew(t *testing.T) {
  12	l := New()
  13	uassert.Equal(t, 0, l.Size())
  14	uassert.Equal(t, 0, l.TotalSize())
  15}
  16
  17func TestListAppendAndGet(t *testing.T) {
  18	tests := []struct {
  19		name     string
  20		setup    func() *List
  21		index    int
  22		expected any
  23	}{
  24		{
  25			name: "empty list",
  26			setup: func() *List {
  27				return New()
  28			},
  29			index:    0,
  30			expected: nil,
  31		},
  32		{
  33			name: "single append and get",
  34			setup: func() *List {
  35				l := New()
  36				l.Append(42)
  37				return l
  38			},
  39			index:    0,
  40			expected: 42,
  41		},
  42		{
  43			name: "multiple appends and get first",
  44			setup: func() *List {
  45				l := New()
  46				l.Append(1)
  47				l.Append(2)
  48				l.Append(3)
  49				return l
  50			},
  51			index:    0,
  52			expected: 1,
  53		},
  54		{
  55			name: "multiple appends and get last",
  56			setup: func() *List {
  57				l := New()
  58				l.Append(1)
  59				l.Append(2)
  60				l.Append(3)
  61				return l
  62			},
  63			index:    2,
  64			expected: 3,
  65		},
  66		{
  67			name: "get with invalid index",
  68			setup: func() *List {
  69				l := New()
  70				l.Append(1)
  71				return l
  72			},
  73			index:    1,
  74			expected: nil,
  75		},
  76		{
  77			name: "31 items get first",
  78			setup: func() *List {
  79				l := New()
  80				for i := 0; i < 31; i++ {
  81					l.Append(i)
  82				}
  83				return l
  84			},
  85			index:    0,
  86			expected: 0,
  87		},
  88		{
  89			name: "31 items get last",
  90			setup: func() *List {
  91				l := New()
  92				for i := 0; i < 31; i++ {
  93					l.Append(i)
  94				}
  95				return l
  96			},
  97			index:    30,
  98			expected: 30,
  99		},
 100		{
 101			name: "31 items get middle",
 102			setup: func() *List {
 103				l := New()
 104				for i := 0; i < 31; i++ {
 105					l.Append(i)
 106				}
 107				return l
 108			},
 109			index:    15,
 110			expected: 15,
 111		},
 112		{
 113			name: "values around power of 2 boundary",
 114			setup: func() *List {
 115				l := New()
 116				for i := 0; i < 18; i++ {
 117					l.Append(i)
 118				}
 119				return l
 120			},
 121			index:    15,
 122			expected: 15,
 123		},
 124		{
 125			name: "values at power of 2",
 126			setup: func() *List {
 127				l := New()
 128				for i := 0; i < 18; i++ {
 129					l.Append(i)
 130				}
 131				return l
 132			},
 133			index:    16,
 134			expected: 16,
 135		},
 136		{
 137			name: "values after power of 2",
 138			setup: func() *List {
 139				l := New()
 140				for i := 0; i < 18; i++ {
 141					l.Append(i)
 142				}
 143				return l
 144			},
 145			index:    17,
 146			expected: 17,
 147		},
 148	}
 149
 150	for _, tt := range tests {
 151		t.Run(tt.name, func(t *testing.T) {
 152			l := tt.setup()
 153			got := l.Get(tt.index)
 154			if got != tt.expected {
 155				t.Errorf("List.Get() = %v, want %v", got, tt.expected)
 156			}
 157		})
 158	}
 159}
 160
 161// generateSequence creates a slice of integers from 0 to n-1
 162func generateSequence(n int) []any {
 163	result := make([]any, n)
 164	for i := 0; i < n; i++ {
 165		result[i] = i
 166	}
 167	return result
 168}
 169
 170func TestListDelete(t *testing.T) {
 171	tests := []struct {
 172		name          string
 173		setup         func() *List
 174		deleteIndices []int
 175		expectedErr   error
 176		expectedSize  int
 177	}{
 178		{
 179			name: "delete single element",
 180			setup: func() *List {
 181				l := New()
 182				l.Append(1, 2, 3)
 183				return l
 184			},
 185			deleteIndices: []int{1},
 186			expectedErr:   nil,
 187			expectedSize:  2,
 188		},
 189		{
 190			name: "delete multiple elements",
 191			setup: func() *List {
 192				l := New()
 193				l.Append(1, 2, 3, 4, 5)
 194				return l
 195			},
 196			deleteIndices: []int{0, 2, 4},
 197			expectedErr:   nil,
 198			expectedSize:  2,
 199		},
 200		{
 201			name: "delete with negative index",
 202			setup: func() *List {
 203				l := New()
 204				l.Append(1)
 205				return l
 206			},
 207			deleteIndices: []int{-1},
 208			expectedErr:   ErrOutOfBounds,
 209			expectedSize:  1,
 210		},
 211		{
 212			name: "delete beyond size",
 213			setup: func() *List {
 214				l := New()
 215				l.Append(1)
 216				return l
 217			},
 218			deleteIndices: []int{1},
 219			expectedErr:   ErrOutOfBounds,
 220			expectedSize:  1,
 221		},
 222		{
 223			name: "delete already deleted element",
 224			setup: func() *List {
 225				l := New()
 226				l.Append(1)
 227				l.Delete(0)
 228				return l
 229			},
 230			deleteIndices: []int{0},
 231			expectedErr:   ErrDeleted,
 232			expectedSize:  0,
 233		},
 234		{
 235			name: "delete multiple elements in reverse",
 236			setup: func() *List {
 237				l := New()
 238				l.Append(1, 2, 3, 4, 5)
 239				return l
 240			},
 241			deleteIndices: []int{4, 2, 0},
 242			expectedErr:   nil,
 243			expectedSize:  2,
 244		},
 245	}
 246
 247	for _, tt := range tests {
 248		t.Run(tt.name, func(t *testing.T) {
 249			l := tt.setup()
 250			initialSize := l.Size()
 251			err := l.Delete(tt.deleteIndices...)
 252			if err != nil && tt.expectedErr != nil {
 253				uassert.Equal(t, tt.expectedErr.Error(), err.Error())
 254			} else {
 255				uassert.Equal(t, tt.expectedErr, err)
 256			}
 257			uassert.Equal(t, tt.expectedSize, l.Size(),
 258				ufmt.Sprintf("Expected size %d after deleting %d elements from size %d, got %d",
 259					tt.expectedSize, len(tt.deleteIndices), initialSize, l.Size()))
 260		})
 261	}
 262}
 263
 264func TestListSizeAndTotalSize(t *testing.T) {
 265	t.Run("empty list", func(t *testing.T) {
 266		list := New()
 267		uassert.Equal(t, 0, list.Size())
 268		uassert.Equal(t, 0, list.TotalSize())
 269	})
 270
 271	t.Run("list with elements", func(t *testing.T) {
 272		list := New()
 273		list.Append(1)
 274		list.Append(2)
 275		list.Append(3)
 276		uassert.Equal(t, 3, list.Size())
 277		uassert.Equal(t, 3, list.TotalSize())
 278	})
 279
 280	t.Run("list with deleted elements", func(t *testing.T) {
 281		list := New()
 282		list.Append(1)
 283		list.Append(2)
 284		list.Append(3)
 285		list.Delete(1)
 286		uassert.Equal(t, 2, list.Size())
 287		uassert.Equal(t, 3, list.TotalSize())
 288	})
 289}
 290
 291func TestIterator(t *testing.T) {
 292	tests := []struct {
 293		name      string
 294		values    []any
 295		start     int
 296		end       int
 297		expected  []Entry
 298		wantStop  bool
 299		stopAfter int // stop after N elements, -1 for no stop
 300	}{
 301		{
 302			name:      "empty list",
 303			values:    []any{},
 304			start:     0,
 305			end:       10,
 306			expected:  []Entry{},
 307			stopAfter: -1,
 308		},
 309		{
 310			name:      "nil list",
 311			values:    nil,
 312			start:     0,
 313			end:       0,
 314			expected:  []Entry{},
 315			stopAfter: -1,
 316		},
 317		{
 318			name:   "single element forward",
 319			values: []any{42},
 320			start:  0,
 321			end:    0,
 322			expected: []Entry{
 323				{Index: 0, Value: 42},
 324			},
 325			stopAfter: -1,
 326		},
 327		{
 328			name:   "multiple elements forward",
 329			values: []any{1, 2, 3, 4, 5},
 330			start:  0,
 331			end:    4,
 332			expected: []Entry{
 333				{Index: 0, Value: 1},
 334				{Index: 1, Value: 2},
 335				{Index: 2, Value: 3},
 336				{Index: 3, Value: 4},
 337				{Index: 4, Value: 5},
 338			},
 339			stopAfter: -1,
 340		},
 341		{
 342			name:   "multiple elements reverse",
 343			values: []any{1, 2, 3, 4, 5},
 344			start:  4,
 345			end:    0,
 346			expected: []Entry{
 347				{Index: 4, Value: 5},
 348				{Index: 3, Value: 4},
 349				{Index: 2, Value: 3},
 350				{Index: 1, Value: 2},
 351				{Index: 0, Value: 1},
 352			},
 353			stopAfter: -1,
 354		},
 355		{
 356			name:   "partial range forward",
 357			values: []any{1, 2, 3, 4, 5},
 358			start:  1,
 359			end:    3,
 360			expected: []Entry{
 361				{Index: 1, Value: 2},
 362				{Index: 2, Value: 3},
 363				{Index: 3, Value: 4},
 364			},
 365			stopAfter: -1,
 366		},
 367		{
 368			name:   "partial range reverse",
 369			values: []any{1, 2, 3, 4, 5},
 370			start:  3,
 371			end:    1,
 372			expected: []Entry{
 373				{Index: 3, Value: 4},
 374				{Index: 2, Value: 3},
 375				{Index: 1, Value: 2},
 376			},
 377			stopAfter: -1,
 378		},
 379		{
 380			name:      "stop iteration early",
 381			values:    []any{1, 2, 3, 4, 5},
 382			start:     0,
 383			end:       4,
 384			wantStop:  true,
 385			stopAfter: 2,
 386			expected: []Entry{
 387				{Index: 0, Value: 1},
 388				{Index: 1, Value: 2},
 389			},
 390		},
 391		{
 392			name:   "negative start",
 393			values: []any{1, 2, 3},
 394			start:  -1,
 395			end:    2,
 396			expected: []Entry{
 397				{Index: 0, Value: 1},
 398				{Index: 1, Value: 2},
 399				{Index: 2, Value: 3},
 400			},
 401			stopAfter: -1,
 402		},
 403		{
 404			name:   "negative end",
 405			values: []any{1, 2, 3},
 406			start:  0,
 407			end:    -2,
 408			expected: []Entry{
 409				{Index: 0, Value: 1},
 410			},
 411			stopAfter: -1,
 412		},
 413		{
 414			name:      "start beyond size",
 415			values:    []any{1, 2, 3},
 416			start:     5,
 417			end:       6,
 418			expected:  []Entry{},
 419			stopAfter: -1,
 420		},
 421		{
 422			name:   "end beyond size",
 423			values: []any{1, 2, 3},
 424			start:  0,
 425			end:    5,
 426			expected: []Entry{
 427				{Index: 0, Value: 1},
 428				{Index: 1, Value: 2},
 429				{Index: 2, Value: 3},
 430			},
 431			stopAfter: -1,
 432		},
 433		{
 434			name:   "with deleted elements",
 435			values: []any{1, 2, nil, 4, 5},
 436			start:  0,
 437			end:    4,
 438			expected: []Entry{
 439				{Index: 0, Value: 1},
 440				{Index: 1, Value: 2},
 441				{Index: 3, Value: 4},
 442				{Index: 4, Value: 5},
 443			},
 444			stopAfter: -1,
 445		},
 446		{
 447			name:   "with deleted elements reverse",
 448			values: []any{1, nil, 3, nil, 5},
 449			start:  4,
 450			end:    0,
 451			expected: []Entry{
 452				{Index: 4, Value: 5},
 453				{Index: 2, Value: 3},
 454				{Index: 0, Value: 1},
 455			},
 456			stopAfter: -1,
 457		},
 458		{
 459			name:      "start equals end",
 460			values:    []any{1, 2, 3},
 461			start:     1,
 462			end:       1,
 463			expected:  []Entry{{Index: 1, Value: 2}},
 464			stopAfter: -1,
 465		},
 466	}
 467
 468	for _, tt := range tests {
 469		t.Run(tt.name, func(t *testing.T) {
 470			list := New()
 471			list.Append(tt.values...)
 472
 473			var result []Entry
 474			stopped := list.Iterator(tt.start, tt.end, func(index int, value any) bool {
 475				result = append(result, Entry{Index: index, Value: value})
 476				return tt.stopAfter >= 0 && len(result) >= tt.stopAfter
 477			})
 478
 479			uassert.Equal(t, len(result), len(tt.expected), "comparing length")
 480
 481			for i := range result {
 482				uassert.Equal(t, result[i].Index, tt.expected[i].Index, "comparing index")
 483				uassert.Equal(t, typeutil.ToString(result[i].Value), typeutil.ToString(tt.expected[i].Value), "comparing value")
 484			}
 485
 486			uassert.Equal(t, stopped, tt.wantStop, "comparing stopped")
 487		})
 488	}
 489}
 490
 491func TestLargeListAppendGetAndDelete(t *testing.T) {
 492	l := New()
 493	size := 100
 494
 495	// Append values from 0 to 99
 496	for i := 0; i < size; i++ {
 497		l.Append(i)
 498		val := l.Get(i)
 499		uassert.Equal(t, i, val)
 500	}
 501
 502	// Verify size
 503	uassert.Equal(t, size, l.Size())
 504	uassert.Equal(t, size, l.TotalSize())
 505
 506	// Get and verify each value
 507	for i := 0; i < size; i++ {
 508		val := l.Get(i)
 509		uassert.Equal(t, i, val)
 510	}
 511
 512	// Get and verify each value
 513	for i := 0; i < size; i++ {
 514		err := l.Delete(i)
 515		uassert.Equal(t, nil, err)
 516	}
 517
 518	// Verify size
 519	uassert.Equal(t, 0, l.Size())
 520	uassert.Equal(t, size, l.TotalSize())
 521
 522	// Get and verify each value
 523	for i := 0; i < size; i++ {
 524		val := l.Get(i)
 525		uassert.Equal(t, nil, val)
 526	}
 527}
 528
 529func TestEdgeCases(t *testing.T) {
 530	tests := []struct {
 531		name string
 532		test func(t *testing.T)
 533	}{
 534		{
 535			name: "nil list operations",
 536			test: func(t *testing.T) {
 537				var l *List
 538				uassert.Equal(t, 0, l.Size())
 539				uassert.Equal(t, 0, l.TotalSize())
 540				uassert.Equal(t, nil, l.Get(0))
 541				err := l.Delete(0)
 542				uassert.Equal(t, ErrOutOfBounds.Error(), err.Error())
 543			},
 544		},
 545		{
 546			name: "delete empty indices slice",
 547			test: func(t *testing.T) {
 548				l := New()
 549				l.Append(1)
 550				err := l.Delete()
 551				uassert.Equal(t, nil, err)
 552				uassert.Equal(t, 1, l.Size())
 553			},
 554		},
 555		{
 556			name: "append nil values",
 557			test: func(t *testing.T) {
 558				l := New()
 559				l.Append(nil, nil)
 560				uassert.Equal(t, 2, l.Size())
 561				uassert.Equal(t, nil, l.Get(0))
 562				uassert.Equal(t, nil, l.Get(1))
 563			},
 564		},
 565		{
 566			name: "delete same index multiple times",
 567			test: func(t *testing.T) {
 568				l := New()
 569				l.Append(1, 2, 3)
 570				err := l.Delete(1)
 571				uassert.Equal(t, nil, err)
 572				err = l.Delete(1)
 573				uassert.Equal(t, ErrDeleted.Error(), err.Error())
 574			},
 575		},
 576		{
 577			name: "iterator with all deleted elements",
 578			test: func(t *testing.T) {
 579				l := New()
 580				l.Append(1, 2, 3)
 581				l.Delete(0, 1, 2)
 582				var count int
 583				l.Iterator(0, 2, func(index int, value any) bool {
 584					count++
 585					return false
 586				})
 587				uassert.Equal(t, 0, count)
 588			},
 589		},
 590		{
 591			name: "append after delete",
 592			test: func(t *testing.T) {
 593				l := New()
 594				l.Append(1, 2)
 595				l.Delete(1)
 596				l.Append(3)
 597				uassert.Equal(t, 2, l.Size())
 598				uassert.Equal(t, 3, l.TotalSize())
 599				uassert.Equal(t, 1, l.Get(0))
 600				uassert.Equal(t, nil, l.Get(1))
 601				uassert.Equal(t, 3, l.Get(2))
 602			},
 603		},
 604	}
 605
 606	for _, tt := range tests {
 607		t.Run(tt.name, func(t *testing.T) {
 608			tt.test(t)
 609		})
 610	}
 611}
 612
 613func TestIteratorByOffset(t *testing.T) {
 614	tests := []struct {
 615		name     string
 616		values   []any
 617		offset   int
 618		count    int
 619		expected []Entry
 620		wantStop bool
 621	}{
 622		{
 623			name:     "empty list",
 624			values:   []any{},
 625			offset:   0,
 626			count:    5,
 627			expected: []Entry{},
 628			wantStop: false,
 629		},
 630		{
 631			name:   "positive count forward iteration",
 632			values: []any{1, 2, 3, 4, 5},
 633			offset: 1,
 634			count:  2,
 635			expected: []Entry{
 636				{Index: 1, Value: 2},
 637				{Index: 2, Value: 3},
 638			},
 639			wantStop: false,
 640		},
 641		{
 642			name:   "negative count backward iteration",
 643			values: []any{1, 2, 3, 4, 5},
 644			offset: 3,
 645			count:  -2,
 646			expected: []Entry{
 647				{Index: 3, Value: 4},
 648				{Index: 2, Value: 3},
 649			},
 650			wantStop: false,
 651		},
 652		{
 653			name:   "count exceeds available elements forward",
 654			values: []any{1, 2, 3},
 655			offset: 1,
 656			count:  5,
 657			expected: []Entry{
 658				{Index: 1, Value: 2},
 659				{Index: 2, Value: 3},
 660			},
 661			wantStop: false,
 662		},
 663		{
 664			name:   "count exceeds available elements backward",
 665			values: []any{1, 2, 3},
 666			offset: 1,
 667			count:  -5,
 668			expected: []Entry{
 669				{Index: 1, Value: 2},
 670				{Index: 0, Value: 1},
 671			},
 672			wantStop: false,
 673		},
 674		{
 675			name:     "zero count",
 676			values:   []any{1, 2, 3},
 677			offset:   0,
 678			count:    0,
 679			expected: []Entry{},
 680			wantStop: false,
 681		},
 682		{
 683			name:   "negative offset",
 684			values: []any{1, 2, 3},
 685			offset: -1,
 686			count:  2,
 687			expected: []Entry{
 688				{Index: 0, Value: 1},
 689				{Index: 1, Value: 2},
 690			},
 691			wantStop: false,
 692		},
 693		{
 694			name:   "offset beyond size",
 695			values: []any{1, 2, 3},
 696			offset: 5,
 697			count:  -2,
 698			expected: []Entry{
 699				{Index: 2, Value: 3},
 700				{Index: 1, Value: 2},
 701			},
 702			wantStop: false,
 703		},
 704		{
 705			name:   "with deleted elements",
 706			values: []any{1, nil, 3, nil, 5},
 707			offset: 0,
 708			count:  3,
 709			expected: []Entry{
 710				{Index: 0, Value: 1},
 711				{Index: 2, Value: 3},
 712				{Index: 4, Value: 5},
 713			},
 714			wantStop: false,
 715		},
 716		{
 717			name:   "early stop in forward iteration",
 718			values: []any{1, 2, 3, 4, 5},
 719			offset: 0,
 720			count:  5,
 721			expected: []Entry{
 722				{Index: 0, Value: 1},
 723				{Index: 1, Value: 2},
 724			},
 725			wantStop: true, // The callback will return true after 2 elements
 726		},
 727		{
 728			name:   "early stop in backward iteration",
 729			values: []any{1, 2, 3, 4, 5},
 730			offset: 4,
 731			count:  -5,
 732			expected: []Entry{
 733				{Index: 4, Value: 5},
 734				{Index: 3, Value: 4},
 735			},
 736			wantStop: true, // The callback will return true after 2 elements
 737		},
 738		{
 739			name:     "nil list",
 740			values:   nil,
 741			offset:   0,
 742			count:    5,
 743			expected: []Entry{},
 744			wantStop: false,
 745		},
 746		{
 747			name:   "single element forward",
 748			values: []any{1},
 749			offset: 0,
 750			count:  5,
 751			expected: []Entry{
 752				{Index: 0, Value: 1},
 753			},
 754			wantStop: false,
 755		},
 756		{
 757			name:   "single element backward",
 758			values: []any{1},
 759			offset: 0,
 760			count:  -5,
 761			expected: []Entry{
 762				{Index: 0, Value: 1},
 763			},
 764			wantStop: false,
 765		},
 766		{
 767			name:     "all deleted elements",
 768			values:   []any{nil, nil, nil},
 769			offset:   0,
 770			count:    3,
 771			expected: []Entry{},
 772			wantStop: false,
 773		},
 774	}
 775
 776	for _, tt := range tests {
 777		t.Run(tt.name, func(t *testing.T) {
 778			list := New()
 779			list.Append(tt.values...)
 780
 781			var result []Entry
 782			var cb IterCbFn
 783			if tt.wantStop {
 784				cb = func(index int, value any) bool {
 785					result = append(result, Entry{Index: index, Value: value})
 786					return len(result) >= 2 // Stop after 2 elements for early stop tests
 787				}
 788			} else {
 789				cb = func(index int, value any) bool {
 790					result = append(result, Entry{Index: index, Value: value})
 791					return false
 792				}
 793			}
 794
 795			stopped := list.IteratorByOffset(tt.offset, tt.count, cb)
 796
 797			uassert.Equal(t, len(tt.expected), len(result), "comparing length")
 798			for i := range result {
 799				uassert.Equal(t, tt.expected[i].Index, result[i].Index, "comparing index")
 800				uassert.Equal(t, typeutil.ToString(tt.expected[i].Value), typeutil.ToString(result[i].Value), "comparing value")
 801			}
 802			uassert.Equal(t, tt.wantStop, stopped, "comparing stopped")
 803		})
 804	}
 805}
 806
 807func TestMustDelete(t *testing.T) {
 808	tests := []struct {
 809		name        string
 810		setup       func() *List
 811		indices     []int
 812		shouldPanic bool
 813		panicMsg    string
 814	}{
 815		{
 816			name: "successful delete",
 817			setup: func() *List {
 818				l := New()
 819				l.Append(1, 2, 3)
 820				return l
 821			},
 822			indices:     []int{1},
 823			shouldPanic: false,
 824		},
 825		{
 826			name: "out of bounds",
 827			setup: func() *List {
 828				l := New()
 829				l.Append(1)
 830				return l
 831			},
 832			indices:     []int{1},
 833			shouldPanic: true,
 834			panicMsg:    ErrOutOfBounds.Error(),
 835		},
 836		{
 837			name: "already deleted",
 838			setup: func() *List {
 839				l := New()
 840				l.Append(1)
 841				l.Delete(0)
 842				return l
 843			},
 844			indices:     []int{0},
 845			shouldPanic: true,
 846			panicMsg:    ErrDeleted.Error(),
 847		},
 848	}
 849
 850	for _, tt := range tests {
 851		t.Run(tt.name, func(t *testing.T) {
 852			l := tt.setup()
 853			if tt.shouldPanic {
 854				defer func() {
 855					r := recover()
 856					if r == nil {
 857						t.Error("Expected panic but got none")
 858					}
 859					err, ok := r.(error)
 860					if !ok {
 861						t.Errorf("Expected error but got %v", r)
 862					}
 863					uassert.Equal(t, tt.panicMsg, err.Error())
 864				}()
 865			}
 866			l.MustDelete(tt.indices...)
 867			if tt.shouldPanic {
 868				t.Error("Expected panic")
 869			}
 870		})
 871	}
 872}
 873
 874func TestMustGet(t *testing.T) {
 875	tests := []struct {
 876		name        string
 877		setup       func() *List
 878		index       int
 879		expected    any
 880		shouldPanic bool
 881		panicMsg    string
 882	}{
 883		{
 884			name: "successful get",
 885			setup: func() *List {
 886				l := New()
 887				l.Append(42)
 888				return l
 889			},
 890			index:       0,
 891			expected:    42,
 892			shouldPanic: false,
 893		},
 894		{
 895			name: "out of bounds negative",
 896			setup: func() *List {
 897				l := New()
 898				l.Append(1)
 899				return l
 900			},
 901			index:       -1,
 902			shouldPanic: true,
 903			panicMsg:    ErrOutOfBounds.Error(),
 904		},
 905		{
 906			name: "out of bounds positive",
 907			setup: func() *List {
 908				l := New()
 909				l.Append(1)
 910				return l
 911			},
 912			index:       1,
 913			shouldPanic: true,
 914			panicMsg:    ErrOutOfBounds.Error(),
 915		},
 916		{
 917			name: "deleted element",
 918			setup: func() *List {
 919				l := New()
 920				l.Append(1)
 921				l.Delete(0)
 922				return l
 923			},
 924			index:       0,
 925			shouldPanic: true,
 926			panicMsg:    ErrDeleted.Error(),
 927		},
 928		{
 929			name: "nil list",
 930			setup: func() *List {
 931				return nil
 932			},
 933			index:       0,
 934			shouldPanic: true,
 935			panicMsg:    ErrOutOfBounds.Error(),
 936		},
 937	}
 938
 939	for _, tt := range tests {
 940		t.Run(tt.name, func(t *testing.T) {
 941			l := tt.setup()
 942			if tt.shouldPanic {
 943				defer func() {
 944					r := recover()
 945					if r == nil {
 946						t.Error("Expected panic but got none")
 947					}
 948					err, ok := r.(error)
 949					if !ok {
 950						t.Errorf("Expected error but got %v", r)
 951					}
 952					uassert.Equal(t, tt.panicMsg, err.Error())
 953				}()
 954			}
 955			result := l.MustGet(tt.index)
 956			if tt.shouldPanic {
 957				t.Error("Expected panic")
 958			}
 959			uassert.Equal(t, typeutil.ToString(tt.expected), typeutil.ToString(result))
 960		})
 961	}
 962}
 963
 964func TestGetRange(t *testing.T) {
 965	tests := []struct {
 966		name     string
 967		values   []any
 968		start    int
 969		end      int
 970		expected []Entry
 971	}{
 972		{
 973			name:     "empty list",
 974			values:   []any{},
 975			start:    0,
 976			end:      10,
 977			expected: []Entry{},
 978		},
 979		{
 980			name:   "single element",
 981			values: []any{42},
 982			start:  0,
 983			end:    0,
 984			expected: []Entry{
 985				{Index: 0, Value: 42},
 986			},
 987		},
 988		{
 989			name:   "multiple elements forward",
 990			values: []any{1, 2, 3, 4, 5},
 991			start:  1,
 992			end:    3,
 993			expected: []Entry{
 994				{Index: 1, Value: 2},
 995				{Index: 2, Value: 3},
 996				{Index: 3, Value: 4},
 997			},
 998		},
 999		{
1000			name:   "multiple elements reverse",
1001			values: []any{1, 2, 3, 4, 5},
1002			start:  3,
1003			end:    1,
1004			expected: []Entry{
1005				{Index: 3, Value: 4},
1006				{Index: 2, Value: 3},
1007				{Index: 1, Value: 2},
1008			},
1009		},
1010		{
1011			name:   "with deleted elements",
1012			values: []any{1, nil, 3, nil, 5},
1013			start:  0,
1014			end:    4,
1015			expected: []Entry{
1016				{Index: 0, Value: 1},
1017				{Index: 2, Value: 3},
1018				{Index: 4, Value: 5},
1019			},
1020		},
1021		{
1022			name:     "nil list",
1023			values:   nil,
1024			start:    0,
1025			end:      5,
1026			expected: []Entry{},
1027		},
1028		{
1029			name:     "negative indices",
1030			values:   []any{1, 2, 3},
1031			start:    -1,
1032			end:      -2,
1033			expected: []Entry{},
1034		},
1035		{
1036			name:   "indices beyond size",
1037			values: []any{1, 2, 3},
1038			start:  1,
1039			end:    5,
1040			expected: []Entry{
1041				{Index: 1, Value: 2},
1042				{Index: 2, Value: 3},
1043			},
1044		},
1045	}
1046
1047	for _, tt := range tests {
1048		t.Run(tt.name, func(t *testing.T) {
1049			list := New()
1050			list.Append(tt.values...)
1051
1052			result := list.GetRange(tt.start, tt.end)
1053
1054			uassert.Equal(t, len(tt.expected), len(result), "comparing length")
1055			for i := range result {
1056				uassert.Equal(t, tt.expected[i].Index, result[i].Index, "comparing index")
1057				uassert.Equal(t, typeutil.ToString(tt.expected[i].Value), typeutil.ToString(result[i].Value), "comparing value")
1058			}
1059		})
1060	}
1061}
1062
1063func TestGetByOffset(t *testing.T) {
1064	tests := []struct {
1065		name     string
1066		values   []any
1067		offset   int
1068		count    int
1069		expected []Entry
1070	}{
1071		{
1072			name:     "empty list",
1073			values:   []any{},
1074			offset:   0,
1075			count:    5,
1076			expected: []Entry{},
1077		},
1078		{
1079			name:   "positive count forward",
1080			values: []any{1, 2, 3, 4, 5},
1081			offset: 1,
1082			count:  2,
1083			expected: []Entry{
1084				{Index: 1, Value: 2},
1085				{Index: 2, Value: 3},
1086			},
1087		},
1088		{
1089			name:   "negative count backward",
1090			values: []any{1, 2, 3, 4, 5},
1091			offset: 3,
1092			count:  -2,
1093			expected: []Entry{
1094				{Index: 3, Value: 4},
1095				{Index: 2, Value: 3},
1096			},
1097		},
1098		{
1099			name:   "count exceeds available elements",
1100			values: []any{1, 2, 3},
1101			offset: 1,
1102			count:  5,
1103			expected: []Entry{
1104				{Index: 1, Value: 2},
1105				{Index: 2, Value: 3},
1106			},
1107		},
1108		{
1109			name:     "zero count",
1110			values:   []any{1, 2, 3},
1111			offset:   0,
1112			count:    0,
1113			expected: []Entry{},
1114		},
1115		{
1116			name:   "with deleted elements",
1117			values: []any{1, nil, 3, nil, 5},
1118			offset: 0,
1119			count:  3,
1120			expected: []Entry{
1121				{Index: 0, Value: 1},
1122				{Index: 2, Value: 3},
1123				{Index: 4, Value: 5},
1124			},
1125		},
1126		{
1127			name:   "negative offset",
1128			values: []any{1, 2, 3},
1129			offset: -1,
1130			count:  2,
1131			expected: []Entry{
1132				{Index: 0, Value: 1},
1133				{Index: 1, Value: 2},
1134			},
1135		},
1136		{
1137			name:   "offset beyond size",
1138			values: []any{1, 2, 3},
1139			offset: 5,
1140			count:  -2,
1141			expected: []Entry{
1142				{Index: 2, Value: 3},
1143				{Index: 1, Value: 2},
1144			},
1145		},
1146		{
1147			name:     "nil list",
1148			values:   nil,
1149			offset:   0,
1150			count:    5,
1151			expected: []Entry{},
1152		},
1153	}
1154
1155	for _, tt := range tests {
1156		t.Run(tt.name, func(t *testing.T) {
1157			list := New()
1158			list.Append(tt.values...)
1159
1160			result := list.GetByOffset(tt.offset, tt.count)
1161
1162			uassert.Equal(t, len(tt.expected), len(result), "comparing length")
1163			for i := range result {
1164				uassert.Equal(t, tt.expected[i].Index, result[i].Index, "comparing index")
1165				uassert.Equal(t, typeutil.ToString(tt.expected[i].Value), typeutil.ToString(result[i].Value), "comparing value")
1166			}
1167		})
1168	}
1169}
1170
1171func TestMustSet(t *testing.T) {
1172	tests := []struct {
1173		name        string
1174		setup       func() *List
1175		index       int
1176		value       any
1177		shouldPanic bool
1178		panicMsg    string
1179	}{
1180		{
1181			name: "successful set",
1182			setup: func() *List {
1183				l := New()
1184				l.Append(42)
1185				return l
1186			},
1187			index:       0,
1188			value:       99,
1189			shouldPanic: false,
1190		},
1191		{
1192			name: "restore deleted element",
1193			setup: func() *List {
1194				l := New()
1195				l.Append(42)
1196				l.Delete(0)
1197				return l
1198			},
1199			index:       0,
1200			value:       99,
1201			shouldPanic: false,
1202		},
1203		{
1204			name: "out of bounds negative",
1205			setup: func() *List {
1206				l := New()
1207				l.Append(1)
1208				return l
1209			},
1210			index:       -1,
1211			value:       99,
1212			shouldPanic: true,
1213			panicMsg:    ErrOutOfBounds.Error(),
1214		},
1215		{
1216			name: "out of bounds positive",
1217			setup: func() *List {
1218				l := New()
1219				l.Append(1)
1220				return l
1221			},
1222			index:       1,
1223			value:       99,
1224			shouldPanic: true,
1225			panicMsg:    ErrOutOfBounds.Error(),
1226		},
1227		{
1228			name: "nil list",
1229			setup: func() *List {
1230				return nil
1231			},
1232			index:       0,
1233			value:       99,
1234			shouldPanic: true,
1235			panicMsg:    ErrOutOfBounds.Error(),
1236		},
1237	}
1238
1239	for _, tt := range tests {
1240		t.Run(tt.name, func(t *testing.T) {
1241			l := tt.setup()
1242			if tt.shouldPanic {
1243				defer func() {
1244					r := recover()
1245					if r == nil {
1246						t.Error("Expected panic but got none")
1247					}
1248					err, ok := r.(error)
1249					if !ok {
1250						t.Errorf("Expected error but got %v", r)
1251					}
1252					uassert.Equal(t, tt.panicMsg, err.Error())
1253				}()
1254			}
1255			l.MustSet(tt.index, tt.value)
1256			if tt.shouldPanic {
1257				t.Error("Expected panic")
1258			}
1259			// Verify the value was set correctly for non-panic cases
1260			if !tt.shouldPanic {
1261				result := l.Get(tt.index)
1262				uassert.Equal(t, typeutil.ToString(tt.value), typeutil.ToString(result))
1263			}
1264		})
1265	}
1266}
1267
1268func TestSet(t *testing.T) {
1269	tests := []struct {
1270		name        string
1271		setup       func() *List
1272		index       int
1273		value       any
1274		expectedErr error
1275		verify      func(t *testing.T, l *List)
1276	}{
1277		{
1278			name: "set value in empty list",
1279			setup: func() *List {
1280				return New()
1281			},
1282			index:       0,
1283			value:       42,
1284			expectedErr: ErrOutOfBounds,
1285			verify: func(t *testing.T, l *List) {
1286				uassert.Equal(t, 0, l.Size())
1287			},
1288		},
1289		{
1290			name: "set value at valid index",
1291			setup: func() *List {
1292				l := New()
1293				l.Append(1)
1294				return l
1295			},
1296			index: 0,
1297			value: 42,
1298			verify: func(t *testing.T, l *List) {
1299				uassert.Equal(t, 42, l.Get(0))
1300				uassert.Equal(t, 1, l.Size())
1301				uassert.Equal(t, 1, l.TotalSize())
1302			},
1303		},
1304		{
1305			name: "set value at negative index",
1306			setup: func() *List {
1307				l := New()
1308				l.Append(1)
1309				return l
1310			},
1311			index:       -1,
1312			value:       42,
1313			expectedErr: ErrOutOfBounds,
1314			verify: func(t *testing.T, l *List) {
1315				uassert.Equal(t, 1, l.Get(0))
1316			},
1317		},
1318		{
1319			name: "set value beyond size",
1320			setup: func() *List {
1321				l := New()
1322				l.Append(1)
1323				return l
1324			},
1325			index:       1,
1326			value:       42,
1327			expectedErr: ErrOutOfBounds,
1328			verify: func(t *testing.T, l *List) {
1329				uassert.Equal(t, 1, l.Get(0))
1330				uassert.Equal(t, 1, l.Size())
1331			},
1332		},
1333		{
1334			name: "set nil value",
1335			setup: func() *List {
1336				l := New()
1337				l.Append(1)
1338				return l
1339			},
1340			index: 0,
1341			value: nil,
1342			verify: func(t *testing.T, l *List) {
1343				uassert.Equal(t, nil, l.Get(0))
1344				uassert.Equal(t, 0, l.Size())
1345			},
1346		},
1347		{
1348			name: "set value at deleted index",
1349			setup: func() *List {
1350				l := New()
1351				l.Append(1, 2, 3)
1352				l.Delete(1)
1353				return l
1354			},
1355			index: 1,
1356			value: 42,
1357			verify: func(t *testing.T, l *List) {
1358				uassert.Equal(t, 42, l.Get(1))
1359				uassert.Equal(t, 3, l.Size())
1360				uassert.Equal(t, 3, l.TotalSize())
1361			},
1362		},
1363		{
1364			name: "set value in nil list",
1365			setup: func() *List {
1366				return nil
1367			},
1368			index:       0,
1369			value:       42,
1370			expectedErr: ErrOutOfBounds,
1371			verify: func(t *testing.T, l *List) {
1372				uassert.Equal(t, 0, l.Size())
1373			},
1374		},
1375		{
1376			name: "set multiple values at same index",
1377			setup: func() *List {
1378				l := New()
1379				l.Append(1)
1380				return l
1381			},
1382			index: 0,
1383			value: 42,
1384			verify: func(t *testing.T, l *List) {
1385				uassert.Equal(t, 42, l.Get(0))
1386				err := l.Set(0, 99)
1387				uassert.Equal(t, nil, err)
1388				uassert.Equal(t, 99, l.Get(0))
1389				uassert.Equal(t, 1, l.Size())
1390			},
1391		},
1392		{
1393			name: "set value at last index",
1394			setup: func() *List {
1395				l := New()
1396				l.Append(1, 2, 3)
1397				return l
1398			},
1399			index: 2,
1400			value: 42,
1401			verify: func(t *testing.T, l *List) {
1402				uassert.Equal(t, 42, l.Get(2))
1403				uassert.Equal(t, 3, l.Size())
1404			},
1405		},
1406	}
1407
1408	for _, tt := range tests {
1409		t.Run(tt.name, func(t *testing.T) {
1410			l := tt.setup()
1411			err := l.Set(tt.index, tt.value)
1412
1413			if tt.expectedErr != nil {
1414				uassert.Equal(t, tt.expectedErr.Error(), err.Error())
1415			} else {
1416				uassert.Equal(t, nil, err)
1417			}
1418
1419			tt.verify(t, l)
1420		})
1421	}
1422}