Skip to content

Commit d508aaa

Browse files
authored
Merge pull request #3206 from Pana/feat/blockTest
feat: add blocktest subcommand to evm-spec-tester
2 parents 32819c3 + 68b7537 commit d508aaa

File tree

14 files changed

+227
-139
lines changed

14 files changed

+227
-139
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,4 @@ jobs:
183183
run: cargo build --release --bin evm-spec-tester
184184

185185
- name: Run EVM spec tests
186-
run: cargo run --release --bin evm-spec-tester -- testdata/evm-spec-test
186+
run: cargo run --release --bin evm-spec-tester -- statetest testdata/evm-spec-test

Cargo.lock

Lines changed: 17 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,16 +332,19 @@ blst = "0.3"
332332
#rustls = "0.21"
333333
hashbrown = "0.7.1"
334334

335+
# cli arg parsing
336+
clap = "2" # outdated, need to migrate to clap 4
337+
clap4 = { version = "4", package = "clap" }
338+
docopt = "1.0"
339+
clap-verbosity-flag = "3"
340+
335341
# rand & rng
336342
rand = "0.7"
337343
rand_xorshift = "0.2"
338344
rand_08 = { package = "rand", version = "0.8" }
339345
rand_chacha = "0.2.1"
340346

341347
# misc
342-
clap = "2" # outdated, need to migrate to clap 4
343-
clap4 = { version = "4", package = "clap" }
344-
structopt = { version = "0.3", default-features = false } # unmaintained, need to migrate to clap 4
345348
log = "0.4"
346349
log4rs = "1.3.0"
347350
env_logger = "0.11"
@@ -371,7 +374,6 @@ ipnetwork = "0.12.6"
371374
derivative = "2.0.2"
372375
edit-distance = "2"
373376
zeroize = "1"
374-
docopt = "1.0"
375377
vergen = "8.3.2"
376378
target_info = "0.1"
377379
bit-set = "0.4"

bins/evm-spec-tester/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ hex-literal = { workspace = true }
3434

3535
log = { workspace = true }
3636

37-
structopt = { workspace = true }
3837
env_logger = { workspace = true }
39-
itertools = { workspace = true }
38+
itertools = { workspace = true }
39+
40+
clap = { version = "4.5", features = ["derive"] }
41+
clap-verbosity-flag = { workspace = true }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use crate::util::{find_all_json_tests, make_configuration};
2+
use cfx_config::Configuration;
3+
use clap::Args;
4+
use std::{path::PathBuf, sync::Arc};
5+
6+
/// ethereum statetest doc: https://eest.ethereum.org/main/consuming_tests/state_test/
7+
#[derive(Args, Debug)]
8+
pub struct BlockchainTestCmd {
9+
/// Paths to blockchain test files or directories
10+
#[arg(required = true)]
11+
pub(super) paths: Vec<PathBuf>,
12+
13+
/// Conflux client configuration
14+
#[arg(short, long, value_parser = make_configuration, default_value = "", help = "Path to the configuration file")]
15+
pub(super) config: Arc<Configuration>,
16+
17+
/// Only run tests matching this string
18+
#[arg(short, long, value_name = "Matches")]
19+
pub(super) matches: Option<String>,
20+
}
21+
22+
impl BlockchainTestCmd {
23+
pub fn run(&self) -> bool {
24+
for path in &self.paths {
25+
if !path.exists() {
26+
panic!("Path not exists: {:?}", path);
27+
}
28+
29+
let test_files = find_all_json_tests(path);
30+
31+
if test_files.is_empty() {
32+
error!("No fixtures found in directory: {:?}", path);
33+
continue;
34+
}
35+
36+
if let Err(_) = self.run_file_tests(test_files, path) {
37+
warn!("Failed to run tests in directory: {:?}", path);
38+
continue;
39+
}
40+
}
41+
42+
true
43+
}
44+
45+
fn run_file_tests(
46+
&self, test_files: Vec<PathBuf>, path: &PathBuf,
47+
) -> Result<(), String> {
48+
info!(
49+
"Running {} TestSuites in {}",
50+
test_files.len(),
51+
path.display()
52+
);
53+
54+
Ok(())
55+
}
56+
}

bins/evm-spec-tester/src/cmd.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use crate::{blocktest::BlockchainTestCmd, statetest::command::StateTestCmd};
2+
use clap::{Parser, Subcommand};
3+
use clap_verbosity_flag::{InfoLevel, Verbosity};
4+
5+
/// A command line tool for running Ethereum spec tests
6+
#[derive(Parser, Debug)]
7+
#[command(infer_subcommands = true)]
8+
#[command(version, about, long_about = None)]
9+
#[command(propagate_version = true)]
10+
pub struct MainCmd {
11+
/// Verbosity level (can be used multiple times)
12+
/// Check detail at https://docs.rs/clap-verbosity-flag/3.0.2/clap_verbosity_flag/
13+
#[command(flatten)]
14+
pub verbose: Verbosity<InfoLevel>,
15+
#[command(subcommand)]
16+
command: Commands,
17+
}
18+
19+
#[derive(Subcommand, Debug)]
20+
#[command(infer_subcommands = true)]
21+
#[allow(clippy::large_enum_variant)]
22+
pub enum Commands {
23+
/// Execute state tests of ethereum execution spec tests
24+
Statetest(StateTestCmd),
25+
/// Execute blockchain tests of ethereum execution spec tests
26+
Blocktest(BlockchainTestCmd),
27+
}
28+
29+
impl MainCmd {
30+
pub fn run(self) -> bool {
31+
match self.command {
32+
Commands::Statetest(cmd) => cmd.run(),
33+
Commands::Blocktest(cmd) => cmd.run(),
34+
}
35+
}
36+
}

bins/evm-spec-tester/src/main.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,29 @@
11
#[macro_use]
22
extern crate log;
33

4+
mod blocktest;
5+
mod cmd;
46
mod statetest;
7+
mod util;
58

6-
use statetest::command::StateTestCmd;
7-
use structopt::StructOpt;
8-
9-
fn init_logger(verbosity: u8) {
10-
use log::LevelFilter;
11-
12-
const BASE_LEVEL: u8 = 2;
13-
14-
let level = match BASE_LEVEL + verbosity {
15-
0 => LevelFilter::Error,
16-
1 => LevelFilter::Warn,
17-
2 => LevelFilter::Info,
18-
3 => LevelFilter::Debug,
19-
_ => LevelFilter::Trace,
20-
};
9+
use clap::Parser;
10+
use cmd::MainCmd;
11+
use log::LevelFilter;
2112

13+
fn init_logger(level_filter: LevelFilter) {
2214
env_logger::Builder::new()
2315
.target(env_logger::Target::Stdout)
2416
.filter(None, LevelFilter::Off)
25-
.filter_module("evm_spec_tester", level)
17+
.filter_module("evm_spec_tester", level_filter)
2618
.format_timestamp(None) // Optional: add timestamp
2719
// .format_level(true) // show log level
2820
// .format_module_path(true) // show module path
2921
.init();
3022
}
3123

3224
fn main() {
33-
let cmd = StateTestCmd::from_args();
34-
init_logger(cmd.verbose);
25+
let cmd = MainCmd::parse();
26+
init_logger(cmd.verbose.log_level_filter());
3527
let success = cmd.run();
3628
if !success {
3729
std::process::exit(1);
Lines changed: 11 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,20 @@
1-
use cfx_config::{Configuration, RawConfiguration};
2-
use primitives::block_header::CIP112_TRANSITION_HEIGHT;
3-
use std::path::PathBuf;
4-
use structopt::StructOpt;
1+
use crate::util::make_configuration;
2+
use cfx_config::Configuration;
3+
use clap::Args;
4+
use std::{path::PathBuf, sync::Arc};
55

66
/// ethereum statetest doc: https://eest.ethereum.org/main/consuming_tests/state_test/
7-
#[derive(StructOpt)]
8-
#[structopt(name = "statetest", about = "State test command")]
7+
#[derive(Args, Debug)]
98
pub struct StateTestCmd {
10-
/// Paths to test files or directories
11-
#[structopt(parse(from_os_str), required = true)]
9+
/// Paths to state test files or directories
10+
#[arg(required = true)]
1211
pub(super) paths: Vec<PathBuf>,
1312

14-
/// Configuration
15-
#[structopt(short, long, parse(try_from_str = make_configuration), required = true, default_value = "", help = "Path to the configuration file")]
16-
pub(super) config: Configuration,
13+
/// Conflux client configuration
14+
#[arg(short, long, value_parser = make_configuration, default_value = "", help = "Path to the configuration file")]
15+
pub(super) config: Arc<Configuration>,
1716

1817
/// Only run tests matching this string
19-
#[structopt(short, long)]
18+
#[arg(short, long, value_name = "Matches")]
2019
pub(super) matches: Option<String>,
21-
22-
/// Verbosity level (can be used multiple times)
23-
#[structopt(short, long, parse(from_occurrences))]
24-
pub verbose: u8,
25-
}
26-
27-
fn make_configuration(config_file: &str) -> Result<Configuration, String> {
28-
let mut config = Configuration::default();
29-
config.raw_conf = if config_file.is_empty() {
30-
default_raw_configuration()
31-
} else {
32-
RawConfiguration::from_file(config_file)?
33-
};
34-
35-
config.raw_conf.node_type = Some(cfxcore::NodeType::Full);
36-
37-
let cip112_height =
38-
config.raw_conf.cip112_transition_height.unwrap_or(u64::MAX);
39-
match CIP112_TRANSITION_HEIGHT.set(cip112_height) {
40-
Err(e) if e != cip112_height => {
41-
return Err(
42-
"Duplicate setting for CIP-112 config with inconsistent value"
43-
.to_string(),
44-
);
45-
}
46-
_ => {}
47-
}
48-
49-
Ok(config)
50-
}
51-
52-
fn default_raw_configuration() -> RawConfiguration {
53-
let mut config = RawConfiguration::default();
54-
config.mode = Some("dev".to_string());
55-
config.default_transition_time = Some(1);
56-
config.pos_reference_enable_height = 1;
57-
config.align_evm_transition_height = 1;
58-
config.chain_id = Some(2);
59-
config.evm_chain_id = Some(1);
60-
config
6120
}

0 commit comments

Comments
 (0)