2019-01-07 11:33:07 +01:00
|
|
|
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
|
|
|
// This file is part of Parity Ethereum.
|
2016-02-05 13:40:41 +01:00
|
|
|
|
2019-01-07 11:33:07 +01:00
|
|
|
// Parity Ethereum is free software: you can redistribute it and/or modify
|
2016-02-05 13:40:41 +01:00
|
|
|
// 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.
|
|
|
|
|
2019-01-07 11:33:07 +01:00
|
|
|
// Parity Ethereum is distributed in the hope that it will be useful,
|
2016-02-05 13:40:41 +01:00
|
|
|
// 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
|
2019-01-07 11:33:07 +01:00
|
|
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
2016-02-05 13:40:41 +01:00
|
|
|
|
2017-07-29 23:19:33 +02:00
|
|
|
use std::collections::HashSet;
|
|
|
|
use std::io::Read;
|
2017-04-12 13:33:49 +02:00
|
|
|
use std::fs::{File, read_dir};
|
|
|
|
use std::path::Path;
|
|
|
|
use std::ffi::OsString;
|
2018-01-10 13:35:18 +01:00
|
|
|
pub use ethereum_types::{H256, U256, Address};
|
2017-04-12 13:33:49 +02:00
|
|
|
|
2018-06-25 11:21:45 +02:00
|
|
|
/// Indicate when to run the hook passed to test functions.
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
|
|
pub enum HookType {
|
|
|
|
/// Hook to code to run on test start.
|
|
|
|
OnStart,
|
|
|
|
/// Hook to code to run on test end.
|
|
|
|
OnStop
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_test_path<H: FnMut(&str, HookType)>(
|
|
|
|
p: &Path, skip: &[&'static str],
|
|
|
|
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
|
|
|
start_stop_hook: &mut H
|
2018-09-25 12:24:40 +02:00
|
|
|
) {
|
|
|
|
let mut errors = Vec::new();
|
|
|
|
run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors);
|
|
|
|
let empty: [String; 0] = [];
|
|
|
|
assert_eq!(errors, empty);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_test_path_inner<H: FnMut(&str, HookType)>(
|
|
|
|
p: &Path, skip: &[&'static str],
|
|
|
|
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
|
|
|
start_stop_hook: &mut H,
|
|
|
|
errors: &mut Vec<String>
|
2018-06-25 11:21:45 +02:00
|
|
|
) {
|
2017-04-12 13:33:49 +02:00
|
|
|
let path = Path::new(p);
|
|
|
|
let s: HashSet<OsString> = skip.iter().map(|s| {
|
|
|
|
let mut os: OsString = s.into();
|
|
|
|
os.push(".json");
|
|
|
|
os
|
|
|
|
}).collect();
|
2018-09-10 22:38:30 +02:00
|
|
|
let extension = path.extension().and_then(|s| s.to_str());
|
2017-04-12 13:33:49 +02:00
|
|
|
if path.is_dir() {
|
|
|
|
for p in read_dir(path).unwrap().filter_map(|e| {
|
|
|
|
let e = e.unwrap();
|
|
|
|
if s.contains(&e.file_name()) {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(e.path())
|
|
|
|
}}) {
|
2018-09-25 12:24:40 +02:00
|
|
|
run_test_path_inner(&p, skip, runner, start_stop_hook, errors);
|
2017-04-12 13:33:49 +02:00
|
|
|
}
|
2018-09-10 22:38:30 +02:00
|
|
|
} else if extension == Some("swp") || extension == None {
|
|
|
|
// Ignore junk
|
2017-04-12 13:33:49 +02:00
|
|
|
} else {
|
|
|
|
let mut path = p.to_path_buf();
|
|
|
|
path.set_extension("json");
|
2018-09-25 12:24:40 +02:00
|
|
|
run_test_file_append(&path, runner, start_stop_hook, errors)
|
2017-04-12 13:33:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-25 12:24:40 +02:00
|
|
|
fn run_test_file_append<H: FnMut(&str, HookType)>(
|
|
|
|
path: &Path,
|
|
|
|
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
|
|
|
start_stop_hook: &mut H,
|
|
|
|
errors: &mut Vec<String>
|
|
|
|
) {
|
|
|
|
let mut data = Vec::new();
|
|
|
|
let mut file = match File::open(&path) {
|
|
|
|
Ok(file) => file,
|
|
|
|
Err(_) => panic!("Error opening test file at: {:?}", path),
|
|
|
|
};
|
|
|
|
file.read_to_end(&mut data).expect("Error reading test file");
|
|
|
|
errors.append(&mut runner(&data, start_stop_hook));
|
|
|
|
}
|
|
|
|
|
2018-06-25 11:21:45 +02:00
|
|
|
pub fn run_test_file<H: FnMut(&str, HookType)>(
|
|
|
|
path: &Path,
|
|
|
|
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
|
|
|
start_stop_hook: &mut H
|
|
|
|
) {
|
2017-04-12 13:33:49 +02:00
|
|
|
let mut data = Vec::new();
|
2018-09-10 22:38:30 +02:00
|
|
|
let mut file = match File::open(&path) {
|
|
|
|
Ok(file) => file,
|
|
|
|
Err(_) => panic!("Error opening test file at: {:?}", path),
|
|
|
|
};
|
2017-04-12 13:33:49 +02:00
|
|
|
file.read_to_end(&mut data).expect("Error reading test file");
|
2018-06-25 11:21:45 +02:00
|
|
|
let results = runner(&data, start_stop_hook);
|
2017-09-25 19:45:33 +02:00
|
|
|
let empty: [String; 0] = [];
|
|
|
|
assert_eq!(results, empty);
|
2017-04-12 13:33:49 +02:00
|
|
|
}
|
2016-01-12 16:20:29 +01:00
|
|
|
|
2018-06-25 11:21:45 +02:00
|
|
|
#[cfg(test)]
|
2016-01-21 16:08:09 +01:00
|
|
|
macro_rules! test {
|
2017-04-12 13:33:49 +02:00
|
|
|
($name: expr, $skip: expr) => {
|
2018-06-25 11:21:45 +02:00
|
|
|
::json_tests::test_common::run_test_path(::std::path::Path::new(concat!("res/ethereum/tests/", $name)), &$skip, do_json_test, &mut |_, _| ());
|
2016-01-21 16:08:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 16:20:29 +01:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! declare_test {
|
2017-04-12 13:33:49 +02:00
|
|
|
(skip => $arr: expr, $id: ident, $name: expr) => {
|
2018-06-25 11:21:45 +02:00
|
|
|
#[cfg(test)]
|
2017-04-12 13:33:49 +02:00
|
|
|
#[test]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
fn $id() {
|
|
|
|
test!($name, $arr);
|
|
|
|
}
|
|
|
|
};
|
2016-01-21 16:08:09 +01:00
|
|
|
(ignore => $id: ident, $name: expr) => {
|
2018-06-25 11:21:45 +02:00
|
|
|
#[cfg(test)]
|
2016-01-21 16:08:09 +01:00
|
|
|
#[ignore]
|
2016-01-12 16:20:29 +01:00
|
|
|
#[test]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
fn $id() {
|
2017-04-12 13:33:49 +02:00
|
|
|
test!($name, []);
|
2016-01-12 16:20:29 +01:00
|
|
|
}
|
|
|
|
};
|
2016-01-21 16:08:09 +01:00
|
|
|
(heavy => $id: ident, $name: expr) => {
|
2018-06-25 11:21:45 +02:00
|
|
|
#[cfg(test)]
|
2016-01-21 16:08:09 +01:00
|
|
|
#[cfg(feature = "test-heavy")]
|
2016-01-12 16:20:29 +01:00
|
|
|
#[test]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
fn $id() {
|
2017-04-12 13:33:49 +02:00
|
|
|
test!($name, []);
|
2016-01-12 16:20:29 +01:00
|
|
|
}
|
|
|
|
};
|
2016-01-21 16:08:09 +01:00
|
|
|
($id: ident, $name: expr) => {
|
2018-06-25 11:21:45 +02:00
|
|
|
#[cfg(test)]
|
2016-01-21 16:08:09 +01:00
|
|
|
#[test]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
fn $id() {
|
2017-04-12 13:33:49 +02:00
|
|
|
test!($name, []);
|
2016-01-21 16:08:09 +01:00
|
|
|
}
|
|
|
|
}
|
2016-01-12 16:20:29 +01:00
|
|
|
}
|