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 = match test_vector.container_kind.as_deref() {
80 Some("RUNTIME") => CodeType::Runtime,
81 Some("INITCODE") => CodeType::Initcode,
82 None => CodeType::Runtime,
83 _ => return Err(Error::Custom("Invalid container kind")),
84 };
85 let Some(test_result) = test_vector.results.get("Osaka") else {
87 println!("Test without result: {} - {}", name, vector_name);
89 continue;
90 };
91 let res = validate_raw_eof_inner(test_vector.code.clone(), Some(kind));
92 if test_result.result != res.is_ok() {
93 println!(
94 "\nTest failed: {} - {}\nPath:{:?}\nresult:{:?}\nrevm err_result:{:#?}\nExpected exception:{:?}\nbytes:{:?}\n",
95 name,
96 vector_name,
97 test_file,
98 test_result.result,
99 res.as_ref().err(),
100 test_result.exception,
101 test_vector.code
102 );
103 *types_of_error
104 .entry(
105 res.err()
106 .map(ErrorType::Error)
107 .unwrap_or(ErrorType::FalsePositive),
108 )
109 .or_default() += 1;
110 } else {
111 passed_tests += 1;
112 }
113 }
114 }
115 }
116 println!("Passed tests: {}/{}", passed_tests, test_sum);
117 if passed_tests != test_sum {
118 println!("Types of error: {:#?}", types_of_error);
119 Err(Error::EofValidation {
120 failed_test: test_sum - passed_tests,
121 total_tests: test_sum,
122 })
123 } else {
124 Ok(())
125 }
126}