From: Elias Rohrer Date: Mon, 21 Aug 2023 14:17:35 +0000 (+0200) Subject: Add `TestStore` implementation of `KVStore` X-Git-Tag: v0.0.117-alpha1~24^2 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=7a656719af1cf1d124821eb385a7d88f792660b4;p=rust-lightning Add `TestStore` implementation of `KVStore` --- diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 7a9ce0691..8e2be87d8 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -38,6 +38,7 @@ use crate::util::config::UserConfig; use crate::util::test_channel_signer::{TestChannelSigner, EnforcementState}; use crate::util::logger::{Logger, Level, Record}; use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable}; +use crate::util::persist::KVStore; use bitcoin::EcdsaSighashType; use bitcoin::blockdata::constants::ChainHash; @@ -425,6 +426,97 @@ impl chainmonitor::Persist fo } } +pub(crate) struct TestStore { + persisted_bytes: Mutex>>>, + read_only: bool, +} + +impl TestStore { + pub fn new(read_only: bool) -> Self { + let persisted_bytes = Mutex::new(HashMap::new()); + Self { persisted_bytes, read_only } + } +} + +impl KVStore for TestStore { + fn read(&self, namespace: &str, sub_namespace: &str, key: &str) -> io::Result> { + let persisted_lock = self.persisted_bytes.lock().unwrap(); + let prefixed = if sub_namespace.is_empty() { + namespace.to_string() + } else { + format!("{}/{}", namespace, sub_namespace) + }; + + if let Some(outer_ref) = persisted_lock.get(&prefixed) { + if let Some(inner_ref) = outer_ref.get(key) { + let bytes = inner_ref.clone(); + Ok(bytes) + } else { + Err(io::Error::new(io::ErrorKind::NotFound, "Key not found")) + } + } else { + Err(io::Error::new(io::ErrorKind::NotFound, "Namespace not found")) + } + } + + fn write(&self, namespace: &str, sub_namespace: &str, key: &str, buf: &[u8]) -> io::Result<()> { + if self.read_only { + return Err(io::Error::new( + io::ErrorKind::PermissionDenied, + "Cannot modify read-only store", + )); + } + let mut persisted_lock = self.persisted_bytes.lock().unwrap(); + + let prefixed = if sub_namespace.is_empty() { + namespace.to_string() + } else { + format!("{}/{}", namespace, sub_namespace) + }; + let outer_e = persisted_lock.entry(prefixed).or_insert(HashMap::new()); + let mut bytes = Vec::new(); + bytes.write_all(buf)?; + outer_e.insert(key.to_string(), bytes); + Ok(()) + } + + fn remove(&self, namespace: &str, sub_namespace: &str, key: &str, _lazy: bool) -> io::Result<()> { + if self.read_only { + return Err(io::Error::new( + io::ErrorKind::PermissionDenied, + "Cannot modify read-only store", + )); + } + + let mut persisted_lock = self.persisted_bytes.lock().unwrap(); + + let prefixed = if sub_namespace.is_empty() { + namespace.to_string() + } else { + format!("{}/{}", namespace, sub_namespace) + }; + if let Some(outer_ref) = persisted_lock.get_mut(&prefixed) { + outer_ref.remove(&key.to_string()); + } + + Ok(()) + } + + fn list(&self, namespace: &str, sub_namespace: &str) -> io::Result> { + let mut persisted_lock = self.persisted_bytes.lock().unwrap(); + + let prefixed = if sub_namespace.is_empty() { + namespace.to_string() + } else { + format!("{}/{}", namespace, sub_namespace) + }; + match persisted_lock.entry(prefixed) { + hash_map::Entry::Occupied(e) => Ok(e.get().keys().cloned().collect()), + hash_map::Entry::Vacant(_) => Ok(Vec::new()), + } + } +} + pub struct TestBroadcaster { pub txn_broadcasted: Mutex>, pub blocks: Arc>>,