Skip to content

Commit 617d002

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 260e8ee commit 617d002

File tree

1 file changed

+115
-1
lines changed

1 file changed

+115
-1
lines changed

lightning-persister/src/test_utils.rs

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1+
use crate::fs_store::FilesystemStore;
2+
use crate::sqlite_store::SqliteStore;
3+
14
use lightning::util::persist::{KVStore, KVSTORE_NAMESPACE_KEY_MAX_LEN, read_channel_monitors};
25
use lightning::ln::functional_test_utils::{connect_block, create_announced_chan_between_nodes,
36
create_chanmon_cfgs, create_dummy_block, create_network, create_node_cfgs, create_node_chanmgrs,
47
send_payment};
8+
59
use lightning::chain::channelmonitor::CLOSED_CHANNEL_UPDATE_ID;
6-
use lightning::util::test_utils;
10+
use lightning::util::test_utils::{self, TestStore};
711
use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors};
812
use lightning::events::ClosureReason;
913

1014
use rand::distributions::Alphanumeric;
1115
use rand::{thread_rng, Rng};
1216

1317
use std::panic::RefUnwindSafe;
18+
use std::path::PathBuf;
1419

1520
pub fn random_storage_path() -> PathBuf {
1621
let mut temp_path = std::env::temp_dir();
@@ -131,3 +136,112 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
131136
// Make sure everything is persisted as expected after close.
132137
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
133138
}
139+
140+
// A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
141+
pub(crate) struct TestSyncStore {
142+
test_store: TestStore,
143+
fs_store: FilesystemStore,
144+
sqlite_store: SqliteStore,
145+
}
146+
147+
impl TestSyncStore {
148+
pub(crate) fn new(dest_dir: PathBuf) -> Self {
149+
let fs_store = FilesystemStore::new(dest_dir.clone());
150+
let sqlite_store = SqliteStore::new(dest_dir,
151+
Some("test_sync_db".to_string()), Some("test_sync_table".to_string())).unwrap();
152+
let test_store = TestStore::new(false);
153+
Self { fs_store, sqlite_store, test_store }
154+
}
155+
}
156+
157+
impl KVStore for TestSyncStore {
158+
fn read(&self, namespace: &str, sub_namespace: &str, key: &str) -> std::io::Result<Vec<u8>> {
159+
let fs_res = self.fs_store.read(namespace, sub_namespace, key);
160+
let sqlite_res = self.sqlite_store.read(namespace, sub_namespace, key);
161+
let test_res = self.test_store.read(namespace, sub_namespace, key);
162+
163+
match fs_res {
164+
Ok(read) => {
165+
assert_eq!(read, sqlite_res.unwrap());
166+
assert_eq!(read, test_res.unwrap());
167+
Ok(read)
168+
}
169+
Err(e) => {
170+
assert!(sqlite_res.is_err());
171+
assert_eq!(e.kind(), unsafe { sqlite_res.unwrap_err_unchecked().kind() });
172+
assert!(test_res.is_err());
173+
assert_eq!(e.kind(), unsafe { test_res.unwrap_err_unchecked().kind() });
174+
Err(e)
175+
}
176+
}
177+
}
178+
179+
fn write(&self, namespace: &str, sub_namespace: &str, key: &str, buf: &[u8]) -> std::io::Result<()> {
180+
let fs_res = self.fs_store.write(namespace, sub_namespace, key, buf);
181+
let sqlite_res = self.sqlite_store.write(namespace, sub_namespace, key, buf);
182+
let test_res = self.test_store.write(namespace, sub_namespace, key, buf);
183+
184+
assert!(self.list(namespace, sub_namespace).unwrap().contains(&key.to_string()));
185+
186+
match fs_res {
187+
Ok(()) => {
188+
assert!(sqlite_res.is_ok());
189+
assert!(test_res.is_ok());
190+
Ok(())
191+
}
192+
Err(e) => {
193+
assert!(sqlite_res.is_err());
194+
assert!(test_res.is_err());
195+
Err(e)
196+
}
197+
}
198+
}
199+
200+
fn remove(&self, namespace: &str, sub_namespace: &str, key: &str, lazy: bool) -> std::io::Result<()> {
201+
let fs_res = self.fs_store.remove(namespace, sub_namespace, key, lazy);
202+
let sqlite_res = self.sqlite_store.remove(namespace, sub_namespace, key, lazy);
203+
let test_res = self.test_store.remove(namespace, sub_namespace, key, lazy);
204+
205+
assert!(!self.list(namespace, sub_namespace).unwrap().contains(&key.to_string()));
206+
207+
match fs_res {
208+
Ok(()) => {
209+
assert!(sqlite_res.is_ok());
210+
assert!(test_res.is_ok());
211+
Ok(())
212+
}
213+
Err(e) => {
214+
assert!(sqlite_res.is_err());
215+
assert!(test_res.is_err());
216+
Err(e)
217+
}
218+
}
219+
}
220+
221+
fn list(&self, namespace: &str, sub_namespace: &str) -> std::io::Result<Vec<String>> {
222+
let fs_res = self.fs_store.list(namespace, sub_namespace);
223+
let sqlite_res = self.sqlite_store.list(namespace, sub_namespace);
224+
let test_res = self.test_store.list(namespace, sub_namespace);
225+
226+
match fs_res {
227+
Ok(mut list) => {
228+
list.sort();
229+
230+
let mut sqlite_list = sqlite_res.unwrap();
231+
sqlite_list.sort();
232+
assert_eq!(list, sqlite_list);
233+
234+
let mut test_list = test_res.unwrap();
235+
test_list.sort();
236+
assert_eq!(list, test_list);
237+
238+
Ok(list)
239+
}
240+
Err(e) => {
241+
assert!(sqlite_res.is_err());
242+
assert!(test_res.is_err());
243+
Err(e)
244+
}
245+
}
246+
}
247+
}

0 commit comments

Comments
 (0)