cubek_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::current_test_mode;
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 Skipped(String),
45}
46
47#[derive(Debug)]
48/// The overall outcome of a test, combining execution and validation.
49/// Either the kernel was validated or failed to compile.
50pub enum TestOutcome {
51 /// The kernel was executed and validation was performed
52 Validated(ValidationResult),
53 /// The kernel could not compile
54 CompileError(String),
55}
56
57impl TestOutcome {
58 /// Apply the current test mode to this outcome and fail the test if rejected.
59 ///
60 /// This is a convenience wrapper around
61 /// `current_test_mode().decide(self).enforce()`.
62 ///
63 /// # Example
64 ///
65 /// ```ignore
66 /// let outcome = assert_equals_approx(&actual, &expected, 0.001).as_test_outcome();
67 /// outcome.enforce(); // panics if TestMode rejects it
68 /// ```
69 pub fn enforce(self) {
70 current_test_mode().decide(self).enforce();
71 }
72}
73
74#[derive(Debug)]
75/// The final policy-based verdict of a test, after applying the test mode.
76/// Determines whether the test should be considered passing or failing.
77pub enum TestDecision {
78 /// The test is accepted (passes)
79 Accept,
80 /// The test is rejected (fails)
81 Reject(String),
82}
83
84impl TestDecision {
85 /// Actually asserts the test according to the decision.
86 /// Panics if the test is rejected.
87 pub fn enforce(self) {
88 match self {
89 TestDecision::Accept => {}
90 TestDecision::Reject(reason) => panic!("Test failed: {}", reason),
91 }
92 }
93}
94
95impl ValidationResult {
96 /// Convert a `ValidationResult` into a `TestOutcome`.
97 pub fn as_test_outcome(self) -> TestOutcome {
98 TestOutcome::Validated(self)
99 }
100}
101
102impl<E: Display> From<Result<(), E>> for ExecutionOutcome {
103 fn from(result: Result<(), E>) -> Self {
104 match result {
105 Ok(_) => ExecutionOutcome::Executed,
106 Err(err) => ExecutionOutcome::CompileError(format!("Test did not run: {}", err)),
107 }
108 }
109}