pub mod simple_test;
pub use simple_test::*;
use super::*;
use std::time::{Duration, Instant};
pub struct TestConfig {
pub test_duration_ms: u64,
pub precision_tolerance_ns: u64,
pub performance_iterations: usize,
pub tsc_frequency_hz: u64,
pub enable_hardware_validation: bool,
}
impl Default for TestConfig {
fn default() -> Self {
Self {
test_duration_ms: 1000,
precision_tolerance_ns: 100, performance_iterations: 10000,
tsc_frequency_hz: Self::detect_tsc_frequency(),
enable_hardware_validation: true,
}
}
}
impl TestConfig {
pub fn detect_tsc_frequency() -> u64 {
3_000_000_000
}
pub fn high_precision() -> Self {
Self {
precision_tolerance_ns: 10,
performance_iterations: 100000,
..Default::default()
}
}
pub fn stress_test() -> Self {
Self {
test_duration_ms: 10000,
performance_iterations: 1000000,
..Default::default()
}
}
}
pub struct TestUtils;
impl TestUtils {
pub fn measure_execution_time<F, R>(f: F) -> (R, u64)
where
F: FnOnce() -> R,
{
let start = Instant::now();
let result = f();
let end = Instant::now();
let duration_ns = end.duration_since(start).as_nanos() as u64;
(result, duration_ns)
}
pub fn get_tsc_frequency() -> Result<u64, Box<dyn std::error::Error>> {
Ok(TestConfig::detect_tsc_frequency())
}
pub fn verify_precision(expected_ns: u64, actual_ns: u64, tolerance_ns: u64) -> bool {
let diff = if actual_ns > expected_ns {
actual_ns - expected_ns
} else {
expected_ns - actual_ns
};
diff <= tolerance_ns
}
pub fn generate_test_data(size: usize, pattern: TestDataPattern) -> Vec<u8> {
match pattern {
TestDataPattern::Sequential => (0..size).map(|i| (i % 256) as u8).collect(),
TestDataPattern::Random => {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut data = Vec::with_capacity(size);
for i in 0..size {
let mut hasher = DefaultHasher::new();
i.hash(&mut hasher);
data.push((hasher.finish() % 256) as u8);
}
data
},
TestDataPattern::Constant(value) => vec![value; size],
TestDataPattern::Alternating => (0..size).map(|i| if i % 2 == 0 { 0 } else { 255 }).collect(),
}
}
pub fn validate_convergence(values: &[f64], tolerance: f64) -> bool {
if values.len() < 2 {
return false;
}
let final_value = *values.last().unwrap();
let convergence_point = values.len() / 2;
for &value in &values[convergence_point..] {
if (value - final_value).abs() > tolerance {
return false;
}
}
true
}
pub fn calculate_lipschitz_constant(x_values: &[f64], y_values: &[f64]) -> f64 {
assert_eq!(x_values.len(), y_values.len());
let mut max_lipschitz = 0.0;
for i in 0..x_values.len() {
for j in i + 1..x_values.len() {
let dx = (x_values[j] - x_values[i]).abs();
let dy = (y_values[j] - y_values[i]).abs();
if dx > 1e-10 {
let lipschitz = dy / dx;
max_lipschitz = max_lipschitz.max(lipschitz);
}
}
}
max_lipschitz
}
pub fn verify_memory_usage<F>(f: F, max_memory_mb: f64) -> bool
where
F: FnOnce(),
{
let initial_memory = Self::get_memory_usage_mb();
f();
let final_memory = Self::get_memory_usage_mb();
(final_memory - initial_memory) <= max_memory_mb
}
fn get_memory_usage_mb() -> f64 {
50.0 }
}
#[derive(Debug, Clone, Copy)]
pub enum TestDataPattern {
Sequential,
Random,
Constant(u8),
Alternating,
}
#[derive(Debug, Clone, Default)]
pub struct PerformanceMetrics {
pub min_execution_time_ns: u64,
pub max_execution_time_ns: u64,
pub avg_execution_time_ns: f64,
pub median_execution_time_ns: u64,
pub std_deviation_ns: f64,
pub operations_per_second: f64,
pub memory_usage_mb: f64,
pub cpu_utilization_percent: f64,
}
impl PerformanceMetrics {
pub fn from_samples(samples: &[u64]) -> Self {
if samples.is_empty() {
return Self::default();
}
let mut sorted_samples = samples.to_vec();
sorted_samples.sort_unstable();
let min = sorted_samples[0];
let max = sorted_samples[sorted_samples.len() - 1];
let sum: u64 = sorted_samples.iter().sum();
let avg = sum as f64 / sorted_samples.len() as f64;
let median = sorted_samples[sorted_samples.len() / 2];
let variance = sorted_samples.iter()
.map(|&x| (x as f64 - avg).powi(2))
.sum::<f64>() / sorted_samples.len() as f64;
let std_dev = variance.sqrt();
let ops_per_sec = if avg > 0.0 {
1_000_000_000.0 / avg
} else {
0.0
};
Self {
min_execution_time_ns: min,
max_execution_time_ns: max,
avg_execution_time_ns: avg,
median_execution_time_ns: median,
std_deviation_ns: std_dev,
operations_per_second: ops_per_sec,
memory_usage_mb: 0.0, cpu_utilization_percent: 0.0, }
}
pub fn meets_requirements(&self, max_avg_time_ns: u64, min_ops_per_sec: f64) -> bool {
self.avg_execution_time_ns <= max_avg_time_ns as f64 &&
self.operations_per_second >= min_ops_per_sec
}
}
pub struct TestReport {
pub test_name: String,
pub total_tests: usize,
pub passed_tests: usize,
pub failed_tests: usize,
pub duration_ms: u64,
pub performance_metrics: PerformanceMetrics,
pub hardware_info: HardwareInfo,
pub test_results: Vec<TestResult>,
}
#[derive(Debug, Clone)]
pub struct TestResult {
pub name: String,
pub passed: bool,
pub duration_ns: u64,
pub error_message: Option<String>,
pub metrics: Option<PerformanceMetrics>,
}
#[derive(Debug, Clone)]
pub struct HardwareInfo {
pub tsc_frequency_hz: u64,
pub cpu_model: String,
pub memory_mb: u64,
pub core_count: usize,
}
impl HardwareInfo {
pub fn detect() -> Self {
Self {
tsc_frequency_hz: TestConfig::detect_tsc_frequency(),
cpu_model: Self::get_cpu_model(),
memory_mb: Self::get_memory_mb(),
core_count: num_cpus::get(),
}
}
fn get_cpu_model() -> String {
std::env::var("PROCESSOR_IDENTIFIER")
.or_else(|_| std::env::var("CPU_BRAND"))
.unwrap_or_else(|_| "Unknown CPU".to_string())
}
fn get_memory_mb() -> u64 {
8192 }
}
#[derive(Debug, Clone)]
pub struct TestReport {
pub total_tests: usize,
pub passed_tests: usize,
pub failed_tests: usize,
pub performance_metrics: Option<PerformanceMetrics>,
pub test_results: std::collections::HashMap<String, TestCategoryResult>,
}
#[derive(Debug, Clone)]
pub struct TestCategoryResult {
pub success: bool,
pub duration_ms: f64,
pub assertions_count: usize,
pub failure_details: String,
}
impl TestReport {
pub fn new() -> Self {
Self {
total_tests: 0,
passed_tests: 0,
failed_tests: 0,
performance_metrics: None,
test_results: std::collections::HashMap::new(),
}
}
pub fn add_result(&mut self, result: TestResult) {
if result.passed {
self.passed_tests += 1;
} else {
self.failed_tests += 1;
}
self.total_tests += 1;
self.test_results.push(result);
}
pub fn success_rate(&self) -> f64 {
if self.total_tests > 0 {
self.passed_tests as f64 / self.total_tests as f64
} else {
0.0
}
}
pub fn generate_summary(&self) -> String {
format!(
"Test Report: {}\n\
Total Tests: {}\n\
Passed: {} ({:.1}%)\n\
Failed: {} ({:.1}%)\n\
Duration: {}ms\n\
Hardware: {} @ {:.2}GHz\n\
Performance: {:.0} ops/sec (avg: {:.0}ns)\n",
self.test_name,
self.total_tests,
self.passed_tests,
self.success_rate() * 100.0,
self.failed_tests,
(100.0 - self.success_rate() * 100.0),
self.duration_ms,
self.hardware_info.cpu_model,
self.hardware_info.tsc_frequency_hz as f64 / 1e9,
self.performance_metrics.operations_per_second,
self.performance_metrics.avg_execution_time_ns
)
}
}
pub use crate::temporal_nexus::core::*;
extern crate num_cpus;