From 6c205067b194b60c79afe85a5d6caec551d8ec42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 14 Jul 2016 12:16:53 +0200 Subject: [PATCH] Miner tests (#1597) * Un-ignoring RPC test * Additional tests for importing transactions --- ethcore/src/client/test_client.rs | 1 + ethcore/src/miner/miner.rs | 89 ++++++++++++++++++++++- ethcore/src/miner/price_info.rs | 4 +- rpc/src/v1/tests/helpers/miner_service.rs | 2 +- rpc/src/v1/tests/mocked/eth.rs | 5 +- util/src/io/worker.rs | 2 +- util/table/src/lib.rs | 12 +-- 7 files changed, 95 insertions(+), 20 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index b60d537a1..ab5fbee25 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -262,6 +262,7 @@ impl MiningBlockChainClient for TestBlockChainClient { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); self.spec.ensure_db_good(db.as_hashdb_mut()); + let last_hashes = vec![genesis_header.hash()]; OpenBlock::new( engine.deref(), diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 4c1741959..c49397c4e 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -615,7 +615,9 @@ impl MinerService for Miner { let imported = { // Be sure to release the lock before we call enable_and_prepare_sealing let mut transaction_queue = self.transaction_queue.lock(); - let import = self.add_transactions_to_queue(chain, vec![transaction], TransactionOrigin::Local, &mut transaction_queue).pop().unwrap(); + let import = self.add_transactions_to_queue( + chain, vec![transaction], TransactionOrigin::Local, &mut transaction_queue + ).pop().unwrap(); match import { Ok(ref res) => { @@ -834,10 +836,13 @@ impl MinerService for Miner { #[cfg(test)] mod tests { + use std::time::Duration; use super::super::MinerService; - use super::Miner; + use super::*; use util::*; use client::{TestBlockChainClient, EachBlockWith}; + use client::{TransactionImportResult}; + use types::transaction::{Transaction, Action}; use block::*; use spec::Spec; @@ -872,4 +877,84 @@ mod tests { // solution to original work submitted. assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok()); } + + fn miner() -> Miner { + Arc::try_unwrap(Miner::new( + MinerOptions { + new_work_notify: Vec::new(), + force_sealing: false, + reseal_on_external_tx: false, + reseal_on_own_tx: true, + reseal_min_period: Duration::from_secs(5), + tx_gas_limit: !U256::zero(), + tx_queue_size: 1024, + pending_set: PendingSet::AlwaysSealing, + work_queue_size: 5, + enable_resubmission: true, + }, + GasPricer::new_fixed(0u64.into()), + Spec::new_test(), + None, // accounts provider + )).ok().expect("Miner was just created.") + } + + #[test] + fn should_make_pending_block_when_importing_own_transaction() { + // given + let client = TestBlockChainClient::default(); + let miner = miner(); + let transaction = { + let keypair = KeyPair::create().unwrap(); + Transaction { + action: Action::Create, + value: U256::zero(), + data: "3331600055".from_hex().unwrap(), + gas: U256::from(100_000), + gas_price: U256::zero(), + nonce: U256::zero(), + }.sign(keypair.secret()) + }; + + // when + let res = miner.import_own_transaction(&client, transaction); + + // then + assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(miner.all_transactions().len(), 1); + assert_eq!(miner.pending_transactions().len(), 1); + assert_eq!(miner.pending_transactions_hashes().len(), 1); + assert_eq!(miner.pending_receipts().len(), 1); + // This method will let us know if pending block was created (before calling that method) + assert_eq!(miner.enable_and_prepare_sealing(&client), false); + } + + #[test] + fn should_import_external_transaction() { + // given + let client = TestBlockChainClient::default(); + let miner = miner(); + let transaction = { + let keypair = KeyPair::create().unwrap(); + Transaction { + action: Action::Create, + value: U256::zero(), + data: "3331600055".from_hex().unwrap(), + gas: U256::from(100_000), + gas_price: U256::zero(), + nonce: U256::zero(), + }.sign(keypair.secret()) + }; + + // when + let res = miner.import_external_transactions(&client, vec![transaction]).pop().unwrap(); + + // then + assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(miner.all_transactions().len(), 1); + assert_eq!(miner.pending_transactions_hashes().len(), 0); + assert_eq!(miner.pending_transactions().len(), 0); + assert_eq!(miner.pending_receipts().len(), 0); + // This method will let us know if pending block was created (before calling that method) + assert_eq!(miner.enable_and_prepare_sealing(&client), true); + } } diff --git a/ethcore/src/miner/price_info.rs b/ethcore/src/miner/price_info.rs index ee4220c0c..268a5dfb4 100644 --- a/ethcore/src/miner/price_info.rs +++ b/ethcore/src/miner/price_info.rs @@ -77,7 +77,6 @@ impl PriceInfo { } } -//#[ignore] #[test] fn should_get_price_info() { use std::sync::Arc; @@ -88,9 +87,10 @@ fn should_get_price_info() { init_log(); let done = Arc::new((Mutex::new(PriceInfo { ethusd: 0f32 }), Condvar::new())); let rdone = done.clone(); + PriceInfo::get(move |price| { let mut p = rdone.0.lock(); *p = price; rdone.1.notify_one(); }).unwrap(); let mut p = done.0.lock(); let t = done.1.wait_for(&mut p, Duration::from_millis(10000)); assert!(!t.timed_out()); assert!(p.ethusd != 0f32); -} \ No newline at end of file +} diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 8b67b8e09..21b4d5bba 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -182,7 +182,7 @@ impl MinerService for TestMinerService { } fn map_sealing_work(&self, _chain: &MiningBlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { - unimplemented!(); + None } fn transaction(&self, hash: &H256) -> Option { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 688a43b24..92ff3ec8c 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -56,7 +56,7 @@ struct EthTester { pub client: Arc, pub sync: Arc, pub accounts_provider: Arc, - miner: Arc, + pub miner: Arc, hashrates: Arc>>, pub io: IoHandler, } @@ -742,13 +742,12 @@ fn returns_no_work_if_cant_mine() { assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); } -#[ignore] -// enable once TestMinerService supports the mining API. #[test] fn returns_error_if_can_mine_and_no_closed_block() { use ethsync::{SyncState}; let eth_tester = EthTester::default(); + eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()); eth_tester.sync.status.write().state = SyncState::Idle; let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; diff --git a/util/src/io/worker.rs b/util/src/io/worker.rs index 0ceadcd92..a81cdca08 100644 --- a/util/src/io/worker.rs +++ b/util/src/io/worker.rs @@ -87,7 +87,7 @@ impl Worker { if deleting.load(AtomicOrdering::Acquire) { return; } - let _ = wait.wait(&mut lock); + wait.wait(&mut lock); } if deleting.load(AtomicOrdering::Acquire) { diff --git a/util/table/src/lib.rs b/util/table/src/lib.rs index c3b2006cf..a13beab11 100644 --- a/util/table/src/lib.rs +++ b/util/table/src/lib.rs @@ -16,7 +16,6 @@ //! A collection associating pair of keys (row and column) with a single value. -use std::default::Default; use std::hash::Hash; use std::collections::HashMap; @@ -25,22 +24,13 @@ use std::collections::HashMap; /// You can obviously use `HashMap<(Row,Col), Val>`, but this structure gives /// you better access to all `Columns` in Specific `Row`. Namely you can get sub-hashmap /// `HashMap` for specific `Row` +#[derive(Default, Debug, PartialEq)] pub struct Table where Row: Eq + Hash + Clone, Col: Eq + Hash { map: HashMap>, } -impl Default for Table - where Row: Eq + Hash + Clone, - Col: Eq + Hash { - fn default() -> Self { - Table::new() - } -} - -// There is default but clippy does not detect it? -#[cfg_attr(feature="dev", allow(new_without_default))] impl Table where Row: Eq + Hash + Clone, Col: Eq + Hash {