Skip to content

Commit

Permalink
Move the queued_blocks tests into their own module
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Sep 15, 2022
1 parent a2c7b21 commit 4d3cfd6
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 139 deletions.
142 changes: 3 additions & 139 deletions zebra-state/src/service/queued_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use zebra_chain::{block, transparent};

use crate::{BoxError, FinalizedBlock, PreparedBlock};

#[cfg(test)]
mod tests;

/// A queued finalized block, and its corresponding [`Result`] channel.
pub type QueuedFinalized = (
FinalizedBlock,
Expand Down Expand Up @@ -188,142 +191,3 @@ impl QueuedBlocks {
self.known_utxos.get(outpoint).cloned()
}
}

// TODO: move these tests into their own `tests/vectors.rs` module
#[cfg(test)]
mod tests {
use std::sync::Arc;

use tokio::sync::oneshot;
use zebra_chain::{block::Block, serialization::ZcashDeserializeInto};
use zebra_test::prelude::*;

use crate::{arbitrary::Prepare, tests::FakeChainHelper};

use super::*;

// Quick helper trait for making queued blocks with throw away channels
trait IntoQueued {
fn into_queued(self) -> QueuedNonFinalized;
}

impl IntoQueued for Arc<Block> {
fn into_queued(self) -> QueuedNonFinalized {
let (rsp_tx, _) = oneshot::channel();
(self.prepare(), rsp_tx)
}
}

#[test]
fn dequeue_gives_right_children() -> Result<()> {
let _init_guard = zebra_test::init();

let block1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
let child1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419201_BYTES.zcash_deserialize_into()?;
let child2 = block1.make_fake_child();

let parent = block1.header.previous_block_hash;

let mut queue = QueuedBlocks::default();
// Empty to start
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert_eq!(0, queue.known_utxos.len());

// Inserting the first block gives us 1 in each table, and some UTXOs
queue.queue(block1.clone().into_queued());
assert_eq!(1, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert_eq!(2, queue.known_utxos.len());

// The second gives us another in each table because its a child of the first,
// and a lot of UTXOs
queue.queue(child1.clone().into_queued());
assert_eq!(2, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(632, queue.known_utxos.len());

// The 3rd only increments blocks, because it is also a child of the
// first block, so for the second and third tables it gets added to the
// existing HashSet value
queue.queue(child2.clone().into_queued());
assert_eq!(3, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(634, queue.known_utxos.len());

// Dequeueing the first block removes 1 block from each list
let children = queue.dequeue_children(parent);
assert_eq!(1, children.len());
assert_eq!(block1, children[0].0.block);
assert_eq!(2, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert_eq!(632, queue.known_utxos.len());

// Dequeueing the children of the first block removes both of the other
// blocks, and empties all lists
let parent = children[0].0.block.hash();
let children = queue.dequeue_children(parent);
assert_eq!(2, children.len());
assert!(children
.iter()
.any(|(block, _)| block.hash == child1.hash()));
assert!(children
.iter()
.any(|(block, _)| block.hash == child2.hash()));
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert_eq!(0, queue.known_utxos.len());

Ok(())
}

#[test]
fn prune_removes_right_children() -> Result<()> {
let _init_guard = zebra_test::init();

let block1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
let child1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419201_BYTES.zcash_deserialize_into()?;
let child2 = block1.make_fake_child();

let mut queue = QueuedBlocks::default();
queue.queue(block1.clone().into_queued());
queue.queue(child1.clone().into_queued());
queue.queue(child2.clone().into_queued());
assert_eq!(3, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(634, queue.known_utxos.len());

// Pruning the first height removes only block1
queue.prune_by_height(block1.coinbase_height().unwrap());
assert_eq!(2, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert!(queue.get_mut(&block1.hash()).is_none());
assert!(queue.get_mut(&child1.hash()).is_some());
assert!(queue.get_mut(&child2.hash()).is_some());
assert_eq!(632, queue.known_utxos.len());

// Pruning the children of the first block removes both of the other
// blocks, and empties all lists
queue.prune_by_height(child1.coinbase_height().unwrap());
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert!(queue.get_mut(&child1.hash()).is_none());
assert!(queue.get_mut(&child2.hash()).is_none());
assert_eq!(0, queue.known_utxos.len());

Ok(())
}
}
3 changes: 3 additions & 0 deletions zebra-state/src/service/queued_blocks/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! Tests for block queues.
mod vectors;
139 changes: 139 additions & 0 deletions zebra-state/src/service/queued_blocks/tests/vectors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
//! Fixed test vectors for block queues.
use std::sync::Arc;

use tokio::sync::oneshot;

use zebra_chain::{block::Block, serialization::ZcashDeserializeInto};
use zebra_test::prelude::*;

use crate::{
arbitrary::Prepare,
service::queued_blocks::{QueuedBlocks, QueuedNonFinalized},
tests::FakeChainHelper,
};

// Quick helper trait for making queued blocks with throw away channels
trait IntoQueued {
fn into_queued(self) -> QueuedNonFinalized;
}

impl IntoQueued for Arc<Block> {
fn into_queued(self) -> QueuedNonFinalized {
let (rsp_tx, _) = oneshot::channel();
(self.prepare(), rsp_tx)
}
}

#[test]
fn dequeue_gives_right_children() -> Result<()> {
let _init_guard = zebra_test::init();

let block1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
let child1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419201_BYTES.zcash_deserialize_into()?;
let child2 = block1.make_fake_child();

let parent = block1.header.previous_block_hash;

let mut queue = QueuedBlocks::default();
// Empty to start
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert_eq!(0, queue.known_utxos.len());

// Inserting the first block gives us 1 in each table, and some UTXOs
queue.queue(block1.clone().into_queued());
assert_eq!(1, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert_eq!(2, queue.known_utxos.len());

// The second gives us another in each table because its a child of the first,
// and a lot of UTXOs
queue.queue(child1.clone().into_queued());
assert_eq!(2, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(632, queue.known_utxos.len());

// The 3rd only increments blocks, because it is also a child of the
// first block, so for the second and third tables it gets added to the
// existing HashSet value
queue.queue(child2.clone().into_queued());
assert_eq!(3, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(634, queue.known_utxos.len());

// Dequeueing the first block removes 1 block from each list
let children = queue.dequeue_children(parent);
assert_eq!(1, children.len());
assert_eq!(block1, children[0].0.block);
assert_eq!(2, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert_eq!(632, queue.known_utxos.len());

// Dequeueing the children of the first block removes both of the other
// blocks, and empties all lists
let parent = children[0].0.block.hash();
let children = queue.dequeue_children(parent);
assert_eq!(2, children.len());
assert!(children
.iter()
.any(|(block, _)| block.hash == child1.hash()));
assert!(children
.iter()
.any(|(block, _)| block.hash == child2.hash()));
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert_eq!(0, queue.known_utxos.len());

Ok(())
}

#[test]
fn prune_removes_right_children() -> Result<()> {
let _init_guard = zebra_test::init();

let block1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into()?;
let child1: Arc<Block> =
zebra_test::vectors::BLOCK_MAINNET_419201_BYTES.zcash_deserialize_into()?;
let child2 = block1.make_fake_child();

let mut queue = QueuedBlocks::default();
queue.queue(block1.clone().into_queued());
queue.queue(child1.clone().into_queued());
queue.queue(child2.clone().into_queued());
assert_eq!(3, queue.blocks.len());
assert_eq!(2, queue.by_parent.len());
assert_eq!(2, queue.by_height.len());
assert_eq!(634, queue.known_utxos.len());

// Pruning the first height removes only block1
queue.prune_by_height(block1.coinbase_height().unwrap());
assert_eq!(2, queue.blocks.len());
assert_eq!(1, queue.by_parent.len());
assert_eq!(1, queue.by_height.len());
assert!(queue.get_mut(&block1.hash()).is_none());
assert!(queue.get_mut(&child1.hash()).is_some());
assert!(queue.get_mut(&child2.hash()).is_some());
assert_eq!(632, queue.known_utxos.len());

// Pruning the children of the first block removes both of the other
// blocks, and empties all lists
queue.prune_by_height(child1.coinbase_height().unwrap());
assert_eq!(0, queue.blocks.len());
assert_eq!(0, queue.by_parent.len());
assert_eq!(0, queue.by_height.len());
assert!(queue.get_mut(&child1.hash()).is_none());
assert!(queue.get_mut(&child2.hash()).is_none());
assert_eq!(0, queue.known_utxos.len());

Ok(())
}

0 comments on commit 4d3cfd6

Please sign in to comment.