parent
2da67487b5
commit
8eb916771e
@ -1,135 +1,66 @@ |
||||
pub mod error; |
||||
use async_std::{fs::create_dir, path::Path}; |
||||
|
||||
use async_std::sync::{Arc, RwLock}; |
||||
use error::DBError; |
||||
use std::collections::HashMap; |
||||
|
||||
const DATA: &str = "data"; |
||||
|
||||
#[derive(Clone)] |
||||
pub struct MoreThanText { |
||||
databases: Arc<RwLock<HashMap<String, Database>>>, |
||||
} |
||||
pub struct MoreThanText; |
||||
|
||||
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(()) |
||||
pub async fn new(dir: &str) -> Result<Self, DBError> { |
||||
let data_dir = Path::new(dir).join(DATA); |
||||
if !data_dir.is_dir().await { |
||||
match create_dir(data_dir).await { |
||||
Ok(_) => (), |
||||
Err(err) => { |
||||
let mut error = DBError::new("failed to initialize"); |
||||
error.add_source(err); |
||||
return Err(error); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
async fn use_database(&self, name: &str) -> Result<Database, DBError> { |
||||
let databases = self.databases.read().await; |
||||
match databases.get(name) { |
||||
Some(db) => Ok(db.clone()), |
||||
None => Err(DBError::new("database name not found")), |
||||
} |
||||
Ok(Self {}) |
||||
} |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
struct Database; |
||||
|
||||
impl Database { |
||||
async fn new() -> Self { |
||||
Self {} |
||||
} |
||||
|
||||
async fn add_table(&self, _name: &str) {} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod engine_functions { |
||||
mod init { |
||||
use super::*; |
||||
use std::error::Error; |
||||
use tempfile::tempdir; |
||||
|
||||
#[async_std::test] |
||||
async fn create_database() { |
||||
let mtt = MoreThanText::new().await; |
||||
mtt.create_database("smith").await.unwrap(); |
||||
async fn create_data_dir() { |
||||
let dir = tempdir().unwrap(); |
||||
MoreThanText::new(dir.path().to_str().unwrap()) |
||||
.await |
||||
.unwrap(); |
||||
let data_dir = dir.path().join(DATA); |
||||
assert!(data_dir.is_dir(), "Did not create the data directory."); |
||||
dir.close().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 fn existing_data_dir() { |
||||
let dir = tempdir().unwrap(); |
||||
let data_dir = dir.path().join(DATA); |
||||
create_dir(data_dir).await.unwrap(); |
||||
MoreThanText::new(dir.path().to_str().unwrap()) |
||||
.await |
||||
.unwrap(); |
||||
dir.close().unwrap(); |
||||
} |
||||
|
||||
#[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")), |
||||
async fn bad_data_dir() { |
||||
match MoreThanText::new("kljsdgfhslkfrh").await { |
||||
Ok(_) => assert!(false, "This test should fail to create a data directory"), |
||||
Err(err) => { |
||||
if err.to_string() == error { |
||||
Ok(()) |
||||
} else { |
||||
Err(DBError::new(format!( |
||||
"Incorrect error message: Got '{}' Want '{}'", |
||||
err.to_string(), |
||||
error |
||||
))) |
||||
} |
||||
assert_eq!(err.to_string(), "failed to initialize"); |
||||
assert!(err.source().is_some(), "Must include the source 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; |
||||
}; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,153 @@ |
||||
pub mod error; |
||||
|
||||
use async_std::sync::{Arc, RwLock}; |
||||
use error::DBError; |
||||
use std::collections::HashMap; |
||||
|
||||
#[derive(Clone)] |
||||
pub struct MoreThanText { |
||||
databases: Arc<RwLock<HashMap<String, Database>>>, |
||||
} |
||||
|
||||
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<Database, DBError> { |
||||
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; |
||||
} |
||||
} |
Loading…
Reference in new issue