aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-06-06 19:48:22 +0300
committersalmonik <raisersoft@proton.me>2026-06-06 19:48:22 +0300
commitd347d89dfeef54d648ffdea054897617c0016509 (patch)
tree0ea0e25e2a8e9bcdd8c06ffadbe29721a7f07f77 /tests
parentdirty, broken commit (diff)
downloadrsplayer-d347d89dfeef54d648ffdea054897617c0016509.tar.gz
rsplayer-d347d89dfeef54d648ffdea054897617c0016509.zip
correctly working auto completion for db
Diffstat (limited to 'tests')
-rw-r--r--tests/daemon.rs79
-rw-r--r--tests/database.rs112
-rw-r--r--tests/scrobbler.rs17
3 files changed, 161 insertions, 47 deletions
diff --git a/tests/daemon.rs b/tests/daemon.rs
new file mode 100644
index 0000000..e5cb270
--- /dev/null
+++ b/tests/daemon.rs
@@ -0,0 +1,79 @@
1/*
2 * This file is a part of RSPlayer
3 * Licensed under the GPL-3.0 License
4 * Copyright (C) 2026 Salmonik @ salmonik@tuta.io
5 * https://codeberg.org/salmonik/RSPlayer
6*/
7
8use std::path::PathBuf;
9
10use rsp::daemon::ScrobbleState;
11use rsp::queue::Track;
12
13#[test]
14fn test_scrobble_state_new() {
15 let s = ScrobbleState::new();
16 assert!(s.track.is_none());
17 assert!(s.start_time.is_none());
18 assert!(s.timestamp.is_none());
19}
20
21#[test]
22fn test_scrobble_state_clear() {
23 let mut s = ScrobbleState::new();
24 let t = Track {
25 path: PathBuf::from("/test/song.mp3"),
26 title: Some("Test".into()),
27 artist: Some("Artist".into()),
28 album: None,
29 duration_secs: Some(200.0),
30 is_stream: false,
31 };
32 s.start(t);
33 assert!(s.track.is_some());
34 s.clear();
35 assert!(s.track.is_none());
36 assert!(s.start_time.is_none());
37 assert!(s.timestamp.is_none());
38}
39
40#[test]
41fn test_should_scrobble_without_track_returns_false() {
42 assert!(!ScrobbleState::new().should_scrobble());
43}
44
45#[test]
46fn test_should_scrobble_threshold_below_30_seconds() {
47 assert!(!ScrobbleState::should_scrobble_with_params(29, Some(200.0)));
48}
49
50#[test]
51fn test_should_scrobble_threshold_half_duration() {
52 assert!(ScrobbleState::should_scrobble_with_params(100, Some(200.0)));
53}
54
55#[test]
56fn test_should_scrobble_threshold_below_half_duration() {
57 assert!(!ScrobbleState::should_scrobble_with_params(80, Some(200.0)));
58}
59
60#[test]
61fn test_should_scrobble_threshold_capped_at_4min() {
62 assert!(ScrobbleState::should_scrobble_with_params(240, Some(600.0)));
63 assert!(!ScrobbleState::should_scrobble_with_params(
64 239,
65 Some(600.0)
66 ));
67}
68
69#[test]
70fn test_should_scrobble_no_duration_requires_4min() {
71 assert!(ScrobbleState::should_scrobble_with_params(240, None));
72 assert!(!ScrobbleState::should_scrobble_with_params(239, None));
73}
74
75#[test]
76fn test_should_scrobble_short_song() {
77 assert!(ScrobbleState::should_scrobble_with_params(30, Some(60.0)));
78 assert!(!ScrobbleState::should_scrobble_with_params(15, Some(60.0)));
79}
diff --git a/tests/database.rs b/tests/database.rs
index adbf535..84eb663 100644
--- a/tests/database.rs
+++ b/tests/database.rs
@@ -114,115 +114,131 @@ fn seed_test_db(db: &Database) {
114fn test_complete_artists_prefix() { 114fn test_complete_artists_prefix() {
115 let db = Database::open_in_memory().unwrap(); 115 let db = Database::open_in_memory().unwrap();
116 seed_test_db(&db); 116 seed_test_db(&db);
117 let results = db.complete_artists("M").unwrap(); 117 let results = db.complete("M").unwrap();
118 assert_eq!(results.len(), 2); 118 assert!(results.contains(&"Metallica/".to_string()));
119 assert!(results.contains(&"Metallica".to_string())); 119 assert!(results.contains(&"Miles Davis/".to_string()));
120 assert!(results.contains(&"Miles Davis".to_string()));
121} 120}
122 121
123#[test] 122#[test]
124fn test_complete_artists_prefix_lowercase() { 123fn test_complete_artists_prefix_lowercase() {
125 let db = Database::open_in_memory().unwrap(); 124 let db = Database::open_in_memory().unwrap();
126 seed_test_db(&db); 125 seed_test_db(&db);
127 let results = db.complete_artists("m").unwrap(); 126 let results = db.complete("m").unwrap();
128 assert!( 127 assert!(
129 results.contains(&"Metallica".to_string()), 128 results.contains(&"Metallica/".to_string()),
130 "LIKE should be case-insensitive" 129 "LIKE should be case-insensitive"
131 ); 130 );
132} 131}
133 132
134#[test] 133#[test]
135fn test_complete_artists_no_match() { 134fn test_complete_no_match() {
136 let db = Database::open_in_memory().unwrap(); 135 let db = Database::open_in_memory().unwrap();
137 seed_test_db(&db); 136 seed_test_db(&db);
138 let results = db.complete_artists("Z").unwrap(); 137 let results = db.complete("Z").unwrap();
139 assert!(results.is_empty()); 138 assert!(results.is_empty());
140} 139}
141 140
142#[test] 141#[test]
143fn test_complete_artists_empty_prefix() { 142fn test_complete_empty_prefix() {
144 let db = Database::open_in_memory().unwrap(); 143 let db = Database::open_in_memory().unwrap();
145 seed_test_db(&db); 144 seed_test_db(&db);
146 let results = db.complete_artists("").unwrap(); 145 let results = db.complete("").unwrap();
147 assert_eq!(results.len(), 3); 146 assert_eq!(results.len(), 3);
147 assert!(results.contains(&"Metallica/".to_string()));
148 assert!(results.contains(&"Miles Davis/".to_string()));
149 assert!(results.contains(&"Aphex Twin/".to_string()));
148} 150}
149 151
150#[test] 152#[test]
151fn test_complete_albums_with_artist_prefix() { 153fn test_complete_albums_for_artist() {
152 let db = Database::open_in_memory().unwrap(); 154 let db = Database::open_in_memory().unwrap();
153 seed_test_db(&db); 155 seed_test_db(&db);
154 let results = db.complete_albums("Metallica/").unwrap(); 156 let results = db.complete("Metallica/").unwrap();
155 assert_eq!(results.len(), 2); 157 assert_eq!(results.len(), 2);
156 assert!(results.contains(&"Master of Puppets".to_string())); 158 assert!(results.contains(&"Metallica/Master of Puppets/".to_string()));
157 assert!(results.contains(&"Ride the Lightning".to_string())); 159 assert!(results.contains(&"Metallica/Ride the Lightning/".to_string()));
160}
161
162#[test]
163fn test_complete_albums_artist_lowercase() {
164 let db = Database::open_in_memory().unwrap();
165 seed_test_db(&db);
166 let results = db.complete("metallica/").unwrap();
167 assert_eq!(results.len(), 2, "artist match should be case-insensitive");
168 assert!(results.contains(&"metallica/Master of Puppets/".to_string()));
158} 169}
159 170
160#[test] 171#[test]
161fn test_complete_albums_with_album_prefix() { 172fn test_complete_albums_with_album_prefix() {
162 let db = Database::open_in_memory().unwrap(); 173 let db = Database::open_in_memory().unwrap();
163 seed_test_db(&db); 174 seed_test_db(&db);
164 let results = db.complete_albums("Metallica/R").unwrap(); 175 // "R" matches "Ride the Lightning" (prefix) and "Master of Puppets" (contains 'r')
165 assert_eq!(results.len(), 1); 176 let results = db.complete("Metallica/R").unwrap();
166 assert_eq!(results[0], "Ride the Lightning"); 177 assert_eq!(results.len(), 2);
178 assert_eq!(results[0], "Metallica/Ride the Lightning/");
179 assert_eq!(results[1], "Metallica/Master of Puppets/");
167} 180}
168 181
169#[test] 182#[test]
170fn test_complete_albums_unknown_artist() { 183fn test_complete_albums_substring_match() {
171 let db = Database::open_in_memory().unwrap(); 184 let db = Database::open_in_memory().unwrap();
172 seed_test_db(&db); 185 seed_test_db(&db);
173 let results = db.complete_albums("Unknown/").unwrap(); 186 // "ind" matches "Kind of Blue" (contains "ind")
174 assert!(results.is_empty()); 187 let results = db.complete("Miles Davis/ind").unwrap();
188 assert_eq!(results.len(), 1);
189 assert_eq!(results[0], "Miles Davis/Kind of Blue/");
175} 190}
176 191
177#[test] 192#[test]
178fn test_complete_albums_no_slash() { 193fn test_complete_artists_substring_match() {
179 let db = Database::open_in_memory().unwrap(); 194 let db = Database::open_in_memory().unwrap();
180 seed_test_db(&db); 195 seed_test_db(&db);
181 let results = db.complete_albums("Metallica").unwrap(); 196 // "x" matches "Aphex Twin" (contains 'x')
182 assert!(results.is_empty(), "needs trailing slash"); 197 let results = db.complete("x").unwrap();
198 assert!(results.contains(&"Aphex Twin/".to_string()));
183} 199}
184 200
185#[test] 201#[test]
186fn test_complete_tracks_full_path() { 202fn test_complete_albums_unknown_artist() {
187 let db = Database::open_in_memory().unwrap(); 203 let db = Database::open_in_memory().unwrap();
188 seed_test_db(&db); 204 seed_test_db(&db);
189 let results = db.complete_tracks("Metallica/Master of Puppets/").unwrap(); 205 let results = db.complete("Unknown/").unwrap();
190 assert_eq!(results.len(), 2); 206 assert!(results.is_empty());
191 assert!(results.contains(&"Battery".to_string()));
192 assert!(results.contains(&"Master of Puppets".to_string()));
193} 207}
194 208
195#[test] 209#[test]
196fn test_complete_tracks_with_prefix() { 210fn test_complete_tracks_for_album() {
197 let db = Database::open_in_memory().unwrap(); 211 let db = Database::open_in_memory().unwrap();
198 seed_test_db(&db); 212 seed_test_db(&db);
199 let results = db.complete_tracks("Metallica/Master of Puppets/B").unwrap(); 213 let results = db.complete("Metallica/Master of Puppets/").unwrap();
200 assert_eq!(results.len(), 1); 214 assert_eq!(results.len(), 2);
201 assert_eq!(results[0], "Battery"); 215 assert!(results.contains(&"Metallica/Master of Puppets/Battery".to_string()));
216 assert!(results.contains(&"Metallica/Master of Puppets/Master of Puppets".to_string()));
202} 217}
203 218
204#[test] 219#[test]
205fn test_complete_tracks_unknown_album() { 220fn test_complete_tracks_with_prefix() {
206 let db = Database::open_in_memory().unwrap(); 221 let db = Database::open_in_memory().unwrap();
207 seed_test_db(&db); 222 seed_test_db(&db);
208 let results = db.complete_tracks("Metallica/Nonexistent/").unwrap(); 223 let results = db.complete("Metallica/Master of Puppets/B").unwrap();
209 assert!(results.is_empty()); 224 assert_eq!(results.len(), 1);
225 assert_eq!(results[0], "Metallica/Master of Puppets/Battery");
210} 226}
211 227
212#[test] 228#[test]
213fn test_complete_tracks_too_few_parts() { 229fn test_complete_tracks_unknown_album() {
214 let db = Database::open_in_memory().unwrap(); 230 let db = Database::open_in_memory().unwrap();
215 seed_test_db(&db); 231 seed_test_db(&db);
216 let results = db.complete_tracks("Metallica").unwrap(); 232 let results = db.complete("Metallica/Nonexistent/").unwrap();
217 assert!(results.is_empty()); 233 assert!(results.is_empty());
218} 234}
219 235
220#[test] 236#[test]
221fn test_complete_empty_db() { 237fn test_complete_empty_db() {
222 let db = Database::open_in_memory().unwrap(); 238 let db = Database::open_in_memory().unwrap();
223 assert!(db.complete_artists("").unwrap().is_empty()); 239 assert!(db.complete("").unwrap().is_empty());
224 assert!(db.complete_albums("x/").unwrap().is_empty()); 240 assert!(db.complete("x/").unwrap().is_empty());
225 assert!(db.complete_tracks("x/y/").unwrap().is_empty()); 241 assert!(db.complete("x/y/").unwrap().is_empty());
226} 242}
227 243
228// --- find_tracks_by_album tests --- 244// --- find_tracks_by_album tests ---
@@ -271,17 +287,18 @@ fn test_find_tracks_by_album_unknown_album() {
271} 287}
272 288
273#[test] 289#[test]
274fn test_find_tracks_by_album_case_sensitive_artist() { 290fn test_find_tracks_by_album_case_insensitive_artist() {
275 let db = Database::open_in_memory().unwrap(); 291 let db = Database::open_in_memory().unwrap();
276 seed_test_db(&db); 292 seed_test_db(&db);
277 // SQLite = is case-sensitive for TEXT (unless NOCASE collation)
278 let tracks = db 293 let tracks = db
279 .find_tracks_by_album("metallica", "Master of Puppets") 294 .find_tracks_by_album("metallica", "Master of Puppets")
280 .unwrap(); 295 .unwrap();
281 assert!( 296 assert_eq!(
282 tracks.is_empty(), 297 tracks.len(),
283 "artist name match should be case-sensitive" 298 2,
299 "artist name match should be case-insensitive"
284 ); 300 );
301 assert_eq!(tracks[0].title, "Battery");
285} 302}
286 303
287#[test] 304#[test]
@@ -353,13 +370,14 @@ fn test_find_track_by_parts_no_match_artist() {
353} 370}
354 371
355#[test] 372#[test]
356fn test_find_track_by_parts_case_sensitive() { 373fn test_find_track_by_parts_case_insensitive() {
357 let db = Database::open_in_memory().unwrap(); 374 let db = Database::open_in_memory().unwrap();
358 seed_test_db(&db); 375 seed_test_db(&db);
359 let track = db 376 let track = db
360 .find_track_by_parts("metallica", "Master of Puppets", "Battery") 377 .find_track_by_parts("metallica", "Master of Puppets", "Battery")
361 .unwrap(); 378 .unwrap();
362 assert!(track.is_none(), "artist match should be case-sensitive"); 379 assert!(track.is_some(), "artist match should be case-insensitive");
380 assert_eq!(track.unwrap().title, "Battery");
363} 381}
364 382
365// --- resolve_path tests --- 383// --- resolve_path tests ---
diff --git a/tests/scrobbler.rs b/tests/scrobbler.rs
index a4b3fda..237a024 100644
--- a/tests/scrobbler.rs
+++ b/tests/scrobbler.rs
@@ -5,6 +5,8 @@
5 * https://codeberg.org/salmonik/RSPlayer 5 * https://codeberg.org/salmonik/RSPlayer
6*/ 6*/
7 7
8use std::collections::BTreeMap;
9
8use rsp::scrobbler::Scrobbler; 10use rsp::scrobbler::Scrobbler;
9 11
10#[test] 12#[test]
@@ -80,3 +82,18 @@ fn test_scrobbler_skip_empty_credentials() {
80 scrobbler.now_playing("Artist", "Track", Some("Album")); 82 scrobbler.now_playing("Artist", "Track", Some("Album"));
81 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890); 83 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890);
82} 84}
85
86#[test]
87fn test_sign_lastfm() {
88 let params = BTreeMap::from([
89 ("api_key", "abc123"),
90 ("method", "track.scrobble"),
91 ("sk", "session_key"),
92 ("track", "Test Track"),
93 ("artist", "Test Artist"),
94 ("timestamp", "1234567890"),
95 ]);
96 let sig = Scrobbler::sign_lastfm(&params, "sekrit");
97 assert_eq!(sig.len(), 32);
98 assert!(sig.chars().all(|c| c.is_ascii_hexdigit()));
99}