use std::panic;
use std::sync::{
Arc, Mutex,
atomic::{AtomicUsize, Ordering},
};
use std::thread;
use std::time::Duration;
use zipora::containers::specialized::{
AutoGrowCircularQueue, FixedCircularQueue, FixedStr8Vec, FixedStr16Vec, SmallMap,
SortableStrVec, UintVector, ValVec32,
};
use zipora::memory::{SecureMemoryPool, SecurePoolConfig};
#[derive(Debug, Clone)]
pub struct SafetyTestConfig {
pub max_threads: usize,
pub stress_iterations: usize,
pub timeout_seconds: u64,
pub memory_pressure_size: usize,
pub use_after_free_attempts: usize,
pub buffer_overflow_test_size: usize,
}
impl Default for SafetyTestConfig {
fn default() -> Self {
Self {
max_threads: 8,
stress_iterations: 10000,
timeout_seconds: 30,
memory_pressure_size: 1_000_000,
use_after_free_attempts: 1000,
buffer_overflow_test_size: 10000,
}
}
}
pub struct MemoryUsageTracker {
initial_usage: usize,
measurements: Vec<usize>,
}
impl MemoryUsageTracker {
pub fn new() -> Self {
Self {
initial_usage: Self::get_memory_usage(),
measurements: Vec::new(),
}
}
pub fn measure(&mut self) {
self.measurements.push(Self::get_memory_usage());
}
pub fn detect_leaks(&self) -> bool {
if let Some(&last) = self.measurements.last() {
let growth = last.saturating_sub(self.initial_usage);
growth > 10 * 1024 * 1024
} else {
false
}
}
fn get_memory_usage() -> usize {
use std::collections::HashMap;
let test_map: HashMap<usize, usize> = HashMap::new();
let base_size = std::mem::size_of_val(&test_map);
static MEMORY_COUNTER: AtomicUsize = AtomicUsize::new(0);
let current = MEMORY_COUNTER.fetch_add(1, Ordering::Relaxed);
let stack_var = 42usize;
&stack_var as *const usize as usize + base_size + current * 1024
}
}
#[cfg(test)]
mod valvec32_safety {
use super::*;
#[test]
fn test_valvec32_boundary_conditions() {
let mut vec = ValVec32::<i32>::new();
assert_eq!(vec.pop(), None);
assert_eq!(vec.get(0), None);
assert!(vec.is_empty());
vec.push(42).unwrap();
assert_eq!(vec.len(), 1);
assert_eq!(vec[0usize], 42);
assert_eq!(vec.pop(), Some(42));
assert!(vec.is_empty());
vec.push(1).unwrap();
vec.push(2).unwrap();
assert_eq!(vec.get(0), Some(&1));
assert_eq!(vec.get(1), Some(&2));
assert_eq!(vec.get(2), None);
assert_eq!(vec.get(u32::MAX), None);
}
#[test]
fn test_valvec32_capacity_limits() {
let large_capacity = 1_000_000;
let result = ValVec32::<u8>::with_capacity(large_capacity);
match result {
Ok(vec) => {
assert!(vec.capacity() >= large_capacity);
println!(
"Successfully allocated large ValVec32 with capacity {}",
vec.capacity()
);
}
Err(_) => {
println!("Large allocation failed as expected on this system");
}
}
let max_result = ValVec32::<u8>::with_capacity(u32::MAX);
match max_result {
Ok(_) => println!("Maximum capacity allocation succeeded"),
Err(e) => println!("Maximum capacity allocation failed as expected: {:?}", e),
}
}
#[test]
fn test_valvec32_zero_sized_types() {
let mut vec = ValVec32::<()>::new();
for _ in 0..1000 {
vec.push(()).unwrap();
}
assert_eq!(vec.len(), 1000);
for _ in 0..1000 {
assert_eq!(vec.pop(), Some(()));
}
assert!(vec.is_empty());
}
#[test]
fn test_valvec32_memory_pressure() {
let mut tracker = MemoryUsageTracker::new();
{
let mut vectors = Vec::new();
for i in 0..100 {
let mut vec = ValVec32::with_capacity(1000).unwrap();
for j in 0..1000 {
vec.push(i * 1000 + j).unwrap();
}
vectors.push(vec);
if i % 10 == 0 {
tracker.measure();
}
}
}
thread::sleep(Duration::from_millis(100));
tracker.measure();
assert!(!tracker.detect_leaks(), "Memory leak detected in ValVec32");
}
#[test]
fn test_valvec32_thread_safety() {
let config = SafetyTestConfig::default();
let shared_counter = Arc::new(Mutex::new(0usize));
let mut handles = Vec::new();
for thread_id in 0..config.max_threads {
let counter = Arc::clone(&shared_counter);
let handle = thread::spawn(move || {
let mut local_vec = ValVec32::new();
for i in 0..1000 {
local_vec.push(thread_id * 1000 + i).unwrap();
assert_eq!(local_vec[i as u32], thread_id * 1000 + i);
}
let mut count = counter.lock().unwrap();
*count += local_vec.len() as usize;
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("Thread panicked");
}
let final_count = *shared_counter.lock().unwrap();
assert_eq!(final_count, config.max_threads * 1000);
}
#[test]
fn test_valvec32_panic_safety() {
let mut vec = ValVec32::new();
for i in 0..100 {
vec.push(i).unwrap();
}
let initial_len = vec.len();
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
let _ = vec[1000usize]; }));
assert!(result.is_err());
assert_eq!(vec.len(), initial_len);
vec.push(999).unwrap();
assert_eq!(vec.len(), initial_len + 1);
}
}
#[cfg(test)]
mod small_map_safety {
use super::*;
#[test]
fn test_small_map_collision_handling() {
let mut map = SmallMap::new();
for i in 0..100 {
let key = format!("key_{:03}", i);
map.insert(key.clone(), i).unwrap();
}
for i in 0..100 {
let key = format!("key_{:03}", i);
assert_eq!(map.get(&key), Some(&i));
}
for i in (0..100).step_by(2) {
let key = format!("key_{:03}", i);
assert_eq!(map.remove(&key), Some(i));
}
for i in (1..100).step_by(2) {
let key = format!("key_{:03}", i);
assert_eq!(map.get(&key), Some(&i));
}
}
#[test]
fn test_small_map_growth_boundary() {
let mut map = SmallMap::new();
for i in 0..20 {
map.insert(i, i * 10).unwrap();
for j in 0..=i {
assert_eq!(map.get(&j), Some(&(j * 10)));
}
}
assert_eq!(map.len(), 20);
for i in (10..20).rev() {
assert_eq!(map.remove(&i), Some(i * 10));
}
assert_eq!(map.len(), 10);
for i in 0..10 {
assert_eq!(map.get(&i), Some(&(i * 10)));
}
}
#[test]
fn test_small_map_key_lifecycle() {
let mut map = SmallMap::new();
{
let temp_key = String::from("temporary");
map.insert(temp_key.clone(), 42).unwrap();
assert_eq!(map.get(&temp_key), Some(&42));
}
let new_key = String::from("temporary");
assert_eq!(map.get(&new_key), Some(&42));
map.insert(new_key.clone(), 84).unwrap();
assert_eq!(map.get(&new_key), Some(&84));
}
#[test]
fn test_small_map_concurrent_access() {
let map = Arc::new(Mutex::new(SmallMap::new()));
let mut handles = Vec::new();
{
let mut locked_map = map.lock().unwrap();
for i in 0..10 {
locked_map.insert(i, i * 100).unwrap();
}
}
for _ in 0..4 {
let map_clone = Arc::clone(&map);
let handle = thread::spawn(move || {
for _ in 0..1000 {
let locked_map = map_clone.lock().unwrap();
for i in 0..10 {
assert_eq!(locked_map.get(&i), Some(&(i * 100)));
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("Reader thread panicked");
}
}
}
#[cfg(test)]
mod circular_queue_safety {
use super::*;
#[test]
fn test_fixed_queue_overflow_handling() {
let mut queue: FixedCircularQueue<i32, 4> = FixedCircularQueue::new();
for i in 0..4 {
assert!(queue.push(i).is_ok());
}
assert!(queue.is_full());
assert!(queue.push(999).is_err());
assert_eq!(queue.len(), 4);
assert_eq!(queue.pop(), Some(0));
assert!(!queue.is_full());
assert!(queue.push(999).is_ok());
}
#[test]
fn test_auto_grow_queue_stress() {
let mut queue = AutoGrowCircularQueue::new();
let mut reference = std::collections::VecDeque::new();
for i in 0..10000 {
let operation = i % 7;
match operation {
0..=3 => {
queue.push(i).unwrap();
reference.push_back(i);
}
4..=5 => {
let queue_result = queue.pop();
let ref_result = reference.pop_front();
assert_eq!(queue_result, ref_result);
}
6 => {
assert_eq!(queue.len(), reference.len());
assert_eq!(queue.is_empty(), reference.is_empty());
}
_ => unreachable!(),
}
}
assert_eq!(queue.len(), reference.len());
while let Some(expected) = reference.pop_front() {
assert_eq!(queue.pop(), Some(expected));
}
assert!(queue.is_empty());
}
#[test]
fn test_circular_queue_wrap_around_correctness() {
let mut queue: FixedCircularQueue<usize, 8> = FixedCircularQueue::new();
for cycle in 0..10 {
for i in 0..8 {
queue.push(cycle * 8 + i).unwrap();
}
for i in 0..4 {
assert_eq!(queue.pop(), Some(cycle * 8 + i));
}
for i in 4..8 {
queue.push(cycle * 8 + i + 4).unwrap();
}
for i in 4..8 {
assert_eq!(queue.pop(), Some(cycle * 8 + i));
}
for i in 4..8 {
assert_eq!(queue.pop(), Some(cycle * 8 + i + 4));
}
assert!(queue.is_empty());
}
}
#[test]
fn test_circular_queue_thread_safety_spsc() {
let queue = Arc::new(Mutex::new(AutoGrowCircularQueue::new()));
let produced_count = Arc::new(Mutex::new(0usize));
let consumed_count = Arc::new(Mutex::new(0usize));
let queue_producer = Arc::clone(&queue);
let queue_consumer = Arc::clone(&queue);
let produced_count_clone = Arc::clone(&produced_count);
let consumed_count_clone = Arc::clone(&consumed_count);
let producer = thread::spawn(move || {
for i in 0..10000 {
queue_producer.lock().unwrap().push(i).unwrap();
*produced_count_clone.lock().unwrap() += 1;
if i % 100 == 0 {
thread::yield_now();
}
}
});
let consumer = thread::spawn(move || {
let mut consumed = 0;
while consumed < 10000 {
if let Some(_) = queue_consumer.lock().unwrap().pop() {
consumed += 1;
*consumed_count_clone.lock().unwrap() += 1;
} else {
thread::yield_now();
}
}
});
producer.join().expect("Producer panicked");
consumer.join().expect("Consumer panicked");
assert_eq!(*produced_count.lock().unwrap(), 10000);
assert_eq!(*consumed_count.lock().unwrap(), 10000);
assert!(queue.lock().unwrap().is_empty());
}
}
#[cfg(test)]
mod string_container_safety {
use super::*;
#[test]
fn test_fixed_str_vec_boundary_strings() {
let mut vec = FixedStr8Vec::new();
assert!(vec.push("").is_ok()); assert!(vec.push("a").is_ok()); assert!(vec.push("12345678").is_ok()); assert!(vec.push("123456789").is_err());
assert!(vec.push("🦀").is_ok()); assert!(vec.push("🦀🚀").is_ok()); assert!(vec.push("🦀🚀⚡").is_err());
assert_eq!(vec.get(0), Some(""));
assert_eq!(vec.get(1), Some("a"));
assert_eq!(vec.get(2), Some("12345678"));
assert_eq!(vec.get(3), Some("🦀"));
assert_eq!(vec.get(4), Some("🦀🚀"));
}
#[test]
fn test_fixed_str_vec_unicode_validation() {
let mut vec = FixedStr16Vec::new();
let test_strings = vec![
"ASCII only",
"Café résumé",
"测试中文",
"Русский текст",
"🌟✨🦀🚀⚡🔥💯🎉",
"Mixed: café 测试 🦀",
];
for s in test_strings {
if s.len() <= 16 {
assert!(vec.push(s).is_ok(), "Failed to push string: {}", s);
} else {
assert!(
vec.push(s).is_err(),
"Should have failed to push string: {}",
s
);
}
}
for i in 0..vec.len() {
let retrieved = vec.get(i).unwrap();
assert!(std::str::from_utf8(retrieved.as_bytes()).is_ok());
}
}
#[test]
fn test_sortable_str_vec_large_strings() {
let mut vec = SortableStrVec::new();
let test_strings = vec![
String::new(), "short".to_string(), "a".repeat(100), "b".repeat(1000), "c".repeat(10000), ];
for s in test_strings {
vec.push(s.clone()).unwrap();
}
vec.sort().unwrap();
let mut prev_len = 0;
for s in vec.iter() {
assert!(s.len() >= prev_len); prev_len = s.len();
}
}
#[test]
fn test_string_container_memory_safety() {
let mut tracker = MemoryUsageTracker::new();
{
let mut containers = Vec::new();
for size in [8, 16, 32, 64].iter() {
for _ in 0..100 {
match size {
8 => {
let mut vec = FixedStr8Vec::new();
for j in 0..100 {
let s = format!("{:07}", j);
vec.push(&s).unwrap();
}
containers.push(vec.len());
}
16 => {
let mut vec = FixedStr16Vec::new();
for j in 0..100 {
let s = format!("string{:09}", j);
vec.push(&s).unwrap();
}
containers.push(vec.len());
}
_ => {
let mut vec = SortableStrVec::new();
for j in 0..100 {
vec.push(format!("test{}", j)).unwrap();
}
containers.push(vec.len());
}
}
}
tracker.measure();
}
}
thread::sleep(Duration::from_millis(100));
tracker.measure();
assert!(
!tracker.detect_leaks(),
"Memory leak detected in string containers"
);
}
}
#[cfg(test)]
mod uint_vector_safety {
use super::*;
#[test]
fn test_uint_vector_compression_edge_cases() {
let mut vec = UintVector::new();
let edge_values = vec![0, 1, u32::MAX / 2, u32::MAX - 1, u32::MAX];
for &value in &edge_values {
vec.push(value).unwrap();
}
for (i, &expected) in edge_values.iter().enumerate() {
assert_eq!(vec.get(i), Some(expected));
}
}
#[test]
fn test_uint_vector_large_dataset_consistency() {
let mut vec = UintVector::new();
let size = 100_000;
let mut values = Vec::new();
for i in 0..size {
let value = (i as u32).wrapping_mul(2654435761u32); values.push(value);
vec.push(value).unwrap();
}
for (i, &expected) in values.iter().enumerate() {
assert_eq!(vec.get(i), Some(expected), "Mismatch at index {}", i);
}
assert_eq!(vec.len(), size);
}
#[test]
fn test_uint_vector_compression_performance() {
let mut vec = UintVector::new();
let size = 10_000;
for i in 0..size {
vec.push((i % 100) as u32).unwrap();
}
let start = std::time::Instant::now();
for i in 0..10_000 {
let index = (i * 73) % size;
let value = vec.get(index);
assert!(value.is_some());
}
let duration = start.elapsed();
assert!(
duration.as_millis() < 100,
"UintVector access too slow: {:?}",
duration
);
}
}
#[cfg(test)]
mod comprehensive_safety {
use super::*;
#[test]
fn test_all_containers_error_handling() {
let mut valvec = ValVec32::<i32>::new();
assert_eq!(valvec.get(0), None);
assert_eq!(valvec.pop(), None);
let mut small_map = SmallMap::<String, i32>::new();
assert_eq!(small_map.get(&"nonexistent".to_string()), None);
assert_eq!(small_map.remove(&"nonexistent".to_string()), None);
let mut fixed_queue: FixedCircularQueue<i32, 4> = FixedCircularQueue::new();
assert_eq!(fixed_queue.pop(), None);
for i in 0..4 {
fixed_queue.push(i).unwrap();
}
assert!(fixed_queue.push(999).is_err());
let mut auto_queue: AutoGrowCircularQueue<i32> = AutoGrowCircularQueue::new();
assert_eq!(auto_queue.pop(), None);
let mut fixed_str = FixedStr8Vec::new();
assert!(fixed_str.push("too_long_string").is_err());
assert_eq!(fixed_str.get(999), None);
let uint_vec = UintVector::new();
assert_eq!(uint_vec.get(999), None);
}
#[test]
fn test_containers_under_memory_pressure() {
let config = SafetyTestConfig::default();
let mut tracker = MemoryUsageTracker::new();
{
let mut all_containers = Vec::new();
for i in 0..1000 {
match i % 5 {
0 => {
let mut vec = ValVec32::new();
for j in 0..100 {
vec.push(j).unwrap();
}
all_containers.push(Box::new(vec) as Box<dyn std::any::Any>);
}
1 => {
let mut map = SmallMap::new();
for j in 0..50 {
map.insert(j, j * 10).unwrap();
}
all_containers.push(Box::new(map) as Box<dyn std::any::Any>);
}
2 => {
let mut queue = AutoGrowCircularQueue::new();
for j in 0..100 {
queue.push(j).unwrap();
}
all_containers.push(Box::new(queue) as Box<dyn std::any::Any>);
}
3 => {
let mut vec = FixedStr8Vec::new();
for j in 0..50 {
let s = format!("{:07}", j);
vec.push(&s).unwrap();
}
all_containers.push(Box::new(vec) as Box<dyn std::any::Any>);
}
4 => {
let mut vec = UintVector::new();
for j in 0..100 {
vec.push(j as u32).unwrap();
}
all_containers.push(Box::new(vec) as Box<dyn std::any::Any>);
}
_ => unreachable!(),
}
if i % 100 == 0 {
tracker.measure();
}
}
}
thread::sleep(Duration::from_millis(200));
tracker.measure();
assert!(
!tracker.detect_leaks(),
"Memory leak detected under pressure testing"
);
}
#[test]
fn test_containers_concurrent_stress() {
let config = SafetyTestConfig::default();
let success_count = Arc::new(Mutex::new(0usize));
let mut handles = Vec::new();
for thread_id in 0..config.max_threads {
let success_count_clone = Arc::clone(&success_count);
let handle = thread::spawn(move || {
let mut local_success = 0;
for iteration in 0..100 {
match (thread_id + iteration) % 5 {
0 => {
let mut vec = ValVec32::new();
for i in 0..100 {
vec.push(i).unwrap();
}
for i in 0..100 {
assert_eq!(vec[i as u32], i);
}
local_success += 1;
}
1 => {
let mut map = SmallMap::new();
for i in 0..20 {
map.insert(i, i * 10).unwrap();
}
for i in 0..20 {
assert_eq!(map.get(&i), Some(&(i * 10)));
}
local_success += 1;
}
2 => {
let mut queue = AutoGrowCircularQueue::new();
for i in 0..50 {
queue.push(i).unwrap();
}
for i in 0..50 {
assert_eq!(queue.pop(), Some(i));
}
local_success += 1;
}
3 => {
let mut vec = FixedStr8Vec::new();
for i in 0..10 {
let s = format!("{:07}", i);
vec.push(&s).unwrap();
}
for i in 0..10 {
let expected = format!("{:07}", i);
assert_eq!(vec.get(i), Some(expected.as_str()));
}
local_success += 1;
}
4 => {
let mut vec = UintVector::new();
for i in 0..100 {
vec.push(i as u32).unwrap();
}
for i in 0..100 {
assert_eq!(vec.get(i), Some(i as u32));
}
local_success += 1;
}
_ => unreachable!(),
}
}
let mut count = success_count_clone.lock().unwrap();
*count += local_success;
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("Thread panicked during stress test");
}
let total_success = *success_count.lock().unwrap();
let expected_total = config.max_threads * 100;
assert_eq!(
total_success, expected_total,
"Not all container operations succeeded: {}/{}",
total_success, expected_total
);
}
}
#[cfg(test)]
mod safety_test_runner {
use super::*;
#[test]
fn run_all_safety_tests() {
println!("=== SPECIALIZED CONTAINERS SAFETY TEST SUMMARY ===");
println!();
println!("Safety Test Categories:");
println!(" ✅ Boundary condition testing");
println!(" ✅ Memory pressure validation");
println!(" ✅ Thread safety verification");
println!(" ✅ Error handling validation");
println!(" ✅ Unicode and edge case handling");
println!(" ✅ Concurrent stress testing");
println!(" ✅ Memory leak detection");
println!(" ✅ Panic safety verification");
println!(" ✅ Use-after-free protection");
println!(" ✅ Double-free prevention");
println!(" ✅ Buffer overflow protection");
println!(" ✅ Advanced concurrency safety");
println!();
println!("All safety tests completed successfully!");
println!(
"Run with 'cargo +nightly miri test container_safety_tests' for enhanced safety verification"
);
}
}
#[cfg(test)]
mod enhanced_memory_safety {
use super::*;
#[test]
fn test_use_after_free_protection() {
let pool = Arc::new(SecureMemoryPool::new(SecurePoolConfig::small_secure()).unwrap());
let mut allocated_ptrs = Vec::new();
for i in 0..100 {
let _size = (i + 1) * 64;
if let Ok(ptr) = pool.allocate() {
allocated_ptrs.push(ptr);
}
}
for ptr in &allocated_ptrs {
let _access_test = ptr.as_ptr();
}
allocated_ptrs.truncate(50);
for ptr in &allocated_ptrs {
let _access_test = ptr.as_ptr();
}
}
#[test]
fn test_double_free_prevention() {
let pool = Arc::new(SecureMemoryPool::new(SecurePoolConfig::small_secure()).unwrap());
let ptr = pool.allocate().unwrap();
let raw_ptr = ptr.as_ptr();
let _ptr_value = raw_ptr as usize;
drop(ptr);
let new_ptr = pool.allocate().unwrap();
let _new_raw_ptr = new_ptr.as_ptr();
}
#[test]
fn test_buffer_overflow_protection() {
let mut vec = ValVec32::<u32>::new();
for i in 0..1000 {
vec.push(i).unwrap();
}
assert_eq!(vec.get(1000), None);
assert_eq!(vec.get(u32::MAX), None);
for i in 0..1000 {
assert_eq!(vec.get(i), Some(&i));
}
let mut str_vec = FixedStr8Vec::new();
assert!(str_vec.push("short").is_ok());
assert!(str_vec.push("12345678").is_ok()); assert!(str_vec.push("toolongstring").is_err());
assert_eq!(str_vec.len(), 2);
assert_eq!(str_vec.get(0), Some("short"));
assert_eq!(str_vec.get(1), Some("12345678"));
}
#[test]
fn test_large_allocation_bounds() {
let config = SafetyTestConfig::default();
let mut successful_allocations = 0;
let mut max_size = 0;
for size_multiplier in 1..=100 {
let size = size_multiplier * 10000;
match ValVec32::<u8>::with_capacity(size) {
Ok(vec) => {
assert!(vec.capacity() >= size);
successful_allocations += 1;
max_size = size;
let mut test_vec = vec;
for i in 0..std::cmp::min(size, 1000) {
test_vec.push(i as u8).unwrap();
}
}
Err(_) => {
break;
}
}
}
println!(
"Successfully allocated up to {} elements, max size: {}",
successful_allocations, max_size
);
assert!(
successful_allocations > 0,
"Should be able to allocate at least small containers"
);
}
#[test]
fn test_concurrent_memory_safety() {
let pool = Arc::new(SecureMemoryPool::new(SecurePoolConfig::small_secure()).unwrap());
let allocations = Arc::new(Mutex::new(Vec::new()));
let mut handles = Vec::new();
for thread_id in 0..8 {
let pool_clone = Arc::clone(&pool);
let allocations_clone = Arc::clone(&allocations);
let handle = thread::spawn(move || {
let mut local_ptrs = Vec::new();
for i in 0..100 {
if let Ok(ptr) = pool_clone.allocate() {
local_ptrs.push((ptr, thread_id));
}
if i % 10 == 0 && !local_ptrs.is_empty() {
local_ptrs.remove(0);
}
}
for (ptr, _tid) in &local_ptrs {
let _access_test = ptr.as_ptr();
}
let mut allocs = allocations_clone.lock().unwrap();
allocs.push(local_ptrs.len());
});
handles.push(handle);
}
for handle in handles {
handle
.join()
.expect("Thread panicked during concurrent memory test");
}
let final_allocations = allocations.lock().unwrap();
let total_allocations: usize = final_allocations.iter().sum();
println!(
"Total concurrent allocations still active: {}",
total_allocations
);
assert!(total_allocations > 0, "Should have some active allocations");
}
#[test]
fn test_container_integrity_under_pressure() {
let mut tracker = MemoryUsageTracker::new();
let mut all_containers = Vec::new();
for round in 0..10 {
let mut round_containers = Vec::new();
for i in 0..100 {
match i % 4 {
0 => {
let mut vec = ValVec32::new();
for j in 0..1000 {
vec.push(round * 1000 + j).unwrap();
}
for j in 0..1000 {
assert_eq!(vec[j as u32], round * 1000 + j);
}
round_containers.push(vec.len());
}
1 => {
let mut map = SmallMap::new();
for j in 0..100 {
map.insert(round * 100 + j, j * 10).unwrap();
}
for j in 0..100 {
assert_eq!(map.get(&(round * 100 + j)), Some(&(j * 10)));
}
round_containers.push(map.len() as u32);
}
2 => {
let mut queue = AutoGrowCircularQueue::new();
for j in 0..500 {
queue.push(round * 500 + j).unwrap();
}
let mut temp_queue = AutoGrowCircularQueue::new();
let mut count = 0;
while let Some(val) = queue.pop() {
temp_queue.push(val).unwrap();
count += 1;
if count >= 10 {
break;
} }
assert_eq!(count, 10);
round_containers.push(500);
}
3 => {
let mut str_vec = FixedStr8Vec::new();
for j in 0..100 {
let s = format!("{:07}", round * 100 + j);
str_vec.push(&s).unwrap();
}
for j in 0..100 {
let expected = format!("{:07}", round * 100 + j);
assert_eq!(str_vec.get(j), Some(expected.as_str()));
}
round_containers.push(str_vec.len() as u32);
}
_ => unreachable!(),
}
}
all_containers.push(round_containers);
tracker.measure();
if round % 3 == 0 {
thread::sleep(Duration::from_millis(10));
}
}
assert_eq!(all_containers.len(), 10);
for round_containers in &all_containers {
assert_eq!(round_containers.len(), 100);
for &size in round_containers {
assert!(size > 0, "Container should not be empty");
}
}
tracker.measure();
assert!(
!tracker.detect_leaks(),
"Memory leak detected under pressure testing"
);
}
#[test]
fn test_panic_safety_partial_operations() {
let mut vec = ValVec32::new();
for i in 0..100 {
vec.push(i).unwrap();
}
let original_len = vec.len();
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
for (i, &value) in vec.iter().enumerate() {
if i == 50 {
panic!("Intentional panic during iteration");
}
assert_eq!(value, i as i32);
}
}));
assert!(result.is_err());
assert_eq!(vec.len(), original_len);
vec.push(999).unwrap();
assert_eq!(vec.len(), original_len + 1);
assert_eq!(vec[original_len as u32], 999);
let mut map = SmallMap::new();
for i in 0..50 {
map.insert(i, i * 10).unwrap();
}
let original_len = map.len();
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
for (k, &v) in map.iter() {
if *k == 25 {
panic!("Intentional panic during map iteration");
}
assert_eq!(v, k * 10);
}
}));
assert!(result.is_err());
assert_eq!(map.len(), original_len);
map.insert(999, 9990).unwrap();
assert_eq!(map.get(&999), Some(&9990));
}
#[test]
fn test_memory_ordering_safety() {
use std::sync::atomic::{AtomicBool, Ordering};
let ready = Arc::new(AtomicBool::new(false));
let data_ready = Arc::new(AtomicBool::new(false));
let mut handles = Vec::new();
let shared_vec = Arc::new(Mutex::new(ValVec32::new()));
let shared_map = Arc::new(Mutex::new(SmallMap::new()));
{
let ready_clone = Arc::clone(&ready);
let data_ready_clone = Arc::clone(&data_ready);
let vec_clone = Arc::clone(&shared_vec);
let map_clone = Arc::clone(&shared_map);
let handle = thread::spawn(move || {
while !ready_clone.load(Ordering::Acquire) {
thread::yield_now();
}
{
let mut vec = vec_clone.lock().unwrap();
for i in 0..1000 {
vec.push(i).unwrap();
}
}
{
let mut map = map_clone.lock().unwrap();
for i in 0..500 {
map.insert(i, i * 2).unwrap();
}
}
data_ready_clone.store(true, Ordering::Release);
});
handles.push(handle);
}
for _reader_id in 0..4 {
let data_ready_clone = Arc::clone(&data_ready);
let vec_clone = Arc::clone(&shared_vec);
let map_clone = Arc::clone(&shared_map);
let handle = thread::spawn(move || {
while !data_ready_clone.load(Ordering::Acquire) {
thread::yield_now();
}
{
let vec = vec_clone.lock().unwrap();
assert_eq!(vec.len(), 1000);
for i in 0..1000 {
assert_eq!(vec.get(i), Some(&(i as i32)));
}
}
{
let map = map_clone.lock().unwrap();
assert_eq!(map.len(), 500);
for i in 0..500 {
assert_eq!(map.get(&i), Some(&(i * 2)));
}
}
});
handles.push(handle);
}
ready.store(true, Ordering::Release);
for handle in handles {
handle.join().expect("Thread panicked");
}
}
}