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}