use super::*;
use std::sync::Arc;
use std::thread;
#[test]
fn test_basic_create_and_read() {
let swap = Arc::new(GenSwap::new(42u64));
assert_eq!(swap.generation(), 0);
assert_eq!(*swap.load_full(), 42);
}
#[test]
fn test_update_increments_generation() {
let swap = Arc::new(GenSwap::new(1));
assert_eq!(swap.generation(), 0);
swap.update(2);
assert_eq!(swap.generation(), 1);
assert_eq!(*swap.load_full(), 2);
swap.update(3);
assert_eq!(swap.generation(), 2);
assert_eq!(*swap.load_full(), 3);
}
#[test]
fn test_update_arc() {
let swap = Arc::new(GenSwap::new(1));
assert_eq!(swap.generation(), 0);
let arc = Arc::new(100);
swap.update_arc(Arc::clone(&arc));
assert_eq!(swap.generation(), 1);
assert_eq!(*swap.load_full(), 100);
}
#[test]
fn test_new_from_arc() {
let arc = Arc::new(42);
let swap = GenSwap::new_from_arc(arc);
assert_eq!(swap.generation(), 0);
assert_eq!(*swap.load_full(), 42);
}
#[test]
fn test_rcu() {
let swap = Arc::new(GenSwap::new(5));
assert_eq!(swap.generation(), 0);
swap.rcu(|&n| n * 2);
assert_eq!(*swap.load_full(), 10);
assert_eq!(swap.generation(), 1);
swap.rcu(|&n| n + 1);
assert_eq!(*swap.load_full(), 11);
assert_eq!(swap.generation(), 2);
}
#[test]
fn test_cached_reader_basic() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
assert_eq!(**reader.get(), 42);
assert_eq!(reader.cached_generation(), 0);
}
#[test]
fn test_cached_reader_cache_hit() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
let first = Arc::clone(reader.get());
let second = Arc::clone(reader.get());
assert!(Arc::ptr_eq(&first, &second));
}
#[test]
fn test_cached_reader_cache_miss() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
let first = Arc::clone(reader.get());
assert_eq!(*first, 42);
assert_eq!(reader.cached_generation(), 0);
swap.update(100);
let second = Arc::clone(reader.get());
assert_eq!(*second, 100);
assert_eq!(reader.cached_generation(), 1);
assert!(!Arc::ptr_eq(&first, &second));
}
#[test]
fn test_cached_reader_get_clone() {
let swap = Arc::new(GenSwap::new(vec![1, 2, 3]));
let mut reader = swap.reader();
let arc1 = reader.get_clone();
let arc2 = reader.get_clone();
assert_eq!(*arc1, vec![1, 2, 3]);
assert!(Arc::ptr_eq(&arc1, &arc2));
}
#[test]
fn test_is_stale() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
assert!(!reader.is_stale());
swap.update(100);
assert!(reader.is_stale());
reader.get(); assert!(!reader.is_stale());
}
#[test]
fn test_force_refresh() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
let first_gen = reader.cached_generation();
assert_eq!(first_gen, 0);
reader.force_refresh();
let second_gen = reader.cached_generation();
assert_eq!(second_gen, 0); assert_eq!(**reader.get(), 42);
swap.update(100);
assert!(reader.is_stale());
reader.force_refresh();
assert!(!reader.is_stale());
assert_eq!(**reader.get(), 100);
}
#[test]
fn test_cached() {
let swap = Arc::new(GenSwap::new(42));
let mut reader = swap.reader();
let _ = reader.get();
swap.update(100);
assert_eq!(**reader.cached(), 42);
assert_eq!(**reader.get(), 100);
}
#[test]
fn test_multiple_readers() {
let swap = Arc::new(GenSwap::new(1));
let mut reader1 = swap.reader();
let mut reader2 = swap.reader();
assert_eq!(**reader1.get(), 1);
assert_eq!(**reader2.get(), 1);
swap.update(2);
assert_eq!(**reader1.get(), 2);
assert_eq!(**reader2.get(), 2);
}
#[test]
fn test_multiple_updates() {
let swap = Arc::new(GenSwap::new(0));
let mut reader = swap.reader();
for i in 1..=100 {
swap.update(i);
assert_eq!(**reader.get(), i);
assert_eq!(swap.generation(), i as u64);
}
}
#[test]
fn test_default() {
let swap: GenSwap<i32> = GenSwap::default();
assert_eq!(*swap.load_full(), 0);
assert_eq!(swap.generation(), 0);
}
#[test]
fn test_from() {
let swap = GenSwap::from(42);
assert_eq!(*swap.load_full(), 42);
assert_eq!(swap.generation(), 0);
}
#[test]
fn test_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
fn assert_not_sync<T: Send>() {}
assert_send::<GenSwap<i32>>();
assert_sync::<GenSwap<i32>>();
assert_send::<CachedReader<i32>>();
assert_not_sync::<CachedReader<i32>>();
}
#[test]
fn test_threaded_single_reader_per_thread() {
let swap = Arc::new(GenSwap::new(0));
let handles: Vec<_> = (0..4)
.map(|_| {
let swap = Arc::clone(&swap);
thread::spawn(move || {
let mut reader = swap.reader();
for _ in 0..1000 {
let _value = reader.get();
}
})
})
.collect();
for i in 1..=10 {
thread::sleep(std::time::Duration::from_micros(100));
swap.update(i);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn test_threaded_writer_and_readers() {
let swap = Arc::new(GenSwap::new(0));
let reader_handles: Vec<_> = (0..4)
.map(|_| {
let swap = Arc::clone(&swap);
thread::spawn(move || {
let mut reader = swap.reader();
let mut last_seen = 0;
for _ in 0..10000 {
let value = **reader.get();
assert!(value >= last_seen);
last_seen = value;
}
})
})
.collect();
let writer_swap = Arc::clone(&swap);
let writer_handle = thread::spawn(move || {
for i in 1..=100 {
writer_swap.update(i);
thread::sleep(std::time::Duration::from_micros(10));
}
});
writer_handle.join().unwrap();
for handle in reader_handles {
handle.join().unwrap();
}
assert_eq!(swap.generation(), 100);
assert_eq!(*swap.load_full(), 100);
}
#[test]
fn test_rcu_with_contention() {
let swap = Arc::new(GenSwap::new(0));
let handles: Vec<_> = (0..4)
.map(|_| {
let swap = Arc::clone(&swap);
thread::spawn(move || {
for _ in 0..250 {
swap.rcu(|&n| n + 1);
}
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
assert_eq!(*swap.load_full(), 1000);
assert_eq!(swap.generation(), 1000);
}
#[test]
fn test_large_data() {
let data = vec![1u64; 10000];
let swap = Arc::new(GenSwap::new(data.clone()));
let mut reader = swap.reader();
assert_eq!(**reader.get(), data);
let new_data = vec![2u64; 10000];
swap.update(new_data.clone());
assert_eq!(**reader.get(), new_data);
}
#[test]
fn test_string_data() {
let swap = Arc::new(GenSwap::new(String::from("hello")));
let mut reader = swap.reader();
assert_eq!(**reader.get(), "hello");
swap.update(String::from("world"));
assert_eq!(**reader.get(), "world");
}
#[test]
fn test_complex_type() {
#[derive(Debug, Clone, PartialEq)]
struct Config {
name: String,
count: usize,
flags: Vec<bool>,
}
let config1 = Config {
name: "test".to_string(),
count: 42,
flags: vec![true, false, true],
};
let swap = Arc::new(GenSwap::new(config1.clone()));
let mut reader = swap.reader();
assert_eq!(**reader.get(), config1);
let config2 = Config {
name: "updated".to_string(),
count: 100,
flags: vec![false, false],
};
swap.update(config2.clone());
assert_eq!(**reader.get(), config2);
}
#[test]
fn test_generation_monotonic() {
let swap = Arc::new(GenSwap::new(0));
let mut last_gen = 0;
for i in 1..=1000 {
swap.update(i);
let gen = swap.generation();
assert!(gen > last_gen, "Generation should be monotonically increasing");
assert_eq!(gen, i as u64);
last_gen = gen;
}
}
#[test]
fn test_reader_observes_all_updates_eventually() {
let swap = Arc::new(GenSwap::new(0));
let mut reader = swap.reader();
for i in 1..=100 {
swap.update(i);
let value = **reader.get();
assert!(value >= i);
}
}