1
+ use std:: ops:: { Bound , RangeBounds } ;
2
+
1
3
use bdk_chain:: {
2
4
local_chain:: {
3
5
AlterCheckPointError , ApplyHeaderError , CannotConnectError , ChangeSet , CheckPoint ,
@@ -6,6 +8,7 @@ use bdk_chain::{
6
8
BlockId ,
7
9
} ;
8
10
use bitcoin:: { block:: Header , hashes:: Hash , BlockHash } ;
11
+ use proptest:: prelude:: * ;
9
12
10
13
#[ macro_use]
11
14
mod common;
@@ -725,3 +728,48 @@ fn local_chain_apply_header_connected_to() {
725
728
assert_eq ! ( result, exp_result, "[{}:{}] unexpected result" , i, t. name) ;
726
729
}
727
730
}
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