190 lines
5.7 KiB
Go
190 lines
5.7 KiB
Go
package playback
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestApplyPlaylistSelectionFirstNext(t *testing.T) {
|
|
retry := validPlaylistRetryPolicy()
|
|
|
|
next, command, apply, err := ApplyPlaylistSelection(
|
|
navigationPlaylist(false),
|
|
PlaylistState{},
|
|
PlaylistCommand{Kind: PlaylistNext},
|
|
retry,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
|
|
}
|
|
if !apply {
|
|
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
|
|
}
|
|
wantState := PlaylistState{CurrentIndex: 0, HasSelection: true}
|
|
if next != wantState {
|
|
t.Fatalf("ApplyPlaylistSelection() state = %#v, want %#v", next, wantState)
|
|
}
|
|
wantCommand := SessionCommand{
|
|
Kind: CommandSetSession,
|
|
Session: SessionConfig{
|
|
Video: FeedConfig{Domain: "domain", UUID: "video-1", Active: true},
|
|
Retry: retry,
|
|
},
|
|
}
|
|
if command != wantCommand {
|
|
t.Fatalf("ApplyPlaylistSelection() command = %#v, want %#v", command, wantCommand)
|
|
}
|
|
}
|
|
|
|
func TestApplyPlaylistSelectionUsesCompleteEntrySession(t *testing.T) {
|
|
retry := validPlaylistRetryPolicy()
|
|
playlist := Playlist{Entries: []PlaylistEntry{
|
|
{
|
|
Video: PlaylistFeed{Domain: "video-domain", UUID: "video"},
|
|
Audio: PlaylistFeed{Domain: "audio-domain", UUID: "audio"},
|
|
SyncRequested: true,
|
|
},
|
|
{Video: PlaylistFeed{Domain: "next-domain", UUID: "next-video"}},
|
|
}}
|
|
|
|
_, command, apply, err := ApplyPlaylistSelection(
|
|
playlist,
|
|
PlaylistState{CurrentIndex: 1, HasSelection: true},
|
|
PlaylistCommand{Kind: PlaylistSelect, Index: 0},
|
|
retry,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
|
|
}
|
|
if !apply {
|
|
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
|
|
}
|
|
want := SessionConfig{
|
|
Video: FeedConfig{Domain: "video-domain", UUID: "video", Active: true},
|
|
Audio: FeedConfig{Domain: "audio-domain", UUID: "audio", Active: true},
|
|
SyncRequested: true,
|
|
Retry: retry,
|
|
}
|
|
if command.Kind != CommandSetSession || command.Session != want {
|
|
t.Fatalf("ApplyPlaylistSelection() command = %#v, want session %#v", command, want)
|
|
}
|
|
}
|
|
|
|
func TestApplyPlaylistSelectionVideoOnlyClearsAudio(t *testing.T) {
|
|
_, command, apply, err := ApplyPlaylistSelection(
|
|
navigationPlaylist(false),
|
|
PlaylistState{CurrentIndex: 1, HasSelection: true},
|
|
PlaylistCommand{Kind: PlaylistSelect, Index: 0},
|
|
validPlaylistRetryPolicy(),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
|
|
}
|
|
if !apply {
|
|
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
|
|
}
|
|
if command.Session.Audio != (FeedConfig{}) {
|
|
t.Fatalf("ApplyPlaylistSelection() audio = %#v, want zero value", command.Session.Audio)
|
|
}
|
|
}
|
|
|
|
func TestApplyPlaylistSelectionApplicationDecision(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
loop bool
|
|
current int
|
|
command PlaylistCommand
|
|
want int
|
|
apply bool
|
|
}{
|
|
{name: "reselect current", current: 1, command: PlaylistCommand{Kind: PlaylistSelect, Index: 1}, want: 1, apply: true},
|
|
{name: "move next", current: 1, command: PlaylistCommand{Kind: PlaylistNext}, want: 2, apply: true},
|
|
{name: "next stops at end", current: 2, command: PlaylistCommand{Kind: PlaylistNext}, want: 2},
|
|
{name: "previous stops at beginning", current: 0, command: PlaylistCommand{Kind: PlaylistPrevious}, want: 0},
|
|
{name: "next wraps", loop: true, current: 2, command: PlaylistCommand{Kind: PlaylistNext}, want: 0, apply: true},
|
|
{name: "previous wraps", loop: true, current: 0, command: PlaylistCommand{Kind: PlaylistPrevious}, want: 2, apply: true},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
next, command, apply, err := ApplyPlaylistSelection(
|
|
navigationPlaylist(test.loop),
|
|
PlaylistState{CurrentIndex: test.current, HasSelection: true},
|
|
test.command,
|
|
validPlaylistRetryPolicy(),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
|
|
}
|
|
wantState := PlaylistState{CurrentIndex: test.want, HasSelection: true}
|
|
if next != wantState {
|
|
t.Fatalf("ApplyPlaylistSelection() state = %#v, want %#v", next, wantState)
|
|
}
|
|
if apply != test.apply {
|
|
t.Fatalf("ApplyPlaylistSelection() apply = %v, want %v", apply, test.apply)
|
|
}
|
|
if apply && command.Kind != CommandSetSession {
|
|
t.Fatalf("ApplyPlaylistSelection() command kind = %v, want %v", command.Kind, CommandSetSession)
|
|
}
|
|
if !apply && command != (SessionCommand{}) {
|
|
t.Fatalf("ApplyPlaylistSelection() command = %#v, want zero value", command)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestApplyPlaylistSelectionErrorsDoNotApply(t *testing.T) {
|
|
current := PlaylistState{CurrentIndex: 1, HasSelection: true}
|
|
tests := []struct {
|
|
name string
|
|
command PlaylistCommand
|
|
retry RetryPolicy
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "invalid command",
|
|
command: PlaylistCommand{},
|
|
retry: validPlaylistRetryPolicy(),
|
|
wantErr: ErrUnknownPlaylistCommand,
|
|
},
|
|
{
|
|
name: "invalid retry",
|
|
command: PlaylistCommand{Kind: PlaylistNext},
|
|
retry: RetryPolicy{},
|
|
wantErr: ErrInvalidRetryDelay,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
next, command, apply, err := ApplyPlaylistSelection(
|
|
navigationPlaylist(false),
|
|
current,
|
|
test.command,
|
|
test.retry,
|
|
)
|
|
if !errors.Is(err, test.wantErr) {
|
|
t.Fatalf("ApplyPlaylistSelection() error = %v, want %v", err, test.wantErr)
|
|
}
|
|
if next != current {
|
|
t.Fatalf("ApplyPlaylistSelection() state = %#v, want unchanged %#v", next, current)
|
|
}
|
|
if apply {
|
|
t.Fatal("ApplyPlaylistSelection() apply = true, want false")
|
|
}
|
|
if command != (SessionCommand{}) {
|
|
t.Fatalf("ApplyPlaylistSelection() command = %#v, want zero value", command)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func validPlaylistRetryPolicy() RetryPolicy {
|
|
return RetryPolicy{
|
|
MaxAttempts: 3,
|
|
InitialDelay: time.Millisecond,
|
|
MaxDelay: time.Second,
|
|
}
|
|
}
|