From 7edcc38483539ce56ffa3bb6f7c209291e6c9885 Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Tue, 29 Dec 2020 20:05:04 -0800 Subject: [PATCH] Test setup improvements (#125) * More descriptive test names * Test writing tools * Migrate to new test tooling * Adds test for collection cleaner --- Cargo.lock | 7 + Cargo.toml | 1 + src/app/config/test.rs | 104 ++-------- src/app/index/metadata.rs | 4 +- src/app/index/test.rs | 355 ++++++++++++++++++--------------- src/app/mod.rs | 3 + src/app/playlist/test.rs | 171 +++++++++------- src/app/test.rs | 94 +++++++++ src/app/thumbnail/read.rs | 2 +- src/app/user/test.rs | 191 +++++++----------- src/app/vfs/test.rs | 48 ++--- src/db/mod.rs | 40 +--- src/service/actix/test.rs | 11 +- src/service/test/admin.rs | 10 +- src/service/test/auth.rs | 22 +- src/service/test/collection.rs | 34 ++-- src/service/test/ddns.rs | 8 +- src/service/test/lastfm.rs | 5 +- src/service/test/media.rs | 14 +- src/service/test/playlist.rs | 22 +- src/service/test/settings.rs | 12 +- src/service/test/swagger.rs | 4 +- src/service/test/web.rs | 2 +- src/test.rs | 13 +- src/utils.rs | 2 +- 25 files changed, 580 insertions(+), 599 deletions(-) create mode 100644 src/app/test.rs diff --git a/Cargo.lock b/Cargo.lock index 9275487..6abcc45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -903,6 +903,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1815,6 +1821,7 @@ dependencies = [ "crossbeam-channel", "diesel", "diesel_migrations", + "fs_extra", "futures-util", "getopts", "headers", diff --git a/Cargo.toml b/Cargo.toml index 51e0d34..e708912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,3 +68,4 @@ unix-daemonize = "0.1.2" [dev-dependencies] headers = "0.3" +fs_extra = "1.2.0" diff --git a/src/app/config/test.rs b/src/app/config/test.rs index f885cb0..0c2508a 100644 --- a/src/app/config/test.rs +++ b/src/app/config/test.rs @@ -1,40 +1,10 @@ -use std::fs; -use std::path::PathBuf; - use super::*; -use crate::app::{settings, user, vfs}; -use crate::db::DB; +use crate::app::{ddns, settings, test, user, vfs}; use crate::test_name; -#[cfg(test)] -fn get_test_db(name: &str) -> DB { - let mut db_path = PathBuf::new(); - db_path.push("test-output"); - fs::create_dir_all(&db_path).unwrap(); - - db_path.push(name); - if db_path.exists() { - fs::remove_file(&db_path).unwrap(); - } - - DB::new(&db_path).unwrap() -} - #[test] fn apply_saves_misc_settings() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = user::Manager::new(db.clone(), auth_secret); - let vfs_manager = vfs::Manager::new(db.clone()); - let ddns_manager = ddns::Manager::new(db.clone()); - let config_manager = Manager::new( - settings_manager.clone(), - user_manager.clone(), - vfs_manager.clone(), - ddns_manager.clone(), - ); - + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_config = Config { settings: Some(settings::NewSettings { album_art_pattern: Some("🖼️\\.jpg".into()), @@ -44,8 +14,8 @@ fn apply_saves_misc_settings() { ..Default::default() }; - config_manager.apply(&new_config).unwrap(); - let settings = settings_manager.read().unwrap(); + ctx.config_manager.apply(&new_config).unwrap(); + let settings = ctx.settings_manager.read().unwrap(); let new_settings = new_config.settings.unwrap(); assert_eq!( settings.album_art_pattern, @@ -59,18 +29,7 @@ fn apply_saves_misc_settings() { #[test] fn apply_saves_mount_points() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = user::Manager::new(db.clone(), auth_secret); - let vfs_manager = vfs::Manager::new(db.clone()); - let ddns_manager = ddns::Manager::new(db.clone()); - let config_manager = Manager::new( - settings_manager.clone(), - user_manager.clone(), - vfs_manager.clone(), - ddns_manager.clone(), - ); + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_config = Config { mount_dirs: Some(vec![vfs::MountDir { @@ -80,27 +39,14 @@ fn apply_saves_mount_points() { ..Default::default() }; - config_manager.apply(&new_config).unwrap(); - let actual_mount_dirs: Vec = vfs_manager.mount_dirs().unwrap(); + ctx.config_manager.apply(&new_config).unwrap(); + let actual_mount_dirs: Vec = ctx.vfs_manager.mount_dirs().unwrap(); assert_eq!(actual_mount_dirs, new_config.mount_dirs.unwrap()); } #[test] fn apply_saves_ddns_settings() { - use crate::app::ddns; - - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = user::Manager::new(db.clone(), auth_secret); - let vfs_manager = vfs::Manager::new(db.clone()); - let ddns_manager = ddns::Manager::new(db.clone()); - let config_manager = Manager::new( - settings_manager.clone(), - user_manager.clone(), - vfs_manager.clone(), - ddns_manager.clone(), - ); + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_config = Config { ydns: Some(ddns::Config { @@ -111,36 +57,18 @@ fn apply_saves_ddns_settings() { ..Default::default() }; - config_manager.apply(&new_config).unwrap(); - let actual_ddns = ddns_manager.config().unwrap(); + ctx.config_manager.apply(&new_config).unwrap(); + let actual_ddns = ctx.ddns_manager.config().unwrap(); assert_eq!(actual_ddns, new_config.ydns.unwrap()); } #[test] fn apply_can_toggle_admin() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = user::Manager::new(db.clone(), auth_secret); - let vfs_manager = vfs::Manager::new(db.clone()); - let ddns_manager = ddns::Manager::new(db.clone()); - let config_manager = Manager::new( - settings_manager.clone(), - user_manager.clone(), - vfs_manager.clone(), - ddns_manager.clone(), - ); + let ctx = test::ContextBuilder::new(test_name!()) + .user("Walter", "Tasty🍖", true) + .build(); - let initial_config = Config { - users: Some(vec![user::NewUser { - name: "Walter".into(), - password: "Tasty🍖".into(), - admin: true, - }]), - ..Default::default() - }; - config_manager.apply(&initial_config).unwrap(); - assert!(user_manager.list().unwrap()[0].is_admin()); + assert!(ctx.user_manager.list().unwrap()[0].is_admin()); let new_config = Config { users: Some(vec![user::NewUser { @@ -150,6 +78,6 @@ fn apply_can_toggle_admin() { }]), ..Default::default() }; - config_manager.apply(&new_config).unwrap(); - assert!(!user_manager.list().unwrap()[0].is_admin()); + ctx.config_manager.apply(&new_config).unwrap(); + assert!(!ctx.user_manager.list().unwrap()[0].is_admin()); } diff --git a/src/app/index/metadata.rs b/src/app/index/metadata.rs index fb52f59..6177ffb 100644 --- a/src/app/index/metadata.rs +++ b/src/app/index/metadata.rs @@ -258,7 +258,7 @@ fn read_mp4(path: &Path) -> Result { } #[test] -fn test_read_metadata() { +fn reads_file_metadata() { let sample_tags = SongTags { disc_number: Some(3), track_number: Some(1), @@ -309,7 +309,7 @@ fn test_read_metadata() { } #[test] -fn test_read_artwork() { +fn reads_embedded_artwork() { assert!( read(Path::new("test-data/artwork/sample.mp3")) .unwrap() diff --git a/src/app/index/test.rs b/src/app/index/test.rs index 3c2b357..8ebc3a4 100644 --- a/src/app/index/test.rs +++ b/src/app/index/test.rs @@ -1,26 +1,24 @@ use diesel::prelude::*; +use std::default::Default; use std::path::{Path, PathBuf}; use super::*; -use crate::app::{index::Index, settings, vfs}; -use crate::db::{self, directories, songs}; +use crate::app::test; +use crate::db::{directories, songs}; use crate::test_name; -fn get_context(test_name: &str) -> (db::DB, Index) { - let db = db::get_test_db(test_name); - let vfs_manager = vfs::Manager::new(db.clone()); - let settings_manager = settings::Manager::new(db.clone()); - let index = Index::new(db.clone(), vfs_manager, settings_manager); - (db, index) -} +const TEST_MOUNT_NAME: &str = "root"; #[test] -fn test_populate() { - let (db, index) = get_context(&test_name!()); - index.update().unwrap(); - index.update().unwrap(); // Validates that subsequent updates don't run into conflicts +fn update_adds_new_content() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); - let connection = db.connect().unwrap(); + ctx.index.update().unwrap(); + ctx.index.update().unwrap(); // Validates that subsequent updates don't run into conflicts + + let connection = ctx.db.connect().unwrap(); let all_directories: Vec = directories::table.load(&connection).unwrap(); let all_songs: Vec = songs::table.load(&connection).unwrap(); assert_eq!(all_directories.len(), 6); @@ -28,29 +26,154 @@ fn test_populate() { } #[test] -fn test_metadata() { - let target: PathBuf = ["test-data", "small-collection", "Tobokegao", "Picnic"] - .iter() - .collect(); +fn update_removes_missing_content() { + let builder = test::ContextBuilder::new(test_name!()); - let mut song_path = target.clone(); - song_path.push("05 - シャーベット (Sherbet).mp3"); + let original_collection_dir: PathBuf = ["test-data", "small-collection"].iter().collect(); + let test_collection_dir: PathBuf = builder.test_directory.join("small-collection"); - let mut artwork_path = target.clone(); - artwork_path.push("Folder.png"); + let copy_options = fs_extra::dir::CopyOptions::new(); + fs_extra::dir::copy( + &original_collection_dir, + &builder.test_directory, + ©_options, + ) + .unwrap(); - let (db, index) = get_context(&test_name!()); - index.update().unwrap(); + let ctx = builder + .mount(TEST_MOUNT_NAME, test_collection_dir.to_str().unwrap()) + .build(); - let connection = db.connect().unwrap(); - let songs: Vec = songs::table - .filter(songs::title.eq("シャーベット (Sherbet)")) - .load(&connection) - .unwrap(); + ctx.index.update().unwrap(); - assert_eq!(songs.len(), 1); - let song = &songs[0]; - assert_eq!(song.path, song_path.to_string_lossy().as_ref()); + { + let connection = ctx.db.connect().unwrap(); + let all_directories: Vec = directories::table.load(&connection).unwrap(); + let all_songs: Vec = songs::table.load(&connection).unwrap(); + assert_eq!(all_directories.len(), 6); + assert_eq!(all_songs.len(), 13); + } + + let khemmis_directory = test_collection_dir.join("Khemmis"); + std::fs::remove_dir_all(&khemmis_directory).unwrap(); + ctx.index.update().unwrap(); + { + let connection = ctx.db.connect().unwrap(); + let all_directories: Vec = directories::table.load(&connection).unwrap(); + let all_songs: Vec = songs::table.load(&connection).unwrap(); + assert_eq!(all_directories.len(), 4); + assert_eq!(all_songs.len(), 8); + } +} + +#[test] +fn can_browse_top_level() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + + let root_path = Path::new(TEST_MOUNT_NAME); + let files = ctx.index.browse(Path::new("")).unwrap(); + assert_eq!(files.len(), 1); + match files[0] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } +} + +#[test] +fn can_browse_directory() { + let khemmis_path: PathBuf = [TEST_MOUNT_NAME, "Khemmis"].iter().collect(); + let tobokegao_path: PathBuf = [TEST_MOUNT_NAME, "Tobokegao"].iter().collect(); + + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + + let files = ctx.index.browse(Path::new(TEST_MOUNT_NAME)).unwrap(); + + assert_eq!(files.len(), 2); + match files[0] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } + + match files[1] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } +} + +#[test] +fn can_flatten_root() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + let songs = ctx.index.flatten(Path::new(TEST_MOUNT_NAME)).unwrap(); + assert_eq!(songs.len(), 13); + assert_eq!(songs[0].title, Some("Above The Water".to_owned())); +} + +#[test] +fn can_flatten_directory() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + let path: PathBuf = [TEST_MOUNT_NAME, "Tobokegao"].iter().collect(); + let songs = ctx.index.flatten(&path).unwrap(); + assert_eq!(songs.len(), 8); +} + +#[test] +fn can_flatten_directory_with_shared_prefix() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + let path: PathBuf = [TEST_MOUNT_NAME, "Tobokegao", "Picnic"].iter().collect(); // Prefix of '(Picnic Remixes)' + let songs = ctx.index.flatten(&path).unwrap(); + assert_eq!(songs.len(), 7); +} + +#[test] +fn can_get_random_albums() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + let albums = ctx.index.get_random_albums(1).unwrap(); + assert_eq!(albums.len(), 1); +} + +#[test] +fn can_get_recent_albums() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + ctx.index.update().unwrap(); + let albums = ctx.index.get_recent_albums(2).unwrap(); + assert_eq!(albums.len(), 2); + assert!(albums[0].date_added >= albums[1].date_added); +} + +#[test] +fn can_get_a_song() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + + ctx.index.update().unwrap(); + + let picnic_virtual_dir: PathBuf = [TEST_MOUNT_NAME, "Tobokegao", "Picnic"].iter().collect(); + let song_virtual_path = picnic_virtual_dir.join("05 - シャーベット (Sherbet).mp3"); + let artwork_virtual_path = picnic_virtual_dir.join("Folder.png"); + + let song = ctx.index.get_song(&song_virtual_path).unwrap(); + assert_eq!(song.path, song_virtual_path.to_string_lossy().as_ref()); assert_eq!(song.track_number, Some(5)); assert_eq!(song.disc_number, None); assert_eq!(song.title, Some("シャーベット (Sherbet)".to_owned())); @@ -60,152 +183,54 @@ fn test_metadata() { assert_eq!(song.year, Some(2016)); assert_eq!( song.artwork, - Some(artwork_path.to_string_lossy().into_owned()) + Some(artwork_virtual_path.to_string_lossy().into_owned()) ); } #[test] -fn test_artwork_pattern_case_insensitive() { - let target: PathBuf = ["test-data", "small-collection", "Khemmis", "Hunted"] - .iter() - .collect(); +fn indexes_embedded_artwork() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); - let mut song_path = target.clone(); - song_path.push("05 - Hunted.mp3"); + ctx.index.update().unwrap(); - let mut artwork_path = target.clone(); - artwork_path.push("folder.jpg"); + let picnic_virtual_dir: PathBuf = [TEST_MOUNT_NAME, "Tobokegao", "Picnic"].iter().collect(); + let song_virtual_path = picnic_virtual_dir.join("07 - なぜ (Why).mp3"); - let (db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let connection = db.connect().unwrap(); - let songs: Vec = songs::table - .filter(songs::title.eq("Hunted")) - .load(&connection) - .unwrap(); - - assert_eq!(songs.len(), 1); - let song = &songs[0]; + let song = ctx.index.get_song(&song_virtual_path).unwrap(); assert_eq!( - song.artwork.as_ref().unwrap().to_lowercase(), - artwork_path.to_string_lossy().to_lowercase() + song.artwork, + Some(song_virtual_path.to_string_lossy().into_owned()) ); } #[test] -fn test_embedded_artwork() { - let song_path: PathBuf = [ - "test-data", - "small-collection", - "Tobokegao", - "Picnic", - "07 - なぜ (Why).mp3", - ] - .iter() - .collect(); +fn album_art_pattern_is_case_insensitive() { + let ctx = test::ContextBuilder::new(test_name!()) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); - let (db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let connection = db.connect().unwrap(); - let songs: Vec = songs::table - .filter(songs::title.eq("なぜ (Why?)")) - .load(&connection) - .unwrap(); - - assert_eq!(songs.len(), 1); - let song = &songs[0]; - assert_eq!(song.artwork, Some(song_path.to_string_lossy().into_owned())); -} - -#[test] -fn test_browse_top_level() { - let mut root_path = PathBuf::new(); - root_path.push("root"); - - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let results = index.browse(Path::new("")).unwrap(); - - assert_eq!(results.len(), 1); - match results[0] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } -} - -#[test] -fn test_browse() { - let khemmis_path: PathBuf = ["root", "Khemmis"].iter().collect(); - let tobokegao_path: PathBuf = ["root", "Tobokegao"].iter().collect(); - - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let results = index.browse(Path::new("root")).unwrap(); - - assert_eq!(results.len(), 2); - match results[0] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } - match results[1] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } -} - -#[test] -fn test_flatten() { - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - // Flatten all - let results = index.flatten(Path::new("root")).unwrap(); - assert_eq!(results.len(), 13); - assert_eq!(results[0].title, Some("Above The Water".to_owned())); - - // Flatten a directory - let path: PathBuf = ["root", "Tobokegao"].iter().collect(); - let results = index.flatten(&path).unwrap(); - assert_eq!(results.len(), 8); - - // Flatten a directory that is a prefix of another directory (Picnic Remixes) - let path: PathBuf = ["root", "Tobokegao", "Picnic"].iter().collect(); - let results = index.flatten(&path).unwrap(); - assert_eq!(results.len(), 7); -} - -#[test] -fn test_random() { - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let results = index.get_random_albums(1).unwrap(); - assert_eq!(results.len(), 1); -} - -#[test] -fn test_recent() { - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let results = index.get_recent_albums(2).unwrap(); - assert_eq!(results.len(), 2); - assert!(results[0].date_added >= results[1].date_added); -} - -#[test] -fn test_get_song() { - let (_db, index) = get_context(&test_name!()); - index.update().unwrap(); - - let song_path: PathBuf = ["root", "Khemmis", "Hunted", "02 - Candlelight.mp3"] + let patterns = vec!["folder", "FOLDER"] .iter() - .collect(); + .map(|s| s.to_string()) + .collect::>(); - let song = index.get_song(&song_path).unwrap(); - assert_eq!(song.title.unwrap(), "Candlelight"); + for pattern in patterns.into_iter() { + ctx.settings_manager + .amend(&settings::NewSettings { + album_art_pattern: Some(pattern), + ..Default::default() + }) + .unwrap(); + ctx.index.update().unwrap(); + + let hunted_virtual_dir: PathBuf = [TEST_MOUNT_NAME, "Khemmis", "Hunted"].iter().collect(); + let artwork_virtual_path = hunted_virtual_dir.join("Folder.jpg"); + let song = &ctx.index.flatten(&hunted_virtual_dir).unwrap()[0]; + assert_eq!( + song.artwork, + Some(artwork_virtual_path.to_string_lossy().into_owned()) + ); + } } diff --git a/src/app/mod.rs b/src/app/mod.rs index 51c241e..bd3f7bc 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -7,3 +7,6 @@ pub mod settings; pub mod thumbnail; pub mod user; pub mod vfs; + +#[cfg(test)] +pub mod test; diff --git a/src/app/playlist/test.rs b/src/app/playlist/test.rs index 29088c4..2df21b3 100644 --- a/src/app/playlist/test.rs +++ b/src/app/playlist/test.rs @@ -1,99 +1,118 @@ -use core::clone::Clone; use std::path::{Path, PathBuf}; -use super::*; -use crate::app::{index::Index, settings, vfs}; -use crate::db; +use crate::app::test; use crate::test_name; +const TEST_USER: &str = "test_user"; +const TEST_PASSWORD: &str = "password"; +const TEST_PLAYLIST_NAME: &str = "Chill & Grill"; +const TEST_MOUNT_NAME: &str = "root"; + #[test] -fn test_create_playlist() { - let db = db::get_test_db(&test_name!()); - let vfs_manager = vfs::Manager::new(db.clone()); - let manager = Manager::new(db, vfs_manager); +fn save_playlist_golden_path() { + let ctx = test::ContextBuilder::new(test_name!()) + .user(TEST_USER, TEST_PASSWORD, false) + .build(); - let found_playlists = manager.list_playlists("test_user").unwrap(); - assert!(found_playlists.is_empty()); - - manager - .save_playlist("chill_and_grill", "test_user", &Vec::new()) + ctx.playlist_manager + .save_playlist(TEST_PLAYLIST_NAME, TEST_USER, &Vec::new()) .unwrap(); - let found_playlists = manager.list_playlists("test_user").unwrap(); - assert_eq!(found_playlists.len(), 1); - assert_eq!(found_playlists[0], "chill_and_grill"); - let found_playlists = manager.list_playlists("someone_else"); - assert!(found_playlists.is_err()); + let found_playlists = ctx.playlist_manager.list_playlists(TEST_USER).unwrap(); + assert_eq!(found_playlists.len(), 1); + assert_eq!(found_playlists[0], TEST_PLAYLIST_NAME); } #[test] -fn test_delete_playlist() { - let db = db::get_test_db(&test_name!()); - let vfs_manager = vfs::Manager::new(db.clone()); - let manager = Manager::new(db, vfs_manager); +fn save_playlist_is_idempotent() { + let ctx = test::ContextBuilder::new(test_name!()) + .user(TEST_USER, TEST_PASSWORD, false) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); - let playlist_content = Vec::new(); + ctx.index.update().unwrap(); - manager - .save_playlist("chill_and_grill", "test_user", &playlist_content) - .unwrap(); - manager - .save_playlist("mellow_bungalow", "test_user", &playlist_content) - .unwrap(); - let found_playlists = manager.list_playlists("test_user").unwrap(); - assert_eq!(found_playlists.len(), 2); - - manager - .delete_playlist("chill_and_grill", "test_user") - .unwrap(); - let found_playlists = manager.list_playlists("test_user").unwrap(); - assert_eq!(found_playlists.len(), 1); - assert_eq!(found_playlists[0], "mellow_bungalow"); - - let delete_result = manager.delete_playlist("mellow_bungalow", "someone_else"); - assert!(delete_result.is_err()); -} - -#[test] -fn test_fill_playlist() { - let db = db::get_test_db(&test_name!()); - let vfs_manager = vfs::Manager::new(db.clone()); - let settings_manager = settings::Manager::new(db.clone()); - let index = Index::new(db.clone(), vfs_manager.clone(), settings_manager); - let manager = Manager::new(db, vfs_manager); - - index.update().unwrap(); - - let mut playlist_content: Vec = index - .flatten(Path::new("root")) + let playlist_content: Vec = ctx + .index + .flatten(Path::new(TEST_MOUNT_NAME)) .unwrap() .into_iter() .map(|s| s.path) .collect(); assert_eq!(playlist_content.len(), 13); - let first_song = playlist_content[0].clone(); - playlist_content.push(first_song); - assert_eq!(playlist_content.len(), 14); - - manager - .save_playlist("all_the_music", "test_user", &playlist_content) + ctx.playlist_manager + .save_playlist(TEST_PLAYLIST_NAME, TEST_USER, &playlist_content) .unwrap(); - let songs = manager.read_playlist("all_the_music", "test_user").unwrap(); - assert_eq!(songs.len(), 14); - assert_eq!(songs[0].title, Some("Above The Water".to_owned())); - assert_eq!(songs[13].title, Some("Above The Water".to_owned())); - - let first_song_path: PathBuf = ["root", "Khemmis", "Hunted", "01 - Above The Water.mp3"] - .iter() - .collect(); - assert_eq!(songs[0].path, first_song_path.to_str().unwrap()); - - // Save again to verify that we don't dupe the content - manager - .save_playlist("all_the_music", "test_user", &playlist_content) + ctx.playlist_manager + .save_playlist(TEST_PLAYLIST_NAME, TEST_USER, &playlist_content) .unwrap(); - let songs = manager.read_playlist("all_the_music", "test_user").unwrap(); - assert_eq!(songs.len(), 14); + + let songs = ctx + .playlist_manager + .read_playlist(TEST_PLAYLIST_NAME, TEST_USER) + .unwrap(); + assert_eq!(songs.len(), 13); +} + +#[test] +fn delete_playlist_golden_path() { + let ctx = test::ContextBuilder::new(test_name!()) + .user(TEST_USER, TEST_PASSWORD, false) + .build(); + + let playlist_content = Vec::new(); + + ctx.playlist_manager + .save_playlist(TEST_PLAYLIST_NAME, TEST_USER, &playlist_content) + .unwrap(); + + ctx.playlist_manager + .delete_playlist(TEST_PLAYLIST_NAME, TEST_USER) + .unwrap(); + + let found_playlists = ctx.playlist_manager.list_playlists(TEST_USER).unwrap(); + assert_eq!(found_playlists.len(), 0); +} + +#[test] +fn read_playlist_golden_path() { + let ctx = test::ContextBuilder::new(test_name!()) + .user(TEST_USER, TEST_PASSWORD, false) + .mount(TEST_MOUNT_NAME, "test-data/small-collection") + .build(); + + ctx.index.update().unwrap(); + + let playlist_content: Vec = ctx + .index + .flatten(Path::new(TEST_MOUNT_NAME)) + .unwrap() + .into_iter() + .map(|s| s.path) + .collect(); + assert_eq!(playlist_content.len(), 13); + + ctx.playlist_manager + .save_playlist(TEST_PLAYLIST_NAME, TEST_USER, &playlist_content) + .unwrap(); + + let songs = ctx + .playlist_manager + .read_playlist(TEST_PLAYLIST_NAME, TEST_USER) + .unwrap(); + + assert_eq!(songs.len(), 13); + assert_eq!(songs[0].title, Some("Above The Water".to_owned())); + + let first_song_path: PathBuf = [ + TEST_MOUNT_NAME, + "Khemmis", + "Hunted", + "01 - Above The Water.mp3", + ] + .iter() + .collect(); + assert_eq!(songs[0].path, first_song_path.to_str().unwrap()); } diff --git a/src/app/test.rs b/src/app/test.rs new file mode 100644 index 0000000..230abbc --- /dev/null +++ b/src/app/test.rs @@ -0,0 +1,94 @@ +use std::path::PathBuf; + +use crate::app::{config, ddns, index::Index, lastfm, playlist, settings, thumbnail, user, vfs}; +use crate::db::DB; +use crate::test::*; + +pub struct Context { + pub db: DB, + pub index: Index, + pub config_manager: config::Manager, + pub ddns_manager: ddns::Manager, + pub lastfm_manager: lastfm::Manager, + pub playlist_manager: playlist::Manager, + pub settings_manager: settings::Manager, + pub thumbnail_manager: thumbnail::Manager, + pub user_manager: user::Manager, + pub vfs_manager: vfs::Manager, + pub test_directory: PathBuf, +} + +pub struct ContextBuilder { + config: config::Config, + pub test_directory: PathBuf, +} + +impl ContextBuilder { + pub fn new(test_name: String) -> Self { + Self { + test_directory: prepare_test_directory(&test_name), + config: config::Config::default(), + } + } + + pub fn user(mut self, name: &str, password: &str, is_admin: bool) -> Self { + self.config + .users + .get_or_insert(Vec::new()) + .push(user::NewUser { + name: name.to_owned(), + password: password.to_owned(), + admin: is_admin, + }); + self + } + + pub fn mount(mut self, name: &str, source: &str) -> Self { + self.config + .mount_dirs + .get_or_insert(Vec::new()) + .push(vfs::MountDir { + name: name.to_owned(), + source: source.to_owned(), + }); + self + } + + pub fn build(self) -> Context { + let cache_output_dir = self.test_directory.join("cache"); + let db_path = self.test_directory.join("db.sqlite"); + + let db = DB::new(&db_path).unwrap(); + let settings_manager = settings::Manager::new(db.clone()); + let auth_secret = settings_manager.get_auth_secret().unwrap(); + let user_manager = user::Manager::new(db.clone(), auth_secret); + let vfs_manager = vfs::Manager::new(db.clone()); + let ddns_manager = ddns::Manager::new(db.clone()); + let config_manager = config::Manager::new( + settings_manager.clone(), + user_manager.clone(), + vfs_manager.clone(), + ddns_manager.clone(), + ); + let index = Index::new(db.clone(), vfs_manager.clone(), settings_manager.clone()); + let playlist_manager = playlist::Manager::new(db.clone(), vfs_manager.clone()); + let thumbnail_manager = thumbnail::Manager::new(cache_output_dir); + let lastfm_manager = lastfm::Manager::new(index.clone(), user_manager.clone()); + + config_manager.apply(&self.config).unwrap(); + + Context { + db, + index, + config_manager, + ddns_manager, + lastfm_manager, + playlist_manager, + settings_manager, + thumbnail_manager, + user_manager, + vfs_manager, + test_directory: self.test_directory, + } + } +} diff --git a/src/app/thumbnail/read.rs b/src/app/thumbnail/read.rs index 5c7b4f8..e518704 100644 --- a/src/app/thumbnail/read.rs +++ b/src/app/thumbnail/read.rs @@ -75,7 +75,7 @@ fn read_opus(_: &Path) -> Result { } #[test] -fn test_read_artwork() { +fn can_read_artwork_data() { let ext_img = image::open("test-data/artwork/Folder.png") .unwrap() .to_rgb8(); diff --git a/src/app/user/test.rs b/src/app/user/test.rs index 86a9898..f9cd721 100644 --- a/src/app/user/test.rs +++ b/src/app/user/test.rs @@ -1,103 +1,70 @@ use super::*; -use crate::app::settings; -use crate::db::DB; +use crate::app::test; use crate::test_name; -#[cfg(test)] -pub fn get_test_db(name: &str) -> DB { - let mut db_path = std::path::PathBuf::new(); - db_path.push("test-output"); - std::fs::create_dir_all(&db_path).unwrap(); - - db_path.push(name); - if db_path.exists() { - std::fs::remove_file(&db_path).unwrap(); - } - - DB::new(&db_path).unwrap() -} +const TEST_USERNAME: &str = "Walter"; +const TEST_PASSWORD: &str = "super_secret!"; #[test] fn create_delete_user_golden_path() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: "Walter".to_owned(), - password: "super_secret!".to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - assert_eq!(user_manager.list().unwrap().len(), 0); - user_manager.create(&new_user).unwrap(); - assert_eq!(user_manager.list().unwrap().len(), 1); - user_manager.delete(&new_user.name).unwrap(); - assert_eq!(user_manager.list().unwrap().len(), 0); + ctx.user_manager.create(&new_user).unwrap(); + assert_eq!(ctx.user_manager.list().unwrap().len(), 1); + + ctx.user_manager.delete(&new_user.name).unwrap(); + assert_eq!(ctx.user_manager.list().unwrap().len(), 0); } #[test] fn cannot_create_user_with_blank_username() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { name: "".to_owned(), - password: "super_secret!".to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - assert_eq!( - user_manager.create(&new_user).unwrap_err(), + ctx.user_manager.create(&new_user).unwrap_err(), Error::EmptyUsername ); } #[test] fn cannot_create_user_with_blank_password() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: "Walter".to_owned(), + name: TEST_USERNAME.to_owned(), password: "".to_owned(), admin: false, }; - assert_eq!( - user_manager.create(&new_user).unwrap_err(), + ctx.user_manager.create(&new_user).unwrap_err(), Error::EmptyPassword ); } #[test] fn cannot_create_duplicate_user() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: "Walter".to_owned(), - password: "super_secret!".to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - - user_manager.create(&new_user).unwrap(); - user_manager.create(&new_user).unwrap_err(); + ctx.user_manager.create(&new_user).unwrap(); + ctx.user_manager.create(&new_user).unwrap_err(); } #[test] fn can_read_write_preferences() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_preferences = Preferences { web_theme_base: Some("very-dark-theme".to_owned()), @@ -106,40 +73,34 @@ fn can_read_write_preferences() { }; let new_user = NewUser { - name: "Walter".to_owned(), - password: "super_secret!".to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - user_manager.create(&new_user).unwrap(); + ctx.user_manager.create(&new_user).unwrap(); - user_manager - .write_preferences("Walter", &new_preferences) + ctx.user_manager + .write_preferences(TEST_USERNAME, &new_preferences) .unwrap(); - let read_preferences = user_manager.read_preferences("Walter").unwrap(); + let read_preferences = ctx.user_manager.read_preferences("Walter").unwrap(); assert_eq!(new_preferences, read_preferences); } #[test] fn login_rejects_bad_password() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - - let username = "Walter"; - let password = "super_secret!"; + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: username.to_owned(), - password: password.to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - user_manager.create(&new_user).unwrap(); + ctx.user_manager.create(&new_user).unwrap(); assert_eq!( - user_manager - .login(username, "not the password") + ctx.user_manager + .login(TEST_USERNAME, "not the password") .unwrap_err(), Error::IncorrectPassword ) @@ -147,72 +108,57 @@ fn login_rejects_bad_password() { #[test] fn login_golden_path() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - - let username = "Walter"; - let password = "super_secret!"; - + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: username.to_owned(), - password: password.to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - - user_manager.create(&new_user).unwrap(); - assert!(user_manager.login(username, password).is_ok()) + ctx.user_manager.create(&new_user).unwrap(); + assert!(ctx.user_manager.login(TEST_USERNAME, TEST_PASSWORD).is_ok()) } #[test] fn authenticate_rejects_bad_token() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - - let username = "Walter"; - let password = "super_secret!"; + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: username.to_owned(), - password: password.to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - user_manager.create(&new_user).unwrap(); + ctx.user_manager.create(&new_user).unwrap(); let fake_token = AuthToken("fake token".to_owned()); - assert!(user_manager + assert!(ctx + .user_manager .authenticate(&fake_token, AuthorizationScope::PolarisAuth) .is_err()) } #[test] fn authenticate_golden_path() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - - let username = "Walter"; - let password = "super_secret!"; + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: username.to_owned(), - password: password.to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - user_manager.create(&new_user).unwrap(); - let token = user_manager.login(username, password).unwrap(); - let authorization = user_manager + ctx.user_manager.create(&new_user).unwrap(); + let token = ctx + .user_manager + .login(TEST_USERNAME, TEST_PASSWORD) + .unwrap(); + let authorization = ctx + .user_manager .authenticate(&token, AuthorizationScope::PolarisAuth) .unwrap(); assert_eq!( authorization, Authorization { - username: username.to_owned(), + username: TEST_USERNAME.to_owned(), scope: AuthorizationScope::PolarisAuth, } ) @@ -220,23 +166,22 @@ fn authenticate_golden_path() { #[test] fn authenticate_validates_scope() { - let db = get_test_db(&test_name!()); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = Manager::new(db, auth_secret); - - let username = "Walter"; - let password = "super_secret!"; + let ctx = test::ContextBuilder::new(test_name!()).build(); let new_user = NewUser { - name: username.to_owned(), - password: password.to_owned(), + name: TEST_USERNAME.to_owned(), + password: TEST_PASSWORD.to_owned(), admin: false, }; - user_manager.create(&new_user).unwrap(); - let token = user_manager.generate_lastfm_link_token(username).unwrap(); - let authorization = user_manager.authenticate(&token, AuthorizationScope::PolarisAuth); + ctx.user_manager.create(&new_user).unwrap(); + let token = ctx + .user_manager + .generate_lastfm_link_token(TEST_USERNAME) + .unwrap(); + let authorization = ctx + .user_manager + .authenticate(&token, AuthorizationScope::PolarisAuth); assert_eq!( authorization.unwrap_err(), Error::IncorrectAuthorizationScope diff --git a/src/app/vfs/test.rs b/src/app/vfs/test.rs index 6ed5cd4..9579be6 100644 --- a/src/app/vfs/test.rs +++ b/src/app/vfs/test.rs @@ -3,60 +3,42 @@ use std::path::{Path, PathBuf}; use super::*; #[test] -fn test_virtual_to_real() { +fn converts_virtual_to_real() { let vfs = VFS::new(vec![Mount { name: "root".to_owned(), source: Path::new("test_dir").to_owned(), }]); - - let mut correct_path = PathBuf::new(); - correct_path.push("test_dir"); - correct_path.push("somewhere"); - correct_path.push("something.png"); - - let mut virtual_path = PathBuf::new(); - virtual_path.push("root"); - virtual_path.push("somewhere"); - virtual_path.push("something.png"); - - let found_path = vfs.virtual_to_real(virtual_path.as_path()).unwrap(); - assert!(found_path.to_str() == correct_path.to_str()); + let real_path: PathBuf = ["test_dir", "somewhere", "something.png"].iter().collect(); + let virtual_path: PathBuf = ["root", "somewhere", "something.png"].iter().collect(); + let converted_path = vfs.virtual_to_real(virtual_path.as_path()).unwrap(); + assert_eq!(converted_path, real_path); } #[test] -fn test_virtual_to_real_no_trail() { +fn converts_virtual_to_real_top_level() { let vfs = VFS::new(vec![Mount { name: "root".to_owned(), source: Path::new("test_dir").to_owned(), }]); - let correct_path = Path::new("test_dir"); - let found_path = vfs.virtual_to_real(Path::new("root")).unwrap(); - assert!(found_path.to_str() == correct_path.to_str()); + let real_path = Path::new("test_dir"); + let converted_path = vfs.virtual_to_real(Path::new("root")).unwrap(); + assert_eq!(converted_path, real_path); } #[test] -fn test_real_to_virtual() { +fn converts_real_to_virtual() { let vfs = VFS::new(vec![Mount { name: "root".to_owned(), source: Path::new("test_dir").to_owned(), }]); - - let mut correct_path = PathBuf::new(); - correct_path.push("root"); - correct_path.push("somewhere"); - correct_path.push("something.png"); - - let mut real_path = PathBuf::new(); - real_path.push("test_dir"); - real_path.push("somewhere"); - real_path.push("something.png"); - - let found_path = vfs.real_to_virtual(real_path.as_path()).unwrap(); - assert!(found_path == correct_path); + let virtual_path: PathBuf = ["root", "somewhere", "something.png"].iter().collect(); + let real_path: PathBuf = ["test_dir", "somewhere", "something.png"].iter().collect(); + let converted_path = vfs.real_to_virtual(real_path.as_path()).unwrap(); + assert_eq!(converted_path, virtual_path); } #[test] -fn test_clean_path_string() { +fn cleans_path_string() { let mut correct_path = path::PathBuf::new(); if cfg!(target_os = "windows") { correct_path.push("C:\\"); diff --git a/src/db/mod.rs b/src/db/mod.rs index d392cf7..568840e 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -87,42 +87,14 @@ impl DB { } } -#[cfg(test)] -pub fn get_test_db(name: &str) -> DB { - use crate::app::{config, ddns, settings, user, vfs}; - - let mut db_path = std::path::PathBuf::new(); - db_path.push("test-output"); - std::fs::create_dir_all(&db_path).unwrap(); - - db_path.push(name); - if db_path.exists() { - std::fs::remove_file(&db_path).unwrap(); - } - +#[test] +fn run_migrations() { + use crate::test::*; + use crate::test_name; + let output_dir = prepare_test_directory(test_name!()); + let db_path = output_dir.join("db.sqlite"); let db = DB::new(&db_path).unwrap(); - let settings_manager = settings::Manager::new(db.clone()); - let auth_secret = settings_manager.get_auth_secret().unwrap(); - let user_manager = user::Manager::new(db.clone(), auth_secret); - let vfs_manager = vfs::Manager::new(db.clone()); - let ddns_manager = ddns::Manager::new(db.clone()); - let config_manager = - config::Manager::new(settings_manager, user_manager, vfs_manager, ddns_manager); - let config_path = Path::new("test-data/config.toml"); - let config = config::Config::from_path(&config_path).unwrap(); - config_manager.apply(&config).unwrap(); - db -} - -#[test] -fn test_migrations_up() { - get_test_db("migrations_up.sqlite"); -} - -#[test] -fn test_migrations_down() { - let db = get_test_db("migrations_down.sqlite"); db.migrate_down().unwrap(); db.migrate_up().unwrap(); } diff --git a/src/service/actix/test.rs b/src/service/actix/test.rs index 1bc9343..17e0c1e 100644 --- a/src/service/actix/test.rs +++ b/src/service/actix/test.rs @@ -9,13 +9,13 @@ use actix_web::{ use http::{response::Builder, Method, Request, Response}; use serde::de::DeserializeOwned; use serde::Serialize; -use std::fs; use std::ops::Deref; use std::path::{Path, PathBuf}; use crate::service::actix::*; use crate::service::dto; use crate::service::test::TestService; +use crate::test::*; pub struct ActixTestService { system_runner: SystemRunner, @@ -76,13 +76,8 @@ impl ActixTestService { impl TestService for ActixTestService { fn new(test_name: &str) -> Self { - let mut db_path: PathBuf = ["test-output", test_name].iter().collect(); - fs::create_dir_all(&db_path).unwrap(); - db_path.push("db.sqlite"); - - if db_path.exists() { - fs::remove_file(&db_path).unwrap(); - } + let output_dir = prepare_test_directory(test_name); + let db_path: PathBuf = output_dir.join("db.sqlite"); let context = service::ContextBuilder::new() .port(5050) diff --git a/src/service/test/admin.rs b/src/service/test/admin.rs index cb023f2..f5e679f 100644 --- a/src/service/test/admin.rs +++ b/src/service/test/admin.rs @@ -6,7 +6,7 @@ use crate::service::test::{protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_returns_api_version() { +fn returns_api_version() { let mut service = ServiceType::new(&test_name!()); let request = protocol::version(); let response = service.fetch_json::<_, dto::Version>(&request); @@ -14,7 +14,7 @@ fn test_returns_api_version() { } #[test] -fn test_initial_setup_golden_path() { +fn initial_setup_golden_path() { let mut service = ServiceType::new(&test_name!()); let request = protocol::initial_setup(); { @@ -43,7 +43,7 @@ fn test_initial_setup_golden_path() { } #[test] -fn test_trigger_index_golden_path() { +fn trigger_index_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -62,7 +62,7 @@ fn test_trigger_index_golden_path() { } #[test] -fn test_trigger_index_requires_auth() { +fn trigger_index_requires_auth() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); let request = protocol::trigger_index(); @@ -71,7 +71,7 @@ fn test_trigger_index_requires_auth() { } #[test] -fn test_trigger_index_requires_admin() { +fn trigger_index_requires_admin() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); diff --git a/src/service/test/auth.rs b/src/service/test/auth.rs index c18d171..6da6fe1 100644 --- a/src/service/test/auth.rs +++ b/src/service/test/auth.rs @@ -52,7 +52,7 @@ fn validate_no_cookies(response: &Response) { } #[test] -fn test_login_rejects_bad_username() { +fn login_rejects_bad_username() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -62,7 +62,7 @@ fn test_login_rejects_bad_username() { } #[test] -fn test_login_rejects_bad_password() { +fn login_rejects_bad_password() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -72,7 +72,7 @@ fn test_login_rejects_bad_password() { } #[test] -fn test_login_golden_path() { +fn login_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -89,7 +89,7 @@ fn test_login_golden_path() { } #[test] -fn test_requests_without_auth_header_do_not_set_cookies() { +fn requests_without_auth_header_do_not_set_cookies() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -102,7 +102,7 @@ fn test_requests_without_auth_header_do_not_set_cookies() { } #[test] -fn test_authentication_via_basic_http_header_rejects_bad_username() { +fn authentication_via_basic_http_header_rejects_bad_username() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -115,7 +115,7 @@ fn test_authentication_via_basic_http_header_rejects_bad_username() { } #[test] -fn test_authentication_via_basic_http_header_rejects_bad_password() { +fn authentication_via_basic_http_header_rejects_bad_password() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -128,7 +128,7 @@ fn test_authentication_via_basic_http_header_rejects_bad_password() { } #[test] -fn test_authentication_via_basic_http_header_golden_path() { +fn authentication_via_basic_http_header_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -143,7 +143,7 @@ fn test_authentication_via_basic_http_header_golden_path() { } #[test] -fn test_authentication_via_bearer_http_header_rejects_bad_token() { +fn authentication_via_bearer_http_header_rejects_bad_token() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -156,7 +156,7 @@ fn test_authentication_via_bearer_http_header_rejects_bad_token() { } #[test] -fn test_authentication_via_bearer_http_header_golden_path() { +fn authentication_via_bearer_http_header_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -179,7 +179,7 @@ fn test_authentication_via_bearer_http_header_golden_path() { } #[test] -fn test_authentication_via_query_param_rejects_bad_token() { +fn authentication_via_query_param_rejects_bad_token() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -193,7 +193,7 @@ fn test_authentication_via_query_param_rejects_bad_token() { } #[test] -fn test_authentication_via_query_param_golden_path() { +fn authentication_via_query_param_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); diff --git a/src/service/test/collection.rs b/src/service/test/collection.rs index 564d51f..a95aa75 100644 --- a/src/service/test/collection.rs +++ b/src/service/test/collection.rs @@ -6,7 +6,7 @@ use crate::service::test::{add_trailing_slash, constants::*, protocol, ServiceTy use crate::test_name; #[test] -fn test_browse_requires_auth() { +fn browse_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::browse(&PathBuf::new()); let response = service.fetch(&request); @@ -14,7 +14,7 @@ fn test_browse_requires_auth() { } #[test] -fn test_browse_root() { +fn browse_root() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -29,7 +29,7 @@ fn test_browse_root() { } #[test] -fn test_browse_directory() { +fn browse_directory() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -45,7 +45,7 @@ fn test_browse_directory() { } #[test] -fn test_browse_bad_directory() { +fn browse_bad_directory() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -57,7 +57,7 @@ fn test_browse_bad_directory() { } #[test] -fn test_flatten_requires_auth() { +fn flatten_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::flatten(&PathBuf::new()); let response = service.fetch(&request); @@ -65,7 +65,7 @@ fn test_flatten_requires_auth() { } #[test] -fn test_flatten_root() { +fn flatten_root() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -80,7 +80,7 @@ fn test_flatten_root() { } #[test] -fn test_flatten_directory() { +fn flatten_directory() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -95,7 +95,7 @@ fn test_flatten_directory() { } #[test] -fn test_flatten_bad_directory() { +fn flatten_bad_directory() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -107,7 +107,7 @@ fn test_flatten_bad_directory() { } #[test] -fn test_random_requires_auth() { +fn random_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::random(); let response = service.fetch(&request); @@ -115,7 +115,7 @@ fn test_random_requires_auth() { } #[test] -fn test_random_golden_path() { +fn random_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -130,7 +130,7 @@ fn test_random_golden_path() { } #[test] -fn test_random_with_trailing_slash() { +fn random_with_trailing_slash() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -146,7 +146,7 @@ fn test_random_with_trailing_slash() { } #[test] -fn test_recent_requires_auth() { +fn recent_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::recent(); let response = service.fetch(&request); @@ -154,7 +154,7 @@ fn test_recent_requires_auth() { } #[test] -fn test_recent_golden_path() { +fn recent_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -169,7 +169,7 @@ fn test_recent_golden_path() { } #[test] -fn test_recent_with_trailing_slash() { +fn recent_with_trailing_slash() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -185,7 +185,7 @@ fn test_recent_with_trailing_slash() { } #[test] -fn test_search_requires_auth() { +fn search_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::search(""); let response = service.fetch(&request); @@ -193,7 +193,7 @@ fn test_search_requires_auth() { } #[test] -fn test_search_without_query() { +fn search_without_query() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -204,7 +204,7 @@ fn test_search_without_query() { } #[test] -fn test_search_with_query() { +fn search_with_query() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); diff --git a/src/service/test/ddns.rs b/src/service/test/ddns.rs index 77f1204..8c269b5 100644 --- a/src/service/test/ddns.rs +++ b/src/service/test/ddns.rs @@ -5,7 +5,7 @@ use crate::service::test::{protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_get_ddns_config_requires_admin() { +fn get_ddns_config_requires_admin() { let mut service = ServiceType::new(&test_name!()); let request = protocol::get_ddns_config(); service.complete_initial_setup(); @@ -19,7 +19,7 @@ fn test_get_ddns_config_requires_admin() { } #[test] -fn test_get_ddns_config_golden_path() { +fn get_ddns_config_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -30,7 +30,7 @@ fn test_get_ddns_config_golden_path() { } #[test] -fn test_put_ddns_config_requires_admin() { +fn put_ddns_config_requires_admin() { let mut service = ServiceType::new(&test_name!()); let request = protocol::put_ddns_config(dto::DDNSConfig { host: "test".to_owned(), @@ -48,7 +48,7 @@ fn test_put_ddns_config_requires_admin() { } #[test] -fn test_put_ddns_config_golden_path() { +fn put_ddns_config_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); diff --git a/src/service/test/lastfm.rs b/src/service/test/lastfm.rs index 3e0c905..7373124 100644 --- a/src/service/test/lastfm.rs +++ b/src/service/test/lastfm.rs @@ -6,7 +6,7 @@ use crate::service::test::{constants::*, protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_lastfm_scrobble_ignores_unlinked_user() { +fn lastfm_scrobble_ignores_unlinked_user() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -23,7 +23,7 @@ fn test_lastfm_scrobble_ignores_unlinked_user() { } #[test] -fn test_lastfm_now_playing_ignores_unlinked_user() { +fn lastfm_now_playing_ignores_unlinked_user() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -59,4 +59,3 @@ fn lastfm_link_token_golden_path() { let link_token = response.body(); assert!(!link_token.value.is_empty()); } - diff --git a/src/service/test/media.rs b/src/service/test/media.rs index 7c7ec95..9c2bf61 100644 --- a/src/service/test/media.rs +++ b/src/service/test/media.rs @@ -5,7 +5,7 @@ use crate::service::test::{constants::*, protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_audio_requires_auth() { +fn audio_requires_auth() { let mut service = ServiceType::new(&test_name!()); let path: PathBuf = [TEST_MOUNT_NAME, "Khemmis", "Hunted", "02 - Candlelight.mp3"] @@ -18,7 +18,7 @@ fn test_audio_requires_auth() { } #[test] -fn test_audio_golden_path() { +fn audio_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -36,7 +36,7 @@ fn test_audio_golden_path() { } #[test] -fn test_audio_partial_content() { +fn audio_partial_content() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -64,7 +64,7 @@ fn test_audio_partial_content() { } #[test] -fn test_audio_bad_path_returns_not_found() { +fn audio_bad_path_returns_not_found() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -77,7 +77,7 @@ fn test_audio_bad_path_returns_not_found() { } #[test] -fn test_thumbnail_requires_auth() { +fn thumbnail_requires_auth() { let mut service = ServiceType::new(&test_name!()); let path: PathBuf = [TEST_MOUNT_NAME, "Khemmis", "Hunted", "Folder.jpg"] @@ -91,7 +91,7 @@ fn test_thumbnail_requires_auth() { } #[test] -fn test_thumbnail_golden_path() { +fn thumbnail_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -109,7 +109,7 @@ fn test_thumbnail_golden_path() { } #[test] -fn test_thumbnail_bad_path_returns_not_found() { +fn thumbnail_bad_path_returns_not_found() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); diff --git a/src/service/test/playlist.rs b/src/service/test/playlist.rs index 1b2e812..3677800 100644 --- a/src/service/test/playlist.rs +++ b/src/service/test/playlist.rs @@ -6,7 +6,7 @@ use crate::service::test::{constants::*, protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_list_playlists_requires_auth() { +fn list_playlists_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::playlists(); let response = service.fetch(&request); @@ -14,7 +14,7 @@ fn test_list_playlists_requires_auth() { } #[test] -fn test_list_playlists_golden_path() { +fn list_playlists_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -24,7 +24,7 @@ fn test_list_playlists_golden_path() { } #[test] -fn test_save_playlist_requires_auth() { +fn save_playlist_requires_auth() { let mut service = ServiceType::new(&test_name!()); let my_playlist = dto::SavePlaylistInput { tracks: Vec::new() }; let request = protocol::save_playlist(TEST_PLAYLIST_NAME, my_playlist); @@ -33,7 +33,7 @@ fn test_save_playlist_requires_auth() { } #[test] -fn test_save_playlist_golden_path() { +fn save_playlist_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -45,7 +45,7 @@ fn test_save_playlist_golden_path() { } #[test] -fn test_save_playlist_large() { +fn save_playlist_large() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -60,7 +60,7 @@ fn test_save_playlist_large() { } #[test] -fn test_get_playlist_requires_auth() { +fn get_playlist_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::read_playlist(TEST_PLAYLIST_NAME); let response = service.fetch(&request); @@ -68,7 +68,7 @@ fn test_get_playlist_requires_auth() { } #[test] -fn test_get_playlist_golden_path() { +fn get_playlist_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -86,7 +86,7 @@ fn test_get_playlist_golden_path() { } #[test] -fn test_get_playlist_bad_name_returns_not_found() { +fn get_playlist_bad_name_returns_not_found() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -97,7 +97,7 @@ fn test_get_playlist_bad_name_returns_not_found() { } #[test] -fn test_delete_playlist_requires_auth() { +fn delete_playlist_requires_auth() { let mut service = ServiceType::new(&test_name!()); let request = protocol::delete_playlist(TEST_PLAYLIST_NAME); let response = service.fetch(&request); @@ -105,7 +105,7 @@ fn test_delete_playlist_requires_auth() { } #[test] -fn test_delete_playlist_golden_path() { +fn delete_playlist_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -123,7 +123,7 @@ fn test_delete_playlist_golden_path() { } #[test] -fn test_delete_playlist_bad_name_returns_not_found() { +fn delete_playlist_bad_name_returns_not_found() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); diff --git a/src/service/test/settings.rs b/src/service/test/settings.rs index d0e493c..2d66a2c 100644 --- a/src/service/test/settings.rs +++ b/src/service/test/settings.rs @@ -5,7 +5,7 @@ use crate::service::test::{protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_get_settings_requires_auth() { +fn get_settings_requires_auth() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); @@ -15,7 +15,7 @@ fn test_get_settings_requires_auth() { } #[test] -fn test_get_settings_requires_admin() { +fn get_settings_requires_admin() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -26,7 +26,7 @@ fn test_get_settings_requires_admin() { } #[test] -fn test_get_settings_golden_path() { +fn get_settings_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); @@ -37,7 +37,7 @@ fn test_get_settings_golden_path() { } #[test] -fn test_put_settings_requires_auth() { +fn put_settings_requires_auth() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); let request = protocol::put_settings(dto::NewSettings::default()); @@ -46,7 +46,7 @@ fn test_put_settings_requires_auth() { } #[test] -fn test_put_settings_requires_admin() { +fn put_settings_requires_admin() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login(); @@ -56,7 +56,7 @@ fn test_put_settings_requires_admin() { } #[test] -fn test_put_settings_golden_path() { +fn put_settings_golden_path() { let mut service = ServiceType::new(&test_name!()); service.complete_initial_setup(); service.login_admin(); diff --git a/src/service/test/swagger.rs b/src/service/test/swagger.rs index 29241e6..41d56f1 100644 --- a/src/service/test/swagger.rs +++ b/src/service/test/swagger.rs @@ -4,7 +4,7 @@ use crate::service::test::{add_trailing_slash, protocol, ServiceType, TestServic use crate::test_name; #[test] -fn test_swagger_can_get_index() { +fn can_get_swagger_index() { let mut service = ServiceType::new(&test_name!()); let request = protocol::swagger_index(); let response = service.fetch(&request); @@ -13,7 +13,7 @@ fn test_swagger_can_get_index() { } #[test] -fn test_swagger_can_get_index_with_trailing_slash() { +fn can_get_swagger_index_with_trailing_slash() { let mut service = ServiceType::new(&test_name!()); let mut request = protocol::swagger_index(); add_trailing_slash(&mut request); diff --git a/src/service/test/web.rs b/src/service/test/web.rs index f688dd7..00169d2 100644 --- a/src/service/test/web.rs +++ b/src/service/test/web.rs @@ -4,7 +4,7 @@ use crate::service::test::{protocol, ServiceType, TestService}; use crate::test_name; #[test] -fn test_serves_web_client() { +fn serves_web_client() { let mut service = ServiceType::new(&test_name!()); let request = protocol::web_index(); let response = service.fetch_bytes(&request); diff --git a/src/test.rs b/src/test.rs index 909cd2b..c910d38 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + #[macro_export] macro_rules! test_name { () => {{ @@ -5,5 +7,14 @@ macro_rules! test_name { let file_name = file_name.replace("/", "-"); let file_name = file_name.replace("\\", "-"); format!("{}-line-{}", file_name, line!()) - }}; + }}; +} + +pub fn prepare_test_directory>(test_name: T) -> PathBuf { + let output_dir: PathBuf = [".", "test-output", test_name.as_ref()].iter().collect(); + if output_dir.is_dir() { + std::fs::remove_dir_all(&output_dir).unwrap(); + } + std::fs::create_dir_all(&output_dir).unwrap(); + return output_dir; } diff --git a/src/utils.rs b/src/utils.rs index f21ff62..e5f1bb7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -45,7 +45,7 @@ pub fn get_audio_format(path: &Path) -> Option { } #[test] -fn test_get_audio_format() { +fn can_guess_audio_format() { assert_eq!(get_audio_format(Path::new("animals/🐷/my🐖file.jpg")), None); assert_eq!( get_audio_format(Path::new("animals/🐷/my🐖file.flac")),