Skip to content

Commit

Permalink
unit test for reject
Browse files Browse the repository at this point in the history
  • Loading branch information
mwtian committed Feb 28, 2024
1 parent dbbdb27 commit 64c2c21
Showing 1 changed file with 96 additions and 9 deletions.
105 changes: 96 additions & 9 deletions consensus/core/src/block_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,12 @@ impl BlockManager {

#[cfg(test)]
mod tests {
use crate::block::{Block, BlockAPI, Round, TestBlock, VerifiedBlock};
use crate::block::{Block, BlockAPI, BlockRef, Round, SignedBlock, TestBlock, VerifiedBlock};
use crate::block_manager::BlockManager;
use crate::block_verifier::NoopBlockVerifier;
use crate::block_verifier::{BlockVerifier, NoopBlockVerifier};
use crate::context::Context;
use crate::dag_state::DagState;
use crate::error::{ConsensusError, ConsensusResult};
use crate::storage::mem_store::MemStore;
use parking_lot::RwLock;
use rand::prelude::StdRng;
Expand Down Expand Up @@ -433,13 +434,8 @@ mod tests {
let (context, _key_pairs) = Context::new_for_test(4);
let context = Arc::new(context);

// create a DAG of 3 rounds
let all_blocks = dag(context.clone(), 3);
// keep only the non-genesis blocks
let mut all_blocks = all_blocks
.into_iter()
.filter(|block| block.round() > 0)
.collect::<Vec<_>>();
// create a DAG of rounds 1 ~ 3
let mut all_blocks = dag(context.clone(), 3);

// Now randomize the sequence of sending the blocks to block manager. In the end all the blocks should be uniquely
// suspended and no missing blocks should exist.
Expand Down Expand Up @@ -483,6 +479,7 @@ mod tests {
let mut this_round_blocks = Vec::new();
for (index, _authority) in context.committee.authorities() {
let block = TestBlock::new(round as Round, index.value() as u32)
.set_timestamp_ms(round * 1000)
.set_ancestors(last_round_blocks.iter().map(|b| b.reference()).collect())
.build();

Expand All @@ -493,4 +490,94 @@ mod tests {
}
all_blocks
}
struct TestBlockVerifier {
fail: BTreeSet<BlockRef>,
}

impl TestBlockVerifier {
fn new(fail: BTreeSet<BlockRef>) -> Self {
Self { fail }
}
}

impl BlockVerifier for TestBlockVerifier {
fn verify(&self, _block: &SignedBlock) -> ConsensusResult<()> {
Ok(())
}

fn check_ancestors(
&self,
block: &VerifiedBlock,
_ancestors: &[VerifiedBlock],
) -> ConsensusResult<()> {
if self.fail.contains(&block.reference()) {
Err(ConsensusError::InvalidBlockTimestamp {
max_timestamp_ms: 0,
block_timestamp_ms: block.timestamp_ms(),
})
} else {
Ok(())
}
}
}

#[test]
fn reject_blocks_failing_verifications() {
// GIVEN
let (context, _key_pairs) = Context::new_for_test(4);
let context = Arc::new(context);

// create a DAG of rounds 1 ~ 5.
let all_blocks = dag(context.clone(), 5);

// Create a test verifier that fails the blocks of round 3
let test_verifier = TestBlockVerifier::new(
all_blocks
.iter()
.filter(|block| block.round() == 3)
.map(|block| block.reference())
.collect(),
);

// Create BlockManager.
let store = Arc::new(MemStore::new());
let dag_state = Arc::new(RwLock::new(DagState::new(context.clone(), store.clone())));
let mut block_manager =
BlockManager::new(context.clone(), dag_state, Arc::new(test_verifier));

// Try to accept blocks from round 2 ~ 5 into block manager. All of them should be suspended.
let (accepted_blocks, missing_refs) = block_manager.try_accept_blocks(
all_blocks
.iter()
.filter(|block| block.round() > 1)
.cloned()
.collect(),
);

// Missing refs should all come from round 1.
assert!(accepted_blocks.is_empty());
assert_eq!(missing_refs.len(), 4);
missing_refs.iter().for_each(|missing_ref| {
assert_eq!(missing_ref.round, 1);
});

// Now add round 1 blocks into block manager.
let (accepted_blocks, missing_refs) = block_manager.try_accept_blocks(
all_blocks
.iter()
.filter(|block| block.round() == 1)
.cloned()
.collect(),
);

// Only round 1 and round 2 blocks should be accepted.
assert_eq!(accepted_blocks.len(), 8);
accepted_blocks.iter().for_each(|block| {
assert!(block.round() <= 2);
});
assert!(missing_refs.is_empty());

// Other blocks should be rejected and there should be no remaining suspended block.
assert!(block_manager.suspended_blocks().is_empty());
}
}

0 comments on commit 64c2c21

Please sign in to comment.