diff options
Diffstat (limited to 'tests/queue.rs')
| -rw-r--r-- | tests/queue.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tests/queue.rs b/tests/queue.rs index 2eaa6f3..d338f2a 100644 --- a/tests/queue.rs +++ b/tests/queue.rs | |||
| @@ -474,6 +474,99 @@ fn test_clear_resets_shuffle_indices() { | |||
| 474 | assert!(q.shuffled_indices().is_empty()); | 474 | assert!(q.shuffled_indices().is_empty()); |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | // ---------- Regression tests ---------- | ||
| 478 | // These encode invariants the queue must uphold across shuffle transitions. | ||
| 479 | // They previously failed and now pin the fixed behavior. | ||
| 480 | |||
| 481 | #[test] | ||
| 482 | fn test_add_during_shuffle_survives_shuffle_off() { | ||
| 483 | // A track added while Shuffle::All is active must survive turning shuffle | ||
| 484 | // off: `restore_from_original` rebuilds the queue from the live track | ||
| 485 | // list (entries, not paths), so late additions are kept. | ||
| 486 | // (src/queue.rs: add_track 223, restore_from_original 266) | ||
| 487 | let mut q = Queue::new(); | ||
| 488 | add_track(&mut q, "/music/a.mp3"); | ||
| 489 | add_track(&mut q, "/music/b.mp3"); | ||
| 490 | add_track(&mut q, "/music/c.mp3"); | ||
| 491 | q.set_shuffle(ShuffleMode::All); | ||
| 492 | |||
| 493 | // User adds a track while shuffle is active (e.g. `rsp play --next`). | ||
| 494 | add_track(&mut q, "/music/d.mp3"); | ||
| 495 | assert_eq!(q.len(), 4); | ||
| 496 | |||
| 497 | q.set_shuffle(ShuffleMode::None); | ||
| 498 | |||
| 499 | // d.mp3 must still be in the queue. | ||
| 500 | assert_eq!( | ||
| 501 | q.len(), | ||
| 502 | 4, | ||
| 503 | "queue lost a track after shuffle-off; len = {}", | ||
| 504 | q.len() | ||
| 505 | ); | ||
| 506 | assert!( | ||
| 507 | q.tracks().iter().any(|t| t.path == PathBuf::from("/music/d.mp3")), | ||
| 508 | "track added during shuffle was dropped when shuffle was turned off" | ||
| 509 | ); | ||
| 510 | } | ||
| 511 | |||
| 512 | #[test] | ||
| 513 | fn test_clear_then_shuffle_off_does_not_resurrect_queue() { | ||
| 514 | // A cleared queue must stay empty across a later shuffle-off: `clear()` | ||
| 515 | // wipes tracks/position/shuffled_indices, and `restore_from_original` | ||
| 516 | // must not resurrect entries from any lingering state. | ||
| 517 | // (src/queue.rs: clear 546 / restore_from_original 266; | ||
| 518 | // src/daemon.rs: stop 815, queue-end 353-354) | ||
| 519 | let mut q = Queue::new(); | ||
| 520 | add_track(&mut q, "/music/a.mp3"); | ||
| 521 | add_track(&mut q, "/music/b.mp3"); | ||
| 522 | add_track(&mut q, "/music/c.mp3"); | ||
| 523 | q.set_shuffle(ShuffleMode::All); | ||
| 524 | |||
| 525 | q.clear(); | ||
| 526 | assert!(q.is_empty()); | ||
| 527 | assert_eq!(q.len(), 0); | ||
| 528 | |||
| 529 | // Later the user toggles shuffle off: the queue must stay empty. | ||
| 530 | q.set_shuffle(ShuffleMode::None); | ||
| 531 | assert!( | ||
| 532 | q.is_empty(), | ||
| 533 | "cleared queue was resurrected from the stale shuffle snapshot (len = {})", | ||
| 534 | q.len() | ||
| 535 | ); | ||
| 536 | assert_eq!(q.len(), 0); | ||
| 537 | } | ||
| 538 | |||
| 539 | #[test] | ||
| 540 | fn test_shuffle_off_keeps_unplayed_duplicate_entries() { | ||
| 541 | // Duplicates are distinct queue entries: `restore_from_original` rebuilds | ||
| 542 | // by entry identity (played indices vs. the rest), never by path, so an | ||
| 543 | // unplayed duplicate of an already-played path must survive shuffle-off. | ||
| 544 | // (src/queue.rs: restore_from_original 266) | ||
| 545 | let mut q = Queue::new(); | ||
| 546 | add_track(&mut q, "/music/a.mp3"); | ||
| 547 | add_track(&mut q, "/music/b.mp3"); | ||
| 548 | add_track(&mut q, "/music/a.mp3"); // duplicate entry (same path) | ||
| 549 | |||
| 550 | // Play the first two entries (position 1). The third entry is unplayed. | ||
| 551 | q.next(); | ||
| 552 | assert_eq!(q.position(), 1); | ||
| 553 | |||
| 554 | // Position is 1 with len 3: the shuffled tail is a single element, so the | ||
| 555 | // shuffled indices stay identity and the restore is deterministic. | ||
| 556 | q.set_shuffle(ShuffleMode::All); | ||
| 557 | q.set_shuffle(ShuffleMode::None); | ||
| 558 | |||
| 559 | // All three entries must survive shuffle-off (duplicates are distinct | ||
| 560 | // queue entries, not a single path). | ||
| 561 | assert_eq!( | ||
| 562 | q.len(), | ||
| 563 | 3, | ||
| 564 | "unplayed duplicate entry was dropped on shuffle-off (len = {})", | ||
| 565 | q.len() | ||
| 566 | ); | ||
| 567 | assert_eq!(q.position(), 1); | ||
| 568 | } | ||
| 569 | |||
| 477 | // ---------- Track struct ---------- | 570 | // ---------- Track struct ---------- |
| 478 | 571 | ||
| 479 | #[test] | 572 | #[test] |
