use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) struct MockKey {
pub op: MockOp,
pub pk: String,
pub sk: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) enum MockOp {
Get,
Put,
Delete,
}
#[derive(Clone)]
pub(crate) enum MockResult {
OkGet(Option<Vec<u8>>),
OkVoid,
Err(String),
}
#[derive(Clone)]
pub(crate) struct MockRule {
pub key: MockKey,
pub result: MockResult,
}
#[derive(Clone, Default)]
pub(crate) struct MockState {
rules: Arc<Mutex<VecDeque<MockRule>>>,
}
impl MockState {
pub(crate) fn push(&self, rule: MockRule) {
self.rules.lock().unwrap().push_back(rule);
}
pub(crate) fn try_match(&self, op: MockOp, pk: &str, sk: &str) -> Option<MockResult> {
let mut rules = self.rules.lock().unwrap();
let pos = rules
.iter()
.position(|r| r.key.op == op && r.key.pk == pk && r.key.sk == sk)?;
Some(rules.remove(pos).unwrap().result)
}
pub(crate) fn clear(&self) {
self.rules.lock().unwrap().clear();
}
}
pub struct MockGetBuilder<'a> {
db: &'a crate::Database,
pk: String,
sk: String,
}
impl<'a> MockGetBuilder<'a> {
pub(crate) fn new(db: &'a crate::Database, pk: String, sk: String) -> Self {
Self { db, pk, sk }
}
pub fn returns(self, data: impl Into<Vec<u8>>) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Get,
pk: self.pk,
sk: self.sk,
},
result: MockResult::OkGet(Some(data.into())),
});
}
pub fn returns_none(self) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Get,
pk: self.pk,
sk: self.sk,
},
result: MockResult::OkGet(None),
});
}
pub fn returns_err(self, msg: impl Into<String>) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Get,
pk: self.pk,
sk: self.sk,
},
result: MockResult::Err(msg.into()),
});
}
}
pub struct MockPutBuilder<'a> {
db: &'a crate::Database,
pk: String,
sk: String,
}
impl<'a> MockPutBuilder<'a> {
pub(crate) fn new(db: &'a crate::Database, pk: String, sk: String) -> Self {
Self { db, pk, sk }
}
pub fn returns_ok(self) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Put,
pk: self.pk,
sk: self.sk,
},
result: MockResult::OkVoid,
});
}
pub fn returns_err(self, msg: impl Into<String>) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Put,
pk: self.pk,
sk: self.sk,
},
result: MockResult::Err(msg.into()),
});
}
}
pub struct MockDeleteBuilder<'a> {
db: &'a crate::Database,
pk: String,
sk: String,
}
impl<'a> MockDeleteBuilder<'a> {
pub(crate) fn new(db: &'a crate::Database, pk: String, sk: String) -> Self {
Self { db, pk, sk }
}
pub fn returns_ok(self) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Delete,
pk: self.pk,
sk: self.sk,
},
result: MockResult::OkVoid,
});
}
pub fn returns_err(self, msg: impl Into<String>) {
self.db.add_mock_rule(MockRule {
key: MockKey {
op: MockOp::Delete,
pk: self.pk,
sk: self.sk,
},
result: MockResult::Err(msg.into()),
});
}
}