From 634a17c2bf8031a3d635c834466e067a07d84c7b Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 07:43:46 +0100 Subject: [PATCH] Add load test --- src/external/database/serde/common.rs | 8 +-- src/external/database/serde/deserialize.rs | 6 +- src/external/database/sql/backend.rs | 58 ++++++++++------ src/external/database/sql/mod.rs | 77 +++++++++++++++------- 4 files changed, 98 insertions(+), 51 deletions(-) diff --git a/src/external/database/serde/common.rs b/src/external/database/serde/common.rs index 07f085b..8a2207d 100644 --- a/src/external/database/serde/common.rs +++ b/src/external/database/serde/common.rs @@ -13,7 +13,7 @@ pub enum AlbumLibIdDef { None, } -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct SerdeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); impl From for AlbumLibId { @@ -36,7 +36,7 @@ pub struct AlbumDateDef { day: Option, } -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct SerdeAlbumDate(#[serde(with = "AlbumDateDef")] pub AlbumDate); impl From for AlbumDate { @@ -69,7 +69,7 @@ pub enum AlbumPrimaryTypeDef { Other, } -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct SerdeAlbumPrimaryType(#[serde(with = "AlbumPrimaryTypeDef")] AlbumPrimaryType); impl From for AlbumPrimaryType { @@ -101,7 +101,7 @@ pub enum AlbumSecondaryTypeDef { FieldRecording, } -#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct SerdeAlbumSecondaryType(#[serde(with = "AlbumSecondaryTypeDef")] AlbumSecondaryType); impl From for AlbumSecondaryType { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 1ce3da6..bd1db1a 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -30,7 +30,7 @@ impl From for Collection { } } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize)] pub struct DeserializeArtist { pub name: String, pub sort: Option, @@ -39,7 +39,7 @@ pub struct DeserializeArtist { pub albums: Vec, } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize)] pub struct DeserializeAlbum { pub title: String, pub lib_id: SerdeAlbumLibId, @@ -50,7 +50,7 @@ pub struct DeserializeAlbum { pub secondary_types: Vec, } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize)] pub struct DeserializeMbRefOption(#[serde(with = "MbRefOptionDef")] MbRefOption); #[derive(Clone, Debug)] diff --git a/src/external/database/sql/backend.rs b/src/external/database/sql/backend.rs index ad70b86..9051ae9 100644 --- a/src/external/database/sql/backend.rs +++ b/src/external/database/sql/backend.rs @@ -191,13 +191,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { let mut artists = vec![]; while let Some(row) = Self::next_row(&mut rows)? { - artists.push(DeserializeArtist { - name: Self::get_value(row, 0)?, - sort: Self::get_value(row, 1)?, - musicbrainz: serde_json::from_str(&Self::get_value::(row, 2)?)?, - properties: serde_json::from_str(&Self::get_value::(row, 3)?)?, - albums: vec![], - }); + artists.push(row.try_into()?); } Ok(artists) @@ -235,21 +229,45 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { let mut albums = vec![]; while let Some(row) = Self::next_row(&mut rows)? { - albums.push(DeserializeAlbum { - title: Self::get_value(row, 0)?, - lib_id: serde_json::from_str(&Self::get_value::(row, 1)?)?, - date: SerdeAlbumDate(AlbumDate::new( - Self::get_value(row, 2)?, - Self::get_value(row, 3)?, - Self::get_value(row, 4)?, - )), - seq: Self::get_value(row, 5)?, - musicbrainz: serde_json::from_str(&Self::get_value::(row, 6)?)?, - primary_type: serde_json::from_str(&Self::get_value::(row, 7)?)?, - secondary_types: serde_json::from_str(&Self::get_value::(row, 8)?)?, - }); + albums.push(row.try_into()?); } Ok(albums) } } + +impl TryFrom<&Row<'_>> for DeserializeArtist { + type Error = Error; + + fn try_from(row: &Row<'_>) -> Result { + type Backend<'a> = SqlTransactionSqliteBackend<'a>; + Ok(DeserializeArtist { + name: Backend::get_value(row, 0)?, + sort: Backend::get_value(row, 1)?, + musicbrainz: serde_json::from_str(&Backend::get_value::(row, 2)?)?, + properties: serde_json::from_str(&Backend::get_value::(row, 3)?)?, + albums: vec![], + }) + } +} + +impl TryFrom<&Row<'_>> for DeserializeAlbum { + type Error = Error; + + fn try_from(row: &Row<'_>) -> Result { + type Backend<'a> = SqlTransactionSqliteBackend<'a>; + Ok(DeserializeAlbum { + title: Backend::get_value(row, 0)?, + lib_id: serde_json::from_str(&Backend::get_value::(row, 1)?)?, + date: SerdeAlbumDate(AlbumDate::new( + Backend::get_value(row, 2)?, + Backend::get_value(row, 3)?, + Backend::get_value(row, 4)?, + )), + seq: Backend::get_value(row, 5)?, + musicbrainz: serde_json::from_str(&Backend::get_value::(row, 6)?)?, + primary_type: serde_json::from_str(&Backend::get_value::(row, 7)?)?, + secondary_types: serde_json::from_str(&Backend::get_value::(row, 8)?)?, + }) + } +} diff --git a/src/external/database/sql/mod.rs b/src/external/database/sql/mod.rs index d442002..559c9be 100644 --- a/src/external/database/sql/mod.rs +++ b/src/external/database/sql/mod.rs @@ -203,28 +203,26 @@ impl ISqlDatabaseBackend<'conn>> IDatabase for SqlDatabase #[cfg(test)] mod tests { - // use std::collections::HashMap; + use std::fs; use std::collections::VecDeque; use mockall::{predicate, Sequence}; + use rusqlite::Connection; - use crate::core::{ - // collection::{artist::Artist, Collection}, - testmod::FULL_COLLECTION, - }; + use crate::core::{collection::Collection, testmod::FULL_COLLECTION}; use super::*; - // fn expected() -> Collection { - // let mut expected = FULL_COLLECTION.to_owned(); - // for artist in expected.iter_mut() { - // for album in artist.albums.iter_mut() { - // album.tracks.clear(); - // } - // } - // expected - // } + fn expected() -> Collection { + let mut expected = FULL_COLLECTION.to_owned(); + for artist in expected.iter_mut() { + for album in artist.albums.iter_mut() { + album.tracks.clear(); + } + } + expected + } struct SqlDatabaseTestBackend { pub txs: VecDeque, @@ -323,19 +321,50 @@ mod tests { assert!(database(VecDeque::from([tx])).save(&write_data).is_ok()); } - // #[test] - // fn load() { - // let expected = expected(); - // let result = Ok(DATABASE_JSON.to_owned()); - // eprintln!("{DATABASE_JSON}"); + #[test] + fn load() { + let path = fs::canonicalize("./src/external/database/sql/testmod.db").unwrap(); + let db = Connection::open(path).unwrap(); - // let mut backend = MockISqlDatabaseBackend::new(); - // backend.expect_read().times(1).return_once(|| result); + let mut tx = MockISqlTransactionBackend::new(); + let mut seq = Sequence::new(); - // let read_data: Vec = SqlDatabase::new(backend).load().unwrap(); + let version_query = "SELECT value FROM database_metadata WHERE name = 'version'"; + let version: String = db.query_row(&version_query, (), |row| row.get(0)).unwrap(); + then!(tx, seq, expect_select_database_version).return_once(|| Ok(Some(version))); - // assert_eq!(read_data, expected); - // } + let artist_query = "SELECT name, sort, mbid, properties FROM artists"; + let mut artist_query = db.prepare(&artist_query).unwrap(); + let mut artist_rows = artist_query.query(()).unwrap(); + let mut de_artists = vec![]; + while let Some(row) = artist_rows.next().unwrap() { + de_artists.push(row.try_into().unwrap()); + } + let artists: Collection = de_artists.iter().cloned().map(Into::into).collect(); + then!(tx, seq, expect_select_all_artists).return_once(|| Ok(de_artists)); + + for artist in artists.iter() { + let album_query = + "SELECT title, lib_id, year, month, day, seq, mbid, primary_type, secondary_types + FROM albums WHERE artist_name = ?1"; + let mut album_query = db.prepare(&album_query).unwrap(); + let mut album_rows = album_query.query([artist.meta.id.name.clone()]).unwrap(); + let mut de_albums = vec![]; + while let Some(row) = album_rows.next().unwrap() { + de_albums.push(row.try_into().unwrap()); + } + then!(tx, seq, expect_select_artist_albums) + .with(predicate::eq(artist.meta.id.name.clone())) + .return_once(|_| Ok(de_albums)); + } + + then0!(tx, seq, expect_commit); + + let read_data = database(VecDeque::from([tx])).load().unwrap(); + + let expected = expected(); + assert_eq!(read_data, expected); + } // #[test] // fn reverse() {