use async_std::{ channel::{unbounded, Sender}, path::PathBuf, task::spawn, }; use std::{error::Error, fmt}; const ENTRY: &str = "EntryPoint"; #[derive(Debug)] enum ErrorCode { Undefined(String), IncorrectDataType(String), } impl fmt::Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ErrorCode::Undefined(msg) => write!(f, "{}", msg), ErrorCode::IncorrectDataType(item) => write!(f, "data type '{}' does not exist", item), } } } mod errorcodes { use super::*; const ITEMS: [&str; 2] = ["one", "two"]; #[test] fn undefined_display() { for item in ITEMS { let err = ErrorCode::Undefined(item.to_string()); assert_eq!(err.to_string(), item); } } #[test] fn incorrect_data_type() { for item in ITEMS { let err = ErrorCode::IncorrectDataType(item.to_string()); assert_eq!( err.to_string(), format!("data type '{}' does not exist", item) ); } } } #[derive(Debug)] pub struct MTTError { code: ErrorCode, } impl MTTError { fn new(msg: S) -> Self where S: Into, { let text = msg.into(); Self { code: ErrorCode::Undefined(text), } } fn from_code(code: ErrorCode) -> Self { Self { code: code } } } impl Error for MTTError {} impl fmt::Display for MTTError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.code) } } #[cfg(test)] mod errors { use super::*; #[test] fn create_with_str() { let msgs = ["one", "two"]; for msg in msgs { let err = MTTError::new(msg); assert_eq!(err.to_string(), msg); } } #[test] fn create_with_string() { let msg = "three"; let err = MTTError::new(msg.to_string()); assert_eq!(err.to_string(), msg); } #[test] fn create_from_code() { let code = ErrorCode::Undefined("oops".to_string()); let err = MTTError::from_code(code); match err.code { ErrorCode::Undefined(_) => (), _ => assert!(false, "{:?} is not undefined", err.code), } } #[test] fn create_from_different_code() { let code = ErrorCode::IncorrectDataType("nuts".to_string()); let err = MTTError::from_code(code); match err.code { ErrorCode::IncorrectDataType(_) => (), _ => assert!(false, "{:?} is not incorrect data type", err.code), } } } #[derive(Clone, Debug)] struct Store; impl Store { fn new() -> Self { Self {} } } #[cfg(test)] mod stores { use super::*; #[test] fn create() { Store::new(); } } #[derive(Clone, Debug)] enum DataType { DBMap(Store), } impl DataType { fn new(dtype: &str) -> Result { match dtype { "store" => Ok(Self::DBMap(Store::new())), _ => Err(MTTError::from_code(ErrorCode::IncorrectDataType( dtype.to_string(), ))), } } } #[cfg(test)] mod datatypes { use super::*; #[test] fn error_on_bad_datatype() { let items = ["sdgthsth", "jfjty"]; for item in items { match DataType::new(item) { Ok(_) => assert!(false, "bad data types should return an error"), Err(err) => match err.code { ErrorCode::IncorrectDataType(dtype) => assert_eq!(dtype, item), _ => assert!(false, "{:?} is not incorrect data type", err.code), }, } } } #[test] fn create_store() { let dtype = DataType::new("store").unwrap(); match dtype { DataType::DBMap(_) => (), _ => assert!(false, "{:?} is not incorrect data type", dtype), } } } #[derive(Clone)] pub struct MoreThanText { session: Vec, channel: Sender, } impl MoreThanText { async fn new() {} async fn get_entry(&self, id: String) { self.channel.send(id).await.unwrap(); } } #[cfg(test)] mod mtt { use super::*; #[async_std::test] async fn create() { MoreThanText::new().await; } } pub async fn start_db

(dir: P) -> Result where P: Into, { let data_dir = dir.into(); let (s, r) = unbounded(); spawn(async move { loop { r.recv().await.unwrap(); } }); Ok(MoreThanText { session: [ENTRY.to_string()].to_vec(), channel: s, }) } #[cfg(test)] mod db_start_up { use super::*; use tempfile::tempdir; #[async_std::test] async fn initial_session() { let dir = tempdir().unwrap(); let mtt = start_db(dir.path()).await.unwrap(); assert_eq!(mtt.session, [ENTRY]); } }