use serde::Serialize;
use crate::test_timing::DurationSummary;
#[derive(Clone, Debug, Serialize)]
pub struct TestResult {
pub name: String,
pub file: String,
pub passed: bool,
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub captured_output: Option<String>,
pub timeout: Option<TestTimeout>,
pub duration_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub phases: Option<PhaseTimings>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
pub struct TestTimeout {
pub phase: TestPhase,
pub limit_ms: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum TestPhase {
Execute,
}
#[derive(Clone, Debug, Serialize)]
pub struct TestSummary {
pub results: Vec<TestResult>,
pub passed: usize,
pub failed: usize,
pub total: usize,
pub duration_ms: u64,
pub timing: DurationSummary,
pub aggregate: AggregateTimings,
}
#[derive(Debug, Default, Clone, Copy, Serialize)]
pub struct PhaseTimings {
pub setup_ms: u64,
pub compile_ms: u64,
pub execute_ms: u64,
pub teardown_ms: u64,
pub modules: harn_vm::ModulePhaseStats,
}
#[derive(Debug, Default, Clone, Copy, Serialize)]
pub struct AggregateTimings {
pub collection_ms: u64,
pub setup_ms: u64,
pub compile_ms: u64,
pub execute_ms: u64,
pub teardown_ms: u64,
pub modules: harn_vm::ModulePhaseStats,
}
impl AggregateTimings {
pub(super) fn from_results(collection_ms: u64, results: &[TestResult]) -> Self {
results.iter().filter_map(|result| result.phases).fold(
Self {
collection_ms,
..Self::default()
},
|acc, phases| Self {
collection_ms: acc.collection_ms,
setup_ms: acc.setup_ms.saturating_add(phases.setup_ms),
compile_ms: acc.compile_ms.saturating_add(phases.compile_ms),
execute_ms: acc.execute_ms.saturating_add(phases.execute_ms),
teardown_ms: acc.teardown_ms.saturating_add(phases.teardown_ms),
modules: acc.modules.saturating_add(phases.modules),
},
)
}
}
impl TestResult {
pub(super) fn emit_diagnose(&self) {
let outcome = if self.passed { "ok" } else { "FAIL" };
let phases = self
.phases
.expect("diagnostics are emitted only for executed cases");
eprintln!(
"[harn test diag] {} {} setup={}ms compile={}ms execute={}ms teardown={}ms module_compile={}ms module_load={}ms modules_compiled={} modules_loaded={} total={}ms",
outcome,
self.name,
phases.setup_ms,
phases.compile_ms,
phases.execute_ms,
phases.teardown_ms,
phases.modules.module_compile_ms,
phases.modules.module_load_ms,
phases.modules.modules_compiled,
phases.modules.modules_loaded,
self.duration_ms,
);
}
}