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

Commit

Permalink
Merge pull request #803 from ethcore/executive_tests
Browse files Browse the repository at this point in the history
refactored loading of execution tests
  • Loading branch information
gavofyork committed Mar 25, 2016
2 parents 2c2e8ef + a7ce6fc commit 100e6fa
Show file tree
Hide file tree
Showing 18 changed files with 601 additions and 84 deletions.
17 changes: 17 additions & 0 deletions ethcore/src/action_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

//! Evm input params.
use common::*;
use ethjson;

/// Transaction value
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -67,3 +68,19 @@ impl Default for ActionParams {
}
}
}

impl From<ethjson::vm::Transaction> for ActionParams {
fn from(t: ethjson::vm::Transaction) -> Self {
ActionParams {
code_address: Address::new(),
address: t.address.into(),
sender: t.sender.into(),
origin: t.origin.into(),
code: Some(t.code.into()),
data: Some(t.data.into()),
gas: t.gas.into(),
gas_price: t.gas_price.into(),
value: ActionValue::Transfer(t.value.into()),
}
}
}
16 changes: 16 additions & 0 deletions ethcore/src/env_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use util::*;
use header::BlockNumber;
use ethjson;

/// Simple vector of hashes, should be at most 256 items large, can be smaller if being used
/// for a block whose number is less than 257.
Expand Down Expand Up @@ -69,6 +70,21 @@ impl FromJson for EnvInfo {
}
}

impl From<ethjson::vm::Env> for EnvInfo {
fn from(e: ethjson::vm::Env) -> Self {
let number = e.number.into();
EnvInfo {
number: number,
author: e.author.into(),
difficulty: e.difficulty.into(),
gas_limit: e.gas_limit.into(),
timestamp: e.timestamp.into(),
last_hashes: (1..cmp::min(number + 1, 257)).map(|i| format!("{}", number - i).as_bytes().sha3()).collect(),
gas_used: U256::zero(),
}
}
}

#[cfg(test)]
mod tests {
extern crate rustc_serialize;
Expand Down
4 changes: 2 additions & 2 deletions ethcore/src/json_tests/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
let tests = ethjson::blockchain::Test::load(json_data).unwrap();
let mut failed = Vec::new();

for (name, blockchain) in tests.deref() {
for (name, blockchain) in tests.into_iter() {
let mut fail = false;
{
let mut fail_unless = |cond: bool| if !cond && !fail {
Expand Down Expand Up @@ -61,7 +61,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
client.import_verified_blocks(&IoChannel::disconnected());
}
}
fail_unless(client.chain_info().best_block_hash == blockchain.best_block.clone().into());
fail_unless(client.chain_info().best_block_hash == blockchain.best_block.into());
}
}

Expand Down
113 changes: 44 additions & 69 deletions ethcore/src/json_tests/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use ethereum;
use externalities::*;
use substate::*;
use tests::helpers::*;
use ethjson;

struct TestEngineFrontier {
vm_factory: Factory,
Expand Down Expand Up @@ -53,13 +54,26 @@ impl Engine for TestEngineFrontier {
}
}

#[derive(Debug, PartialEq)]
struct CallCreate {
data: Bytes,
destination: Option<Address>,
gas_limit: U256,
value: U256
}

impl From<ethjson::vm::Call> for CallCreate {
fn from(c: ethjson::vm::Call) -> Self {
let dst: Option<_> = c.destination.into();
CallCreate {
data: c.data.into(),
destination: dst.map(Into::into),
gas_limit: c.gas_limit.into(),
value: c.value.into()
}
}
}

/// Tiny wrapper around executive externalities.
/// Stores callcreates.
struct TestExt<'a> {
Expand Down Expand Up @@ -174,58 +188,26 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
.collect()
}

fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec<String> {
let tests = ethjson::vm::Test::load(json_data).unwrap();
let mut failed = Vec::new();
for (name, test) in json.as_object().unwrap() {

for (name, vm) in tests.into_iter() {
println!("name: {:?}", name);
// sync io is usefull when something crashes in jit
// ::std::io::stdout().write(&name.as_bytes());
// ::std::io::stdout().write(b"\n");
// ::std::io::stdout().flush();
let mut fail = false;
//let mut fail_unless = |cond: bool| if !cond && !fail { failed.push(name.to_string()); fail = true };

let mut fail_unless = |cond: bool, s: &str | if !cond && !fail {
failed.push(format!("[{}] {}: {}", vm, name, s));
failed.push(format!("[{}] {}: {}", vm_type, name, s));
fail = true
};

// test env
let out_of_gas = vm.out_of_gas();
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();

test.find("pre").map(|pre| for (addr, s) in pre.as_object().unwrap() {
let address = Address::from(addr.as_ref());
let balance = xjson!(&s["balance"]);
let code = xjson!(&s["code"]);
let _nonce: U256 = xjson!(&s["nonce"]);

state.new_contract(&address, balance);
state.init_code(&address, code);
BTreeMap::from_json(&s["storage"]).into_iter().foreach(|(k, v)| state.set_storage(&address, k, v));
});

let info = test.find("env").map(|env| {
EnvInfo::from_json(env)
}).unwrap_or_default();

let engine = TestEngineFrontier::new(1, vm.clone());

// params
let mut params = ActionParams::default();
test.find("exec").map(|exec| {
params.address = xjson!(&exec["address"]);
params.sender = xjson!(&exec["caller"]);
params.origin = xjson!(&exec["origin"]);
params.code = xjson!(&exec["code"]);
params.data = xjson!(&exec["data"]);
params.gas = xjson!(&exec["gas"]);
params.gas_price = xjson!(&exec["gasPrice"]);
params.value = ActionValue::Transfer(xjson!(&exec["value"]));
});

let out_of_gas = test.find("callcreates").map(|_calls| {
}).is_none();
state.populate_from(From::from(vm.pre_state.clone()));
let info = From::from(vm.env);
let engine = TestEngineFrontier::new(1, vm_type.clone());
let params = ActionParams::from(vm.transaction);

let mut substate = Substate::new(false);
let mut output = vec![];
Expand All @@ -247,44 +229,37 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
(res, ex.callcreates)
};

// then validate
match res {
Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."),
Ok(gas_left) => {
// println!("name: {}, gas_left : {:?}", name, gas_left);
fail_unless(!out_of_gas, "expected to run out of gas.");
fail_unless(gas_left == xjson!(&test["gas"]), "gas_left is incorrect");
fail_unless(output == Bytes::from_json(&test["out"]), "output is incorrect");

test.find("post").map(|pre| for (addr, s) in pre.as_object().unwrap() {
let address = Address::from(addr.as_ref());

fail_unless(state.code(&address).unwrap_or_else(|| vec![]) == Bytes::from_json(&s["code"]), "code is incorrect");
fail_unless(state.balance(&address) == xjson!(&s["balance"]), "balance is incorrect");
fail_unless(state.nonce(&address) == xjson!(&s["nonce"]), "nonce is incorrect");
BTreeMap::from_json(&s["storage"]).iter().foreach(|(k, v)| fail_unless(&state.storage_at(&address, &k) == v, "storage is incorrect"));
});

let cc = test["callcreates"].as_array().unwrap();
fail_unless(callcreates.len() == cc.len(), "callcreates does not match");
for i in 0..cc.len() {
let callcreate = &callcreates[i];
let expected = &cc[i];
fail_unless(callcreate.data == Bytes::from_json(&expected["data"]), "callcreates data is incorrect");
fail_unless(callcreate.destination == xjson!(&expected["destination"]), "callcreates destination is incorrect");
fail_unless(callcreate.value == xjson!(&expected["value"]), "callcreates value is incorrect");
fail_unless(callcreate.gas_limit == xjson!(&expected["gasLimit"]), "callcreates gas_limit is incorrect");
fail_unless(Some(gas_left) == vm.gas_left.map(Into::into), "gas_left is incorrect");
let vm_output: Option<Vec<u8>> = vm.output.map(Into::into);
fail_unless(Some(output) == vm_output, "output is incorrect");

for (address, account) in vm.post_state.unwrap().into_iter() {
let address = address.into();
let code: Vec<u8> = account.code.into();
fail_unless(state.code(&address).unwrap_or_else(Vec::new) == code, "code is incorrect");
fail_unless(state.balance(&address) == account.balance.into(), "balance is incorrect");
fail_unless(state.nonce(&address) == account.nonce.into(), "nonce is incorrect");
account.storage.into_iter().foreach(|(k, v)| {
let key: U256 = k.into();
let value: U256 = v.into();
fail_unless(state.storage_at(&address, &From::from(key)) == From::from(value), "storage is incorrect");
});
}

let calls: Option<Vec<CallCreate>> = vm.calls.map(|c| c.into_iter().map(From::from).collect());
fail_unless(Some(callcreates) == calls, "callcreates does not match");
}
}
};
}


for f in &failed {
println!("FAILED: {:?}", f);
}

//assert!(false);
failed
}

Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/pod_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use account::*;
use account_db::*;
use ethjson;

#[derive(Debug,Clone,PartialEq,Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
/// An account, expressed as Plain-Old-Data (hence the name).
/// Does not have a DB overlay cache, code hash or anything like that.
pub struct PodAccount {
Expand Down
10 changes: 9 additions & 1 deletion ethcore/src/state_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use pod_state::*;
use account_diff::*;

#[derive(Debug,Clone,PartialEq,Eq)]
/// Expression for the delta between two system states. Encoded the
/// Expression for the delta between two system states. Encoded the
/// delta of every altered account.
pub struct StateDiff (BTreeMap<Address, AccountDiff>);

Expand All @@ -41,6 +41,14 @@ impl fmt::Display for StateDiff {
}
}

impl Deref for StateDiff {
type Target = BTreeMap<Address, AccountDiff>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[cfg(test)]
mod test {
use common::*;
Expand Down
10 changes: 5 additions & 5 deletions json/src/blockchain/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
//! Blockchain test state deserializer.
use std::collections::BTreeMap;
use std::ops::Deref;
use hash::Address;
use blockchain::account::Account;

/// Blockchain test state deserializer.
#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct State(pub BTreeMap<Address, Account>);

impl Deref for State {
type Target = BTreeMap<Address, Account>;
impl IntoIterator for State {
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;

fn deref(&self) -> &Self::Target {
&self.0
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
10 changes: 5 additions & 5 deletions json/src/blockchain/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
//! Blockchain test deserializer.
use std::collections::BTreeMap;
use std::ops::Deref;
use std::io::Read;
use serde_json;
use serde_json::Error;
Expand All @@ -27,11 +26,12 @@ use blockchain::blockchain::BlockChain;
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, BlockChain>);

impl Deref for Test {
type Target = BTreeMap<String, BlockChain>;
impl IntoIterator for Test {
type Item = <BTreeMap<String, BlockChain> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, BlockChain> as IntoIterator>::IntoIter;

fn deref(&self) -> &Self::Target {
&self.0
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

Expand Down
2 changes: 1 addition & 1 deletion json/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ macro_rules! impl_hash {
($name: ident, $inner: ident) => {
/// Lenient hash json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
pub struct $name($inner);
pub struct $name(pub $inner);

impl Into<$inner> for $name {
fn into(self) -> $inner {
Expand Down
2 changes: 2 additions & 0 deletions json/src/lib.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ pub mod uint;
pub mod bytes;
pub mod blockchain;
pub mod spec;
pub mod vm;
pub mod maybe;
Loading

0 comments on commit 100e6fa

Please sign in to comment.