Skip to content

Commit a5d704e

Browse files
committed
Add TestStore implementation of KVStore
1 parent 4ed1a0b commit a5d704e

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

lightning/src/util/test_utils.rs

+92
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use crate::util::config::UserConfig;
3838
use crate::util::test_channel_signer::{TestChannelSigner, EnforcementState};
3939
use crate::util::logger::{Logger, Level, Record};
4040
use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable};
41+
use crate::util::persist::KVStore;
4142

4243
use bitcoin::EcdsaSighashType;
4344
use bitcoin::blockdata::constants::ChainHash;
@@ -425,6 +426,97 @@ impl<Signer: sign::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> fo
425426
}
426427
}
427428

429+
pub(crate) struct TestStore {
430+
persisted_bytes: Mutex<HashMap<String, HashMap<String, Vec<u8>>>>,
431+
read_only: bool,
432+
}
433+
434+
impl TestStore {
435+
pub fn new(read_only: bool) -> Self {
436+
let persisted_bytes = Mutex::new(HashMap::new());
437+
Self { persisted_bytes, read_only }
438+
}
439+
}
440+
441+
impl KVStore for TestStore {
442+
fn read(&self, namespace: &str, sub_namespace: &str, key: &str) -> io::Result<Vec<u8>> {
443+
let persisted_lock = self.persisted_bytes.lock().unwrap();
444+
let prefixed = if sub_namespace.is_empty() {
445+
namespace.to_string()
446+
} else {
447+
format!("{}/{}", namespace, sub_namespace)
448+
};
449+
450+
if let Some(outer_ref) = persisted_lock.get(&prefixed) {
451+
if let Some(inner_ref) = outer_ref.get(key) {
452+
let bytes = inner_ref.clone();
453+
Ok(bytes)
454+
} else {
455+
Err(io::Error::new(io::ErrorKind::NotFound, "Key not found"))
456+
}
457+
} else {
458+
Err(io::Error::new(io::ErrorKind::NotFound, "Namespace not found"))
459+
}
460+
}
461+
462+
fn write(&self, namespace: &str, sub_namespace: &str, key: &str, buf: &[u8]) -> io::Result<()> {
463+
if self.read_only {
464+
return Err(io::Error::new(
465+
io::ErrorKind::PermissionDenied,
466+
"Cannot modify read-only store",
467+
));
468+
}
469+
let mut persisted_lock = self.persisted_bytes.lock().unwrap();
470+
471+
let prefixed = if sub_namespace.is_empty() {
472+
namespace.to_string()
473+
} else {
474+
format!("{}/{}", namespace, sub_namespace)
475+
};
476+
let outer_e = persisted_lock.entry(prefixed).or_insert(HashMap::new());
477+
let mut bytes = Vec::new();
478+
bytes.write_all(buf)?;
479+
outer_e.insert(key.to_string(), bytes);
480+
Ok(())
481+
}
482+
483+
fn remove(&self, namespace: &str, sub_namespace: &str, key: &str, _lazy: bool) -> io::Result<()> {
484+
if self.read_only {
485+
return Err(io::Error::new(
486+
io::ErrorKind::PermissionDenied,
487+
"Cannot modify read-only store",
488+
));
489+
}
490+
491+
let mut persisted_lock = self.persisted_bytes.lock().unwrap();
492+
493+
let prefixed = if sub_namespace.is_empty() {
494+
namespace.to_string()
495+
} else {
496+
format!("{}/{}", namespace, sub_namespace)
497+
};
498+
if let Some(outer_ref) = persisted_lock.get_mut(&prefixed) {
499+
outer_ref.remove(&key.to_string());
500+
}
501+
502+
Ok(())
503+
}
504+
505+
fn list(&self, namespace: &str, sub_namespace: &str) -> io::Result<Vec<String>> {
506+
let mut persisted_lock = self.persisted_bytes.lock().unwrap();
507+
508+
let prefixed = if sub_namespace.is_empty() {
509+
namespace.to_string()
510+
} else {
511+
format!("{}/{}", namespace, sub_namespace)
512+
};
513+
match persisted_lock.entry(prefixed) {
514+
hash_map::Entry::Occupied(e) => Ok(e.get().keys().cloned().collect()),
515+
hash_map::Entry::Vacant(_) => Ok(Vec::new()),
516+
}
517+
}
518+
}
519+
428520
pub struct TestBroadcaster {
429521
pub txn_broadcasted: Mutex<Vec<Transaction>>,
430522
pub blocks: Arc<Mutex<Vec<(Block, u32)>>>,

0 commit comments

Comments
 (0)