154 lines
5.8 KiB
Rust
154 lines
5.8 KiB
Rust
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
|
// This file is part of OpenEthereum.
|
|
|
|
// OpenEthereum is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// OpenEthereum is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use super::{test_common::*, HookType};
|
|
use client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess};
|
|
use ethjson::{self, spec::ForkSpec};
|
|
use pod_state::PodState;
|
|
use std::path::Path;
|
|
use trace;
|
|
use vm::EnvInfo;
|
|
|
|
fn skip_test(
|
|
test: ðjson::test::StateTests,
|
|
subname: &str,
|
|
chain: &String,
|
|
number: usize,
|
|
) -> bool {
|
|
trace!(target: "json-tests", "[state, skip_test] subname: '{}', chain: '{}', number: {}", subname, chain, number);
|
|
test.skip.iter().any(|state_test| {
|
|
if let Some(subtest) = state_test.names.get(subname) {
|
|
trace!(target: "json-tests", "[state, skip_test] Maybe skipping {:?}", subtest);
|
|
chain == &subtest.chain
|
|
&& (subtest.subnumbers[0] == "*"
|
|
|| subtest.subnumbers.contains(&number.to_string()))
|
|
} else {
|
|
false
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn json_state_test<H: FnMut(&str, HookType)>(
|
|
state_test: ðjson::test::StateTests,
|
|
path: &Path,
|
|
json_data: &[u8],
|
|
start_stop_hook: &mut H,
|
|
) -> Vec<String> {
|
|
let _ = ::env_logger::try_init();
|
|
let tests = ethjson::state::test::Test::load(json_data).expect(&format!(
|
|
"Could not parse JSON state test data from {}",
|
|
path.display()
|
|
));
|
|
let mut failed = Vec::new();
|
|
|
|
for (name, test) in tests.into_iter() {
|
|
if !super::debug_include_test(&name) {
|
|
continue;
|
|
}
|
|
|
|
start_stop_hook(&name, HookType::OnStart);
|
|
|
|
{
|
|
let multitransaction = test.transaction;
|
|
let env: EnvInfo = test.env.into();
|
|
let pre: PodState = test.pre_state.into();
|
|
|
|
for (spec_name, states) in test.post_states {
|
|
let spec = match EvmTestClient::spec_from_json(&spec_name) {
|
|
Some(spec) => spec,
|
|
None => {
|
|
panic!(
|
|
"Unimplemented chainspec '{:?}' in test '{}'",
|
|
spec_name, name
|
|
);
|
|
}
|
|
};
|
|
|
|
//hardcode base fee for part of the london tests, that miss base fee field in env
|
|
let mut test_env = env.clone();
|
|
if spec_name >= ForkSpec::London {
|
|
if test_env.base_fee.is_none() {
|
|
test_env.base_fee = Some(0x0a.into());
|
|
}
|
|
}
|
|
|
|
for (i, state) in states.into_iter().enumerate() {
|
|
let info = format!(
|
|
"TestState/{}/{:?}/{}/trie",
|
|
path.to_string_lossy(),
|
|
spec_name,
|
|
i
|
|
);
|
|
if skip_test(&state_test, &name, &spec.name, i + 1) {
|
|
println!("{}: SKIPPED", info);
|
|
continue;
|
|
}
|
|
|
|
let post_root: H256 = state.hash.into();
|
|
let transaction = multitransaction.select(&state.indexes);
|
|
|
|
let result = || -> Result<_, EvmTestError> {
|
|
Ok(EvmTestClient::from_pod_state(&spec, pre.clone())?.transact(
|
|
&test_env,
|
|
transaction,
|
|
trace::NoopTracer,
|
|
trace::NoopVMTracer,
|
|
))
|
|
};
|
|
match result() {
|
|
Err(err) => {
|
|
println!("{} !!! Unexpected internal error: {:?}", info, err);
|
|
flushln!("{} fail", info);
|
|
failed.push(name.clone());
|
|
}
|
|
Ok(Ok(TransactSuccess { state_root, .. })) if state_root != post_root => {
|
|
println!(
|
|
"{}: post state root mismatch: got {:?}, want {:?}",
|
|
info, state_root, post_root
|
|
);
|
|
flushln!("{} fail", info);
|
|
failed.push(name.clone());
|
|
}
|
|
Ok(Err(TransactErr {
|
|
state_root,
|
|
ref error,
|
|
..
|
|
})) if state_root != post_root => {
|
|
println!(
|
|
"{}: post state root mismatch: got {:?}, want {:?}",
|
|
info, state_root, post_root
|
|
);
|
|
println!("{} !!! Execution error: {:?}", info, error);
|
|
flushln!("{} fail", info);
|
|
failed.push(name.clone());
|
|
}
|
|
Ok(Err(TransactErr { error, .. })) => {
|
|
flushln!("{} ok ({:?})", info, error);
|
|
}
|
|
Ok(_) => {
|
|
flushln!("{} ok", info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
start_stop_hook(&name, HookType::OnStop);
|
|
}
|
|
|
|
failed
|
|
}
|