Skip to main content

huff_neo_test_runner/
types.rs

1use crate::internal::HuffFunction;
2use crate::outcome::{Failure, Outcome};
3use alloy_primitives::Log;
4use clap::ValueEnum;
5use comfy_table::{Cell, Color};
6use foundry_evm::traces::SparsedTraceArena;
7use huff_neo_utils::artifact::SourceMapEntry;
8use serde::Serialize;
9use yansi::Paint;
10
11/// A test result
12#[derive(Debug, Clone, Serialize)]
13pub struct TestResult {
14    pub name: String,
15    pub return_data: Option<String>,
16    pub gas: u64,
17    pub status: TestStatus,
18    pub revert_reason: Option<String>,
19    /// Whether the test ran and met every expectation; the same as `status` being `Success`
20    pub passed: bool,
21    /// How the test call ended
22    pub outcome: Outcome,
23    /// The expectations the test did not meet
24    pub failures: Vec<Failure>,
25    /// The call traces of the test, as far as the runner records them
26    #[serde(skip)]
27    pub traces: Option<SparsedTraceArena>,
28    /// The logs the test emitted, when the runner collects them
29    #[serde(skip)]
30    pub logs: Option<Vec<Log>>,
31    /// The Huff functions of the test, which traces show as internal calls
32    #[serde(skip)]
33    pub functions: Vec<HuffFunction>,
34    /// Source map for the test bytecode (for debugging)
35    #[serde(skip)]
36    pub source_map: Option<Vec<SourceMapEntry>>,
37    /// Deployed contract address
38    #[serde(skip)]
39    pub address: Option<alloy_primitives::Address>,
40    /// Source code for debugging
41    #[serde(skip)]
42    pub source_code: Option<String>,
43    /// Bytecode for debugging
44    #[serde(skip)]
45    pub bytecode: Option<String>,
46    /// Multiple source files for multi-file debugging
47    /// Vec of (file_path, source_content)
48    #[serde(skip)]
49    pub source_files: Vec<(String, String)>,
50}
51
52/// A test status variant
53#[derive(Debug, Clone, PartialEq, Serialize)]
54pub enum TestStatus {
55    Success,
56    Revert,
57    Skipped,
58}
59
60/// The format of the test report
61#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum)]
62pub enum ReportKind {
63    /// Each test with its failures, logs and traces
64    #[default]
65    List,
66    /// A table of the tests and their gas
67    Table,
68    /// Machine-readable JSON
69    Json,
70}
71
72impl TestStatus {
73    /// The status of a test that met, or did not meet, every expectation
74    fn from_passed(passed: bool) -> Self {
75        if passed { Self::Success } else { Self::Revert }
76    }
77
78    /// The status of a test that ended this way and met, or did not meet, every expectation
79    pub fn from_outcome(outcome: &Outcome, passed: bool) -> Self {
80        if matches!(outcome, Outcome::Skip { .. }) { Self::Skipped } else { Self::from_passed(passed) }
81    }
82}
83
84/// Convert a TestStatus variant directly to a colored string for use in the report
85impl From<TestStatus> for String {
86    fn from(status: TestStatus) -> Self {
87        match status {
88            TestStatus::Success => Paint::green("PASS").to_string(),
89            TestStatus::Revert => Paint::red("FAIL").to_string(),
90            TestStatus::Skipped => Paint::yellow("SKIP").to_string(),
91        }
92    }
93}
94
95/// Convert a TestStatus variant directly to a table cell for use in the report
96impl From<TestStatus> for Cell {
97    fn from(status: TestStatus) -> Self {
98        match status {
99            TestStatus::Success => Cell::new("PASS").fg(Color::Green),
100            TestStatus::Revert => Cell::new("FAIL").fg(Color::Red),
101            TestStatus::Skipped => Cell::new("SKIP").fg(Color::Yellow),
102        }
103    }
104}