revm_ee_tests/lib.rs
1//! Common test utilities for REVM crates.
2//!
3//! This crate provides shared test utilities that are used across different REVM crates.
4
5use std::path::PathBuf;
6
7use serde_json::Value;
8
9/// Configuration for the test data comparison utility.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct TestdataConfig {
12 /// The directory where test data files are stored.
13 pub testdata_dir: PathBuf,
14}
15
16impl Default for TestdataConfig {
17 fn default() -> Self {
18 Self {
19 testdata_dir: PathBuf::from("tests/testdata"),
20 }
21 }
22}
23
24/// Compares or saves the execution output to a testdata file.
25///
26/// This utility helps maintain consistent test behavior by comparing
27/// execution results against known-good outputs stored in JSON files.
28///
29/// # Arguments
30///
31/// * `filename` - The name of the testdata file, relative to tests/testdata/
32/// * `output` - The execution output to compare or save
33///
34/// # Panics
35///
36/// This function panics if:
37/// - The output doesn't match the expected testdata (when testdata file exists)
38/// - There's an error reading/writing files
39/// - JSON serialization/deserialization fails
40///
41/// # Note
42///
43/// Tests using this function require the `serde` feature to be enabled:
44/// ```bash
45/// cargo test --features serde
46/// ```
47pub fn compare_or_save_testdata<T>(filename: &str, output: &T)
48where
49 T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug,
50{
51 compare_or_save_testdata_with_config(filename, output, TestdataConfig::default());
52}
53
54/// Compares or saves the execution output to a testdata file with custom configuration.
55///
56/// This is a more flexible version of [`compare_or_save_testdata`] that allows
57/// specifying a custom testdata directory.
58///
59/// # Arguments
60///
61/// * `filename` - The name of the testdata file, relative to the testdata directory
62/// * `output` - The execution output to compare or save
63/// * `config` - Configuration for the test data comparison
64pub fn compare_or_save_testdata_with_config<T>(filename: &str, output: &T, config: TestdataConfig)
65where
66 T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug,
67{
68 use std::fs;
69
70 let testdata_file = config.testdata_dir.join(filename);
71
72 // Create directory if it doesn't exist
73 if !config.testdata_dir.exists() {
74 fs::create_dir_all(&config.testdata_dir).unwrap();
75 }
76
77 // Serialize the output to serde Value.
78 let output_json = serde_json::to_string(&output).unwrap();
79
80 // convert to Value and sort all objects.
81 let mut temp: Value = serde_json::from_str(&output_json).unwrap();
82 temp.sort_all_objects();
83
84 // serialize to pretty string
85 let output_json = serde_json::to_string_pretty(&temp).unwrap();
86
87 // If the testdata file doesn't exist, save the output
88 if !testdata_file.exists() {
89 fs::write(&testdata_file, &output_json).unwrap();
90 println!("Saved testdata to {}", testdata_file.display());
91 return;
92 }
93
94 // Read the expected output from the testdata file
95 let expected_json = fs::read_to_string(&testdata_file).unwrap();
96
97 // Deserialize to actual object for proper comparison
98 let expected: T = serde_json::from_str(&expected_json).unwrap();
99
100 // Compare the output objects directly
101 if *output != expected {
102 similar_asserts::assert_eq!(
103 *output,
104 expected,
105 "value does not match testdata {testdata_file:?}"
106 );
107 similar_asserts::assert_eq!(
108 output_json,
109 expected_json,
110 "value does not match testdata {testdata_file:?}"
111 );
112 panic!("output != expected @ {testdata_file:?}");
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
121 struct TestData {
122 value: u32,
123 message: String,
124 }
125
126 #[test]
127 fn test_compare_or_save_testdata() {
128 let test_data = TestData {
129 value: 42,
130 message: "test message".to_string(),
131 };
132
133 // This will save the test data on first run, then compare on subsequent runs
134 compare_or_save_testdata("test_data.json", &test_data);
135 }
136}
137
138#[cfg(test)]
139mod revm_tests;
140
141#[cfg(test)]
142mod eip8037;