Skip to content

Commit f020ff1

Browse files
committed
Add TestSyncStore
We add a `KVStore` implementation that wraps all three of our `KVStore` implementation and uses them in lock step while asserting they behave identical. This will be useful for (upcoming) integration tests.
1 parent 4f256c2 commit f020ff1

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

lightning-persister/src/test_utils.rs

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
use crate::fs_store::FilesystemStore;
2+
use crate::sqlite_store::SqliteStore;
3+
14
use lightning::util::persist::{KVStore, read_channel_monitors};
25
use lightning::ln::functional_test_utils::*;
36
use lightning::chain::channelmonitor::CLOSED_CHANNEL_UPDATE_ID;
4-
use lightning::util::test_utils;
7+
use lightning::util::test_utils::{self, TestStore};
58
use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors};
69
use lightning::events::ClosureReason;
710

811
use std::io::Cursor;
912
use std::panic::RefUnwindSafe;
13+
use std::path::PathBuf;
1014

1115
pub(crate) fn do_read_write_remove_list_persist<K: KVStore + RefUnwindSafe>(kv_store: &K) {
1216
use lightning::util::ser::Readable;
@@ -101,3 +105,111 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
101105
// Make sure everything is persisted as expected after close.
102106
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
103107
}
108+
109+
// A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
110+
pub(crate) struct TestSyncStore {
111+
test_store: TestStore,
112+
fs_store: FilesystemStore,
113+
sqlite_store: SqliteStore,
114+
}
115+
116+
impl TestSyncStore {
117+
pub(crate) fn new(dest_dir: PathBuf) -> Self {
118+
let fs_store = FilesystemStore::new(dest_dir.clone());
119+
let sqlite_store = SqliteStore::new(dest_dir, Some("test_sync_db".to_string()), Some("test_sync_table".to_string()));
120+
let test_store = TestStore::new(false);
121+
Self { fs_store, sqlite_store, test_store }
122+
}
123+
}
124+
125+
impl KVStore for TestSyncStore {
126+
fn read(&self, namespace: &str, key: &str) -> std::io::Result<Vec<u8>> {
127+
let fs_res = self.fs_store.read(namespace, key);
128+
let sqlite_res = self.sqlite_store.read(namespace, key);
129+
let test_res = self.test_store.read(namespace, key);
130+
131+
match fs_res {
132+
Ok(read) => {
133+
assert_eq!(read, sqlite_res.unwrap());
134+
assert_eq!(read, test_res.unwrap());
135+
Ok(read)
136+
}
137+
Err(e) => {
138+
assert!(sqlite_res.is_err());
139+
assert_eq!(e.kind(), unsafe { sqlite_res.unwrap_err_unchecked().kind() });
140+
assert!(test_res.is_err());
141+
assert_eq!(e.kind(), unsafe { test_res.unwrap_err_unchecked().kind() });
142+
Err(e)
143+
}
144+
}
145+
}
146+
147+
fn write(&self, namespace: &str, key: &str, buf: &[u8]) -> std::io::Result<()> {
148+
let fs_res = self.fs_store.write(namespace, key, buf);
149+
let sqlite_res = self.sqlite_store.write(namespace, key, buf);
150+
let test_res = self.test_store.write(namespace, key, buf);
151+
152+
assert!(self.list(namespace).unwrap().contains(&key.to_string()));
153+
154+
match fs_res {
155+
Ok(()) => {
156+
assert!(sqlite_res.is_ok());
157+
assert!(test_res.is_ok());
158+
Ok(())
159+
}
160+
Err(e) => {
161+
assert!(sqlite_res.is_err());
162+
assert!(test_res.is_err());
163+
Err(e)
164+
}
165+
}
166+
}
167+
168+
fn remove(&self, namespace: &str, key: &str) -> std::io::Result<()> {
169+
let fs_res = self.fs_store.remove(namespace, key);
170+
let sqlite_res = self.sqlite_store.remove(namespace, key);
171+
let test_res = self.test_store.remove(namespace, key);
172+
173+
assert!(!self.list(namespace).unwrap().contains(&key.to_string()));
174+
175+
match fs_res {
176+
Ok(()) => {
177+
assert!(sqlite_res.is_ok());
178+
assert!(test_res.is_ok());
179+
Ok(())
180+
}
181+
Err(e) => {
182+
assert!(sqlite_res.is_err());
183+
assert!(test_res.is_err());
184+
Err(e)
185+
}
186+
}
187+
}
188+
189+
fn list(&self, namespace: &str) -> std::io::Result<Vec<String>> {
190+
let fs_res = self.fs_store.list(namespace);
191+
let sqlite_res = self.sqlite_store.list(namespace);
192+
let test_res = self.test_store.list(namespace);
193+
194+
match fs_res {
195+
Ok(mut list) => {
196+
list.sort();
197+
198+
let mut sqlite_list = sqlite_res.unwrap();
199+
sqlite_list.sort();
200+
assert_eq!(list, sqlite_list);
201+
202+
let mut test_list = test_res.unwrap();
203+
test_list.sort();
204+
assert_eq!(list, test_list);
205+
206+
Ok(list)
207+
}
208+
Err(e) => {
209+
assert!(sqlite_res.is_err());
210+
assert!(test_res.is_err());
211+
Err(e)
212+
}
213+
}
214+
}
215+
}

lightning/src/util/test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ impl<Signer: sign::WriteableEcdsaChannelSigner> chainmonitor::Persist<Signer> fo
317317
}
318318
}
319319

320-
pub(crate) struct TestStore {
320+
pub struct TestStore {
321321
persisted_bytes: Mutex<HashMap<String, HashMap<String, Vec<u8>>>>,
322322
did_persist: Arc<AtomicBool>,
323323
read_only: bool,

0 commit comments

Comments
 (0)