From 27391b2c1bec019eae0145a3a49a4b2b0322e3b5 Mon Sep 17 00:00:00 2001 From: giuseppe-g-gelardi Date: Thu, 5 Dec 2024 19:53:55 -0500 Subject: [PATCH] add async methods & tests --- src/cargobase/database.rs | 24 ++++----- src/cargobase/mod.rs | 5 +- src/cargobase/table.rs | 103 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/cargobase/database.rs b/src/cargobase/database.rs index 3426625..bdc25f9 100644 --- a/src/cargobase/database.rs +++ b/src/cargobase/database.rs @@ -41,7 +41,7 @@ impl Database { } } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub async fn new_async(name: &str) -> Self { let name = name.to_string(); let file_name = format!("{name}.json"); @@ -83,7 +83,7 @@ impl Database { Ok(()) } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub async fn drop_database_async(&self) -> Result<(), DatabaseError> { if tokio::fs::remove_file(&self.file_name).await.is_err() { tracing::error!( @@ -111,7 +111,7 @@ impl Database { Ok(()) } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub async fn add_table_async(&mut self, table: &mut Table) -> Result<(), DatabaseError> { if self.tables.iter().any(|t| t.name == table.name) { tracing::warn!( @@ -145,7 +145,7 @@ impl Database { } } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub async fn drop_table_async(&mut self, table_name: &str) -> Result<(), DatabaseError> { let mut db = Database::load_from_file_async(&self.file_name) .await @@ -194,7 +194,7 @@ impl Database { Ok(()) } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub(crate) async fn save_to_file_async(&self) -> Result<(), tokio::io::Error> { let json_data = serde_json::to_string_pretty(&self)?; tokio::fs::write(&self.file_name, json_data).await?; @@ -209,7 +209,7 @@ impl Database { Ok(db) } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] pub(crate) async fn load_from_file_async(file_name: &str) -> Result { let json_data = tokio::fs::read_to_string(file_name).await?; let db: Database = serde_json::from_str(&json_data)?; @@ -334,7 +334,7 @@ mod tests { assert_eq!(db.tables.len(), 1); // the setup_temp_db function adds a table } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_database_new_async() { let db = setup_temp_db_async().await; @@ -356,7 +356,7 @@ mod tests { assert!(!std::path::Path::new(&db.file_name).exists()); } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_drop_database_async() { let db = setup_temp_db_async().await; @@ -386,7 +386,7 @@ mod tests { std::fs::remove_file("test_db.json").ok(); } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_add_table_success_async() { // this test does not use the setup_temp_db function @@ -456,7 +456,7 @@ mod tests { assert_eq!(db.tables.len(), 0); } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_drop_table_success_async() { let mut db = setup_temp_db_async().await; @@ -517,7 +517,7 @@ mod tests { assert_eq!(db, loaded_db); } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_save_to_file_async() { use tempfile::NamedTempFile; @@ -538,7 +538,7 @@ mod tests { assert_eq!(db, loaded_db); } - #[cfg(feature = "async")] + // #[cfg(feature = "async")] #[tokio::test] async fn test_load_from_file_async() { use tempfile::NamedTempFile; diff --git a/src/cargobase/mod.rs b/src/cargobase/mod.rs index edf3740..99315e4 100644 --- a/src/cargobase/mod.rs +++ b/src/cargobase/mod.rs @@ -13,8 +13,5 @@ pub use errors::errors::DatabaseError; pub use query::Query; pub use row::Row; pub use table::Table; -pub use util::setup_temp_db; +pub use util::{setup_temp_db, setup_temp_db_async}; pub use view::View; - -#[cfg(feature = "async")] -pub use util::setup_temp_db_async; diff --git a/src/cargobase/table.rs b/src/cargobase/table.rs index 3fb4571..5124f64 100644 --- a/src/cargobase/table.rs +++ b/src/cargobase/table.rs @@ -38,10 +38,34 @@ impl Table { tracing::error!("Table {} not found", self.name); } } + + pub async fn add_row_async(&mut self, db: &mut Database, data: Value) { + if let Some(table) = db.get_table_mut(&self.name) { + if data.is_array() { + if let Some(array) = data.as_array() { + for item in array { + table.rows.push(Row::new(item.clone())) + } + } + } else { + table.rows.push(Row::new(data)) + } + match db.save_to_file_async().await { + Ok(_) => {} + Err(e) => { + tracing::error!("Failed to save to file: {}", e); + } + } + } else { + tracing::error!("Table {} not found", self.name); + } + } } #[cfg(test)] mod tests { + use crate::cargobase::setup_temp_db_async; + use super::super::{setup_temp_db, Column, Columns}; use super::*; @@ -75,6 +99,25 @@ mod tests { ); } + #[tokio::test] + async fn test_table_add_row_single_async() { + let mut db = setup_temp_db_async().await; + let mut table = Table::new( + "TestTable".to_string(), + Columns::new(vec![Column::new("id", true), Column::new("name", true)]), + ); + db.add_table_async(&mut table).await.unwrap(); + + let row_data = json!({"id": "1", "name": "John Doe"}); + table.add_row_async(&mut db, row_data).await; + + assert_eq!(db.tables[0].rows.len(), 1); + assert_eq!( + db.tables[0].rows[0].data, + json!({"id": "1", "name": "John Doe"}) + ); + } + #[test] fn test_table_add_row_array() { let mut db = setup_temp_db(); @@ -101,6 +144,32 @@ mod tests { ); } + #[tokio::test] + async fn test_table_add_row_array_async() { + let mut db = setup_temp_db_async().await; + let mut table = Table::new( + "TestTable".to_string(), + Columns::new(vec![Column::new("id", true), Column::new("name", true)]), + ); + db.add_table_async(&mut table).await.unwrap(); + + let row_data = json!([ + {"id": "1", "name": "John Doe"}, + {"id": "2", "name": "Jane Doe"} + ]); + table.add_row_async(&mut db, row_data).await; + + assert_eq!(db.tables[0].rows.len(), 2); + assert_eq!( + db.tables[0].rows[0].data, + json!({"id": "1", "name": "John Doe"}) + ); + assert_eq!( + db.tables[0].rows[1].data, + json!({"id": "2", "name": "Jane Doe"}) + ); + } + #[traced_test] #[test] fn test_table_add_row_table_not_found() { @@ -117,6 +186,22 @@ mod tests { assert_eq!(db.tables.len(), 1); // Original table remains unchanged } + #[traced_test] + #[tokio::test] + async fn test_table_add_row_table_now_found_async() { + let mut db = setup_temp_db_async().await; + let mut table = Table::new( + "NonExistentTable".to_string(), + Columns::new(vec![Column::new("id", true), Column::new("name", true)]), + ); + + let row_data = json!({"id": "1", "name": "John Doe"}); + table.add_row_async(&mut db, row_data).await; + + assert!(logs_contain("Table NonExistentTable not found")); + assert_eq!(db.tables.len(), 1); // Original table remains unchanged + } + #[traced_test] #[test] fn test_table_add_row_save_failure() { @@ -134,4 +219,22 @@ mod tests { assert!(logs_contain("Failed to save to file")); } + + #[traced_test] + #[tokio::test] + async fn test_table_add_row_save_failure_async() { + let mut db = setup_temp_db_async().await; + let mut table = Table::new( + "TestTable".to_string(), + Columns::new(vec![Column::new("id", true), Column::new("name", true)]), + ); + db.add_table_async(&mut table).await.unwrap(); + + // Simulate failure in saving + db.file_name = "/invalid/path.json".to_string(); + let row_data = json!({"id": "1", "name": "John Doe"}); + table.add_row_async(&mut db, row_data).await; + + assert!(logs_contain("Failed to save to file")); + } }