Rewrite zebra-state tests to use transcripts.
This makes adding more tests easier.
This commit is contained in:
parent
e8d42264e8
commit
87a8d328d5
|
|
@ -2385,6 +2385,7 @@ dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"sled",
|
"sled",
|
||||||
"spandoc",
|
"spandoc",
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,4 @@ tracing-error = "0.1.2"
|
||||||
tracing-subscriber = "0.2.6"
|
tracing-subscriber = "0.2.6"
|
||||||
tempdir = "0.3.7"
|
tempdir = "0.3.7"
|
||||||
color-eyre = "0.5"
|
color-eyre = "0.5"
|
||||||
|
once_cell = "1.4"
|
||||||
|
|
|
||||||
|
|
@ -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
|
/// A state request, used to manipulate the zebra-state on disk or in memory
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
// TODO(jlusby): deprecate in the future based on our validation story
|
// 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
|
/// A state response
|
||||||
pub enum Response {
|
pub enum Response {
|
||||||
/// The response to a `AddBlock` request indicating a block was successfully
|
/// The response to a `AddBlock` request indicating a block was successfully
|
||||||
|
|
@ -91,162 +91,3 @@ pub enum Response {
|
||||||
Option<u32>,
|
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue