- Fix errcheck for db.Close() in testhelper.go - Fix errcheck, nlreturn, wsl, gofumpt issues in genevents/main.go - Fix gofumpt and wsl issues in library.go
211 lines
4.6 KiB
Go
211 lines
4.6 KiB
Go
package queue
|
|
|
|
import (
|
|
"log/slog"
|
|
"testing"
|
|
)
|
|
|
|
// newTestQueueDirect creates a Queue with direct field manipulation
|
|
// (no DB needed) for pure navigation logic tests.
|
|
func newTestQueueDirect(tracks int, currentIndex int) *Queue {
|
|
q := &Queue{
|
|
logger: slog.Default(),
|
|
repeatMode: RepeatOff,
|
|
}
|
|
|
|
q.tracks = make([]Track, tracks)
|
|
for i := range tracks {
|
|
q.tracks[i] = Track{FilePath: "/test/track.mp3", Position: int64(i)}
|
|
}
|
|
|
|
q.currentIndex = currentIndex
|
|
|
|
return q
|
|
}
|
|
|
|
func TestNextIndex_NormalMode_AdvancesToNextTrack(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 2)
|
|
|
|
got := q.nextIndex()
|
|
if got != 3 {
|
|
t.Errorf("nextIndex: got %d, want 3", got)
|
|
}
|
|
}
|
|
|
|
func TestNextIndex_NormalMode_EndOfQueue_RepeatOff(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 4)
|
|
|
|
got := q.nextIndex()
|
|
if got != -1 {
|
|
t.Errorf("nextIndex at end (repeatOff): got %d, want -1", got)
|
|
}
|
|
}
|
|
|
|
func TestNextIndex_NormalMode_EndOfQueue_RepeatAll(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 4)
|
|
q.repeatMode = RepeatAll
|
|
|
|
got := q.nextIndex()
|
|
if got != 0 {
|
|
t.Errorf("nextIndex at end (repeatAll): got %d, want 0", got)
|
|
}
|
|
}
|
|
|
|
func TestNextIndex_RepeatOne(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Note: RepeatOne is handled in the Next() method, not nextIndex().
|
|
// nextIndex() with RepeatOne still advances normally — the repeat-one
|
|
// logic replays the current track before calling nextIndex().
|
|
// This test verifies nextIndex advances in the RepeatOne case.
|
|
q := newTestQueueDirect(5, 2)
|
|
q.repeatMode = RepeatOne
|
|
|
|
got := q.nextIndex()
|
|
// nextIndex itself doesn't handle RepeatOne — it just advances.
|
|
if got != 3 {
|
|
t.Errorf("nextIndex (repeatOne): got %d, want 3", got)
|
|
}
|
|
}
|
|
|
|
func TestPreviousIndex_NormalMode_GoesBack(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 3)
|
|
|
|
got := q.previousIndex()
|
|
if got != 2 {
|
|
t.Errorf("previousIndex: got %d, want 2", got)
|
|
}
|
|
}
|
|
|
|
func TestPreviousIndex_AtStart_RepeatOff(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 0)
|
|
|
|
got := q.previousIndex()
|
|
if got != -1 {
|
|
t.Errorf("previousIndex at start (repeatOff): got %d, want -1", got)
|
|
}
|
|
}
|
|
|
|
func TestPreviousIndex_AtStart_RepeatAll(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 0)
|
|
q.repeatMode = RepeatAll
|
|
|
|
got := q.previousIndex()
|
|
if got != 4 {
|
|
t.Errorf("previousIndex at start (repeatAll): got %d, want 4", got)
|
|
}
|
|
}
|
|
|
|
func TestGenerateShuffleOrder_Properties(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
trackCount int
|
|
currentIdx int
|
|
}{
|
|
{"single track", 1, 0},
|
|
{"five tracks", 5, 2},
|
|
{"twenty tracks", 20, 10},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(tc.trackCount, tc.currentIdx)
|
|
q.generateShuffleOrder()
|
|
|
|
// Property 1: length matches track count.
|
|
if got := len(q.shuffleOrder); got != tc.trackCount {
|
|
t.Errorf("shuffleOrder length: got %d, want %d", got, tc.trackCount)
|
|
}
|
|
|
|
// Property 2: current track is at shuffleOrder[0].
|
|
if q.shuffleOrder[0] != tc.currentIdx {
|
|
t.Errorf(
|
|
"shuffleOrder[0]: got %d, want %d (currentIndex)",
|
|
q.shuffleOrder[0], tc.currentIdx,
|
|
)
|
|
}
|
|
|
|
// Property 3: all indices present (no duplicates, no missing).
|
|
seen := make(map[int]bool, tc.trackCount)
|
|
|
|
for _, idx := range q.shuffleOrder {
|
|
if idx < 0 || idx >= tc.trackCount {
|
|
t.Errorf("shuffleOrder contains out-of-range index: %d", idx)
|
|
}
|
|
|
|
if seen[idx] {
|
|
t.Errorf("shuffleOrder contains duplicate index: %d", idx)
|
|
}
|
|
|
|
seen[idx] = true
|
|
}
|
|
|
|
if len(seen) != tc.trackCount {
|
|
t.Errorf(
|
|
"unique indices in shuffleOrder: got %d, want %d",
|
|
len(seen), tc.trackCount,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNextIndex_ShuffleMode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
q := newTestQueueDirect(5, 2)
|
|
q.shuffleMode = true
|
|
// Set a known shuffle order: [2, 4, 0, 3, 1]
|
|
// Current index is 2, which is at shuffleOrder[0].
|
|
q.shuffleOrder = []int{2, 4, 0, 3, 1}
|
|
|
|
// Next in shuffle order should be shuffleOrder[1] = 4.
|
|
got := q.nextIndex()
|
|
if got != 4 {
|
|
t.Errorf("nextIndex (shuffle): got %d, want 4", got)
|
|
}
|
|
|
|
// Advance to index 4 and get next.
|
|
q.currentIndex = 4
|
|
got = q.nextIndex()
|
|
|
|
if got != 0 {
|
|
t.Errorf("nextIndex (shuffle, pos 2): got %d, want 0", got)
|
|
}
|
|
|
|
// At the end of shuffle order with RepeatOff.
|
|
q.currentIndex = 1 // last in shuffleOrder
|
|
got = q.nextIndex()
|
|
|
|
if got != -1 {
|
|
t.Errorf("nextIndex (shuffle, end, repeatOff): got %d, want -1", got)
|
|
}
|
|
|
|
// At the end of shuffle order with RepeatAll.
|
|
q.repeatMode = RepeatAll
|
|
got = q.nextIndex()
|
|
|
|
if got != 2 {
|
|
t.Errorf(
|
|
"nextIndex (shuffle, end, repeatAll): got %d, want 2 "+
|
|
"(wraps to shuffleOrder[0])", got,
|
|
)
|
|
}
|
|
}
|