Merge pull request #239 from ethcore/general-tests
General tests and some helpers
This commit is contained in:
		
						commit
						888cc14bde
					
				| @ -1,22 +1,7 @@ | |||||||
| use client::{BlockChainClient,Client}; | use client::{BlockChainClient,Client}; | ||||||
| use std::env; |  | ||||||
| use super::test_common::*; | use super::test_common::*; | ||||||
| use std::path::PathBuf; | use super::helpers::*; | ||||||
| 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 { | fn get_good_dummy_block() -> Bytes { | ||||||
| 	let mut block_header = Header::new(); | 	let mut block_header = Header::new(); | ||||||
| 	let test_spec = get_test_spec(); | 	let test_spec = get_test_spec(); | ||||||
| @ -31,7 +16,6 @@ fn get_good_dummy_block() -> Bytes { | |||||||
| 	create_test_block(&block_header) | 	create_test_block(&block_header) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] |  | ||||||
| fn get_bad_state_dummy_block() -> Bytes { | fn get_bad_state_dummy_block() -> Bytes { | ||||||
| 	let mut block_header = Header::new(); | 	let mut block_header = Header::new(); | ||||||
| 	let test_spec = get_test_spec(); | 	let test_spec = get_test_spec(); | ||||||
| @ -46,18 +30,10 @@ fn get_bad_state_dummy_block() -> Bytes { | |||||||
| 	create_test_block(&block_header) | 	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<Bytes>) -> Arc<Client> { | fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> Arc<Client> { | ||||||
| 	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 { | 	for block in &blocks { | ||||||
| 		if let Err(_) = client.import_block(block.clone()) { | 		if let Err(_) = client.import_block(block.clone()) { | ||||||
| 			panic!("panic importing block which is well-formed"); | 			panic!("panic importing block which is well-formed"); | ||||||
| @ -71,20 +47,23 @@ fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> Arc<Client> { | |||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn created() { | 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()); | 	assert!(client_result.is_ok()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn imports_from_empty() { | 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.import_verified_blocks(&IoChannel::disconnected()); | ||||||
| 	client.flush_queue(); | 	client.flush_queue(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn imports_good_block() { | 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(); | 	let good_block = get_good_dummy_block(); | ||||||
| 	if let Err(_) = client.import_block(good_block) { | 	if let Err(_) = client.import_block(good_block) { | ||||||
| 		panic!("error importing block being good by definition"); | 		panic!("error importing block being good by definition"); | ||||||
| @ -98,7 +77,8 @@ fn imports_good_block() { | |||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn query_none_block() { | 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); |     let non_existant = client.block_header_at(188); | ||||||
| 	assert!(non_existant.is_none()); | 	assert!(non_existant.is_none()); | ||||||
| @ -120,3 +100,18 @@ fn returns_chain_info() { | |||||||
| 	let info = client.chain_info(); | 	let info = client.chain_info(); | ||||||
| 	assert_eq!(info.best_block_hash, block.header().hash()); | 	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); | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								src/tests/helpers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/tests/helpers.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<Client> { | ||||||
|  | 	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 | ||||||
|  | } | ||||||
| @ -6,3 +6,4 @@ mod executive; | |||||||
| mod state; | mod state; | ||||||
| mod client; | mod client; | ||||||
| mod chain; | mod chain; | ||||||
|  | mod helpers; | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user