Add integration tests
This commit is contained in:
parent
5c7579ba23
commit
16045a6c85
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -98,12 +98,19 @@ checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d"
|
|||||||
name = "musichoard"
|
name = "musichoard"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.54"
|
version = "1.0.54"
|
||||||
|
@ -11,4 +11,5 @@ serde_json = "1.0"
|
|||||||
uuid = { version = "1.3", features = ["serde"] }
|
uuid = { version = "1.3", features = ["serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
once_cell = "1.17"
|
||||||
tempfile = "3.5"
|
tempfile = "3.5"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module for storing MusicHoard data in a JSON file database.
|
//! Module for storing MusicHoard data in a JSON file database.
|
||||||
|
|
||||||
use std::fs::{read_to_string, write};
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::{PathBuf, Path};
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -56,8 +56,8 @@ pub struct DatabaseJsonFile {
|
|||||||
|
|
||||||
impl DatabaseJsonFile {
|
impl DatabaseJsonFile {
|
||||||
/// Create a database instance that will read/write to the provided path.
|
/// Create a database instance that will read/write to the provided path.
|
||||||
pub fn new(path: PathBuf) -> Self {
|
pub fn new(path: &Path) -> Self {
|
||||||
DatabaseJsonFile { path }
|
DatabaseJsonFile { path: path.to_path_buf() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,11 +65,11 @@ impl DatabaseJsonBackend for DatabaseJsonFile {
|
|||||||
fn read(&self) -> Result<String, std::io::Error> {
|
fn read(&self) -> Result<String, std::io::Error> {
|
||||||
// Read entire file to memory as for now this is faster than a buffered read from disk:
|
// Read entire file to memory as for now this is faster than a buffered read from disk:
|
||||||
// https://github.com/serde-rs/json/issues/160
|
// https://github.com/serde-rs/json/issues/160
|
||||||
read_to_string(&self.path)
|
fs::read_to_string(&self.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&mut self, json: &str) -> Result<(), std::io::Error> {
|
fn write(&mut self, json: &str) -> Result<(), std::io::Error> {
|
||||||
write(&self.path, json)
|
fs::write(&self.path, json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ impl DatabaseJsonBackend for DatabaseJsonFile {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::{tests::test_data, Artist};
|
use crate::{tests::COLLECTION, Artist};
|
||||||
|
|
||||||
struct DatabaseJsonTest {
|
struct DatabaseJsonTest {
|
||||||
json: String,
|
json: String,
|
||||||
@ -154,7 +154,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn write() {
|
fn write() {
|
||||||
let write_data = test_data();
|
let write_data = COLLECTION.to_owned();
|
||||||
let backend = DatabaseJsonTest {
|
let backend = DatabaseJsonTest {
|
||||||
json: artists_to_json(&write_data),
|
json: artists_to_json(&write_data),
|
||||||
};
|
};
|
||||||
@ -166,7 +166,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read() {
|
fn read() {
|
||||||
let expected = test_data();
|
let expected = COLLECTION.to_owned();
|
||||||
let backend = DatabaseJsonTest {
|
let backend = DatabaseJsonTest {
|
||||||
json: artists_to_json(&expected),
|
json: artists_to_json(&expected),
|
||||||
};
|
};
|
||||||
@ -181,13 +181,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reverse() {
|
fn reverse() {
|
||||||
let expected = test_data();
|
let expected = COLLECTION.to_owned();
|
||||||
let backend = DatabaseJsonTest {
|
let backend = DatabaseJsonTest {
|
||||||
json: artists_to_json(&expected),
|
json: artists_to_json(&expected),
|
||||||
};
|
};
|
||||||
let mut database = DatabaseJson::new(Box::new(backend));
|
let mut database = DatabaseJson::new(Box::new(backend));
|
||||||
|
|
||||||
let write_data = test_data();
|
let write_data = COLLECTION.to_owned();
|
||||||
let mut read_data: Vec<Artist> = vec![];
|
let mut read_data: Vec<Artist> = vec![];
|
||||||
database.write(&write_data).unwrap();
|
database.write(&write_data).unwrap();
|
||||||
database.read(&mut read_data).unwrap();
|
database.read(&mut read_data).unwrap();
|
||||||
|
16
src/lib.rs
16
src/lib.rs
@ -10,7 +10,7 @@ pub mod library;
|
|||||||
pub type Mbid = Uuid;
|
pub type Mbid = Uuid;
|
||||||
|
|
||||||
/// A single track on an album.
|
/// A single track on an album.
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
pub struct Track {
|
pub struct Track {
|
||||||
pub number: u32,
|
pub number: u32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
@ -18,27 +18,27 @@ pub struct Track {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The album identifier.
|
/// The album identifier.
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||||
pub struct AlbumId {
|
pub struct AlbumId {
|
||||||
pub year: u32,
|
pub year: u32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An album is a collection of tracks that were released together.
|
/// An album is a collection of tracks that were released together.
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
pub struct Album {
|
pub struct Album {
|
||||||
pub id: AlbumId,
|
pub id: AlbumId,
|
||||||
pub tracks: Vec<Track>,
|
pub tracks: Vec<Track>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The artist identifier.
|
/// The artist identifier.
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||||
pub struct ArtistId {
|
pub struct ArtistId {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An artist.
|
/// An artist.
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
pub struct Artist {
|
pub struct Artist {
|
||||||
pub id: ArtistId,
|
pub id: ArtistId,
|
||||||
pub albums: Vec<Album>,
|
pub albums: Vec<Album>,
|
||||||
@ -48,7 +48,9 @@ pub struct Artist {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn test_data() -> Vec<Artist> {
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| {
|
||||||
vec![
|
vec![
|
||||||
Artist {
|
Artist {
|
||||||
id: ArtistId {
|
id: ArtistId {
|
||||||
@ -128,5 +130,5 @@ mod tests {
|
|||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
process::Command,
|
process::Command, path::{PathBuf, Path},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Album, AlbumId, Artist, ArtistId, Track};
|
use crate::{Album, AlbumId, Artist, ArtistId, Track};
|
||||||
@ -117,7 +117,7 @@ impl Library for Beets {
|
|||||||
|
|
||||||
macro_rules! list_format_separator {
|
macro_rules! list_format_separator {
|
||||||
() => {
|
() => {
|
||||||
"-*^-"
|
" -*^- "
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,8 +151,11 @@ impl LibraryPrivate for Beets {
|
|||||||
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
||||||
|
|
||||||
for line in list_output.iter() {
|
for line in list_output.iter() {
|
||||||
let split: Vec<&str> = line.split(Self::LIST_FORMAT_SEPARATOR).collect();
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let split: Vec<&str> = line.split(Self::LIST_FORMAT_SEPARATOR).collect();
|
||||||
if split.len() != 6 {
|
if split.len() != 6 {
|
||||||
return Err(Error::InvalidData(line.to_string()));
|
return Err(Error::InvalidData(line.to_string()));
|
||||||
}
|
}
|
||||||
@ -221,25 +224,32 @@ impl LibraryPrivate for Beets {
|
|||||||
/// Executor for executing beets commands on the local system.
|
/// Executor for executing beets commands on the local system.
|
||||||
pub struct SystemExecutor {
|
pub struct SystemExecutor {
|
||||||
bin: String,
|
bin: String,
|
||||||
|
config: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemExecutor {
|
impl SystemExecutor {
|
||||||
pub fn new(bin: &str) -> SystemExecutor {
|
pub fn new(bin: &str, path: Option<&Path>) -> SystemExecutor {
|
||||||
SystemExecutor {
|
SystemExecutor {
|
||||||
bin: bin.to_string(),
|
bin: bin.to_string(),
|
||||||
|
config: path.map(|p| p.to_path_buf()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SystemExecutor {
|
impl Default for SystemExecutor {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
SystemExecutor::new("beet")
|
SystemExecutor::new("beet", None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeetsExecutor for SystemExecutor {
|
impl BeetsExecutor for SystemExecutor {
|
||||||
fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error> {
|
fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error> {
|
||||||
let output = Command::new(&self.bin).args(arguments).output()?;
|
let mut cmd = Command::new(&self.bin);
|
||||||
|
if let Some(ref path) = self.config {
|
||||||
|
cmd.arg("--config");
|
||||||
|
cmd.arg(path);
|
||||||
|
}
|
||||||
|
let output = cmd.args(arguments).output()?;
|
||||||
let output = std::str::from_utf8(&output.stdout)?;
|
let output = std::str::from_utf8(&output.stdout)?;
|
||||||
Ok(output.split('\n').map(|s| s.to_string()).collect())
|
Ok(output.split('\n').map(|s| s.to_string()).collect())
|
||||||
}
|
}
|
||||||
@ -249,7 +259,7 @@ impl BeetsExecutor for SystemExecutor {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::tests::test_data;
|
use crate::tests::COLLECTION;
|
||||||
|
|
||||||
struct TestExecutor {
|
struct TestExecutor {
|
||||||
arguments: Option<Vec<String>>,
|
arguments: Option<Vec<String>>,
|
||||||
@ -333,7 +343,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_ordered() {
|
fn test_list_ordered() {
|
||||||
let expected = test_data();
|
let expected = COLLECTION.to_owned();
|
||||||
let output = artists_to_beets_string(&expected);
|
let output = artists_to_beets_string(&expected);
|
||||||
|
|
||||||
let executor = TestExecutor {
|
let executor = TestExecutor {
|
||||||
@ -348,7 +358,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_unordered() {
|
fn test_list_unordered() {
|
||||||
let mut expected = test_data();
|
let mut expected = COLLECTION.to_owned();
|
||||||
let mut output = artists_to_beets_string(&expected);
|
let mut output = artists_to_beets_string(&expected);
|
||||||
let last = output.len() - 1;
|
let last = output.len() - 1;
|
||||||
output.swap(0, last);
|
output.swap(0, last);
|
||||||
@ -377,7 +387,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_album_title_year_clash() {
|
fn test_list_album_title_year_clash() {
|
||||||
let mut expected = test_data();
|
let mut expected = COLLECTION.to_owned();
|
||||||
expected[0].albums[0].id.year = expected[1].albums[0].id.year;
|
expected[0].albums[0].id.year = expected[1].albums[0].id.year;
|
||||||
expected[0].albums[0].id.title = expected[1].albums[0].id.title.clone();
|
expected[0].albums[0].id.title = expected[1].albums[0].id.title.clone();
|
||||||
|
|
||||||
|
56
tests/database/json.rs
Normal file
56
tests/database/json.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use musichoard::{database::{
|
||||||
|
json::{DatabaseJson, DatabaseJsonFile},
|
||||||
|
DatabaseRead, DatabaseWrite,
|
||||||
|
}, Artist};
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
use crate::COLLECTION;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write() {
|
||||||
|
let file = NamedTempFile::new().unwrap();
|
||||||
|
|
||||||
|
let backend = DatabaseJsonFile::new(file.path());
|
||||||
|
let mut database = DatabaseJson::new(Box::new(backend));
|
||||||
|
|
||||||
|
let write_data = COLLECTION.to_owned();
|
||||||
|
database.write(&write_data).unwrap();
|
||||||
|
|
||||||
|
let expected_path = fs::canonicalize("./tests/files/database/database.json").unwrap();
|
||||||
|
let expected = fs::read_to_string(expected_path).unwrap();
|
||||||
|
let actual = fs::read_to_string(file.path()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read() {
|
||||||
|
let file_path = fs::canonicalize("./tests/files/database/database.json").unwrap();
|
||||||
|
|
||||||
|
let backend = DatabaseJsonFile::new(&file_path);
|
||||||
|
let database = DatabaseJson::new(Box::new(backend));
|
||||||
|
|
||||||
|
let mut read_data: Vec<Artist> = vec![];
|
||||||
|
database.read(&mut read_data).unwrap();
|
||||||
|
|
||||||
|
let expected = COLLECTION.to_owned();
|
||||||
|
assert_eq!(read_data, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reverse() {
|
||||||
|
let file = NamedTempFile::new().unwrap();
|
||||||
|
|
||||||
|
let backend = DatabaseJsonFile::new(file.path());
|
||||||
|
let mut database = DatabaseJson::new(Box::new(backend));
|
||||||
|
|
||||||
|
let write_data = COLLECTION.to_owned();
|
||||||
|
database.write(&write_data).unwrap();
|
||||||
|
|
||||||
|
let mut read_data: Vec<Artist> = vec![];
|
||||||
|
database.read(&mut read_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(write_data, read_data);
|
||||||
|
}
|
1
tests/database/mod.rs
Normal file
1
tests/database/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod json;
|
1
tests/files/.gitignore
vendored
Normal file
1
tests/files/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
library
|
1
tests/files/database/database.json
Normal file
1
tests/files/database/database.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{"id":{"name":"Аркона"},"albums":[{"id":{"year":2011,"title":"Slovo"},"tracks":[{"number":1,"title":"Az’","artist":["Аркона"]},{"number":2,"title":"Arkaim","artist":["Аркона"]},{"number":3,"title":"Bol’no mne","artist":["Аркона"]},{"number":4,"title":"Leshiy","artist":["Аркона"]},{"number":5,"title":"Zakliatie","artist":["Аркона"]},{"number":6,"title":"Predok","artist":["Аркона"]},{"number":7,"title":"Nikogda","artist":["Аркона"]},{"number":8,"title":"Tam za tumanami","artist":["Аркона"]},{"number":9,"title":"Potomok","artist":["Аркона"]},{"number":10,"title":"Slovo","artist":["Аркона"]},{"number":11,"title":"Odna","artist":["Аркона"]},{"number":12,"title":"Vo moiom sadochke…","artist":["Аркона"]},{"number":13,"title":"Stenka na stenku","artist":["Аркона"]},{"number":14,"title":"Zimushka","artist":["Аркона"]}]}]},{"id":{"name":"Eluveitie"},"albums":[{"id":{"year":2008,"title":"Slania"},"tracks":[{"number":1,"title":"Samon","artist":["Eluveitie"]},{"number":2,"title":"Primordial Breath","artist":["Eluveitie"]},{"number":3,"title":"Inis Mona","artist":["Eluveitie"]},{"number":4,"title":"Gray Sublime Archon","artist":["Eluveitie"]},{"number":5,"title":"Anagantios","artist":["Eluveitie"]},{"number":6,"title":"Bloodstained Ground","artist":["Eluveitie"]},{"number":7,"title":"The Somber Lay","artist":["Eluveitie"]},{"number":8,"title":"Slanias Song","artist":["Eluveitie"]},{"number":9,"title":"Giamonios","artist":["Eluveitie"]},{"number":10,"title":"Tarvos","artist":["Eluveitie"]},{"number":11,"title":"Calling the Rain","artist":["Eluveitie"]},{"number":12,"title":"Elembivos","artist":["Eluveitie"]}]},{"id":{"year":2004,"title":"Vên [re‐recorded]"},"tracks":[{"number":1,"title":"Verja Urit an Bitus","artist":["Eluveitie"]},{"number":2,"title":"Uis Elveti","artist":["Eluveitie"]},{"number":3,"title":"Ôrô","artist":["Eluveitie"]},{"number":4,"title":"Lament","artist":["Eluveitie"]},{"number":5,"title":"Druid","artist":["Eluveitie"]},{"number":6,"title":"Jêzaïg","artist":["Eluveitie"]}]}]},{"id":{"name":"Frontside"},"albums":[{"id":{"year":2001,"title":"…nasze jest królestwo, potęga i chwała na wieki…"},"tracks":[{"number":1,"title":"Intro = Chaos","artist":["Frontside"]},{"number":2,"title":"Modlitwa","artist":["Frontside"]},{"number":3,"title":"Długa droga z piekła","artist":["Frontside"]},{"number":4,"title":"Synowie ognia","artist":["Frontside"]},{"number":5,"title":"1902","artist":["Frontside"]},{"number":6,"title":"Krew za krew","artist":["Frontside"]},{"number":7,"title":"Kulminacja","artist":["Frontside"]},{"number":8,"title":"Judasz","artist":["Frontside"]},{"number":9,"title":"Więzy","artist":["Frontside"]},{"number":10,"title":"Zagubione dusze","artist":["Frontside"]},{"number":11,"title":"Linia życia","artist":["Frontside"]}]}]},{"id":{"name":"Metallica"},"albums":[{"id":{"year":1984,"title":"Ride the Lightning"},"tracks":[{"number":1,"title":"Fight Fire with Fire","artist":["Metallica"]},{"number":2,"title":"Ride the Lightning","artist":["Metallica"]},{"number":3,"title":"For Whom the Bell Tolls","artist":["Metallica"]},{"number":4,"title":"Fade to Black","artist":["Metallica"]},{"number":5,"title":"Trapped under Ice","artist":["Metallica"]},{"number":6,"title":"Escape","artist":["Metallica"]},{"number":7,"title":"Creeping Death","artist":["Metallica"]},{"number":8,"title":"The Call of Ktulu","artist":["Metallica"]}]},{"id":{"year":1999,"title":"S&M"},"tracks":[{"number":1,"title":"The Ecstasy of Gold","artist":["Metallica"]},{"number":2,"title":"The Call of Ktulu","artist":["Metallica"]},{"number":3,"title":"Master of Puppets","artist":["Metallica"]},{"number":4,"title":"Of Wolf and Man","artist":["Metallica"]},{"number":5,"title":"The Thing That Should Not Be","artist":["Metallica"]},{"number":6,"title":"Fuel","artist":["Metallica"]},{"number":7,"title":"The Memory Remains","artist":["Metallica"]},{"number":8,"title":"No Leaf Clover","artist":["Metallica"]},{"number":9,"title":"Hero of the Day","artist":["Metallica"]},{"number":10,"title":"Devil’s Dance","artist":["Metallica"]},{"number":11,"title":"Bleeding Me","artist":["Metallica"]},{"number":12,"title":"Nothing Else Matters","artist":["Metallica"]},{"number":13,"title":"Until It Sleeps","artist":["Metallica"]},{"number":14,"title":"For Whom the Bell Tolls","artist":["Metallica"]},{"number":15,"title":"−Human","artist":["Metallica"]},{"number":16,"title":"Wherever I May Roam","artist":["Metallica"]},{"number":17,"title":"Outlaw Torn","artist":["Metallica"]},{"number":18,"title":"Sad but True","artist":["Metallica"]},{"number":19,"title":"One","artist":["Metallica"]},{"number":20,"title":"Enter Sandman","artist":["Metallica"]},{"number":21,"title":"Battery","artist":["Metallica"]}]}]}]
|
442
tests/lib.rs
Normal file
442
tests/lib.rs
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
mod database;
|
||||||
|
mod library;
|
||||||
|
|
||||||
|
use musichoard::{Album, AlbumId, Artist, ArtistId, Track};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| {
|
||||||
|
vec![
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: String::from("Аркона"),
|
||||||
|
},
|
||||||
|
albums: vec![Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2011,
|
||||||
|
title: String::from("Slovo"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("Az’"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("Arkaim"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("Bol’no mne"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Leshiy"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("Zakliatie"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Predok"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 07,
|
||||||
|
title: String::from("Nikogda"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 08,
|
||||||
|
title: String::from("Tam za tumanami"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 09,
|
||||||
|
title: String::from("Potomok"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 10,
|
||||||
|
title: String::from("Slovo"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 11,
|
||||||
|
title: String::from("Odna"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 12,
|
||||||
|
title: String::from("Vo moiom sadochke…"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 13,
|
||||||
|
title: String::from("Stenka na stenku"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 14,
|
||||||
|
title: String::from("Zimushka"),
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: String::from("Eluveitie"),
|
||||||
|
},
|
||||||
|
albums: vec![
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2008,
|
||||||
|
title: String::from("Slania"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("Samon"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("Primordial Breath"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("Inis Mona"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Gray Sublime Archon"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("Anagantios"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Bloodstained Ground"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 07,
|
||||||
|
title: String::from("The Somber Lay"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 08,
|
||||||
|
title: String::from("Slanias Song"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 09,
|
||||||
|
title: String::from("Giamonios"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 10,
|
||||||
|
title: String::from("Tarvos"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 11,
|
||||||
|
title: String::from("Calling the Rain"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 12,
|
||||||
|
title: String::from("Elembivos"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2004,
|
||||||
|
title: String::from("Vên [re‐recorded]"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("Verja Urit an Bitus"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("Uis Elveti"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("Ôrô"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Lament"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("Druid"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Jêzaïg"),
|
||||||
|
artist: vec![String::from("Eluveitie")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: String::from("Frontside"),
|
||||||
|
},
|
||||||
|
albums: vec![Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2001,
|
||||||
|
title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("Intro = Chaos"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("Modlitwa"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("Długa droga z piekła"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Synowie ognia"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("1902"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Krew za krew"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 07,
|
||||||
|
title: String::from("Kulminacja"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 08,
|
||||||
|
title: String::from("Judasz"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 09,
|
||||||
|
title: String::from("Więzy"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 10,
|
||||||
|
title: String::from("Zagubione dusze"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 11,
|
||||||
|
title: String::from("Linia życia"),
|
||||||
|
artist: vec![String::from("Frontside")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: String::from("Metallica"),
|
||||||
|
},
|
||||||
|
albums: vec![
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 1984,
|
||||||
|
title: String::from("Ride the Lightning"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("Fight Fire with Fire"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("Ride the Lightning"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("For Whom the Bell Tolls"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Fade to Black"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("Trapped under Ice"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Escape"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 07,
|
||||||
|
title: String::from("Creeping Death"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 08,
|
||||||
|
title: String::from("The Call of Ktulu"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 1999,
|
||||||
|
title: String::from("S&M"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 01,
|
||||||
|
title: String::from("The Ecstasy of Gold"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 02,
|
||||||
|
title: String::from("The Call of Ktulu"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 03,
|
||||||
|
title: String::from("Master of Puppets"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 04,
|
||||||
|
title: String::from("Of Wolf and Man"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 05,
|
||||||
|
title: String::from("The Thing That Should Not Be"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 06,
|
||||||
|
title: String::from("Fuel"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 07,
|
||||||
|
title: String::from("The Memory Remains"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 08,
|
||||||
|
title: String::from("No Leaf Clover"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 09,
|
||||||
|
title: String::from("Hero of the Day"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 10,
|
||||||
|
title: String::from("Devil’s Dance"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 11,
|
||||||
|
title: String::from("Bleeding Me"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 12,
|
||||||
|
title: String::from("Nothing Else Matters"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 13,
|
||||||
|
title: String::from("Until It Sleeps"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 14,
|
||||||
|
title: String::from("For Whom the Bell Tolls"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 15,
|
||||||
|
title: String::from("−Human"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 16,
|
||||||
|
title: String::from("Wherever I May Roam"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 17,
|
||||||
|
title: String::from("Outlaw Torn"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 18,
|
||||||
|
title: String::from("Sad but True"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 19,
|
||||||
|
title: String::from("One"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 20,
|
||||||
|
title: String::from("Enter Sandman"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 21,
|
||||||
|
title: String::from("Battery"),
|
||||||
|
artist: vec![String::from("Metallica")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
85
tests/library/beets.rs
Normal file
85
tests/library/beets.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use musichoard::{
|
||||||
|
library::{
|
||||||
|
beets::{Beets, SystemExecutor},
|
||||||
|
Library, Query, QueryOption,
|
||||||
|
},
|
||||||
|
Artist,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::COLLECTION;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_config_list() {
|
||||||
|
let executor = SystemExecutor::new("beet", None);
|
||||||
|
|
||||||
|
let mut beets = Beets::new(Box::new(executor));
|
||||||
|
let output = beets.list(&Query::default()).unwrap();
|
||||||
|
|
||||||
|
let expected: Vec<Artist> = vec![];
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_full_list() {
|
||||||
|
let executor = SystemExecutor::new(
|
||||||
|
"beet",
|
||||||
|
Some(&fs::canonicalize("./tests/files/library/config.yml").unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut beets = Beets::new(Box::new(executor));
|
||||||
|
let output = beets.list(&Query::default()).unwrap();
|
||||||
|
|
||||||
|
let expected: Vec<Artist> = COLLECTION.to_owned();
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_album_artist_query() {
|
||||||
|
let executor = SystemExecutor::new(
|
||||||
|
"beet",
|
||||||
|
Some(&fs::canonicalize("./tests/files/library/config.yml").unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut beets = Beets::new(Box::new(executor));
|
||||||
|
let output = beets
|
||||||
|
.list(&Query::default().album_artist(QueryOption::Include(String::from("Аркона"))))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let expected: Vec<Artist> = COLLECTION[0..1].to_owned();
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_album_title_query() {
|
||||||
|
let executor = SystemExecutor::new(
|
||||||
|
"beet",
|
||||||
|
Some(&fs::canonicalize("./tests/files/library/config.yml").unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut beets = Beets::new(Box::new(executor));
|
||||||
|
let output = beets
|
||||||
|
.list(&Query::default().album_title(QueryOption::Include(String::from("Slovo"))))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let expected: Vec<Artist> = COLLECTION[0..1].to_owned();
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exclude_query() {
|
||||||
|
let executor = SystemExecutor::new(
|
||||||
|
"beet",
|
||||||
|
Some(&fs::canonicalize("./tests/files/library/config.yml").unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut beets = Beets::new(Box::new(executor));
|
||||||
|
let output = beets
|
||||||
|
.list(&Query::default().album_artist(QueryOption::Exclude(String::from("Аркона"))))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let expected: Vec<Artist> = COLLECTION[1..].to_owned();
|
||||||
|
assert_eq!(output, expected);
|
||||||
|
}
|
1
tests/library/mod.rs
Normal file
1
tests/library/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod beets;
|
Loading…
Reference in New Issue
Block a user