#![cfg(feature = "std")]
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Barrier};
use std::thread;
use uselesskey_core::{Factory, Mode, Seed};
fn det_factory(byte: u8) -> Factory {
Factory::deterministic(Seed::new([byte; 32]))
}
fn seed_array<const N: usize>(seed: Seed) -> [u8; N] {
let mut buf = [0u8; N];
seed.fill_bytes(&mut buf);
buf
}
fn seed_u64_from_bytes(seed: Seed) -> u64 {
u64::from_le_bytes(seed_array::<8>(seed))
}
#[test]
fn concurrent_get_or_init_same_key_calls_init_once() {
let fx = det_factory(0x01);
let init_count = Arc::new(AtomicUsize::new(0));
let barrier = Arc::new(Barrier::new(8));
let handles: Vec<_> = (0..8)
.map(|_| {
let fx = fx.clone();
let count = init_count.clone();
let bar = barrier.clone();
thread::spawn(move || {
bar.wait();
let v = fx.get_or_init("domain:conc", "shared", b"spec", "good", |_rng| {
count.fetch_add(1, Ordering::SeqCst);
42u64
});
assert_eq!(*v, 42u64);
})
})
.collect();
for h in handles {
h.join().unwrap();
}
let count = init_count.load(Ordering::SeqCst);
assert!((1..=8).contains(&count), "init called {count} times");
}
#[test]
fn concurrent_get_or_init_different_keys_all_succeed() {
let fx = det_factory(0x02);
let barrier = Arc::new(Barrier::new(16));
let handles: Vec<_> = (0..16)
.map(|i| {
let fx = fx.clone();
let bar = barrier.clone();
thread::spawn(move || {
bar.wait();
let label = format!("thread-{i}");
let v = fx.get_or_init("domain:multi", &label, b"spec", "good", |_rng| i as u64);
assert_eq!(*v, i as u64);
})
})
.collect();
for h in handles {
h.join().unwrap();
}
}
#[test]
fn cache_clear_while_readers_active_does_not_panic() {
let fx = det_factory(0x03);
for i in 0..10 {
let label = format!("pre-{i}");
let _ = fx.get_or_init("domain:clear", &label, b"spec", "good", |_rng| i as u32);
}
let barrier = Arc::new(Barrier::new(9));
let mut handles: Vec<_> = (0..8)
.map(|i| {
let fx = fx.clone();
let bar = barrier.clone();
thread::spawn(move || {
bar.wait();
for _ in 0..100 {
let label = format!("pre-{}", i % 10);
let _ =
fx.get_or_init("domain:clear", &label, b"spec", "good", |_rng| i as u32);
}
})
})
.collect();
{
let fx = fx.clone();
let bar = barrier.clone();
handles.push(thread::spawn(move || {
bar.wait();
for _ in 0..50 {
fx.clear_cache();
}
}));
}
for h in handles {
h.join().unwrap();
}
}
#[test]
fn cache_handles_many_entries() {
let fx = det_factory(0x04);
let entry_count = 500;
for i in 0..entry_count {
let label = format!("entry-{i}");
let _ = fx.get_or_init("domain:many", &label, b"spec", "good", |_rng| i as u64);
}
for i in 0..entry_count {
let label = format!("entry-{i}");
let v = fx.get_or_init("domain:many", &label, b"spec", "good", |_rng| 999_999u64);
assert_eq!(*v, i as u64);
}
}
#[test]
fn clear_cache_forces_reinit_with_new_values() {
let fx = det_factory(0x05);
let init_count = AtomicUsize::new(0);
let first = fx.get_or_init("domain:reinit", "label", b"spec", "good", |_rng| {
init_count.fetch_add(1, Ordering::SeqCst);
100u32
});
assert_eq!(*first, 100);
assert_eq!(init_count.load(Ordering::SeqCst), 1);
fx.clear_cache();
let second = fx.get_or_init("domain:reinit", "label", b"spec", "good", |_rng| {
init_count.fetch_add(1, Ordering::SeqCst);
200u32
});
assert_eq!(init_count.load(Ordering::SeqCst), 2);
assert_eq!(*second, 200);
}
#[test]
fn random_factory_mode_is_random() {
let fx = Factory::random();
assert!(matches!(fx.mode(), Mode::Random));
}
#[test]
fn deterministic_factory_mode_contains_seed() {
let seed = Seed::new([0xAA; 32]);
let fx = Factory::deterministic(seed);
match fx.mode() {
Mode::Deterministic { master } => {
assert_eq!(master.bytes(), &[0xAA; 32]);
}
Mode::Random => panic!("expected deterministic mode"),
}
}
#[test]
fn empty_domain_label_variant_spec_does_not_panic() {
let fx = det_factory(0x07);
let v = fx.get_or_init("", "", b"", "", |_rng| 99u8);
assert_eq!(*v, 99);
}
#[test]
fn unicode_label_and_variant_work() {
let fx = det_factory(0x08);
let v = fx.get_or_init(
"domain:unicode",
"日本語ラベル",
b"spec",
"変体",
|_rng| 77u16,
);
assert_eq!(*v, 77);
}
#[test]
fn very_long_spec_bytes_work() {
let fx = det_factory(0x09);
let big_spec = vec![0xFFu8; 10_000];
let v = fx.get_or_init("domain:bigspec", "label", &big_spec, "good", |_rng| 55u32);
assert_eq!(*v, 55);
}
#[test]
fn different_domains_produce_different_values() {
let fx = det_factory(0x0A);
let spec = b"same-spec";
let a = fx.get_or_init("domain:a", "label", spec, "good", seed_u64_from_bytes);
let b = fx.get_or_init("domain:b", "label", spec, "good", seed_u64_from_bytes);
assert_ne!(*a, *b);
}
#[test]
fn different_labels_produce_different_values() {
let fx = det_factory(0x0B);
let make = |label: &str| -> Arc<u64> {
fx.get_or_init("domain:lbl", label, b"spec", "good", seed_u64_from_bytes)
};
assert_ne!(*make("alpha"), *make("beta"));
}
#[test]
fn different_variants_produce_different_values() {
let fx1 = det_factory(0x0C);
let fx2 = det_factory(0x0C);
let a = fx1.get_or_init("domain:var", "label", b"spec", "good", seed_u64_from_bytes);
let b = fx2.get_or_init("domain:var", "label", b"spec", "other", seed_u64_from_bytes);
assert_ne!(*a, *b);
}
#[test]
fn seed_from_env_value_empty_string_is_ok() {
assert!(Seed::from_env_value("").is_ok());
}
#[test]
fn seed_from_env_value_exactly_64_hex_chars() {
let hex = "a".repeat(64);
let result = Seed::from_env_value(&hex);
assert!(result.is_ok());
}
#[test]
fn seed_from_env_value_64_chars_invalid_hex_is_err() {
let mut bad = "0".repeat(63);
bad.push('g');
let result = Seed::from_env_value(&bad);
assert!(result.is_err());
}
#[test]
fn seed_from_env_value_with_0x_prefix() {
let hex = format!("0x{}", "b".repeat(64));
let result = Seed::from_env_value(&hex);
assert!(result.is_ok());
}
#[test]
fn factory_debug_includes_cache_size() {
let fx = det_factory(0x10);
let dbg = format!("{:?}", fx);
assert!(dbg.contains("Factory"));
assert!(dbg.contains("cache_size"));
}
#[test]
fn seed_debug_never_leaks_bytes() {
let seed = Seed::new([0xFF; 32]);
let dbg = format!("{:?}", seed);
assert!(dbg.contains("redacted"));
assert!(!dbg.to_lowercase().contains("ff"));
}