From 4ccaabde40365d0815a9fcd0c69eecc041cea784 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 19:30:40 +0200 Subject: [PATCH] add transaction count verifier tests --- rpc/src/v1/tests/eth.rs | 96 ++++++++++++++++++++++++++++++++++++----- rpc/src/v1/tests/mod.rs | 25 ++++++++--- 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 9b2cb3195..0c159ceb2 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,15 +19,18 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; +use ethcore::ids::BlockID; use ethcore::client::{Client, BlockChainClient, ClientConfig}; use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; +use ethcore::views::BlockView; use ethcore::ethereum; use ethminer::{Miner, MinerService, ExternalMiner}; use devtools::RandomTempPath; +use util::Hashable; use util::io::IoChannel; -use util::hash::Address; -use util::numbers::{Uint, U256}; +use util::hash::{Address, H256}; +use util::numbers::U256; use util::keys::{AccountProvider, TestAccount, TestAccountProvider}; use jsonrpc_core::IoHandler; use ethjson::blockchain::BlockChain; @@ -72,8 +75,8 @@ struct EthTester { } impl EthTester { - fn from_chain(chain: BlockChain) -> Self { - let tester = Self::from_spec_provider(|| make_spec(&chain)); + fn from_chain(chain: &BlockChain) -> Self { + let tester = Self::from_spec_provider(|| make_spec(chain)); for b in &chain.blocks_rlp() { if Block::is_good(&b) { @@ -83,7 +86,9 @@ impl EthTester { } } - assert!(tester.client.chain_info().best_block_hash == chain.best_block.into()); + tester.client.flush_queue(); + + assert!(tester.client.chain_info().best_block_hash == chain.best_block.clone().into()); tester } @@ -116,13 +121,13 @@ impl EthTester { #[test] fn harness_works() { let chain: BlockChain = extract_chain!("BlockchainTests/bcUncleTest"); - let _ = EthTester::from_chain(chain); + let _ = EthTester::from_chain(&chain); } #[test] fn eth_get_balance() { let chain = extract_chain!("BlockchainTests/bcWalletTest", "wallet2outOf3txs"); - let tester = EthTester::from_chain(chain); + let tester = EthTester::from_chain(&chain); // final account state let req_latest = r#"{ "jsonrpc": "2.0", @@ -148,7 +153,7 @@ fn eth_get_balance() { #[test] fn eth_block_number() { let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); - let tester = EthTester::from_chain(chain); + let tester = EthTester::from_chain(&chain); let req_number = r#"{ "jsonrpc": "2.0", "method": "eth_blockNumber", @@ -206,7 +211,6 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{ } "#; -#[cfg(test)] #[test] fn eth_transaction_count() { use util::crypto::Secret; @@ -271,4 +275,76 @@ fn eth_transaction_count() { let res_after_pending = r#"{"jsonrpc":"2.0","result":"0x01","id":18}"#; assert_eq!(&tester.handler.handle_request(&req_after_pending).unwrap(), res_after_pending); -} \ No newline at end of file +} + +fn verify_transaction_counts(name: String, chain: BlockChain) { + struct PanicHandler(String); + impl Drop for PanicHandler { + fn drop(&mut self) { + if ::std::thread::panicking() { + println!("Test failed: {}", self.0); + } + } + } + + let _panic = PanicHandler(name); + + fn by_hash(hash: H256, count: usize, id: &mut usize) -> (String, String) { + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBlockTransactionCountByHash", + "params": [ + ""#.to_owned() + format!("0x{:?}", hash).as_ref() + r#"" + ], + "id": "# + format!("{}", *id).as_ref() + r#" + }"#; + + let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + + format!("0x{:02x}", count).as_ref() + + r#"","id":"# + + format!("{}", *id).as_ref() + r#"}"#; + *id += 1; + (req, res) + } + + fn by_number(num: u64, count: usize, id: &mut usize) -> (String, String) { + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBlockTransactionCountByNumber", + "params": [ + "#.to_owned() + &::serde_json::to_string(&U256::from(num)).unwrap() + r#" + ], + "id": "# + format!("{}", *id).as_ref() + r#" + }"#; + + let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + + format!("0x{:02x}", count).as_ref() + + r#"","id":"# + + format!("{}", *id).as_ref() + r#"}"#; + *id += 1; + (req, res) + } + + let tester = EthTester::from_chain(&chain); + + let mut id = 1; + for b in chain.blocks_rlp().iter().filter(|b| Block::is_good(b)).map(|b| BlockView::new(b)) { + let count = b.transactions_count(); + + let hash = b.sha3(); + let number = b.header_view().number(); + + let (req, res) = by_hash(hash, count, &mut id); + assert_eq!(tester.handler.handle_request(&req), Some(res)); + + // uncles can share block numbers, so skip them. + if tester.client.block_hash(BlockID::Number(number)) == Some(hash) { + let (req, res) = by_number(number, count, &mut id); + assert_eq!(tester.handler.handle_request(&req), Some(res)); + } + } +} + +register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest"); +register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest"); +register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest"); \ No newline at end of file diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 3455bfd1f..9e71addd4 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -13,11 +13,15 @@ pub mod helpers; // extract the chain with that name. This will panic if no chain by that name // is found. macro_rules! extract_chain { - ($file:expr, $name:expr) => {{ + (iter $file:expr) => {{ const RAW_DATA: &'static [u8] = include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/", $file, ".json")); + ::ethjson::blockchain::Test::load(RAW_DATA).unwrap().into_iter() + }}; + + ($file:expr, $name:expr) => {{ let mut chain = None; - for (name, c) in ::ethjson::blockchain::Test::load(RAW_DATA).unwrap() { + for (name, c) in extract_chain!(iter $file) { if name == $name { chain = Some(c); break; @@ -27,14 +31,21 @@ macro_rules! extract_chain { }}; ($file:expr) => {{ - const RAW_DATA: &'static [u8] = - include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/", $file, ".json")); - - ::ethjson::blockchain::Test::load(RAW_DATA) - .unwrap().into_iter().next().unwrap().1 + extract_chain!(iter $file).next().unwrap().1 }}; } +macro_rules! register_test { + ($name:ident, $cb:expr, $file:expr) => { + #[test] + fn $name() { + for (name, chain) in extract_chain!(iter $file) { + $cb(name, chain); + } + } + } +} + #[cfg(test)] mod mocked; #[cfg(test)]