Remove dead code: duplicate ExternalRelease/Artist/ParsedArtist structs in model.go, ParseArtist/mbArtist/mbArtistData in client.go, ArtistTypeFilter and related filtering functions in api.go, SyncArtistDiscographyWithFilter in sync.go, and CacheStats/IsArtistCacheValid in cache.go. Fix bugs: SaveExternalRelease now stores NULL instead of empty string for zero CachedAt; sync upserts are now transactional with stale release cleanup; getCachedReleases returns int instead of *CacheStats; doGet uses url.Values for proper query encoding of MBID. Fix tests: removed duplicate TestRun_GracefulShutdown, removed dead code (_ = dbPath) from TestNewApp, fixed assertions in httptest handler goroutine to avoid data race, increased rate limiter timing tolerance, removed Client.Close() calls (no-op removed), fixed sync test cache expiry to use UPDATE instead of 0 TTL races. Fix formatting: cancel()}() formatting in main.go, error format string in sync.go.
182 lines
4.7 KiB
Go
182 lines
4.7 KiB
Go
package musicbrainz
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"naviwatcher/internal/database"
|
|
)
|
|
|
|
func insertTestArtistForCache(db *database.DB, id string) error {
|
|
_, err := db.Conn().Exec(
|
|
"INSERT OR IGNORE INTO artist_settings (id, name) VALUES (?, ?)",
|
|
id, "Test Artist "+id,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func TestGetCachedReleases_CacheHit(t *testing.T) {
|
|
db, err := database.New(":memory:")
|
|
if err != nil {
|
|
t.Fatalf("New() error: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
artistID := "artist-cache-hit"
|
|
if err := insertTestArtistForCache(db, artistID); err != nil {
|
|
t.Fatalf("insertTestArtist: %v", err)
|
|
}
|
|
|
|
// Insert releases with recent cached_at timestamps
|
|
now := time.Now().Format("2006-01-02 15:04:05")
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, type, cached_at) VALUES (?, ?, ?, ?, ?)",
|
|
"rg-hit-1", artistID, "Cached Album 1", "album", now,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert rg-hit-1: %v", err)
|
|
}
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, type, cached_at) VALUES (?, ?, ?, ?, ?)",
|
|
"rg-hit-2", artistID, "Cached Album 2", "single", now,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert rg-hit-2: %v", err)
|
|
}
|
|
|
|
ttl := 24 * time.Hour
|
|
count, err := GetCachedReleases(db, artistID, ttl)
|
|
if err != nil {
|
|
t.Fatalf("GetCachedReleases() error: %v", err)
|
|
}
|
|
|
|
if count != 2 {
|
|
t.Errorf("GetCachedReleases() = %d, want 2", count)
|
|
}
|
|
}
|
|
|
|
func TestGetCachedReleases_CacheMiss_Expired(t *testing.T) {
|
|
db, err := database.New(":memory:")
|
|
if err != nil {
|
|
t.Fatalf("New() error: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
artistID := "artist-cache-miss"
|
|
if err := insertTestArtistForCache(db, artistID); err != nil {
|
|
t.Fatalf("insertTestArtist: %v", err)
|
|
}
|
|
|
|
// Insert a release with an expired cached_at (48 hours ago)
|
|
expired := time.Now().Add(-48 * time.Hour).Format("2006-01-02 15:04:05")
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, type, cached_at) VALUES (?, ?, ?, ?, ?)",
|
|
"rg-expired", artistID, "Expired Album", "album", expired,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert expired release: %v", err)
|
|
}
|
|
|
|
ttl := 24 * time.Hour
|
|
count, err := GetCachedReleases(db, artistID, ttl)
|
|
if err != nil {
|
|
t.Fatalf("GetCachedReleases() error: %v", err)
|
|
}
|
|
|
|
if count != 0 {
|
|
t.Errorf("GetCachedReleases() = %d, want 0 (expired entry should not be cached)", count)
|
|
}
|
|
}
|
|
|
|
func TestGetCachedReleases_CacheMiss_NoCachedAt(t *testing.T) {
|
|
db, err := database.New(":memory:")
|
|
if err != nil {
|
|
t.Fatalf("New() error: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
artistID := "artist-no-cached"
|
|
if err := insertTestArtistForCache(db, artistID); err != nil {
|
|
t.Fatalf("insertTestArtist: %v", err)
|
|
}
|
|
|
|
// Insert a release WITHOUT cached_at (NULL)
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, type) VALUES (?, ?, ?, ?)",
|
|
"rg-nocached", artistID, "Uncached Album", "album",
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert uncached release: %v", err)
|
|
}
|
|
|
|
ttl := 24 * time.Hour
|
|
count, err := GetCachedReleases(db, artistID, ttl)
|
|
if err != nil {
|
|
t.Fatalf("GetCachedReleases() error: %v", err)
|
|
}
|
|
|
|
if count != 0 {
|
|
t.Errorf("GetCachedReleases() = %d, want 0 (NULL cached_at should not be cached)", count)
|
|
}
|
|
}
|
|
|
|
func TestGetCachedReleases_EmptyArtist(t *testing.T) {
|
|
db, err := database.New(":memory:")
|
|
if err != nil {
|
|
t.Fatalf("New() error: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
ttl := 24 * time.Hour
|
|
count, err := GetCachedReleases(db, "nonexistent-artist", ttl)
|
|
if err != nil {
|
|
t.Fatalf("GetCachedReleases() error: %v", err)
|
|
}
|
|
|
|
if count != 0 {
|
|
t.Errorf("GetCachedReleases() = %d, want 0 for nonexistent artist", count)
|
|
}
|
|
}
|
|
|
|
func TestGetCachedReleases_MixedExpiry(t *testing.T) {
|
|
db, err := database.New(":memory:")
|
|
if err != nil {
|
|
t.Fatalf("New() error: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
artistID := "artist-mixed"
|
|
if err := insertTestArtistForCache(db, artistID); err != nil {
|
|
t.Fatalf("insertTestArtist: %v", err)
|
|
}
|
|
|
|
now := time.Now().Format("2006-01-02 15:04:05")
|
|
expired := time.Now().Add(-48 * time.Hour).Format("2006-01-02 15:04:05")
|
|
|
|
// Mix of fresh and expired
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, cached_at) VALUES (?, ?, ?, ?)",
|
|
"rg-fresh", artistID, "Fresh Album", now,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert fresh: %v", err)
|
|
}
|
|
_, err = db.Conn().Exec(
|
|
"INSERT INTO external_releases (rgid, artist_id, title, cached_at) VALUES (?, ?, ?, ?)",
|
|
"rg-old", artistID, "Old Album", expired,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("insert old: %v", err)
|
|
}
|
|
|
|
ttl := 24 * time.Hour
|
|
count, err := GetCachedReleases(db, artistID, ttl)
|
|
if err != nil {
|
|
t.Fatalf("GetCachedReleases() error: %v", err)
|
|
}
|
|
|
|
if count != 1 {
|
|
t.Errorf("GetCachedReleases() = %d, want 1 (only fresh entry)", count)
|
|
}
|
|
}
|