use std::sync::OnceLock;
pub const DEFAULT_TEST_SEED: u64 = 42;
pub const DEFAULT_PROPTEST_SEED: u64 = 0xdeadbeef;
pub const DEFAULT_BENCH_SEED: u64 = 12345;
static TEST_SEED: OnceLock<u64> = OnceLock::new();
static BENCH_SEED: OnceLock<u64> = OnceLock::new();
pub fn get_test_seed() -> u64 {
*TEST_SEED.get_or_init(|| {
std::env::var("PRESENTAR_TEST_SEED")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_TEST_SEED)
})
}
pub fn get_bench_seed() -> u64 {
*BENCH_SEED.get_or_init(|| {
std::env::var("PRESENTAR_BENCH_SEED")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_BENCH_SEED)
})
}
#[derive(Clone, Debug)]
pub struct DeterministicRng {
state: u64,
}
impl DeterministicRng {
pub fn new(seed: u64) -> Self {
Self { state: seed }
}
pub fn from_test_seed() -> Self {
Self::new(get_test_seed())
}
pub fn from_bench_seed() -> Self {
Self::new(get_bench_seed())
}
pub fn next_u64(&mut self) -> u64 {
self.state ^= self.state << 13;
self.state ^= self.state >> 7;
self.state ^= self.state << 17;
self.state
}
pub fn next_f64(&mut self) -> f64 {
(self.next_u64() as f64) / (u64::MAX as f64)
}
pub fn next_f64_range(&mut self, min: f64, max: f64) -> f64 {
min + self.next_f64() * (max - min)
}
pub fn reset(&mut self, seed: u64) {
self.state = seed;
}
}
pub fn deterministic_rng() -> DeterministicRng {
DeterministicRng::from_test_seed()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deterministic_rng_reproducible() {
let mut rng1 = DeterministicRng::new(42);
let mut rng2 = DeterministicRng::new(42);
for _ in 0..100 {
assert_eq!(rng1.next_u64(), rng2.next_u64());
}
}
#[test]
fn test_f64_range() {
let mut rng = DeterministicRng::new(42);
for _ in 0..100 {
let v = rng.next_f64_range(0.0, 100.0);
assert!(v >= 0.0 && v < 100.0);
}
}
#[test]
fn test_seed_from_env() {
let seed = get_test_seed();
assert_eq!(seed, DEFAULT_TEST_SEED);
}
#[test]
fn test_default_constants() {
assert_eq!(DEFAULT_TEST_SEED, 42);
assert_eq!(DEFAULT_PROPTEST_SEED, 0xdeadbeef);
assert_eq!(DEFAULT_BENCH_SEED, 12345);
}
#[test]
fn test_get_bench_seed() {
let seed = get_bench_seed();
assert_eq!(seed, DEFAULT_BENCH_SEED);
}
#[test]
fn test_deterministic_rng_from_test_seed() {
let mut rng = DeterministicRng::from_test_seed();
let val1 = rng.next_u64();
rng.reset(get_test_seed());
let val2 = rng.next_u64();
assert_eq!(val1, val2);
}
#[test]
fn test_deterministic_rng_from_bench_seed() {
let mut rng = DeterministicRng::from_bench_seed();
let _val = rng.next_u64();
}
#[test]
fn test_next_f64() {
let mut rng = DeterministicRng::new(12345);
for _ in 0..100 {
let val = rng.next_f64();
assert!(val >= 0.0 && val < 1.0);
}
}
#[test]
fn test_next_f64_range_negative() {
let mut rng = DeterministicRng::new(42);
for _ in 0..100 {
let val = rng.next_f64_range(-50.0, 50.0);
assert!(val >= -50.0 && val < 50.0);
}
}
#[test]
fn test_reset() {
let mut rng = DeterministicRng::new(42);
let val1 = rng.next_u64();
let val2 = rng.next_u64();
rng.reset(42);
let val3 = rng.next_u64();
let val4 = rng.next_u64();
assert_eq!(val1, val3);
assert_eq!(val2, val4);
}
#[test]
fn test_deterministic_rng_debug() {
let rng = DeterministicRng::new(42);
let debug = format!("{:?}", rng);
assert!(debug.contains("DeterministicRng"));
}
#[test]
fn test_deterministic_rng_clone() {
let mut rng1 = DeterministicRng::new(42);
let _ = rng1.next_u64();
let rng2 = rng1.clone();
assert_eq!(rng1.next_u64(), rng2.clone().next_u64());
}
#[test]
fn test_deterministic_rng_different_seeds() {
let mut rng1 = DeterministicRng::new(1);
let mut rng2 = DeterministicRng::new(2);
assert_ne!(rng1.next_u64(), rng2.next_u64());
}
#[test]
fn test_deterministic_rng_function() {
let mut rng = deterministic_rng();
let _val = rng.next_u64();
}
#[test]
fn test_next_u64_not_zero() {
let mut rng = DeterministicRng::new(42);
for _ in 0..10 {
rng.next_u64();
}
assert_ne!(rng.next_u64(), 0);
}
#[test]
fn test_deterministic_rng_zero_seed() {
let mut rng = DeterministicRng::new(0);
let val = rng.next_u64();
assert_eq!(val, 0);
}
#[test]
fn test_deterministic_rng_max_seed() {
let mut rng = DeterministicRng::new(u64::MAX);
let _val = rng.next_u64();
}
}