revme/cmd/
eofvalidation.rs1mod test_suite;
2
3pub use test_suite::{TestResult, TestSuite, TestUnit, TestVector};
4
5use crate::{cmd::Error, dir_utils::find_all_json_tests};
6use clap::Parser;
7use revm::bytecode::eof::{validate_raw_eof_inner, CodeType, EofError};
8use std::collections::BTreeMap;
9use std::path::{Path, PathBuf};
10
11#[derive(Parser, Debug)]
13pub struct Cmd {
14 #[arg(required = true, num_args = 1..)]
16 paths: Vec<PathBuf>,
17}
18
19impl Cmd {
20 pub fn run(&self) -> Result<(), Error> {
22 for path in &self.paths {
24 if !path.exists() {
25 return Err(Error::Custom("The specified path does not exist"));
26 }
27 run_test(path)?
28 }
29 Ok(())
30 }
31}
32
33fn skip_test(name: &str) -> bool {
34 if name.starts_with("EOF1_embedded_container") {
36 return true;
37 }
38 matches!(
39 name,
40 "EOF1_undefined_opcodes_186"
41 | ""
42 | "validInvalid_48"
44 | "validInvalid_1"
45 | "EOF1_truncated_section_3"
46 | "EOF1_truncated_section_4"
47 | "validInvalid_2"
48 | "validInvalid_3"
49 | "EOF1_returncontract_valid_0"
51 | "EOF1_returncontract_valid_1"
52 | "EOF1_returncontract_valid_2"
53 | "EOF1_eofcreate_valid_1"
54 | "EOF1_eofcreate_valid_2"
55 | "EOF1_section_order_6"
56 )
57}
58
59pub fn run_test(path: &Path) -> Result<(), Error> {
60 let test_files = find_all_json_tests(path);
61 let mut test_sum = 0;
62 let mut passed_tests = 0;
63
64 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
65 enum ErrorType {
66 FalsePositive,
67 Error(EofError),
68 }
69 let mut types_of_error: BTreeMap<ErrorType, usize> = BTreeMap::new();
70 for test_file in test_files {
71 let s = std::fs::read_to_string(test_file).unwrap();
72 let suite: TestSuite = serde_json::from_str(&s).unwrap();
73 for (name, test_unit) in suite.0 {
74 for (vector_name, test_vector) in test_unit.vectors {
75 if skip_test(&vector_name) {
76 continue;
77 }
78 test_sum += 1;
79 let kind = if test_vector.container_kind.is_some() {
80 Some(CodeType::ReturnContract)
81 } else {
82 Some(CodeType::ReturnOrStop)
83 };
84 let Some(test_result) = test_vector.results.get("Osaka") else {
86 println!("Test without result: {} - {}", name, vector_name);
88 continue;
89 };
90 let res = validate_raw_eof_inner(test_vector.code.clone(), kind);
91 if test_result.result != res.is_ok() {
92 println!(
93 "\nTest failed: {} - {}\nresult:{:?}\nrevm err_result:{:#?}\nExpected exception:{:?}\nbytes:{:?}\n",
94 name,
95 vector_name,
96 test_result.result,
97 res.as_ref().err(),
98 test_result.exception,
99 test_vector.code
100 );
101 *types_of_error
102 .entry(
103 res.err()
104 .map(ErrorType::Error)
105 .unwrap_or(ErrorType::FalsePositive),
106 )
107 .or_default() += 1;
108 } else {
109 passed_tests += 1;
110 }
111 }
112 }
113 }
114 println!("Passed tests: {}/{}", passed_tests, test_sum);
115 if passed_tests != test_sum {
116 println!("Types of error: {:#?}", types_of_error);
117 Err(Error::EofValidation {
118 failed_test: test_sum - passed_tests,
119 total_tests: test_sum,
120 })
121 } else {
122 Ok(())
123 }
124}