Create the main binary #15
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -98,12 +98,19 @@ checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d"
|
||||
name = "musichoard"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.54"
|
||||
|
@ -11,4 +11,5 @@ serde_json = "1.0"
|
||||
uuid = { version = "1.3", features = ["serde"] }
|
||||
|
||||
[dev-dependencies]
|
||||
once_cell = "1.17"
|
||||
tempfile = "3.5"
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Module for storing MusicHoard data in a JSON file database.
|
||||
|
||||
use std::fs::{read_to_string, write};
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
use std::path::{PathBuf, Path};
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
@ -56,8 +56,8 @@ pub struct DatabaseJsonFile {
|
||||
|
||||
impl DatabaseJsonFile {
|
||||
/// Create a database instance that will read/write to the provided path.
|
||||
pub fn new(path: PathBuf) -> Self {
|
||||
DatabaseJsonFile { path }
|
||||
pub fn new(path: &Path) -> Self {
|
||||
DatabaseJsonFile { path: path.to_path_buf() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,11 +65,11 @@ impl DatabaseJsonBackend for DatabaseJsonFile {
|
||||
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:
|
||||
// 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> {
|
||||
write(&self.path, json)
|
||||
fs::write(&self.path, json)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ impl DatabaseJsonBackend for DatabaseJsonFile {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::{tests::test_data, Artist};
|
||||
use crate::{tests::COLLECTION, Artist};
|
||||
|
||||
struct DatabaseJsonTest {
|
||||
json: String,
|
||||
@ -154,7 +154,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn write() {
|
||||
let write_data = test_data();
|
||||
let write_data = COLLECTION.to_owned();
|
||||
let backend = DatabaseJsonTest {
|
||||
json: artists_to_json(&write_data),
|
||||
};
|
||||
@ -166,7 +166,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn read() {
|
||||
let expected = test_data();
|
||||
let expected = COLLECTION.to_owned();
|
||||
let backend = DatabaseJsonTest {
|
||||
json: artists_to_json(&expected),
|
||||
};
|
||||
@ -181,13 +181,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn reverse() {
|
||||
let expected = test_data();
|
||||
let expected = COLLECTION.to_owned();
|
||||
let backend = DatabaseJsonTest {
|
||||
json: artists_to_json(&expected),
|
||||
};
|
||||
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![];
|
||||
database.write(&write_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;
|
||||
|
||||
/// A single track on an album.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct Track {
|
||||
pub number: u32,
|
||||
pub title: String,
|
||||
@ -18,27 +18,27 @@ pub struct Track {
|
||||
}
|
||||
|
||||
/// The album identifier.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct AlbumId {
|
||||
pub year: u32,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
/// 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 id: AlbumId,
|
||||
pub tracks: Vec<Track>,
|
||||
}
|
||||
|
||||
/// The artist identifier.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct ArtistId {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// An artist.
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct Artist {
|
||||
pub id: ArtistId,
|
||||
pub albums: Vec<Album>,
|
||||
@ -48,7 +48,9 @@ pub struct Artist {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
pub fn test_data() -> Vec<Artist> {
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| {
|
||||
vec![
|
||||
Artist {
|
||||
id: ArtistId {
|
||||
@ -128,5 +130,5 @@ mod tests {
|
||||
}],
|
||||
},
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::Display,
|
||||
process::Command,
|
||||
process::Command, path::{PathBuf, Path},
|
||||
};
|
||||
|
||||
use crate::{Album, AlbumId, Artist, ArtistId, Track};
|
||||
@ -117,7 +117,7 @@ impl Library for Beets {
|
||||
|
||||
macro_rules! list_format_separator {
|
||||
() => {
|
||||
"-*^-"
|
||||
" -*^- "
|
||||
};
|
||||
}
|
||||
|
||||
@ -151,8 +151,11 @@ impl LibraryPrivate for Beets {
|
||||
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
||||
|
||||
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 {
|
||||
return Err(Error::InvalidData(line.to_string()));
|
||||
}
|
||||
@ -221,25 +224,32 @@ impl LibraryPrivate for Beets {
|
||||
/// Executor for executing beets commands on the local system.
|
||||
pub struct SystemExecutor {
|
||||
bin: String,
|
||||
config: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl SystemExecutor {
|
||||
pub fn new(bin: &str) -> SystemExecutor {
|
||||
pub fn new(bin: &str, path: Option<&Path>) -> SystemExecutor {
|
||||
SystemExecutor {
|
||||
bin: bin.to_string(),
|
||||
config: path.map(|p| p.to_path_buf()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SystemExecutor {
|
||||
fn default() -> Self {
|
||||
SystemExecutor::new("beet")
|
||||
SystemExecutor::new("beet", None)
|
||||
}
|
||||
}
|
||||
|
||||
impl BeetsExecutor for SystemExecutor {
|
||||
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)?;
|
||||
Ok(output.split('\n').map(|s| s.to_string()).collect())
|
||||
}
|
||||
@ -249,7 +259,7 @@ impl BeetsExecutor for SystemExecutor {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::tests::test_data;
|
||||
use crate::tests::COLLECTION;
|
||||
|
||||
struct TestExecutor {
|
||||
arguments: Option<Vec<String>>,
|
||||
@ -333,7 +343,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_list_ordered() {
|
||||
let expected = test_data();
|
||||
let expected = COLLECTION.to_owned();
|
||||
let output = artists_to_beets_string(&expected);
|
||||
|
||||
let executor = TestExecutor {
|
||||
@ -348,7 +358,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_list_unordered() {
|
||||
let mut expected = test_data();
|
||||
let mut expected = COLLECTION.to_owned();
|
||||
let mut output = artists_to_beets_string(&expected);
|
||||
let last = output.len() - 1;
|
||||
output.swap(0, last);
|
||||
@ -377,7 +387,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
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.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