diff --git a/src/sync/tests.rs b/src/sync/tests.rs index cc0645b50..eca8a07a6 100644 --- a/src/sync/tests.rs +++ b/src/sync/tests.rs @@ -51,6 +51,10 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { + fn block_total_difficulty(&self, _h: &H256) -> Option { + unimplemented!(); + } + fn block_header(&self, h: &H256) -> Option { self.blocks.read().unwrap().get(h).map(|r| Rlp::new(r).at(0).as_raw().to_vec()) @@ -76,6 +80,10 @@ impl BlockChainClient for TestBlockChainClient { } } + fn block_total_difficulty_at(&self, _number: BlockNumber) -> Option { + unimplemented!(); + } + fn block_header_at(&self, n: BlockNumber) -> Option { self.numbers.read().unwrap().get(&(n as usize)).and_then(|h| self.block_header(h)) } diff --git a/src/tests/client.rs b/src/tests/client.rs index eb58699b4..f6d603f43 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,22 +1,7 @@ use client::{BlockChainClient,Client}; -use std::env; use super::test_common::*; -use std::path::PathBuf; -use spec::*; +use super::helpers::*; -#[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(); @@ -31,7 +16,6 @@ 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(); @@ -46,18 +30,10 @@ fn get_bad_state_dummy_block() -> Bytes { 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() -} -#[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(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); @@ -71,20 +47,23 @@ fn get_test_client_with_blocks(blocks: Vec) -> Arc { #[test] fn created() { - let client_result = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()); + let dir = RandomTempPath::new(); + let client_result = Client::new(get_test_spec(), dir.as_path(), 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(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } #[test] fn imports_good_block() { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), 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"); @@ -98,7 +77,8 @@ fn imports_good_block() { #[test] fn query_none_block() { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header_at(188); assert!(non_existant.is_none()); @@ -119,4 +99,19 @@ fn returns_chain_info() { let block = BlockView::new(&dummy_block); let info = client.chain_info(); assert_eq!(info.best_block_hash, block.header().hash()); +} + +#[test] +fn imports_block_sequence() { + let client = generate_dummy_client(6); + let block = client.block_header_at(5).unwrap(); + + assert!(!block.is_empty()); +} + +#[test] +fn can_collect_garbage() { + let client = generate_dummy_client(100); + client.tick(); + assert!(client.cache_info().blocks < 100 * 1024); } \ No newline at end of file diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs new file mode 100644 index 000000000..a566392cc --- /dev/null +++ b/src/tests/helpers.rs @@ -0,0 +1,80 @@ +use client::{BlockChainClient,Client}; +use std::env; +use super::test_common::*; +use std::path::PathBuf; +use spec::*; +use std::fs::{remove_dir_all}; + + +pub struct RandomTempPath { + path: PathBuf +} + +impl RandomTempPath { + pub fn new() -> RandomTempPath { + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + RandomTempPath { + path: dir.clone() + } + } + + pub fn as_path(&self) -> &PathBuf { + &self.path + } +} + +impl Drop for RandomTempPath { + fn drop(&mut self) { + if let Err(e) = remove_dir_all(self.as_path()) { + panic!("failed to remove temp directory, probably something failed to destroyed ({})", e); + } + } +} + +pub fn get_test_spec() -> Spec { + Spec::new_test() +} + +pub 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() +} + +pub fn generate_dummy_client(block_number: usize) -> Arc { + let dir = RandomTempPath::new(); + + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + let state_root = test_engine.spec().genesis_header().state_root; + let mut rolling_hash = test_engine.spec().genesis_header().hash(); + let mut rolling_block_number = 1; + let mut rolling_timestamp = 40; + + for _ in 0..block_number { + let mut header = Header::new(); + + header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + header.timestamp = rolling_timestamp; + header.number = rolling_block_number; + header.parent_hash = rolling_hash; + header.state_root = state_root.clone(); + + rolling_hash = header.hash(); + rolling_block_number = rolling_block_number + 1; + rolling_timestamp = rolling_timestamp + 10; + + if let Err(_) = client.import_block(create_test_block(&header)) { + panic!("error importing block which is valid by definition"); + } + + } + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); + client +} \ No newline at end of file diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 290c2e293..17da72d77 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -6,3 +6,4 @@ mod executive; mod state; mod client; mod chain; +mod helpers; \ No newline at end of file