package uploads import ( "context" "github.com/google/uuid" "github.com/stretchr/testify/require" "pipu/api/internal/auth" "pipu/api/internal/library" "pipu/api/internal/musicbrainz" "testing" ) func TestReleaseOperationsRequireReviewPermission(t *testing.T) { s := &Service{} for _, ctx := range []context.Context{context.Background(), auth.WithPrincipal(context.Background(), auth.Principal{UserID: uuid.New(), Role: auth.RoleAdmin})} { _, err := s.GetReleaseReport(ctx, uuid.New()) require.Error(t, err) _, err = s.SearchReleases(ctx, uuid.New(), musicbrainz.Query{}) require.Error(t, err) _, err = s.ReleaseCover(ctx, uuid.New(), uuid.NewString()) require.Error(t, err) _, err = s.ApplyRelease(ctx, uuid.New(), uuid.NewString(), true, true) require.Error(t, err) } } func releaseFile(title string, number, disc, duration int) File { return File{ID: uuid.New(), Status: StatusPendingReview, Meta: &Meta{Artist: "Artist", AlbumArtist: "Artist", Album: "Album", Title: title, Track: &number, Disc: &disc}, DurationMs: &duration} } func TestReleaseCompletenessUsesTracksAndEditions(t *testing.T) { r := musicbrainz.Release{ID: uuid.NewString(), Artist: "Artist", Type: "Single", Tracks: []musicbrainz.Track{ {Title: "One", Artist: "Artist", Disc: 1, Position: 1, DurationMs: 180000}, {Title: "Two", Artist: "Artist", Disc: 2, Position: 1, DurationMs: 200000}, }} files := []File{releaseFile("One", 1, 1, 180100), releaseFile("Two", 1, 2, 199000)} c := matchRelease(files, r) require.True(t, c.Complete) require.Equal(t, 2, c.Matched) require.Equal(t, "high", c.Confidence) // Two encodings of the same song cover one catalogue slot, never two. c = matchRelease([]File{files[0], releaseFile("One", 1, 1, 180000)}, r) require.False(t, c.Complete) require.Equal(t, 1, c.Matched) require.Len(t, c.Missing, 1) // A deluxe edition with another track must remain incomplete. deluxe := r deluxe.Tracks = append(append([]musicbrainz.Track{}, r.Tracks...), musicbrainz.Track{Title: "Bonus", Artist: "Artist", Disc: 2, Position: 2, DurationMs: 220000}) require.False(t, matchRelease(files, deluxe).Complete) // A one-track upload does not turn the two-track single into a full single. require.False(t, matchRelease(files[:1], r).Complete) } func TestReleaseMatchingDoesNotClaimAmbiguousOrWeakMatchesAreComplete(t *testing.T) { r := musicbrainz.Release{Artist: "Artist", Tracks: []musicbrainz.Track{{Title: "Intro", Artist: "Artist", Disc: 1, Position: 1, DurationMs: 12000}, {Title: "Intro", Artist: "Artist", Disc: 2, Position: 1, DurationMs: 12000}}} c := matchRelease([]File{releaseFile("Intro", 1, 1, 12000)}, r) require.False(t, c.Complete) require.Len(t, c.Unmatched, 1) r.Tracks = r.Tracks[:1] f := releaseFile("Untitled", 1, 1, 12000) c = matchRelease([]File{f}, r) require.False(t, c.Complete) require.Equal(t, "medium", c.Confidence) f.Meta.Title = "Intro" f.Meta.Artist = "Someone Else" f.Meta.AlbumArtist = "Someone Else" require.False(t, matchRelease([]File{f}, r).Complete) f = releaseFile("Intro", 1, 1, 12000) f.DurationMs = nil require.False(t, matchRelease([]File{f}, r).Complete) } func TestReleaseQueryPrioritizesIDsAndRejectsMixedAlbums(t *testing.T) { a, b := releaseFile("One", 1, 1, 180000), releaseFile("Two", 2, 1, 180000) b.Meta.Album = "Another Album" _, ok := batchReleaseQuery([]File{a, b}) require.False(t, ok) id := uuid.NewString() a.Tags = map[string]string{"musicbrainz_albumid": id} a.Meta.Album = library.UnknownAlbum q, ok := batchReleaseQuery([]File{a, b}) require.True(t, ok) require.Equal(t, id, q.ReleaseID) b.Tags = map[string]string{"musicbrainz_albumid": uuid.NewString()} _, ok = batchReleaseQuery([]File{a, b}) require.False(t, ok) } func TestReleaseFingerprintInvalidatesEditsButNotApproval(t *testing.T) { f := releaseFile("One", 1, 1, 180000) files := []File{f} hash := releaseHash(files) files[0].Status = StatusApproved require.Equal(t, hash, releaseHash(files)) files[0].Meta.Title = "Changed" require.NotEqual(t, hash, releaseHash(files)) files[0].Status = StatusWithdrawn require.NotEqual(t, hash, releaseHash(files)) }