@@ -39,7 +39,7 @@ use std::time::Duration;
39
39
use std:: sync:: { Mutex , Arc } ;
40
40
use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
41
41
use std:: { cmp, mem} ;
42
- use std:: collections:: { HashMap , HashSet } ;
42
+ use std:: collections:: { HashMap , HashSet , VecDeque } ;
43
43
use chain:: keysinterface:: InMemorySigner ;
44
44
45
45
pub struct TestVecWriter ( pub Vec < u8 > ) ;
@@ -518,6 +518,7 @@ pub struct TestChainSource {
518
518
pub utxo_ret : Mutex < Result < TxOut , chain:: AccessError > > ,
519
519
pub watched_txn : Mutex < HashSet < ( Txid , Script ) > > ,
520
520
pub watched_outputs : Mutex < HashSet < ( OutPoint , Script ) > > ,
521
+ expectations : Mutex < Option < VecDeque < OnRegisterOutput > > > ,
521
522
}
522
523
523
524
impl TestChainSource {
@@ -528,8 +529,17 @@ impl TestChainSource {
528
529
utxo_ret : Mutex :: new ( Ok ( TxOut { value : u64:: max_value ( ) , script_pubkey } ) ) ,
529
530
watched_txn : Mutex :: new ( HashSet :: new ( ) ) ,
530
531
watched_outputs : Mutex :: new ( HashSet :: new ( ) ) ,
532
+ expectations : Mutex :: new ( None ) ,
531
533
}
532
534
}
535
+
536
+ /// Sets an expectation that [`chain::Filter::register_output`] is called.
537
+ pub fn expect ( & self , expectation : OnRegisterOutput ) -> & Self {
538
+ self . expectations . lock ( ) . unwrap ( )
539
+ . get_or_insert_with ( || VecDeque :: new ( ) )
540
+ . push_back ( expectation) ;
541
+ self
542
+ }
533
543
}
534
544
535
545
impl chain:: Access for TestChainSource {
@@ -548,7 +558,71 @@ impl chain::Filter for TestChainSource {
548
558
}
549
559
550
560
fn register_output ( & self , output : WatchedOutput ) -> Option < ( usize , Transaction ) > {
561
+ let dependent_tx = match & mut * self . expectations . lock ( ) . unwrap ( ) {
562
+ None => None ,
563
+ Some ( expectations) => match expectations. pop_front ( ) {
564
+ None => {
565
+ panic ! ( "Unexpected register_output: {:?}" ,
566
+ ( output. outpoint, output. script_pubkey) ) ;
567
+ } ,
568
+ Some ( expectation) => {
569
+ assert_eq ! ( output. outpoint, expectation. outpoint( ) ) ;
570
+ assert_eq ! ( & output. script_pubkey, expectation. script_pubkey( ) ) ;
571
+ expectation. returns
572
+ } ,
573
+ } ,
574
+ } ;
575
+
551
576
self . watched_outputs . lock ( ) . unwrap ( ) . insert ( ( output. outpoint , output. script_pubkey ) ) ;
552
- None
577
+ dependent_tx
578
+ }
579
+ }
580
+
581
+ impl Drop for TestChainSource {
582
+ fn drop ( & mut self ) {
583
+ if std:: thread:: panicking ( ) {
584
+ return ;
585
+ }
586
+
587
+ if let Some ( expectations) = & * self . expectations . lock ( ) . unwrap ( ) {
588
+ if !expectations. is_empty ( ) {
589
+ panic ! ( "Unsatisfied expectations: {:?}" , expectations) ;
590
+ }
591
+ }
592
+ }
593
+ }
594
+
595
+ /// An expectation that [`chain::Filter::register_output`] was called with a transaction output and
596
+ /// returns an optional dependent transaction that spends the output in the same block.
597
+ pub struct OnRegisterOutput {
598
+ /// The transaction output to register.
599
+ pub with : TxOutReference ,
600
+
601
+ /// A dependent transaction spending the output along with its position in the block.
602
+ pub returns : Option < ( usize , Transaction ) > ,
603
+ }
604
+
605
+ /// A transaction output as identified by an index into a transaction's output list.
606
+ pub struct TxOutReference ( pub Transaction , pub usize ) ;
607
+
608
+ impl OnRegisterOutput {
609
+ fn outpoint ( & self ) -> OutPoint {
610
+ let txid = self . with . 0 . txid ( ) ;
611
+ let index = self . with . 1 as u16 ;
612
+ OutPoint { txid, index }
613
+ }
614
+
615
+ fn script_pubkey ( & self ) -> & Script {
616
+ let index = self . with . 1 ;
617
+ & self . with . 0 . output [ index] . script_pubkey
618
+ }
619
+ }
620
+
621
+ impl std:: fmt:: Debug for OnRegisterOutput {
622
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
623
+ f. debug_struct ( "OnRegisterOutput" )
624
+ . field ( "outpoint" , & self . outpoint ( ) )
625
+ . field ( "script_pubkey" , self . script_pubkey ( ) )
626
+ . finish ( )
553
627
}
554
628
}
0 commit comments