Skip to content

Commit 25a046a

Browse files
committed
Refactor test code and introduce TestSyncStore
.. which asserts that all `KVStore` implementations operatate synchronously, i.e., yield identical results given the same inputs.
1 parent e597429 commit 25a046a

File tree

5 files changed

+210
-135
lines changed

5 files changed

+210
-135
lines changed

src/io/sqlite_store/migrations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub(super) fn migrate_schema(
7070
mod tests {
7171
use crate::io::sqlite_store::SqliteStore;
7272
use crate::io::test_utils::do_read_write_remove_list_persist;
73+
use crate::test::utils::random_storage_path;
7374

7475
use lightning::util::persist::KVStore;
7576

@@ -81,7 +82,7 @@ mod tests {
8182
fn rwrl_post_schema_1_migration() {
8283
let old_schema_version = 1;
8384

84-
let mut temp_path = std::env::temp_dir();
85+
let mut temp_path = random_storage_path();
8586
temp_path.push("rwrl_post_schema_1_migration");
8687

8788
let db_file_name = "test_db".to_string();

src/io/sqlite_store/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ impl KVStore for SqliteStore {
285285
mod tests {
286286
use super::*;
287287
use crate::io::test_utils::{do_read_write_remove_list_persist, do_test_store};
288+
use crate::test::utils::random_storage_path;
288289

289290
impl Drop for SqliteStore {
290291
fn drop(&mut self) {
@@ -297,7 +298,7 @@ mod tests {
297298

298299
#[test]
299300
fn read_write_remove_list_persist() {
300-
let mut temp_path = std::env::temp_dir();
301+
let mut temp_path = random_storage_path();
301302
temp_path.push("read_write_remove_list_persist");
302303
let store = SqliteStore::new(
303304
temp_path,
@@ -310,7 +311,7 @@ mod tests {
310311

311312
#[test]
312313
fn test_sqlite_store() {
313-
let mut temp_path = std::env::temp_dir();
314+
let mut temp_path = random_storage_path();
314315
temp_path.push("test_sqlite_store");
315316
let store_0 = SqliteStore::new(
316317
temp_path.clone(),

src/io/test_utils.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use lightning::{check_added_monitors, check_closed_broadcast, check_closed_event
1515

1616
use std::panic::RefUnwindSafe;
1717
use std::path::PathBuf;
18+
use std::sync::RwLock;
1819

1920
pub(crate) fn do_read_write_remove_list_persist<K: KVStore + RefUnwindSafe>(kv_store: &K) {
2021
let data = [42u8; 32];
@@ -173,3 +174,148 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
173174
// Make sure everything is persisted as expected after close.
174175
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
175176
}
177+
178+
// A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
179+
pub(crate) struct TestSyncStore {
180+
serializer: RwLock<()>,
181+
test_store: TestStore,
182+
fs_store: FilesystemStore,
183+
sqlite_store: SqliteStore,
184+
}
185+
186+
impl TestSyncStore {
187+
pub(crate) fn new(dest_dir: PathBuf) -> Self {
188+
let serializer = RwLock::new(());
189+
let mut fs_dir = dest_dir.clone();
190+
fs_dir.push("fs_store");
191+
let fs_store = FilesystemStore::new(fs_dir);
192+
let mut sql_dir = dest_dir.clone();
193+
sql_dir.push("sqlite_store");
194+
let sqlite_store = SqliteStore::new(
195+
sql_dir,
196+
Some("test_sync_db".to_string()),
197+
Some("test_sync_table".to_string()),
198+
)
199+
.unwrap();
200+
let test_store = TestStore::new();
201+
Self { serializer, fs_store, sqlite_store, test_store }
202+
}
203+
204+
fn do_list(
205+
&self, primary_namespace: &str, secondary_namespace: &str,
206+
) -> std::io::Result<Vec<String>> {
207+
let fs_res = self.fs_store.list(primary_namespace, secondary_namespace);
208+
let sqlite_res = self.sqlite_store.list(primary_namespace, secondary_namespace);
209+
let test_res = self.test_store.list(primary_namespace, secondary_namespace);
210+
211+
match fs_res {
212+
Ok(mut list) => {
213+
list.sort();
214+
215+
let mut sqlite_list = sqlite_res.unwrap();
216+
sqlite_list.sort();
217+
assert_eq!(list, sqlite_list);
218+
219+
let mut test_list = test_res.unwrap();
220+
test_list.sort();
221+
assert_eq!(list, test_list);
222+
223+
Ok(list)
224+
}
225+
Err(e) => {
226+
assert!(sqlite_res.is_err());
227+
assert!(test_res.is_err());
228+
Err(e)
229+
}
230+
}
231+
}
232+
}
233+
234+
impl KVStore for TestSyncStore {
235+
fn read(
236+
&self, primary_namespace: &str, secondary_namespace: &str, key: &str,
237+
) -> std::io::Result<Vec<u8>> {
238+
let _guard = self.serializer.read().unwrap();
239+
240+
let fs_res = self.fs_store.read(primary_namespace, secondary_namespace, key);
241+
let sqlite_res = self.sqlite_store.read(primary_namespace, secondary_namespace, key);
242+
let test_res = self.test_store.read(primary_namespace, secondary_namespace, key);
243+
244+
match fs_res {
245+
Ok(read) => {
246+
assert_eq!(read, sqlite_res.unwrap());
247+
assert_eq!(read, test_res.unwrap());
248+
Ok(read)
249+
}
250+
Err(e) => {
251+
assert!(sqlite_res.is_err());
252+
assert_eq!(e.kind(), unsafe { sqlite_res.unwrap_err_unchecked().kind() });
253+
assert!(test_res.is_err());
254+
assert_eq!(e.kind(), unsafe { test_res.unwrap_err_unchecked().kind() });
255+
Err(e)
256+
}
257+
}
258+
}
259+
260+
fn write(
261+
&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8],
262+
) -> std::io::Result<()> {
263+
let _guard = self.serializer.write().unwrap();
264+
let fs_res = self.fs_store.write(primary_namespace, secondary_namespace, key, buf);
265+
let sqlite_res = self.sqlite_store.write(primary_namespace, secondary_namespace, key, buf);
266+
let test_res = self.test_store.write(primary_namespace, secondary_namespace, key, buf);
267+
268+
assert!(self
269+
.do_list(primary_namespace, secondary_namespace)
270+
.unwrap()
271+
.contains(&key.to_string()));
272+
273+
match fs_res {
274+
Ok(()) => {
275+
assert!(sqlite_res.is_ok());
276+
assert!(test_res.is_ok());
277+
Ok(())
278+
}
279+
Err(e) => {
280+
assert!(sqlite_res.is_err());
281+
assert!(test_res.is_err());
282+
Err(e)
283+
}
284+
}
285+
}
286+
287+
fn remove(
288+
&self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool,
289+
) -> std::io::Result<()> {
290+
let _guard = self.serializer.write().unwrap();
291+
let fs_res = self.fs_store.remove(primary_namespace, secondary_namespace, key, lazy);
292+
let sqlite_res =
293+
self.sqlite_store.remove(primary_namespace, secondary_namespace, key, lazy);
294+
let test_res = self.test_store.remove(primary_namespace, secondary_namespace, key, lazy);
295+
296+
assert!(!self
297+
.do_list(primary_namespace, secondary_namespace)
298+
.unwrap()
299+
.contains(&key.to_string()));
300+
301+
match fs_res {
302+
Ok(()) => {
303+
assert!(sqlite_res.is_ok());
304+
assert!(test_res.is_ok());
305+
Ok(())
306+
}
307+
Err(e) => {
308+
assert!(sqlite_res.is_err());
309+
assert!(test_res.is_err());
310+
Err(e)
311+
}
312+
}
313+
}
314+
315+
fn list(
316+
&self, primary_namespace: &str, secondary_namespace: &str,
317+
) -> std::io::Result<Vec<String>> {
318+
let _guard = self.serializer.read().unwrap();
319+
self.do_list(primary_namespace, secondary_namespace)
320+
}
321+
}

0 commit comments

Comments
 (0)