1use crate::encoding::{self, ContentEncoding, MAX_INFLATED_BYTES};
15use crate::key::check_prefix;
16use crate::{clip, Bytes, Cond, Error, Key, Meta, Object, ObjectStore, Result, Stat};
17use std::collections::{BTreeMap, VecDeque};
18use std::future::{ready, Ready};
19use std::ops::Range;
20use std::sync::Mutex;
21
22#[derive(Debug)]
24#[non_exhaustive]
25pub enum Fault {
26 Pass,
29 Fail(Error),
31 LostResponse(Error),
33}
34
35#[derive(Debug, Clone)]
37struct Stored {
38 obj: Object,
39 encoding: Option<ContentEncoding>,
40}
41
42impl Stored {
43 fn meta(&self, key: String) -> Meta {
44 Meta { key, size: self.obj.bytes.len() as u64, generation: self.obj.generation }
45 }
46}
47
48#[derive(Debug, Default)]
49struct Inner {
50 objects: BTreeMap<String, Stored>,
51 next_generation: u64,
52 faults: VecDeque<Fault>,
53 ops: u64,
54}
55
56#[derive(Debug)]
59pub struct Mem {
60 inner: Mutex<Inner>,
61 max_inflated: u64,
63}
64
65impl Default for Mem {
66 fn default() -> Self {
67 Self { inner: Mutex::default(), max_inflated: MAX_INFLATED_BYTES }
68 }
69}
70
71impl Mem {
72 #[must_use]
75 pub fn with_max_inflated(mut self, limit: u64) -> Self {
76 self.max_inflated = limit;
77 self
78 }
79
80 pub fn inject(&self, fault: Fault) {
82 self.lock().faults.push_back(fault);
83 }
84
85 pub fn inject_after(&self, skip: u64, fault: Fault) {
88 let mut g = self.lock();
89 for _ in 0..skip {
90 g.faults.push_back(Fault::Pass);
91 }
92 g.faults.push_back(fault);
93 }
94
95 pub fn clear_faults(&self) {
97 self.lock().faults.clear();
98 }
99
100 #[must_use]
102 pub fn ops(&self) -> u64 {
103 self.lock().ops
104 }
105
106 #[must_use]
108 pub fn keys(&self) -> Vec<String> {
109 self.lock().objects.keys().cloned().collect()
110 }
111
112 fn lock(&self) -> std::sync::MutexGuard<'_, Inner> {
113 self.inner.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
117 }
118
119 fn put_stored(
120 &self,
121 key: &str,
122 body: Bytes,
123 cond: Cond,
124 encoding: Option<ContentEncoding>,
125 ) -> Result<u64> {
126 let k = Key::parse(key)?;
127 self.run(|g| {
128 let current = g.objects.get(k.as_str()).map(|o| o.obj.generation);
129 match (cond, current) {
130 (Cond::CreateOnly, Some(_)) => return Err(Error::Conflict),
131 (Cond::IfGeneration(want), cur) if cur != Some(want) => {
132 return Err(Error::PreconditionFailed)
133 }
134 _ => {}
135 }
136 g.next_generation += 1;
137 let generation = g.next_generation;
138 let obj = Object { bytes: body, generation };
139 g.objects.insert(k.as_str().to_owned(), Stored { obj, encoding });
140 Ok(generation)
141 })
142 }
143
144 fn run<T>(&self, op: impl FnOnce(&mut Inner) -> Result<T>) -> Result<T> {
145 let mut g = self.lock();
146 g.ops += 1;
147 match g.faults.pop_front() {
148 Some(Fault::Fail(e)) => Err(e),
149 Some(Fault::LostResponse(e)) => {
150 let _ = op(&mut g);
151 Err(e)
152 }
153 Some(Fault::Pass) | None => op(&mut g),
154 }
155 }
156}
157
158impl ObjectStore for Mem {
159 type Get<'a> = Ready<Result<Option<Object>>>;
160 type GetRange<'a> = Ready<Result<Bytes>>;
161 type Head<'a> = Ready<Result<Option<Meta>>>;
162 type Put<'a> = Ready<Result<u64>>;
163 type List<'a> = Ready<Result<Vec<Meta>>>;
164 type Delete<'a> = Ready<Result<()>>;
165
166 fn get<'a>(&'a self, key: &'a str) -> Self::Get<'a> {
167 let stored =
168 Key::parse(key).and_then(|k| self.run(|g| Ok(g.objects.get(k.as_str()).cloned())));
169 ready(stored.and_then(|s| {
170 s.map(|Stored { obj, encoding }| match encoding {
171 None => Ok(obj),
172 Some(e) => Ok(Object {
173 bytes: encoding::decode(e, &obj.bytes, self.max_inflated)?,
174 generation: obj.generation,
175 }),
176 })
177 .transpose()
178 }))
179 }
180
181 fn get_range<'a>(&'a self, key: &'a str, range: Range<u64>) -> Self::GetRange<'a> {
182 ready(Key::parse(key).and_then(|k| {
183 self.run(|g| {
184 let o = g.objects.get(k.as_str()).ok_or(Error::NotFound)?;
185 if let Some(e) = o.encoding {
186 return Err(Error::EncodedRange { encoding: e.as_str().into() });
187 }
188 Ok(o.obj.bytes.slice(clip(&range, o.obj.bytes.len() as u64)))
189 })
190 }))
191 }
192
193 fn head<'a>(&'a self, key: &'a str) -> Self::Head<'a> {
194 ready(Key::parse(key).and_then(|k| {
195 self.run(|g| Ok(g.objects.get(k.as_str()).map(|o| o.meta(k.as_str().to_owned()))))
196 }))
197 }
198
199 fn put<'a>(&'a self, key: &'a str, body: Bytes, cond: Cond) -> Self::Put<'a> {
200 ready(self.put_stored(key, body, cond, None))
201 }
202
203 fn list<'a>(&'a self, prefix: &'a str) -> Self::List<'a> {
204 ready(check_prefix(prefix).and_then(|()| {
205 self.run(|g| {
206 Ok(g.objects
207 .range(prefix.to_owned()..)
208 .take_while(|(k, _)| k.starts_with(prefix))
209 .map(|(k, o)| o.meta(k.clone()))
210 .collect())
211 })
212 }))
213 }
214
215 fn delete<'a>(&'a self, key: &'a str) -> Self::Delete<'a> {
216 ready(Key::parse(key).and_then(|k| {
217 self.run(|g| {
218 g.objects.remove(k.as_str());
219 Ok(())
220 })
221 }))
222 }
223
224 fn put_encoded<'a>(
225 &'a self,
226 key: &'a str,
227 body: Bytes,
228 cond: Cond,
229 encoding: ContentEncoding,
230 ) -> impl std::future::Future<Output = Result<u64>> + 'a {
231 ready(Key::parse(key).and_then(|_| {
233 let stored = encoding::encode(encoding, &body)?;
234 self.put_stored(key, stored, cond, Some(encoding))
235 }))
236 }
237
238 fn stat<'a>(
239 &'a self,
240 key: &'a str,
241 ) -> impl std::future::Future<Output = Result<Option<Stat>>> + 'a {
242 ready(Key::parse(key).and_then(|k| {
243 self.run(|g| {
244 Ok(g.objects.get(k.as_str()).map(|o| Stat {
245 meta: o.meta(k.as_str().to_owned()),
246 content_encoding: o.encoding,
247 }))
248 })
249 }))
250 }
251
252 fn list_stat<'a>(
253 &'a self,
254 prefix: &'a str,
255 ) -> impl std::future::Future<Output = Result<Vec<Stat>>> + 'a {
256 ready(check_prefix(prefix).and_then(|()| {
257 self.run(|g| {
258 Ok(g.objects
259 .range(prefix.to_owned()..)
260 .take_while(|(k, _)| k.starts_with(prefix))
261 .map(|(k, o)| Stat { meta: o.meta(k.clone()), content_encoding: o.encoding })
262 .collect())
263 })
264 }))
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn inject_after_targets_the_nth_operation() {
274 let m = Mem::default();
275 m.inject_after(2, Fault::Fail(Error::unavailable("boom", true)));
276 let put = |k| futures::executor::block_on(m.put(k, Bytes::new(), Cond::None));
277 assert!(put("a").is_ok());
278 assert!(put("b").is_ok());
279 assert!(put("c").is_err());
280 assert!(put("d").is_ok());
281 }
282 use futures::executor::block_on;
283
284 #[test]
285 fn faults_apply_in_order() {
286 let m = Mem::default();
287 m.inject(Fault::LostResponse(Error::unavailable("lost", true)));
288 m.inject(Fault::Fail(Error::unavailable("down", true)));
289 assert!(block_on(m.put("a", Bytes::from_static(b"1"), Cond::CreateOnly)).is_err());
290 assert_eq!(block_on(m.get("a")).unwrap_err().to_string(), "store unavailable: down");
291 assert!(block_on(m.get("a")).unwrap().is_some(), "the lost-response write was applied");
292 assert!(matches!(
293 block_on(m.put("a", Bytes::new(), Cond::CreateOnly)),
294 Err(Error::Conflict)
295 ));
296 assert_eq!(m.ops(), 4);
297 }
298}