Track details from the queue, a playlist or a smart playlist looked the track up in libraryStore's whole-library array, and returned silently when it had not loaded, so the menu item did nothing. That dependency is also why every track was fetched eagerly at startup (20.5 MB at 26k tracks). GetTracksByPaths answers for the paths in hand, and trackCache holds the answers: bounded, coalesced into one call per task, and forgetting what the retag, removal and scan events name. Every opener, and track-details' own refresh after a save, go through it. A source sweep pins the whole-library array to the store and the Tracks view. Closes #279
65 lines
1.8 KiB
Go
65 lines
1.8 KiB
Go
package library
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
// #279: the track-details openers resolve the rows a surface is showing
|
|
// by path, instead of finding them in the whole library's array. The
|
|
// answer must keep the caller's order (a batch dialog lists them as
|
|
// selected), drop what is not in the library rather than invent it, and
|
|
// survive more paths than one IN (...) can bind.
|
|
func TestGetTracksByPaths(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
lib, _ := setupTestLibrary(t)
|
|
seedAlbumsAndGenres(t, lib)
|
|
|
|
got, err := lib.GetTracksByPaths([]string{
|
|
"/other/b1.mp3", "/music/missing.mp3", "/music/a1.mp3", "/other/b1.mp3",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("GetTracksByPaths: %v", err)
|
|
}
|
|
|
|
paths := make([]string, 0, len(got))
|
|
for _, tr := range got {
|
|
paths = append(paths, tr.FilePath)
|
|
}
|
|
|
|
if want := "[/other/b1.mp3 /music/a1.mp3]"; fmt.Sprint(paths) != want {
|
|
t.Fatalf("paths = %v, want %s (caller order, missing dropped, duplicate once)", paths, want)
|
|
}
|
|
|
|
// Whole tracks, not just the key: details render every field.
|
|
if got[1].TrackName != "A1" || len(got[1].Genre) != 2 {
|
|
t.Errorf("a1 = %+v, want title A1 with two genres", got[1])
|
|
}
|
|
}
|
|
|
|
func TestGetTracksByPathsSpansChunks(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
lib, _ := setupTestLibrary(t)
|
|
seedAlbumsAndGenres(t, lib)
|
|
|
|
// The real path last, behind more misses than one chunk binds, so a
|
|
// loop that only ran the first chunk would return nothing.
|
|
paths := make([]string, 0, pathLookupChunk+2)
|
|
for i := range pathLookupChunk + 1 {
|
|
paths = append(paths, fmt.Sprintf("/nowhere/%d.mp3", i))
|
|
}
|
|
|
|
paths = append(paths, "/music/a2.mp3")
|
|
|
|
got, err := lib.GetTracksByPaths(paths)
|
|
if err != nil {
|
|
t.Fatalf("GetTracksByPaths: %v", err)
|
|
}
|
|
|
|
if len(got) != 1 || got[0].FilePath != "/music/a2.mp3" {
|
|
t.Fatalf("got %d tracks (%v), want only /music/a2.mp3", len(got), got)
|
|
}
|
|
}
|