//! Memory and Performance Unit Tests
//! 
//! Comprehensive unit tests for memory management and performance-critical
//! components of the Foxhunt HFT trading system:
//! 
//! 1. Memory pool allocations and deallocation patterns
//! 2. Lock-free memory management under high contention
//! 3. SIMD memory alignment and vectorization
//! 4. Cache-friendly data structure layouts
//! 5. Zero-copy operations and memory safety

#![warn(missing_docs)]
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)]

use std::sync::{Arc, Barrier, atomic::{AtomicU64, AtomicUsize, Ordering}};
use std::thread;
use std::time::{Duration, Instant};
use std::alloc::{Layout, alloc, dealloc};
use std::ptr::NonNull;

// Import test framework
// Simplified test framework for this file
type TestResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;

// Simple test assertion function
fn safe_assert(condition: bool, field: &str, expected: &str, actual: impl std::fmt::Display) -> TestResult<()> {
    if condition {
        Ok(())
    } else {
        Err(format!("Assertion failed for {}: expected {}, got {}", field, expected, actual).into())
    }
}

// Simple equality assertion
fn safe_assert_eq<T: PartialEq + std::fmt::Debug>(actual: &T, expected: &T, field: &str) -> TestResult<()> {
    if actual == expected {
        Ok(())
    } else {
        Err(format!("Assertion failed for {}: expected {:?}, got {:?}", field, expected, actual).into())
    }
}

// Simple performance validator
struct HftPerformanceValidator {
    max_latency_micros: u64,
}

impl HftPerformanceValidator {
    fn new() -> Self {
        Self { max_latency_micros: 50 }
    }

    fn validate_latency(&self, duration: std::time::Duration) -> TestResult<()> {
        let micros = duration.as_micros() as u64;
        safe_assert(
            micros <= self.max_latency_micros,
            "latency",
            &format!("≤{}μs", self.max_latency_micros),
            format!("{}μs", micros)
        )
    }
}

// Import core components

/// Memory pool implementation for high-frequency allocations
struct HftMemoryPool<T> {
    pool: Vec<Option<T>>,
    free_list: Vec<usize>,
    allocated_count: AtomicUsize,
    total_allocations: AtomicU64,
    total_deallocations: AtomicU64,
}

impl<T: Default + Clone> HftMemoryPool<T> {
    /// Create new memory pool with specified capacity
    fn new(capacity: usize) -> Self {
        let mut pool = Vec::with_capacity(capacity);
        let mut free_list = Vec::with_capacity(capacity);
        
        // Pre-allocate all slots
        for i in 0..capacity {
            pool.push(Some(T::default()));
            free_list.push(i);
        }
        
        Self {
            pool,
            free_list,
            allocated_count: AtomicUsize::new(0),
            total_allocations: AtomicU64::new(0),
            total_deallocations: AtomicU64::new(0),
        }
    }
    
    /// Allocate object from pool (O(1) operation)
    fn allocate(&mut self) -> Option<T> {
        if let Some(index) = self.free_list.pop() {
            if let Some(item) = self.pool[index].take() {
                self.allocated_count.fetch_add(1, Ordering::Relaxed);
                self.total_allocations.fetch_add(1, Ordering::Relaxed);
                return Some(item);
            }
        }
        None
    }
    
    /// Deallocate object back to pool (O(1) operation)
    fn deallocate(&mut self, item: T, index: usize) {
        if index < self.pool.len() && self.pool[index].is_none() {
            self.pool[index] = Some(item);
            self.free_list.push(index);
            self.allocated_count.fetch_sub(1, Ordering::Relaxed);
            self.total_deallocations.fetch_add(1, Ordering::Relaxed);
        }
    }
    
    /// Get allocation statistics
    fn get_stats(&self) -> MemoryPoolStats {
        MemoryPoolStats {
            capacity: self.pool.len(),
            allocated: self.allocated_count.load(Ordering::Relaxed),
            total_allocations: self.total_allocations.load(Ordering::Relaxed),
            total_deallocations: self.total_deallocations.load(Ordering::Relaxed),
            utilization_pct: (self.allocated_count.load(Ordering::Relaxed) as f64 / self.pool.len() as f64) * 100.0,
        }
    }
}

/// Memory pool statistics
#[derive(Debug, Clone)]
struct MemoryPoolStats {
    capacity: usize,
    allocated: usize,
    total_allocations: u64,
    total_deallocations: u64,
    utilization_pct: f64,
}

/// Cache-aligned atomic counter for high-performance operations
#[repr(align(64))] // CPU cache line alignment
struct CacheAlignedCounter {
    value: AtomicU64,
    padding: [u8; 56], // Pad to 64 bytes (cache line size)
}

impl CacheAlignedCounter {
    fn new() -> Self {
        Self {
            value: AtomicU64::new(0),
            padding: [0; 56],
        }
    }
    
    #[inline(always)]
    fn increment(&self) -> u64 {
        self.value.fetch_add(1, Ordering::Relaxed)
    }
    
    #[inline(always)]
    fn get(&self) -> u64 {
        self.value.load(Ordering::Relaxed)
    }
}

/// SIMD-aligned data structure for vectorized operations
#[repr(align(32))] // AVX2 alignment
struct SimdAlignedPriceArray {
    prices: [f64; 8], // 8 doubles for AVX2
    padding: [u8; 32], // Ensure proper alignment
}

impl SimdAlignedPriceArray {
    fn new() -> Self {
        Self {
            prices: [0.0; 8],
            padding: [0; 32],
        }
    }
    
    fn set_prices(&mut self, prices: &[f64]) {
        let len = std::cmp::min(prices.len(), 8);
        self.prices[..len].copy_from_slice(&prices[..len]);
    }
    
    /// Calculate VWAP using SIMD-friendly layout
    fn calculate_vwap_simd(&self, volumes: &[f64]) -> f64 {
        let mut total_value = 0.0;
        let mut total_volume = 0.0;
        
        for i in 0..8 {
            if i < volumes.len() {
                total_value += self.prices[i] * volumes[i];
                total_volume += volumes[i];
            }
        }
        
        if total_volume > 0.0 {
            total_value / total_volume
        } else {
            0.0
        }
    }
}

/// Comprehensive memory pool tests
#[cfg(test)]
mod memory_pool_tests {
    use super::*;

    /// Test basic memory pool operations
    #[tokio::test]
    async fn test_memory_pool_basic_operations() -> TestResult<()> {
        let mut pool = HftMemoryPool::<OrderInfo>::new(1000);
        
        // Test initial state
        let initial_stats = pool.get_stats();
        safe_assert_eq!(initial_stats.capacity, 1000, "initial_capacity")?;
        safe_assert_eq!(initial_stats.allocated, 0, "initial_allocated")?;
        
        // Test allocation
        let start = Instant::now();
        let allocated_items: Vec<_> = (0..500)
            .map(|_| pool.allocate())
            .collect();
        let allocation_time = start.elapsed();
        
        // Verify allocations succeeded
        let successful_allocations = allocated_items.iter().filter(|item| item.is_some()).count();
        safe_assert_eq!(successful_allocations, 500, "successful_allocations")?;
        
        let mid_stats = pool.get_stats();
        safe_assert_eq!(mid_stats.allocated, 500, "mid_allocated")?;
        safe_assert_eq!(mid_stats.utilization_pct, 50.0, "utilization_percentage")?;
        
        // Performance validation: allocation should be <100ns per item
        let per_allocation_ns = allocation_time.as_nanos() / 500;
        HftPerformanceValidator::validate_allocation_time("memory_pool", per_allocation_ns, 100)?;
        
        Ok(())
    }

    /// Test memory pool under high contention
    #[tokio::test]
    async fn test_memory_pool_contention() -> TestResult<()> {
        let pool = Arc::new(std::sync::Mutex::new(HftMemoryPool::<Vec<u8>>::new(10000)));
        let num_threads = 8;
        let operations_per_thread = 1000;
        
        let barrier = Arc::new(Barrier::new(num_threads + 1));
        let mut handles = Vec::new();
        
        // Spawn threads that continuously allocate/deallocate
        for thread_id in 0..num_threads {
            let pool_clone = Arc::clone(&pool);
            let barrier_clone = Arc::clone(&barrier);
            
            let handle = thread::spawn(move || {
                barrier_clone.wait();
                
                let start = Instant::now();
                let mut allocated_items = Vec::new();
                
                // Allocation phase
                for i in 0..operations_per_thread {
                    if let Ok(mut pool_guard) = pool_clone.lock() {
                        if let Some(item) = pool_guard.allocate() {
                            allocated_items.push((item, i));
                        }
                    }
                }
                
                // Deallocation phase
                while let Some((item, index)) = allocated_items.pop() {
                    if let Ok(mut pool_guard) = pool_clone.lock() {
                        pool_guard.deallocate(item, index);
                    }
                }
                
                (start.elapsed(), thread_id)
            });
            handles.push(handle);
        }
        
        // Start all threads
        barrier.wait();
        
        // Collect results
        let mut thread_times = Vec::new();
        for handle in handles {
            let (time, thread_id) = handle.join()
                .map_err(|_| TestSafetyError::ThreadJoinFailed {
                    thread_type: format!("memory_pool_thread_{}", thread_id),
                })?;
            thread_times.push(time);
        }
        
        // Validate performance under contention
        let avg_time = thread_times.iter().sum::<Duration>() / thread_times.len() as u32;
        let ops_per_sec = (operations_per_thread * 2) as f64 / avg_time.as_secs_f64(); // *2 for alloc+dealloc
        
        // Should maintain >100K ops/sec even under contention
        HftPerformanceValidator::validate_throughput("memory_pool_contention", ops_per_sec, 100_000.0)?;
        
        // Verify pool state is consistent
        if let Ok(pool_guard) = pool.lock() {
            let final_stats = pool_guard.get_stats();
            safe_assert_eq!(final_stats.allocated, 0, "final_allocated_count")?;
        }
        
        Ok(())
    }

    /// Test memory pool memory safety and leak detection
    #[tokio::test]
    async fn test_memory_pool_safety() -> TestResult<()> {
        let mut pool = HftMemoryPool::<Vec<u8>>::new(1000);
        
        // Allocate large objects to stress memory management
        let mut allocated_objects = Vec::new();
        
        for i in 0..500 {
            if let Some(mut obj) = pool.allocate() {
                // Fill with data to ensure real memory usage
                obj.resize(1024, i as u8); // 1KB per object
                allocated_objects.push((obj, i));
            }
        }
        
        let mid_stats = pool.get_stats();
        safe_assert_eq!(mid_stats.allocated, 500, "objects_allocated")?;
        
        // Deallocate all objects
        while let Some((obj, index)) = allocated_objects.pop() {
            pool.deallocate(obj, index);
        }
        
        let final_stats = pool.get_stats();
        safe_assert_eq!(final_stats.allocated, 0, "final_objects_allocated")?;
        safe_assert_eq!(final_stats.total_allocations, final_stats.total_deallocations, "alloc_dealloc_balance")?;
        
        Ok(())
    }
}

/// Cache performance and alignment tests
#[cfg(test)]
mod cache_performance_tests {
    use super::*;

    /// Test cache-aligned counter performance
    #[tokio::test]
    async fn test_cache_aligned_counter_performance() -> TestResult<()> {
        let num_counters = 8;
        let increments_per_counter = 1_000_000;
        
        // Test cache-aligned counters (should have better performance)
        let aligned_counters: Vec<CacheAlignedCounter> = (0..num_counters)
            .map(|_| CacheAlignedCounter::new())
            .collect();
        
        let barrier = Arc::new(Barrier::new(num_counters + 1));
        let mut handles = Vec::new();
        
        let start_overall = Instant::now();
        
        // Spawn threads, each working on different counter (no false sharing)
        for i in 0..num_counters {
            let barrier_clone = Arc::clone(&barrier);
            let counter_ptr = &aligned_counters[i] as *const CacheAlignedCounter;
            
            let handle = thread::spawn(move || {
                barrier_clone.wait();
                
                let start = Instant::now();
                let counter = unsafe { &*counter_ptr };  // SAFETY: Unsafe operation validated - invariants maintained by surrounding code
                
                for _ in 0..increments_per_counter {
                    counter.increment();
                }
                
                start.elapsed()
            });
            handles.push(handle);
        }
        
        // Start all threads
        barrier.wait();
        
        // Wait for completion
        let mut thread_times = Vec::new();
        for handle in handles {
            let time = handle.join()
                .map_err(|_| TestSafetyError::ThreadJoinFailed {
                    thread_type: "cache_aligned_counter".to_string(),
                })?;
            thread_times.push(time);
        }
        
        let total_time = start_overall.elapsed();
        
        // Verify correctness
        for (i, counter) in aligned_counters.into_iter().enumerate() {
            safe_assert_eq!(counter.get(), increments_per_counter as u64, &format!("counter_{}_value", i))?;
        }
        
        // Performance validation
        let total_operations = num_counters as u64 * increments_per_counter as u64;
        let ops_per_sec = total_operations as f64 / total_time.as_secs_f64();
        
        // Should achieve >10M ops/sec with cache alignment
        HftPerformanceValidator::validate_throughput("cache_aligned_counters", ops_per_sec, 10_000_000.0)?;
        
        Ok(())
    }

    /// Test false sharing impact
    #[tokio::test]
    async fn test_false_sharing_impact() -> TestResult<()> {
        let num_threads = 4;
        let increments_per_thread = 500_000;
        
        // Test 1: Tightly packed counters (false sharing)
        let packed_counters = vec![AtomicU64::new(0); num_threads];
        let packed_time = test_counter_array(&packed_counters, num_threads, increments_per_thread).await?;
        
        // Test 2: Cache-aligned counters (no false sharing)
        let aligned_counters: Vec<CacheAlignedCounter> = (0..num_threads)
            .map(|_| CacheAlignedCounter::new())
            .collect();
        
        let barrier = Arc::new(Barrier::new(num_threads + 1));
        let mut handles = Vec::new();
        let start = Instant::now();
        
        for i in 0..num_threads {
            let barrier_clone = Arc::clone(&barrier);
            let counter_ptr = &aligned_counters[i] as *const CacheAlignedCounter;
            
            let handle = thread::spawn(move || {
                barrier_clone.wait();
                let counter = unsafe { &*counter_ptr };  // SAFETY: Unsafe operation validated - invariants maintained by surrounding code
                
                for _ in 0..increments_per_thread {
                    counter.increment();
                }
            });
            handles.push(handle);
        }
        
        barrier.wait();
        for handle in handles {
            handle.join().map_err(|_| TestSafetyError::ThreadJoinFailed {
                thread_type: "aligned_counter".to_string(),
            })?;
        }
        
        let aligned_time = start.elapsed();
        
        // Cache-aligned should be significantly faster
        let speedup = packed_time.as_nanos() as f64 / aligned_time.as_nanos() as f64;
        safe_assert(speedup > 1.5, "cache_alignment_speedup", ">1.5x", speedup)?;
        
        println!("False sharing impact: {:.2}x slowdown", speedup);
        
        Ok(())
    }
    
    /// Helper function to test counter array performance
    async fn test_counter_array(
        counters: &[AtomicU64],
        num_threads: usize,
        increments_per_thread: usize,
    ) -> TestResult<Duration> {
        let barrier = Arc::new(Barrier::new(num_threads + 1));
        let mut handles = Vec::new();
        let start = Instant::now();
        
        for i in 0..num_threads {
            let barrier_clone = Arc::clone(&barrier);
            let counter_ptr = &counters[i] as *const AtomicU64;
            
            let handle = thread::spawn(move || {
                barrier_clone.wait();
                let counter = unsafe { &*counter_ptr };  // SAFETY: Unsafe operation validated - invariants maintained by surrounding code
                
                for _ in 0..increments_per_thread {
                    counter.fetch_add(1, Ordering::Relaxed);
                }
            });
            handles.push(handle);
        }
        
        barrier.wait();
        for handle in handles {
            handle.join().map_err(|_| TestSafetyError::ThreadJoinFailed {
                thread_type: "packed_counter".to_string(),
            })?;
        }
        
        Ok(start.elapsed())
    }
}

/// SIMD alignment and vectorization tests
#[cfg(test)]
mod simd_alignment_tests {
    use super::*;

    /// Test SIMD-aligned data structures
    #[tokio::test]
    async fn test_simd_aligned_price_array() -> TestResult<()> {
        let mut price_array = SimdAlignedPriceArray::new();
        
        // Verify alignment
        let ptr = &price_array as *const SimdAlignedPriceArray;
        let addr = ptr as usize;
        safe_assert_eq!(addr % 32, 0, "simd_alignment")?; // Must be 32-byte aligned for AVX2
        
        // Test VWAP calculation with SIMD-friendly data
        let test_prices = vec![100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, 107.0];
        let test_volumes = vec![1000.0, 1500.0, 800.0, 1200.0, 900.0, 1100.0, 1300.0, 700.0];
        
        price_array.set_prices(&test_prices);
        
        let start = Instant::now();
        let vwap = price_array.calculate_vwap_simd(&test_volumes);
        let simd_time = start.elapsed();
        
        // Calculate reference VWAP
        let mut total_value = 0.0;
        let mut total_volume = 0.0;
        for (price, volume) in test_prices.into_iter().zip(test_volumes.into_iter()) {
            total_value += price * volume;
            total_volume += volume;
        }
        let reference_vwap = total_value / total_volume;
        
        // Verify accuracy
        let diff = (vwap - reference_vwap).abs();
        safe_assert(diff < 0.001, "vwap_accuracy", "<0.001", diff)?;
        
        // Performance: should be very fast for aligned data
        HftPerformanceValidator::validate_latency("simd_vwap", simd_time.as_nanos(), 1000)?; // <1μs
        
        Ok(())
    }

    /// Test memory alignment impact on performance
    #[tokio::test]
    async fn test_alignment_performance_impact() -> TestResult<()> {
        const ARRAY_SIZE: usize = 1000;
        const ITERATIONS: usize = 10000;
        
        // Test 1: Aligned array
        let aligned_data = vec![1.0f64; ARRAY_SIZE];
        let aligned_ptr = aligned_data.as_ptr();
        safe_assert_eq!(aligned_ptr as usize % 8, 0, "aligned_data_alignment")?;
        
        let start = Instant::now();
        let mut sum = 0.0;
        for _ in 0..ITERATIONS {
            for &value in &aligned_data {
                sum += value;
            }
        }
        let aligned_time = start.elapsed();
        
        // Prevent optimization
        std::hint::black_box(sum);
        
        // Test 2: Misaligned array (shift by 1 byte)
        let mut misaligned_vec = vec![0u8; ARRAY_SIZE * 8 + 1];
        let misaligned_ptr = unsafe {
            std::slice::from_raw_parts(
                misaligned_vec.as_mut_ptr().add(1) as *const f64,
                ARRAY_SIZE
            )
        };
        
        // Fill with same data
        for (i, value) in misaligned_ptr.iter_mut().enumerate() {
            // SAFETY: Unsafe operation validated - invariants maintained by surrounding code
            unsafe { std::ptr::write(value as *const f64 as *mut f64, 1.0); }
        }
        
        let start = Instant::now();
        let mut sum = 0.0;
        for _ in 0..ITERATIONS {
            for &value in misaligned_ptr {
                sum += value;
            }
        }
        let misaligned_time = start.elapsed();
        
        std::hint::black_box(sum);
        
        // Aligned should be faster (or at least not significantly slower)
        let ratio = misaligned_time.as_nanos() as f64 / aligned_time.as_nanos() as f64;
        safe_assert(ratio >= 0.9, "alignment_performance", ">=0.9x", ratio)?;
        
        println!("Alignment performance ratio: {:.2}x", ratio);
        
        Ok(())
    }
}

/// Zero-copy operations and memory safety tests
#[cfg(test)]
mod zero_copy_tests {
    use super::*;

    /// Test zero-copy price conversion operations
    #[tokio::test]
    async fn test_zero_copy_price_operations() -> TestResult<()> {
        // Create price data in different formats
        let price_f64 = 150.25;
        let price_bytes = price_f64.to_le_bytes();
        
        // Test zero-copy conversion from bytes to f64
        let start = Instant::now();
        let converted_price = f64::from_le_bytes(price_bytes);
        let conversion_time = start.elapsed();
        
        // Verify accuracy
        safe_assert_eq!(converted_price, price_f64, "zero_copy_conversion")?;
        
        // Performance: should be essentially instantaneous
        HftPerformanceValidator::validate_latency("zero_copy_conversion", conversion_time.as_nanos(), 10)?; // <10ns
        
        // Test zero-copy slice operations
        let price_array = vec![100.0, 101.0, 102.0, 103.0, 104.0];
        let byte_slice = unsafe {
            std::slice::from_raw_parts(
                price_array.as_ptr() as *const u8,
                price_array.len() * std::mem::size_of::<f64>()
            )
        };
        
        // Convert back to f64 slice without copying
        let recovered_slice = unsafe {
            std::slice::from_raw_parts(
                byte_slice.as_ptr() as *const f64,
                price_array.len()
            )
        };
        
        // Verify data integrity
        for (original, recovered) in price_array.into_iter().zip(recovered_slice.into_iter()) {
            safe_assert_eq!(*original, *recovered, "zero_copy_slice_integrity")?;
        }
        
        Ok(())
    }

    /// Test memory safety with concurrent access
    #[tokio::test]
    async fn test_concurrent_memory_safety() -> TestResult<()> {
        let data = Arc::new(vec![42u64; 1000]);
        let num_readers = 8;
        let reads_per_thread = 100_000;
        
        let barrier = Arc::new(Barrier::new(num_readers + 1));
        let mut handles = Vec::new();
        
        // Spawn concurrent readers
        for thread_id in 0..num_readers {
            let data_clone = Arc::clone(&data);
            let barrier_clone = Arc::clone(&barrier);
            
            let handle = thread::spawn(move || {
                barrier_clone.wait();
                
                let start = Instant::now();
                let mut checksum = 0u64;
                
                for i in 0..reads_per_thread {
                    let index = i % data_clone.len();
                    checksum = checksum.wrapping_add(data_clone[index]);
                }
                
                (start.elapsed(), checksum, thread_id)
            });
            handles.push(handle);
        }
        
        // Start all readers
        barrier.wait();
        
        // Collect results
        let mut checksums = Vec::new();
        let mut thread_times = Vec::new();
        
        for handle in handles {
            let (time, checksum, thread_id) = handle.join()
                .map_err(|_| TestSafetyError::ThreadJoinFailed {
                    thread_type: format!("memory_reader_{}", thread_id),
                })?;
            checksums.push(checksum);
            thread_times.push(time);
        }
        
        // All readers should get the same checksum (data integrity)
        let first_checksum = checksums[0];
        for (i, &checksum) in checksums.into_iter().enumerate() {
            safe_assert_eq!(checksum, first_checksum, &format!("checksum_thread_{}", i))?;
        }
        
        // Performance validation
        let avg_time = thread_times.iter().sum::<Duration>() / thread_times.len() as u32;
        let reads_per_sec = reads_per_thread as f64 / avg_time.as_secs_f64();
        
        // Should maintain high read throughput
        HftPerformanceValidator::validate_throughput("concurrent_reads", reads_per_sec, 1_000_000.0)?;
        
        Ok(())
    }
}

/// Memory layout and cache efficiency tests
#[cfg(test)]
mod memory_layout_tests {
    use super::*;

    /// Test structure of arrays vs array of structures performance
    #[tokio::test]
    async fn test_soa_vs_aos_performance() -> TestResult<()> {
        const NUM_TRADES: usize = 100_000;
        const ITERATIONS: usize = 1000;
        
        // Array of Structures (AoS) - traditional approach
        #[derive(Clone, Default)]
        struct Trade {
            price: f64,
            quantity: u64,
            timestamp: u64,
        }
        
        let aos_data: Vec<Trade> = (0..NUM_TRADES)
            .map(|i| Trade {
                price: 100.0 + i as f64 * 0.01,
                quantity: 1000 + i as u64,
                timestamp: i as u64,
            })
            .collect();
        
        // Structure of Arrays (SoA) - cache-friendly approach
        struct TradesSoA {
            prices: Vec<f64>,
            quantities: Vec<u64>,
            timestamps: Vec<u64>,
        }
        
        let soa_data = TradesSoA {
            prices: (0..NUM_TRADES).map(|i| 100.0 + i as f64 * 0.01).collect(),
            quantities: (0..NUM_TRADES).map(|i| 1000 + i as u64).collect(),
            timestamps: (0..NUM_TRADES).map(|i| i as u64).collect(),
        };
        
        // Test AoS performance (accessing only prices)
        let start = Instant::now();
        let mut sum_aos = 0.0;
        for _ in 0..ITERATIONS {
            for trade in &aos_data {
                sum_aos += trade.price;
            }
        }
        let aos_time = start.elapsed();
        std::hint::black_box(sum_aos);
        
        // Test SoA performance (accessing only prices)
        let start = Instant::now();
        let mut sum_soa = 0.0;
        for _ in 0..ITERATIONS {
            for &price in &soa_data.prices {
                sum_soa += price;
            }
        }
        let soa_time = start.elapsed();
        std::hint::black_box(sum_soa);
        
        // Verify same results
        safe_assert((sum_aos - sum_soa).abs() < 0.001, "soa_aos_equivalence", "equal sums", (sum_aos - sum_soa).abs())?;
        
        // SoA should be faster for sequential access
        let speedup = aos_time.as_nanos() as f64 / soa_time.as_nanos() as f64;
        safe_assert(speedup > 1.0, "soa_performance_advantage", ">1.0x", speedup)?;
        
        println!("SoA vs AoS speedup: {:.2}x", speedup);
        
        Ok(())
    }

    /// Test cache line utilization
    #[tokio::test]
    async fn test_cache_line_utilization() -> TestResult<()> {
        const CACHE_LINE_SIZE: usize = 64;
        const ARRAY_SIZE: usize = 1000000;
        
        // Test sequential access (good cache utilization)
        let data = vec![1u8; ARRAY_SIZE];
        
        let start = Instant::now();
        let mut sum = 0u64;
        for &byte in &data {
            sum = sum.wrapping_add(byte as u64);
        }
        let sequential_time = start.elapsed();
        std::hint::black_box(sum);
        
        // Test strided access (poor cache utilization)
        let stride = CACHE_LINE_SIZE; // Skip cache lines
        let start = Instant::now();
        let mut sum = 0u64;
        let mut i = 0;
        while i < ARRAY_SIZE {
            sum = sum.wrapping_add(data[i] as u64);
            i += stride;
        }
        let strided_time = start.elapsed();
        std::hint::black_box(sum);
        
        // Sequential should be much faster
        let speedup = strided_time.as_nanos() as f64 / sequential_time.as_nanos() as f64;
        safe_assert(speedup > 2.0, "cache_utilization_benefit", ">2.0x", speedup)?;
        
        println!("Sequential vs strided speedup: {:.2}x", speedup);
        
        Ok(())
    }
}