Skip to main content

ruda_test_utils/test_mode/
result.rs

1//! Kernel Test Workflow
2//!
3//! 1. **Execution**  
4//!    - Kernel runs or fails to compile [`ExecutionOutcome`].
5//!      - `Executed`: ran (correctness not checked).  
6//!      - `CompileError`: did not compile.
7//!
8//! 2. **Validation**  
9//!    - Check correctness of the executed kernel [`ValidationResult`].
10//!      - `Pass`: result matches reference.  
11//!      - `Fail`: result incorrect.  
12//!      - `Skipped`: could not decide.
13//!
14//! 3. **Test Outcome**  
15//!    - Combines execution + validation [`TestOutcome`].
16//!
17//! 4. **Policy Decision**  
18//!    - Applies test mode to decide if the test passes [`TestDecision`].
19//!      - `Accept`: test passes.  
20//!      - `Reject(String)`: test fails.  
21//!    - Call [`TestDecision::enforce`] to actually fail the test.
22
23use crate::test_mode::base::decide;
24use std::fmt::Display;
25
26#[derive(Debug)]
27/// Whether a kernel was executed (without regard to correctness)
28/// or failed to compile.
29pub enum ExecutionOutcome {
30    /// The kernel was executed successfully (correctness not checked)
31    Executed,
32    /// The kernel could not compile
33    CompileError(String),
34}
35
36#[derive(Debug)]
37/// The result of correctness validation for a kernel execution.
38pub enum ValidationResult {
39    /// The kernel passed the correctness test
40    Pass,
41    /// The kernel failed the correctness test
42    Fail(String),
43    /// The correctness test could not determine pass/fail
44    Error(String),
45    /// Validation was skipped. Useful to print stuff instead of actual testing
46    Skipped(String),
47}
48
49#[derive(Debug)]
50/// The overall outcome of a test, combining execution and validation.
51/// Either the kernel was validated or failed to compile.
52pub enum TestOutcome {
53    /// The kernel was executed and validation was performed
54    Validated(ValidationResult),
55    /// The kernel could not compile
56    CompileError(String),
57}
58
59impl TestOutcome {
60    /// Apply the current test mode to this outcome and fail the test if rejected.
61    ///
62    /// Convenience wrapper for `decide(self).enforce()` — applies the
63    /// active test policy (from `ruda-test.toml`) to this outcome and fails the
64    /// test if the decision is `Reject`.
65    ///
66    /// # Example
67    ///
68    /// ```ignore
69    /// let outcome = assert_equals_approx(&actual, &expected, 0.001).as_test_outcome();
70    /// outcome.enforce(); // panics if the active policy rejects it
71    /// ```
72    #[track_caller]
73    pub fn enforce(self) {
74        decide(self).enforce();
75    }
76}
77
78#[derive(Debug)]
79/// The final policy-based verdict of a test, after applying the test mode.
80/// Determines whether the test should be considered passing or failing.
81pub enum TestDecision {
82    /// The test is accepted (passes)
83    Accept,
84    /// The test is rejected (fails)
85    Reject(String),
86}
87
88impl TestDecision {
89    /// Actually asserts the test according to the decision.
90    /// Panics if the test is rejected.
91    #[track_caller]
92    pub fn enforce(self) {
93        match self {
94            TestDecision::Accept => {}
95            TestDecision::Reject(reason) => panic!("Test failed: {}", reason),
96        }
97    }
98}
99
100impl ValidationResult {
101    /// Convert a `ValidationResult` into a `TestOutcome`.
102    pub fn as_test_outcome(self) -> TestOutcome {
103        TestOutcome::Validated(self)
104    }
105}
106
107impl<E: Display> From<Result<(), E>> for ExecutionOutcome {
108    fn from(result: Result<(), E>) -> Self {
109        match result {
110            Ok(_) => ExecutionOutcome::Executed,
111            Err(err) => ExecutionOutcome::CompileError(format!("Test did not run: {}", err)),
112        }
113    }
114}