pwasm-run-test utility upgrade

This commit is contained in:
NikVolf 2017-11-27 16:19:02 +03:00
parent e8787c1acf
commit 4f12e1dab1
5 changed files with 104 additions and 12 deletions

View File

@ -1,7 +1,7 @@
[ [
{ {
"caption": "Sample test", "caption": "Sample test",
"wasm": "./res/sample1.wasm", "source": "./res/sample1.wasm",
"address": "0x1000000000000000000000000000000000000001", "address": "0x1000000000000000000000000000000000000001",
"sender": "0x1000000000000000000000000000000000000002", "sender": "0x1000000000000000000000000000000000000002",
"value": "0x0000000000000000000000000000000000000000000000000000000000000000", "value": "0x0000000000000000000000000000000000000000000000000000000000000000",
@ -21,11 +21,25 @@
}, },
{ {
"caption": "Keccak test", "caption": "Keccak test",
"wasm": "./res/sample2.wasm", "source": "./res/sample2.wasm",
"payload": "0x736f6d657468696e67", "payload": "0x736f6d657468696e67",
"gasLimit": 100000, "gasLimit": 100000,
"asserts": [ "asserts": [
{ "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" } { "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" }
] ]
},
{
"caption": "Token total supply",
"source": {
"constructor": "./res/sample3.wasm",
"sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
"at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"arguments": "0x0000000000000000000000000000000000000000000000000000000010000000"
},
"payload": "0x18160ddd",
"gasLimit": 100000,
"asserts": [
{ "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" }
]
} }
] ]

Binary file not shown.

View File

@ -3,11 +3,32 @@ use ethjson::uint::Uint;
use ethjson::hash::{Address, H256}; use ethjson::hash::{Address, H256};
use ethjson::bytes::Bytes; use ethjson::bytes::Bytes;
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Source {
Raw(Cow<'static, String>),
Constructor {
#[serde(rename="constructor")]
source: Cow<'static, String>,
arguments: Bytes,
sender: Address,
at: Address,
},
}
impl Source {
pub fn as_ref(&self) -> &str {
match *self {
Source::Raw(ref r) => r.as_ref(),
Source::Constructor { ref source, .. } => source.as_ref(),
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Fixture { pub struct Fixture {
pub caption: Cow<'static, String>, pub caption: Cow<'static, String>,
#[serde(rename="wasm")] pub source: Source,
pub wasm_file: Cow<'static, String>,
pub address: Option<Address>, pub address: Option<Address>,
pub sender: Option<Address>, pub sender: Option<Address>,
pub value: Option<Uint>, pub value: Option<Uint>,

View File

@ -1,6 +1,6 @@
use fixture::{Fixture, Assert, CallLocator}; use fixture::{Fixture, Assert, CallLocator, Source};
use wasm::WasmInterpreter; use wasm::WasmInterpreter;
use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; use vm::{self, Vm, GasLeft, ActionParams, ActionValue, ParamsType};
use vm::tests::FakeExt; use vm::tests::FakeExt;
use std::io::{self, Read}; use std::io::{self, Read};
use std::{fs, path, fmt}; use std::{fs, path, fmt};
@ -19,6 +19,11 @@ fn wasm_interpreter() -> WasmInterpreter {
WasmInterpreter::new().expect("wasm interpreter to create without errors") WasmInterpreter::new().expect("wasm interpreter to create without errors")
} }
#[derive(Debug)]
pub enum SpecNonconformity {
Address,
}
#[derive(Debug)] #[derive(Debug)]
pub enum Fail { pub enum Fail {
Return { expected: Vec<u8>, actual: Vec<u8> }, Return { expected: Vec<u8>, actual: Vec<u8> },
@ -27,6 +32,7 @@ pub enum Fail {
Load(io::Error), Load(io::Error),
NoCall(CallLocator), NoCall(CallLocator),
StorageMismatch { key: H256, expected: H256, actual: Option<H256> }, StorageMismatch { key: H256, expected: H256, actual: Option<H256> },
Nonconformity(SpecNonconformity)
} }
impl Fail { impl Fail {
@ -37,6 +43,10 @@ impl Fail {
fn load(err: io::Error) -> Vec<Fail> { fn load(err: io::Error) -> Vec<Fail> {
vec![Fail::Load(err)] vec![Fail::Load(err)]
} }
fn nononformity(kind: SpecNonconformity) -> Vec<Fail> {
vec![Fail::Nonconformity(kind)]
}
} }
impl fmt::Display for Fail { impl fmt::Display for Fail {
@ -52,6 +62,7 @@ impl fmt::Display for Fail {
actual.to_hex(), actual.to_hex(),
actual.len() actual.len()
), ),
UsedGas { expected, actual } => UsedGas { expected, actual } =>
write!(f, "Expected to use gas: {}, but got actual gas used: {}", expected, actual), write!(f, "Expected to use gas: {}, but got actual gas used: {}", expected, actual),
@ -80,22 +91,69 @@ impl fmt::Display for Fail {
key.as_ref().to_vec().to_hex(), key.as_ref().to_vec().to_hex(),
expected.as_ref().to_vec().to_hex(), expected.as_ref().to_vec().to_hex(),
), ),
Nonconformity(SpecNonconformity::Address) =>
write!(f, "Cannot use address when constructor is specified!"),
} }
} }
} }
pub fn construct(
ext: &mut vm::Ext,
source: Vec<u8>,
arguments: Vec<u8>,
sender: H160,
at: H160,
) -> Result<Vec<u8>, vm::Error> {
let mut params = ActionParams::default();
params.sender = sender;
params.address = at;
params.gas = U256::from(100_000_000);
params.data = Some(arguments);
params.code = Some(Arc::new(source));
params.params_type = ParamsType::Separate;
Ok(
match wasm_interpreter().exec(params, ext)? {
GasLeft::Known(_) => Vec::new(),
GasLeft::NeedsReturn { data, .. } => data.to_vec(),
}
)
}
pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> { pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> {
let mut params = ActionParams::default(); let mut params = ActionParams::default();
params.code = Some(Arc::new( let source = match load_code(fixture.source.as_ref()) {
match load_code(fixture.wasm_file.as_ref()) {
Ok(code) => code, Ok(code) => code,
Err(e) => { return Fail::load(e); }, Err(e) => { return Fail::load(e); },
};
let mut ext = FakeExt::new();
params.code = Some(Arc::new(
if let Source::Constructor { ref arguments, ref sender, ref at, .. } = fixture.source {
match construct(&mut ext, source, arguments.clone().into(), sender.clone().into(), at.clone().into()) {
Ok(code) => code,
Err(e) => { return Fail::runtime(e); }
}
} else {
source
} }
)); ));
if let Some(ref sender) = fixture.sender {
params.sender = sender.clone().into();
}
if let Some(ref address) = fixture.address { if let Some(ref address) = fixture.address {
if let Source::Constructor { .. } = fixture.source {
return Fail::nononformity(SpecNonconformity::Address);
}
params.address = address.clone().into(); params.address = address.clone().into();
} else if let Source::Constructor { ref at, .. } = fixture.source {
params.address = at.clone().into();
} }
if let Some(gas_limit) = fixture.gas_limit { if let Some(gas_limit) = fixture.gas_limit {
@ -110,7 +168,6 @@ pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> {
params.value = ActionValue::Transfer(value.clone().into()) params.value = ActionValue::Transfer(value.clone().into())
} }
let mut ext = FakeExt::new();
if let Some(ref storage) = fixture.storage { if let Some(ref storage) = fixture.storage {
for storage_entry in storage.iter() { for storage_entry in storage.iter() {
let key: U256 = storage_entry.key.into(); let key: U256 = storage_entry.key.into();

View File

@ -32,8 +32,8 @@ lazy_static! {
builder.parse(&log); builder.parse(&log);
} }
if builder.init().is_ok() { if !builder.init().is_ok() {
println!("logger initialized"); println!("logger initialization failed!");
} }
}; };
} }