use crate::side_channel::{SideChannelConfig, SideChannelContext};
use std::sync::{Arc, Mutex};
#[test]
fn test_countermeasure_stats_isolation() {
let config1 = SideChannelConfig::default();
let mut context1 = SideChannelContext::new(config1);
let initial_stats = context1.get_stats();
assert_eq!(initial_stats.timing_protections, 0);
assert_eq!(initial_stats.masking_operations, 0);
assert_eq!(initial_stats.error_detection_triggers, 0);
assert_eq!(initial_stats.cache_flush_operations, 0);
context1.increment_timing_protections();
context1.increment_timing_protections();
context1.increment_masking_operations();
let after_ops_stats = context1.get_stats();
assert_eq!(after_ops_stats.timing_protections, 2);
assert_eq!(after_ops_stats.masking_operations, 1);
let config2 = SideChannelConfig::default();
let context2 = SideChannelContext::new(config2);
let new_context_stats = context2.get_stats();
assert_eq!(new_context_stats.timing_protections, 0);
assert_eq!(new_context_stats.masking_operations, 0);
let context1_final_stats = context1.get_stats();
assert_eq!(context1_final_stats.timing_protections, 2);
assert_eq!(context1_final_stats.masking_operations, 1);
}
#[test]
fn test_countermeasure_stats_with_arc_mutex() {
let config = SideChannelConfig::default();
let context = Arc::new(Mutex::new(SideChannelContext::new(config)));
let context_clone1 = Arc::clone(&context);
let context_clone2 = Arc::clone(&context);
let handle1 = std::thread::spawn(move || {
let mut ctx = context_clone1.lock().unwrap();
ctx.increment_timing_protections();
ctx.increment_masking_operations();
ctx.get_stats()
});
let handle2 = std::thread::spawn(move || {
let mut ctx = context_clone2.lock().unwrap();
ctx.increment_timing_protections();
ctx.increment_cache_flush();
ctx.get_stats()
});
let _stats1 = handle1.join().unwrap();
let _stats2 = handle2.join().unwrap();
let final_stats = context.lock().unwrap().get_stats();
assert_eq!(final_stats.timing_protections, 2); assert_eq!(final_stats.masking_operations, 1); assert_eq!(final_stats.cache_flush_operations, 1);
assert!(final_stats.timing_protections >= 2); assert_eq!(final_stats.masking_operations, 1); assert_eq!(final_stats.cache_flush_operations, 1); }
#[test]
fn test_countermeasure_stats_parallel_tests() {
let mut handles = vec![];
for i in 0..4 {
let handle = std::thread::spawn(move || {
let config = SideChannelConfig::default();
let mut context = SideChannelContext::new(config);
for _ in 0..(i + 1) {
context.increment_timing_protections();
context.increment_masking_operations();
}
context.get_stats()
});
handles.push(handle);
}
let mut results = vec![];
for handle in handles {
results.push(handle.join().unwrap());
}
for (i, stats) in results.iter().enumerate() {
let expected_count = (i + 1) as u64;
assert_eq!(stats.timing_protections, expected_count);
assert_eq!(stats.masking_operations, expected_count);
assert_eq!(stats.error_detection_triggers, 0);
assert_eq!(stats.cache_flush_operations, 0);
}
let unique_timing_counts: std::collections::HashSet<_> =
results.iter().map(|s| s.timing_protections).collect();
assert_eq!(unique_timing_counts.len(), 4); }