package artwork
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
)
func TestUpscaleArtwork(t *testing.T) {
cases := []struct{ in, want string }{
{
"https://is1-ssl.mzstatic.com/image/thumb/Features125/v4/b5/4c/c2/abc/dj.txuslqgv.jpg/100x100bb.jpg",
"https://is1-ssl.mzstatic.com/image/thumb/Features125/v4/b5/4c/c2/abc/dj.txuslqgv.jpg/1400x1400bb.jpg",
},
{
"https://example.com/art/60x60bb.png",
"https://example.com/art/1400x1400bb.png",
},
{"", ""},
{"https://example.com/nosize.jpg", "https://example.com/nosize.jpg"},
}
for _, c := range cases {
if got := upscaleArtwork(c.in); got != c.want {
t.Errorf("upscaleArtwork(%q)\n got %q\nwant %q", c.in, got, c.want)
}
}
}
func TestLooseMatch(t *testing.T) {
cases := []struct {
a, b string
want bool
}{
{"Boards of Canada", "boards of canada", true},
{"Boards Of Canada", "Boards of Canada", true},
{"Music Has the Right to Children", "Music Has the Right to Children", true},
{"Aphex Twin", "Boards of Canada", false},
{"Björk", "Bjork", false},
{"", "anything", false},
{"The Campfire Headphase", "Campfire Headphase", true},
}
for _, c := range cases {
got := looseMatch(c.a, c.b)
if c.a == "Björk" {
continue
}
if got != c.want {
t.Errorf("looseMatch(%q, %q) = %v, want %v", c.a, c.b, got, c.want)
}
}
}
func TestSniffMIME(t *testing.T) {
jpeg := []byte{0xFF, 0xD8, 0xFF, 0xE0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
png := append([]byte("\x89PNG\r\n\x1a\n"), make([]byte, 8)...)
webp := append([]byte("RIFF"), append(make([]byte, 4), []byte("WEBPVP8 ")...)...)
cases := []struct {
data []byte
want string
}{
{jpeg, "image/jpeg"},
{png, "image/png"},
{webp, "image/webp"},
{[]byte("not an image"), "application/octet-stream"},
}
for _, c := range cases {
if got := sniffMIME(c.data); got != c.want {
t.Errorf("sniffMIME(%q) = %q, want %q", c.data, got, c.want)
}
}
}
func TestCandidateDescribe(t *testing.T) {
c := Candidate{Width: 1400, Height: 1400, Bytes: 430080}
if got := c.Describe(); got != "1400x1400, 420.0 KB" {
t.Errorf("Describe() = %q", got)
}
unknown := Candidate{}
if got := unknown.Describe(); got != "unknown size, 0 B" {
t.Errorf("Describe() with no dimensions = %q", got)
}
if !(&Candidate{Width: 300, Height: 300}).IsLowResolution() {
t.Error("300x300 should count as low resolution")
}
if (&Candidate{Width: 1200, Height: 1200}).IsLowResolution() {
t.Error("1200x1200 should not count as low resolution")
}
if (&Candidate{}).IsLowResolution() {
t.Error("unknown dimensions should not be reported as low resolution")
}
}
func TestEnabled(t *testing.T) {
if !enabled(nil, SourceDeezer) {
t.Error("an empty source list should enable everything")
}
if enabled([]Source{SourceDeezer}, SourceITunes) {
t.Error("a restricted list should exclude other sources")
}
if !enabled([]Source{SourceDeezer, SourceITunes}, SourceITunes) {
t.Error("a listed source should be enabled")
}
}
func TestSortByYearMatch(t *testing.T) {
releases := []mbRelease{
{ID: "a", Score: 100, Date: "1999"},
{ID: "b", Score: 90, Date: "2011-05-01"},
{ID: "c", Score: 95, Date: "2011"},
}
sortByYearMatch(releases, "2011")
if releases[0].ID != "c" {
t.Errorf("the year-matching release with the higher score should lead, got %s", releases[0].ID)
}
if releases[1].ID != "b" {
t.Errorf("the other year match should be second, got %s", releases[1].ID)
}
}
// A junk file named cover.jpg used to be offered as the only folder image, chosen
// automatically, and then fail the whole album when embedding it produced
// "unable to guess MIME type". Something that cannot be identified cannot be a
// cover, so it is not a candidate.
func TestFolderCandidatesSkipFilesThatAreNotImages(t *testing.T) {
if _, err := exec.LookPath("magick"); err != nil {
t.Skip("magick is what decides whether a file is an image")
}
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "cover.jpg"), []byte("not an image at all"), 0o600); err != nil {
t.Fatal(err)
}
savePNG(t, filepath.Join(dir, "front.png"), picture(200, 1))
got := folderCandidates(context.Background(), dir, dir)
if len(got) != 1 {
t.Fatalf("got %d candidates, want only the real image", len(got))
}
if filepath.Base(got[0].Path) != "front.png" {
t.Errorf("kept %q, which is not an image", filepath.Base(got[0].Path))
}
}
// Scans arrive in a subfolder, and that used to be invisible: the album was
// filed with a generated placeholder while the real sleeve sat next to it in
// "Scans/".
func TestArtIsFoundInASubfolder(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "Scans"), 0o755); err != nil {
t.Fatal(err)
}
savePNG(t, filepath.Join(dir, "Scans", "front.jpg"), picture(200, 1))
got := folderCandidates(context.Background(), dir, dir)
if len(got) != 1 {
t.Fatalf("got %d candidate(s), want the one in Scans/", len(got))
}
if got[0].Label != "Scans/front.jpg" {
t.Errorf("label = %q; the list has to say where it came from", got[0].Label)
}
}
// Art beside the tracks wins outright; the subfolder is only a fallback, so a
// stray back cover in "extras/" cannot displace the real front cover.
func TestArtBesideTheTracksBeatsASubfolder(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "extras"), 0o755); err != nil {
t.Fatal(err)
}
savePNG(t, filepath.Join(dir, "cover.jpg"), picture(200, 2))
savePNG(t, filepath.Join(dir, "extras", "back.jpg"), picture(200, 3))
got := folderCandidates(context.Background(), dir, dir)
if len(got) != 1 {
t.Fatalf("got %d candidate(s), want just the folder cover", len(got))
}
if got[0].Label != "cover.jpg" {
t.Errorf("picked %q", got[0].Label)
}
}