#![allow(clippy::arithmetic_side_effects)] use crate::{ new_service, ports::{ MockBlockImporter, MockBlockProducer, MockP2pPort, MockTransactionPool, }, service::MainTask, Config, Service, Trigger, }; use fuel_core_services::{ stream::pending, Service as StorageTrait, State, }; use fuel_core_types::{ blockchain::{ header::BlockHeader, primitives::SecretKeyWrapper, SealedBlock, }, fuel_crypto::SecretKey, fuel_tx::{ field::ScriptGasLimit, *, }, fuel_types::{ BlockHeight, ChainId, }, secrecy::Secret, services::executor::{ Error as ExecutorError, ExecutionResult, UncommittedResult, }, tai64::Tai64, }; use rand::{ prelude::StdRng, Rng, SeedableRng, }; use std::{ collections::HashSet, sync::{ Arc, Mutex as StdMutex, Mutex, }, time::Duration, }; use tokio::{ sync::{ broadcast, watch, }, time, }; mod manually_produce_tests; mod trigger_tests; struct TestContextBuilder { config: Option, txpool: Option, importer: Option, producer: Option, } fn generate_p2p_port() -> MockP2pPort { let mut p2p_port = MockP2pPort::default(); p2p_port .expect_reserved_peers_count() .returning(move || Box::pin(tokio_stream::pending())); p2p_port } impl TestContextBuilder { fn new() -> Self { Self { config: None, txpool: None, importer: None, producer: None, } } fn with_config(&mut self, config: Config) -> &mut Self { self.config = Some(config); self } fn with_txpool(&mut self, txpool: MockTransactionPool) -> &mut Self { self.txpool = Some(txpool); self } fn with_importer(&mut self, importer: MockBlockImporter) -> &mut Self { self.importer = Some(importer); self } fn with_producer(&mut self, producer: MockBlockProducer) -> &mut Self { self.producer = Some(producer); self } fn build(self) -> TestContext { let config = self.config.unwrap_or_default(); let producer = self.producer.unwrap_or_else(|| { let mut producer = MockBlockProducer::default(); producer .expect_produce_and_execute_block() .returning(|_, _, _| { Ok(UncommittedResult::new( ExecutionResult { block: Default::default(), skipped_transactions: Default::default(), tx_status: Default::default(), events: Default::default(), }, Default::default(), )) }); producer }); let importer = self.importer.unwrap_or_else(|| { let mut importer = MockBlockImporter::default(); importer.expect_commit_result().returning(|_| Ok(())); importer .expect_block_stream() .returning(|| Box::pin(tokio_stream::pending())); importer }); let txpool = self .txpool .unwrap_or_else(MockTransactionPool::no_tx_updates); let p2p_port = generate_p2p_port(); let service = new_service( &BlockHeader::new_block(BlockHeight::from(1u32), Tai64::now()), config, txpool, producer, importer, p2p_port, ); service.start().unwrap(); TestContext { service } } } struct TestContext { service: Service, } impl TestContext { async fn stop(&self) -> State { self.service.stop_and_await().await.unwrap() } } pub struct TxPoolContext { pub txpool: MockTransactionPool, pub txs: Arc>>, pub status_sender: Arc>>, } impl MockTransactionPool { fn no_tx_updates() -> Self { let mut txpool = MockTransactionPool::default(); txpool .expect_transaction_status_events() .returning(|| Box::pin(pending())); txpool } pub fn new_with_txs(txs: Vec