github.com/MetalBlockchain/metalgo@v1.11.9/utils/buffer/unbounded_deque_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package buffer 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestUnboundedDeque_InitialCapGreaterThanMin(t *testing.T) { 13 require := require.New(t) 14 15 bIntf := NewUnboundedDeque[int](10) 16 require.IsType(&unboundedSliceDeque[int]{}, bIntf) 17 b := bIntf.(*unboundedSliceDeque[int]) 18 require.Empty(b.List()) 19 require.Zero(b.Len()) 20 _, ok := b.Index(0) 21 require.False(ok) 22 23 b.PushLeft(1) 24 require.Equal(1, b.Len()) 25 require.Equal([]int{1}, b.List()) 26 got, ok := b.Index(0) 27 require.True(ok) 28 require.Equal(1, got) 29 _, ok = b.Index(1) 30 require.False(ok) 31 32 got, ok = b.PopLeft() 33 require.Zero(b.Len()) 34 require.True(ok) 35 require.Equal(1, got) 36 _, ok = b.Index(0) 37 require.False(ok) 38 39 b.PushLeft(1) 40 require.Equal(1, b.Len()) 41 require.Equal([]int{1}, b.List()) 42 got, ok = b.Index(0) 43 require.True(ok) 44 require.Equal(1, got) 45 46 got, ok = b.PopRight() 47 require.Zero(b.Len()) 48 require.True(ok) 49 require.Equal(1, got) 50 require.Empty(b.List()) 51 _, ok = b.Index(0) 52 require.False(ok) 53 54 b.PushRight(1) 55 require.Equal(1, b.Len()) 56 require.Equal([]int{1}, b.List()) 57 got, ok = b.Index(0) 58 require.True(ok) 59 require.Equal(1, got) 60 61 got, ok = b.PopRight() 62 require.Zero(b.Len()) 63 require.True(ok) 64 require.Equal(1, got) 65 require.Empty(b.List()) 66 _, ok = b.Index(0) 67 require.False(ok) 68 69 b.PushRight(1) 70 require.Equal(1, b.Len()) 71 require.Equal([]int{1}, b.List()) 72 got, ok = b.Index(0) 73 require.True(ok) 74 require.Equal(1, got) 75 76 got, ok = b.PopLeft() 77 require.Zero(b.Len()) 78 require.True(ok) 79 require.Equal(1, got) 80 require.Empty(b.List()) 81 _, ok = b.Index(0) 82 require.False(ok) 83 84 b.PushLeft(1) 85 require.Equal(1, b.Len()) 86 require.Equal([]int{1}, b.List()) 87 got, ok = b.Index(0) 88 require.True(ok) 89 require.Equal(1, got) 90 91 b.PushLeft(2) 92 require.Equal(2, b.Len()) 93 require.Equal([]int{2, 1}, b.List()) 94 95 got, ok = b.PopLeft() 96 require.Equal(1, b.Len()) 97 require.True(ok) 98 require.Equal(2, got) 99 require.Equal([]int{1}, b.List()) 100 got, ok = b.Index(0) 101 require.True(ok) 102 require.Equal(1, got) 103 104 got, ok = b.PopLeft() 105 require.Zero(b.Len()) 106 require.True(ok) 107 require.Equal(1, got) 108 require.Empty(b.List()) 109 _, ok = b.Index(0) 110 require.False(ok) 111 112 b.PushRight(1) 113 require.Equal(1, b.Len()) 114 require.Equal([]int{1}, b.List()) 115 got, ok = b.Index(0) 116 require.True(ok) 117 require.Equal(1, got) 118 119 b.PushRight(2) 120 require.Equal(2, b.Len()) 121 require.Equal([]int{1, 2}, b.List()) 122 123 got, ok = b.PopRight() 124 require.Equal(1, b.Len()) 125 require.True(ok) 126 require.Equal(2, got) 127 require.Equal([]int{1}, b.List()) 128 got, ok = b.Index(0) 129 require.True(ok) 130 require.Equal(1, got) 131 132 got, ok = b.PopRight() 133 require.Zero(b.Len()) 134 require.True(ok) 135 require.Equal(1, got) 136 require.Empty(b.List()) 137 _, ok = b.Index(0) 138 require.False(ok) 139 140 b.PushLeft(1) 141 require.Equal(1, b.Len()) 142 require.Equal([]int{1}, b.List()) 143 got, ok = b.Index(0) 144 require.True(ok) 145 require.Equal(1, got) 146 147 b.PushLeft(2) 148 require.Equal(2, b.Len()) 149 require.Equal([]int{2, 1}, b.List()) 150 151 got, ok = b.PopRight() 152 require.Equal(1, b.Len()) 153 require.True(ok) 154 require.Equal(1, got) 155 require.Equal([]int{2}, b.List()) 156 got, ok = b.Index(0) 157 require.True(ok) 158 require.Equal(2, got) 159 160 got, ok = b.PopLeft() 161 require.Zero(b.Len()) 162 require.True(ok) 163 require.Equal(2, got) 164 require.Empty(b.List()) 165 _, ok = b.Index(0) 166 require.False(ok) 167 168 b.PushRight(1) 169 require.Equal(1, b.Len()) 170 require.Equal([]int{1}, b.List()) 171 got, ok = b.Index(0) 172 require.True(ok) 173 require.Equal(1, got) 174 175 b.PushLeft(2) 176 require.Equal(2, b.Len()) 177 require.Equal([]int{2, 1}, b.List()) 178 179 got, ok = b.PopRight() 180 require.Equal(1, b.Len()) 181 require.True(ok) 182 require.Equal(1, got) 183 require.Equal([]int{2}, b.List()) 184 got, ok = b.Index(0) 185 require.True(ok) 186 require.Equal(2, got) 187 188 got, ok = b.PopLeft() 189 require.Zero(b.Len()) 190 require.True(ok) 191 require.Equal(2, got) 192 require.Empty(b.List()) 193 _, ok = b.Index(0) 194 require.False(ok) 195 196 b.PushLeft(1) 197 require.Equal(1, b.Len()) 198 require.Equal([]int{1}, b.List()) 199 got, ok = b.Index(0) 200 require.True(ok) 201 require.Equal(1, got) 202 203 b.PushRight(2) 204 require.Equal(2, b.Len()) 205 require.Equal([]int{1, 2}, b.List()) 206 207 got, ok = b.PopLeft() 208 require.Equal(1, b.Len()) 209 require.True(ok) 210 require.Equal(1, got) 211 require.Equal([]int{2}, b.List()) 212 got, ok = b.Index(0) 213 require.True(ok) 214 require.Equal(2, got) 215 216 got, ok = b.PopRight() 217 require.Zero(b.Len()) 218 require.True(ok) 219 require.Equal(2, got) 220 require.Empty(b.List()) 221 _, ok = b.Index(0) 222 require.False(ok) 223 } 224 225 // Cases we test: 226 // 1. [left] moves to the left (no wrap around). 227 // 2. [left] moves to the right (no wrap around). 228 // 3. [left] wrapping around to the left side. 229 // 4. [left] wrapping around to the right side. 230 // 5. Resize. 231 func TestUnboundedSliceDequePushLeftPopLeft(t *testing.T) { 232 require := require.New(t) 233 234 // Starts empty. 235 bIntf := NewUnboundedDeque[int](2) 236 require.IsType(&unboundedSliceDeque[int]{}, bIntf) 237 b := bIntf.(*unboundedSliceDeque[int]) 238 require.Zero(bIntf.Len()) 239 require.Len(b.data, 2) 240 require.Zero(b.left) 241 require.Equal(1, b.right) 242 require.Empty(b.List()) 243 // slice is [EMPTY] 244 245 _, ok := b.PopLeft() 246 require.False(ok) 247 _, ok = b.PeekLeft() 248 require.False(ok) 249 _, ok = b.PeekRight() 250 require.False(ok) 251 252 b.PushLeft(1) // slice is [1,EMPTY] 253 require.Equal(1, b.Len()) 254 require.Len(b.data, 2) 255 require.Equal(1, b.left) 256 require.Equal(1, b.right) 257 require.Equal([]int{1}, b.List()) 258 259 got, ok := b.PeekLeft() 260 require.True(ok) 261 require.Equal(1, got) 262 263 got, ok = b.PeekRight() 264 require.True(ok) 265 require.Equal(1, got) 266 267 // This causes a resize 268 b.PushLeft(2) // slice is [2,1,EMPTY,EMPTY] 269 require.Equal(2, b.Len()) 270 require.Len(b.data, 4) 271 require.Equal(3, b.left) 272 require.Equal(2, b.right) 273 require.Equal([]int{2, 1}, b.List()) 274 got, ok = b.Index(0) 275 require.True(ok) 276 require.Equal(2, got) 277 got, ok = b.Index(1) 278 require.True(ok) 279 require.Equal(1, got) 280 281 got, ok = b.PeekLeft() 282 require.True(ok) 283 require.Equal(2, got) 284 285 got, ok = b.PeekRight() 286 require.True(ok) 287 require.Equal(1, got) 288 289 // Tests left moving left with no wrap around. 290 b.PushLeft(3) // slice is [2,1,EMPTY,3] 291 require.Equal(3, b.Len()) 292 require.Len(b.data, 4) 293 require.Equal(2, b.left) 294 require.Equal(2, b.right) 295 require.Equal([]int{3, 2, 1}, b.List()) 296 got, ok = b.Index(0) 297 require.True(ok) 298 require.Equal(3, got) 299 got, ok = b.Index(1) 300 require.True(ok) 301 require.Equal(2, got) 302 got, ok = b.Index(2) 303 require.True(ok) 304 require.Equal(1, got) 305 _, ok = b.Index(3) 306 require.False(ok) 307 308 got, ok = b.PeekLeft() 309 require.True(ok) 310 require.Equal(3, got) 311 312 got, ok = b.PeekRight() 313 require.True(ok) 314 require.Equal(1, got) 315 316 // Tests left moving right with no wrap around. 317 got, ok = b.PopLeft() // slice is [2,1,EMPTY,EMPTY] 318 require.True(ok) 319 require.Equal(3, got) 320 require.Equal(2, b.Len()) 321 require.Len(b.data, 4) 322 require.Equal(3, b.left) 323 require.Equal(2, b.right) 324 require.Equal([]int{2, 1}, b.List()) 325 got, ok = b.Index(0) 326 require.True(ok) 327 require.Equal(2, got) 328 got, ok = b.Index(1) 329 require.True(ok) 330 require.Equal(1, got) 331 332 got, ok = b.PeekLeft() 333 require.True(ok) 334 require.Equal(2, got) 335 336 got, ok = b.PeekRight() 337 require.True(ok) 338 require.Equal(1, got) 339 340 // Tests left wrapping around to the left side. 341 got, ok = b.PopLeft() // slice is [EMPTY,1,EMPTY,EMPTY] 342 require.True(ok) 343 require.Equal(2, got) 344 require.Equal(1, b.Len()) 345 require.Len(b.data, 4) 346 require.Zero(b.left) 347 require.Equal(2, b.right) 348 require.Equal([]int{1}, b.List()) 349 got, ok = b.Index(0) 350 require.True(ok) 351 require.Equal(1, got) 352 353 got, ok = b.PeekLeft() 354 require.True(ok) 355 require.Equal(1, got) 356 357 got, ok = b.PeekRight() 358 require.True(ok) 359 require.Equal(1, got) 360 361 // Test left wrapping around to the right side. 362 b.PushLeft(2) // slice is [2,1,EMPTY,EMPTY] 363 require.Equal(2, b.Len()) 364 require.Len(b.data, 4) 365 require.Equal(3, b.left) 366 require.Equal(2, b.right) 367 require.Equal([]int{2, 1}, b.List()) 368 got, ok = b.Index(0) 369 require.True(ok) 370 require.Equal(2, got) 371 got, ok = b.Index(1) 372 require.True(ok) 373 require.Equal(1, got) 374 375 got, ok = b.PeekLeft() 376 require.True(ok) 377 require.Equal(2, got) 378 379 got, ok = b.PeekRight() 380 require.True(ok) 381 require.Equal(1, got) 382 383 got, ok = b.PopLeft() // slice is [EMPTY,1,EMPTY,EMPTY] 384 require.True(ok) 385 require.Equal(2, got) 386 require.Equal(1, b.Len()) 387 require.Len(b.data, 4) 388 require.Zero(b.left) 389 require.Equal(2, b.right) 390 require.Equal([]int{1}, b.List()) 391 got, ok = b.Index(0) 392 require.True(ok) 393 require.Equal(1, got) 394 395 got, ok = b.PopLeft() // slice is [EMPTY,EMPTY,EMPTY,EMPTY] 396 require.True(ok) 397 require.Equal(1, got) 398 require.Zero(b.Len()) 399 require.Len(b.data, 4) 400 require.Equal(1, b.left) 401 require.Equal(2, b.right) 402 require.Empty(b.List()) 403 _, ok = b.Index(0) 404 require.False(ok) 405 406 _, ok = b.PopLeft() 407 require.False(ok) 408 _, ok = b.PeekLeft() 409 require.False(ok) 410 _, ok = b.PeekRight() 411 require.False(ok) 412 } 413 414 func TestUnboundedSliceDequePushRightPopRight(t *testing.T) { 415 require := require.New(t) 416 417 // Starts empty. 418 bIntf := NewUnboundedDeque[int](2) 419 require.IsType(&unboundedSliceDeque[int]{}, bIntf) 420 b := bIntf.(*unboundedSliceDeque[int]) 421 require.Zero(bIntf.Len()) 422 require.Len(b.data, 2) 423 require.Zero(b.left) 424 require.Equal(1, b.right) 425 require.Empty(b.List()) 426 // slice is [EMPTY] 427 428 _, ok := b.PopRight() 429 require.False(ok) 430 _, ok = b.PeekLeft() 431 require.False(ok) 432 _, ok = b.PeekRight() 433 require.False(ok) 434 435 b.PushRight(1) // slice is [1,EMPTY] 436 require.Equal(1, b.Len()) 437 require.Len(b.data, 2) 438 require.Zero(b.left) 439 require.Zero(b.right) 440 require.Equal([]int{1}, b.List()) 441 got, ok := b.Index(0) 442 require.True(ok) 443 require.Equal(1, got) 444 445 got, ok = b.PeekLeft() 446 require.True(ok) 447 require.Equal(1, got) 448 449 got, ok = b.PeekRight() 450 require.True(ok) 451 require.Equal(1, got) 452 453 // This causes a resize 454 b.PushRight(2) // slice is [1,2,EMPTY,EMPTY] 455 require.Equal(2, b.Len()) 456 require.Len(b.data, 4) 457 require.Equal(3, b.left) 458 require.Equal(2, b.right) 459 require.Equal([]int{1, 2}, b.List()) 460 got, ok = b.Index(0) 461 require.True(ok) 462 require.Equal(1, got) 463 got, ok = b.Index(1) 464 require.True(ok) 465 require.Equal(2, got) 466 467 got, ok = b.PeekLeft() 468 require.True(ok) 469 require.Equal(1, got) 470 471 got, ok = b.PeekRight() 472 require.True(ok) 473 require.Equal(2, got) 474 475 // Tests right moving right with no wrap around 476 b.PushRight(3) // slice is [1,2,3,EMPTY] 477 require.Equal(3, b.Len()) 478 require.Len(b.data, 4) 479 require.Equal(3, b.left) 480 require.Equal(3, b.right) 481 require.Equal([]int{1, 2, 3}, b.List()) 482 got, ok = b.Index(0) 483 require.True(ok) 484 require.Equal(1, got) 485 got, ok = b.Index(1) 486 require.True(ok) 487 require.Equal(2, got) 488 got, ok = b.Index(2) 489 require.True(ok) 490 require.Equal(3, got) 491 492 got, ok = b.PeekLeft() 493 require.True(ok) 494 require.Equal(1, got) 495 496 got, ok = b.PeekRight() 497 require.True(ok) 498 require.Equal(3, got) 499 500 // Tests right moving left with no wrap around 501 got, ok = b.PopRight() // slice is [1,2,EMPTY,EMPTY] 502 require.True(ok) 503 require.Equal(3, got) 504 require.Equal(2, b.Len()) 505 require.Len(b.data, 4) 506 require.Equal(3, b.left) 507 require.Equal(2, b.right) 508 require.Equal([]int{1, 2}, b.List()) 509 got, ok = b.Index(0) 510 require.True(ok) 511 require.Equal(1, got) 512 got, ok = b.Index(1) 513 require.True(ok) 514 require.Equal(2, got) 515 _, ok = b.Index(2) 516 require.False(ok) 517 518 got, ok = b.PeekLeft() 519 require.True(ok) 520 require.Equal(1, got) 521 522 got, ok = b.PeekRight() 523 require.True(ok) 524 require.Equal(2, got) 525 526 got, ok = b.PopRight() // slice is [1,EMPTY,EMPTY,EMPTY] 527 require.True(ok) 528 require.Equal(2, got) 529 require.Equal(1, b.Len()) 530 require.Len(b.data, 4) 531 require.Equal(3, b.left) 532 require.Equal(1, b.right) 533 require.Equal([]int{1}, b.List()) 534 got, ok = b.Index(0) 535 require.True(ok) 536 require.Equal(1, got) 537 _, ok = b.Index(1) 538 require.False(ok) 539 540 got, ok = b.PeekLeft() 541 require.True(ok) 542 require.Equal(1, got) 543 544 got, ok = b.PeekRight() 545 require.True(ok) 546 require.Equal(1, got) 547 548 got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY] 549 require.True(ok) 550 require.Equal(1, got) 551 require.Zero(b.Len()) 552 require.Len(b.data, 4) 553 require.Equal(3, b.left) 554 require.Zero(b.right) 555 require.Empty(b.List()) 556 require.Zero(b.Len()) 557 _, ok = b.Index(0) 558 require.False(ok) 559 560 _, ok = b.PeekLeft() 561 require.False(ok) 562 _, ok = b.PeekRight() 563 require.False(ok) 564 _, ok = b.PopRight() 565 require.False(ok) 566 567 b.PushLeft(1) // slice is [EMPTY,EMPTY,EMPTY,1] 568 require.Equal(1, b.Len()) 569 require.Len(b.data, 4) 570 require.Equal(2, b.left) 571 require.Zero(b.right) 572 require.Equal([]int{1}, b.List()) 573 got, ok = b.Index(0) 574 require.True(ok) 575 require.Equal(1, got) 576 577 got, ok = b.PeekLeft() 578 require.True(ok) 579 require.Equal(1, got) 580 581 got, ok = b.PeekRight() 582 require.True(ok) 583 require.Equal(1, got) 584 585 // Test right wrapping around to the right 586 got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY] 587 require.True(ok) 588 require.Equal(1, got) 589 require.Zero(b.Len()) 590 require.Len(b.data, 4) 591 require.Equal(2, b.left) 592 require.Equal(3, b.right) 593 require.Empty(b.List()) 594 require.Zero(b.Len()) 595 _, ok = b.Index(0) 596 require.False(ok) 597 598 _, ok = b.PeekLeft() 599 require.False(ok) 600 601 _, ok = b.PeekRight() 602 require.False(ok) 603 604 // Tests right wrapping around to the left 605 b.PushRight(2) // slice is [EMPTY,EMPTY,EMPTY,2] 606 require.Equal(1, b.Len()) 607 require.Len(b.data, 4) 608 require.Equal(2, b.left) 609 require.Zero(b.right) 610 require.Equal([]int{2}, b.List()) 611 got, ok = b.Index(0) 612 require.True(ok) 613 require.Equal(2, got) 614 615 got, ok = b.PeekLeft() 616 require.True(ok) 617 require.Equal(2, got) 618 619 got, ok = b.PeekRight() 620 require.True(ok) 621 require.Equal(2, got) 622 623 got, ok = b.PopRight() // slice is [EMPTY,EMPTY,EMPTY,EMPTY] 624 require.True(ok) 625 require.Equal(2, got) 626 require.Empty(b.List()) 627 _, ok = b.Index(0) 628 require.False(ok) 629 630 _, ok = b.PeekLeft() 631 require.False(ok) 632 _, ok = b.PeekRight() 633 require.False(ok) 634 _, ok = b.PopRight() 635 require.False(ok) 636 } 637 638 func FuzzUnboundedSliceDeque(f *testing.F) { 639 f.Fuzz( 640 func(t *testing.T, initSize uint, input []byte) { 641 require := require.New(t) 642 b := NewUnboundedDeque[byte](int(initSize)) 643 for i, n := range input { 644 b.PushRight(n) 645 gotIndex, ok := b.Index(i) 646 require.True(ok) 647 require.Equal(n, gotIndex) 648 } 649 650 list := b.List() 651 require.Len(list, len(input)) 652 for i, n := range input { 653 require.Equal(n, list[i]) 654 } 655 656 for i := 0; i < len(input); i++ { 657 _, _ = b.PopLeft() 658 list = b.List() 659 if i == len(input)-1 { 660 require.Empty(list) 661 _, ok := b.Index(0) 662 require.False(ok) 663 } else { 664 require.Equal(input[i+1:], list) 665 got, ok := b.Index(0) 666 require.True(ok) 667 require.Equal(input[i+1], got) 668 } 669 } 670 }, 671 ) 672 }