From 94be108e8be8cfe66a4d470bb31bd6d124664012 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Fri, 10 Nov 2023 18:31:47 +0100 Subject: [PATCH] Tests and fixed for LB additional data conversion --- backends/listenbrainz/models.go | 96 +++++++++++++--- backends/listenbrainz/models_test.go | 159 +++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 16 deletions(-) create mode 100644 backends/listenbrainz/models_test.go diff --git a/backends/listenbrainz/models.go b/backends/listenbrainz/models.go index e6f5a57..602ee11 100644 --- a/backends/listenbrainz/models.go +++ b/backends/listenbrainz/models.go @@ -22,7 +22,10 @@ THE SOFTWARE. package listenbrainz import ( + "strconv" "time" + + "golang.org/x/exp/constraints" ) type GetListensResult struct { @@ -52,44 +55,105 @@ type Track struct { } func (t Track) Duration() time.Duration { - var duration time.Duration - milliseconds, ok := t.AdditionalInfo["duration_ms"].(float64) + info := t.AdditionalInfo + millisecondsF, ok := tryGetFloat[float64](info, "duration_ms") if ok { - duration = time.Duration(int64(milliseconds) * int64(time.Millisecond)) - } else { - seconds, ok := t.AdditionalInfo["duration_ms"].(float64) - if ok { - duration = time.Duration(int64(seconds) * int64(time.Second)) - } + return time.Duration(int64(millisecondsF * float64(time.Millisecond))) } - return duration + + millisecondsI, ok := tryGetInteger[int64](info, "duration_ms") + if ok { + return time.Duration(millisecondsI * int64(time.Millisecond)) + } + + secondsF, ok := tryGetFloat[float64](info, "duration") + if ok { + return time.Duration(int64(secondsF * float64(time.Second))) + } + + secondsI, ok := tryGetInteger[int64](info, "duration") + if ok { + return time.Duration(secondsI * int64(time.Second)) + } + + return time.Duration(0) } func (t Track) TrackNumber() int { - return int(tryGetValue[float64](t, "tracknumber")) + value, ok := tryGetInteger[int](t.AdditionalInfo, "tracknumber") + if ok { + return value + } + return 0 } func (t Track) Isrc() string { - return tryGetValue[string](t, "isrc") + return tryGetValueOrEmpty[string](t.AdditionalInfo, "isrc") } func (t Track) RecordingMbid() string { - return tryGetValue[string](t, "recording_mbid") + return tryGetValueOrEmpty[string](t.AdditionalInfo, "recording_mbid") } func (t Track) ReleaseMbid() string { - return tryGetValue[string](t, "release_mbid") + return tryGetValueOrEmpty[string](t.AdditionalInfo, "release_mbid") } func (t Track) ReleaseGroupMbid() string { - return tryGetValue[string](t, "release_group_mbid") + return tryGetValueOrEmpty[string](t.AdditionalInfo, "release_group_mbid") } -func tryGetValue[T any](track Track, key string) T { +func tryGetValueOrEmpty[T any](dict map[string]any, key string) T { var result T - value, ok := track.AdditionalInfo[key].(T) + value, ok := dict[key].(T) if ok { result = value } return result } + +func tryGetFloat[T constraints.Float](dict map[string]any, key string) (T, bool) { + valueFloat64, ok := dict[key].(float64) + if ok { + return T(valueFloat64), ok + } + + valueFloat32, ok := dict[key].(float32) + if ok { + return T(valueFloat32), ok + } + + valueStr, ok := dict[key].(string) + if ok { + valueFloat64, err := strconv.ParseFloat(valueStr, 64) + if err == nil { + return T(valueFloat64), ok + } + } + + return 0, false +} + +func tryGetInteger[T constraints.Integer](dict map[string]any, key string) (T, bool) { + valueInt64, ok := dict[key].(int64) + if ok { + return T(valueInt64), ok + } + + valueInt32, ok := dict[key].(int32) + if ok { + return T(valueInt32), ok + } + + valueInt, ok := dict[key].(int) + if ok { + return T(valueInt), ok + } + + valueFloat, ok := tryGetFloat[float64](dict, key) + if ok { + return T(valueFloat), ok + } + + return 0, false +} diff --git a/backends/listenbrainz/models_test.go b/backends/listenbrainz/models_test.go new file mode 100644 index 0000000..ac212f2 --- /dev/null +++ b/backends/listenbrainz/models_test.go @@ -0,0 +1,159 @@ +/* +Copyright © 2023 Philipp Wolfer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package listenbrainz_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.uploadedlobster.com/scotty/backends/listenbrainz" +) + +func TestTrackDurationMillisecondsInt(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration_ms": 528235, + }, + } + assert.Equal(t, time.Duration(528235*time.Millisecond), track.Duration()) +} + +func TestTrackDurationMillisecondsInt64(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration_ms": int64(528235), + }, + } + assert.Equal(t, time.Duration(528235*time.Millisecond), track.Duration()) +} + +func TestTrackDurationMillisecondsFloat(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration_ms": 528235.0, + }, + } + assert.Equal(t, time.Duration(528235*time.Millisecond), track.Duration()) +} + +func TestTrackDurationSecondsInt(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration": 528, + }, + } + assert.Equal(t, time.Duration(528*time.Second), track.Duration()) +} + +func TestTrackDurationSecondsInt64(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration": int64(528), + }, + } + assert.Equal(t, time.Duration(528*time.Second), track.Duration()) +} + +func TestTrackDurationSecondsFloat(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration": 528.235, + }, + } + assert.Equal(t, time.Duration(528235*time.Millisecond), track.Duration()) +} + +func TestTrackDurationSecondsString(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "duration": "528.235", + }, + } + assert.Equal(t, time.Duration(528235*time.Millisecond), track.Duration()) +} + +func TestTrackDurationEmpty(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{}, + } + assert.Empty(t, track.Duration()) +} + +func TestTrackTrackNumber(t *testing.T) { + expected := 7 + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "tracknumber": expected, + }, + } + assert.Equal(t, expected, track.TrackNumber()) +} + +func TestTrackTrackNumberString(t *testing.T) { + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "tracknumber": "12", + }, + } + assert.Equal(t, 12, track.TrackNumber()) +} + +func TestTrackIsrc(t *testing.T) { + expected := "TCAEJ1934417" + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "isrc": expected, + }, + } + assert.Equal(t, expected, track.Isrc()) +} + +func TestTrackRecordingMbid(t *testing.T) { + expected := "e02cc1c3-93fd-4e24-8b77-325060de920b" + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "recording_mbid": expected, + }, + } + assert.Equal(t, expected, track.RecordingMbid()) +} + +func TestTrackReleaseMbid(t *testing.T) { + expected := "e02cc1c3-93fd-4e24-8b77-325060de920b" + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "release_mbid": expected, + }, + } + assert.Equal(t, expected, track.ReleaseMbid()) +} + +func TestReleaseGroupMbid(t *testing.T) { + expected := "e02cc1c3-93fd-4e24-8b77-325060de920b" + track := listenbrainz.Track{ + AdditionalInfo: map[string]any{ + "release_group_mbid": expected, + }, + } + assert.Equal(t, expected, track.ReleaseGroupMbid()) +}