From 800154a8ae66a941c50a5adacccfe94195831e85 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 14:39:49 +0400 Subject: [PATCH 1/9] client test creating --- src/tests/client.rs | 20 ++++++++++++++++++++ src/tests/mod.rs | 1 + 2 files changed, 21 insertions(+) create mode 100644 src/tests/client.rs diff --git a/src/tests/client.rs b/src/tests/client.rs new file mode 100644 index 000000000..25c8cb9b0 --- /dev/null +++ b/src/tests/client.rs @@ -0,0 +1,20 @@ +use ethereum; +use client::{BlockChainClient,Client}; +use std::env; +use pod_state::*; + + +#[test] +fn test_client_is_created() { + + let mut spec = ethereum::new_frontier_like_test(); + spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap())); + spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); + + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + + let client_result = Client::new(spec, &dir, IOChannel::disconnected()); + + assert!(client_result.is_ok()); +} \ No newline at end of file diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c30f7f9b8..c6e38dbd0 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -4,3 +4,4 @@ mod test_common; mod transaction; mod executive; mod state; +mod client; \ No newline at end of file From 46e0a81c52dce6905b3361068d8f63e10524f1d2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 14:55:12 +0400 Subject: [PATCH 2/9] more of testing --- res/ethereum/tests | 2 +- src/tests/client.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/res/ethereum/tests b/res/ethereum/tests index dc86e6359..e838fd909 160000 --- a/res/ethereum/tests +++ b/res/ethereum/tests @@ -1 +1 @@ -Subproject commit dc86e6359675440aea59ddb48648a01c799925d8 +Subproject commit e838fd90998fc5502d0b7c9427a4c231f9a6953d diff --git a/src/tests/client.rs b/src/tests/client.rs index 25c8cb9b0..c0f202edd 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -2,6 +2,7 @@ use ethereum; use client::{BlockChainClient,Client}; use std::env; use pod_state::*; +use super::test_common::*; #[test] From 81bffd48e89be4d4d2745f69f00c006743fdd2ab Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 17:33:22 +0400 Subject: [PATCH 3/9] basic client tests working --- src/block.rs | 2 +- src/block_queue.rs | 2 +- src/tests/client.rs | 92 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/src/block.rs b/src/block.rs index 1ff326430..0e928e9b0 100644 --- a/src/block.rs +++ b/src/block.rs @@ -85,7 +85,7 @@ impl IsBlock for Block { /// /// It's a bit like a Vec, eccept that whenever a transaction is pushed, we execute it and /// maintain the system `state()`. We also archive execution receipts in preparation for later block creation. -pub struct OpenBlock<'x, 'y> { + pub struct OpenBlock<'x, 'y> { block: Block, engine: &'x Engine, last_hashes: &'y LastHashes, diff --git a/src/block_queue.rs b/src/block_queue.rs index fa091d0c4..c45a86a8b 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -191,7 +191,7 @@ impl BlockQueue { /// Wait for queue to be empty pub fn flush(&mut self) { let mut verification = self.verification.lock().unwrap(); - while !verification.unverified.is_empty() && !verification.verifying.is_empty() { + while !verification.unverified.is_empty() || !verification.verifying.is_empty() { verification = self.empty.wait(verification).unwrap(); } } diff --git a/src/tests/client.rs b/src/tests/client.rs index c0f202edd..c14f2e2f0 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,21 +1,85 @@ -use ethereum; -use client::{BlockChainClient,Client}; + use client::{BlockChainClient,Client}; use std::env; -use pod_state::*; use super::test_common::*; +use std::path::PathBuf; +use spec::*; + +#[cfg(test)] +fn get_random_temp_dir() -> PathBuf { + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + dir +} + +#[cfg(test)] +fn get_test_spec() -> Spec { + Spec::new_test() +} + +#[cfg(test)] +fn get_good_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = test_engine.spec().genesis_header().state_root; + + create_test_block(&block_header) +} + +#[cfg(test)] +fn create_test_block(header: &Header) -> Bytes { + let mut rlp = RlpStream::new_list(3); + rlp.append(header); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.out() +} #[test] -fn test_client_is_created() { - - let mut spec = ethereum::new_frontier_like_test(); - spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap())); - spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); - - let mut dir = env::temp_dir(); - dir.push(H32::random().hex()); - - let client_result = Client::new(spec, &dir, IOChannel::disconnected()); - +fn created() { + let client_result = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()); assert!(client_result.is_ok()); +} + +#[test] +fn imports_from_empty() { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + client.import_verified_blocks(&IoChannel::disconnected()); + client.flush_queue(); +} + +#[test] +fn imports_good_block() { + + ::env_logger::init().ok(); + + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + + let good_block = get_good_dummy_block(); + if let Err(_) = client.import_block(good_block) { + panic!("error importing block being good by definition"); + } + + client.flush_queue(); + + client.import_verified_blocks(&IoChannel::disconnected()); + + let block = client.block_header_at(1).unwrap(); + + assert!(!block.is_empty()); +} + +#[test] +fn query_none_block() { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + + let non_existant = client.block_header_at(188); + + assert!(non_existant == Option::None); } \ No newline at end of file From 8d30f9fecbd91e132ccf368d4b6eb35ed403718f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 17:55:08 +0400 Subject: [PATCH 4/9] bad block import checks --- src/tests/client.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index c14f2e2f0..a9d212bc1 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -31,6 +31,21 @@ fn get_good_dummy_block() -> Bytes { create_test_block(&block_header) } +#[cfg(test)] +fn get_bad_state_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = x!(0xbad); + + create_test_block(&block_header) +} + #[cfg(test)] fn create_test_block(header: &Header) -> Bytes { let mut rlp = RlpStream::new_list(3); @@ -40,6 +55,23 @@ fn create_test_block(header: &Header) -> Bytes { rlp.out() } +#[cfg(test)] +fn get_test_client_with_blocks(blocks: Vec) -> Arc { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + + for block in &blocks { + if let Err(_) = client.import_block(block.clone()) { + panic!("panic importing block which is well-formed"); + } + } + + client.flush_queue(); + + client.import_verified_blocks(&IoChannel::disconnected()); + + client +} + #[test] fn created() { @@ -81,5 +113,13 @@ fn query_none_block() { let non_existant = client.block_header_at(188); - assert!(non_existant == Option::None); + assert!(non_existant.is_none()); +} + +#[test] +fn query_bad_block() { + let client = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); + let bad_block:Option = client.block_header_at(1); + + assert!(bad_block.is_none()); } \ No newline at end of file From 253f56afe1f5928f76b1e0efcbe75193f74f0021 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 18:03:12 +0400 Subject: [PATCH 5/9] hack indent --- src/block.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/block.rs b/src/block.rs index 0e928e9b0..31378e8a6 100644 --- a/src/block.rs +++ b/src/block.rs @@ -108,6 +108,7 @@ pub struct SealedBlock { uncle_bytes: Bytes, } + impl<'x, 'y> OpenBlock<'x, 'y> { /// Create a new OpenBlock ready for transaction pushing. pub fn new<'a, 'b>(engine: &'a Engine, db: JournalDB, parent: &Header, last_hashes: &'b LastHashes, author: Address, extra_data: Bytes) -> OpenBlock<'a, 'b> { From b8c2f9cf15c77257384833e29bdeef9ec809dc61 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:05:25 +0400 Subject: [PATCH 6/9] chain info test --- src/tests/client.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index a9d212bc1..f6641ff91 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,4 +1,4 @@ - use client::{BlockChainClient,Client}; +use client::{BlockChainClient,Client}; use std::env; use super::test_common::*; use std::path::PathBuf; @@ -88,9 +88,6 @@ fn imports_from_empty() { #[test] fn imports_good_block() { - - ::env_logger::init().ok(); - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); let good_block = get_good_dummy_block(); @@ -122,4 +119,13 @@ fn query_bad_block() { let bad_block:Option = client.block_header_at(1); assert!(bad_block.is_none()); +} + +#[test] +fn returns_chain_info() { + let dummy_block = get_good_dummy_block(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); + let block = BlockView::new(&dummy_block); + let info = client.chain_info(); + assert_eq!(info.best_block_hash, block.header().hash()); } \ No newline at end of file From cd57e480f51072f6920d2fe0431989ae531c7144 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:12:25 +0400 Subject: [PATCH 7/9] fix indentation again --- src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/block.rs b/src/block.rs index 31378e8a6..5691d2bf5 100644 --- a/src/block.rs +++ b/src/block.rs @@ -85,7 +85,7 @@ impl IsBlock for Block { /// /// It's a bit like a Vec, eccept that whenever a transaction is pushed, we execute it and /// maintain the system `state()`. We also archive execution receipts in preparation for later block creation. - pub struct OpenBlock<'x, 'y> { +pub struct OpenBlock<'x, 'y> { block: Block, engine: &'x Engine, last_hashes: &'y LastHashes, From f07fc497c5b0516137617d0cf40bc446293e032a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:14:06 +0400 Subject: [PATCH 8/9] cleanup --- src/block.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/block.rs b/src/block.rs index 5691d2bf5..1ff326430 100644 --- a/src/block.rs +++ b/src/block.rs @@ -108,7 +108,6 @@ pub struct SealedBlock { uncle_bytes: Bytes, } - impl<'x, 'y> OpenBlock<'x, 'y> { /// Create a new OpenBlock ready for transaction pushing. pub fn new<'a, 'b>(engine: &'a Engine, db: JournalDB, parent: &Header, last_hashes: &'b LastHashes, author: Address, extra_data: Bytes) -> OpenBlock<'a, 'b> { From 91828065f45cf1a543218151397f24f4707859d3 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 22:06:11 +0400 Subject: [PATCH 9/9] fixed line spaces --- src/tests/client.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index f6641ff91..eb58699b4 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -58,17 +58,13 @@ fn create_test_block(header: &Header) -> Bytes { #[cfg(test)] fn get_test_client_with_blocks(blocks: Vec) -> Arc { let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); - for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); } } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); - client } @@ -89,18 +85,14 @@ fn imports_from_empty() { #[test] fn imports_good_block() { let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); - let good_block = get_good_dummy_block(); if let Err(_) = client.import_block(good_block) { panic!("error importing block being good by definition"); } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); let block = client.block_header_at(1).unwrap(); - assert!(!block.is_empty()); } @@ -109,7 +101,6 @@ fn query_none_block() { let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header_at(188); - assert!(non_existant.is_none()); }