use chrono::{DateTime, Utc};
use crate::Result;
pub trait Clock: Send + Sync {
fn now(&self) -> DateTime<Utc>;
}
pub trait Storage: Send + Sync {
fn save(&mut self, key: &str, data: Vec<u8>) -> Result<()>;
fn load(&self, key: &str) -> Result<Option<Vec<u8>>>;
fn delete(&mut self, key: &str) -> Result<()>;
fn list_keys(&self) -> Result<Vec<String>>;
fn begin_transaction(&mut self) -> Result<()> {
Ok(())
}
fn commit_transaction(&mut self) -> Result<()> {
Ok(())
}
fn rollback_transaction(&mut self) -> Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
struct TestClockImpl {
time: DateTime<Utc>,
}
impl Clock for TestClockImpl {
fn now(&self) -> DateTime<Utc> {
self.time
}
}
struct TestStorageImpl {
data: HashMap<String, Vec<u8>>,
}
impl Storage for TestStorageImpl {
fn save(&mut self, key: &str, data: Vec<u8>) -> Result<()> {
self.data.insert(key.to_string(), data);
Ok(())
}
fn load(&self, key: &str) -> Result<Option<Vec<u8>>> {
Ok(self.data.get(key).cloned())
}
fn delete(&mut self, key: &str) -> Result<()> {
self.data.remove(key);
Ok(())
}
fn list_keys(&self) -> Result<Vec<String>> {
Ok(self.data.keys().cloned().collect())
}
}
#[test]
fn test_clock_trait_works() {
let time = Utc::now();
let clock = TestClockImpl { time };
assert_eq!(clock.now(), time);
}
#[test]
fn test_clock_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Box<dyn Clock>>();
assert_sync::<Box<dyn Clock>>();
}
#[test]
fn test_storage_save_and_load() {
let mut storage = TestStorageImpl {
data: HashMap::new(),
};
let data = vec![1, 2, 3, 4];
storage.save("test_key", data.clone()).unwrap();
let loaded = storage.load("test_key").unwrap();
assert_eq!(loaded, Some(data));
}
#[test]
fn test_storage_load_nonexistent() {
let storage = TestStorageImpl {
data: HashMap::new(),
};
let loaded = storage.load("nonexistent").unwrap();
assert_eq!(loaded, None);
}
#[test]
fn test_storage_delete() {
let mut storage = TestStorageImpl {
data: HashMap::new(),
};
storage.save("test_key", vec![1, 2, 3]).unwrap();
storage.delete("test_key").unwrap();
let loaded = storage.load("test_key").unwrap();
assert_eq!(loaded, None);
}
#[test]
fn test_storage_is_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Box<dyn Storage>>();
assert_sync::<Box<dyn Storage>>();
}
}