use crate::{ bundle_state::BundleStateWithReceipts, BlockExecutor, BlockExecutorStats, ExecutorFactory, PrunableBlockExecutor, StateProvider, }; use parking_lot::Mutex; use reth_interfaces::executor::BlockExecutionError; use reth_primitives::{Address, Block, BlockNumber, ChainSpec, PruneModes, U256}; use std::sync::Arc; /// Test executor with mocked result. #[derive(Debug)] pub struct TestExecutor(pub Option); impl BlockExecutor for TestExecutor { fn execute( &mut self, _block: &Block, _total_difficulty: U256, _senders: Option>, ) -> Result<(), BlockExecutionError> { if self.0.is_none() { return Err(BlockExecutionError::UnavailableForTest) } Ok(()) } fn execute_and_verify_receipt( &mut self, _block: &Block, _total_difficulty: U256, _senders: Option>, ) -> Result<(), BlockExecutionError> { if self.0.is_none() { return Err(BlockExecutionError::UnavailableForTest) } Ok(()) } fn take_output_state(&mut self) -> BundleStateWithReceipts { self.0.clone().unwrap_or_default() } fn stats(&self) -> BlockExecutorStats { BlockExecutorStats::default() } fn size_hint(&self) -> Option { None } } impl PrunableBlockExecutor for TestExecutor { fn set_tip(&mut self, _tip: BlockNumber) {} fn set_prune_modes(&mut self, _prune_modes: PruneModes) {} } /// Executor factory with pre-set execution results. #[derive(Clone, Debug)] pub struct TestExecutorFactory { exec_results: Arc>>, chain_spec: Arc, } impl TestExecutorFactory { /// Create new instance of test factory. pub fn new(chain_spec: Arc) -> Self { Self { exec_results: Arc::new(Mutex::new(Vec::new())), chain_spec } } /// Extend the mocked execution results pub fn extend(&self, results: Vec) { self.exec_results.lock().extend(results); } } impl ExecutorFactory for TestExecutorFactory { fn with_state<'a, SP: StateProvider + 'a>( &'a self, _sp: SP, ) -> Box { let exec_res = self.exec_results.lock().pop(); Box::new(TestExecutor(exec_res)) } fn chain_spec(&self) -> &ChainSpec { self.chain_spec.as_ref() } }