diff --git a/server/mockfs/mockfs.go b/server/mockfs/mockfs.go index 2dfd323..8b14ba3 100644 --- a/server/mockfs/mockfs.go +++ b/server/mockfs/mockfs.go @@ -20,11 +20,11 @@ import ( var ErrPathNotFound = errors.New("path not found") type MockFS struct { - t testing.TB - scanner *scanner.Scanner - dir string - reader *mreader - db *db.DB + t testing.TB + scanner *scanner.Scanner + dir string + tagReader *tagReader + db *db.DB } func New(t testing.TB) *MockFS { return new(t, []string{""}) } @@ -52,15 +52,15 @@ func new(t testing.TB, dirs []string) *MockFS { } } - parser := &mreader{map[string]*Tags{}} - scanner := scanner.New(absDirs, dbc, ";", parser) + tagReader := &tagReader{paths: map[string]*tagReaderResult{}} + scanner := scanner.New(absDirs, dbc, ";", tagReader) return &MockFS{ - t: t, - scanner: scanner, - dir: tmpDir, - reader: parser, - db: dbc, + t: t, + scanner: scanner, + dir: tmpDir, + tagReader: tagReader, + db: dbc, } } @@ -104,11 +104,12 @@ func (m *MockFS) addItems(prefix string, covers bool) { for al := 0; al < 3; al++ { for tr := 0; tr < 3; tr++ { m.AddTrack(p("artist-%d/album-%d/track-%d.flac", ar, al, tr)) - m.SetTags(p("artist-%d/album-%d/track-%d.flac", ar, al, tr), func(tags *Tags) { + m.SetTags(p("artist-%d/album-%d/track-%d.flac", ar, al, tr), func(tags *Tags) error { tags.RawArtist = fmt.Sprintf("artist-%d", ar) tags.RawAlbumArtist = fmt.Sprintf("artist-%d", ar) tags.RawAlbum = fmt.Sprintf("album-%d", al) tags.RawTitle = fmt.Sprintf("title-%d", tr) + return nil }) } if covers { @@ -134,8 +135,8 @@ func (m *MockFS) Symlink(src, dest string) { } src = filepath.Clean(src) dest = filepath.Clean(dest) - for k, v := range m.reader.tags { - m.reader.tags[strings.Replace(k, src, dest, 1)] = v + for k, v := range m.tagReader.paths { + m.tagReader.paths[strings.Replace(k, src, dest, 1)] = v } } @@ -240,15 +241,18 @@ func (m *MockFS) AddCover(path string) { defer f.Close() } -func (m *MockFS) SetTags(path string, cb func(*Tags)) { +func (m *MockFS) SetTags(path string, cb func(*Tags) error) { abspath := filepath.Join(m.dir, path) if err := os.Chtimes(abspath, time.Time{}, time.Now()); err != nil { m.t.Fatalf("touch track: %v", err) } - if _, ok := m.reader.tags[abspath]; !ok { - m.reader.tags[abspath] = &Tags{} + r := m.tagReader + if _, ok := r.paths[abspath]; !ok { + r.paths[abspath] = &tagReaderResult{tags: &Tags{}} + } + if err := cb(r.paths[abspath].tags); err != nil { + r.paths[abspath].err = err } - cb(m.reader.tags[abspath]) } func (m *MockFS) DumpDB(suffix ...string) { @@ -300,19 +304,24 @@ func (m *MockFS) DumpDB(suffix ...string) { } } -type mreader struct { - tags map[string]*Tags +type tagReaderResult struct { + tags *Tags + err error } -func (m *mreader) Read(abspath string) (tags.Parser, error) { - parser, ok := m.tags[abspath] +type tagReader struct { + paths map[string]*tagReaderResult +} + +func (m *tagReader) Read(abspath string) (tags.Parser, error) { + p, ok := m.paths[abspath] if !ok { return nil, ErrPathNotFound } - return parser, nil + return p.tags, p.err } -var _ tags.Reader = (*mreader)(nil) +var _ tags.Reader = (*tagReader)(nil) type Tags struct { RawTitle string diff --git a/server/scanner/scanner_fuzz_test.go b/server/scanner/scanner_fuzz_test.go index 634fbf8..aa833a4 100644 --- a/server/scanner/scanner_fuzz_test.go +++ b/server/scanner/scanner_fuzz_test.go @@ -37,7 +37,10 @@ func FuzzScanner(f *testing.F) { for i := 0; i < toAdd; i++ { path := fmt.Sprintf("artist-%d/album-%d/track-%d.flac", i/6, i/3, i) m.AddTrack(path) - m.SetTags(path, func(tags *mockfs.Tags) { fuzzStruct(i, data, tags) }) + m.SetTags(path, func(tags *mockfs.Tags) error { + fuzzStruct(i, data, tags) + return nil + }) } checkDelta(is, m, toAdd, toAdd) // we added all tracks, 0 delta diff --git a/server/scanner/scanner_test.go b/server/scanner/scanner_test.go index a10588b..5d812b1 100644 --- a/server/scanner/scanner_test.go +++ b/server/scanner/scanner_test.go @@ -111,11 +111,12 @@ func TestUpdatedTags(t *testing.T) { defer m.CleanUp() m.AddTrack("artist-10/album-10/track-10.flac") - m.SetTags("artist-10/album-10/track-10.flac", func(tags *mockfs.Tags) { + m.SetTags("artist-10/album-10/track-10.flac", func(tags *mockfs.Tags) error { tags.RawArtist = "artist" tags.RawAlbumArtist = "album-artist" tags.RawAlbum = "album" tags.RawTitle = "title" + return nil }) m.ScanAndClean() @@ -127,11 +128,12 @@ func TestUpdatedTags(t *testing.T) { is.Equal(track.Album.TagTitle, "album") // track has tags is.Equal(track.TagTitle, "title") // track has tags - m.SetTags("artist-10/album-10/track-10.flac", func(tags *mockfs.Tags) { + m.SetTags("artist-10/album-10/track-10.flac", func(tags *mockfs.Tags) error { tags.RawArtist = "artist-upd" tags.RawAlbumArtist = "album-artist-upd" tags.RawAlbum = "album-upd" tags.RawTitle = "title-upd" + return nil }) m.ScanAndClean() @@ -234,10 +236,10 @@ func TestGenres(t *testing.T) { } m.AddItems() - m.SetTags("artist-0/album-0/track-0.flac", func(tags *mockfs.Tags) { tags.RawGenre = "genre-a;genre-b" }) - m.SetTags("artist-0/album-0/track-1.flac", func(tags *mockfs.Tags) { tags.RawGenre = "genre-c;genre-d" }) - m.SetTags("artist-1/album-2/track-0.flac", func(tags *mockfs.Tags) { tags.RawGenre = "genre-e;genre-f" }) - m.SetTags("artist-1/album-2/track-1.flac", func(tags *mockfs.Tags) { tags.RawGenre = "genre-g;genre-h" }) + m.SetTags("artist-0/album-0/track-0.flac", func(tags *mockfs.Tags) error { tags.RawGenre = "genre-a;genre-b"; return nil }) + m.SetTags("artist-0/album-0/track-1.flac", func(tags *mockfs.Tags) error { tags.RawGenre = "genre-c;genre-d"; return nil }) + m.SetTags("artist-1/album-2/track-0.flac", func(tags *mockfs.Tags) error { tags.RawGenre = "genre-e;genre-f"; return nil }) + m.SetTags("artist-1/album-2/track-1.flac", func(tags *mockfs.Tags) error { tags.RawGenre = "genre-g;genre-h"; return nil }) m.ScanAndClean() isGenre("genre-a") // genre exists @@ -257,7 +259,7 @@ func TestGenres(t *testing.T) { isAlbumGenre("artist-0/", "album-0", "genre-a") // album genre exists isAlbumGenre("artist-0/", "album-0", "genre-b") // album genre exists - m.SetTags("artist-0/album-0/track-0.flac", func(tags *mockfs.Tags) { tags.RawGenre = "genre-aa;genre-bb" }) + m.SetTags("artist-0/album-0/track-0.flac", func(tags *mockfs.Tags) error { tags.RawGenre = "genre-aa;genre-bb"; return nil }) m.ScanAndClean() isTrackGenre("artist-0/", "album-0", "track-0.flac", "genre-aa") // updated track genre exists @@ -325,11 +327,12 @@ func TestNewAlbumForExistingArtist(t *testing.T) { for tr := 0; tr < 3; tr++ { m.AddTrack(fmt.Sprintf("artist-2/new-album/track-%d.mp3", tr)) - m.SetTags(fmt.Sprintf("artist-2/new-album/track-%d.mp3", tr), func(tags *mockfs.Tags) { + m.SetTags(fmt.Sprintf("artist-2/new-album/track-%d.mp3", tr), func(tags *mockfs.Tags) error { tags.RawArtist = "artist-2" tags.RawAlbumArtist = "artist-2" tags.RawAlbum = "new-album" tags.RawTitle = fmt.Sprintf("title-%d", tr) + return nil }) } @@ -351,20 +354,22 @@ func TestMultiFolderWithSharedArtist(t *testing.T) { const artistName = "artist-a" m.AddTrack(fmt.Sprintf("m-0/%s/album-a/track-1.flac", artistName)) - m.SetTags(fmt.Sprintf("m-0/%s/album-a/track-1.flac", artistName), func(tags *mockfs.Tags) { + m.SetTags(fmt.Sprintf("m-0/%s/album-a/track-1.flac", artistName), func(tags *mockfs.Tags) error { tags.RawArtist = artistName tags.RawAlbumArtist = artistName tags.RawAlbum = "album-a" tags.RawTitle = "track-1" + return nil }) m.ScanAndClean() m.AddTrack(fmt.Sprintf("m-1/%s/album-a/track-1.flac", artistName)) - m.SetTags(fmt.Sprintf("m-1/%s/album-a/track-1.flac", artistName), func(tags *mockfs.Tags) { + m.SetTags(fmt.Sprintf("m-1/%s/album-a/track-1.flac", artistName), func(tags *mockfs.Tags) error { tags.RawArtist = artistName tags.RawAlbumArtist = artistName tags.RawAlbum = "album-a" tags.RawTitle = "track-1" + return nil }) m.ScanAndClean() @@ -425,11 +430,12 @@ func TestSymlinkedSubdiscs(t *testing.T) { addItem := func(prefix, artist, album, disc, track string) { p := fmt.Sprintf("%s/%s/%s/%s/%s", prefix, artist, album, disc, track) m.AddTrack(p) - m.SetTags(p, func(tags *mockfs.Tags) { + m.SetTags(p, func(tags *mockfs.Tags) error { tags.RawArtist = artist tags.RawAlbumArtist = artist tags.RawAlbum = album tags.RawTitle = track + return nil }) }