pub use tacet_core::preflight::{
autocorrelation_check, compute_acf, resolution_check, run_core_checks, sanity_check,
AutocorrWarning, PreflightResult as CorePreflightResult,
PreflightWarnings as CorePreflightWarnings, ResolutionWarning, SanityWarning,
};
mod resolution;
mod system;
pub use resolution::timer_sanity_check;
pub use system::{system_check, SystemWarning};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PreflightResult {
pub warnings: PreflightWarnings,
pub has_critical: bool,
pub is_valid: bool,
}
impl PreflightResult {
pub fn new() -> Self {
Self {
warnings: PreflightWarnings::default(),
has_critical: false,
is_valid: true,
}
}
pub fn from_core(core: CorePreflightResult) -> Self {
Self {
warnings: PreflightWarnings::from_core(core.warnings),
has_critical: core.has_critical,
is_valid: core.is_valid,
}
}
pub fn add_sanity_warning(&mut self, warning: SanityWarning) {
if warning.is_result_undermining() {
self.has_critical = true;
self.is_valid = false;
}
self.warnings.sanity.push(warning);
}
pub fn add_autocorr_warning(&mut self, warning: AutocorrWarning) {
self.warnings.autocorr.push(warning);
}
pub fn add_system_warning(&mut self, warning: SystemWarning) {
self.warnings.system.push(warning);
}
pub fn add_resolution_warning(&mut self, warning: ResolutionWarning) {
if warning.is_result_undermining() {
self.has_critical = true;
self.is_valid = false;
}
self.warnings.resolution.push(warning);
}
pub fn has_warnings(&self) -> bool {
!self.warnings.sanity.is_empty()
|| !self.warnings.autocorr.is_empty()
|| !self.warnings.system.is_empty()
|| !self.warnings.resolution.is_empty()
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PreflightWarnings {
pub sanity: Vec<SanityWarning>,
pub autocorr: Vec<AutocorrWarning>,
pub system: Vec<SystemWarning>,
pub resolution: Vec<ResolutionWarning>,
}
impl PreflightWarnings {
pub fn new() -> Self {
Self::default()
}
pub fn from_core(core: CorePreflightWarnings) -> Self {
Self {
sanity: core.sanity,
autocorr: core.autocorr,
system: Vec::new(),
resolution: core.resolution,
}
}
pub fn count(&self) -> usize {
self.sanity.len() + self.autocorr.len() + self.system.len() + self.resolution.len()
}
pub fn is_empty(&self) -> bool {
self.count() == 0
}
}
pub fn run_all_checks(
fixed_samples: &[f64],
random_samples: &[f64],
timer_resolution_ns: f64,
seed: u64,
) -> PreflightResult {
let core_result = run_core_checks(fixed_samples, random_samples, timer_resolution_ns, seed);
let mut result = PreflightResult::from_core(core_result);
for warning in system_check() {
result.add_system_warning(warning);
}
result
}
pub fn run_timer_sanity_check(timer: &crate::measurement::BoxedTimer) -> PreflightResult {
let mut result = PreflightResult::new();
if let Some(warning) = timer_sanity_check(timer) {
result.add_resolution_warning(warning.to_resolution_warning());
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_preflight_result_default() {
let result = PreflightResult::new();
assert!(result.is_valid);
assert!(!result.has_critical);
assert!(!result.has_warnings());
}
#[test]
fn test_warnings_count() {
let mut warnings = PreflightWarnings::new();
assert_eq!(warnings.count(), 0);
assert!(warnings.is_empty());
warnings.sanity.push(SanityWarning::BrokenHarness {
variance_ratio: 7.5,
});
assert_eq!(warnings.count(), 1);
assert!(!warnings.is_empty());
}
#[test]
fn test_from_core() {
let mut core = CorePreflightResult::new();
core.has_critical = true;
core.is_valid = false;
let result = PreflightResult::from_core(core);
assert!(result.has_critical);
assert!(!result.is_valid);
}
}