#[cfg(test)]
mod tests {
    use sec_mem::SecretBox;
    use zeroize::Zeroize;

    #[test]
    fn test_basic_usage() {
        let mut secret_box = SecretBox::new(42u32);

        // Test read access
        secret_box.with_secret(|s| {
            assert_eq!(*s, 42);
        });

        // Test write access
        secret_box.with_secret_mut(|s| {
            *s = 100;
        });

        secret_box.with_secret(|s| {
            assert_eq!(*s, 100);
        });
    }

    #[test]
    fn test_init_with_mut() {
        // Test initializing a large array without moving it across the stack
        let mut secret_box = SecretBox::<[u8; 32]>::init_with_mut(|s| {
            for (i, byte) in s.iter_mut().enumerate() {
                *byte = i as u8;
            }
        });

        secret_box.with_secret(|s| {
            assert_eq!(s[0], 0);
            assert_eq!(s[31], 31);
        });
    }

    #[test]
    fn test_debug_redaction() {
        let secret = "highly confidential password".to_string();
        let secret_box = SecretBox::new(secret);

        let debug_output = format!("{:?}", secret_box);
        assert!(debug_output.contains("SecretBox<alloc::string::String>([REDACTED])"));
        assert!(!debug_output.contains("confidential"));
    }

    #[test]
    fn test_constant_time_comparison() {
        // Use a type we know implements ConstantTimeEq, like a single u8 or a wrapped slice.
        // Or simply u32 which implements ConstantTimeEq in modern subtle
        let mut box1 = SecretBox::new(5u8);
        let mut box2 = SecretBox::new(5u8);
        let mut box3 = SecretBox::new(9u8);

        let res_equal: bool = box1.constant_time_eq(&mut box2).into();
        let res_different: bool = box1.constant_time_eq(&mut box3).into();

        assert!(res_equal, "Identical secrets should compare equal");
        assert!(!res_different, "Different secrets should compare not equal");
    }

    #[test]
    #[should_panic(expected = "SECURITY ALERT: SecretBox stack memory corruption detected!")]
    fn attack_stack_corruption_front_canary() {
        let mut secret_box = SecretBox::new("my secret".to_string());
        
        // Attacker uses a stack-based buffer overflow or unsafe pointer arithmetic
        // to overwrite the front canary surrounding the data.
        unsafe {
            // Get the raw address of the SecretBox struct on the stack
            let struct_ptr = &mut secret_box as *mut _ as *mut usize;
            
            // The SecretBox is #[repr(C)], so we know the physical layout:
            // struct_ptr.add(0) = canary_front
            // ...
            
            // Attacker overwrites the front canary with garbage
            struct_ptr.add(0).write_volatile(0xBAD_C0DE);
        }
        
        // Application unknowingly attempts to use the secret
        secret_box.with_secret(|s| {
            println!("This should never execute: {}", s);
        });
    }

    #[test]
    #[should_panic(expected = "SECURITY ALERT: SecretBox stack memory corruption detected!")]
    fn attack_stack_corruption_back_canary() {
        let mut secret_box = SecretBox::new(42u64);
        
        unsafe {
            // Because of #[repr(C)], we know the layout precisely:
            // struct_ptr.add(0) = canary_front
            // struct_ptr.add(1) = inner_secret (the u64 is exactly 1 usize on 64-bit platforms)
            // struct_ptr.add(2) = canary_back
            
            let struct_ptr = &mut secret_box as *mut _ as *mut usize;
            
            // Attacker overwrites the back canary
            #[cfg(target_pointer_width = "64")]
            struct_ptr.add(2).write_volatile(0xBAD_C0DE);
            
            #[cfg(target_pointer_width = "32")]
            struct_ptr.add(3).write_volatile(0xBAD_C0DE); // u64 takes 2 usizes on 32-bit
        }
        
        // Application unknowingly attempts to use the secret
        secret_box.with_secret(|_| {});
    }

    #[test]
    fn test_zeroize_method() {
        let mut secret_box = SecretBox::new([0xAAu8; 32]);
        
        secret_box.with_secret(|s| {
            assert!(s.iter().all(|&x| x == 0xAA));
        });
        
        secret_box.zeroize();
        
        secret_box.with_secret(|s| {
            // It should be completely filled with zeroes now
            assert!(s.iter().all(|&x| x == 0));
        });
    }

    #[test]
    fn test_concurrency_mutex_enforcement() {
        use std::sync::{Arc, Mutex};
        use std::thread;

        // Since SecretBox requires &mut self to access the secret, it is mathematically
        // impossible to share it across threads without an explicit synchronization primitive
        // like a Mutex. This proves the strict Exclusive Access enforcement works perfectly.
        
        let shared_secret = Arc::new(Mutex::new(SecretBox::new(0u32)));
        
        let mut handles = vec![];
        
        for _ in 0..10 {
            let secret_clone = Arc::clone(&shared_secret);
            handles.push(thread::spawn(move || {
                let mut lock = secret_clone.lock().unwrap();
                lock.with_secret_mut(|s| {
                    *s += 1;
                });
            }));
        }
        
        for handle in handles {
            handle.join().unwrap();
        }
        
        let mut final_lock = shared_secret.lock().unwrap();
        final_lock.with_secret(|s| {
            assert_eq!(*s, 10);
        });
    }
}
