Skip to content

Commit e051962

Browse files
committed
tests: replicate data instead of synchronizing access
In the future we also want to integration-test the higher-level `BlockchainParser` struct, which needs access to a proper `ChainStorage`. Our current approach of synchronizing access to a single one would lead to problems there, as it is only available behind a mutex guard. To solve this, we replicate the test data into a new tempdir for every test, which then has exclusive access. This also gets rid of the awkward Git cleanup afterwards.
1 parent 6ff1a9c commit e051962

File tree

5 files changed

+39
-25
lines changed

5 files changed

+39
-25
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,4 @@ tracing-subscriber = { version = "0.3.17", features = [ "env-filter", "fmt", "an
2020

2121
[dev-dependencies]
2222
hex = "0.4.3"
23-
once_cell = "1.18.0"
2423
tempfile = "3.7.0"

tests/bitcoin.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
mod common;
22

3-
static STORAGE: once_cell::sync::Lazy<
4-
std::sync::Mutex<bitcoin_blockparser::parser::chain::ChainStorage>,
5-
> = once_cell::sync::Lazy::new(|| std::sync::Mutex::new(common::storage("bitcoin", 170)));
3+
fn storage() -> bitcoin_blockparser::parser::chain::ChainStorage {
4+
common::storage("bitcoin", 170)
5+
}
66

77
#[test]
88
fn test_bitcoin_genesis() {
9-
let genesis = STORAGE.lock().unwrap().get_block(0).unwrap();
9+
let genesis = storage().get_block(0).unwrap();
1010
assert_eq!(
1111
genesis,
1212
bitcoin::blockdata::constants::genesis_block(bitcoin::network::constants::Network::Bitcoin)
@@ -76,7 +76,7 @@ fn test_bitcoin_genesis() {
7676

7777
#[test]
7878
fn test_genesis_header() {
79-
let header = STORAGE.lock().unwrap().get_header(0).unwrap();
79+
let header = storage().get_header(0).unwrap();
8080
assert_eq!(
8181
header,
8282
bitcoin::blockdata::constants::genesis_block(bitcoin::network::constants::Network::Bitcoin)
@@ -86,11 +86,12 @@ fn test_genesis_header() {
8686

8787
#[test]
8888
fn test_blockdata_parsing() {
89+
let mut storage = storage();
8990
for height in 0..=169 {
90-
let block = STORAGE.lock().unwrap().get_block(height).unwrap();
91+
let block = storage.get_block(height).unwrap();
9192
assert_eq!(block.txdata.len(), 1);
9293
}
93-
let first_tx_block = STORAGE.lock().unwrap().get_block(170).unwrap();
94+
let first_tx_block = storage.get_block(170).unwrap();
9495
assert_eq!(first_tx_block.txdata.len(), 2);
9596

9697
let tx = first_tx_block.txdata.get(1).unwrap();
@@ -105,7 +106,8 @@ fn test_blockdata_parsing() {
105106

106107
#[test]
107108
fn test_timing() {
109+
let mut storage = storage();
108110
for height in 0..=169 {
109-
STORAGE.lock().unwrap().get_header(height).unwrap();
111+
storage.get_header(height).unwrap();
110112
}
111113
}

tests/common/mod.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
1+
fn copy_dir_all(
2+
src: impl AsRef<std::path::Path>,
3+
dst: impl AsRef<std::path::Path>,
4+
) -> std::io::Result<()> {
5+
std::fs::create_dir_all(&dst)?;
6+
for entry in std::fs::read_dir(src)? {
7+
let entry = entry?;
8+
let ty = entry.file_type()?;
9+
if ty.is_dir() {
10+
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
11+
} else {
12+
std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
13+
}
14+
}
15+
Ok(())
16+
}
17+
118
pub fn storage(datadir: &str, max_height: u64) -> bitcoin_blockparser::parser::chain::ChainStorage {
19+
let tempdir = tempfile::tempdir().unwrap();
20+
copy_dir_all(format!("tests/testdata/{datadir}"), &tempdir).unwrap();
221
let options = bitcoin_blockparser::ParserOptions {
322
coin: datadir.parse().unwrap(),
423
verify: true,
5-
blockchain_dir: std::path::PathBuf::from(format!("tests/testdata/{datadir}")),
24+
blockchain_dir: tempdir.into_path(),
625
range: bitcoin_blockparser::BlockHeightRange::new(0, Some(max_height)).unwrap(),
726
};
8-
let storage = bitcoin_blockparser::parser::chain::ChainStorage::new(&options).unwrap();
9-
10-
// Discard transient diff on LevelDB files
11-
std::process::Command::new("git")
12-
.args(["checkout", format!("tests/testdata/{datadir}").as_str()])
13-
.output()
14-
.unwrap();
15-
storage
27+
bitcoin_blockparser::parser::chain::ChainStorage::new(&options).unwrap()
1628
}

tests/testnet3.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
mod common;
22

3-
static STORAGE: once_cell::sync::Lazy<
4-
std::sync::Mutex<bitcoin_blockparser::parser::chain::ChainStorage>,
5-
> = once_cell::sync::Lazy::new(|| std::sync::Mutex::new(common::storage("testnet3", 120)));
3+
fn storage() -> bitcoin_blockparser::parser::chain::ChainStorage {
4+
common::storage("testnet3", 120)
5+
}
66

77
#[test]
88
fn test_blockdata_parsing() {
9-
let genesis = STORAGE.lock().unwrap().get_block(0).unwrap();
9+
let mut storage = storage();
10+
let genesis = storage.get_block(0).unwrap();
1011
assert_eq!(
1112
genesis,
1213
bitcoin::blockdata::constants::genesis_block(bitcoin::network::constants::Network::Testnet)
@@ -16,14 +17,15 @@ fn test_blockdata_parsing() {
1617
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
1718
);
1819
for height in 0..=120 {
19-
let block = STORAGE.lock().unwrap().get_block(height).unwrap();
20+
let block = storage.get_block(height).unwrap();
2021
assert_eq!(block.txdata.len(), 1);
2122
}
2223
}
2324

2425
#[test]
2526
fn test_genesis_header() {
26-
let header = STORAGE.lock().unwrap().get_header(0).unwrap();
27+
let mut storage = storage();
28+
let header = storage.get_header(0).unwrap();
2729
assert_eq!(
2830
header,
2931
bitcoin::blockdata::constants::genesis_block(bitcoin::network::constants::Network::Testnet)

0 commit comments

Comments
 (0)