mod common;
use common::{byte_frequency_chi_squared, runs_test_statistic};
mod tier1_stats {
use super::*;
use mod_rand::tier1::Xoshiro256;
#[test]
fn byte_frequency_passes_chi_squared() {
let mut rng = Xoshiro256::seed_from_u64(0xC0FFEE);
let mut buf = vec![0u8; 1 << 20];
rng.fill_bytes(&mut buf);
let chi = byte_frequency_chi_squared(&buf);
assert!(chi < 500.0, "tier1 byte-frequency chi-squared = {chi}");
}
#[test]
fn runs_test_within_bounds() {
let mut rng = Xoshiro256::seed_from_u64(0x1234_5678);
let mut buf = vec![0u8; 1 << 18];
rng.fill_bytes(&mut buf);
let z = runs_test_statistic(&buf);
assert!(
z.abs() < 6.0,
"tier1 runs-test |z| = {} (>6σ implies stream is degenerate)",
z.abs()
);
}
#[test]
fn low_byte_of_u64_uniform() {
let mut rng = Xoshiro256::seed_from_u64(7);
let samples = 1_000_000;
let mut counts = [0u32; 256];
for _ in 0..samples {
counts[(rng.next_u64() & 0xFF) as usize] += 1;
}
let n = samples as f64;
let expected = n / 256.0;
let chi: f64 = counts
.iter()
.map(|&c| {
let diff = c as f64 - expected;
diff * diff / expected
})
.sum();
assert!(chi < 500.0, "low-byte chi-squared {chi}");
}
#[test]
fn high_byte_of_u64_uniform() {
let mut rng = Xoshiro256::seed_from_u64(13);
let samples = 1_000_000;
let mut counts = [0u32; 256];
for _ in 0..samples {
counts[(rng.next_u64() >> 56) as usize] += 1;
}
let n = samples as f64;
let expected = n / 256.0;
let chi: f64 = counts
.iter()
.map(|&c| {
let diff = c as f64 - expected;
diff * diff / expected
})
.sum();
assert!(chi < 500.0, "high-byte chi-squared {chi}");
}
#[test]
fn jump_produces_independent_stream() {
let mut a = Xoshiro256::seed_from_u64(1);
let mut b = a.clone();
b.jump();
let mut coincidences = 0;
for _ in 0..4096 {
if a.next_u64() == b.next_u64() {
coincidences += 1;
}
}
assert!(
coincidences == 0,
"jump_produces_independent_stream: {coincidences} unexpected matches"
);
}
#[test]
fn long_jump_produces_independent_stream() {
let mut a = Xoshiro256::seed_from_u64(1);
let mut b = a.clone();
b.long_jump();
let mut coincidences = 0;
for _ in 0..4096 {
if a.next_u64() == b.next_u64() {
coincidences += 1;
}
}
assert!(coincidences == 0, "long_jump matches: {coincidences}");
}
#[test]
fn next_f64_uniform_over_unit_interval() {
let mut rng = Xoshiro256::seed_from_u64(2026);
let samples = 1_000_000;
let mut buckets = [0u32; 10];
for _ in 0..samples {
let f = rng.next_f64();
let idx = ((f * 10.0) as usize).min(9);
buckets[idx] += 1;
}
let n = samples as f64;
let expected = n / 10.0;
let chi: f64 = buckets
.iter()
.map(|&c| {
let diff = c as f64 - expected;
diff * diff / expected
})
.sum();
assert!(chi < 50.0, "next_f64 decile chi {chi}");
}
}
#[cfg(feature = "tier2")]
mod tier2_stats {
use mod_rand::tier2;
use std::collections::HashSet;
#[test]
fn one_million_unique_u64_distinct() {
let n = 1_000_000;
let mut set = HashSet::with_capacity(n);
for _ in 0..n {
assert!(set.insert(tier2::unique_u64()), "collision at scale");
}
assert_eq!(set.len(), n);
}
#[test]
fn one_million_unique_names_distinct() {
let n = 1_000_000;
let mut set = HashSet::with_capacity(n);
for _ in 0..n {
assert!(set.insert(tier2::unique_name(16)));
}
}
#[test]
fn alphabet_distribution_uniform() {
const ALPHABET: &[u8; 32] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
let samples = 200_000;
let mut counts = [0u32; 32];
for _ in 0..samples {
let c = tier2::unique_base32(1).chars().next().unwrap();
let idx = ALPHABET
.iter()
.position(|&b| b as char == c)
.expect("Crockford char");
counts[idx] += 1;
}
let n = samples as f64;
let expected = n / 32.0;
let chi: f64 = counts
.iter()
.map(|&c| {
let diff = c as f64 - expected;
diff * diff / expected
})
.sum();
assert!(chi < 100.0, "tier2 base32 chi-squared {chi}");
}
}
#[cfg(feature = "tier3")]
mod tier3_stats {
use super::*;
use mod_rand::tier3;
#[test]
fn byte_frequency_passes_chi_squared() {
let buf = tier3::random_bytes(1 << 20).unwrap();
let chi = byte_frequency_chi_squared(&buf);
assert!(chi < 500.0, "tier3 byte-frequency chi-squared = {chi}");
}
#[test]
fn runs_test_within_bounds() {
let buf = tier3::random_bytes(1 << 18).unwrap();
let z = runs_test_statistic(&buf);
assert!(z.abs() < 6.0, "tier3 runs-test |z| = {}", z.abs());
}
#[test]
fn stress_ten_thousand_calls() {
for _ in 0..10_000 {
let mut buf = [0u8; 32];
tier3::fill_bytes(&mut buf).unwrap();
}
}
#[test]
fn tokens_are_distinct() {
use std::collections::HashSet;
let mut set = HashSet::with_capacity(10_000);
for _ in 0..10_000 {
assert!(set.insert(tier3::random_hex(16).unwrap()));
}
}
}