Files
pipu-music/services/api/internal/uploads/release_match_test.go
T
mrleo1nid 39bf7d4b70
ci / module boundaries / boundaries (push) Successful in 10s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m30s
ci / api / api (push) Successful in 58s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m1s
ci / db / db (push) Failing after 25s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m36s
ci / ts / ts (packages + web) (push) Failing after 6m3s
feat(uploads): match release groups with MusicBrainz and AcoustID
2026-10-29 20:44:59 +03:00

96 lines
4.1 KiB
Go

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))
}