172 lines
4.9 KiB
Go
172 lines
4.9 KiB
Go
package subsonic
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
|
|
)
|
|
|
|
func TestReportPlaybackPlaying(t *testing.T) {
|
|
s, db := newTestServer(t)
|
|
createTestUser(t, s, "alice", "password123", false)
|
|
seedLibrary(t, s)
|
|
song := firstSong(t, s)
|
|
|
|
srv := newSubsonicTestServer(t, s)
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", song.ID)
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "5000")
|
|
q.Set("state", "playing")
|
|
resp := getPath(t, srv, "/rest/reportPlayback.view", q)
|
|
x := decodeXML(t, resp)
|
|
if x.Status != "ok" {
|
|
t.Fatalf("reportPlayback failed: %+v", x)
|
|
}
|
|
|
|
nowPlaying, err := database.ListNowPlaying(db)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(nowPlaying) != 1 || nowPlaying[0].SongID != song.ID {
|
|
t.Fatalf("now playing = %v, want 1 entry for %s", nowPlaying, song.ID)
|
|
}
|
|
}
|
|
|
|
func TestReportPlaybackStoppedClearsNowPlayingAndRecordsHistory(t *testing.T) {
|
|
s, db := newTestServer(t)
|
|
u := createTestUser(t, s, "alice", "password123", false)
|
|
seedLibrary(t, s)
|
|
song := firstSong(t, s)
|
|
|
|
srv := newSubsonicTestServer(t, s)
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", song.ID)
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "1000")
|
|
q.Set("state", "playing")
|
|
getPath(t, srv, "/rest/reportPlayback.view", q)
|
|
|
|
q2 := baseParams("alice", "password123")
|
|
q2.Set("mediaId", song.ID)
|
|
q2.Set("mediaType", "song")
|
|
q2.Set("positionMs", "45000")
|
|
q2.Set("state", "stopped")
|
|
resp := getPath(t, srv, "/rest/reportPlayback.view", q2)
|
|
x := decodeXML(t, resp)
|
|
if x.Status != "ok" {
|
|
t.Fatalf("reportPlayback stopped failed: %+v", x)
|
|
}
|
|
|
|
nowPlaying, err := database.ListNowPlaying(db)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(nowPlaying) != 0 {
|
|
t.Fatalf("now playing should be cleared after stopped, got %v", nowPlaying)
|
|
}
|
|
history, err := database.ListRecentlyPlayed(db, u.ID, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(history) != 1 {
|
|
t.Fatalf("expected a playback_history entry after stopped, got %v", history)
|
|
}
|
|
}
|
|
|
|
func TestReportPlaybackIgnoreScrobble(t *testing.T) {
|
|
s, db := newTestServer(t)
|
|
u := createTestUser(t, s, "alice", "password123", false)
|
|
seedLibrary(t, s)
|
|
song := firstSong(t, s)
|
|
|
|
srv := newSubsonicTestServer(t, s)
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", song.ID)
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "45000")
|
|
q.Set("state", "stopped")
|
|
q.Set("ignoreScrobble", "true")
|
|
getPath(t, srv, "/rest/reportPlayback.view", q)
|
|
|
|
history, err := database.ListRecentlyPlayed(db, u.ID, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(history) != 0 {
|
|
t.Fatalf("ignoreScrobble=true should not record history, got %v", history)
|
|
}
|
|
}
|
|
|
|
func TestReportPlaybackInvalidState(t *testing.T) {
|
|
s, srv := newTestRecorderServer(t)
|
|
createTestUser(t, s, "alice", "password123", false)
|
|
seedLibrary(t, s)
|
|
song := firstSong(t, s)
|
|
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", song.ID)
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "1000")
|
|
q.Set("state", "bogus")
|
|
resp := getPath(t, srv.URL, "/rest/reportPlayback.view", q)
|
|
x := decodeXML(t, resp)
|
|
if x.Status != "failed" {
|
|
t.Fatalf("expected failure for invalid state, got %+v", x)
|
|
}
|
|
}
|
|
|
|
func TestReportPlaybackMissingParams(t *testing.T) {
|
|
s, srv := newTestRecorderServer(t)
|
|
createTestUser(t, s, "alice", "password123", false)
|
|
|
|
resp := getPath(t, srv.URL, "/rest/reportPlayback.view", baseParams("alice", "password123"))
|
|
x := decodeXML(t, resp)
|
|
if x.Status != "failed" || x.Error == nil || x.Error.Code != ErrMissingParameter {
|
|
t.Fatalf("expected error 10, got %+v", x)
|
|
}
|
|
}
|
|
|
|
func TestReportPlaybackUnknownMedia(t *testing.T) {
|
|
s, srv := newTestRecorderServer(t)
|
|
createTestUser(t, s, "alice", "password123", false)
|
|
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", "sg_doesnotexist")
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "0")
|
|
q.Set("state", "playing")
|
|
resp := getPath(t, srv.URL, "/rest/reportPlayback.view", q)
|
|
x := decodeXML(t, resp)
|
|
if x.Status != "failed" || x.Error == nil || x.Error.Code != ErrNotFound {
|
|
t.Fatalf("expected error 70, got %+v", x)
|
|
}
|
|
}
|
|
|
|
// TestReportPlaybackDoesNotLeakOtherUsersBookmarksOrQueue guards the
|
|
// "never expose one user's private state to another" requirement: each
|
|
// user's saved play queue is scoped by user, so alice's report never
|
|
// becomes visible in bob's queue.
|
|
func TestReportPlaybackDoesNotLeakAcrossUsers(t *testing.T) {
|
|
s, srv := newTestRecorderServer(t)
|
|
createTestUser(t, s, "alice", "password123", false)
|
|
createTestUser(t, s, "bob", "password123", false)
|
|
seedLibrary(t, s)
|
|
song := firstSong(t, s)
|
|
|
|
q := baseParams("alice", "password123")
|
|
q.Set("mediaId", song.ID)
|
|
q.Set("mediaType", "song")
|
|
q.Set("positionMs", "1000")
|
|
q.Set("state", "playing")
|
|
getPath(t, srv.URL, "/rest/reportPlayback.view", q)
|
|
|
|
q2 := baseParams("bob", "password123")
|
|
q2.Set("f", "json")
|
|
resp := getPath(t, srv.URL, "/rest/getPlayQueue.view", q2)
|
|
j := decodeJSON(t, resp)
|
|
if _, ok := j["playQueue"]; ok {
|
|
t.Fatalf("bob should not see alice's queue/report state: %v", j)
|
|
}
|
|
}
|