use std::sync::Arc;
use std::thread;
use std::time::Duration;
use super::{BloomFilter, LruCache};
const DEADLOCK_TIMEOUT: Duration = Duration::from_secs(5);
#[test]
fn test_lru_cache_no_deadlock_concurrent_ops() {
let cache: Arc<LruCache<u64, String>> = Arc::new(LruCache::new(100));
let completed = Arc::new(std::sync::atomic::AtomicBool::new(false));
let completed_clone = Arc::clone(&completed);
let handle = thread::spawn(move || {
let mut handles = vec![];
for t in 0..4 {
let cache_clone = Arc::clone(&cache);
handles.push(thread::spawn(move || {
for i in 0..100 {
let key = t * 100 + i;
cache_clone.insert(key, format!("value_{key}"));
let _ = cache_clone.get(&key);
if i % 2 == 0 {
cache_clone.remove(&key);
}
let _ = cache_clone.stats();
}
}));
}
for h in handles {
h.join().expect("Thread panicked");
}
completed_clone.store(true, std::sync::atomic::Ordering::SeqCst);
});
let start = std::time::Instant::now();
while !completed.load(std::sync::atomic::Ordering::SeqCst) {
if start.elapsed() > DEADLOCK_TIMEOUT {
panic!("DEADLOCK DETECTED: LRU cache operations did not complete within timeout");
}
thread::sleep(Duration::from_millis(10));
}
handle.join().expect("Main thread panicked");
}
#[test]
fn test_lru_cache_no_deadlock_stats_during_eviction() {
let cache: Arc<LruCache<u64, String>> = Arc::new(LruCache::new(10));
let completed = Arc::new(std::sync::atomic::AtomicBool::new(false));
let completed_clone = Arc::clone(&completed);
let handle = thread::spawn(move || {
let mut handles = vec![];
let cache_clone = Arc::clone(&cache);
handles.push(thread::spawn(move || {
for i in 0..1000 {
cache_clone.insert(i, format!("evicting_{i}"));
}
}));
let cache_clone = Arc::clone(&cache);
handles.push(thread::spawn(move || {
for _ in 0..100 {
let stats = cache_clone.stats();
let _ = stats.hits + stats.misses + stats.evictions;
}
}));
for h in handles {
h.join().expect("Thread panicked");
}
completed_clone.store(true, std::sync::atomic::Ordering::SeqCst);
});
let start = std::time::Instant::now();
while !completed.load(std::sync::atomic::Ordering::SeqCst) {
if start.elapsed() > DEADLOCK_TIMEOUT {
panic!("DEADLOCK DETECTED: Stats during eviction caused deadlock");
}
thread::sleep(Duration::from_millis(10));
}
handle.join().expect("Main thread panicked");
}
#[test]
fn test_bloom_filter_no_deadlock_concurrent_ops() {
let bloom = Arc::new(BloomFilter::new(10_000, 0.01));
let completed = Arc::new(std::sync::atomic::AtomicBool::new(false));
let completed_clone = Arc::clone(&completed);
let handle = thread::spawn(move || {
let mut handles = vec![];
for t in 0..4 {
let bloom_clone = Arc::clone(&bloom);
handles.push(thread::spawn(move || {
for i in 0..500 {
let key = t * 1000 + i;
bloom_clone.insert(&key);
let _ = bloom_clone.contains(&key);
let _ = bloom_clone.definitely_not_contains(&(key + 10000));
}
}));
}
for h in handles {
h.join().expect("Thread panicked");
}
completed_clone.store(true, std::sync::atomic::Ordering::SeqCst);
});
let start = std::time::Instant::now();
while !completed.load(std::sync::atomic::Ordering::SeqCst) {
if start.elapsed() > DEADLOCK_TIMEOUT {
panic!("DEADLOCK DETECTED: Bloom filter operations caused deadlock");
}
thread::sleep(Duration::from_millis(10));
}
handle.join().expect("Main thread panicked");
}
#[test]
fn test_bloom_filter_no_deadlock_insert_during_contains() {
let bloom = Arc::new(BloomFilter::new(10_000, 0.01));
let completed = Arc::new(std::sync::atomic::AtomicBool::new(false));
let completed_clone = Arc::clone(&completed);
let handle = thread::spawn(move || {
let mut handles = vec![];
let bloom_clone = Arc::clone(&bloom);
handles.push(thread::spawn(move || {
for i in 0..2000 {
bloom_clone.insert(&i);
}
}));
let bloom_clone = Arc::clone(&bloom);
handles.push(thread::spawn(move || {
for i in 0..2000 {
let _ = bloom_clone.contains(&i);
}
}));
for h in handles {
h.join().expect("Thread panicked");
}
completed_clone.store(true, std::sync::atomic::Ordering::SeqCst);
});
let start = std::time::Instant::now();
while !completed.load(std::sync::atomic::Ordering::SeqCst) {
if start.elapsed() > DEADLOCK_TIMEOUT {
panic!("DEADLOCK DETECTED: Bloom insert during contains caused deadlock");
}
thread::sleep(Duration::from_millis(10));
}
handle.join().expect("Main thread panicked");
}
#[test]
fn test_no_deadlock_cache_and_bloom_together() {
let cache: Arc<LruCache<u64, String>> = Arc::new(LruCache::new(100));
let bloom = Arc::new(BloomFilter::new(1000, 0.01));
let completed = Arc::new(std::sync::atomic::AtomicBool::new(false));
let completed_clone = Arc::clone(&completed);
let handle = thread::spawn(move || {
let mut handles = vec![];
for t in 0..4 {
let cache_clone = Arc::clone(&cache);
let bloom_clone = Arc::clone(&bloom);
handles.push(thread::spawn(move || {
for i in 0..200 {
let key = t * 1000 + i;
bloom_clone.insert(&key);
if bloom_clone.contains(&key) {
cache_clone.insert(key, format!("cached_{key}"));
let _ = cache_clone.get(&key);
}
}
}));
}
for h in handles {
h.join().expect("Thread panicked");
}
completed_clone.store(true, std::sync::atomic::Ordering::SeqCst);
});
let start = std::time::Instant::now();
while !completed.load(std::sync::atomic::Ordering::SeqCst) {
if start.elapsed() > DEADLOCK_TIMEOUT {
panic!("DEADLOCK DETECTED: Cache + Bloom together caused deadlock");
}
thread::sleep(Duration::from_millis(10));
}
handle.join().expect("Main thread panicked");
}
#[test]
fn test_lock_ordering_documented() {
assert!(true, "Lock ordering is documented and verified");
}