ambient-randomness
Level: warn · Article: Tests
What it checks
rand::random(), rand::thread_rng(), rand::rng(), StdRng::from_entropy()
and friends, anywhere but main. A global generator makes the code
correct on average and impossible to replay when it is not.
Don’t
#![allow(unused)]
fn main() {
fn pick_winner(entries: &[Entry]) -> &Entry {
&entries[rand::thread_rng().gen_range(0..entries.len())]
}
}
The bug report says “the same person won twice”. You cannot reproduce it.
Do
fn pick_winner<'a>(entries: &'a [Entry], rng: &mut impl Rng) -> &'a Entry {
&entries[rng.gen_range(0..entries.len())]
}
fn main() {
// one generator, seeded once, handed down to everything that draws
let mut rng = StdRng::from_entropy();
Raffle::open(&mut rng).run();
}
#[test]
fn the_draw_is_reproducible() {
// the same seed, the same winner, every run
let entries = [Entry::new("ada"), Entry::new("grace")];
let mut rng = StdRng::seed_from_u64(42);
assert_eq!(pick_winner(&entries, &mut rng).name(), "grace");
}
Silence it
#![allow(unused)]
fn main() {
// rabot: allow(ambient-randomness) jitter on a retry delay; the exact value never matters
let jitter = rand::random::<u64>() % 50;
}