use std::{collections::HashSet, thread};
use moa_idalloc::monotonic::IdGen;
#[test]
fn starts_at_one() {
let g = IdGen::new();
assert_eq!(g.alloc(), 1);
assert_eq!(g.alloc(), 2);
assert_eq!(g.alloc(), 3);
}
#[test]
fn never_yields_zero() {
let g = IdGen::new();
for _ in 0..1000 {
assert_ne!(g.alloc(), 0);
}
}
#[test]
fn strictly_increasing_and_unique() {
let g = IdGen::new();
let mut prev = g.alloc();
let mut seen = HashSet::new();
seen.insert(prev);
for _ in 0..10_000 {
let cur = g.alloc();
assert!(cur > prev, "must be strictly increasing");
assert!(seen.insert(cur), "must be unique");
prev = cur;
}
}
#[test]
fn default_matches_new() {
let g = IdGen::default();
assert_eq!(g.alloc(), 1);
}
#[test]
fn concurrent_allocs_are_unique() {
const THREADS: usize = 8;
const PER_THREAD: usize = 5_000;
let idgen = IdGen::new();
let all: Vec<u64> = thread::scope(|s| {
let handles: Vec<_> = (0..THREADS)
.map(|_| s.spawn(|| (0..PER_THREAD).map(|_| idgen.alloc()).collect::<Vec<u64>>()))
.collect();
handles.into_iter().flat_map(|h| h.join().unwrap()).collect()
});
let total = all.len();
assert_eq!(total, THREADS * PER_THREAD);
let unique: HashSet<u64> = all.into_iter().collect();
assert_eq!(unique.len(), total, "并发分配的 id 必须各不相同");
}