use rand::{distributions::Alphanumeric, Rng, thread_rng}; use super::{DBError, Store, SessionData}; use std::{ cell::Cell, time::{Duration, Instant}, }; enum DataType { DBMap(Store), } impl DataType { fn new(data_type: &str) -> Result { match data_type { "store" => Ok(DataType::DBMap(Store::new())), _ => Err(DBError::new("invalid data type")), } } } impl SessionData for DataType { fn add(&mut self, key: &str, value: &str, data: &str) -> Result, DBError> { match self { DataType::DBMap(dbs) => dbs.add(key, value, data), } } fn eq(&self, key: &str, value: &str) -> Result, DBError> { match self { DataType::DBMap(dbs) => dbs.eq(key, value), } } fn list(&self, keys: Vec<&str>) -> Result, DBError> { match self { DataType::DBMap(dbs) => dbs.list(keys), } } } struct Entry { data: DataType, last_used: Cell, } impl Entry { fn new(data_type: &str) -> Result { let data = match DataType::new(data_type) { Ok(item) => item, Err(err) => return Err(err), }; Ok(Self { data: data, last_used: Cell::new(Instant::now()), }) } fn elapsed(&self) -> Duration { self.last_used.get().elapsed() } } impl SessionData for Entry { fn add(&mut self, key: &str, value: &str, data: &str) -> Result, DBError> { self.last_used.set(Instant::now()); self.data.add(key, value, data) } fn eq(&self, key: &str, value: &str) -> Result, DBError> { self.last_used.set(Instant::now()); self.data.eq(key, value) } fn list(&self, keys: Vec<&str>) -> Result, DBError> { self.last_used.set(Instant::now()); self.data.list(keys) } } struct Cache; impl Cache { async fn new(dir: &str) -> Self { Self } } #[cfg(test)] mod datatype { use super::*; #[test] fn invalid_cache_type() -> Result<(), DBError> { match DataType::new("dkhgdl") { Ok(_) => Err(DBError::new("invalid data type should raise an error")), Err(err) => { assert_eq!(err.to_string(), "invalid data type"); Ok(()) } } } #[test] fn create_storage() { let dbs = DataType::new("store").unwrap(); let expected: Vec = Vec::new(); assert_eq!(dbs.list(["database"].to_vec()).unwrap(), expected); } #[test] fn update_storage() { let mut dbs = DataType::new("store").unwrap(); let name = "new_database"; let id = "someid"; dbs.add("database", name, id).unwrap(); assert_eq!(dbs.eq("database", name).unwrap(), [id].to_vec()); assert_eq!(dbs.list(["database"].to_vec()).unwrap(), [name].to_vec()); } } #[cfg(test)] mod entry { use super::*; #[test] fn invalid_cache_type() -> Result<(), DBError> { match Entry::new("uydg") { Ok(_) => Err(DBError::new("invalid data type should raise an error")), Err(err) => { assert_eq!(err.to_string(), "invalid data type"); Ok(()) } } } #[test] fn create_storage() { let entry = Entry::new("store").unwrap(); assert!( Duration::from_secs(1) > entry.elapsed(), "Entry last used should be now." ); let expected: Vec = Vec::new(); assert_eq!(entry.list(["database"].to_vec()).unwrap(), expected); } #[test] fn add_database_to_storage() { let mut entry = Entry::new("store").unwrap(); entry .last_used .set(Instant::now() - Duration::from_secs(500)); let name = "roger"; let id = "cormick"; entry.add("database", name, id).unwrap(); assert!( Duration::from_secs(1) > entry.elapsed(), "Entry last used should be now." ); assert_eq!(entry.eq("database", name).unwrap(), [id].to_vec()); } #[test] fn get_database_from_storage() { let mut entry = Entry::new("store").unwrap(); let name = "jessica"; entry.add("database", name, "rabbit").unwrap(); entry .last_used .set(Instant::now() - Duration::from_secs(500)); entry.eq("database", name).unwrap(); assert!( Duration::from_secs(1) > entry.elapsed(), "Entry last used should be now." ); } #[test] fn list_database_from_storage() { let entry = Entry::new("store").unwrap(); entry .last_used .set(Instant::now() - Duration::from_secs(500)); entry.list(["database"].to_vec()).unwrap(); assert!( Duration::from_secs(1) > entry.elapsed(), "Entry last used should be now." ); } } #[cfg(test)] mod cache { use super::*; use tempfile::tempdir; #[async_std::test] async fn create() { let dir = tempdir().unwrap(); Cache::new(dir.path().to_str().unwrap()).await; } }