Skip to content

Commit c7f87b5

Browse files
committed
Merge #1397: Introduce proptesting, starting with CheckPoint::range
446b045 test(chain): introduce proptest for `CheckPoint::range` (志宇) Pull request description: ### Description This is based on #1369. It made sense for me to introduce the `CheckPoint::range` test as a proptest. I think we should also start introducing it for other methods too. ### Changelog notice * Added proptest for `CheckPoint::range`. ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature Top commit has no ACKs. Tree-SHA512: 2d8aad5a1ad152413fbc716fed4a47ad621e723928c5331728da2fbade995ebd677acfa05d2e7639d74d0f66e0971c72582d9cd562ea008b012774057b480d62
2 parents 62619d3 + 446b045 commit c7f87b5

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

.github/workflows/cont_integration.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
cargo update -p zstd-sys --precise "2.0.8+zstd.1.5.5"
3434
cargo update -p time --precise "0.3.20"
3535
cargo update -p home --precise "0.5.5"
36+
cargo update -p proptest --precise "1.2.0"
3637
- name: Build
3738
run: cargo build ${{ matrix.features }}
3839
- name: Test

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ cargo update -p time --precise "0.3.20"
7575
cargo update -p jobserver --precise "0.1.26"
7676
# home 0.5.9 has MSRV 1.70.0
7777
cargo update -p home --precise "0.5.5"
78+
# proptest 1.4.0 has MSRV 1.65.0
79+
cargo update -p proptest --precise "1.2.0"
7880
```
7981

8082
## License

crates/chain/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ miniscript = { version = "10.0.0", optional = true, default-features = false }
2323

2424
[dev-dependencies]
2525
rand = "0.8"
26+
proptest = "1.2.0"
2627

2728
[features]
2829
default = ["std"]

crates/chain/tests/test_local_chain.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::{Bound, RangeBounds};
2+
13
use bdk_chain::{
24
local_chain::{
35
AlterCheckPointError, ApplyHeaderError, CannotConnectError, ChangeSet, CheckPoint,
@@ -6,6 +8,7 @@ use bdk_chain::{
68
BlockId,
79
};
810
use bitcoin::{block::Header, hashes::Hash, BlockHash};
11+
use proptest::prelude::*;
912

1013
#[macro_use]
1114
mod common;
@@ -725,3 +728,48 @@ fn local_chain_apply_header_connected_to() {
725728
assert_eq!(result, exp_result, "[{}:{}] unexpected result", i, t.name);
726729
}
727730
}
731+
732+
fn generate_height_range_bounds(
733+
height_upper_bound: u32,
734+
) -> impl Strategy<Value = (Bound<u32>, Bound<u32>)> {
735+
fn generate_height_bound(height_upper_bound: u32) -> impl Strategy<Value = Bound<u32>> {
736+
prop_oneof![
737+
(0..height_upper_bound).prop_map(Bound::Included),
738+
(0..height_upper_bound).prop_map(Bound::Excluded),
739+
Just(Bound::Unbounded),
740+
]
741+
}
742+
(
743+
generate_height_bound(height_upper_bound),
744+
generate_height_bound(height_upper_bound),
745+
)
746+
}
747+
748+
fn generate_checkpoints(max_height: u32, max_count: usize) -> impl Strategy<Value = CheckPoint> {
749+
proptest::collection::btree_set(1..max_height, 0..max_count).prop_map(|mut heights| {
750+
heights.insert(0); // must have genesis
751+
CheckPoint::from_block_ids(heights.into_iter().map(|height| {
752+
let hash = bitcoin::hashes::Hash::hash(height.to_le_bytes().as_slice());
753+
BlockId { height, hash }
754+
}))
755+
.expect("blocks must be in order as it comes from btreeset")
756+
})
757+
}
758+
759+
proptest! {
760+
#![proptest_config(ProptestConfig {
761+
..Default::default()
762+
})]
763+
764+
/// Ensure that [`CheckPoint::range`] returns the expected checkpoint heights by comparing it
765+
/// against a more primitive approach.
766+
#[test]
767+
fn checkpoint_range(
768+
range in generate_height_range_bounds(21_000),
769+
cp in generate_checkpoints(21_000, 2100)
770+
) {
771+
let exp_heights = cp.iter().map(|cp| cp.height()).filter(|h| range.contains(h)).collect::<Vec<u32>>();
772+
let heights = cp.range(range).map(|cp| cp.height()).collect::<Vec<u32>>();
773+
prop_assert_eq!(heights, exp_heights);
774+
}
775+
}

0 commit comments

Comments
 (0)