1use chrono::{DateTime, Utc};
2
3use crate::Result;
4
5pub trait Clock: Send + Sync {
12 fn now(&self) -> DateTime<Utc>;
13}
14
15pub trait Storage: Send + Sync {
39 fn save(&mut self, key: &str, data: Vec<u8>) -> Result<()>;
40 fn load(&self, key: &str) -> Result<Option<Vec<u8>>>;
41 fn delete(&mut self, key: &str) -> Result<()>;
42 fn list_keys(&self) -> Result<Vec<String>>;
43
44 fn begin_transaction(&mut self) -> Result<()> {
49 Ok(())
50 }
51
52 fn commit_transaction(&mut self) -> Result<()> {
56 Ok(())
57 }
58
59 fn rollback_transaction(&mut self) -> Result<()> {
63 Ok(())
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use std::collections::HashMap;
70
71 use super::*;
72
73 struct TestClockImpl {
75 time: DateTime<Utc>,
76 }
77
78 impl Clock for TestClockImpl {
79 fn now(&self) -> DateTime<Utc> {
80 self.time
81 }
82 }
83
84 struct TestStorageImpl {
86 data: HashMap<String, Vec<u8>>,
87 }
88
89 impl Storage for TestStorageImpl {
90 fn save(&mut self, key: &str, data: Vec<u8>) -> Result<()> {
91 self.data.insert(key.to_string(), data);
92 Ok(())
93 }
94
95 fn load(&self, key: &str) -> Result<Option<Vec<u8>>> {
96 Ok(self.data.get(key).cloned())
97 }
98
99 fn delete(&mut self, key: &str) -> Result<()> {
100 self.data.remove(key);
101 Ok(())
102 }
103
104 fn list_keys(&self) -> Result<Vec<String>> {
105 Ok(self.data.keys().cloned().collect())
106 }
107 }
108
109 #[test]
110 fn test_clock_trait_works() {
111 let time = Utc::now();
112 let clock = TestClockImpl { time };
113 assert_eq!(clock.now(), time);
114 }
115
116 #[test]
117 fn test_clock_is_send_sync() {
118 fn assert_send<T: Send>() {}
119 fn assert_sync<T: Sync>() {}
120 assert_send::<Box<dyn Clock>>();
121 assert_sync::<Box<dyn Clock>>();
122 }
123
124 #[test]
125 fn test_storage_save_and_load() {
126 let mut storage = TestStorageImpl {
127 data: HashMap::new(),
128 };
129
130 let data = vec![1, 2, 3, 4];
131 storage.save("test_key", data.clone()).unwrap();
132
133 let loaded = storage.load("test_key").unwrap();
134 assert_eq!(loaded, Some(data));
135 }
136
137 #[test]
138 fn test_storage_load_nonexistent() {
139 let storage = TestStorageImpl {
140 data: HashMap::new(),
141 };
142
143 let loaded = storage.load("nonexistent").unwrap();
144 assert_eq!(loaded, None);
145 }
146
147 #[test]
148 fn test_storage_delete() {
149 let mut storage = TestStorageImpl {
150 data: HashMap::new(),
151 };
152
153 storage.save("test_key", vec![1, 2, 3]).unwrap();
154 storage.delete("test_key").unwrap();
155
156 let loaded = storage.load("test_key").unwrap();
157 assert_eq!(loaded, None);
158 }
159
160 #[test]
161 fn test_storage_is_send_sync() {
162 fn assert_send<T: Send>() {}
163 fn assert_sync<T: Sync>() {}
164 assert_send::<Box<dyn Storage>>();
165 assert_sync::<Box<dyn Storage>>();
166 }
167}