aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock133
-rw-r--r--Cargo.toml6
-rw-r--r--src/audio.rs1
-rw-r--r--src/database.rs4
-rw-r--r--src/lib.rs7
-rw-r--r--src/playback.rs13
-rw-r--r--src/scrobbler.rs8
-rw-r--r--tests/config.rs133
-rw-r--r--tests/database.rs85
-rw-r--r--tests/playback.rs175
-rw-r--r--tests/scrobbler.rs77
11 files changed, 615 insertions, 27 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1baedf3..82ef060 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -492,6 +492,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
492checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 492checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
493 493
494[[package]] 494[[package]]
495name = "fastrand"
496version = "2.4.1"
497source = "registry+https://github.com/rust-lang/crates.io-index"
498checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
499
500[[package]]
495name = "find-msvc-tools" 501name = "find-msvc-tools"
496version = "0.1.9" 502version = "0.1.9"
497source = "registry+https://github.com/rust-lang/crates.io-index" 503source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -920,16 +926,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
920checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" 926checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
921 927
922[[package]] 928[[package]]
923name = "iri-string"
924version = "0.7.12"
925source = "registry+https://github.com/rust-lang/crates.io-index"
926checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
927dependencies = [
928 "memchr",
929 "serde",
930]
931
932[[package]]
933name = "is_terminal_polyfill" 929name = "is_terminal_polyfill"
934version = "1.70.2" 930version = "1.70.2"
935source = "registry+https://github.com/rust-lang/crates.io-index" 931source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1076,6 +1072,12 @@ dependencies = [
1076] 1072]
1077 1073
1078[[package]] 1074[[package]]
1075name = "linux-raw-sys"
1076version = "0.12.1"
1077source = "registry+https://github.com/rust-lang/crates.io-index"
1078checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
1079
1080[[package]]
1079name = "litemap" 1081name = "litemap"
1080version = "0.8.2" 1082version = "0.8.2"
1081source = "registry+https://github.com/rust-lang/crates.io-index" 1083source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1470,7 +1472,7 @@ dependencies = [
1470 "once_cell", 1472 "once_cell",
1471 "socket2", 1473 "socket2",
1472 "tracing", 1474 "tracing",
1473 "windows-sys 0.52.0", 1475 "windows-sys 0.60.2",
1474] 1476]
1475 1477
1476[[package]] 1478[[package]]
@@ -1631,6 +1633,7 @@ dependencies = [
1631 "serde", 1633 "serde",
1632 "serde_json", 1634 "serde_json",
1633 "symphonia", 1635 "symphonia",
1636 "tempfile",
1634 "tokio", 1637 "tokio",
1635 "toml", 1638 "toml",
1636] 1639]
@@ -1676,6 +1679,19 @@ dependencies = [
1676] 1679]
1677 1680
1678[[package]] 1681[[package]]
1682name = "rustix"
1683version = "1.1.4"
1684source = "registry+https://github.com/rust-lang/crates.io-index"
1685checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
1686dependencies = [
1687 "bitflags 2.11.1",
1688 "errno",
1689 "libc",
1690 "linux-raw-sys",
1691 "windows-sys 0.61.2",
1692]
1693
1694[[package]]
1679name = "rustls" 1695name = "rustls"
1680version = "0.23.40" 1696version = "0.23.40"
1681source = "registry+https://github.com/rust-lang/crates.io-index" 1697source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2193,6 +2209,19 @@ dependencies = [
2193] 2209]
2194 2210
2195[[package]] 2211[[package]]
2212name = "tempfile"
2213version = "3.27.0"
2214source = "registry+https://github.com/rust-lang/crates.io-index"
2215checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
2216dependencies = [
2217 "fastrand",
2218 "getrandom 0.4.2",
2219 "once_cell",
2220 "rustix",
2221 "windows-sys 0.61.2",
2222]
2223
2224[[package]]
2196name = "thiserror" 2225name = "thiserror"
2197version = "1.0.69" 2226version = "1.0.69"
2198source = "registry+https://github.com/rust-lang/crates.io-index" 2227source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2376,20 +2405,20 @@ dependencies = [
2376 2405
2377[[package]] 2406[[package]]
2378name = "tower-http" 2407name = "tower-http"
2379version = "0.6.8" 2408version = "0.6.9"
2380source = "registry+https://github.com/rust-lang/crates.io-index" 2409source = "registry+https://github.com/rust-lang/crates.io-index"
2381checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" 2410checksum = "a28f0d049ccfaa566e14e9663d304d8577427b368cb4710a20528690287a738b"
2382dependencies = [ 2411dependencies = [
2383 "bitflags 2.11.1", 2412 "bitflags 2.11.1",
2384 "bytes", 2413 "bytes",
2385 "futures-util", 2414 "futures-util",
2386 "http", 2415 "http",
2387 "http-body", 2416 "http-body",
2388 "iri-string",
2389 "pin-project-lite", 2417 "pin-project-lite",
2390 "tower", 2418 "tower",
2391 "tower-layer", 2419 "tower-layer",
2392 "tower-service", 2420 "tower-service",
2421 "url",
2393] 2422]
2394 2423
2395[[package]] 2424[[package]]
@@ -2779,6 +2808,15 @@ dependencies = [
2779 2808
2780[[package]] 2809[[package]]
2781name = "windows-sys" 2810name = "windows-sys"
2811version = "0.60.2"
2812source = "registry+https://github.com/rust-lang/crates.io-index"
2813checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
2814dependencies = [
2815 "windows-targets 0.53.5",
2816]
2817
2818[[package]]
2819name = "windows-sys"
2782version = "0.61.2" 2820version = "0.61.2"
2783source = "registry+https://github.com/rust-lang/crates.io-index" 2821source = "registry+https://github.com/rust-lang/crates.io-index"
2784checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 2822checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
@@ -2810,7 +2848,7 @@ dependencies = [
2810 "windows_aarch64_gnullvm 0.52.6", 2848 "windows_aarch64_gnullvm 0.52.6",
2811 "windows_aarch64_msvc 0.52.6", 2849 "windows_aarch64_msvc 0.52.6",
2812 "windows_i686_gnu 0.52.6", 2850 "windows_i686_gnu 0.52.6",
2813 "windows_i686_gnullvm", 2851 "windows_i686_gnullvm 0.52.6",
2814 "windows_i686_msvc 0.52.6", 2852 "windows_i686_msvc 0.52.6",
2815 "windows_x86_64_gnu 0.52.6", 2853 "windows_x86_64_gnu 0.52.6",
2816 "windows_x86_64_gnullvm 0.52.6", 2854 "windows_x86_64_gnullvm 0.52.6",
@@ -2818,6 +2856,23 @@ dependencies = [
2818] 2856]
2819 2857
2820[[package]] 2858[[package]]
2859name = "windows-targets"
2860version = "0.53.5"
2861source = "registry+https://github.com/rust-lang/crates.io-index"
2862checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
2863dependencies = [
2864 "windows-link",
2865 "windows_aarch64_gnullvm 0.53.1",
2866 "windows_aarch64_msvc 0.53.1",
2867 "windows_i686_gnu 0.53.1",
2868 "windows_i686_gnullvm 0.53.1",
2869 "windows_i686_msvc 0.53.1",
2870 "windows_x86_64_gnu 0.53.1",
2871 "windows_x86_64_gnullvm 0.53.1",
2872 "windows_x86_64_msvc 0.53.1",
2873]
2874
2875[[package]]
2821name = "windows-threading" 2876name = "windows-threading"
2822version = "0.2.1" 2877version = "0.2.1"
2823source = "registry+https://github.com/rust-lang/crates.io-index" 2878source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2839,6 +2894,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2839checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2894checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
2840 2895
2841[[package]] 2896[[package]]
2897name = "windows_aarch64_gnullvm"
2898version = "0.53.1"
2899source = "registry+https://github.com/rust-lang/crates.io-index"
2900checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
2901
2902[[package]]
2842name = "windows_aarch64_msvc" 2903name = "windows_aarch64_msvc"
2843version = "0.42.2" 2904version = "0.42.2"
2844source = "registry+https://github.com/rust-lang/crates.io-index" 2905source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2851,6 +2912,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2851checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2912checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
2852 2913
2853[[package]] 2914[[package]]
2915name = "windows_aarch64_msvc"
2916version = "0.53.1"
2917source = "registry+https://github.com/rust-lang/crates.io-index"
2918checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
2919
2920[[package]]
2854name = "windows_i686_gnu" 2921name = "windows_i686_gnu"
2855version = "0.42.2" 2922version = "0.42.2"
2856source = "registry+https://github.com/rust-lang/crates.io-index" 2923source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2863,12 +2930,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2863checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2930checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
2864 2931
2865[[package]] 2932[[package]]
2933name = "windows_i686_gnu"
2934version = "0.53.1"
2935source = "registry+https://github.com/rust-lang/crates.io-index"
2936checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
2937
2938[[package]]
2866name = "windows_i686_gnullvm" 2939name = "windows_i686_gnullvm"
2867version = "0.52.6" 2940version = "0.52.6"
2868source = "registry+https://github.com/rust-lang/crates.io-index" 2941source = "registry+https://github.com/rust-lang/crates.io-index"
2869checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2942checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
2870 2943
2871[[package]] 2944[[package]]
2945name = "windows_i686_gnullvm"
2946version = "0.53.1"
2947source = "registry+https://github.com/rust-lang/crates.io-index"
2948checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
2949
2950[[package]]
2872name = "windows_i686_msvc" 2951name = "windows_i686_msvc"
2873version = "0.42.2" 2952version = "0.42.2"
2874source = "registry+https://github.com/rust-lang/crates.io-index" 2953source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2881,6 +2960,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2881checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2960checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
2882 2961
2883[[package]] 2962[[package]]
2963name = "windows_i686_msvc"
2964version = "0.53.1"
2965source = "registry+https://github.com/rust-lang/crates.io-index"
2966checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
2967
2968[[package]]
2884name = "windows_x86_64_gnu" 2969name = "windows_x86_64_gnu"
2885version = "0.42.2" 2970version = "0.42.2"
2886source = "registry+https://github.com/rust-lang/crates.io-index" 2971source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2893,6 +2978,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2893checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2978checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
2894 2979
2895[[package]] 2980[[package]]
2981name = "windows_x86_64_gnu"
2982version = "0.53.1"
2983source = "registry+https://github.com/rust-lang/crates.io-index"
2984checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
2985
2986[[package]]
2896name = "windows_x86_64_gnullvm" 2987name = "windows_x86_64_gnullvm"
2897version = "0.42.2" 2988version = "0.42.2"
2898source = "registry+https://github.com/rust-lang/crates.io-index" 2989source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2905,6 +2996,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2905checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2996checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
2906 2997
2907[[package]] 2998[[package]]
2999name = "windows_x86_64_gnullvm"
3000version = "0.53.1"
3001source = "registry+https://github.com/rust-lang/crates.io-index"
3002checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
3003
3004[[package]]
2908name = "windows_x86_64_msvc" 3005name = "windows_x86_64_msvc"
2909version = "0.42.2" 3006version = "0.42.2"
2910source = "registry+https://github.com/rust-lang/crates.io-index" 3007source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2917,6 +3014,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2917checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3014checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2918 3015
2919[[package]] 3016[[package]]
3017name = "windows_x86_64_msvc"
3018version = "0.53.1"
3019source = "registry+https://github.com/rust-lang/crates.io-index"
3020checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
3021
3022[[package]]
2920name = "winnow" 3023name = "winnow"
2921version = "1.0.2" 3024version = "1.0.2"
2922source = "registry+https://github.com/rust-lang/crates.io-index" 3025source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 0ceee6f..21614c5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,9 @@ name = "rsp"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5 5
6[lib]
7path = "src/lib.rs"
8
6[dependencies] 9[dependencies]
7clap = { version = "4.6.1", features = ["derive", "string"] } 10clap = { version = "4.6.1", features = ["derive", "string"] }
8rusqlite = { version = "0.39", features = ["bundled"] } 11rusqlite = { version = "0.39", features = ["bundled"] }
@@ -19,3 +22,6 @@ dirs = "6.0"
19libc = "0.2.186" 22libc = "0.2.186"
20ctrlc = "3.5.2" 23ctrlc = "3.5.2"
21rand = "0.10.1" 24rand = "0.10.1"
25
26[dev-dependencies]
27tempfile = "3.17"
diff --git a/src/audio.rs b/src/audio.rs
index 93eb8e6..d716a23 100644
--- a/src/audio.rs
+++ b/src/audio.rs
@@ -21,6 +21,7 @@ pub struct AudioEngine {
21 volume: Arc<Mutex<f32>>, 21 volume: Arc<Mutex<f32>>,
22} 22}
23 23
24#[allow(clippy::new_without_default)]
24impl AudioEngine { 25impl AudioEngine {
25 pub fn new() -> Self { 26 pub fn new() -> Self {
26 let (tx, rx) = mpsc::channel(); 27 let (tx, rx) = mpsc::channel();
diff --git a/src/database.rs b/src/database.rs
index 9d1d5f2..b7b8e88 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -220,7 +220,7 @@ impl Database {
220 } 220 }
221} 221}
222 222
223fn is_audio_file(path: &Path) -> bool { 223pub fn is_audio_file(path: &Path) -> bool {
224 path.extension() 224 path.extension()
225 .and_then(|ext| ext.to_str()) 225 .and_then(|ext| ext.to_str())
226 .map(|ext| { 226 .map(|ext| {
@@ -232,7 +232,7 @@ fn is_audio_file(path: &Path) -> bool {
232 .unwrap_or(false) 232 .unwrap_or(false)
233} 233}
234 234
235fn extract_metadata(path: &Path) -> (String, String, String, Option<i32>, Option<u64>) { 235pub fn extract_metadata(path: &Path) -> (String, String, String, Option<i32>, Option<u64>) {
236 let file_stem = path 236 let file_stem = path
237 .file_stem() 237 .file_stem()
238 .and_then(|s| s.to_str()) 238 .and_then(|s| s.to_str())
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..9317bcd
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,7 @@
1pub mod audio;
2pub mod cli;
3pub mod config;
4pub mod daemon;
5pub mod database;
6pub mod playback;
7pub mod scrobbler;
diff --git a/src/playback.rs b/src/playback.rs
index 76c0f44..d9dd1f9 100644
--- a/src/playback.rs
+++ b/src/playback.rs
@@ -18,7 +18,7 @@ pub struct Track {
18 pub duration: Option<u64>, 18 pub duration: Option<u64>,
19} 19}
20 20
21#[derive(Debug, Clone)] 21#[derive(Debug, Clone, PartialEq)]
22#[allow(dead_code)] 22#[allow(dead_code)]
23pub enum ShuffleMode { 23pub enum ShuffleMode {
24 None, 24 None,
@@ -28,14 +28,15 @@ pub enum ShuffleMode {
28 28
29#[allow(dead_code)] 29#[allow(dead_code)]
30pub struct Player { 30pub struct Player {
31 state: PlaybackState, 31 pub state: PlaybackState,
32 current_track: Option<Track>, 32 pub current_track: Option<Track>,
33 queue: Vec<Track>, 33 pub queue: Vec<Track>,
34 volume: u8, 34 pub volume: u8,
35 shuffle: ShuffleMode, 35 pub shuffle: ShuffleMode,
36} 36}
37 37
38#[allow(dead_code)] 38#[allow(dead_code)]
39#[allow(clippy::new_without_default)]
39impl Player { 40impl Player {
40 pub fn new() -> Self { 41 pub fn new() -> Self {
41 Player { 42 Player {
diff --git a/src/scrobbler.rs b/src/scrobbler.rs
index 09a7f55..ddcbed9 100644
--- a/src/scrobbler.rs
+++ b/src/scrobbler.rs
@@ -2,10 +2,10 @@ use reqwest::Client;
2 2
3#[allow(dead_code)] 3#[allow(dead_code)]
4pub struct Scrobbler { 4pub struct Scrobbler {
5 lastfm_api_key: Option<String>, 5 pub lastfm_api_key: Option<String>,
6 lastfm_api_secret: Option<String>, 6 pub lastfm_api_secret: Option<String>,
7 lastfm_session_key: Option<String>, 7 pub lastfm_session_key: Option<String>,
8 listenbrainz_token: Option<String>, 8 pub listenbrainz_token: Option<String>,
9 client: Client, 9 client: Client,
10} 10}
11 11
diff --git a/tests/config.rs b/tests/config.rs
new file mode 100644
index 0000000..70c5034
--- /dev/null
+++ b/tests/config.rs
@@ -0,0 +1,133 @@
1use rsp::config::Config;
2use std::path::PathBuf;
3
4#[test]
5fn test_config_get_scan_interval() {
6 let config = Config {
7 config_path: PathBuf::from("/test/config.toml"),
8 music_paths: vec![],
9 scan_interval: Some(3600),
10 socket_path: None,
11 lastfm_api_key: None,
12 lastfm_api_secret: None,
13 lastfm_session_key: None,
14 listenbrainz_token: None,
15 volume: None,
16 shuffle: None,
17 };
18 assert_eq!(config.get("scan_interval").unwrap(), "3600");
19}
20
21#[test]
22fn test_config_get_not_set() {
23 let config = Config {
24 config_path: PathBuf::from("/test/config.toml"),
25 ..Default::default()
26 };
27 assert_eq!(config.get("scan_interval").unwrap(), "not set");
28}
29
30#[test]
31fn test_config_get_volume() {
32 let config = Config {
33 config_path: PathBuf::from("/test/config.toml"),
34 music_paths: vec![],
35 scan_interval: None,
36 socket_path: None,
37 lastfm_api_key: None,
38 lastfm_api_secret: None,
39 lastfm_session_key: None,
40 listenbrainz_token: None,
41 volume: Some(75),
42 shuffle: None,
43 };
44 assert_eq!(config.get("volume").unwrap(), "75");
45}
46
47#[test]
48fn test_config_get_unknown_key() {
49 let config = Config::default();
50 let result = config.get("unknown_key");
51 assert!(result.is_err());
52}
53
54#[test]
55fn test_config_set_scan_interval() {
56 let mut config = Config::default();
57 config.set("scan_interval", "7200").unwrap();
58 assert_eq!(config.scan_interval, Some(7200));
59}
60
61#[test]
62fn test_config_set_invalid_scan_interval() {
63 let mut config = Config::default();
64 let result = config.set("scan_interval", "invalid");
65 assert!(result.is_err());
66}
67
68#[test]
69fn test_config_set_volume() {
70 let mut config = Config::default();
71 config.set("volume", "50").unwrap();
72 assert_eq!(config.volume, Some(50));
73}
74
75#[test]
76fn test_config_set_invalid_volume() {
77 let mut config = Config::default();
78 let result = config.set("volume", "256");
79 assert!(result.is_err());
80}
81
82#[test]
83fn test_config_set_shuffle_valid() {
84 let mut config = Config::default();
85 config.set("shuffle", "all").unwrap();
86 assert_eq!(config.shuffle, Some("all".to_string()));
87}
88
89#[test]
90fn test_config_set_shuffle_off() {
91 let mut config = Config::default();
92 config.set("shuffle", "off").unwrap();
93 assert_eq!(config.shuffle, None);
94}
95
96#[test]
97fn test_config_set_shuffle_invalid() {
98 let mut config = Config::default();
99 let result = config.set("shuffle", "invalid");
100 assert!(result.is_err());
101}
102
103#[test]
104fn test_config_set_unknown_key() {
105 let mut config = Config::default();
106 let result = config.set("unknown_key", "value");
107 assert!(result.is_err());
108}
109
110#[test]
111fn test_config_unset_volume() {
112 let mut config = Config {
113 config_path: PathBuf::from("/test/config.toml"),
114 music_paths: vec![],
115 scan_interval: None,
116 socket_path: None,
117 lastfm_api_key: None,
118 lastfm_api_secret: None,
119 lastfm_session_key: None,
120 listenbrainz_token: None,
121 volume: Some(50),
122 shuffle: None,
123 };
124 config.unset("volume").unwrap();
125 assert_eq!(config.volume, None);
126}
127
128#[test]
129fn test_config_unset_unknown_key() {
130 let mut config = Config::default();
131 let result = config.unset("unknown_key");
132 assert!(result.is_err());
133}
diff --git a/tests/database.rs b/tests/database.rs
new file mode 100644
index 0000000..67fe0ed
--- /dev/null
+++ b/tests/database.rs
@@ -0,0 +1,85 @@
1use rsp::database::{extract_metadata, is_audio_file};
2use std::path::PathBuf;
3
4#[test]
5fn test_is_audio_file_mp3() {
6 let path = PathBuf::from("/music/song.mp3");
7 assert!(is_audio_file(&path));
8}
9
10#[test]
11fn test_is_audio_file_flac() {
12 let path = PathBuf::from("/music/song.flac");
13 assert!(is_audio_file(&path));
14}
15
16#[test]
17fn test_is_audio_file_ogg() {
18 let path = PathBuf::from("/music/song.ogg");
19 assert!(is_audio_file(&path));
20}
21
22#[test]
23fn test_is_audio_file_m4a() {
24 let path = PathBuf::from("/music/song.m4a");
25 assert!(is_audio_file(&path));
26}
27
28#[test]
29fn test_is_audio_file_wav() {
30 let path = PathBuf::from("/music/song.wav");
31 assert!(is_audio_file(&path));
32}
33
34#[test]
35fn test_is_audio_file_opus() {
36 let path = PathBuf::from("/music/song.opus");
37 assert!(is_audio_file(&path));
38}
39
40#[test]
41fn test_is_audio_file_uppercase() {
42 let path = PathBuf::from("/music/song.MP3");
43 assert!(is_audio_file(&path));
44}
45
46#[test]
47fn test_is_audio_file_non_audio() {
48 let path = PathBuf::from("/music/song.txt");
49 assert!(!is_audio_file(&path));
50}
51
52#[test]
53fn test_is_audio_file_no_extension() {
54 let path = PathBuf::from("/music/songfile");
55 assert!(!is_audio_file(&path));
56}
57
58#[test]
59fn test_extract_metadata_standard_path() {
60 let path = PathBuf::from("/music/Artist/Album/Track.mp3");
61 let (artist, album, title, track_num, duration) = extract_metadata(&path);
62 assert_eq!(artist, "Artist");
63 assert_eq!(album, "Album");
64 assert_eq!(title, "Track");
65 assert_eq!(track_num, None);
66 assert_eq!(duration, None);
67}
68
69#[test]
70fn test_extract_metadata_deep_path() {
71 let path = PathBuf::from("/music/Artist/Album/Disc1/Track.mp3");
72 let (artist, album, title, _, _) = extract_metadata(&path);
73 assert_eq!(artist, "Album");
74 assert_eq!(album, "Disc1");
75 assert_eq!(title, "Track");
76}
77
78#[test]
79fn test_extract_metadata_no_parent() {
80 let path = PathBuf::from("/song.mp3");
81 let (artist, album, title, _, _) = extract_metadata(&path);
82 assert_eq!(artist, "Unknown");
83 assert_eq!(album, "Unknown");
84 assert_eq!(title, "song");
85}
diff --git a/tests/playback.rs b/tests/playback.rs
new file mode 100644
index 0000000..80ecf58
--- /dev/null
+++ b/tests/playback.rs
@@ -0,0 +1,175 @@
1use rsp::playback::{PlaybackState, Player, ShuffleMode, Track};
2use std::path::PathBuf;
3
4fn dummy_track(title: &str) -> Track {
5 Track {
6 path: PathBuf::from(format!("/music/{}", title)),
7 title: title.to_string(),
8 artist: "Test Artist".to_string(),
9 album: "Test Album".to_string(),
10 duration: Some(180000),
11 }
12}
13
14#[test]
15fn test_player_default_state() {
16 let player = Player::new();
17 assert_eq!(player.state(), &PlaybackState::Stopped);
18 assert_eq!(player.volume(), 70);
19}
20
21#[test]
22fn test_player_play_with_track_in_queue() {
23 let mut player = Player::new();
24 player.queue_track(dummy_track("Test Track"), "last");
25 player.play();
26 assert_eq!(player.state(), &PlaybackState::Playing);
27 assert!(player.current_track.is_some());
28 assert!(player.queue.is_empty());
29}
30
31#[test]
32fn test_player_play_with_no_track() {
33 let mut player = Player::new();
34 player.play();
35 assert_eq!(player.state(), &PlaybackState::Stopped);
36}
37
38#[test]
39fn test_player_play_track() {
40 let mut player = Player::new();
41 player.play_track(dummy_track("Test Track"));
42 assert_eq!(player.state(), &PlaybackState::Playing);
43 assert!(player.current_track.is_some());
44}
45
46#[test]
47fn test_player_pause() {
48 let mut player = Player::new();
49 player.play_track(dummy_track("Test Track"));
50 player.pause();
51 assert_eq!(player.state(), &PlaybackState::Paused);
52}
53
54#[test]
55fn test_player_pause_when_stopped() {
56 let mut player = Player::new();
57 player.pause();
58 assert_eq!(player.state(), &PlaybackState::Stopped);
59}
60
61#[test]
62fn test_player_resume() {
63 let mut player = Player::new();
64 player.play_track(dummy_track("Test Track"));
65 player.pause();
66 player.resume();
67 assert_eq!(player.state(), &PlaybackState::Playing);
68}
69
70#[test]
71fn test_player_resume_when_stopped() {
72 let mut player = Player::new();
73 player.resume();
74 assert_eq!(player.state(), &PlaybackState::Stopped);
75}
76
77#[test]
78fn test_player_stop() {
79 let mut player = Player::new();
80 player.play_track(dummy_track("Test Track"));
81 player.stop();
82 assert_eq!(player.state(), &PlaybackState::Stopped);
83 assert!(player.current_track.is_none());
84}
85
86#[test]
87fn test_player_next_with_queue() {
88 let mut player = Player::new();
89 player.queue_track(dummy_track("Track 1"), "last");
90 player.queue_track(dummy_track("Track 2"), "last");
91 player.next();
92 assert_eq!(player.current_track.as_ref().unwrap().title, "Track 1");
93}
94
95#[test]
96fn test_player_next_empty_queue() {
97 let mut player = Player::new();
98 player.next();
99 assert_eq!(player.state(), &PlaybackState::Stopped);
100 assert!(player.current_track.is_none());
101}
102
103#[test]
104fn test_player_previous() {
105 let mut player = Player::new();
106 player.play_track(dummy_track("Test Track"));
107 player.previous();
108 assert_eq!(player.state(), &PlaybackState::Playing);
109}
110
111#[test]
112fn test_player_set_volume() {
113 let mut player = Player::new();
114 player.set_volume(50);
115 assert_eq!(player.volume(), 50);
116}
117
118#[test]
119fn test_player_set_volume_caps_at_100() {
120 let mut player = Player::new();
121 player.set_volume(150);
122 assert_eq!(player.volume(), 100);
123}
124
125#[test]
126fn test_player_set_shuffle() {
127 let mut player = Player::new();
128 player.set_shuffle(ShuffleMode::All);
129 assert_eq!(player.shuffle, ShuffleMode::All);
130}
131
132#[test]
133fn test_player_queue_track_now() {
134 let mut player = Player::new();
135 player.queue_track(dummy_track("Track 1"), "now");
136 assert_eq!(player.queue.len(), 1);
137 assert_eq!(player.queue[0].title, "Track 1");
138}
139
140#[test]
141fn test_player_queue_track_next() {
142 let mut player = Player::new();
143 player.queue_track(dummy_track("Track 1"), "last");
144 player.queue_track(dummy_track("Track 2"), "next");
145 assert_eq!(player.queue.len(), 2);
146 assert_eq!(player.queue[0].title, "Track 1");
147 assert_eq!(player.queue[1].title, "Track 2");
148}
149
150#[test]
151fn test_player_queue_track_last() {
152 let mut player = Player::new();
153 player.queue_track(dummy_track("Track 1"), "last");
154 player.queue_track(dummy_track("Track 2"), "last");
155 assert_eq!(player.queue.len(), 2);
156 assert_eq!(player.queue[0].title, "Track 1");
157 assert_eq!(player.queue[1].title, "Track 2");
158}
159
160#[test]
161fn test_player_dequeue_next() {
162 let mut player = Player::new();
163 player.queue_track(dummy_track("Track 1"), "last");
164 let track = player.dequeue_next();
165 assert!(track.is_some());
166 assert_eq!(track.unwrap().title, "Track 1");
167 assert!(player.queue.is_empty());
168}
169
170#[test]
171fn test_player_dequeue_next_empty() {
172 let mut player = Player::new();
173 let track = player.dequeue_next();
174 assert!(track.is_none());
175}
diff --git a/tests/scrobbler.rs b/tests/scrobbler.rs
new file mode 100644
index 0000000..f326250
--- /dev/null
+++ b/tests/scrobbler.rs
@@ -0,0 +1,77 @@
1use rsp::scrobbler::Scrobbler;
2
3#[test]
4fn test_scrobbler_new_with_all_params() {
5 let scrobbler = Scrobbler::new(
6 Some("api_key".to_string()),
7 Some("secret".to_string()),
8 Some("session".to_string()),
9 Some("token".to_string()),
10 );
11 assert!(scrobbler.lastfm_api_key.is_some());
12 assert!(scrobbler.lastfm_api_secret.is_some());
13 assert!(scrobbler.lastfm_session_key.is_some());
14 assert!(scrobbler.listenbrainz_token.is_some());
15}
16
17#[test]
18fn test_scrobbler_new_with_none() {
19 let scrobbler = Scrobbler::new(None, None, None, None);
20 assert!(scrobbler.lastfm_api_key.is_none());
21 assert!(scrobbler.lastfm_api_secret.is_none());
22 assert!(scrobbler.lastfm_session_key.is_none());
23 assert!(scrobbler.listenbrainz_token.is_none());
24}
25
26#[test]
27fn test_scrobbler_now_playing_no_api_key() {
28 let scrobbler = Scrobbler::new(None, None, None, None);
29 scrobbler.now_playing("Artist", "Track", Some("Album"));
30}
31
32#[test]
33fn test_scrobbler_now_playing_with_api_key() {
34 let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None);
35 scrobbler.now_playing("Artist", "Track", Some("Album"));
36}
37
38#[test]
39fn test_scrobbler_scrobble_no_keys() {
40 let scrobbler = Scrobbler::new(None, None, None, None);
41 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890);
42}
43
44#[test]
45fn test_scrobbler_scrobble_with_lastfm() {
46 let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None);
47 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890);
48}
49
50#[test]
51fn test_scrobbler_scrobble_with_listenbrainz() {
52 let scrobbler = Scrobbler::new(None, None, None, Some("token".to_string()));
53 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890);
54}
55
56#[test]
57fn test_scrobbler_scrobble_with_both() {
58 let scrobbler = Scrobbler::new(
59 Some("api_key".to_string()),
60 None,
61 None,
62 Some("token".to_string()),
63 );
64 scrobbler.scrobble("Artist", "Track", Some("Album"), 1234567890);
65}
66
67#[test]
68fn test_scrobbler_now_playing_no_album() {
69 let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None);
70 scrobbler.now_playing("Artist", "Track", None);
71}
72
73#[test]
74fn test_scrobbler_scrobble_no_album() {
75 let scrobbler = Scrobbler::new(Some("api_key".to_string()), None, None, None);
76 scrobbler.scrobble("Artist", "Track", None, 1234567890);
77}