package metadata import "testing" func TestParseFFprobeOutputBasicTags(t *testing.T) { raw := ffprobeOutput{ Format: ffprobeFormat{ FormatName: "mp3", Duration: "215.5", BitRate: "320000", Tags: map[string]string{ "title": "Test Song", "album": "Test Album", "album_artist": "Album Artist", "artist": "Artist One; Artist Two", "genre": "Rock; Alternative", "date": "2004-05-11", "track": "3/12", "disc": "1/2", "composer": "Some Composer", "isrc": "USRC17607839", "producer": "Rick Rubin", }, }, Streams: []ffprobeStream{ {Index: 0, CodecType: "audio", SampleRate: "44100", Channels: 2, BitRate: "320000"}, }, } tags := parseFFprobeOutput(raw) if tags.Title != "Test Song" { t.Errorf("Title = %q", tags.Title) } if tags.Album != "Test Album" { t.Errorf("Album = %q", tags.Album) } if tags.AlbumArtist != "Album Artist" { t.Errorf("AlbumArtist = %q", tags.AlbumArtist) } if len(tags.Artists) != 2 || tags.Artists[0] != "Artist One" || tags.Artists[1] != "Artist Two" { t.Errorf("Artists = %v", tags.Artists) } if len(tags.Genres) != 2 || tags.Genres[0] != "Rock" || tags.Genres[1] != "Alternative" { t.Errorf("Genres = %v", tags.Genres) } if tags.Year != 2004 { t.Errorf("Year = %d, want 2004", tags.Year) } if tags.TrackNumber != 3 || tags.TrackTotal != 12 { t.Errorf("Track = %d/%d, want 3/12", tags.TrackNumber, tags.TrackTotal) } if tags.DiscNumber != 1 || tags.DiscTotal != 2 { t.Errorf("Disc = %d/%d, want 1/2", tags.DiscNumber, tags.DiscTotal) } if tags.ISRC != "USRC17607839" { t.Errorf("ISRC = %q", tags.ISRC) } if len(tags.Contributors) != 1 || tags.Contributors[0].Name != "Rick Rubin" || tags.Contributors[0].Role != "producer" { t.Errorf("Contributors = %v", tags.Contributors) } if tags.DurationSeconds != 215.5 { t.Errorf("DurationSeconds = %v", tags.DurationSeconds) } if tags.Format != "mp3" { t.Errorf("Format = %q", tags.Format) } if tags.SampleRateHz != 44100 || tags.Channels != 2 { t.Errorf("SampleRateHz/Channels = %d/%d", tags.SampleRateHz, tags.Channels) } if tags.BitrateKbps != 320 { t.Errorf("BitrateKbps = %d, want 320", tags.BitrateKbps) } if tags.Kind != "song" { t.Errorf("Kind = %q, want song", tags.Kind) } } func TestParseFFprobeOutputArtistWithSlashNotSplit(t *testing.T) { raw := ffprobeOutput{Format: ffprobeFormat{Tags: map[string]string{"artist": "AC/DC"}}} tags := parseFFprobeOutput(raw) if len(tags.Artists) != 1 || tags.Artists[0] != "AC/DC" { t.Errorf("Artists = %v, want [\"AC/DC\"] (must not split band names on '/')", tags.Artists) } } func TestParseFFprobeOutputEmbeddedArt(t *testing.T) { raw := ffprobeOutput{ Format: ffprobeFormat{Tags: map[string]string{"title": "Song"}}, Streams: []ffprobeStream{ {Index: 0, CodecType: "audio"}, {Index: 1, CodecType: "video", CodecName: "mjpeg", Disposition: map[string]int{"attached_pic": 1}}, }, } tags := parseFFprobeOutput(raw) if !tags.HasEmbeddedArt { t.Error("HasEmbeddedArt = false, want true") } if tags.EmbeddedArtStream != 1 { t.Errorf("EmbeddedArtStream = %d, want 1", tags.EmbeddedArtStream) } if tags.Kind != "song" { t.Errorf("Kind = %q, want song (attached_pic stream should not make this a video)", tags.Kind) } } func TestParseFFprobeOutputRealVideoStream(t *testing.T) { raw := ffprobeOutput{ Format: ffprobeFormat{Tags: map[string]string{"title": "Music Video"}}, Streams: []ffprobeStream{ {Index: 0, CodecType: "video", CodecName: "h264"}, {Index: 1, CodecType: "audio"}, }, } tags := parseFFprobeOutput(raw) if tags.Kind != "video" { t.Errorf("Kind = %q, want video", tags.Kind) } } func TestParseFFprobeOutputReplayGain(t *testing.T) { raw := ffprobeOutput{Format: ffprobeFormat{Tags: map[string]string{ "replaygain_track_gain": "-6.30 dB", "replaygain_track_peak": "0.987654", }}} tags := parseFFprobeOutput(raw) if tags.ReplayGainTrackGainDB == nil || *tags.ReplayGainTrackGainDB != -6.30 { t.Errorf("ReplayGainTrackGainDB = %v, want -6.30", tags.ReplayGainTrackGainDB) } if tags.ReplayGainTrackPeak == nil || *tags.ReplayGainTrackPeak != 0.987654 { t.Errorf("ReplayGainTrackPeak = %v, want 0.987654", tags.ReplayGainTrackPeak) } } func TestParseFFprobeOutputCaseInsensitiveTags(t *testing.T) { raw := ffprobeOutput{Format: ffprobeFormat{Tags: map[string]string{"ALBUMARTIST": "Vorbis Style Artist"}}} tags := parseFFprobeOutput(raw) if tags.AlbumArtist != "Vorbis Style Artist" { t.Errorf("AlbumArtist = %q, want case-insensitive match", tags.AlbumArtist) } } func TestParseFFprobeOutputNoTags(t *testing.T) { raw := ffprobeOutput{Format: ffprobeFormat{Duration: "10"}} tags := parseFFprobeOutput(raw) if tags.Title != "" || tags.Artists != nil { t.Errorf("expected empty tags, got %+v", tags) } }