package database import ( "database/sql" "fmt" "path/filepath" "testing" ) func setupGenreFixture(t *testing.T) *sql.DB { t.Helper() db, err := Open(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatalf("Open: %v", err) } t.Cleanup(func() { db.Close() }) folder, err := CreateMusicFolder(db, "Music", "/music", "music") if err != nil { t.Fatal(err) } artist, err := FindOrCreateArtist(db, "Test Artist", "", "") if err != nil { t.Fatal(err) } album, err := FindOrCreateAlbum(db, "Test Album", nullStr2(artist.ID), "", nullInt2(2020), nullInt2(0), "", "") if err != nil { t.Fatal(err) } if err := LinkAlbumArtist(db, album.ID, artist.ID, 0); err != nil { t.Fatal(err) } genre, err := FindOrCreateGenre(db, "Rock") if err != nil { t.Fatal(err) } if err := LinkAlbumGenre(db, album.ID, genre.ID); err != nil { t.Fatal(err) } for i := 1; i <= 3; i++ { mf, err := CreateMediaFile(db, folder.ID, fmt.Sprintf("song%d.mp3", i), 1000, 0, fmt.Sprintf("hash%d", i), "mp3", "song", 180, 320, 44100, 2) if err != nil { t.Fatal(err) } song, err := UpsertSong(db, UpsertSongInput{MediaFileID: mf.ID, AlbumID: nullStr2(album.ID), Title: "Song"}) if err != nil { t.Fatal(err) } if err := LinkSongGenre(db, song.ID, genre.ID); err != nil { t.Fatal(err) } } return db } func nullStr2(s string) sql.NullString { return sql.NullString{String: s, Valid: s != ""} } func nullInt2(n int64) sql.NullInt64 { if n == 0 { return sql.NullInt64{} } return sql.NullInt64{Int64: n, Valid: true} } func TestAlbumStats(t *testing.T) { db := setupGenreFixture(t) albums, err := ListAlbums(db, 10, 0) if err != nil || len(albums) != 1 { t.Fatalf("ListAlbums: %v, %v", albums, err) } count, dur, err := AlbumStats(db, albums[0].ID) if err != nil { t.Fatalf("AlbumStats: %v", err) } if count != 3 { t.Errorf("songCount = %d, want 3", count) } if dur != 540 { t.Errorf("duration = %v, want 540", dur) } } func TestListGenreStats(t *testing.T) { db := setupGenreFixture(t) stats, err := ListGenreStats(db) if err != nil { t.Fatalf("ListGenreStats: %v", err) } if len(stats) != 1 { t.Fatalf("stats = %v, want 1 genre", stats) } if stats[0].Name != "Rock" || stats[0].SongCount != 3 || stats[0].AlbumCount != 1 { t.Errorf("stats[0] = %+v, want Rock/3/1", stats[0]) } } func TestSongsByGenre(t *testing.T) { db := setupGenreFixture(t) songs, err := SongsByGenre(db, "Rock", 10, 0) if err != nil { t.Fatalf("SongsByGenre: %v", err) } if len(songs) != 3 { t.Fatalf("songs = %v, want 3", songs) } } func TestRandomSongIDsFilteredByGenre(t *testing.T) { db := setupGenreFixture(t) ids, err := RandomSongIDs(db, 10, "Rock", 0, 0) if err != nil { t.Fatalf("RandomSongIDs: %v", err) } if len(ids) != 3 { t.Fatalf("ids = %v, want 3", ids) } ids2, err := RandomSongIDs(db, 10, "Jazz", 0, 0) if err != nil { t.Fatalf("RandomSongIDs(Jazz): %v", err) } if len(ids2) != 0 { t.Fatalf("ids2 = %v, want 0 for nonexistent genre", ids2) } } func TestArtistAlbumCountAndCoverArt(t *testing.T) { db := setupGenreFixture(t) artists, err := ListArtists(db) if err != nil || len(artists) != 1 { t.Fatalf("ListArtists: %v, %v", artists, err) } n, err := ArtistAlbumCount(db, artists[0].ID) if err != nil { t.Fatalf("ArtistAlbumCount: %v", err) } if n != 1 { t.Errorf("ArtistAlbumCount = %d, want 1", n) } cover, err := ArtistCoverArtID(db, artists[0].ID) if err != nil { t.Fatalf("ArtistCoverArtID: %v", err) } if cover != "" { t.Errorf("ArtistCoverArtID = %q, want empty (no cover art set in fixture)", cover) } } func TestAlbumsByYearRange(t *testing.T) { db := setupGenreFixture(t) albums, err := AlbumsByYearRange(db, 2019, 2021, 10, 0) if err != nil { t.Fatalf("AlbumsByYearRange: %v", err) } if len(albums) != 1 { t.Fatalf("albums = %v, want 1", albums) } none, err := AlbumsByYearRange(db, 1990, 1991, 10, 0) if err != nil { t.Fatalf("AlbumsByYearRange: %v", err) } if len(none) != 0 { t.Fatalf("albums = %v, want 0 outside range", none) } }