use core::fmt::{Display, Formatter};
use crate::testing::export::ScenarioResultExport;
use crate::testing::macros::BuiltAssertSpec;
use crate::testing::specs::SpecViolation;
use crate::trace::ConsumedTrace;
#[cfg(feature = "testing-fdr")]
use crate::testing::fdr::FdrVerdict;
#[cfg(feature = "testing-schedulability")]
use crate::testing::schedulability::{SchedulabilityResult, TaskSet};
#[cfg(feature = "testing-csp")]
use crate::testing::specs::csp::{CspValidationResult, Process};
#[cfg(feature = "testing-timing")]
use crate::testing::timing::{TimingConstraints, TimingVerificationResult};
#[derive(Debug)]
pub struct ScenarioResult {
pub trace: ConsumedTrace,
pub assert_spec: Option<BuiltAssertSpec>,
pub assert_specs: Vec<BuiltAssertSpec>,
pub spec_violation: Option<SpecViolation>,
#[cfg(feature = "testing-csp")]
pub csp_result: Option<CspValidationResult>,
#[cfg(feature = "testing-csp")]
pub process: Option<Process>,
#[cfg(feature = "testing-fdr")]
pub fdr_verdict: Option<FdrVerdict>,
#[cfg(feature = "testing-timing")]
pub timing_result: Option<TimingVerificationResult>,
#[cfg(feature = "testing-timing")]
pub timing_constraints: Option<TimingConstraints>,
#[cfg(feature = "testing-schedulability")]
pub task_set: Option<TaskSet>,
#[cfg(feature = "testing-schedulability")]
pub schedulability_result: Option<SchedulabilityResult>,
pub passed: bool,
}
impl ScenarioResult {
pub fn from_spec_result(result: Result<(), SpecViolation>) -> Self {
let (spec_violation, passed) = match result {
Ok(()) => (None, true),
Err(violation) => (Some(violation), false),
};
Self {
trace: ConsumedTrace::new(),
assert_spec: None,
assert_specs: Vec::new(),
spec_violation,
#[cfg(feature = "testing-csp")]
csp_result: None,
#[cfg(feature = "testing-csp")]
process: None,
#[cfg(feature = "testing-fdr")]
fdr_verdict: None,
#[cfg(feature = "testing-timing")]
timing_result: None,
#[cfg(feature = "testing-timing")]
timing_constraints: None,
#[cfg(feature = "testing-schedulability")]
task_set: None,
#[cfg(feature = "testing-schedulability")]
schedulability_result: None,
passed,
}
}
pub fn all_passed(&self) -> bool {
self.passed
}
pub fn has_failures(&self) -> bool {
!self.passed
}
}
impl Default for ScenarioResult {
fn default() -> Self {
Self {
trace: ConsumedTrace::new(),
assert_spec: None,
assert_specs: Vec::new(),
spec_violation: None,
#[cfg(feature = "testing-csp")]
csp_result: None,
#[cfg(feature = "testing-csp")]
process: None,
#[cfg(feature = "testing-fdr")]
fdr_verdict: None,
#[cfg(feature = "testing-timing")]
timing_result: None,
#[cfg(feature = "testing-timing")]
timing_constraints: None,
#[cfg(feature = "testing-schedulability")]
task_set: None,
#[cfg(feature = "testing-schedulability")]
schedulability_result: None,
passed: true,
}
}
}
impl Display for ScenarioResult {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
if self.passed {
write!(f, "Verification passed")
} else {
writeln!(f, "Verification failed:")?;
if let Some(ref violation) = self.spec_violation {
writeln!(f, " [Assertion] {violation}")?;
}
#[cfg(feature = "testing-csp")]
if let Some(ref csp_res) = self.csp_result {
if !csp_res.valid {
writeln!(f, " [CSP] Validation failed:")?;
for violation in &csp_res.violations {
writeln!(f, " - {violation}")?;
}
}
}
#[cfg(feature = "testing-fdr")]
if let Some(ref fdr_verdict) = self.fdr_verdict {
if !fdr_verdict.passed {
writeln!(f, " [FDR] Refinement check failed")?;
}
}
#[cfg(feature = "testing-timing")]
if let Some(ref timing_res) = self.timing_result {
if !timing_res.passed {
writeln!(f, " [Timing] Verification failed")?;
}
}
#[cfg(feature = "testing-schedulability")]
if let Some(ref schedule_res) = self.schedulability_result {
if !schedule_res.is_schedulable {
writeln!(
f,
" [Schedulability] Analysis failed: utilization {:.2}% (bound {:.2}%)",
schedule_res.utilization * 100.0,
schedule_res.utilization_bound * 100.0
)?;
}
}
Ok(())
}
}
}
impl ScenarioResultExport for ScenarioResult {}