#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::needless_raw_string_hashes,
clippy::duration_suboptimal_units,
clippy::branches_sharing_code,
clippy::used_underscore_binding,
clippy::single_char_pattern,
clippy::ignore_without_reason,
clippy::cloned_ref_to_slice_refs,
clippy::doc_overindented_list_items,
clippy::match_wildcard_for_single_variants,
clippy::ignored_unit_patterns,
clippy::needless_collect,
clippy::unnecessary_map_or,
clippy::manual_flatten,
clippy::manual_strip,
clippy::future_not_send
)]
use sha2::{Digest, Sha256};
use std::fmt::Debug;
use std::sync::Arc;
use std::time::{Duration, Instant};
pub trait Deterministic: Send + Sync + Debug {
fn generate_output(&self) -> Vec<u8>;
fn output_hash(&self) -> String {
let output = self.generate_output();
let mut hasher = Sha256::new();
hasher.update(&output);
format!("{:x}", hasher.finalize())
}
fn validate_determinism(&self, iterations: usize) -> DeterminismResult {
let hashes: Vec<_> = (0..iterations).map(|_| self.output_hash()).collect();
let first_hash = &hashes[0];
let all_identical = hashes.iter().all(|h| h == first_hash);
let variance = if all_identical {
0.0
} else {
let different_count = hashes.iter().filter(|h| **h != **first_hash).count();
different_count as f32 / iterations as f32
};
DeterminismResult {
all_identical,
consistency_score: 1.0 - variance,
iterations,
variance,
sample_hash: first_hash.clone(),
}
}
}
#[async_trait::async_trait]
pub trait AsyncDeterministic: Send + Sync + Debug {
async fn generate_output_async(&self) -> Vec<u8>;
async fn validate_async_determinism(&self, iterations: usize) -> DeterminismResult {
let futures: Vec<_> = (0..iterations)
.map(|_| self.generate_output_async())
.collect();
let outputs = futures::future::join_all(futures).await;
let hashes: Vec<_> = outputs
.iter()
.map(|out| {
let mut hasher = Sha256::new();
hasher.update(out);
format!("{:x}", hasher.finalize())
})
.collect();
let first_hash = &hashes[0];
let all_identical = hashes.iter().all(|h| h == first_hash);
let variance = if all_identical {
0.0
} else {
hashes.iter().filter(|h| **h != **first_hash).count() as f32 / iterations as f32
};
DeterminismResult {
all_identical,
consistency_score: 1.0 - variance,
iterations,
variance,
sample_hash: first_hash.clone(),
}
}
}
pub trait FormatValidator: Send + Sync {
fn format_name(&self) -> &'static str;
fn validate(&self, data: &[u8]) -> Result<(), String>;
fn transform(&self, input: &[u8]) -> Vec<u8>;
}
pub struct MultiFormatValidator {
validators: Vec<Arc<dyn FormatValidator>>,
}
impl MultiFormatValidator {
pub fn new(validators: Vec<Arc<dyn FormatValidator>>) -> Self {
Self { validators }
}
pub fn validate_equivalence(&self, base_output: &[u8]) -> EquivalenceResult {
let results: Vec<_> = self
.validators
.iter()
.map(|v| {
let transformed = v.transform(base_output);
EquivalenceCheck {
format: v.format_name(),
valid: v.validate(&transformed).is_ok(),
hash: compute_hash(&transformed),
}
})
.collect();
let all_valid = results.iter().all(|r| r.valid);
EquivalenceResult {
all_valid,
results,
consistency_score: if all_valid { 100.0 } else { 0.0 },
}
}
}
pub struct ParallelTestExecutor {
max_concurrent: usize,
timeout: Duration,
}
impl ParallelTestExecutor {
pub fn new(max_concurrent: usize, timeout: Duration) -> Self {
Self {
max_concurrent,
timeout,
}
}
pub async fn execute<F, T>(&self, tests: Vec<(&str, F)>) -> Vec<TestExecutionResult>
where
F: Fn() -> T + Send + 'static,
T: Send + 'static,
{
let semaphore = Arc::new(tokio::sync::Semaphore::new(self.max_concurrent));
let futures: Vec<_> = tests
.into_iter()
.map(|(name, test_fn)| {
let sem = semaphore.clone();
async move {
let _permit = sem.acquire().await.unwrap();
let start = Instant::now();
let result = tokio::time::timeout(self.timeout, async {
test_fn();
"passed"
})
.await;
let duration = start.elapsed();
TestExecutionResult {
test_name: name.to_string(),
passed: result.is_ok(),
duration,
error: result.err().map(|_| "timeout".to_string()),
}
}
})
.collect();
futures::future::join_all(futures).await
}
}
pub struct RegressionDetector {
history: Vec<BenchmarkSnapshot>,
threshold: f32,
}
impl RegressionDetector {
pub fn new(threshold: f32) -> Self {
Self {
history: Vec::new(),
threshold,
}
}
pub fn record(&mut self, snapshot: BenchmarkSnapshot) {
self.history.push(snapshot);
}
pub fn detect_regressions(&self) -> Vec<RegressionAlert> {
let mut alerts = Vec::new();
if self.history.len() < 2 {
return alerts;
}
let current = &self.history[self.history.len() - 1];
let previous = &self.history[self.history.len() - 2];
let consistency_delta = (previous.consistency_score - current.consistency_score).abs();
if consistency_delta > self.threshold {
alerts.push(RegressionAlert {
metric: "consistency_score".to_string(),
previous: previous.consistency_score,
current: current.consistency_score,
delta: consistency_delta,
});
}
let performance_delta = (current.duration.as_secs_f64() - previous.duration.as_secs_f64())
/ previous.duration.as_secs_f64();
if performance_delta > self.threshold as f64 {
alerts.push(RegressionAlert {
metric: "performance".to_string(),
previous: previous.duration.as_secs_f64() as f32,
current: current.duration.as_secs_f64() as f32,
delta: performance_delta as f32,
});
}
alerts
}
}
#[derive(Debug, Clone)]
pub struct DeterminismResult {
pub all_identical: bool,
pub consistency_score: f32,
pub iterations: usize,
pub variance: f32,
pub sample_hash: String,
}
#[derive(Debug, Clone)]
pub struct EquivalenceCheck {
pub format: &'static str,
pub valid: bool,
pub hash: String,
}
#[derive(Debug, Clone)]
pub struct EquivalenceResult {
pub all_valid: bool,
pub results: Vec<EquivalenceCheck>,
pub consistency_score: f32,
}
#[derive(Debug, Clone)]
pub struct TestExecutionResult {
pub test_name: String,
pub passed: bool,
pub duration: Duration,
pub error: Option<String>,
}
#[derive(Debug, Clone)]
pub struct BenchmarkSnapshot {
pub timestamp: Instant,
pub consistency_score: f32,
pub duration: Duration,
pub test_count: usize,
}
#[derive(Debug, Clone)]
pub struct RegressionAlert {
pub metric: String,
pub previous: f32,
pub current: f32,
pub delta: f32,
}
pub fn compute_hash(data: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(data);
format!("{:x}", hasher.finalize())
}
#[macro_export]
macro_rules! determinism_test {
($test_name:ident, $test_fn:expr) => {
#[test]
fn $test_name() {
let test = $test_fn;
let result = test.validate_determinism(5);
assert!(
result.all_identical,
"Test failed determinism check. Consistency: {:.2}%",
result.consistency_score * 100.0
);
}
};
}
#[macro_export]
macro_rules! async_determinism_test {
($test_name:ident, $test_fn:expr) => {
#[tokio::test]
async fn $test_name() {
let test = $test_fn;
let result = test.validate_async_determinism(5).await;
assert!(
result.all_identical,
"Async test failed determinism check. Consistency: {:.2}%",
result.consistency_score * 100.0
);
}
};
}
#[macro_export]
macro_rules! format_equivalence_test {
($test_name:ident, $validators:expr, $output:expr) => {
#[test]
fn $test_name() {
let multi_validator = MultiFormatValidator::new($validators);
let result = multi_validator.validate_equivalence($output);
assert!(
result.all_valid,
"Format equivalence test failed for {}",
stringify!($test_name)
);
}
};
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug)]
struct SimpleTest;
impl Deterministic for SimpleTest {
fn generate_output(&self) -> Vec<u8> {
vec![1, 2, 3, 4, 5]
}
}
#[test]
fn test_determinism_validator_passes() {
let test = SimpleTest;
let result = test.validate_determinism(3);
assert!(result.all_identical);
assert_eq!(result.consistency_score, 1.0);
}
#[test]
fn test_hash_computation() {
let data = b"test data";
let hash1 = compute_hash(data);
let hash2 = compute_hash(data);
assert_eq!(hash1, hash2);
}
}