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