pub mod error; use async_std::sync::{Arc, RwLock}; use error::DBError; use std::collections::HashMap; #[derive(Clone)] pub struct MoreThanText { databases: Arc>>, } impl MoreThanText { pub async fn new() -> Self { Self { databases: Arc::new(RwLock::new(HashMap::new())), } } async fn create_database(&self, name: &str) -> Result<(), DBError> { let mut databases = self.databases.write().await; match databases.get(name) { Some(_) => Err(DBError::new("duplicate database name")), None => { let db = Database::new().await; databases.insert(name.to_string(), db); Ok(()) } } } async fn use_database(&self, name: &str) -> Result { let databases = self.databases.read().await; match databases.get(name) { Some(db) => Ok(db.clone()), None => Err(DBError::new("database name not found")), } } } #[derive(Clone)] struct Database; impl Database { async fn new() -> Self { Self {} } async fn add_table(&self, _name: &str) {} } struct Table; impl Table { async fn new() -> Self { Self {} } } #[cfg(test)] mod engine_functions { use super::*; #[async_std::test] async fn create_database() { let mtt = MoreThanText::new().await; mtt.create_database("smith").await.unwrap(); } #[async_std::test] async fn database_names_must_be_unique() -> Result<(), DBError> { let mtt = MoreThanText::new().await; let msg = "duplicate database name"; mtt.create_database("john").await.unwrap(); match mtt.create_database("john").await { Ok(_) => Err(DBError::new("Duplicate names should cause error")), Err(err) => { if err.to_string() == msg { Ok(()) } else { Err(DBError::new(format!( "incorrect err message: got: '{}' want: '{}'", err.to_string(), msg ))) } } } } #[async_std::test] async fn use_database() -> Result<(), DBError> { let mtt = MoreThanText::new().await; let dbname = "Johnson"; mtt.create_database(dbname).await.unwrap(); mtt.use_database(dbname).await.unwrap(); Ok(()) } #[async_std::test] async fn use_missing_database() -> Result<(), DBError> { let error = "database name not found"; let mtt = MoreThanText::new().await; match mtt.use_database("ssmith").await { Ok(_) => Err(DBError::new("Should raise database missing error")), Err(err) => { if err.to_string() == error { Ok(()) } else { Err(DBError::new(format!( "Incorrect error message: Got '{}' Want '{}'", err.to_string(), error ))) } } } } #[async_std::test] async fn create_get_table() { let db = "thedatabase"; let mtt = MoreThanText::new().await; mtt.create_database(db).await.unwrap(); let dbase = mtt.use_database(db).await.unwrap(); dbase.add_table("melvin").await; } } #[cfg(test)] mod database_functions { use super::*; #[async_std::test] async fn new_database() { Database::new().await; } #[async_std::test] async fn new_table() { let db = Database::new().await; db.add_table("fred").await; } } #[cfg(test)] mod table_functions { use super::*; #[async_std::test] async fn new_table() { Table::new().await; } }