diff options
| author | salmonik <raisersoft@proton.me> | 2026-06-04 00:21:46 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-06-04 00:21:46 +0200 |
| commit | 1e48765ab39a679abcc4eac6927ad3bb58f7b438 (patch) | |
| tree | 5554f2a06bde693d4d9c39ed26f80677d61da991 /tests/database.rs | |
| parent | fix no metadata songs handling (diff) | |
| download | rsplayer-1e48765ab39a679abcc4eac6927ad3bb58f7b438.tar.gz rsplayer-1e48765ab39a679abcc4eac6927ad3bb58f7b438.zip | |
dirty, broken commit
Diffstat (limited to '')
| -rw-r--r-- | tests/database.rs | 393 |
1 files changed, 392 insertions, 1 deletions
diff --git a/tests/database.rs b/tests/database.rs index 6cd870e..adbf535 100644 --- a/tests/database.rs +++ b/tests/database.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * https://codeberg.org/salmonik/RSPlayer | 5 | * https://codeberg.org/salmonik/RSPlayer |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | use rsp::database::{extract_metadata, is_audio_file}; | 8 | use rsp::database::{Database, extract_metadata, is_audio_file}; |
| 9 | use std::path::PathBuf; | 9 | use std::path::PathBuf; |
| 10 | 10 | ||
| 11 | #[test] | 11 | #[test] |
| @@ -90,3 +90,394 @@ fn test_extract_metadata_no_parent() { | |||
| 90 | assert_eq!(album, "Unknown"); | 90 | assert_eq!(album, "Unknown"); |
| 91 | assert_eq!(title, "song"); | 91 | assert_eq!(title, "song"); |
| 92 | } | 92 | } |
| 93 | |||
| 94 | fn seed_test_db(db: &Database) { | ||
| 95 | let conn: &rusqlite::Connection = db.conn(); | ||
| 96 | conn.execute_batch( | ||
| 97 | "INSERT INTO artists (id, name) VALUES (1, 'Metallica'), (2, 'Miles Davis'), (3, 'Aphex Twin'); | ||
| 98 | INSERT INTO albums (id, artist_id, title) VALUES | ||
| 99 | (1, 1, 'Master of Puppets'), | ||
| 100 | (2, 1, 'Ride the Lightning'), | ||
| 101 | (3, 2, 'Kind of Blue'), | ||
| 102 | (4, 3, 'Selected Ambient Works'); | ||
| 103 | INSERT INTO tracks (id, album_id, title, path, duration, track_number) VALUES | ||
| 104 | (1, 1, 'Battery', '/m/Metallica/Master of Puppets/01-Battery.mp3', 313, 1), | ||
| 105 | (2, 1, 'Master of Puppets', '/m/Metallica/Master of Puppets/02-Master of Puppets.mp3', 515, 2), | ||
| 106 | (3, 2, 'Fight Fire with Fire', '/m/Metallica/Ride the Lightning/01-Fight Fire with Fire.mp3', 285, 1), | ||
| 107 | (4, 3, 'So What', '/m/Miles Davis/Kind of Blue/01-So What.mp3', 562, 1), | ||
| 108 | (5, 4, 'Xtal', '/m/Aphex Twin/Selected Ambient Works/01-Xtal.mp3', 437, 1);", | ||
| 109 | ) | ||
| 110 | .unwrap(); | ||
| 111 | } | ||
| 112 | |||
| 113 | #[test] | ||
| 114 | fn test_complete_artists_prefix() { | ||
| 115 | let db = Database::open_in_memory().unwrap(); | ||
| 116 | seed_test_db(&db); | ||
| 117 | let results = db.complete_artists("M").unwrap(); | ||
| 118 | assert_eq!(results.len(), 2); | ||
| 119 | assert!(results.contains(&"Metallica".to_string())); | ||
| 120 | assert!(results.contains(&"Miles Davis".to_string())); | ||
| 121 | } | ||
| 122 | |||
| 123 | #[test] | ||
| 124 | fn test_complete_artists_prefix_lowercase() { | ||
| 125 | let db = Database::open_in_memory().unwrap(); | ||
| 126 | seed_test_db(&db); | ||
| 127 | let results = db.complete_artists("m").unwrap(); | ||
| 128 | assert!( | ||
| 129 | results.contains(&"Metallica".to_string()), | ||
| 130 | "LIKE should be case-insensitive" | ||
| 131 | ); | ||
| 132 | } | ||
| 133 | |||
| 134 | #[test] | ||
| 135 | fn test_complete_artists_no_match() { | ||
| 136 | let db = Database::open_in_memory().unwrap(); | ||
| 137 | seed_test_db(&db); | ||
| 138 | let results = db.complete_artists("Z").unwrap(); | ||
| 139 | assert!(results.is_empty()); | ||
| 140 | } | ||
| 141 | |||
| 142 | #[test] | ||
| 143 | fn test_complete_artists_empty_prefix() { | ||
| 144 | let db = Database::open_in_memory().unwrap(); | ||
| 145 | seed_test_db(&db); | ||
| 146 | let results = db.complete_artists("").unwrap(); | ||
| 147 | assert_eq!(results.len(), 3); | ||
| 148 | } | ||
| 149 | |||
| 150 | #[test] | ||
| 151 | fn test_complete_albums_with_artist_prefix() { | ||
| 152 | let db = Database::open_in_memory().unwrap(); | ||
| 153 | seed_test_db(&db); | ||
| 154 | let results = db.complete_albums("Metallica/").unwrap(); | ||
| 155 | assert_eq!(results.len(), 2); | ||
| 156 | assert!(results.contains(&"Master of Puppets".to_string())); | ||
| 157 | assert!(results.contains(&"Ride the Lightning".to_string())); | ||
| 158 | } | ||
| 159 | |||
| 160 | #[test] | ||
| 161 | fn test_complete_albums_with_album_prefix() { | ||
| 162 | let db = Database::open_in_memory().unwrap(); | ||
| 163 | seed_test_db(&db); | ||
| 164 | let results = db.complete_albums("Metallica/R").unwrap(); | ||
| 165 | assert_eq!(results.len(), 1); | ||
| 166 | assert_eq!(results[0], "Ride the Lightning"); | ||
| 167 | } | ||
| 168 | |||
| 169 | #[test] | ||
| 170 | fn test_complete_albums_unknown_artist() { | ||
| 171 | let db = Database::open_in_memory().unwrap(); | ||
| 172 | seed_test_db(&db); | ||
| 173 | let results = db.complete_albums("Unknown/").unwrap(); | ||
| 174 | assert!(results.is_empty()); | ||
| 175 | } | ||
| 176 | |||
| 177 | #[test] | ||
| 178 | fn test_complete_albums_no_slash() { | ||
| 179 | let db = Database::open_in_memory().unwrap(); | ||
| 180 | seed_test_db(&db); | ||
| 181 | let results = db.complete_albums("Metallica").unwrap(); | ||
| 182 | assert!(results.is_empty(), "needs trailing slash"); | ||
| 183 | } | ||
| 184 | |||
| 185 | #[test] | ||
| 186 | fn test_complete_tracks_full_path() { | ||
| 187 | let db = Database::open_in_memory().unwrap(); | ||
| 188 | seed_test_db(&db); | ||
| 189 | let results = db.complete_tracks("Metallica/Master of Puppets/").unwrap(); | ||
| 190 | assert_eq!(results.len(), 2); | ||
| 191 | assert!(results.contains(&"Battery".to_string())); | ||
| 192 | assert!(results.contains(&"Master of Puppets".to_string())); | ||
| 193 | } | ||
| 194 | |||
| 195 | #[test] | ||
| 196 | fn test_complete_tracks_with_prefix() { | ||
| 197 | let db = Database::open_in_memory().unwrap(); | ||
| 198 | seed_test_db(&db); | ||
| 199 | let results = db.complete_tracks("Metallica/Master of Puppets/B").unwrap(); | ||
| 200 | assert_eq!(results.len(), 1); | ||
| 201 | assert_eq!(results[0], "Battery"); | ||
| 202 | } | ||
| 203 | |||
| 204 | #[test] | ||
| 205 | fn test_complete_tracks_unknown_album() { | ||
| 206 | let db = Database::open_in_memory().unwrap(); | ||
| 207 | seed_test_db(&db); | ||
| 208 | let results = db.complete_tracks("Metallica/Nonexistent/").unwrap(); | ||
| 209 | assert!(results.is_empty()); | ||
| 210 | } | ||
| 211 | |||
| 212 | #[test] | ||
| 213 | fn test_complete_tracks_too_few_parts() { | ||
| 214 | let db = Database::open_in_memory().unwrap(); | ||
| 215 | seed_test_db(&db); | ||
| 216 | let results = db.complete_tracks("Metallica").unwrap(); | ||
| 217 | assert!(results.is_empty()); | ||
| 218 | } | ||
| 219 | |||
| 220 | #[test] | ||
| 221 | fn test_complete_empty_db() { | ||
| 222 | let db = Database::open_in_memory().unwrap(); | ||
| 223 | assert!(db.complete_artists("").unwrap().is_empty()); | ||
| 224 | assert!(db.complete_albums("x/").unwrap().is_empty()); | ||
| 225 | assert!(db.complete_tracks("x/y/").unwrap().is_empty()); | ||
| 226 | } | ||
| 227 | |||
| 228 | // --- find_tracks_by_album tests --- | ||
| 229 | |||
| 230 | #[test] | ||
| 231 | fn test_find_tracks_by_album_all() { | ||
| 232 | let db = Database::open_in_memory().unwrap(); | ||
| 233 | seed_test_db(&db); | ||
| 234 | let tracks = db | ||
| 235 | .find_tracks_by_album("Metallica", "Master of Puppets") | ||
| 236 | .unwrap(); | ||
| 237 | assert_eq!(tracks.len(), 2); | ||
| 238 | assert_eq!(tracks[0].title, "Battery"); | ||
| 239 | assert_eq!(tracks[1].title, "Master of Puppets"); | ||
| 240 | assert_eq!(tracks[0].artist_name.as_deref(), Some("Metallica")); | ||
| 241 | assert_eq!(tracks[0].album_title.as_deref(), Some("Master of Puppets")); | ||
| 242 | } | ||
| 243 | |||
| 244 | #[test] | ||
| 245 | fn test_find_tracks_by_album_single_track() { | ||
| 246 | let db = Database::open_in_memory().unwrap(); | ||
| 247 | seed_test_db(&db); | ||
| 248 | let tracks = db | ||
| 249 | .find_tracks_by_album("Miles Davis", "Kind of Blue") | ||
| 250 | .unwrap(); | ||
| 251 | assert_eq!(tracks.len(), 1); | ||
| 252 | assert_eq!(tracks[0].title, "So What"); | ||
| 253 | } | ||
| 254 | |||
| 255 | #[test] | ||
| 256 | fn test_find_tracks_by_album_unknown_artist() { | ||
| 257 | let db = Database::open_in_memory().unwrap(); | ||
| 258 | seed_test_db(&db); | ||
| 259 | let tracks = db | ||
| 260 | .find_tracks_by_album("Nonexistent", "Master of Puppets") | ||
| 261 | .unwrap(); | ||
| 262 | assert!(tracks.is_empty()); | ||
| 263 | } | ||
| 264 | |||
| 265 | #[test] | ||
| 266 | fn test_find_tracks_by_album_unknown_album() { | ||
| 267 | let db = Database::open_in_memory().unwrap(); | ||
| 268 | seed_test_db(&db); | ||
| 269 | let tracks = db.find_tracks_by_album("Metallica", "Nonexistent").unwrap(); | ||
| 270 | assert!(tracks.is_empty()); | ||
| 271 | } | ||
| 272 | |||
| 273 | #[test] | ||
| 274 | fn test_find_tracks_by_album_case_sensitive_artist() { | ||
| 275 | let db = Database::open_in_memory().unwrap(); | ||
| 276 | seed_test_db(&db); | ||
| 277 | // SQLite = is case-sensitive for TEXT (unless NOCASE collation) | ||
| 278 | let tracks = db | ||
| 279 | .find_tracks_by_album("metallica", "Master of Puppets") | ||
| 280 | .unwrap(); | ||
| 281 | assert!( | ||
| 282 | tracks.is_empty(), | ||
| 283 | "artist name match should be case-sensitive" | ||
| 284 | ); | ||
| 285 | } | ||
| 286 | |||
| 287 | #[test] | ||
| 288 | fn test_find_tracks_by_album_ordered_by_track_number() { | ||
| 289 | let db = Database::open_in_memory().unwrap(); | ||
| 290 | seed_test_db(&db); | ||
| 291 | let tracks = db | ||
| 292 | .find_tracks_by_album("Metallica", "Master of Puppets") | ||
| 293 | .unwrap(); | ||
| 294 | assert_eq!(tracks[0].track_number, Some(1)); | ||
| 295 | assert_eq!(tracks[1].track_number, Some(2)); | ||
| 296 | } | ||
| 297 | |||
| 298 | // --- find_track_by_parts tests --- | ||
| 299 | |||
| 300 | #[test] | ||
| 301 | fn test_find_track_by_parts_exact() { | ||
| 302 | let db = Database::open_in_memory().unwrap(); | ||
| 303 | seed_test_db(&db); | ||
| 304 | let track = db | ||
| 305 | .find_track_by_parts("Metallica", "Master of Puppets", "Battery") | ||
| 306 | .unwrap(); | ||
| 307 | assert!(track.is_some()); | ||
| 308 | let t = track.unwrap(); | ||
| 309 | assert_eq!(t.title, "Battery"); | ||
| 310 | assert_eq!(t.artist_name.as_deref(), Some("Metallica")); | ||
| 311 | assert_eq!(t.album_title.as_deref(), Some("Master of Puppets")); | ||
| 312 | } | ||
| 313 | |||
| 314 | #[test] | ||
| 315 | fn test_find_track_by_parts_prefix() { | ||
| 316 | let db = Database::open_in_memory().unwrap(); | ||
| 317 | seed_test_db(&db); | ||
| 318 | let track = db | ||
| 319 | .find_track_by_parts("Metallica", "Master of Puppets", "B") | ||
| 320 | .unwrap(); | ||
| 321 | assert!(track.is_some()); | ||
| 322 | assert_eq!(track.unwrap().title, "Battery"); | ||
| 323 | } | ||
| 324 | |||
| 325 | #[test] | ||
| 326 | fn test_find_track_by_parts_no_match_track() { | ||
| 327 | let db = Database::open_in_memory().unwrap(); | ||
| 328 | seed_test_db(&db); | ||
| 329 | let track = db | ||
| 330 | .find_track_by_parts("Metallica", "Master of Puppets", "Z") | ||
| 331 | .unwrap(); | ||
| 332 | assert!(track.is_none()); | ||
| 333 | } | ||
| 334 | |||
| 335 | #[test] | ||
| 336 | fn test_find_track_by_parts_no_match_album() { | ||
| 337 | let db = Database::open_in_memory().unwrap(); | ||
| 338 | seed_test_db(&db); | ||
| 339 | let track = db | ||
| 340 | .find_track_by_parts("Metallica", "Nonexistent", "B") | ||
| 341 | .unwrap(); | ||
| 342 | assert!(track.is_none()); | ||
| 343 | } | ||
| 344 | |||
| 345 | #[test] | ||
| 346 | fn test_find_track_by_parts_no_match_artist() { | ||
| 347 | let db = Database::open_in_memory().unwrap(); | ||
| 348 | seed_test_db(&db); | ||
| 349 | let track = db | ||
| 350 | .find_track_by_parts("Nonexistent", "Master of Puppets", "B") | ||
| 351 | .unwrap(); | ||
| 352 | assert!(track.is_none()); | ||
| 353 | } | ||
| 354 | |||
| 355 | #[test] | ||
| 356 | fn test_find_track_by_parts_case_sensitive() { | ||
| 357 | let db = Database::open_in_memory().unwrap(); | ||
| 358 | seed_test_db(&db); | ||
| 359 | let track = db | ||
| 360 | .find_track_by_parts("metallica", "Master of Puppets", "Battery") | ||
| 361 | .unwrap(); | ||
| 362 | assert!(track.is_none(), "artist match should be case-sensitive"); | ||
| 363 | } | ||
| 364 | |||
| 365 | // --- resolve_path tests --- | ||
| 366 | |||
| 367 | #[test] | ||
| 368 | fn test_resolve_path_two_parts_album() { | ||
| 369 | let db = Database::open_in_memory().unwrap(); | ||
| 370 | seed_test_db(&db); | ||
| 371 | let result = db.resolve_path("Metallica/Master of Puppets").unwrap(); | ||
| 372 | assert!(result.is_some()); | ||
| 373 | let tracks = result.unwrap(); | ||
| 374 | assert_eq!(tracks.len(), 2); | ||
| 375 | assert_eq!(tracks[0].title, "Battery"); | ||
| 376 | } | ||
| 377 | |||
| 378 | #[test] | ||
| 379 | fn test_resolve_path_two_parts_trailing_slash() { | ||
| 380 | let db = Database::open_in_memory().unwrap(); | ||
| 381 | seed_test_db(&db); | ||
| 382 | let result = db.resolve_path("Metallica/Master of Puppets/").unwrap(); | ||
| 383 | assert!(result.is_some()); | ||
| 384 | let tracks = result.unwrap(); | ||
| 385 | assert_eq!(tracks.len(), 2); | ||
| 386 | } | ||
| 387 | |||
| 388 | #[test] | ||
| 389 | fn test_resolve_path_three_parts_track() { | ||
| 390 | let db = Database::open_in_memory().unwrap(); | ||
| 391 | seed_test_db(&db); | ||
| 392 | let result = db | ||
| 393 | .resolve_path("Metallica/Master of Puppets/Battery") | ||
| 394 | .unwrap(); | ||
| 395 | assert!(result.is_some()); | ||
| 396 | let tracks = result.unwrap(); | ||
| 397 | assert_eq!(tracks.len(), 1); | ||
| 398 | assert_eq!(tracks[0].title, "Battery"); | ||
| 399 | } | ||
| 400 | |||
| 401 | #[test] | ||
| 402 | fn test_resolve_path_three_parts_track_prefix() { | ||
| 403 | let db = Database::open_in_memory().unwrap(); | ||
| 404 | seed_test_db(&db); | ||
| 405 | let result = db.resolve_path("Metallica/Master of Puppets/B").unwrap(); | ||
| 406 | assert!(result.is_some()); | ||
| 407 | let tracks = result.unwrap(); | ||
| 408 | assert_eq!(tracks.len(), 1); | ||
| 409 | assert_eq!(tracks[0].title, "Battery"); | ||
| 410 | } | ||
| 411 | |||
| 412 | #[test] | ||
| 413 | fn test_resolve_path_single_part_returns_none() { | ||
| 414 | let db = Database::open_in_memory().unwrap(); | ||
| 415 | seed_test_db(&db); | ||
| 416 | let result = db.resolve_path("Metallica").unwrap(); | ||
| 417 | assert!( | ||
| 418 | result.is_none(), | ||
| 419 | "single part should return None for fallback" | ||
| 420 | ); | ||
| 421 | } | ||
| 422 | |||
| 423 | #[test] | ||
| 424 | fn test_resolve_path_no_match_album() { | ||
| 425 | let db = Database::open_in_memory().unwrap(); | ||
| 426 | seed_test_db(&db); | ||
| 427 | let result = db.resolve_path("Metallica/Nonexistent").unwrap(); | ||
| 428 | assert!(result.is_some()); | ||
| 429 | assert!(result.unwrap().is_empty()); | ||
| 430 | } | ||
| 431 | |||
| 432 | #[test] | ||
| 433 | fn test_resolve_path_no_match_track() { | ||
| 434 | let db = Database::open_in_memory().unwrap(); | ||
| 435 | seed_test_db(&db); | ||
| 436 | let result = db.resolve_path("Metallica/Master of Puppets/Z").unwrap(); | ||
| 437 | assert!(result.is_some()); | ||
| 438 | assert!(result.unwrap().is_empty()); | ||
| 439 | } | ||
| 440 | |||
| 441 | #[test] | ||
| 442 | fn test_resolve_path_empty_db() { | ||
| 443 | let db = Database::open_in_memory().unwrap(); | ||
| 444 | assert!(db.resolve_path("Artist/Album").unwrap().unwrap().is_empty()); | ||
| 445 | assert!( | ||
| 446 | db.resolve_path("Artist/Album/Track") | ||
| 447 | .unwrap() | ||
| 448 | .unwrap() | ||
| 449 | .is_empty() | ||
| 450 | ); | ||
| 451 | assert!(db.resolve_path("Artist").unwrap().is_none()); | ||
| 452 | } | ||
| 453 | |||
| 454 | // --- Track conversion helper tests --- | ||
| 455 | |||
| 456 | #[test] | ||
| 457 | fn test_find_tracks_by_album_returns_full_metadata() { | ||
| 458 | let db = Database::open_in_memory().unwrap(); | ||
| 459 | seed_test_db(&db); | ||
| 460 | let tracks = db | ||
| 461 | .find_tracks_by_album("Metallica", "Ride the Lightning") | ||
| 462 | .unwrap(); | ||
| 463 | assert_eq!(tracks.len(), 1); | ||
| 464 | let t = &tracks[0]; | ||
| 465 | assert_eq!(t.artist_name.as_deref(), Some("Metallica")); | ||
| 466 | assert_eq!(t.album_title.as_deref(), Some("Ride the Lightning")); | ||
| 467 | assert_eq!(t.title, "Fight Fire with Fire"); | ||
| 468 | assert!(t.path.to_string_lossy().contains("Ride the Lightning")); | ||
| 469 | } | ||
| 470 | |||
| 471 | #[test] | ||
| 472 | fn test_find_track_by_parts_returns_full_metadata() { | ||
| 473 | let db = Database::open_in_memory().unwrap(); | ||
| 474 | seed_test_db(&db); | ||
| 475 | let t = db | ||
| 476 | .find_track_by_parts("Aphex Twin", "Selected Ambient Works", "Xtal") | ||
| 477 | .unwrap() | ||
| 478 | .expect("track should be found"); | ||
| 479 | assert_eq!(t.artist_name.as_deref(), Some("Aphex Twin")); | ||
| 480 | assert_eq!(t.album_title.as_deref(), Some("Selected Ambient Works")); | ||
| 481 | assert_eq!(t.title, "Xtal"); | ||
| 482 | assert_eq!(t.track_number, Some(1)); | ||
| 483 | } | ||
