Rewrite zebra-state tests to use transcripts.

This makes adding more tests easier.
This commit is contained in:
Henry de Valence 2020-06-22 21:31:44 -07:00
parent e8d42264e8
commit 87a8d328d5
4 changed files with 100 additions and 161 deletions

1
Cargo.lock generated
View File

@ -2385,6 +2385,7 @@ dependencies = [
"futures",
"hex",
"lazy_static",
"once_cell",
"serde",
"sled",
"spandoc",

View File

@ -26,3 +26,4 @@ tracing-error = "0.1.2"
tracing-subscriber = "0.2.6"
tempdir = "0.3.7"
color-eyre = "0.5"
once_cell = "1.4"

View File

@ -42,7 +42,7 @@ impl Default for Config {
}
}
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
/// A state request, used to manipulate the zebra-state on disk or in memory
pub enum Request {
// TODO(jlusby): deprecate in the future based on our validation story
@ -65,7 +65,7 @@ pub enum Request {
},
}
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
/// A state response
pub enum Response {
/// The response to a `AddBlock` request indicating a block was successfully
@ -91,162 +91,3 @@ pub enum Response {
Option<u32>,
),
}
#[cfg(test)]
mod tests {
use super::*;
use color_eyre::eyre::Report;
use color_eyre::eyre::{bail, ensure, eyre};
use std::sync::Once;
use tower::Service;
use tracing_error::ErrorLayer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
use zebra_chain::serialization::ZcashDeserialize;
static LOGGER_INIT: Once = Once::new();
fn install_tracing() {
LOGGER_INIT.call_once(|| {
let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.with(ErrorLayer::default())
.init();
})
}
#[tokio::test]
async fn test_round_trip() -> Result<(), Report> {
install_tracing();
let service = in_memory::init();
round_trip(service).await?;
let mut config = crate::Config::default();
let tmp_dir = tempdir::TempDir::new("round_trip")?;
config.path = tmp_dir.path().to_owned();
let service = on_disk::init(config);
get_tip(service).await?;
Ok(())
}
async fn round_trip<S>(mut service: S) -> Result<(), Report>
where
S: Service<
Request,
Error = Box<dyn std::error::Error + Send + Sync + 'static>,
Response = Response,
>,
{
let block: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..])?.into();
let hash = block.as_ref().into();
let response = service
.call(Request::AddBlock {
block: block.clone(),
})
.await
.map_err(|e| eyre!(e))?;
ensure!(
response == Response::Added { hash },
"unexpected response kind: {:?}",
response
);
let block_response = service
.call(Request::GetBlock { hash })
.await
.map_err(|e| eyre!(e))?;
match block_response {
Response::Block {
block: returned_block,
} => assert_eq!(block, returned_block),
_ => bail!("unexpected response kind: {:?}", block_response),
}
Ok(())
}
#[tokio::test]
async fn test_get_tip() -> Result<(), Report> {
install_tracing();
let service = in_memory::init();
get_tip(service).await?;
let mut config = crate::Config::default();
let tmp_dir = tempdir::TempDir::new("get_tip")?;
config.path = tmp_dir.path().to_owned();
let service = on_disk::init(config);
get_tip(service).await?;
Ok(())
}
#[spandoc::spandoc]
async fn get_tip<S>(mut service: S) -> Result<(), Report>
where
S: Service<
Request,
Error = Box<dyn std::error::Error + Send + Sync + 'static>,
Response = Response,
>,
{
install_tracing();
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])?.into();
let block1: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])?.into();
let block0_hash: BlockHeaderHash = block0.as_ref().into();
let block1_hash: BlockHeaderHash = block1.as_ref().into();
let expected_hash: BlockHeaderHash = block1_hash;
/// insert the higher block first
let response = service
.call(Request::AddBlock { block: block1 })
.await
.map_err(|e| eyre!(e))?;
ensure!(
response == Response::Added { hash: block1_hash },
"unexpected response kind: {:?}",
response
);
/// genesis block second
let response = service
.call(Request::AddBlock {
block: block0.clone(),
})
.await
.map_err(|e| eyre!(e))?;
ensure!(
response == Response::Added { hash: block0_hash },
"unexpected response kind: {:?}",
response
);
let block_response = service.call(Request::GetTip).await.map_err(|e| eyre!(e))?;
/// assert that the higher block is returned as the tip even tho it was least recently inserted
match block_response {
Response::Tip { hash } => assert_eq!(expected_hash, hash),
_ => bail!("unexpected response kind: {:?}", block_response),
}
Ok(())
}
}

View File

@ -0,0 +1,96 @@
use color_eyre::eyre::Report;
use color_eyre::eyre::{bail, ensure, eyre};
use once_cell::sync::Lazy;
use std::sync::{Arc, Once};
use tempdir::TempDir;
use tower::Service;
use tracing_error::ErrorLayer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
use zebra_chain::{
block::{Block, BlockHeaderHash},
serialization::ZcashDeserialize,
};
use zebra_test::transcript::Transcript;
use zebra_state::*;
static LOGGER_INIT: Once = Once::new();
fn install_tracing() {
LOGGER_INIT.call_once(|| {
let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.with(ErrorLayer::default())
.init();
})
}
static ADD_BLOCK_TRANSCRIPT: Lazy<Vec<(Request, Response)>> = Lazy::new(|| {
let block: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_415000_BYTES[..])
.unwrap()
.into();
let hash = block.as_ref().into();
vec![
(
Request::AddBlock {
block: block.clone(),
},
Response::Added { hash },
),
(Request::GetBlock { hash }, Response::Block { block }),
]
});
static GET_TIP_TRANSCRIPT: Lazy<Vec<(Request, Response)>> = Lazy::new(|| {
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
.unwrap()
.into();
let block1: Arc<_> = Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])
.unwrap()
.into();
let hash0 = block0.as_ref().into();
let hash1 = block1.as_ref().into();
vec![
// Insert higher block first, lower block second
(
Request::AddBlock { block: block1 },
Response::Added { hash: hash1 },
),
(
Request::AddBlock { block: block0 },
Response::Added { hash: hash0 },
),
(Request::GetTip, Response::Tip { hash: hash1 }),
]
});
#[tokio::test]
async fn check_transcripts() -> Result<(), Report> {
install_tracing();
for transcript_data in &[&ADD_BLOCK_TRANSCRIPT, &GET_TIP_TRANSCRIPT] {
let service = in_memory::init();
let transcript = Transcript::from(transcript_data.iter().cloned());
transcript.check(service).await?;
let storage_guard = TempDir::new("")?;
let service = on_disk::init(Config {
path: storage_guard.path().to_owned(),
});
let transcript = Transcript::from(transcript_data.iter().cloned());
transcript.check(service).await?;
// Delete the contents of the temp directory before going to the next case.
std::mem::drop(storage_guard);
}
Ok(())
}