fixed loading of executive tests, unrevealed failing consensus tests
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Evm input params.
|
||||
use common::*;
|
||||
use ethjson;
|
||||
|
||||
/// Transaction value
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -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,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.
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ use ethereum;
|
||||
use externalities::*;
|
||||
use substate::*;
|
||||
use tests::helpers::*;
|
||||
use state_diff::StateDiff;
|
||||
use ethjson;
|
||||
|
||||
struct TestEngineFrontier {
|
||||
vm_factory: Factory,
|
||||
@@ -53,6 +55,7 @@ impl Engine for TestEngineFrontier {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct CallCreate {
|
||||
data: Bytes,
|
||||
destination: Option<Address>,
|
||||
@@ -60,6 +63,18 @@ struct CallCreate {
|
||||
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> {
|
||||
@@ -174,58 +189,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![];
|
||||
@@ -247,44 +230,26 @@ 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");
|
||||
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");
|
||||
|
||||
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");
|
||||
}
|
||||
let diff = StateDiff::diff_pod(&state.to_pod(), &From::from(vm.post_state.unwrap()));
|
||||
fail_unless(diff.is_empty(), format!("diff should be empty!: {:?}", diff).as_ref());
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
Reference in New Issue
Block a user