package uploads import ( "context" "errors" "testing" "github.com/google/uuid" "github.com/stretchr/testify/require" "pipu/api/internal/acoustid" "pipu/api/internal/musicbrainz" ) func TestAudioRecognitionRejectsWeakAndAmbiguousRecordings(t *testing.T) { a, b := uuid.NewString(), uuid.NewString() for _, tc := range []struct { matches []acoustid.Match state string }{ {nil, "not_found"}, {[]acoustid.Match{{RecordingID: a, Score: .89}}, "ambiguous"}, {[]acoustid.Match{{RecordingID: a, Score: .99}, {RecordingID: b, Score: .97}}, "ambiguous"}, {[]acoustid.Match{{RecordingID: a, Score: .99}, {RecordingID: a, Score: .98}, {RecordingID: b, Score: .7}}, "matched"}, {[]acoustid.Match{{RecordingID: "invalid", Score: 1}}, "not_found"}, } { r := chooseAudioMatch(uuid.New(), tc.matches) require.Equal(t, tc.state, r.State) if tc.state != "matched" { require.Empty(t, r.RecordingID) } } } func TestAudioOverridesWrongTagsButDoesNotProveEditionOrDuration(t *testing.T) { id := uuid.NewString() f := releaseFile("Wrong title", 9, 1, 180000) r := musicbrainz.Release{Tracks: []musicbrainz.Track{{RecordingID: id, Title: "Correct title", Artist: "Correct artist", Position: 1, Disc: 1, DurationMs: 180000}}} audio := map[uuid.UUID]AudioRecognition{f.ID: {FileID: f.ID, State: "matched", RecordingID: id, Score: .99}} c := matchReleaseWithAudio([]File{f}, r, audio) require.True(t, c.Complete) require.Equal(t, "acoustid", c.Matches[0].Method) require.Equal(t, "Wrong title", f.Meta.Title) require.Empty(t, f.Tags) r.Tracks = append(r.Tracks, r.Tracks[0]) c = matchReleaseWithAudio([]File{f}, r, audio) require.False(t, c.Complete) require.Empty(t, c.Matches, "same recording twice in an edition remains ambiguous") r.Tracks = r.Tracks[:1] r.Tracks[0].DurationMs = 195000 c = matchReleaseWithAudio([]File{f}, r, audio) require.False(t, c.Complete) require.Equal(t, "medium", c.Matches[0].Confidence) r.Tracks[0].RecordingID = uuid.NewString() c = matchReleaseWithAudio([]File{f}, r, audio) require.Empty(t, c.Matches) } type testAudioIdentifier struct { calls int err error id string duration int } func (a *testAudioIdentifier) Lookup(_ context.Context, fp string, duration int) ([]acoustid.Match, error) { a.calls++ a.duration = duration return []acoustid.Match{{RecordingID: a.id, Score: .99}}, a.err } func TestAudioIdentificationUsesFullDurationAndSkipsUnavailableFiles(t *testing.T) { f := releaseFile("Unknown", 1, 1, 321000) f.StagingPath = "batch/file.flac" provider := &testAudioIdentifier{id: uuid.NewString()} s := &Service{cfg: Config{StagingDir: t.TempDir()}, identifier: provider, encodedFingerprint: func(context.Context, string) (string, error) { return "fp", nil }} results, byFile, ids, err := s.identifyAudio(context.Background(), []File{f}) require.NoError(t, err) require.Len(t, results, 1) require.Equal(t, 321, provider.duration) require.Equal(t, provider.id, byFile[f.ID].RecordingID) require.Equal(t, []string{provider.id}, ids) s.encodedFingerprint = func(context.Context, string) (string, error) { return "", errors.New("fpcalc missing") } results, _, ids, err = s.identifyAudio(context.Background(), []File{f}) require.NoError(t, err) require.Equal(t, "unavailable", results[0].State) require.Empty(t, ids) require.Equal(t, 1, provider.calls) s.encodedFingerprint = func(context.Context, string) (string, error) { return "fp", nil } provider.err = errors.New("provider offline") _, _, _, err = s.identifyAudio(context.Background(), []File{f}) require.ErrorContains(t, err, "provider offline") }