Rewrites the internal/api comment blocks to rule 32: task, milestone and rule ids gone, the stories behind them restated as the constraint they left, stale references corrected (the stream secret is wired from config, the timezone handler already refreshes the scheduler, the Android app is the native client, the design docs cited are not in the repo). Also rewraps comment lines over 80 columns left by the earlier batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
4.0 KiB
Go
92 lines
4.0 KiB
Go
package api
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
|
)
|
|
|
|
func dupUUID(b byte) pgtype.UUID {
|
|
var u pgtype.UUID
|
|
u.Bytes[15] = b
|
|
u.Valid = true
|
|
return u
|
|
}
|
|
|
|
func dupTS(t time.Time) pgtype.Timestamptz { return pgtype.Timestamptz{Time: t, Valid: true} }
|
|
|
|
// Rows arrive one per member, members of a group together. The fold must keep
|
|
// groups apart, keep the query's order, and propose each group's survivor from
|
|
// its own members only.
|
|
func TestFoldDuplicateGroups(t *testing.T) {
|
|
older := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
newer := older.Add(48 * time.Hour)
|
|
ber := float32(0.04)
|
|
rows := []dbq.ListPendingDuplicateGroupMembersRow{
|
|
// Group 1: identical audio, sizes tie, the older copy should be kept.
|
|
{GroupID: dupUUID(1), Tier: "exact", DetectedAt: dupTS(newer), TrackID: dupUUID(10),
|
|
Title: "WWW", FileFormat: "mp3", FileSize: 6_900_000, DurationMs: 215_400, AddedAt: dupTS(newer), PlayCount: 3},
|
|
{GroupID: dupUUID(1), Tier: "exact", DetectedAt: dupTS(newer), TrackID: dupUUID(11),
|
|
Title: "WWW", FileFormat: "mp3", FileSize: 6_900_000, DurationMs: 215_400, AddedAt: dupTS(older), LikeCount: 1},
|
|
// Group 2: the same recording, FLAC against MP3.
|
|
{GroupID: dupUUID(2), Tier: "acoustic", WorstBitErrorRate: &ber, DetectedAt: dupTS(older), TrackID: dupUUID(20),
|
|
Title: "Lovesick", FileFormat: "mp3", FileSize: 9_000_000, DurationMs: 198_000, AddedAt: dupTS(older)},
|
|
{GroupID: dupUUID(2), Tier: "acoustic", WorstBitErrorRate: &ber, DetectedAt: dupTS(older), TrackID: dupUUID(21),
|
|
Title: "Lovesick", FileFormat: "flac", FileSize: 30_000_000, DurationMs: 198_000, AddedAt: dupTS(newer)},
|
|
}
|
|
|
|
got := foldDuplicateGroups(rows)
|
|
if len(got) != 2 {
|
|
t.Fatalf("folded %d groups, want 2", len(got))
|
|
}
|
|
|
|
g1, g2 := got[0], got[1]
|
|
if g1.ID != uuidToString(dupUUID(1)) || len(g1.Members) != 2 || g1.WorstBitErrorRate != nil {
|
|
t.Fatalf("group 1 = %+v, want the exact pair with no score", g1)
|
|
}
|
|
if g1.SurvivorTrackID != uuidToString(dupUUID(11)) || g1.SurvivorReason != "in the library longest" {
|
|
t.Errorf("group 1 survivor = (%s, %q), want the older copy", g1.SurvivorTrackID, g1.SurvivorReason)
|
|
}
|
|
if g1.Members[0].DurationSec != 215 || g1.Members[0].PlayCount != 3 || g1.Members[1].LikeCount != 1 {
|
|
t.Errorf("group 1 members lost their facts: %+v", g1.Members)
|
|
}
|
|
|
|
if g2.Tier != "acoustic" || g2.WorstBitErrorRate == nil || *g2.WorstBitErrorRate != ber {
|
|
t.Fatalf("group 2 = %+v, want the acoustic pair with its score", g2)
|
|
}
|
|
// Chosen from group 2's own members: a survivor leaking across groups is
|
|
// exactly what a wrong fold boundary would produce.
|
|
if g2.SurvivorTrackID != uuidToString(dupUUID(21)) || g2.SurvivorReason != "lossless (flac)" {
|
|
t.Errorf("group 2 survivor = (%s, %q), want the FLAC copy", g2.SurvivorTrackID, g2.SurvivorReason)
|
|
}
|
|
}
|
|
|
|
// the proposal shown beside a group follows the resolver's rule. The copy
|
|
// whose tags fit the album is proposed even when the other is larger (only a
|
|
// lossless copy outranks it).
|
|
func TestFoldDuplicateGroups_ProposesTheCopyWhoseTagsFit(t *testing.T) {
|
|
at := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
class := "same_release"
|
|
three := int32(3)
|
|
rows := []dbq.ListPendingDuplicateGroupMembersRow{
|
|
{GroupID: dupUUID(3), Tier: "acoustic", DetectedAt: dupTS(at), TrackID: dupUUID(30), Class: &class,
|
|
Title: "Song", FileFormat: "m4a", FileSize: 30_000_000, AddedAt: dupTS(at)},
|
|
{GroupID: dupUUID(3), Tier: "acoustic", DetectedAt: dupTS(at), TrackID: dupUUID(31), Class: &class,
|
|
Title: "Song", FileFormat: "mp3", FileSize: 9_000_000, AddedAt: dupTS(at), TrackNumber: &three, HasMbid: true},
|
|
}
|
|
got := foldDuplicateGroups(rows)
|
|
if len(got) != 1 {
|
|
t.Fatalf("folded %d groups, want 1", len(got))
|
|
}
|
|
g := got[0]
|
|
if g.SurvivorTrackID != uuidToString(dupUUID(31)) || g.SurvivorReason != "tags fit the album" {
|
|
t.Errorf("survivor = (%s, %q), want the tagged mp3", g.SurvivorTrackID, g.SurvivorReason)
|
|
}
|
|
if g.Class == nil || *g.Class != "same_release" {
|
|
t.Errorf("class not carried: %+v", g)
|
|
}
|
|
}
|