omaha_client/storage/
memory.rsuse super::*;
use futures::future::BoxFuture;
use futures::prelude::*;
use std::collections::HashMap;
use thiserror::Error;
#[derive(Debug)]
pub struct MemStorage {
data: HashMap<String, Value>,
committed: bool,
}
#[derive(Debug)]
enum Value {
String(String),
Int(i64),
Bool(bool),
}
#[derive(Debug, Error)]
pub enum StorageErrors {
#[error("Unknown error occurred")]
Unknown,
}
impl MemStorage {
pub fn new() -> Self {
MemStorage {
data: HashMap::new(),
committed: true,
}
}
pub fn committed(&self) -> bool {
self.committed
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl Default for MemStorage {
fn default() -> Self {
Self::new()
}
}
impl Storage for MemStorage {
type Error = StorageErrors;
fn get_string<'a>(&'a self, key: &'a str) -> BoxFuture<'_, Option<String>> {
future::ready(match self.data.get(key) {
Some(Value::String(s)) => Some(s.clone()),
_ => None,
})
.boxed()
}
fn get_int<'a>(&'a self, key: &'a str) -> BoxFuture<'_, Option<i64>> {
future::ready(match self.data.get(key) {
Some(Value::Int(i)) => Some(*i),
_ => None,
})
.boxed()
}
fn get_bool<'a>(&'a self, key: &'a str) -> BoxFuture<'_, Option<bool>> {
future::ready(match self.data.get(key) {
Some(Value::Bool(b)) => Some(*b),
_ => None,
})
.boxed()
}
fn set_string<'a>(
&'a mut self,
key: &'a str,
value: &'a str,
) -> BoxFuture<'_, Result<(), Self::Error>> {
self.data
.insert(key.to_string(), Value::String(value.to_string()));
self.committed = false;
future::ready(Ok(())).boxed()
}
fn set_int<'a>(
&'a mut self,
key: &'a str,
value: i64,
) -> BoxFuture<'_, Result<(), Self::Error>> {
self.data.insert(key.to_string(), Value::Int(value));
self.committed = false;
future::ready(Ok(())).boxed()
}
fn set_bool<'a>(
&'a mut self,
key: &'a str,
value: bool,
) -> BoxFuture<'_, Result<(), Self::Error>> {
self.data.insert(key.to_string(), Value::Bool(value));
self.committed = false;
future::ready(Ok(())).boxed()
}
fn remove<'a>(&'a mut self, key: &'a str) -> BoxFuture<'_, Result<(), Self::Error>> {
self.data.remove(key);
self.committed = false;
future::ready(Ok(())).boxed()
}
fn commit(&mut self) -> BoxFuture<'_, Result<(), Self::Error>> {
self.committed = true;
future::ready(Ok(())).boxed()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::storage::tests::*;
use futures::executor::block_on;
#[test]
fn test_set_get_remove_string() {
block_on(do_test_set_get_remove_string(&mut MemStorage::new()));
}
#[test]
fn test_set_get_remove_int() {
block_on(do_test_set_get_remove_int(&mut MemStorage::new()));
}
#[test]
fn test_set_option_int() {
block_on(do_test_set_option_int(&mut MemStorage::new()));
}
#[test]
fn test_set_get_remove_bool() {
block_on(do_test_set_get_remove_bool(&mut MemStorage::new()));
}
#[test]
fn test_set_get_remove_time() {
block_on(do_test_set_get_remove_time(&mut MemStorage::new()));
}
#[test]
fn test_return_none_for_wrong_value_type() {
block_on(do_return_none_for_wrong_value_type(&mut MemStorage::new()));
}
#[test]
fn test_ensure_no_error_remove_nonexistent_key() {
block_on(do_ensure_no_error_remove_nonexistent_key(
&mut MemStorage::new(),
));
}
#[test]
fn test_committed() {
block_on(async {
let mut storage = MemStorage::new();
assert!(storage.committed());
storage.set_bool("some bool key", false).await.unwrap();
assert!(!storage.committed());
storage.commit().await.unwrap();
assert!(storage.committed());
storage
.set_string("some string key", "some string")
.await
.unwrap();
assert!(!storage.committed());
storage.set_int("some int key", 42).await.unwrap();
assert!(!storage.committed());
storage.commit().await.unwrap();
assert!(storage.committed());
});
}
}