like malachite (atproto-lastfm-importer) but in go and bluer
go
spotify
tealfm
lastfm
atproto
1package kway
2
3import (
4 "testing"
5 "time"
6)
7
8// TestPlayRecord is a simple implementation of Mergeable for testing
9type TestPlayRecord struct {
10 TrackName string
11 Artist string
12 time time.Time
13 Source string // "lastfm" or "spotify"
14 HasMBID bool
15}
16
17func (r TestPlayRecord) IsDuplicate(other TestPlayRecord, tolerance time.Duration) (bool, bool) {
18 return r.SameAs(other, tolerance), r.BetterThan(other)
19}
20
21func (r TestPlayRecord) SameAs(other TestPlayRecord, tolerance time.Duration) bool {
22 if r.TrackName != other.TrackName {
23 return false
24 }
25 if r.Artist != other.Artist {
26 return false
27 }
28
29 diff := r.time.Sub(other.time)
30 if diff < 0 {
31 diff = -diff
32 }
33 return diff <= tolerance
34}
35
36func (r TestPlayRecord) BetterThan(other TestPlayRecord) bool {
37 if r.Source == "lastfm" && other.Source != "lastfm" {
38 return true
39 }
40 if r.Source != "lastfm" && other.Source == "lastfm" {
41 return false
42 }
43 return r.HasMBID && !other.HasMBID
44}
45
46func (r TestPlayRecord) Time() time.Time {
47 return r.time
48}
49
50func TestMerge(t *testing.T) {
51 baseTime := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC)
52
53 // Test case where duplicates are very close in time and should be merged
54 lastfmRecords := []TestPlayRecord{
55 {TrackName: "Song A", Artist: "Artist", time: baseTime, Source: "lastfm"},
56 {TrackName: "Song D", Artist: "Artist", time: baseTime.Add(3 * time.Hour), Source: "lastfm"},
57 }
58
59 spotifyRecords := []TestPlayRecord{
60 {TrackName: "Song A", Artist: "Artist", time: baseTime.Add(3 * time.Minute), Source: "spotify"}, // Duplicate within tolerance
61 {TrackName: "Song B", Artist: "Artist", time: baseTime.Add(time.Hour), Source: "spotify"},
62 {TrackName: "Song C", Artist: "Artist", time: baseTime.Add(2 * time.Hour), Source: "spotify"},
63 }
64
65 result := Merge([][]TestPlayRecord{lastfmRecords, spotifyRecords}, 10*time.Minute)
66
67 if len(result) != 4 {
68 t.Errorf("Expected 4 results, got %d", len(result))
69 }
70
71 // Check order - should be sorted by time
72 expectedOrder := []string{"Song A", "Song B", "Song C", "Song D"}
73 for i, expected := range expectedOrder {
74 if i >= len(result) {
75 t.Errorf("Missing result at position %d", i)
76 break
77 }
78 if result[i].TrackName != expected {
79 t.Errorf("Result %d should be %s, got %s", i, expected, result[i].TrackName)
80 }
81 }
82
83 // Check that LastFM version is preferred for duplicate Song A
84 if result[0].Source != "lastfm" {
85 t.Errorf("Duplicate Song A should be from lastfm, got %s", result[0].Source)
86 }
87}
88
89func TestMergeExactDuplicate(t *testing.T) {
90 baseTime := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC)
91
92 lastfmRecords := []TestPlayRecord{
93 {TrackName: "Song A", Artist: "Artist", time: baseTime, Source: "lastfm"},
94 }
95
96 spotifyRecords := []TestPlayRecord{
97 {TrackName: "Song A", Artist: "Artist", time: baseTime, Source: "spotify"}, // Exact duplicate
98 }
99
100 result := Merge([][]TestPlayRecord{lastfmRecords, spotifyRecords}, 0)
101
102 if len(result) != 1 {
103 t.Errorf("Expected 1 result, got %d", len(result))
104 }
105
106 // Check that LastFM version is preferred
107 if result[0].Source != "lastfm" {
108 t.Errorf("Duplicate should be from lastfm, got %s", result[0].Source)
109 }
110}
111
112func TestMergeEmptySources(t *testing.T) {
113 result := Merge([][]TestPlayRecord{}, 0)
114 if len(result) != 0 {
115 t.Errorf("Expected empty result, got %d items", len(result))
116 }
117
118 result = Merge([][]TestPlayRecord{{}, {}}, 0)
119 if len(result) != 0 {
120 t.Errorf("Expected empty result from empty sources, got %d items", len(result))
121 }
122}