Make database loads explicit by the MH user
Some checks failed
Cargo CI / Build and Test (pull_request) Successful in 2m38s
Cargo CI / Lint (pull_request) Failing after 1m10s

This commit is contained in:
Wojciech Kozlowski 2025-01-05 10:45:38 +01:00
parent d2e3fd4cd8
commit 180a2edd83
6 changed files with 44 additions and 55 deletions

View File

@ -249,9 +249,9 @@ fn main() {
let db = JsonDatabase::new(JsonDatabaseFileBackend::new(&opt.database_file_path)); let db = JsonDatabase::new(JsonDatabaseFileBackend::new(&opt.database_file_path));
let mut music_hoard = MusicHoardBuilder::default() let mut music_hoard = MusicHoardBuilder::default().set_database(db).build();
.set_database(db) music_hoard
.build() .reload_database()
.expect("failed to initialise MusicHoard"); .expect("failed to load MusicHoard database");
opt.command.handle(&mut music_hoard); opt.command.handle(&mut music_hoard);
} }

View File

@ -1,8 +1,6 @@
use crate::core::{ use crate::core::{
interface::{database::IDatabase, library::ILibrary}, interface::{database::IDatabase, library::ILibrary},
musichoard::{ musichoard::{CollectionFilter, MusicHoard, NoDatabase, NoLibrary},
database::IMusicHoardDatabase, CollectionFilter, Error, MusicHoard, NoDatabase, NoLibrary,
},
}; };
/// Builder for [`MusicHoard`]. Its purpose is to make it easier to set various combinations of /// Builder for [`MusicHoard`]. Its purpose is to make it easier to set various combinations of
@ -99,15 +97,15 @@ impl<Library: ILibrary> MusicHoard<NoDatabase, Library> {
impl<Database: IDatabase> MusicHoardBuilder<Database, NoLibrary> { impl<Database: IDatabase> MusicHoardBuilder<Database, NoLibrary> {
/// Build [`MusicHoard`] with the currently set library and database. /// Build [`MusicHoard`] with the currently set library and database.
pub fn build(self) -> Result<MusicHoard<Database, NoLibrary>, Error> { pub fn build(self) -> MusicHoard<Database, NoLibrary> {
MusicHoard::database(self.database) MusicHoard::database(self.database)
} }
} }
impl<Database: IDatabase> MusicHoard<Database, NoLibrary> { impl<Database: IDatabase> MusicHoard<Database, NoLibrary> {
/// Create a new [`MusicHoard`] with the provided [`IDatabase`] and no library. /// Create a new [`MusicHoard`] with the provided [`IDatabase`] and no library.
pub fn database(database: Database) -> Result<Self, Error> { pub fn database(database: Database) -> Self {
let mut mh = MusicHoard { MusicHoard {
filter: CollectionFilter::default(), filter: CollectionFilter::default(),
filtered: vec![], filtered: vec![],
collection: vec![], collection: vec![],
@ -115,23 +113,21 @@ impl<Database: IDatabase> MusicHoard<Database, NoLibrary> {
database, database,
library: NoLibrary, library: NoLibrary,
library_cache: vec![], library_cache: vec![],
}; }
mh.reload_database()?;
Ok(mh)
} }
} }
impl<Database: IDatabase, Library: ILibrary> MusicHoardBuilder<Database, Library> { impl<Database: IDatabase, Library: ILibrary> MusicHoardBuilder<Database, Library> {
/// Build [`MusicHoard`] with the currently set library and database. /// Build [`MusicHoard`] with the currently set library and database.
pub fn build(self) -> Result<MusicHoard<Database, Library>, Error> { pub fn build(self) -> MusicHoard<Database, Library> {
MusicHoard::new(self.database, self.library) MusicHoard::new(self.database, self.library)
} }
} }
impl<Database: IDatabase, Library: ILibrary> MusicHoard<Database, Library> { impl<Database: IDatabase, Library: ILibrary> MusicHoard<Database, Library> {
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and [`IDatabase`]. /// Create a new [`MusicHoard`] with the provided [`ILibrary`] and [`IDatabase`].
pub fn new(database: Database, library: Library) -> Result<Self, Error> { pub fn new(database: Database, library: Library) -> Self {
let mut mh = MusicHoard { MusicHoard {
filter: CollectionFilter::default(), filter: CollectionFilter::default(),
filtered: vec![], filtered: vec![],
collection: vec![], collection: vec![],
@ -139,18 +135,16 @@ impl<Database: IDatabase, Library: ILibrary> MusicHoard<Database, Library> {
database, database,
library, library,
library_cache: vec![], library_cache: vec![],
}; }
mh.reload_database()?;
Ok(mh)
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::core::{ use crate::{core::{
interface::{database::NullDatabase, library::NullLibrary}, interface::{database::NullDatabase, library::NullLibrary},
musichoard::library::IMusicHoardLibrary, musichoard::library::IMusicHoardLibrary,
}; }, IMusicHoardDatabase};
use super::*; use super::*;
@ -177,8 +171,7 @@ mod tests {
fn no_library_with_database() { fn no_library_with_database() {
let mut mh = MusicHoardBuilder::default() let mut mh = MusicHoardBuilder::default()
.set_database(NullDatabase) .set_database(NullDatabase)
.build() .build();
.unwrap();
assert!(mh.reload_database().is_ok()); assert!(mh.reload_database().is_ok());
} }
@ -187,8 +180,7 @@ mod tests {
let mut mh = MusicHoardBuilder::default() let mut mh = MusicHoardBuilder::default()
.set_library(NullLibrary) .set_library(NullLibrary)
.set_database(NullDatabase) .set_database(NullDatabase)
.build() .build();
.unwrap();
assert!(mh.rescan_library().is_ok()); assert!(mh.rescan_library().is_ok());
assert!(mh.reload_database().is_ok()); assert!(mh.reload_database().is_ok());
} }

View File

@ -504,7 +504,8 @@ mod tests {
.with(predicate::eq(collection.clone())) .with(predicate::eq(collection.clone()))
.returning(|_| Ok(())); .returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
assert_eq!(music_hoard.collection, collection); assert_eq!(music_hoard.collection, collection);
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
@ -523,11 +524,10 @@ mod tests {
#[test] #[test]
fn artist_sort_set_clear() { fn artist_sort_set_clear() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(4).returning(|_| Ok(())); database.expect_save().times(4).returning(|_| Ok(()));
type MH = MusicHoard<MockIDatabase, NoLibrary>; type MH = MusicHoard<MockIDatabase, NoLibrary>;
let mut music_hoard: MH = MusicHoard::database(database).unwrap(); let mut music_hoard: MH = MusicHoard::database(database);
let artist_1_id = ArtistId::new("the artist"); let artist_1_id = ArtistId::new("the artist");
let artist_1_sort = String::from("artist, the"); let artist_1_sort = String::from("artist, the");
@ -574,9 +574,8 @@ mod tests {
#[test] #[test]
fn collection_error() { fn collection_error() {
let mut database = MockIDatabase::new(); let database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![])); let mut music_hoard = MusicHoard::database(database);
let mut music_hoard = MusicHoard::database(database).unwrap();
let artist_id = ArtistId::new("an artist"); let artist_id = ArtistId::new("an artist");
let actual_err = music_hoard let actual_err = music_hoard
@ -591,12 +590,11 @@ mod tests {
#[test] #[test]
fn set_clear_artist_mb_ref() { fn set_clear_artist_mb_ref() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(3).returning(|_| Ok(())); database.expect_save().times(3).returning(|_| Ok(()));
let mut artist_id = ArtistId::new("an artist"); let mut artist_id = ArtistId::new("an artist");
let artist_id_2 = ArtistId::new("another artist"); let artist_id_2 = ArtistId::new("another artist");
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
@ -637,12 +635,11 @@ mod tests {
#[test] #[test]
fn set_clear_artist_info() { fn set_clear_artist_info() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(3).returning(|_| Ok(())); database.expect_save().times(3).returning(|_| Ok(()));
let artist_id = ArtistId::new("an artist"); let artist_id = ArtistId::new("an artist");
let artist_id_2 = ArtistId::new("another artist"); let artist_id_2 = ArtistId::new("another artist");
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
@ -681,12 +678,11 @@ mod tests {
#[test] #[test]
fn add_to_remove_from_property() { fn add_to_remove_from_property() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(3).returning(|_| Ok(())); database.expect_save().times(3).returning(|_| Ok(()));
let artist_id = ArtistId::new("an artist"); let artist_id = ArtistId::new("an artist");
let artist_id_2 = ArtistId::new("another artist"); let artist_id_2 = ArtistId::new("another artist");
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
@ -730,12 +726,11 @@ mod tests {
#[test] #[test]
fn set_clear_property() { fn set_clear_property() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(3).returning(|_| Ok(())); database.expect_save().times(3).returning(|_| Ok(()));
let artist_id = ArtistId::new("an artist"); let artist_id = ArtistId::new("an artist");
let artist_id_2 = ArtistId::new("another artist"); let artist_id_2 = ArtistId::new("another artist");
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
@ -805,7 +800,8 @@ mod tests {
.with(predicate::eq(collection.clone())) .with(predicate::eq(collection.clone()))
.returning(|_| Ok(())); .returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
assert_eq!(music_hoard.collection, collection); assert_eq!(music_hoard.collection, collection);
assert!(music_hoard assert!(music_hoard
@ -844,7 +840,8 @@ mod tests {
.return_once(|| Ok(database_result)); .return_once(|| Ok(database_result));
database.expect_save().times(2).returning(|_| Ok(())); database.expect_save().times(2).returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
let album = &music_hoard.collection[0].albums[0]; let album = &music_hoard.collection[0].albums[0];
assert_eq!(album.meta.id.mb_ref, AlbumMbRef::None); assert_eq!(album.meta.id.mb_ref, AlbumMbRef::None);
@ -902,7 +899,8 @@ mod tests {
.return_once(|| Ok(database_result)); .return_once(|| Ok(database_result));
database.expect_save().times(2).returning(|_| Ok(())); database.expect_save().times(2).returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
assert_eq!(music_hoard.collection[0].albums[0].meta.seq, AlbumSeq(0)); assert_eq!(music_hoard.collection[0].albums[0].meta.seq, AlbumSeq(0));
// Seting seq on an album not belonging to the artist is an error. // Seting seq on an album not belonging to the artist is an error.
@ -941,7 +939,8 @@ mod tests {
.times(1) .times(1)
.return_once(|| Ok(database_result)); .return_once(|| Ok(database_result));
database.expect_save().times(2).returning(|_| Ok(())); database.expect_save().times(2).returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
let meta = &music_hoard.collection[0].albums[0].meta; let meta = &music_hoard.collection[0].albums[0].meta;
assert_eq!(meta.info.primary_type, None); assert_eq!(meta.info.primary_type, None);
@ -986,7 +985,8 @@ mod tests {
.times(1) .times(1)
.return_once(|| Ok(FULL_COLLECTION.to_owned())); .return_once(|| Ok(FULL_COLLECTION.to_owned()));
let music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
assert_eq!(music_hoard.get_collection(), &*FULL_COLLECTION); assert_eq!(music_hoard.get_collection(), &*FULL_COLLECTION);
} }
@ -1002,7 +1002,8 @@ mod tests {
.times(1) .times(1)
.return_once(|| database_result); .return_once(|| database_result);
let actual_err = MusicHoard::database(database).unwrap_err(); let mut music_hoard = MusicHoard::database(database);
let actual_err = music_hoard.reload_database().unwrap_err();
let expected_err = Error::DatabaseError( let expected_err = Error::DatabaseError(
database::LoadError::IoError(String::from("I/O error")).to_string(), database::LoadError::IoError(String::from("I/O error")).to_string(),
); );
@ -1023,7 +1024,8 @@ mod tests {
.times(1) .times(1)
.return_once(|_: &Collection| database_result); .return_once(|_: &Collection| database_result);
let mut music_hoard = MusicHoard::database(database).unwrap(); let mut music_hoard = MusicHoard::database(database);
music_hoard.reload_database().unwrap();
let actual_err = music_hoard let actual_err = music_hoard
.add_artist(ArtistId::new("an artist")) .add_artist(ArtistId::new("an artist"))

View File

@ -157,11 +157,6 @@ mod tests {
// The database contents are not relevant in this test. // The database contents are not relevant in this test.
let mut seq = Sequence::new(); let mut seq = Sequence::new();
database
.expect_load()
.times(1)
.in_sequence(&mut seq)
.returning(|| Ok(vec![]));
database database
.expect_load() .expect_load()
.times(1) .times(1)
@ -174,7 +169,7 @@ mod tests {
.in_sequence(&mut seq) .in_sequence(&mut seq)
.return_once(|_| Ok(())); .return_once(|_| Ok(()));
let mut music_hoard = MusicHoard::new(database, library).unwrap(); let mut music_hoard = MusicHoard::new(database, library);
music_hoard.rescan_library().unwrap(); music_hoard.rescan_library().unwrap();
assert_eq!(music_hoard.get_collection(), &*LIBRARY_COLLECTION); assert_eq!(music_hoard.get_collection(), &*LIBRARY_COLLECTION);

View File

@ -97,7 +97,7 @@ fn default_filter() -> CollectionFilter {
fn with<Database: IDatabase + 'static, Library: ILibrary + 'static>( fn with<Database: IDatabase + 'static, Library: ILibrary + 'static>(
builder: MusicHoardBuilder<Database, Library>, builder: MusicHoardBuilder<Database, Library>,
) { ) {
let mut music_hoard = builder.build().expect("failed to initialise MusicHoard"); let mut music_hoard = builder.build();
music_hoard.set_filter(default_filter()); music_hoard.set_filter(default_filter());
// Initialize the terminal user interface. // Initialize the terminal user interface.

View File

@ -31,7 +31,7 @@ fn merge_library_then_database() {
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
let database = JsonDatabase::new(backend); let database = JsonDatabase::new(backend);
let mut music_hoard = MusicHoard::new(database, library).unwrap(); let mut music_hoard = MusicHoard::new(database, library);
music_hoard.rescan_library().unwrap(); music_hoard.rescan_library().unwrap();
music_hoard.reload_database().unwrap(); music_hoard.reload_database().unwrap();
@ -54,7 +54,7 @@ fn merge_database_then_library() {
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
let database = JsonDatabase::new(backend); let database = JsonDatabase::new(backend);
let mut music_hoard = MusicHoard::new(database, library).unwrap(); let mut music_hoard = MusicHoard::new(database, library);
music_hoard.reload_database().unwrap(); music_hoard.reload_database().unwrap();
music_hoard.rescan_library().unwrap(); music_hoard.rescan_library().unwrap();