github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/linked_list_test.go (about) 1 package list 2 3 import ( 4 "container/list" 5 "fmt" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestLinkedList_AppendValue(t *testing.T) { 13 dlist := NewLinkedList[int]() 14 elements := dlist.AppendValue(1, 2, 3, 4, 5) 15 assert.Equal(t, len(elements), 5) 16 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 17 t.Logf("index: %d, e: %v", idx, e) 18 assert.Equal(t, elements[idx], e) 19 t.Logf("addr: %p, return addr: %p", elements[idx], e) 20 return nil 21 }) 22 require.NoError(t, err) 23 24 dlist2 := list.New() 25 dlist2.PushBack(1) 26 dlist2.PushBack(2) 27 dlist2.PushBack(3) 28 dlist2.PushBack(4) 29 dlist2.PushBack(5) 30 31 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 32 33 dlistItr := dlist.Front() 34 dlist2Itr := dlist2.Front() 35 for dlist2Itr != nil { 36 assert.Equal(t, dlistItr.Value, dlist2Itr.Value) 37 dlist2Itr = dlist2Itr.Next() 38 dlistItr = dlistItr.Next() 39 } 40 } 41 42 func TestDoublyLinkedList_InsertBefore(t *testing.T) { 43 dlist := NewLinkedList[int]() 44 elements := dlist.AppendValue(1) 45 _2n := dlist.InsertBefore(2, elements[0]) 46 _3n := dlist.InsertBefore(3, _2n) 47 _4n := dlist.InsertBefore(4, _3n) 48 dlist.InsertBefore(5, _4n) 49 assert.Equal(t, int64(5), dlist.Len()) 50 51 dlist2 := list.New() 52 _1n_2 := dlist2.PushBack(1) 53 _2n_2 := dlist2.InsertBefore(2, _1n_2) 54 _3n_2 := dlist2.InsertBefore(3, _2n_2) 55 _4n_2 := dlist2.InsertBefore(4, _3n_2) 56 dlist2.InsertBefore(5, _4n_2) 57 58 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 59 60 dlistItr := dlist.Front() 61 dlist2Itr := dlist2.Front() 62 for dlist2Itr != nil { 63 assert.Equal(t, dlistItr.Value, dlist2Itr.Value) 64 dlist2Itr = dlist2Itr.Next() 65 dlistItr = dlistItr.Next() 66 } 67 } 68 69 func TestDoublyLinkedList_InsertAfter(t *testing.T) { 70 dlist := NewLinkedList[int]() 71 elements := dlist.AppendValue(1) 72 _2n := dlist.InsertAfter(2, elements[0]) 73 _3n := dlist.InsertAfter(3, _2n) 74 _4n := dlist.InsertAfter(4, _3n) 75 dlist.InsertAfter(5, _4n) 76 assert.Equal(t, int64(5), dlist.Len()) 77 78 dlist2 := list.New() 79 _1n_2 := dlist2.PushBack(1) 80 _2n_2 := dlist2.InsertAfter(2, _1n_2) 81 _3n_2 := dlist2.InsertAfter(3, _2n_2) 82 _4n_2 := dlist2.InsertAfter(4, _3n_2) 83 dlist2.InsertAfter(5, _4n_2) 84 85 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 86 87 dlistItr := dlist.Front() 88 dlist2Itr := dlist2.Front() 89 for dlist2Itr != nil { 90 assert.Equal(t, dlistItr.Value, dlist2Itr.Value) 91 dlist2Itr = dlist2Itr.Next() 92 dlistItr = dlistItr.Next() 93 } 94 } 95 96 func TestLinkedList_AppendValueThenRemove(t *testing.T) { 97 t.Log("test linked list append value") 98 dlist := NewLinkedList[int]() 99 dlist2 := list.New() 100 checkItems := func() { 101 dlistItr := dlist.Front() 102 dlist2Itr := dlist2.Front() 103 for dlist2Itr != nil { 104 require.Equal(t, dlistItr.Value, dlist2Itr.Value) 105 dlist2Itr = dlist2Itr.Next() 106 dlistItr = dlistItr.Next() 107 } 108 } 109 110 elements := dlist.AppendValue(1, 2, 3, 4, 5) 111 require.Equal(t, len(elements), 5) 112 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 113 require.Equal(t, elements[idx], e) 114 addr1, addr2 := fmt.Sprintf("%p", elements[idx]), fmt.Sprintf("%p", e) 115 require.Equal(t, addr1, addr2) 116 return nil 117 }) 118 require.NoError(t, err) 119 120 dlist2.PushBack(1) 121 dlist2.PushBack(2) 122 _3n := dlist2.PushBack(3) 123 dlist2.PushBack(4) 124 dlist2.PushBack(5) 125 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 126 checkItems() 127 128 t.Log("test linked list remove middle") 129 dlist.Remove(elements[2]) 130 dlist2.Remove(_3n) 131 checkItems() 132 133 t.Log("test linked list remove head") 134 dlist.Remove(dlist.Front()) 135 dlist2.Remove(dlist2.Front()) 136 checkItems() 137 138 t.Log("test linked list remove tail") 139 dlist.Remove(dlist.Back()) 140 dlist2.Remove(dlist2.Back()) 141 checkItems() 142 143 t.Log("test linked list remove nil") 144 dlist.Remove(nil) 145 // dlist2.Remove(nil) // nil panic 146 checkItems() 147 148 t.Log("check released elements") 149 require.Equal(t, int64(dlist2.Len()), dlist.Len()) 150 expected := []int{2, 4} 151 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 152 require.Equal(t, expected[idx], e.Value) 153 return nil 154 }) 155 require.NoError(t, err) 156 157 require.Nil(t, elements[0].prev) 158 require.Nil(t, elements[0].next) 159 require.Nil(t, elements[0].listRef) 160 161 require.Nil(t, elements[2].prev) 162 require.Nil(t, elements[2].next) 163 require.Nil(t, elements[2].listRef) 164 165 require.Nil(t, elements[4].prev) 166 require.Nil(t, elements[4].next) 167 require.Nil(t, elements[4].listRef) 168 } 169 170 func BenchmarkNewLinkedList_AppendValue(b *testing.B) { 171 dlist := NewLinkedList[int]() 172 b.ResetTimer() 173 for i := 0; i < b.N; i++ { 174 dlist.AppendValue(i) 175 } 176 b.ReportAllocs() 177 } 178 179 func BenchmarkSDKLinkedList_PushBack(b *testing.B) { 180 dlist := list.New() 181 b.ResetTimer() 182 for i := 0; i < b.N; i++ { 183 dlist.PushBack(i) 184 } 185 b.ReportAllocs() 186 } 187 188 func TestLinkedList_PushBack(t *testing.T) { 189 dlist := NewLinkedList[int]() 190 element := dlist.PushBack(1) 191 require.Equal(t, int64(1), dlist.Len()) 192 require.Equal(t, element.Value, 1) 193 194 element = dlist.PushBack(2) 195 require.Equal(t, int64(2), dlist.Len()) 196 require.Equal(t, element.Value, 2) 197 198 expected := []int{1, 2} 199 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 200 require.Equal(t, expected[idx], e.Value) 201 return nil 202 }) 203 require.NoError(t, err) 204 205 reverseExpected := []int{2, 1} 206 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 207 require.Equal(t, reverseExpected[idx], e.Value) 208 }) 209 } 210 211 func TestLinkedList_PushFront(t *testing.T) { 212 dlist := NewLinkedList[int]() 213 element := dlist.PushFront(1) 214 require.Equal(t, int64(1), dlist.Len()) 215 require.Equal(t, element.Value, 1) 216 217 element = dlist.PushFront(2) 218 require.Equal(t, int64(2), dlist.Len()) 219 require.Equal(t, element.Value, 2) 220 221 expected := []int{2, 1} 222 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 223 require.Equal(t, expected[idx], e.Value) 224 return nil 225 }) 226 require.NoError(t, err) 227 228 reverseExpected := []int{1, 2} 229 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 230 require.Equal(t, reverseExpected[idx], e.Value) 231 }) 232 } 233 234 func BenchmarkDoublyLinkedList_PushBack(b *testing.B) { 235 dlist := NewLinkedList[int]() 236 b.ResetTimer() 237 for i := 0; i < b.N; i++ { 238 dlist.PushBack(i) 239 } 240 b.ReportAllocs() 241 } 242 243 func BenchmarkDoublyLinkedList_Append(b *testing.B) { 244 dlist := NewLinkedList[int]() 245 elements := make([]*NodeElement[int], 0, b.N) 246 for i := 0; i < b.N; i++ { 247 elements = append(elements, newNodeElement[int](i, dlist.(*doublyLinkedList[int]))) 248 } 249 b.ResetTimer() 250 for i := 0; i < b.N; i++ { 251 dlist.Append(elements[i]) 252 } 253 b.StopTimer() 254 b.ReportAllocs() 255 require.Equal(b, int64(b.N), dlist.Len()) 256 } 257 258 func TestDoublyLinkedList_InsertBefore2(t *testing.T) { 259 dlist := NewLinkedList[int]() 260 _2n := dlist.InsertBefore(2, dlist.Front()) 261 require.Equal(t, int64(1), dlist.Len()) 262 require.Equal(t, _2n.Value, 2) 263 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 264 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 265 return nil 266 }) 267 require.NoError(t, err) 268 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 269 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 270 }) 271 } 272 273 func TestLinkedList_InsertAfterAndMove(t *testing.T) { 274 dlist := NewLinkedList[int]() 275 dlist2 := list.New() 276 checkItems := func() { 277 dlistItr := dlist.Front() 278 dlist2Itr := dlist2.Front() 279 require.NotNil(t, dlistItr) 280 require.NotNil(t, dlist2Itr) 281 require.Equal(t, int64(dlist2.Len()), dlist.Len()) 282 for dlist2Itr != nil { 283 require.Equal(t, dlist2Itr.Value, dlistItr.Value) 284 dlist2Itr = dlist2Itr.Next() 285 dlistItr = dlistItr.Next() 286 } 287 } 288 289 elements := dlist.AppendValue(1, 2, 3, 4, 5) 290 _6n := dlist.InsertAfter(6, elements[len(elements)-1]) 291 _7n := dlist.InsertBefore(7, elements[0]) 292 require.Equal(t, int64(7), dlist.Len()) 293 expected := []int{7, 1, 2, 3, 4, 5, 6} 294 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 295 require.Equal(t, expected[idx], e.Value) 296 return nil 297 }) 298 require.NoError(t, err) 299 reverseExpected := []int{6, 5, 4, 3, 2, 1, 7} 300 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 301 require.Equal(t, reverseExpected[idx], e.Value) 302 }) 303 304 dlist2.PushBack(1) 305 dlist2.PushBack(2) 306 dlist2.PushBack(3) 307 dlist2.PushBack(4) 308 dlist2.PushBack(5) 309 _6n_2 := dlist2.InsertAfter(6, dlist2.Back()) 310 _7n_2 := dlist2.InsertBefore(7, dlist2.Front()) 311 require.Equal(t, int64(dlist2.Len()), dlist.Len()) 312 checkItems() 313 314 t.Log("test move after") 315 dlist.MoveToBack(_7n) 316 dlist2.MoveToBack(_7n_2) 317 checkItems() 318 expected = []int{1, 2, 3, 4, 5, 6, 7} 319 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 320 require.Equal(t, expected[idx], e.Value) 321 return nil 322 }) 323 require.NoError(t, err) 324 reverseExpected = []int{7, 6, 5, 4, 3, 2, 1} 325 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 326 require.Equal(t, reverseExpected[idx], e.Value) 327 }) 328 329 t.Log("test move to front") 330 dlist.MoveToFront(_6n) 331 dlist2.MoveToFront(_6n_2) 332 checkItems() 333 expected = []int{6, 1, 2, 3, 4, 5, 7} 334 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 335 require.Equal(t, expected[idx], e.Value) 336 return nil 337 }) 338 require.NoError(t, err) 339 reverseExpected = []int{7, 5, 4, 3, 2, 1, 6} 340 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 341 require.Equal(t, reverseExpected[idx], e.Value) 342 }) 343 344 t.Log("test move before") 345 dlist.MoveBefore(_6n, _7n) 346 dlist2.MoveBefore(_6n_2, _7n_2) 347 checkItems() 348 expected = []int{1, 2, 3, 4, 5, 6, 7} 349 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 350 require.Equal(t, expected[idx], e.Value) 351 return nil 352 }) 353 require.NoError(t, err) 354 reverseExpected = []int{7, 6, 5, 4, 3, 2, 1} 355 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 356 require.Equal(t, reverseExpected[idx], e.Value) 357 }) 358 359 t.Log("test move after") 360 dlist.MoveAfter(_7n, dlist.Front()) 361 dlist2.MoveAfter(_7n_2, dlist2.Front()) 362 checkItems() 363 expected = []int{1, 7, 2, 3, 4, 5, 6} 364 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 365 require.Equal(t, expected[idx], e.Value) 366 return nil 367 }) 368 require.NoError(t, err) 369 reverseExpected = []int{6, 5, 4, 3, 2, 7, 1} 370 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 371 require.Equal(t, reverseExpected[idx], e.Value) 372 }) 373 374 t.Log("test push front list") 375 dlist_1 := NewLinkedList[int]() 376 dlist_1.AppendValue(8, 9, 10) 377 dlist2_1 := list.New() 378 dlist2_1.PushBack(8) 379 dlist2_1.PushBack(9) 380 dlist2_1.PushBack(10) 381 382 dlist.PushFrontList(dlist_1) 383 dlist2.PushFrontList(dlist2_1) 384 checkItems() 385 expected = []int{8, 9, 10, 1, 7, 2, 3, 4, 5, 6} 386 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 387 require.Equal(t, expected[idx], e.Value) 388 return nil 389 }) 390 require.NoError(t, err) 391 reverseExpected = []int{6, 5, 4, 3, 2, 7, 1, 10, 9, 8} 392 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 393 require.Equal(t, reverseExpected[idx], e.Value) 394 }) 395 396 t.Log("test push back list") 397 dlist_2 := NewLinkedList[int]() 398 dlist_2.AppendValue(11, 12, 13) 399 dlist2_2 := list.New() 400 dlist2_2.PushBack(11) 401 dlist2_2.PushBack(12) 402 dlist2_2.PushBack(13) 403 404 dlist.PushBackList(dlist_2) 405 dlist2.PushBackList(dlist2_2) 406 checkItems() 407 expected = []int{8, 9, 10, 1, 7, 2, 3, 4, 5, 6, 11, 12, 13} 408 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 409 require.Equal(t, expected[idx], e.Value) 410 return nil 411 }) 412 require.NoError(t, err) 413 reverseExpected = []int{13, 12, 11, 6, 5, 4, 3, 2, 7, 1, 10, 9, 8} 414 dlist.ReverseForeach(func(idx int64, e *NodeElement[int]) { 415 require.Equal(t, reverseExpected[idx], e.Value) 416 }) 417 } 418 419 func TestDoublyLinkedList_APIsCoverage(t *testing.T) { 420 dlist := NewLinkedList[int]() 421 dlist2 := list.New() 422 checkItems := func() { 423 dlistItr := dlist.Front() 424 dlist2Itr := dlist2.Front() 425 require.NotNil(t, dlistItr) 426 require.NotNil(t, dlist2Itr) 427 require.Equal(t, int64(dlist2.Len()), dlist.Len()) 428 for dlist2Itr != nil { 429 require.Equal(t, dlist2Itr.Value, dlistItr.Value) 430 dlist2Itr = dlist2Itr.Next() 431 dlistItr = dlistItr.Next() 432 } 433 } 434 435 e1 := dlist.PushFront(1) 436 e2 := dlist.PushBack(2) 437 dlist.MoveBefore(e2, e1) 438 439 e1_1 := dlist2.PushFront(1) 440 e2_1 := dlist2.PushBack(2) 441 dlist2.MoveBefore(e2_1, e1_1) 442 443 checkItems() 444 445 e3 := dlist.InsertAfter(3, e1) 446 e3_1 := dlist2.InsertAfter(3, e1_1) 447 checkItems() 448 449 expected := []int{2, 1, 3} 450 err := dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 451 require.Equal(t, expected[idx], e.Value) 452 return nil 453 }) 454 require.NoError(t, err) 455 456 dlist.MoveBefore(e3, e1) 457 dlist2.MoveBefore(e3_1, e1_1) 458 checkItems() 459 460 expected = []int{2, 3, 1} 461 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 462 require.Equal(t, expected[idx], e.Value) 463 return nil 464 }) 465 require.NoError(t, err) 466 467 dlist.MoveBefore(e2, e3) 468 dlist2.MoveBefore(e2_1, e3_1) 469 checkItems() 470 expected = []int{2, 3, 1} 471 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 472 require.Equal(t, expected[idx], e.Value) 473 return nil 474 }) 475 require.NoError(t, err) 476 477 dlist.MoveBefore(e2, e1) 478 dlist2.MoveBefore(e2_1, e1_1) 479 checkItems() 480 expected = []int{3, 2, 1} 481 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 482 require.Equal(t, expected[idx], e.Value) 483 return nil 484 }) 485 require.NoError(t, err) 486 487 dlist.MoveBefore(e2, e3) 488 dlist2.MoveBefore(e2_1, e3_1) 489 checkItems() 490 expected = []int{2, 3, 1} 491 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 492 require.Equal(t, expected[idx], e.Value) 493 return nil 494 }) 495 require.NoError(t, err) 496 497 dlist.MoveAfter(e2, e3) 498 dlist2.MoveAfter(e2_1, e3_1) 499 checkItems() 500 expected = []int{3, 2, 1} 501 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 502 require.Equal(t, expected[idx], e.Value) 503 return nil 504 }) 505 require.NoError(t, err) 506 507 dlist.MoveAfter(e1, e2) 508 dlist2.MoveAfter(e1_1, e2_1) 509 checkItems() 510 expected = []int{3, 2, 1} 511 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 512 require.Equal(t, expected[idx], e.Value) 513 return nil 514 }) 515 require.NoError(t, err) 516 517 dlist.MoveAfter(e2, e1) 518 dlist2.MoveAfter(e2_1, e1_1) 519 checkItems() 520 expected = []int{3, 1, 2} 521 err = dlist.Foreach(func(idx int64, e *NodeElement[int]) error { 522 require.Equal(t, expected[idx], e.Value) 523 return nil 524 }) 525 require.NoError(t, err) 526 527 moved := dlist.MoveAfter(e2, e2) 528 require.False(t, moved) 529 checkItems() 530 531 moved = dlist.MoveBefore(e1, e1) 532 require.False(t, moved) 533 checkItems() 534 535 moved = dlist.MoveBefore(nil, e1) 536 require.False(t, moved) 537 checkItems() 538 539 moved = dlist.MoveBefore(e1, nil) 540 require.False(t, moved) 541 checkItems() 542 543 moved = dlist.MoveAfter(nil, e1) 544 require.False(t, moved) 545 checkItems() 546 547 moved = dlist.MoveAfter(e1, nil) 548 require.False(t, moved) 549 checkItems() 550 551 moved = dlist.MoveToBack(nil) 552 require.False(t, moved) 553 checkItems() 554 555 moved = dlist.MoveToFront(nil) 556 require.False(t, moved) 557 checkItems() 558 559 var nilE *NodeElement[int] = nil 560 require.Nil(t, nilE.Prev()) 561 require.Nil(t, nilE.Next()) 562 require.False(t, nilE.HasNext()) 563 require.False(t, nilE.HasPrev()) 564 }