Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Coverage effort [in progress] #382

Merged
merged 9 commits into from
Feb 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions cov.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ if ! type kcov > /dev/null; then
exit 1
fi

cargo test --features ethcore/json-tests -p ethcore --no-run || exit $?
cargo test -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity --no-run || exit $?
rm -rf target/coverage
mkdir -p target/coverage
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1 --include-pattern src --verify target/coverage target/debug/deps/ethcore*
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,src/tests --include-pattern src --verify target/coverage target/debug/deps/ethcore-*
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,src/tests --include-pattern src --verify target/coverage target/debug/deps/ethash-*
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,src/tests --include-pattern src --verify target/coverage target/debug/deps/ethcore_util-*
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,src/tests --include-pattern src --verify target/coverage target/debug/deps/ethsync-*
kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,src/tests --include-pattern src --verify target/coverage target/debug/deps/ethcore_rpc-*
xdg-open target/coverage/index.html
234 changes: 201 additions & 33 deletions ethcore/src/ethereum/ethash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ use spec::*;
use engine::*;
use evm::Schedule;
use evm::Factory;
#[cfg(test)]
use tests::helpers::*;

/// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum
/// mainnet chains in the Olympic, Frontier and Homestead eras.
Expand All @@ -49,6 +47,17 @@ impl Ethash {
})
}

#[cfg(test)]
fn new_test(spec: Spec) -> Ethash {
Ethash {
spec: spec,
pow: EthashManager::new(),
factory: Factory::default(),
u64_params: RwLock::new(HashMap::new()),
u256_params: RwLock::new(HashMap::new())
}
}

fn u64_param(&self, name: &str) -> u64 {
*self.u64_params.write().unwrap().entry(name.to_owned()).or_insert_with(||
self.spec().engine_params.get(name).map_or(0u64, |a| decode(&a)))
Expand Down Expand Up @@ -123,6 +132,11 @@ impl Engine for Ethash {

fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
// check the seal fields.
if header.seal.len() != self.seal_fields() {
return Err(From::from(BlockError::InvalidSealArity(
Mismatch { expected: self.seal_fields(), found: header.seal.len() }
)));
}
try!(UntrustedRlp::new(&header.seal[0]).as_val::<H256>());
try!(UntrustedRlp::new(&header.seal[1]).as_val::<H64>());

Expand All @@ -143,6 +157,11 @@ impl Engine for Ethash {
}

fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
if header.seal.len() != self.seal_fields() {
return Err(From::from(BlockError::InvalidSealArity(
Mismatch { expected: self.seal_fields(), found: header.seal.len() }
)));
}
let result = self.pow.compute_light(header.number as u64, &Ethash::to_ethash(header.bare_hash()), header.nonce().low_u64());
let mix = Ethash::from_ethash(result.mix_hash);
let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value));
Expand Down Expand Up @@ -242,38 +261,187 @@ impl Header {
}
}

#[test]
fn on_close_block() {
use super::*;
let engine = new_morden().to_engine().unwrap();
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
let last_hashes = vec![genesis_header.hash()];
let b = OpenBlock::new(engine.deref(), db, &genesis_header, &last_hashes, Address::zero(), vec![]);
let b = b.close();
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
}
#[cfg(test)]
mod tests {
extern crate ethash;

#[test]
fn on_close_block_with_uncle() {
use common::*;
use block::*;
use engine::*;
use tests::helpers::*;
use super::*;
let engine = new_morden().to_engine().unwrap();
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
let last_hashes = vec![genesis_header.hash()];
let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, &last_hashes, Address::zero(), vec![]);
let mut uncle = Header::new();
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
uncle.author = uncle_author.clone();
b.push_uncle(uncle).unwrap();

let b = b.close();
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("478eae0e571ba000").unwrap());
assert_eq!(b.state().balance(&uncle_author), U256::from_str("3cb71f51fc558000").unwrap());
use super::super::new_morden;

#[test]
fn on_close_block() {
let engine = new_morden().to_engine().unwrap();
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
let last_hashes = vec![genesis_header.hash()];
let b = OpenBlock::new(engine.deref(), db, &genesis_header, &last_hashes, Address::zero(), vec![]);
let b = b.close();
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
}

#[test]
fn on_close_block_with_uncle() {
let engine = new_morden().to_engine().unwrap();
let genesis_header = engine.spec().genesis_header();
let mut db_result = get_temp_journal_db();
let mut db = db_result.take();
engine.spec().ensure_db_good(&mut db);
let last_hashes = vec![genesis_header.hash()];
let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, &last_hashes, Address::zero(), vec![]);
let mut uncle = Header::new();
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
uncle.author = uncle_author.clone();
b.push_uncle(uncle).unwrap();

let b = b.close();
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("478eae0e571ba000").unwrap());
assert_eq!(b.state().balance(&uncle_author), U256::from_str("3cb71f51fc558000").unwrap());
}

#[test]
fn has_valid_metadata() {
let engine = Ethash::new_boxed(new_morden());
assert!(!engine.name().is_empty());
assert!(engine.version().major >= 1);
}

#[test]
fn can_return_params() {
let engine = Ethash::new_test(new_morden());
assert!(engine.u64_param("durationLimit") > 0);
assert!(engine.u256_param("minimumDifficulty") > U256::zero());
}

#[test]
fn can_return_factory() {
let engine = Ethash::new_test(new_morden());
engine.vm_factory();
}

#[test]
fn can_return_schedule() {
let engine = Ethash::new_test(new_morden());
let schedule = engine.schedule(&EnvInfo {
number: 10000000,
author: x!(0),
timestamp: 0,
difficulty: x!(0),
last_hashes: vec![],
gas_used: x!(0),
gas_limit: x!(0)
});

assert!(schedule.stack_limit > 0);

let schedule = engine.schedule(&EnvInfo {
number: 100,
author: x!(0),
timestamp: 0,
difficulty: x!(0),
last_hashes: vec![],
gas_used: x!(0),
gas_limit: x!(0)
});

assert!(!schedule.have_delegate_call);
}

#[test]
fn can_do_seal_verification_fail() {
let engine = Ethash::new_test(new_morden());
let header: Header = Header::default();

let verify_result = engine.verify_block_basic(&header, None);

match verify_result {
Err(Error::Block(BlockError::InvalidSealArity(_))) => {},
Err(_) => { panic!("should be block seal-arity mismatch error (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}
}

#[test]
fn can_do_difficulty_verification_fail() {
let engine = Ethash::new_test(new_morden());
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).to_vec(), rlp::encode(&H64::zero()).to_vec()]);

let verify_result = engine.verify_block_basic(&header, None);

match verify_result {
Err(Error::Block(BlockError::DifficultyOutOfBounds(_))) => {},
Err(_) => { panic!("should be block difficulty error (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}
}

#[test]
fn can_do_proof_of_work_verification_fail() {
let engine = Ethash::new_test(new_morden());
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).to_vec(), rlp::encode(&H64::zero()).to_vec()]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());

let verify_result = engine.verify_block_basic(&header, None);

match verify_result {
Err(Error::Block(BlockError::InvalidProofOfWork(_))) => {},
Err(_) => { panic!("should be invalid proof of work error (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}
}

#[test]
fn can_do_seal_unordered_verification_fail() {
let engine = Ethash::new_test(new_morden());
let header: Header = Header::default();

let verify_result = engine.verify_block_unordered(&header, None);

match verify_result {
Err(Error::Block(BlockError::InvalidSealArity(_))) => {},
Err(_) => { panic!("should be block seal-arity mismatch error (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}
}

#[test]
fn can_do_seal256_verification_fail() {
let engine = Ethash::new_test(new_morden());
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).to_vec(), rlp::encode(&H64::zero()).to_vec()]);
let verify_result = engine.verify_block_unordered(&header, None);

match verify_result {
Err(Error::Block(BlockError::MismatchedH256SealElement(_))) => {},
Err(_) => { panic!("should be invalid 256-bit seal fail (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}
}

#[test]
fn can_do_proof_of_work_unordered_verification_fail() {
let engine = Ethash::new_test(new_morden());
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).to_vec(), rlp::encode(&H64::zero()).to_vec()]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());

let verify_result = engine.verify_block_unordered(&header, None);

match verify_result {
Err(Error::Block(BlockError::InvalidProofOfWork(_))) => {},
Err(_) => { panic!("should be invalid proof-of-work fail (got {:?})", verify_result); },
_ => { panic!("Should be error, got Ok"); },
}

}

// TODO: difficulty test
}

// TODO: difficulty test
2 changes: 2 additions & 0 deletions ethcore/src/evm/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,13 @@ macro_rules! evm_test_ignore(
#[test]
#[ignore]
#[cfg(feature = "jit")]
#[cfg(feature = "ignored-tests")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit));
}
#[test]
#[ignore]
#[cfg(feature = "ignored-tests")]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter));
}
Expand Down
5 changes: 4 additions & 1 deletion ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ impl<'a> Executive<'a> {
}

#[cfg(test)]
#[allow(dead_code)]
mod tests {
use super::*;
use common::*;
Expand Down Expand Up @@ -599,6 +600,7 @@ mod tests {
}

// test is incorrect, mk
// TODO: fix (preferred) or remove
evm_test_ignore!{test_aba_calls: test_aba_calls_jit, test_aba_calls_int}
fn test_aba_calls(factory: Factory) {
// 60 00 - push 0
Expand Down Expand Up @@ -659,6 +661,7 @@ mod tests {
}

// test is incorrect, mk
// TODO: fix (preferred) or remove
evm_test_ignore!{test_recursive_bomb1: test_recursive_bomb1_jit, test_recursive_bomb1_int}
fn test_recursive_bomb1(factory: Factory) {
// 60 01 - push 1
Expand Down Expand Up @@ -704,6 +707,7 @@ mod tests {
}

// test is incorrect, mk
// TODO: fix (preferred) or remove
evm_test_ignore!{test_transact_simple: test_transact_simple_jit, test_transact_simple_int}
fn test_transact_simple(factory: Factory) {
let keypair = KeyPair::create().unwrap();
Expand Down Expand Up @@ -902,5 +906,4 @@ mod tests {
}
}
}

}
1 change: 0 additions & 1 deletion ethcore/src/json_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ mod test_common;
mod transaction;
mod executive;
mod state;
mod client;
mod chain;
mod homestead_state;
mod homestead_chain;
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use client::{BlockChainClient,Client};
use super::test_common::*;
use tests::helpers::*;
use common::*;

#[test]
fn created() {
Expand Down
4 changes: 0 additions & 4 deletions ethcore/src/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

#[cfg(feature = "json-tests")]
use client::{BlockChainClient, Client};
use std::env;
use common::*;
Expand Down Expand Up @@ -134,7 +133,6 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans
rlp.out()
}

#[cfg(feature = "json-tests")]
pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();

Expand Down Expand Up @@ -174,7 +172,6 @@ pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>
}
}

#[cfg(feature = "json-tests")]
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
Expand Down Expand Up @@ -271,7 +268,6 @@ pub fn get_good_dummy_block() -> Bytes {
create_test_block(&block_header)
}

#[cfg(feature = "json-tests")]
pub fn get_bad_state_dummy_block() -> Bytes {
let mut block_header = Header::new();
let test_spec = get_test_spec();
Expand Down
1 change: 1 addition & 0 deletions ethcore/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

pub mod helpers;
mod client;