Merge pull request #93 from gavofyork/gav
Utils for consensus test decoding and better layout.
This commit is contained in:
commit
2b184585e2
@ -109,6 +109,9 @@ pub mod blockchain;
|
||||
pub mod extras;
|
||||
pub mod evm;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod client;
|
||||
pub mod sync;
|
||||
pub mod block;
|
||||
|
4
src/tests/mod.rs
Normal file
4
src/tests/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[macro_use]
|
||||
mod test_common;
|
||||
|
||||
mod transaction;
|
62
src/tests/test_common.rs
Normal file
62
src/tests/test_common.rs
Normal file
@ -0,0 +1,62 @@
|
||||
pub use common::*;
|
||||
|
||||
pub fn clean(s: &str) -> &str {
|
||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||
&s[2..]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_from_json(json: &Json) -> Bytes {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() % 2 == 1 {
|
||||
FromHex::from_hex(&("0".to_string() + &(clean(s).to_string()))[..]).unwrap_or(vec![])
|
||||
} else {
|
||||
FromHex::from_hex(clean(s)).unwrap_or(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn address_from_json(json: &Json) -> Address {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() % 2 == 1 {
|
||||
address_from_hex(&("0".to_string() + &(clean(s).to_string()))[..])
|
||||
} else {
|
||||
address_from_hex(clean(s))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u256_from_json(json: &Json) -> U256 {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||
// hex
|
||||
U256::from_str(&s[2..]).unwrap()
|
||||
}
|
||||
else {
|
||||
// dec
|
||||
U256::from_dec_str(s).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! declare_test {
|
||||
($id: ident, $name: expr) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $id() {
|
||||
assert!(do_json_test(include_bytes!(concat!("../../res/ethereum/tests/", $name, ".json"))).len() == 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! declare_test_ignore {
|
||||
($id: ident, $name: expr) => {
|
||||
#[test]
|
||||
#[ignore]
|
||||
#[allow(non_snake_case)]
|
||||
fn $id() {
|
||||
assert!(do_json_test(include_bytes!(concat!("../../res/ethereum/tests/", $name, ".json"))).len() == 0);
|
||||
}
|
||||
};
|
||||
}
|
75
src/tests/transaction.rs
Normal file
75
src/tests/transaction.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use super::test_common::*;
|
||||
use evm;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||
let mut failed = Vec::new();
|
||||
let old_schedule = evm::Schedule::new_frontier();
|
||||
let new_schedule = evm::Schedule::new_homestead();
|
||||
for (name, test) in json.as_object().unwrap() {
|
||||
let mut fail = false;
|
||||
let mut fail_unless = |cond: bool| if !cond && fail { failed.push(name.to_string()); fail = true };
|
||||
let schedule = match test.find("blocknumber")
|
||||
.and_then(|j| j.as_string())
|
||||
.and_then(|s| BlockNumber::from_str(s).ok())
|
||||
.unwrap_or(0) { x if x < 900000 => &old_schedule, _ => &new_schedule };
|
||||
let rlp = bytes_from_json(&test["rlp"]);
|
||||
let res = UntrustedRlp::new(&rlp).as_val().map_err(|e| From::from(e)).and_then(|t: Transaction| t.validate(schedule));
|
||||
fail_unless(test.find("transaction").is_none() == res.is_err());
|
||||
if let (Some(&Json::Object(ref tx)), Some(&Json::String(ref expect_sender))) = (test.find("transaction"), test.find("sender")) {
|
||||
let t = res.unwrap();
|
||||
fail_unless(t.sender().unwrap() == address_from_hex(clean(expect_sender)));
|
||||
fail_unless(t.data == bytes_from_json(&tx["data"]));
|
||||
fail_unless(t.gas == u256_from_json(&tx["gasLimit"]));
|
||||
fail_unless(t.gas_price == u256_from_json(&tx["gasPrice"]));
|
||||
fail_unless(t.nonce == u256_from_json(&tx["nonce"]));
|
||||
fail_unless(t.value == u256_from_json(&tx["value"]));
|
||||
if let Action::Call(ref to) = t.action {
|
||||
fail_unless(to == &address_from_json(&tx["to"]));
|
||||
} else {
|
||||
fail_unless(bytes_from_json(&tx["to"]).len() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for f in failed.iter() {
|
||||
println!("FAILED: {:?}", f);
|
||||
}
|
||||
failed
|
||||
}
|
||||
|
||||
// Once we have interpolate idents.
|
||||
/*macro_rules! declare_test {
|
||||
($test_set_name: ident / $name: ident) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $name() {
|
||||
assert!(do_json_test(include_bytes!(concat!("../res/ethereum/tests/", stringify!($test_set_name), "/", stringify!($name), ".json"))).len() == 0);
|
||||
}
|
||||
};
|
||||
($test_set_name: ident / $prename: ident / $name: ident) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
interpolate_idents! { fn [$prename _ $name]()
|
||||
{
|
||||
let json = include_bytes!(concat!("../res/ethereum/tests/", stringify!($test_set_name), "/", stringify!($prename), "/", stringify!($name), ".json"));
|
||||
assert!(do_json_test(json).len() == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare_test!{TransactionTests/ttTransactionTest}
|
||||
declare_test!{TransactionTests/tt10mbDataField}
|
||||
declare_test!{TransactionTests/ttWrongRLPTransaction}
|
||||
declare_test!{TransactionTests/Homestead/ttTransactionTest}
|
||||
declare_test!{TransactionTests/Homestead/tt10mbDataField}
|
||||
declare_test!{TransactionTests/Homestead/ttWrongRLPTransaction}
|
||||
declare_test!{TransactionTests/RandomTests/tr201506052141PYTHON}*/
|
||||
|
||||
declare_test!{TransactionTests_ttTransactionTest, "TransactionTests/ttTransactionTest"}
|
||||
declare_test_ignore!{TransactionTests_tt10mbDataField, "TransactionTests/tt10mbDataField"}
|
||||
declare_test!{TransactionTests_ttWrongRLPTransaction, "TransactionTests/ttWrongRLPTransaction"}
|
||||
declare_test!{TransactionTests_Homestead_ttTransactionTest, "TransactionTests/Homestead/ttTransactionTest"}
|
||||
declare_test_ignore!{TransactionTests_Homestead_tt10mbDataField, "TransactionTests/Homestead/tt10mbDataField"}
|
||||
declare_test!{TransactionTests_Homestead_ttWrongRLPTransaction, "TransactionTests/Homestead/ttWrongRLPTransaction"}
|
||||
declare_test!{TransactionTests_RandomTests_tr201506052141PYTHON, "TransactionTests/RandomTests/tr201506052141PYTHON"}
|
@ -147,144 +147,16 @@ impl Decodable for Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean(s: &str) -> &str {
|
||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||
&s[2..]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
#[test]
|
||||
fn sender_test() {
|
||||
let t: Transaction = decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
|
||||
assert_eq!(t.data, b"");
|
||||
assert_eq!(t.gas, U256::from(0x5208u64));
|
||||
assert_eq!(t.gas_price, U256::from(0x01u64));
|
||||
assert_eq!(t.nonce, U256::from(0x00u64));
|
||||
if let Action::Call(ref to) = t.action {
|
||||
assert_eq!(*to, address_from_hex("095e7baea6a6c7c4c2dfeb977efac326af552d87"));
|
||||
} else { panic!(); }
|
||||
assert_eq!(t.value, U256::from(0x0au64));
|
||||
assert_eq!(t.sender().unwrap(), address_from_hex("0f65fe9276bc9a24ae7083ae28e2660ef72df99e"));
|
||||
}
|
||||
|
||||
pub fn bytes_from_json(json: &Json) -> Bytes {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() % 2 == 1 {
|
||||
FromHex::from_hex(&("0".to_string() + &(clean(s).to_string()))[..]).unwrap_or(vec![])
|
||||
} else {
|
||||
FromHex::from_hex(clean(s)).unwrap_or(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn address_from_json(json: &Json) -> Address {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() % 2 == 1 {
|
||||
address_from_hex(&("0".to_string() + &(clean(s).to_string()))[..])
|
||||
} else {
|
||||
address_from_hex(clean(s))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u256_from_json(json: &Json) -> U256 {
|
||||
let s = json.as_string().unwrap();
|
||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||
// hex
|
||||
U256::from_str(&s[2..]).unwrap()
|
||||
}
|
||||
else {
|
||||
// dec
|
||||
U256::from_dec_str(s).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use evm::Schedule;
|
||||
use header::BlockNumber;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sender_test() {
|
||||
let t: Transaction = decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
|
||||
assert_eq!(t.data, b"");
|
||||
assert_eq!(t.gas, U256::from(0x5208u64));
|
||||
assert_eq!(t.gas_price, U256::from(0x01u64));
|
||||
assert_eq!(t.nonce, U256::from(0x00u64));
|
||||
if let Action::Call(ref to) = t.action {
|
||||
assert_eq!(*to, address_from_hex("095e7baea6a6c7c4c2dfeb977efac326af552d87"));
|
||||
} else { panic!(); }
|
||||
assert_eq!(t.value, U256::from(0x0au64));
|
||||
assert_eq!(t.sender().unwrap(), address_from_hex("0f65fe9276bc9a24ae7083ae28e2660ef72df99e"));
|
||||
}
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||
let mut failed = Vec::new();
|
||||
let old_schedule = Schedule::new_frontier();
|
||||
let new_schedule = Schedule::new_homestead();
|
||||
for (name, test) in json.as_object().unwrap() {
|
||||
let mut fail = false;
|
||||
let mut fail_unless = |cond: bool| if !cond && fail { failed.push(name.to_string()); fail = true };
|
||||
let schedule = match test.find("blocknumber")
|
||||
.and_then(|j| j.as_string())
|
||||
.and_then(|s| BlockNumber::from_str(s).ok())
|
||||
.unwrap_or(0) { x if x < 900000 => &old_schedule, _ => &new_schedule };
|
||||
let rlp = bytes_from_json(&test["rlp"]);
|
||||
let res = UntrustedRlp::new(&rlp).as_val().map_err(|e| From::from(e)).and_then(|t: Transaction| t.validate(schedule));
|
||||
fail_unless(test.find("transaction").is_none() == res.is_err());
|
||||
if let (Some(&Json::Object(ref tx)), Some(&Json::String(ref expect_sender))) = (test.find("transaction"), test.find("sender")) {
|
||||
let t = res.unwrap();
|
||||
fail_unless(t.sender().unwrap() == address_from_hex(clean(expect_sender)));
|
||||
fail_unless(t.data == bytes_from_json(&tx["data"]));
|
||||
fail_unless(t.gas == u256_from_json(&tx["gasLimit"]));
|
||||
fail_unless(t.gas_price == u256_from_json(&tx["gasPrice"]));
|
||||
fail_unless(t.nonce == u256_from_json(&tx["nonce"]));
|
||||
fail_unless(t.value == u256_from_json(&tx["value"]));
|
||||
if let Action::Call(ref to) = t.action {
|
||||
fail_unless(to == &address_from_json(&tx["to"]));
|
||||
} else {
|
||||
fail_unless(bytes_from_json(&tx["to"]).len() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for f in failed.iter() {
|
||||
println!("FAILED: {:?}", f);
|
||||
}
|
||||
failed
|
||||
}
|
||||
|
||||
// Once we have interpolate idents.
|
||||
/*macro_rules! declare_test {
|
||||
($test_set_name: ident / $name: ident) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $name() {
|
||||
assert!(do_json_test(include_bytes!(concat!("../res/ethereum/tests/", stringify!($test_set_name), "/", stringify!($name), ".json"))).len() == 0);
|
||||
}
|
||||
};
|
||||
($test_set_name: ident / $prename: ident / $name: ident) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
interpolate_idents! { fn [$prename _ $name]()
|
||||
{
|
||||
let json = include_bytes!(concat!("../res/ethereum/tests/", stringify!($test_set_name), "/", stringify!($prename), "/", stringify!($name), ".json"));
|
||||
assert!(do_json_test(json).len() == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare_test!{TransactionTests/ttTransactionTest}
|
||||
declare_test!{TransactionTests/tt10mbDataField}
|
||||
declare_test!{TransactionTests/ttWrongRLPTransaction}
|
||||
declare_test!{TransactionTests/Homestead/ttTransactionTest}
|
||||
declare_test!{TransactionTests/Homestead/tt10mbDataField}
|
||||
declare_test!{TransactionTests/Homestead/ttWrongRLPTransaction}
|
||||
declare_test!{TransactionTests/RandomTests/tr201506052141PYTHON}*/
|
||||
|
||||
macro_rules! declare_test {
|
||||
($id: ident, $name: expr) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $id() {
|
||||
assert!(do_json_test(include_bytes!(concat!("../res/ethereum/tests/", $name, ".json"))).len() == 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
declare_test!{TransactionTests_ttTransactionTest, "TransactionTests/ttTransactionTest"}
|
||||
declare_test!{TransactionTests_tt10mbDataField, "TransactionTests/tt10mbDataField"}
|
||||
declare_test!{TransactionTests_ttWrongRLPTransaction, "TransactionTests/ttWrongRLPTransaction"}
|
||||
declare_test!{TransactionTests_Homestead_ttTransactionTest, "TransactionTests/Homestead/ttTransactionTest"}
|
||||
declare_test!{TransactionTests_Homestead_tt10mbDataField, "TransactionTests/Homestead/tt10mbDataField"}
|
||||
declare_test!{TransactionTests_Homestead_ttWrongRLPTransaction, "TransactionTests/Homestead/ttWrongRLPTransaction"}
|
||||
declare_test!{TransactionTests_RandomTests_tr201506052141PYTHON, "TransactionTests/RandomTests/tr201506052141PYTHON"}
|
||||
}
|
Loading…
Reference in New Issue
Block a user