Update unit tests

This commit is contained in:
Wojciech Kozlowski 2023-05-14 18:10:53 +02:00
parent 1e1dbe8688
commit 847a6dcf9c
4 changed files with 183 additions and 107 deletions

View File

@ -139,7 +139,9 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new(); let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
for item in items.into_iter() { for item in items.into_iter() {
let artist_id = ArtistId { name: item.album_artist }; let artist_id = ArtistId {
name: item.album_artist,
};
let album_id = AlbumId { let album_id = AlbumId {
year: item.album_year, year: item.album_year,
@ -216,13 +218,125 @@ mod tests {
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| collection!()); pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| collection!());
pub fn artist_to_items(artist: &Artist) -> Vec<Item> {
let mut items = vec![];
for album in artist.albums.iter() {
for track in album.tracks.iter() {
items.push(Item {
album_artist: artist.id.name.clone(),
album_year: album.id.year,
album_title: album.id.title.clone(),
track_number: track.number,
track_title: track.title.clone(),
track_artist: track.artist.clone(),
track_format: track.quality.format,
track_bitrate: track.quality.bitrate,
});
}
}
items
}
pub fn artists_to_items(artists: &[Artist]) -> Vec<Item> {
let mut items = vec![];
for artist in artists.iter() {
items.append(&mut artist_to_items(artist));
}
items
}
#[test]
fn rescan_library_ordered() {
let mut library = MockILibrary::new();
let database = MockIDatabase::new();
let library_input = Query::new();
let library_result = Ok(artists_to_items(&COLLECTION));
library
.expect_list()
.with(predicate::eq(library_input))
.times(1)
.return_once(|_| library_result);
let mut music_hoard = MusicHoard::new(library, database);
music_hoard.rescan_library().unwrap();
assert_eq!(music_hoard.get_collection(), &*COLLECTION);
}
#[test]
fn rescan_library_unordered() {
let mut library = MockILibrary::new();
let database = MockIDatabase::new();
let library_input = Query::new();
let mut library_result = Ok(artists_to_items(&COLLECTION));
// Swap the last item with the first.
let last = library_result.as_ref().unwrap().len() - 1;
library_result.as_mut().unwrap().swap(0, last);
library
.expect_list()
.with(predicate::eq(library_input))
.times(1)
.return_once(|_| library_result);
let mut music_hoard = MusicHoard::new(library, database);
let mut expected = COLLECTION.to_owned();
// Putting the last track first will make the entire artist come first in the output.
expected.rotate_right(1);
// Same applies to that artists' albums.
expected[0].albums.rotate_right(1);
// Same applies to that album's tracks.
expected[0].albums[0].tracks.rotate_right(1);
// And the original first album's (now the first album of the second artist) tracks first
// track comes last as it will only get picked up at the end.
expected[1].albums[0].tracks.rotate_left(1);
music_hoard.rescan_library().unwrap();
assert_eq!(music_hoard.get_collection(), &expected);
}
#[test]
fn rescan_library_album_title_year_clash() {
let mut library = MockILibrary::new();
let database = MockIDatabase::new();
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();
let library_input = Query::new();
let library_result = Ok(artists_to_items(&expected));
library
.expect_list()
.with(predicate::eq(library_input))
.times(1)
.return_once(|_| library_result);
let mut music_hoard = MusicHoard::new(library, database);
music_hoard.rescan_library().unwrap();
assert_eq!(music_hoard.get_collection(), &expected);
}
#[test] #[test]
fn read_get_write() { fn read_get_write() {
let mut library = MockILibrary::new(); let mut library = MockILibrary::new();
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
let library_input = Query::new(); let library_input = Query::new();
let library_result = Ok(COLLECTION.to_owned()); let library_result = Ok(artists_to_items(&COLLECTION));
let database_input = COLLECTION.to_owned(); let database_input = COLLECTION.to_owned();
let database_result = Ok(()); let database_result = Ok(());

View File

@ -164,45 +164,34 @@ impl<BLE: IBeetsLibraryExecutor> ILibraryPrivate for BeetsLibrary<BLE> {
mod tests { mod tests {
use mockall::predicate; use mockall::predicate;
use crate::tests::COLLECTION; use crate::tests::{artists_to_items, COLLECTION};
use super::*; use super::*;
fn artist_to_beets_string(artist: &Artist) -> Vec<String> { fn item_to_beets_string(item: &Item) -> String {
let mut strings = vec![]; format!(
"{album_artist}{sep}{album_year}{sep}{album_title}{sep}\
let album_artist = &artist.id.name; {track_number}{sep}{track_title}{sep}\
{track_artist}{sep}{track_format}{sep}{track_bitrate}kbps",
for album in artist.albums.iter() { album_artist = item.album_artist,
let album_year = &album.id.year; album_year = item.album_year,
let album_title = &album.id.title; album_title = item.album_title,
track_number = item.track_number,
for track in album.tracks.iter() { track_title = item.track_title,
let track_number = &track.number; track_artist = item.track_artist.join("; "),
let track_title = &track.title; track_format = match item.track_format {
let track_artist = &track.artist.join("; ");
let track_format = match track.quality.format {
Format::Flac => TRACK_FORMAT_FLAC, Format::Flac => TRACK_FORMAT_FLAC,
Format::Mp3 => TRACK_FORMAT_MP3, Format::Mp3 => TRACK_FORMAT_MP3,
}; },
let track_bitrate = track.quality.bitrate; track_bitrate = item.track_bitrate,
sep = LIST_FORMAT_SEPARATOR,
strings.push(format!( )
"{album_artist}{0}{album_year}{0}{album_title}{0}\
{track_number}{0}{track_title}{0}\
{track_artist}{0}{track_format}{0}{track_bitrate}kbps",
LIST_FORMAT_SEPARATOR,
));
}
} }
strings fn items_to_beets_strings(items: &[Item]) -> Vec<String> {
}
fn artists_to_beets_string(artists: &[Artist]) -> Vec<String> {
let mut strings = vec![]; let mut strings = vec![];
for artist in artists.iter() { for item in items.iter() {
strings.append(&mut artist_to_beets_string(artist)); strings.push(item_to_beets_string(item));
} }
strings strings
} }
@ -267,72 +256,15 @@ mod tests {
let mut beets = BeetsLibrary::new(executor); let mut beets = BeetsLibrary::new(executor);
let output = beets.list(&Query::new()).unwrap(); let output = beets.list(&Query::new()).unwrap();
let expected: Vec<Artist> = vec![]; let expected: Vec<Item> = vec![];
assert_eq!(output, expected); assert_eq!(output, expected);
} }
#[test] #[test]
fn test_list_ordered() { fn test_list() {
let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()]; let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()];
let expected = COLLECTION.to_owned(); let expected = artists_to_items(&COLLECTION);
let result = Ok(artists_to_beets_string(&expected)); let result = Ok(items_to_beets_strings(&expected));
let mut executor = MockIBeetsLibraryExecutor::new();
executor
.expect_exec()
.with(predicate::eq(arguments))
.times(1)
.return_once(|_| result);
let mut beets = BeetsLibrary::new(executor);
let output = beets.list(&Query::new()).unwrap();
assert_eq!(output, expected);
}
#[test]
fn test_list_unordered() {
let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()];
let mut expected = COLLECTION.to_owned();
let mut output = artists_to_beets_string(&expected);
let last = output.len() - 1;
output.swap(0, last);
let result = Ok(output);
// Putting the last track first will make the entire artist come first in the output.
expected.rotate_right(1);
// Same applies to that artists' albums.
expected[0].albums.rotate_right(1);
// Same applies to that album's tracks.
expected[0].albums[0].tracks.rotate_right(1);
// And the original first album's (now the first album of the second artist) tracks first
// track comes last.
expected[1].albums[0].tracks.rotate_left(1);
let mut executor = MockIBeetsLibraryExecutor::new();
executor
.expect_exec()
.with(predicate::eq(arguments))
.times(1)
.return_once(|_| result);
let mut beets = BeetsLibrary::new(executor);
let output = beets.list(&Query::new()).unwrap();
assert_eq!(output, expected);
}
#[test]
fn test_list_album_title_year_clash() {
let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()];
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();
let output = artists_to_beets_string(&expected);
let result = Ok(output);
let mut executor = MockIBeetsLibraryExecutor::new(); let mut executor = MockIBeetsLibraryExecutor::new();
executor executor
@ -378,15 +310,15 @@ mod tests {
let mut beets = BeetsLibrary::new(executor); let mut beets = BeetsLibrary::new(executor);
let output = beets.list(&query).unwrap(); let output = beets.list(&query).unwrap();
let expected: Vec<Artist> = vec![]; let expected: Vec<Item> = vec![];
assert_eq!(output, expected); assert_eq!(output, expected);
} }
#[test] #[test]
fn invalid_data_split() { fn invalid_data_split() {
let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()]; let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()];
let expected = COLLECTION.to_owned(); let expected = artists_to_items(&COLLECTION);
let mut output = artists_to_beets_string(&expected); let mut output = items_to_beets_strings(&expected);
let invalid_string = output[2] let invalid_string = output[2]
.split(LIST_FORMAT_SEPARATOR) .split(LIST_FORMAT_SEPARATOR)
.map(|s| s.to_owned()) .map(|s| s.to_owned())
@ -411,8 +343,8 @@ mod tests {
#[test] #[test]
fn invalid_data_format() { fn invalid_data_format() {
let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()]; let arguments = vec!["ls".to_string(), LIST_FORMAT_ARG.to_string()];
let expected = COLLECTION.to_owned(); let expected = artists_to_items(&COLLECTION);
let mut output = artists_to_beets_string(&expected); let mut output = items_to_beets_strings(&expected);
let mut invalid_string = output[2] let mut invalid_string = output[2]
.split(LIST_FORMAT_SEPARATOR) .split(LIST_FORMAT_SEPARATOR)
.map(|s| s.to_owned()) .map(|s| s.to_owned())

View File

@ -18,6 +18,7 @@ pub trait ILibrary {
} }
/// An item from the library. An item corresponds to an individual file (usually a single track). /// An item from the library. An item corresponds to an individual file (usually a single track).
#[derive(Debug, PartialEq, Eq)]
pub struct Item { pub struct Item {
pub album_artist: String, pub album_artist: String,
pub album_year: u32, pub album_year: u32,

View File

@ -9,7 +9,7 @@ use once_cell::sync::Lazy;
use musichoard::{ use musichoard::{
library::{ library::{
beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary}, beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary},
Field, ILibrary, Query, Field, ILibrary, Item, Query,
}, },
Artist, Artist,
}; };
@ -32,6 +32,35 @@ static BEETS_TEST_CONFIG: Lazy<Arc<Mutex<BeetsLibrary<BeetsLibraryProcessExecuto
))) )))
}); });
fn artist_to_items(artist: &Artist) -> Vec<Item> {
let mut items = vec![];
for album in artist.albums.iter() {
for track in album.tracks.iter() {
items.push(Item {
album_artist: artist.id.name.clone(),
album_year: album.id.year,
album_title: album.id.title.clone(),
track_number: track.number,
track_title: track.title.clone(),
track_artist: track.artist.clone(),
track_format: track.quality.format,
track_bitrate: track.quality.bitrate,
});
}
}
items
}
fn artists_to_items(artists: &[Artist]) -> Vec<Item> {
let mut items = vec![];
for artist in artists.iter() {
items.append(&mut artist_to_items(artist));
}
items
}
#[test] #[test]
fn test_no_config_list() { fn test_no_config_list() {
let beets_arc = BEETS_EMPTY_CONFIG.clone(); let beets_arc = BEETS_EMPTY_CONFIG.clone();
@ -39,7 +68,7 @@ fn test_no_config_list() {
let output = beets.list(&Query::new()).unwrap(); let output = beets.list(&Query::new()).unwrap();
let expected: Vec<Artist> = vec![]; let expected: Vec<Item> = vec![];
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -61,7 +90,7 @@ fn test_full_list() {
let output = beets.list(&Query::new()).unwrap(); let output = beets.list(&Query::new()).unwrap();
let expected: Vec<Artist> = COLLECTION.to_owned(); let expected: Vec<Item> = artists_to_items(&COLLECTION);
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -74,7 +103,7 @@ fn test_album_artist_query() {
.list(Query::new().include(Field::AlbumArtist(String::from("Аркона")))) .list(Query::new().include(Field::AlbumArtist(String::from("Аркона"))))
.unwrap(); .unwrap();
let expected: Vec<Artist> = COLLECTION[0..1].to_owned(); let expected: Vec<Item> = artists_to_items(&COLLECTION[0..1]);
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -87,7 +116,7 @@ fn test_album_title_query() {
.list(&Query::new().include(Field::AlbumTitle(String::from("Slovo")))) .list(&Query::new().include(Field::AlbumTitle(String::from("Slovo"))))
.unwrap(); .unwrap();
let expected: Vec<Artist> = COLLECTION[0..1].to_owned(); let expected: Vec<Item> = artists_to_items(&COLLECTION[0..1]);
assert_eq!(output, expected); assert_eq!(output, expected);
} }
@ -100,6 +129,6 @@ fn test_exclude_query() {
.list(&Query::new().exclude(Field::AlbumArtist(String::from("Аркона")))) .list(&Query::new().exclude(Field::AlbumArtist(String::from("Аркона"))))
.unwrap(); .unwrap();
let expected: Vec<Artist> = COLLECTION[1..].to_owned(); let expected: Vec<Item> = artists_to_items(&COLLECTION[1..]);
assert_eq!(output, expected); assert_eq!(output, expected);
} }