diff --git a/consensus/src/round_manager_test.rs b/consensus/src/round_manager_test.rs index 2d1208f75d938..bbed79d48058e 100644 --- a/consensus/src/round_manager_test.rs +++ b/consensus/src/round_manager_test.rs @@ -1022,3 +1022,49 @@ fn safety_rules_crash() { node.next_proposal().await; }); } + +#[test] +fn echo_timeout() { + let mut runtime = consensus_runtime(); + let mut playground = NetworkPlayground::new(runtime.handle().clone()); + let mut nodes = NodeSetup::create_nodes(&mut playground, runtime.handle().clone(), 4); + runtime.spawn(playground.start()); + timed_block_on(&mut runtime, async { + // clear the message queue + for node in &mut nodes { + node.next_proposal().await; + } + // timeout 3 nodes + for node in &mut nodes[1..] { + node.round_manager + .process_local_timeout(1) + .await + .unwrap_err(); + } + let node_0 = &mut nodes[0]; + // node 0 doesn't timeout and should echo the timeout after 2 timeout message + for i in 0..3 { + let timeout_vote = node_0.next_vote().await; + let result = node_0.round_manager.process_vote_msg(timeout_vote).await; + // first and third message should not timeout + if i == 0 || i == 2 { + assert!(result.is_ok()); + } + if i == 1 { + // timeout is an Error + assert!(result.is_err()); + } + } + + let node_1 = &mut nodes[1]; + // it receives 4 timeout messages (1 from each) and doesn't echo since it already timeout + for _ in 0..4 { + let timeout_vote = node_1.next_vote().await; + node_1 + .round_manager + .process_vote_msg(timeout_vote) + .await + .unwrap(); + } + }); +} diff --git a/consensus/src/test_utils/mock_payload_manager.rs b/consensus/src/test_utils/mock_payload_manager.rs index feb3d57e30069..ee6d697d32a52 100644 --- a/consensus/src/test_utils/mock_payload_manager.rs +++ b/consensus/src/test_utils/mock_payload_manager.rs @@ -19,7 +19,7 @@ use rand::Rng; pub struct MockPayloadManager { // used non-mocked TxnManager to test interaction with shared mempool - quorum_store_client: Option, + _quorum_store_client: Option, } impl MockPayloadManager { @@ -27,13 +27,13 @@ impl MockPayloadManager { let quorum_store_client = consensus_to_quorum_store_sender.map(|s| QuorumStoreClient::new(s, 1, 1)); Self { - quorum_store_client, + _quorum_store_client: quorum_store_client, } } } // mock transaction status on the fly -fn mock_transaction_status(count: usize) -> Vec { +fn _mock_transaction_status(count: usize) -> Vec { let mut statuses = vec![]; // generate count + 1 status to mock the block metadata txn in mempool proxy for _ in 0..=count {