Complete implementation
This commit is contained in:
parent
a9782b74cc
commit
0fe6fe0be1
@ -11,7 +11,7 @@ use crate::core::collection::{self, Collection};
|
|||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait IDatabase {
|
pub trait IDatabase {
|
||||||
/// Load collection from the database.
|
/// Load collection from the database.
|
||||||
fn load(&self) -> Result<Collection, LoadError>;
|
fn load(&mut self) -> Result<Collection, LoadError>;
|
||||||
|
|
||||||
/// Save collection to the database.
|
/// Save collection to the database.
|
||||||
fn save(&mut self, collection: &Collection) -> Result<(), SaveError>;
|
fn save(&mut self, collection: &Collection) -> Result<(), SaveError>;
|
||||||
@ -21,7 +21,7 @@ pub trait IDatabase {
|
|||||||
pub struct NullDatabase;
|
pub struct NullDatabase;
|
||||||
|
|
||||||
impl IDatabase for NullDatabase {
|
impl IDatabase for NullDatabase {
|
||||||
fn load(&self) -> Result<Collection, LoadError> {
|
fn load(&mut self) -> Result<Collection, LoadError> {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn null_database_load() {
|
fn null_database_load() {
|
||||||
let database = NullDatabase;
|
let mut database = NullDatabase;
|
||||||
assert!(database.load().unwrap().is_empty());
|
assert!(database.load().unwrap().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ impl<JDB: IJsonDatabaseBackend> JsonDatabase<JDB> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<JDB: IJsonDatabaseBackend> IDatabase for JsonDatabase<JDB> {
|
impl<JDB: IJsonDatabaseBackend> IDatabase for JsonDatabase<JDB> {
|
||||||
fn load(&self) -> Result<Collection, LoadError> {
|
fn load(&mut self) -> Result<Collection, LoadError> {
|
||||||
let serialized = self.backend.read()?;
|
let serialized = self.backend.read()?;
|
||||||
let database: DeserializeDatabase = serde_json::from_str(&serialized)?;
|
let database: DeserializeDatabase = serde_json::from_str(&serialized)?;
|
||||||
Ok(database.into())
|
Ok(database.into())
|
||||||
|
@ -32,22 +32,22 @@ impl From<DeserializeDatabase> for Collection {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct DeserializeArtist {
|
pub struct DeserializeArtist {
|
||||||
name: String,
|
pub name: String,
|
||||||
sort: Option<String>,
|
pub sort: Option<String>,
|
||||||
musicbrainz: DeserializeMbRefOption,
|
pub musicbrainz: DeserializeMbRefOption,
|
||||||
properties: HashMap<String, Vec<String>>,
|
pub properties: HashMap<String, Vec<String>>,
|
||||||
albums: Vec<DeserializeAlbum>,
|
pub albums: Vec<DeserializeAlbum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct DeserializeAlbum {
|
pub struct DeserializeAlbum {
|
||||||
title: String,
|
pub title: String,
|
||||||
lib_id: SerdeAlbumLibId,
|
pub lib_id: SerdeAlbumLibId,
|
||||||
date: SerdeAlbumDate,
|
pub date: SerdeAlbumDate,
|
||||||
seq: u8,
|
pub seq: u8,
|
||||||
musicbrainz: DeserializeMbRefOption,
|
pub musicbrainz: DeserializeMbRefOption,
|
||||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
pub primary_type: Option<SerdeAlbumPrimaryType>,
|
||||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
pub secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -110,6 +110,8 @@ impl<'de> Deserialize<'de> for DeserializeMbid {
|
|||||||
|
|
||||||
impl From<DeserializeArtist> for Artist {
|
impl From<DeserializeArtist> for Artist {
|
||||||
fn from(artist: DeserializeArtist) -> Self {
|
fn from(artist: DeserializeArtist) -> Self {
|
||||||
|
let mut albums: Vec<Album> = artist.albums.into_iter().map(Into::into).collect();
|
||||||
|
albums.sort_unstable();
|
||||||
Artist {
|
Artist {
|
||||||
meta: ArtistMeta {
|
meta: ArtistMeta {
|
||||||
id: ArtistId {
|
id: ArtistId {
|
||||||
@ -121,7 +123,7 @@ impl From<DeserializeArtist> for Artist {
|
|||||||
properties: artist.properties,
|
properties: artist.properties,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
albums: artist.albums.into_iter().map(Into::into).collect(),
|
albums,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//! Helper module for backends that can use serde for (de)serialisation.
|
//! Helper module for backends that can use serde for (de)serialisation.
|
||||||
|
|
||||||
mod common;
|
pub mod common;
|
||||||
pub mod deserialize;
|
pub mod deserialize;
|
||||||
pub mod serialize;
|
pub mod serialize;
|
||||||
|
@ -2,11 +2,20 @@
|
|||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rusqlite::{self, CachedStatement, Connection, Params, Statement, Transaction};
|
use rusqlite::{
|
||||||
|
self, types::FromSql, CachedStatement, Connection, Params, Row, Rows, Statement, Transaction,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::external::database::{
|
use crate::{
|
||||||
serde::serialize::{SerializeAlbum, SerializeArtist, SerializeDatabase},
|
collection::album::AlbumDate,
|
||||||
sql::{Error, ISqlDatabaseBackend, ISqlTransactionBackend},
|
external::database::{
|
||||||
|
serde::{
|
||||||
|
common::SerdeAlbumDate,
|
||||||
|
deserialize::{DeserializeAlbum, DeserializeArtist, DeserializeDatabase},
|
||||||
|
serialize::{SerializeAlbum, SerializeArtist, SerializeDatabase},
|
||||||
|
},
|
||||||
|
sql::{Error, ISqlDatabaseBackend, ISqlTransactionBackend},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// SQLite database backend that uses SQLite as the implementation.
|
/// SQLite database backend that uses SQLite as the implementation.
|
||||||
@ -45,6 +54,21 @@ impl<'conn> SqlTransactionSqliteBackend<'conn> {
|
|||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| Error::ExecError(err.to_string()))
|
.map_err(|err| Error::ExecError(err.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn query<'s, P: Params>(stmt: &'s mut Statement, params: P) -> Result<Rows<'s>, Error> {
|
||||||
|
stmt.query(params)
|
||||||
|
.map_err(|err| Error::ExecError(err.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_row<'r, 's>(rows: &'r mut Rows<'s>) -> Result<Option<&'r Row<'s>>, Error> {
|
||||||
|
rows.next()
|
||||||
|
.map_err(|err| Error::SerDeError(err.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value<T: FromSql>(row: &Row<'_>, idx: usize) -> Result<T, Error> {
|
||||||
|
row.get(idx)
|
||||||
|
.map_err(|err| Error::SerDeError(err.to_string()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<serde_json::Error> for Error {
|
impl From<serde_json::Error> for Error {
|
||||||
@ -116,7 +140,7 @@ impl<'conn> ISqlTransactionBackend for SqlTransactionSqliteBackend<'conn> {
|
|||||||
seq INT NOT NULL,
|
seq INT NOT NULL,
|
||||||
primary_type JSON NOT NULL DEFAULT 'null',
|
primary_type JSON NOT NULL DEFAULT 'null',
|
||||||
secondary_types JSON NOT NULL DEFAULT '[]',
|
secondary_types JSON NOT NULL DEFAULT '[]',
|
||||||
FOREIGN KEY (artist_name) REFERENCES artists(name)
|
FOREIGN KEY (artist_name) REFERENCES artists(name) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||||
)",
|
)",
|
||||||
)?;
|
)?;
|
||||||
Self::execute(&mut stmt, ())
|
Self::execute(&mut stmt, ())
|
||||||
@ -138,6 +162,25 @@ impl<'conn> ISqlTransactionBackend for SqlTransactionSqliteBackend<'conn> {
|
|||||||
Self::execute(&mut stmt, ("version", version))
|
Self::execute(&mut stmt, ("version", version))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_database_version<'a>(&self) -> Result<DeserializeDatabase, Error> {
|
||||||
|
let mut stmt =
|
||||||
|
self.prepare_cached("SELECT value FROM database_metadata WHERE name = 'version'")?;
|
||||||
|
let mut rows = Self::query(&mut stmt, ())?;
|
||||||
|
|
||||||
|
match Self::next_row(&mut rows)? {
|
||||||
|
Some(row) => {
|
||||||
|
let version: String = Self::get_value(&row, 0)?;
|
||||||
|
match version.as_str() {
|
||||||
|
"V20250103" => Ok(DeserializeDatabase::V20250103(vec![])),
|
||||||
|
s @ _ => Err(Error::SerDeError(format!("unknown database version: {s}"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => Err(Error::SerDeError(String::from(
|
||||||
|
"database version is missing",
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_artist<'a>(&self, artist: &SerializeArtist<'a>) -> Result<(), Error> {
|
fn insert_artist<'a>(&self, artist: &SerializeArtist<'a>) -> Result<(), Error> {
|
||||||
let mut stmt = self.prepare_cached(
|
let mut stmt = self.prepare_cached(
|
||||||
"INSERT INTO artists (name, sort, mbid, properties)
|
"INSERT INTO artists (name, sort, mbid, properties)
|
||||||
@ -154,6 +197,24 @@ impl<'conn> ISqlTransactionBackend for SqlTransactionSqliteBackend<'conn> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_all_artists(&self) -> Result<Vec<DeserializeArtist>, Error> {
|
||||||
|
let mut stmt = self.prepare_cached("SELECT name, sort, mbid, properties FROM artists")?;
|
||||||
|
let mut rows = Self::query(&mut stmt, ())?;
|
||||||
|
|
||||||
|
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::<String>(row, 2)?)?,
|
||||||
|
properties: serde_json::from_str(&Self::get_value::<String>(row, 3)?)?,
|
||||||
|
albums: vec![],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(artists)
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_album<'a>(&self, artist_name: &str, album: &SerializeAlbum<'a>) -> Result<(), Error> {
|
fn insert_album<'a>(&self, artist_name: &str, album: &SerializeAlbum<'a>) -> Result<(), Error> {
|
||||||
let mut stmt = self.prepare_cached(
|
let mut stmt = self.prepare_cached(
|
||||||
"INSERT INTO albums (title, lib_id, mbid, artist_name,
|
"INSERT INTO albums (title, lib_id, mbid, artist_name,
|
||||||
@ -176,4 +237,31 @@ impl<'conn> ISqlTransactionBackend for SqlTransactionSqliteBackend<'conn> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_artist_albums(&self, artist_name: &str) -> Result<Vec<DeserializeAlbum>, Error> {
|
||||||
|
let mut stmt = self.prepare_cached(
|
||||||
|
"SELECT title, lib_id, year, month, day, seq, mbid, primary_type, secondary_types
|
||||||
|
FROM albums WHERE artist_name = ?1",
|
||||||
|
)?;
|
||||||
|
let mut rows = Self::query(&mut stmt, [artist_name])?;
|
||||||
|
|
||||||
|
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::<String>(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::<String>(row, 6)?)?,
|
||||||
|
primary_type: serde_json::from_str(&Self::get_value::<String>(row, 7)?)?,
|
||||||
|
secondary_types: serde_json::from_str(&Self::get_value::<String>(row, 8)?)?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(albums)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ use crate::{
|
|||||||
collection::Collection,
|
collection::Collection,
|
||||||
interface::database::{IDatabase, LoadError, SaveError},
|
interface::database::{IDatabase, LoadError, SaveError},
|
||||||
},
|
},
|
||||||
external::database::serde::serialize::{SerializeAlbum, SerializeArtist, SerializeDatabase},
|
external::database::serde::{
|
||||||
|
deserialize::{DeserializeAlbum, DeserializeArtist, DeserializeDatabase},
|
||||||
|
serialize::{SerializeAlbum, SerializeArtist, SerializeDatabase},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trait for the SQL database backend.
|
/// Trait for the SQL database backend.
|
||||||
@ -50,11 +53,20 @@ pub trait ISqlTransactionBackend {
|
|||||||
/// Set the database version.
|
/// Set the database version.
|
||||||
fn insert_database_version<'a>(&self, version: &SerializeDatabase<'a>) -> Result<(), Error>;
|
fn insert_database_version<'a>(&self, version: &SerializeDatabase<'a>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Get the database version.
|
||||||
|
fn select_database_version<'a>(&self) -> Result<DeserializeDatabase, Error>;
|
||||||
|
|
||||||
/// Insert an artist into the artist table.
|
/// Insert an artist into the artist table.
|
||||||
fn insert_artist<'a>(&self, artist: &SerializeArtist<'a>) -> Result<(), Error>;
|
fn insert_artist<'a>(&self, artist: &SerializeArtist<'a>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Get all artists from the artist table.
|
||||||
|
fn select_all_artists(&self) -> Result<Vec<DeserializeArtist>, Error>;
|
||||||
|
|
||||||
/// Insert an artist into the artist table.
|
/// Insert an artist into the artist table.
|
||||||
fn insert_album<'a>(&self, artist_name: &str, album: &SerializeAlbum<'a>) -> Result<(), Error>;
|
fn insert_album<'a>(&self, artist_name: &str, album: &SerializeAlbum<'a>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Get all albums from the album table.
|
||||||
|
fn select_artist_albums(&self, artist_name: &str) -> Result<Vec<DeserializeAlbum>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors for SQL database backend.
|
/// Errors for SQL database backend.
|
||||||
@ -95,6 +107,15 @@ impl From<Error> for SaveError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Error> for LoadError {
|
||||||
|
fn from(value: Error) -> Self {
|
||||||
|
match value {
|
||||||
|
Error::SerDeError(s) => LoadError::SerDeError(s),
|
||||||
|
_ => LoadError::IoError(value.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// SQL database.
|
/// SQL database.
|
||||||
pub struct SqlDatabase<SDB> {
|
pub struct SqlDatabase<SDB> {
|
||||||
backend: SDB,
|
backend: SDB,
|
||||||
@ -127,8 +148,21 @@ impl<SDB: for<'conn> ISqlDatabaseBackend<'conn>> SqlDatabase<SDB> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<SDB: for<'conn> ISqlDatabaseBackend<'conn>> IDatabase for SqlDatabase<SDB> {
|
impl<SDB: for<'conn> ISqlDatabaseBackend<'conn>> IDatabase for SqlDatabase<SDB> {
|
||||||
fn load(&self) -> Result<Collection, LoadError> {
|
fn load(&mut self) -> Result<Collection, LoadError> {
|
||||||
Ok(vec![])
|
let tx = self.backend.transaction()?;
|
||||||
|
|
||||||
|
let mut database = tx.select_database_version()?;
|
||||||
|
match database {
|
||||||
|
DeserializeDatabase::V20250103(ref mut coll) => {
|
||||||
|
coll.extend(tx.select_all_artists()?);
|
||||||
|
for artist in coll.iter_mut() {
|
||||||
|
artist.albums.extend(tx.select_artist_albums(&artist.name)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.commit()?;
|
||||||
|
Ok(database.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save(&mut self, collection: &Collection) -> Result<(), SaveError> {
|
fn save(&mut self, collection: &Collection) -> Result<(), SaveError> {
|
||||||
|
@ -227,7 +227,7 @@ impl<'de> Deserialize<'de> for SerdeMbid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SerdeAlbumDate(AlbumDate);
|
pub struct SerdeAlbumDate(pub AlbumDate);
|
||||||
|
|
||||||
impl From<SerdeAlbumDate> for AlbumDate {
|
impl From<SerdeAlbumDate> for AlbumDate {
|
||||||
fn from(value: SerdeAlbumDate) -> Self {
|
fn from(value: SerdeAlbumDate) -> Self {
|
||||||
|
@ -43,7 +43,7 @@ fn save() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn load() {
|
fn load() {
|
||||||
let backend = JsonDatabaseFileBackend::new(&*DATABASE_TEST_FILE);
|
let backend = JsonDatabaseFileBackend::new(&*DATABASE_TEST_FILE);
|
||||||
let database = JsonDatabase::new(backend);
|
let mut database = JsonDatabase::new(backend);
|
||||||
|
|
||||||
let read_data: Vec<Artist> = database.load().unwrap();
|
let read_data: Vec<Artist> = database.load().unwrap();
|
||||||
|
|
||||||
|
@ -3,64 +3,61 @@ use std::{fs, path::PathBuf};
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use musichoard::{
|
use musichoard::{
|
||||||
|
collection::{artist::Artist, Collection},
|
||||||
external::database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase},
|
external::database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase},
|
||||||
interface::database::IDatabase,
|
interface::database::IDatabase,
|
||||||
};
|
};
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
use crate::testlib::COLLECTION;
|
use crate::testlib::COLLECTION;
|
||||||
|
|
||||||
pub static DATABASE_TEST_FILE: Lazy<PathBuf> =
|
pub static DATABASE_TEST_FILE: Lazy<PathBuf> =
|
||||||
Lazy::new(|| fs::canonicalize("./tests/files/database/database.db").unwrap());
|
Lazy::new(|| fs::canonicalize("./tests/files/database/database.db").unwrap());
|
||||||
|
|
||||||
// fn expected() -> Collection {
|
fn expected() -> Collection {
|
||||||
// let mut expected = COLLECTION.to_owned();
|
let mut expected = COLLECTION.to_owned();
|
||||||
// for artist in expected.iter_mut() {
|
for artist in expected.iter_mut() {
|
||||||
// for album in artist.albums.iter_mut() {
|
for album in artist.albums.iter_mut() {
|
||||||
// album.tracks.clear();
|
album.tracks.clear();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// expected
|
expected
|
||||||
// }
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn save() {
|
fn save() {
|
||||||
// let file = NamedTempFile::new().unwrap();
|
let file = NamedTempFile::new().unwrap();
|
||||||
|
|
||||||
let backend = SqlDatabaseSqliteBackend::new(&*DATABASE_TEST_FILE).unwrap();
|
let backend = SqlDatabaseSqliteBackend::new(file.path()).unwrap();
|
||||||
let mut database = SqlDatabase::new(backend).unwrap();
|
let mut database = SqlDatabase::new(backend).unwrap();
|
||||||
|
|
||||||
let write_data = COLLECTION.to_owned();
|
let write_data = COLLECTION.to_owned();
|
||||||
database.save(&write_data).unwrap();
|
database.save(&write_data).unwrap();
|
||||||
|
|
||||||
// let expected = fs::read_to_string(&*DATABASE_TEST_FILE).unwrap();
|
|
||||||
// let actual = fs::read_to_string(file.path()).unwrap();
|
|
||||||
|
|
||||||
// assert_eq!(actual, expected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn load() {
|
fn load() {
|
||||||
// let backend = JsonDatabaseFileBackend::new(&*DATABASE_TEST_FILE);
|
let backend = SqlDatabaseSqliteBackend::new(&*DATABASE_TEST_FILE).unwrap();
|
||||||
// let database = JsonDatabase::new(backend);
|
let mut database = SqlDatabase::new(backend).unwrap();
|
||||||
|
|
||||||
// let read_data: Vec<Artist> = database.load().unwrap();
|
let read_data: Vec<Artist> = database.load().unwrap();
|
||||||
|
|
||||||
// let expected = expected();
|
let expected = expected();
|
||||||
// assert_eq!(read_data, expected);
|
assert_eq!(read_data, expected);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn reverse() {
|
fn reverse() {
|
||||||
// let file = NamedTempFile::new().unwrap();
|
let file = NamedTempFile::new().unwrap();
|
||||||
|
|
||||||
// let backend = JsonDatabaseFileBackend::new(file.path());
|
let backend = SqlDatabaseSqliteBackend::new(file.path()).unwrap();
|
||||||
// let mut database = JsonDatabase::new(backend);
|
let mut database = SqlDatabase::new(backend).unwrap();
|
||||||
|
|
||||||
// let write_data = COLLECTION.to_owned();
|
let write_data = COLLECTION.to_owned();
|
||||||
// database.save(&write_data).unwrap();
|
database.save(&write_data).unwrap();
|
||||||
// let read_data: Vec<Artist> = database.load().unwrap();
|
let read_data: Vec<Artist> = database.load().unwrap();
|
||||||
|
|
||||||
// // Album data is not saved into database.
|
// Not all data is saved into database.
|
||||||
// let expected = expected();
|
let expected = expected();
|
||||||
// assert_eq!(read_data, expected);
|
assert_eq!(read_data, expected);
|
||||||
// }
|
}
|
||||||
|
BIN
tests/files/database/database.db
Normal file
BIN
tests/files/database/database.db
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user