diff --git a/.gitea/workflows/tag_release.yaml b/.gitea/workflows/tag_release.yaml index 921d7e3..287ac4f 100644 --- a/.gitea/workflows/tag_release.yaml +++ b/.gitea/workflows/tag_release.yaml @@ -4,7 +4,7 @@ on: push: branches: - main - - dev + - devel tags: - 'v*' # Trigger on tags matching v* @@ -20,7 +20,7 @@ jobs: - name: Install Rust uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: 1.85.0 components: cargo - name: Extract Version from Cargo.toml diff --git a/.gitea/workflows/workflow.yaml b/.gitea/workflows/workflow.yaml index 4c5afd4..c3640b8 100644 --- a/.gitea/workflows/workflow.yaml +++ b/.gitea/workflows/workflow.yaml @@ -4,11 +4,11 @@ on: push: branches: - main - - dev + - devel pull_request: branches: - main - - dev + - devel jobs: check: @@ -17,6 +17,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.85.0 - run: cargo check test: @@ -25,6 +27,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.85.0 - run: cargo test fmt: @@ -33,6 +37,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.85.0 - run: rustup component add rustfmt - run: cargo fmt --all -- --check @@ -42,6 +48,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.85.0 - run: rustup component add clippy - run: cargo clippy -- -D warnings @@ -51,6 +59,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.85.0 - run: cargo build diff --git a/.gitignore b/.gitignore index ea8c4bf..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 90b37f5..2e6113e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ license = "MIT" serde = { version = "1.0.218", features = ["derive"] } serde_json = { version = "1.0.139" } rand = { version = "0.9" } +tempfile = { version = "3.19.1" } diff --git a/src/access_level.rs b/src/access_level.rs index 2dc4f15..c41d81f 100644 --- a/src/access_level.rs +++ b/src/access_level.rs @@ -20,23 +20,23 @@ impl Default for AccessLevel { } pub fn default_level() -> AccessLevel { - return AccessLevel { + AccessLevel { id: -1, level: String::from("Public"), song_id: -1, - }; + } } pub fn private_level() -> AccessLevel { - return AccessLevel { + AccessLevel { id: -1, level: String::from("Private"), song_id: -1, - }; + } } impl AccessLevel { pub fn _to_json(&self) -> Result { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } } diff --git a/src/album.rs b/src/album.rs index f0db09b..356d23b 100644 --- a/src/album.rs +++ b/src/album.rs @@ -1,15 +1,29 @@ pub mod collection { use serde::{Deserialize, Serialize}; + use std::default::Default; + + use std::fs::File; + use std::io::BufReader; fn is_set(num: &i32) -> bool { *num >= 0 } - #[derive(Clone, Debug, Deserialize, Serialize)] + pub fn parse_album(filepath: &String) -> Result { + let file = File::open(filepath).expect("Failed to open file"); + let reader = BufReader::new(file); + + serde_json::from_reader(reader) + } + + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Album { #[serde(skip_serializing_if = "String::is_empty")] #[serde(alias = "album")] pub title: String, + #[serde(skip_serializing_if = "String::is_empty")] + #[serde(alias = "album_artist")] + pub artist: String, pub genre: String, pub year: i32, pub track_count: i32, @@ -19,7 +33,7 @@ pub mod collection { pub tracks: Vec, } - #[derive(Clone, Debug, Deserialize, Serialize)] + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Track { pub title: String, pub artist: String, diff --git a/src/coverart.rs b/src/coverart.rs index 4703823..f8aaec5 100644 --- a/src/coverart.rs +++ b/src/coverart.rs @@ -16,12 +16,8 @@ impl CoverArt { let mut file = std::fs::File::open(path)?; let mut buffer = Vec::new(); match file.read_to_end(&mut buffer) { - Ok(_) => { - return Ok(buffer); - } - Err(err) => { - return Err(err); - } + Ok(_) => Ok(buffer), + Err(err) => Err(err), } } } diff --git a/src/lib.rs b/src/lib.rs index da15f76..43c2c79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,18 +7,3 @@ pub mod song; pub mod token; pub mod types; pub mod user; - -pub fn add(left: u64, right: u64) -> u64 { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/src/login_result.rs b/src/login_result.rs index 9095fdb..782ca77 100644 --- a/src/login_result.rs +++ b/src/login_result.rs @@ -26,6 +26,6 @@ impl Default for LoginResult { impl LoginResult { pub fn _to_json(&self) -> Result { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } } diff --git a/src/song.rs b/src/song.rs index b024a62..4d319dc 100644 --- a/src/song.rs +++ b/src/song.rs @@ -1,4 +1,3 @@ -use std::default::Default; use std::io::Read; use crate::constants; @@ -7,7 +6,7 @@ use crate::types; use rand::Rng; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Song { #[serde(skip_serializing_if = "is_zero")] #[serde(alias = "id")] @@ -64,41 +63,12 @@ fn is_dur_not_set(num: &i32) -> bool { *num == 0 } -impl Default for Song { - fn default() -> Self { - Song { - id: 0, - title: String::new(), - artist: String::new(), - album: String::new(), - album_artist: String::new(), - genre: String::new(), - year: 0, - duration: 0, - track: 0, - disc: 0, - disc_count: 0, - track_count: 0, - audio_type: String::new(), - date_created: String::new(), - filename: String::new(), - user_id: 0, - data: Vec::new(), - directory: String::new(), - // album_id: 0, - // artist_id: 0, - // genre_id: 0, - // coverart_id: 0, - } - } -} - impl Song { pub fn to_metadata_json(&self, pretty: bool) -> Result { if pretty { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } else { - return serde_json::to_string(&self); + serde_json::to_string(&self) } } @@ -111,7 +81,7 @@ impl Song { } let directory = &self.directory; - let mut buffer: String = String::from(directory.clone()); + let mut buffer: String = directory.clone(); let last_index = directory.len() - 1; if let Some(character) = directory.chars().nth(last_index) { @@ -121,12 +91,12 @@ impl Song { buffer += &self.filename.clone(); - return Ok(buffer); + Ok(buffer) } else { - return Err(std::io::Error::new( + Err(std::io::Error::new( std::io::ErrorKind::Other, "Could not access last character of directory", - )); + )) } } @@ -139,50 +109,45 @@ impl Song { let mut buffer: Vec = Vec::new(); file.read_to_end(&mut buffer)?; - if buffer.len() == 0 { - return Err(std::io::Error::new( + if buffer.is_empty() { + Err(std::io::Error::new( std::io::ErrorKind::Other, "File is empty", - )); + )) } else { - return Ok(buffer); + Ok(buffer) } } - Err(er) => { - return Err(er); - } + Err(er) => Err(er), } } - pub fn generate_filename(&self, typ: types::types::Types, randomize: bool) -> String { + pub fn generate_filename(&self, typ: types::MusicTypes, randomize: bool) -> String { let mut filename: String = String::new(); let filename_len = 10; let file_extension = match typ { - types::types::Types::DefaultMusicExtension => { + types::MusicTypes::DefaultMusicExtension => { String::from(constants::DEFAULTMUSICEXTENSION) } - types::types::Types::WavExtension => String::from(constants::WAVEXTENSION), - types::types::Types::FlacExtension => String::from(constants::FLACEXTENSION), - types::types::Types::MPThreeExtension => String::from(constants::MPTHREEEXTENSION), + types::MusicTypes::WavExtension => String::from(constants::WAVEXTENSION), + types::MusicTypes::FlacExtension => String::from(constants::FLACEXTENSION), + types::MusicTypes::MPThreeExtension => String::from(constants::MPTHREEEXTENSION), }; if randomize { let some_chars: String = String::from("abcdefghij0123456789"); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for _i in 0..filename_len { - let random_number: i32 = rng.gen_range(0..=19); + let random_number: i32 = rng.random_range(0..=19); let index = random_number as usize; let rando_char = some_chars.chars().nth(index); - match rando_char { - Some(c) => { - filename.push(c); - } - None => {} - }; + if let Some(c) = rando_char { + filename.push(c); + } } } else { filename += "track-output"; @@ -190,10 +155,11 @@ impl Song { filename += &file_extension; - return filename; + filename } } +/* mod embedded { use std::io::Read; @@ -202,9 +168,9 @@ mod embedded { impl Song { pub fn to_metadata_json(&self, pretty: bool) -> Result { if pretty { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } else { - return serde_json::to_string(&self); + serde_json::to_string(&self) } } @@ -217,7 +183,7 @@ mod embedded { } let directory = &self.directory; - let mut buffer: String = String::from(directory.clone()); + let mut buffer: String = directory.clone(); let last_index = directory.len() - 1; if let Some(character) = directory.chars().nth(last_index) { @@ -227,12 +193,12 @@ mod embedded { buffer += &self.filename.clone(); - return Ok(buffer); + Ok(buffer) } else { - return Err(std::io::Error::new( + Err(std::io::Error::new( std::io::ErrorKind::Other, "Could not access last character of directory", - )); + )) } } @@ -245,18 +211,16 @@ mod embedded { let mut buffer: Vec = Vec::new(); file.read_to_end(&mut buffer)?; - if buffer.len() == 0 { - return Err(std::io::Error::new( + if buffer.is_empty() { + Err(std::io::Error::new( std::io::ErrorKind::Other, "File is empty", - )); + )) } else { - return Ok(buffer); + Ok(buffer) } } - Err(er) => { - return Err(er); - } + Err(er) => Err(er), } } } @@ -348,3 +312,4 @@ mod embedded { } } } +*/ diff --git a/src/token.rs b/src/token.rs index 3934840..dc5a261 100644 --- a/src/token.rs +++ b/src/token.rs @@ -43,18 +43,18 @@ impl AccessToken { pub fn bearer_token(&self) -> String { let mut token: String = String::from("Bearer "); token += &self.token.clone(); - return token; + token } } impl Token { pub fn _to_json(&self) -> Result { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } // TODO: Implement pub fn token_expired(&self) -> bool { - return false; + false } // TODO: Implement @@ -65,6 +65,6 @@ impl Token { return true; } - return false; + false } } diff --git a/src/types.rs b/src/types.rs index 1cc0995..e518320 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,6 @@ -pub mod types { - pub enum Types { - DefaultMusicExtension, - WavExtension, - FlacExtension, - MPThreeExtension, - } +pub enum MusicTypes { + DefaultMusicExtension, + WavExtension, + FlacExtension, + MPThreeExtension, } diff --git a/src/user.rs b/src/user.rs index 04fe442..07f2a59 100644 --- a/src/user.rs +++ b/src/user.rs @@ -52,9 +52,9 @@ impl Default for User { impl User { pub fn to_json(&self, output_pretty: bool) -> Result { if output_pretty { - return serde_json::to_string_pretty(&self); + serde_json::to_string_pretty(&self) } else { - return serde_json::to_string(&self); + serde_json::to_string(&self) } } } diff --git a/tests/album.json b/tests/album.json new file mode 100644 index 0000000..7124099 --- /dev/null +++ b/tests/album.json @@ -0,0 +1,31 @@ +{ + "album": "Sample Tracks! Yes", + "album_artist": "KD", + "genre": "Country", + "year": 2025, + "track_count": 3, + "disc_count": 1, + "tracks": [ + { + "title": "E less", + "artist": "KD", + "disc": 1, + "track": 1, + "duration": 31 + }, + { + "title": "Aaaaaye", + "artist": "KD", + "disc": 1, + "track": 2, + "duration": 33 + }, + { + "title": "Check D out", + "artist": "KD", + "disc": 1, + "track": 3, + "duration": 22 + } + ] +} diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 0000000..7df899b --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,179 @@ +mod utils { + use std::fs; + use std::io::Read; + use std::path::Path; + + pub fn get_tests_directory() -> String { + String::from(env!("CARGO_MANIFEST_DIR").to_owned() + "/tests/") + } + + pub fn does_directory_exists(directory: &String) -> bool { + let path = Path::new(directory); + if let Ok(dir_i) = fs::metadata(path) { + dir_i.is_dir() + } else { + false + } + } + + pub fn extract_data_from_file(filepath: &String) -> Result, std::io::Error> { + match std::fs::File::open(filepath) { + Ok(mut file) => { + let mut buffer: Vec = Vec::new(); + let _ = file.read_to_end(&mut buffer); + Ok(buffer) + } + Err(err) => Err(err), + } + } +} + +mod song_tests { + use std::fs::File; + use std::io::Write; + + use tempfile::tempdir; + + use icarus_models::song; + use icarus_models::types; + + use crate::utils; + + #[test] + fn test_song_to_data() { + println!("Test"); + let some_val = true; + + println!("Checking if some_val is true"); + assert_eq!(true, some_val); + + println!("Getting track"); + let mut song = song::Song::default(); + song.directory = utils::get_tests_directory(); + song.filename = String::from("track01.flac"); + + assert!( + utils::does_directory_exists(&song.directory), + "Directory does not exist" + ); + + println!("Directory: {}", song.directory); + + match song.song_path() { + Ok(filepath) => match utils::extract_data_from_file(&filepath) { + Ok(buffer) => { + assert_eq!(buffer.is_empty(), false); + + match song.to_data() { + Ok(song_data) => { + println!("Both files match"); + assert_eq!(buffer, song_data); + } + Err(err) => { + assert!(false, "Error producing song data: {:?}", err); + } + }; + } + Err(err) => { + assert!(false, "Failed to open file: {:?}", err); + } + }, + Err(err) => { + assert!(false, "Could not get song path: {:?}", err); + } + } + } + + #[test] + fn test_song_path_check() { + let mut song = song::Song::default(); + song.directory = utils::get_tests_directory(); + song.filename = String::from("track01.flac"); + + assert!( + utils::does_directory_exists(&song.directory), + "Directory does not exist" + ); + } + + #[test] + fn test_song_generate_filename() { + let mut song = song::Song::default(); + song.directory = utils::get_tests_directory(); + song.filename = String::from("track01.flac"); + + match song.song_path() { + Ok(songpath) => match utils::extract_data_from_file(&songpath) { + Ok(buffer) => { + let mut song_cpy = song.clone(); + let temp_dir = tempdir().expect("Failed to create temp dir"); + song_cpy.directory = match temp_dir.path().to_str() { + Some(s) => String::from(s), + None => String::new(), + }; + + assert_eq!(song.directory.is_empty(), false); + song_cpy.filename = + song.generate_filename(types::MusicTypes::FlacExtension, true); + println!("Directory: {:?}", song_cpy.directory); + println!("File to be created: {:?}", song_cpy.filename); + + let path = match song_cpy.song_path() { + Ok(s_path) => s_path, + Err(err) => { + assert!(false, "Error: {:?}", err); + String::new() + } + }; + + match File::create(path) { + Ok(mut file_cpy) => match file_cpy.write_all(&buffer) { + Ok(success) => { + println!("Success: {:?}", success); + } + Err(err) => { + assert!(false, "Error saving file: {:?}", err); + } + }, + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }; + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }, + Err(err) => { + assert!(false, "Error extracting song data: {:?}", err); + } + } + } +} + +mod album_tests { + + use crate::utils; + use icarus_models::album; + + #[test] + fn parse_album() { + let test_dir = utils::get_tests_directory(); + if utils::does_directory_exists(&test_dir) { + let album_file: String = test_dir + &String::from("album.json"); + println!("Album file: {:?}", album_file); + + match album::collection::parse_album(&album_file) { + Ok(album) => { + println!("Album title: {}", album.title); + assert_eq!(album.title.is_empty(), false); + assert_eq!(album.artist.is_empty(), false); + assert_eq!(album.tracks.is_empty(), false); + } + Err(err) => { + assert!(false, "Error parsing album json file: {:?}", err); + } + } + } + } +} diff --git a/tests/track01.flac b/tests/track01.flac new file mode 100644 index 0000000..b018649 Binary files /dev/null and b/tests/track01.flac differ diff --git a/tests/track02.flac b/tests/track02.flac new file mode 100644 index 0000000..3dfdbdb Binary files /dev/null and b/tests/track02.flac differ diff --git a/tests/track03.flac b/tests/track03.flac new file mode 100644 index 0000000..451c4a1 Binary files /dev/null and b/tests/track03.flac differ