diff --git a/ethcore/wasm/run/res/sample-fixture.json b/ethcore/wasm/run/res/sample-fixture.json
index 4f53eaa38..7be3e04be 100644
--- a/ethcore/wasm/run/res/sample-fixture.json
+++ b/ethcore/wasm/run/res/sample-fixture.json
@@ -1,7 +1,7 @@
[
{
"caption": "Sample test",
- "wasm": "./res/sample1.wasm",
+ "source": "./res/sample1.wasm",
"address": "0x1000000000000000000000000000000000000001",
"sender": "0x1000000000000000000000000000000000000002",
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -21,11 +21,25 @@
},
{
"caption": "Keccak test",
- "wasm": "./res/sample2.wasm",
+ "source": "./res/sample2.wasm",
"payload": "0x736f6d657468696e67",
"gasLimit": 100000,
"asserts": [
{ "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" }
]
+ },
+ {
+ "caption": "Token total supply",
+ "source": {
+ "constructor": "./res/sample3.wasm",
+ "sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
+ "at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
+ "arguments": "0x0000000000000000000000000000000000000000000000000000000010000000"
+ },
+ "payload": "0x18160ddd",
+ "gasLimit": 100000,
+ "asserts": [
+ { "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" }
+ ]
}
]
\ No newline at end of file
diff --git a/ethcore/wasm/run/res/sample3.wasm b/ethcore/wasm/run/res/sample3.wasm
new file mode 100644
index 000000000..1811215b4
Binary files /dev/null and b/ethcore/wasm/run/res/sample3.wasm differ
diff --git a/ethcore/wasm/run/src/fixture.rs b/ethcore/wasm/run/src/fixture.rs
index 0fd3a08e1..ba2da0670 100644
--- a/ethcore/wasm/run/src/fixture.rs
+++ b/ethcore/wasm/run/src/fixture.rs
@@ -3,11 +3,32 @@ use ethjson::uint::Uint;
use ethjson::hash::{Address, H256};
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)]
pub struct Fixture {
pub caption: Cow<'static, String>,
- #[serde(rename="wasm")]
- pub wasm_file: Cow<'static, String>,
+ pub source: Source,
pub address: Option
,
pub sender: Option,
pub value: Option,
diff --git a/ethcore/wasm/run/src/runner.rs b/ethcore/wasm/run/src/runner.rs
index edfc1ee4b..06a6b0469 100644
--- a/ethcore/wasm/run/src/runner.rs
+++ b/ethcore/wasm/run/src/runner.rs
@@ -1,6 +1,6 @@
-use fixture::{Fixture, Assert, CallLocator};
+use fixture::{Fixture, Assert, CallLocator, Source};
use wasm::WasmInterpreter;
-use vm::{self, Vm, GasLeft, ActionParams, ActionValue};
+use vm::{self, Vm, GasLeft, ActionParams, ActionValue, ParamsType};
use vm::tests::FakeExt;
use std::io::{self, Read};
use std::{fs, path, fmt};
@@ -19,6 +19,11 @@ fn wasm_interpreter() -> WasmInterpreter {
WasmInterpreter::new().expect("wasm interpreter to create without errors")
}
+#[derive(Debug)]
+pub enum SpecNonconformity {
+ Address,
+}
+
#[derive(Debug)]
pub enum Fail {
Return { expected: Vec, actual: Vec },
@@ -27,6 +32,7 @@ pub enum Fail {
Load(io::Error),
NoCall(CallLocator),
StorageMismatch { key: H256, expected: H256, actual: Option },
+ Nonconformity(SpecNonconformity)
}
impl Fail {
@@ -37,6 +43,10 @@ impl Fail {
fn load(err: io::Error) -> Vec {
vec![Fail::Load(err)]
}
+
+ fn nononformity(kind: SpecNonconformity) -> Vec {
+ vec![Fail::Nonconformity(kind)]
+ }
}
impl fmt::Display for Fail {
@@ -52,6 +62,7 @@ impl fmt::Display for Fail {
actual.to_hex(),
actual.len()
),
+
UsedGas { 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(),
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,
+ arguments: Vec,
+ sender: H160,
+ at: H160,
+) -> Result, 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 {
let mut params = ActionParams::default();
+ let source = match load_code(fixture.source.as_ref()) {
+ Ok(code) => code,
+ Err(e) => { return Fail::load(e); },
+ };
+
+ let mut ext = FakeExt::new();
params.code = Some(Arc::new(
- match load_code(fixture.wasm_file.as_ref()) {
- Ok(code) => code,
- Err(e) => { return Fail::load(e); },
+ 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 Source::Constructor { .. } = fixture.source {
+ return Fail::nononformity(SpecNonconformity::Address);
+ }
+
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 {
@@ -110,7 +168,6 @@ pub fn run_fixture(fixture: &Fixture) -> Vec {
params.value = ActionValue::Transfer(value.clone().into())
}
- let mut ext = FakeExt::new();
if let Some(ref storage) = fixture.storage {
for storage_entry in storage.iter() {
let key: U256 = storage_entry.key.into();
diff --git a/logger/src/rotating.rs b/logger/src/rotating.rs
index d11011f74..e67bdfaad 100644
--- a/logger/src/rotating.rs
+++ b/logger/src/rotating.rs
@@ -32,8 +32,8 @@ lazy_static! {
builder.parse(&log);
}
- if builder.init().is_ok() {
- println!("logger initialized");
+ if !builder.init().is_ok() {
+ println!("logger initialization failed!");
}
};
}