Skip to content

Commit a33e59c

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 5034bd0 commit a33e59c

File tree

4 files changed

+177
-129
lines changed

4 files changed

+177
-129
lines changed

src/io/test_utils.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,123 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
171171
// Make sure everything is persisted as expected after close.
172172
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
173173
}
174+
175+
// A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
176+
pub(crate) struct TestSyncStore {
177+
test_store: TestStore,
178+
fs_store: FilesystemStore,
179+
sqlite_store: SqliteStore,
180+
}
181+
182+
impl TestSyncStore {
183+
pub(crate) fn new(dest_dir: PathBuf) -> Self {
184+
let mut fs_dir = dest_dir.clone();
185+
fs_dir.push("fs_store");
186+
let fs_store = FilesystemStore::new(fs_dir);
187+
let mut sql_dir = dest_dir.clone();
188+
sql_dir.push("sqlite_store");
189+
let sqlite_store = SqliteStore::new(
190+
sql_dir,
191+
Some("test_sync_db".to_string()),
192+
Some("test_sync_table".to_string()),
193+
);
194+
let test_store = TestStore::new();
195+
Self { fs_store, sqlite_store, test_store }
196+
}
197+
}
198+
199+
impl KVStore for TestSyncStore {
200+
fn read(&self, namespace: &str, sub_namespace: &str, key: &str) -> std::io::Result<Vec<u8>> {
201+
let fs_res = self.fs_store.read(namespace, sub_namespace, key);
202+
let sqlite_res = self.sqlite_store.read(namespace, sub_namespace, key);
203+
let test_res = self.test_store.read(namespace, sub_namespace, key);
204+
205+
match fs_res {
206+
Ok(read) => {
207+
assert_eq!(read, sqlite_res.unwrap());
208+
assert_eq!(read, test_res.unwrap());
209+
Ok(read)
210+
}
211+
Err(e) => {
212+
assert!(sqlite_res.is_err());
213+
assert_eq!(e.kind(), unsafe { sqlite_res.unwrap_err_unchecked().kind() });
214+
assert!(test_res.is_err());
215+
assert_eq!(e.kind(), unsafe { test_res.unwrap_err_unchecked().kind() });
216+
Err(e)
217+
}
218+
}
219+
}
220+
221+
fn write(
222+
&self, namespace: &str, sub_namespace: &str, key: &str, buf: &[u8],
223+
) -> std::io::Result<()> {
224+
let fs_res = self.fs_store.write(namespace, sub_namespace, key, buf);
225+
let sqlite_res = self.sqlite_store.write(namespace, sub_namespace, key, buf);
226+
let test_res = self.test_store.write(namespace, sub_namespace, key, buf);
227+
228+
assert!(self.list(namespace, sub_namespace).unwrap().contains(&key.to_string()));
229+
230+
match fs_res {
231+
Ok(()) => {
232+
assert!(sqlite_res.is_ok());
233+
assert!(test_res.is_ok());
234+
Ok(())
235+
}
236+
Err(e) => {
237+
assert!(sqlite_res.is_err());
238+
assert!(test_res.is_err());
239+
Err(e)
240+
}
241+
}
242+
}
243+
244+
fn remove(
245+
&self, namespace: &str, sub_namespace: &str, key: &str, lazy: bool,
246+
) -> std::io::Result<()> {
247+
let fs_res = self.fs_store.remove(namespace, sub_namespace, key, lazy);
248+
let sqlite_res = self.sqlite_store.remove(namespace, sub_namespace, key, lazy);
249+
let test_res = self.test_store.remove(namespace, sub_namespace, key, lazy);
250+
251+
assert!(!self.list(namespace, sub_namespace).unwrap().contains(&key.to_string()));
252+
253+
match fs_res {
254+
Ok(()) => {
255+
assert!(sqlite_res.is_ok());
256+
assert!(test_res.is_ok());
257+
Ok(())
258+
}
259+
Err(e) => {
260+
assert!(sqlite_res.is_err());
261+
assert!(test_res.is_err());
262+
Err(e)
263+
}
264+
}
265+
}
266+
267+
fn list(&self, namespace: &str, sub_namespace: &str) -> std::io::Result<Vec<String>> {
268+
let fs_res = self.fs_store.list(namespace, sub_namespace);
269+
let sqlite_res = self.sqlite_store.list(namespace, sub_namespace);
270+
let test_res = self.test_store.list(namespace, sub_namespace);
271+
272+
match fs_res {
273+
Ok(mut list) => {
274+
list.sort();
275+
276+
let mut sqlite_list = sqlite_res.unwrap();
277+
sqlite_list.sort();
278+
assert_eq!(list, sqlite_list);
279+
280+
let mut test_list = test_res.unwrap();
281+
test_list.sort();
282+
assert_eq!(list, test_list);
283+
284+
Ok(list)
285+
}
286+
Err(e) => {
287+
assert!(sqlite_res.is_err());
288+
assert!(test_res.is_err());
289+
Err(e)
290+
}
291+
}
292+
}
293+
}

src/peer_store.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,11 @@ mod tests {
162162

163163
// Check we can read back what we persisted.
164164
let persisted_bytes = store
165-
.read(PEER_INFO_PERSISTENCE_NAMESPACE, PEER_INFO_PERSISTENCE_SUB_NAMESPACE, PEER_INFO_PERSISTENCE_KEY)
165+
.read(
166+
PEER_INFO_PERSISTENCE_NAMESPACE,
167+
PEER_INFO_PERSISTENCE_SUB_NAMESPACE,
168+
PEER_INFO_PERSISTENCE_KEY,
169+
)
166170
.unwrap();
167171
let deser_peer_store =
168172
PeerStore::read(&mut &persisted_bytes[..], (Arc::clone(&store), logger)).unwrap();

src/test/functional_tests.rs

Lines changed: 23 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,27 @@
11
use crate::builder::NodeBuilder;
2+
use crate::io::test_utils::TestSyncStore;
23
use crate::test::utils::*;
3-
use crate::test::utils::{expect_event, random_config};
4+
use crate::test::utils::{expect_event, random_config, setup_two_nodes};
45
use crate::{Error, Event, Node, PaymentDirection, PaymentStatus};
56

67
use bitcoin::Amount;
78
use electrsd::bitcoind::BitcoinD;
89
use electrsd::ElectrsD;
910
use lightning::util::persist::KVStore;
1011

12+
use std::sync::Arc;
13+
1114
#[test]
1215
fn channel_full_cycle() {
1316
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
14-
println!("== Node A ==");
15-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
16-
let config_a = random_config();
17-
let mut builder_a = NodeBuilder::from_config(config_a);
18-
builder_a.set_esplora_server(esplora_url.clone());
19-
let node_a = builder_a.build().unwrap();
20-
node_a.start().unwrap();
21-
22-
println!("\n== Node B ==");
23-
let config_b = random_config();
24-
let mut builder_b = NodeBuilder::from_config(config_b);
25-
builder_b.set_esplora_server(esplora_url);
26-
let node_b = builder_b.build().unwrap();
27-
node_b.start().unwrap();
28-
17+
let (node_a, node_b) = setup_two_nodes(&electrsd, false);
2918
do_channel_full_cycle(node_a, node_b, &bitcoind, &electrsd, false);
3019
}
3120

3221
#[test]
3322
fn channel_full_cycle_0conf() {
3423
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
35-
println!("== Node A ==");
36-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
37-
let config_a = random_config();
38-
let mut builder_a = NodeBuilder::from_config(config_a);
39-
builder_a.set_esplora_server(esplora_url.clone());
40-
let node_a = builder_a.build().unwrap();
41-
node_a.start().unwrap();
42-
43-
println!("\n== Node B ==");
44-
let mut config_b = random_config();
45-
config_b.trusted_peers_0conf.push(node_a.node_id());
46-
47-
let mut builder_b = NodeBuilder::from_config(config_b);
48-
builder_b.set_esplora_server(esplora_url.clone());
49-
let node_b = builder_b.build().unwrap();
50-
51-
node_b.start().unwrap();
52-
24+
let (node_a, node_b) = setup_two_nodes(&electrsd, true);
5325
do_channel_full_cycle(node_a, node_b, &bitcoind, &electrsd, true)
5426
}
5527

@@ -314,21 +286,9 @@ fn do_channel_full_cycle<K: KVStore + Sync + Send>(
314286
#[test]
315287
fn channel_open_fails_when_funds_insufficient() {
316288
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
317-
println!("== Node A ==");
318-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
319-
let config_a = random_config();
320-
let mut builder_a = NodeBuilder::from_config(config_a);
321-
builder_a.set_esplora_server(esplora_url.clone());
322-
let node_a = builder_a.build().unwrap();
323-
node_a.start().unwrap();
324-
let addr_a = node_a.new_onchain_address().unwrap();
289+
let (node_a, node_b) = setup_two_nodes(&electrsd, false);
325290

326-
println!("\n== Node B ==");
327-
let config_b = random_config();
328-
let mut builder_b = NodeBuilder::from_config(config_b);
329-
builder_b.set_esplora_server(esplora_url);
330-
let node_b = builder_b.build().unwrap();
331-
node_b.start().unwrap();
291+
let addr_a = node_a.new_onchain_address().unwrap();
332292
let addr_b = node_b.new_onchain_address().unwrap();
333293

334294
let premine_amount_sat = 100_000;
@@ -372,81 +332,33 @@ fn connect_to_public_testnet_esplora() {
372332
#[test]
373333
fn start_stop_reinit() {
374334
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
375-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
376335
let config = random_config();
377-
let mut builder = NodeBuilder::from_config(config.clone());
378-
builder.set_esplora_server(esplora_url.clone());
379-
let node = builder.build().unwrap();
380-
let expected_node_id = node.node_id();
381-
382-
let funding_address = node.new_onchain_address().unwrap();
383-
let expected_amount = Amount::from_sat(100000);
384-
385-
premine_and_distribute_funds(&bitcoind, &electrsd, vec![funding_address], expected_amount);
386-
assert_eq!(node.total_onchain_balance_sats().unwrap(), 0);
387-
388-
node.start().unwrap();
389-
assert_eq!(node.start(), Err(Error::AlreadyRunning));
390336

391-
node.sync_wallets().unwrap();
392-
assert_eq!(node.spendable_onchain_balance_sats().unwrap(), expected_amount.to_sat());
337+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
393338

394-
let log_file_symlink = format!("{}/logs/ldk_node_latest.log", config.storage_dir_path);
395-
assert!(std::path::Path::new(&log_file_symlink).is_symlink());
339+
let test_sync_store = Arc::new(TestSyncStore::new(config.storage_dir_path.clone().into()));
396340

397-
node.stop().unwrap();
398-
assert_eq!(node.stop(), Err(Error::NotRunning));
341+
let mut builder = NodeBuilder::from_config(config.clone());
342+
builder.set_esplora_server(esplora_url.clone());
399343

344+
let node = builder.build_with_store(Arc::clone(&test_sync_store)).unwrap();
400345
node.start().unwrap();
401-
assert_eq!(node.start(), Err(Error::AlreadyRunning));
402-
403-
node.stop().unwrap();
404-
assert_eq!(node.stop(), Err(Error::NotRunning));
405-
drop(node);
406-
407-
let mut new_builder = NodeBuilder::from_config(config);
408-
new_builder.set_esplora_server(esplora_url);
409-
let reinitialized_node = builder.build().unwrap();
410-
assert_eq!(reinitialized_node.node_id(), expected_node_id);
411346

412-
reinitialized_node.start().unwrap();
413-
414-
assert_eq!(
415-
reinitialized_node.spendable_onchain_balance_sats().unwrap(),
416-
expected_amount.to_sat()
417-
);
418-
419-
reinitialized_node.sync_wallets().unwrap();
420-
assert_eq!(
421-
reinitialized_node.spendable_onchain_balance_sats().unwrap(),
422-
expected_amount.to_sat()
423-
);
424-
425-
reinitialized_node.stop().unwrap();
426-
}
427-
428-
#[test]
429-
fn start_stop_reinit_fs_store() {
430-
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
431-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
432-
let config = random_config();
433-
let mut builder = NodeBuilder::from_config(config.clone());
434-
builder.set_esplora_server(esplora_url.clone());
435-
let node = builder.build_with_fs_store().unwrap();
436347
let expected_node_id = node.node_id();
348+
assert_eq!(node.start(), Err(Error::AlreadyRunning));
437349

438350
let funding_address = node.new_onchain_address().unwrap();
439351
let expected_amount = Amount::from_sat(100000);
440352

441353
premine_and_distribute_funds(&bitcoind, &electrsd, vec![funding_address], expected_amount);
442354
assert_eq!(node.total_onchain_balance_sats().unwrap(), 0);
443355

444-
node.start().unwrap();
445-
assert_eq!(node.start(), Err(Error::AlreadyRunning));
446-
447356
node.sync_wallets().unwrap();
448357
assert_eq!(node.spendable_onchain_balance_sats().unwrap(), expected_amount.to_sat());
449358

359+
let log_file_symlink = format!("{}/logs/ldk_node_latest.log", config.clone().storage_dir_path);
360+
assert!(std::path::Path::new(&log_file_symlink).is_symlink());
361+
450362
node.stop().unwrap();
451363
assert_eq!(node.stop(), Err(Error::NotRunning));
452364

@@ -457,12 +369,12 @@ fn start_stop_reinit_fs_store() {
457369
assert_eq!(node.stop(), Err(Error::NotRunning));
458370
drop(node);
459371

460-
let mut new_builder = NodeBuilder::from_config(config);
461-
new_builder.set_esplora_server(esplora_url);
462-
let reinitialized_node = builder.build_with_fs_store().unwrap();
463-
assert_eq!(reinitialized_node.node_id(), expected_node_id);
372+
let mut builder = NodeBuilder::from_config(config.clone());
373+
builder.set_esplora_server(esplora_url.clone());
464374

375+
let reinitialized_node = builder.build_with_store(Arc::clone(&test_sync_store)).unwrap();
465376
reinitialized_node.start().unwrap();
377+
assert_eq!(reinitialized_node.node_id(), expected_node_id);
466378

467379
assert_eq!(
468380
reinitialized_node.spendable_onchain_balance_sats().unwrap(),
@@ -481,20 +393,9 @@ fn start_stop_reinit_fs_store() {
481393
#[test]
482394
fn onchain_spend_receive() {
483395
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
484-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
396+
let (node_a, node_b) = setup_two_nodes(&electrsd, false);
485397

486-
let config_a = random_config();
487-
let mut builder_a = NodeBuilder::from_config(config_a);
488-
builder_a.set_esplora_server(esplora_url.clone());
489-
let node_a = builder_a.build().unwrap();
490-
node_a.start().unwrap();
491398
let addr_a = node_a.new_onchain_address().unwrap();
492-
493-
let config_b = random_config();
494-
let mut builder_b = NodeBuilder::from_config(config_b);
495-
builder_b.set_esplora_server(esplora_url);
496-
let node_b = builder_b.build().unwrap();
497-
node_b.start().unwrap();
498399
let addr_b = node_b.new_onchain_address().unwrap();
499400

500401
premine_and_distribute_funds(
@@ -537,13 +438,8 @@ fn onchain_spend_receive() {
537438
#[test]
538439
fn sign_verify_msg() {
539440
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
540-
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
541441
let config = random_config();
542-
let mut builder = NodeBuilder::from_config(config.clone());
543-
builder.set_esplora_server(esplora_url.clone());
544-
let node = builder.build().unwrap();
545-
546-
node.start().unwrap();
442+
let node = setup_node(&electrsd, config);
547443

548444
// Tests arbitrary message signing and later verification
549445
let msg = "OK computer".as_bytes();

0 commit comments

Comments
 (0)