test: add test for thread safety; remove mut for upsert and persist
This commit is contained in:
@@ -59,7 +59,7 @@ fn main() {
|
||||
// Define the path for the SQLite database file.
|
||||
let db_path = "./simple_product.sqlite3";
|
||||
// Create a new `Catalog` instance with the specified database path.
|
||||
let mut catalog = Catalog::new(db_path);
|
||||
let catalog = Catalog::new(db_path);
|
||||
// Initialize the catalog, which sets up the database.
|
||||
catalog.init().unwrap();
|
||||
// Create a new `Product` instance representing a laptop.
|
||||
|
||||
@@ -18,7 +18,7 @@ impl Catalog {
|
||||
/// removed from the in-memory catalog.
|
||||
/// - All other entities that were successfully persisted (new or updated) have
|
||||
/// their state changed to `EntityState::Loaded`.
|
||||
pub fn persist(&mut self) -> result::Result<(), FailedTo> {
|
||||
pub fn persist(&self) -> result::Result<(), FailedTo> {
|
||||
let path = path::Path::new(&self.path);
|
||||
self.on_items(|items| {
|
||||
sqlite::persist::catalog(path, items).map_err(|_| FailedTo::PersistCatalog)?;
|
||||
|
||||
@@ -18,7 +18,7 @@ impl Catalog {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `object` - The object to insert or update, which must implement the `EAV` trait.
|
||||
pub fn upsert(&mut self, object: impl EAV) -> Result<(), FailedTo> {
|
||||
pub fn upsert(&self, object: impl EAV) -> Result<(), FailedTo> {
|
||||
let mut entity = object.try_into().map_err(|_| FailedTo::ConvertObject)?;
|
||||
self.on_items(|items| {
|
||||
if items.contains_key(&entity.id) {
|
||||
|
||||
@@ -4,7 +4,7 @@ mod tests {
|
||||
#[test]
|
||||
fn get_should_retrieve_and_convert_entity_by_id() {
|
||||
// Should retrieve an entity by its ID and correctly convert it to the target type 'T'.
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item = Item {
|
||||
id: "item-123".to_string(),
|
||||
subclass: Some("subitem".to_string()),
|
||||
@@ -21,7 +21,7 @@ mod tests {
|
||||
#[test]
|
||||
fn get_should_return_none_for_nonexistent_id() {
|
||||
// Should return 'None' if the ID does not exist.
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item = Item {
|
||||
id: "item-123".to_string(),
|
||||
name: "Test Item".to_string(),
|
||||
|
||||
@@ -11,7 +11,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. 'init' -> 'insert' -> 'persist'
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item_to_insert = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -96,7 +96,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. 'insert' -> 'persist'
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item_to_delete = Item {
|
||||
id: "item-to-delete".to_string(),
|
||||
@@ -136,7 +136,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Initial setup
|
||||
let mut catalog_setup = Catalog::new(db_path);
|
||||
let catalog_setup = Catalog::new(db_path);
|
||||
catalog_setup.init().unwrap();
|
||||
let initial_item = Item {
|
||||
id: "item-1".to_string(),
|
||||
|
||||
@@ -4,7 +4,7 @@ mod tests {
|
||||
#[test]
|
||||
fn list_by_class_should_return_all_entities_of_class() {
|
||||
// Should return an iterator with all entities of a specific class.
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item1 = Item {
|
||||
id: "item-1".to_string(),
|
||||
subclass: Some("subitem".to_string()),
|
||||
|
||||
@@ -3,7 +3,7 @@ mod tests {
|
||||
use crate::*;
|
||||
#[test]
|
||||
fn list_by_class_and_subclass_should_return_matching_entities() {
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item1 = Item {
|
||||
id: "item-1".to_string(),
|
||||
subclass: Some("electronics".to_string()),
|
||||
@@ -35,7 +35,7 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn list_by_class_and_subclass_should_return_empty_if_no_match() {
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item1 = Item {
|
||||
id: "item-1".to_string(),
|
||||
subclass: Some("electronics".to_string()),
|
||||
|
||||
@@ -11,7 +11,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Setup DB with a few items of the same class
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item1 = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -70,7 +70,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Persist an item to the database.
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item_in_db = Item {
|
||||
id: "item-1".to_string(),
|
||||
|
||||
@@ -133,7 +133,7 @@ mod tests {
|
||||
if path.exists() {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
let mut catalog_setup = Catalog::new(db_path);
|
||||
let catalog_setup = Catalog::new(db_path);
|
||||
catalog_setup.init().unwrap();
|
||||
let item_in_db = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -1421,7 +1421,7 @@ mod tests {
|
||||
if path.exists() {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
let mut catalog_setup = Catalog::new(db_path);
|
||||
let catalog_setup = Catalog::new(db_path);
|
||||
catalog_setup.init().unwrap();
|
||||
// Define a second struct with a different class
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
|
||||
@@ -11,7 +11,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Create a catalog, insert an item, and persist it to the DB.
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item_to_persist = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -66,7 +66,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Persist an item to the database.
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item_in_db = Item {
|
||||
id: "item-1".to_string(),
|
||||
|
||||
@@ -11,7 +11,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Create catalog, insert an item, and persist
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let item1 = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -77,7 +77,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Insert an entity and persist it.
|
||||
let mut catalog1 = Catalog::new(db_path);
|
||||
let catalog1 = Catalog::new(db_path);
|
||||
catalog1.init().unwrap();
|
||||
let original_item = Item {
|
||||
id: "item-1".to_string(),
|
||||
@@ -132,7 +132,7 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
// 1. Setup: Pre-populate the database with some items.
|
||||
let mut catalog_setup = Catalog::new(db_path);
|
||||
let catalog_setup = Catalog::new(db_path);
|
||||
catalog_setup.init().unwrap();
|
||||
let item_to_update_original = Item {
|
||||
id: "update-me".to_string(),
|
||||
@@ -221,7 +221,7 @@ mod tests {
|
||||
// Using a directory as a path should cause a failure.
|
||||
let invalid_path = "target/test_dbs/a_directory_for_persist_fail";
|
||||
std::fs::create_dir_all(invalid_path).unwrap();
|
||||
let mut catalog = Catalog::new(invalid_path);
|
||||
let catalog = Catalog::new(invalid_path);
|
||||
let item = Item {
|
||||
id: "item-1".to_string(),
|
||||
name: "Test".to_string(),
|
||||
|
||||
@@ -3,7 +3,6 @@ mod tests {
|
||||
use crate::*;
|
||||
use std::sync::*;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn thread_safety_test() {
|
||||
let db_path = "target/test_dbs/thread_safety_test.db";
|
||||
@@ -12,10 +11,8 @@ mod tests {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||
|
||||
let catalog = Arc::new(Catalog::new(db_path));
|
||||
catalog.init().unwrap();
|
||||
|
||||
let mut handles = vec![];
|
||||
for i in 0..10 {
|
||||
let catalog = Arc::clone(&catalog);
|
||||
@@ -36,22 +33,16 @@ mod tests {
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
for handle in handles {
|
||||
handle.join().unwrap();
|
||||
}
|
||||
|
||||
let total_items = catalog.with_items(|items| Ok(items.len())).unwrap();
|
||||
assert_eq!(total_items, 1000);
|
||||
|
||||
catalog.persist().unwrap();
|
||||
|
||||
let mut new_catalog = Catalog::new(db_path);
|
||||
new_catalog.load_by_class::<Item>().unwrap();
|
||||
|
||||
let total_items_after_load = new_catalog.with_items(|items| Ok(items.len())).unwrap();
|
||||
assert_eq!(total_items_after_load, 1000);
|
||||
|
||||
std::fs::remove_file(path).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ mod tests {
|
||||
#[test]
|
||||
fn upsert_should_add_single_entity_as_new() {
|
||||
// 'upsert()': Should add a single entity to the 'items' map with 'EntityState::New'.
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item = Item {
|
||||
id: "item-123".to_string(),
|
||||
name: "Test Item".to_string(),
|
||||
@@ -29,7 +29,7 @@ mod tests {
|
||||
#[test]
|
||||
fn upsert_should_overwrite_existing_entity() {
|
||||
// 'upsert()': Should overwrite an existing entity with the same ID.
|
||||
let mut catalog = Catalog::new("dummy.db");
|
||||
let catalog = Catalog::new("dummy.db");
|
||||
let item1 = Item {
|
||||
id: "item-123".to_string(),
|
||||
name: "First Item".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user