Merge pull request #778 from ethcore/json_tests_refactor

use ethjson module to load chain json tests
This commit is contained in:
Gav Wood 2016-03-20 09:51:36 +01:00
commit 0cef2cfc46
8 changed files with 37 additions and 33 deletions

View File

@ -16,18 +16,19 @@
use super::test_common::*; use super::test_common::*;
use client::{BlockChainClient, Client, ClientConfig}; use client::{BlockChainClient, Client, ClientConfig};
use pod_state::*;
use block::Block; use block::Block;
use ethereum; use ethereum;
use tests::helpers::*; use tests::helpers::*;
use devtools::*; use devtools::*;
use spec::Genesis;
use ethjson;
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> { pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
init_log(); init_log();
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let tests = ethjson::blockchain::Test::load(json_data).unwrap();
let mut failed = Vec::new(); let mut failed = Vec::new();
for (name, test) in json.as_object().unwrap() { for (name, blockchain) in tests.deref() {
let mut fail = false; let mut fail = false;
{ {
let mut fail_unless = |cond: bool| if !cond && !fail { let mut fail_unless = |cond: bool| if !cond && !fail {
@ -39,37 +40,36 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
flush!(" - {}...", name); flush!(" - {}...", name);
let blocks: Vec<(Bytes, bool)> = test["blocks"].as_array().unwrap().iter().map(|e| (xjson!(&e["rlp"]), e.find("blockHeader").is_some())).collect();
let mut spec = match era { let mut spec = match era {
ChainEra::Frontier => ethereum::new_frontier_test(), ChainEra::Frontier => ethereum::new_frontier_test(),
ChainEra::Homestead => ethereum::new_homestead_test(), ChainEra::Homestead => ethereum::new_homestead_test(),
}; };
let s = PodState::from_json(test.find("pre").unwrap());
spec.set_genesis_state(s); let genesis = Genesis::from(blockchain.genesis());
spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); let state = From::from(blockchain.pre_state.clone());
spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis);
assert!(spec.is_state_root_valid()); assert!(spec.is_state_root_valid());
let genesis_hash = spec.genesis_header().hash();
assert_eq!(genesis_hash, H256::from_json(&test.find("genesisBlockHeader").unwrap()["hash"]));
let temp = RandomTempPath::new(); let temp = RandomTempPath::new();
{ {
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap();
assert_eq!(client.chain_info().best_block_hash, genesis_hash); for b in &blockchain.blocks_rlp() {
for (b, is_valid) in blocks.into_iter() {
if Block::is_good(&b) { if Block::is_good(&b) {
let _ = client.import_block(b.clone()); let _ = client.import_block(b.clone());
client.flush_queue();
client.import_verified_blocks(&IoChannel::disconnected());
} }
client.flush_queue();
let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0;
assert_eq!(imported_ok, is_valid);
} }
fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); fail_unless(client.chain_info().best_block_hash == blockchain.best_block.clone().into());
} }
} }
if !fail { if !fail {
flushln!("ok"); flushln!("ok");
} }
} }
println!("!!! {:?} tests from failed.", failed.len()); println!("!!! {:?} tests from failed.", failed.len());
failed failed
} }

View File

@ -21,7 +21,7 @@ use pod_account::*;
use ethjson; use ethjson;
/// State of all accounts in the system expressed in Plain Old Data. /// State of all accounts in the system expressed in Plain Old Data.
#[derive(Debug,Clone,PartialEq,Eq,Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PodState (BTreeMap<Address, PodAccount>); pub struct PodState (BTreeMap<Address, PodAccount>);
impl PodState { impl PodState {

View File

@ -19,7 +19,6 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use uint::Uint; use uint::Uint;
use bytes::Bytes; use bytes::Bytes;
use hash::H256;
/// Blockchain test account deserializer. /// Blockchain test account deserializer.
#[derive(Debug, PartialEq, Deserialize, Clone)] #[derive(Debug, PartialEq, Deserialize, Clone)]

View File

@ -24,11 +24,11 @@ use blockchain::transaction::Transaction;
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
pub struct Block { pub struct Block {
#[serde(rename="blockHeader")] #[serde(rename="blockHeader")]
header: Header, header: Option<Header>,
rlp: Bytes, rlp: Bytes,
transactions: Vec<Transaction>, transactions: Option<Vec<Transaction>>,
#[serde(rename="uncleHeaders")] #[serde(rename="uncleHeaders")]
uncles: Vec<Header>, uncles: Option<Vec<Header>>,
} }
impl Block { impl Block {

View File

@ -17,6 +17,7 @@
//! Blockchain deserialization. //! Blockchain deserialization.
use bytes::Bytes; use bytes::Bytes;
use hash::H256;
use blockchain::state::State; use blockchain::state::State;
use blockchain::header::Header; use blockchain::header::Header;
use blockchain::block::Block; use blockchain::block::Block;
@ -30,7 +31,7 @@ pub struct BlockChain {
pub genesis_block: Header, pub genesis_block: Header,
/// Genesis block rlp. /// Genesis block rlp.
#[serde(rename="genesisRLP")] #[serde(rename="genesisRLP")]
pub genesis_rlp: Bytes, pub genesis_rlp: Option<Bytes>,
/// Blocks. /// Blocks.
pub blocks: Vec<Block>, pub blocks: Vec<Block>,
/// Post state. /// Post state.
@ -39,14 +40,12 @@ pub struct BlockChain {
/// Pre state. /// Pre state.
#[serde(rename="pre")] #[serde(rename="pre")]
pub pre_state: State, pub pre_state: State,
/// Hash of best block.
#[serde(rename="lastblockhash")]
pub best_block: H256
} }
impl BlockChain { impl BlockChain {
/// Returns genesis block rlp.
pub fn genesis_rlp(&self) -> Vec<u8> {
self.genesis_rlp.clone().into()
}
/// Returns blocks rlp. /// Returns blocks rlp.
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> { pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
self.blocks.iter().map(|block| block.rlp()).collect() self.blocks.iter().map(|block| block.rlp()).collect()

View File

@ -18,6 +18,9 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ops::Deref; use std::ops::Deref;
use std::io::Read;
use serde_json;
use serde_json::Error;
use blockchain::blockchain::BlockChain; use blockchain::blockchain::BlockChain;
/// Blockchain test deserializer. /// Blockchain test deserializer.
@ -31,3 +34,10 @@ impl Deref for Test {
&self.0 &self.0
} }
} }
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
}

View File

@ -46,12 +46,8 @@ impl Visitor for BytesVisitor {
let v = match value.len() { let v = match value.len() {
0 => vec![], 0 => vec![],
2 if value.starts_with("0x") => vec![], 2 if value.starts_with("0x") => vec![],
_ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| { _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]),
Error::custom(format!("Invalid hex value {}.", value).as_ref()) _ => FromHex::from_hex(value).unwrap_or(vec![]),
})),
_ => try!(FromHex::from_hex(value).map_err(|_| {
Error::custom(format!("Invalid hex value {}.", value).as_ref())
}))
}; };
Ok(Bytes(v)) Ok(Bytes(v))
} }