Skip to content

Commit 2ec38ad

Browse files
authored
Merge pull request #304 from rust-random/rng_tests
This PR adds some tests which make sure calls to getrandom (for both small and large buffers) "look" random. While we could certainly add more complicated randomness tests, these simple tests are: - Very easy to understand - Don't require any external crates - Makes sure we aren't doing something obviously stupid like - forgetting [these lines](https://github.com/rust-random/getrandom/blob/bd0654fe70980583e51573e755bafa3b2f8342d9/src/rdrand.rs#L91-L95) - failing to initialize every other byte - initializing some significant fraction of bytes with a constant As this tests all buffer sizes from 1 to 64, it also fixes #290.
2 parents 97c1789 + b893cb9 commit 2ec38ad

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

tests/common/mod.rs

+39-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ fn test_zero() {
1212
getrandom_impl(&mut [0u8; 0]).unwrap();
1313
}
1414

15+
// Return the number of bits in which s1 and s2 differ
16+
#[cfg(not(feature = "custom"))]
17+
fn num_diff_bits(s1: &[u8], s2: &[u8]) -> usize {
18+
assert_eq!(s1.len(), s2.len());
19+
s1.iter()
20+
.zip(s2.iter())
21+
.map(|(a, b)| (a ^ b).count_ones() as usize)
22+
.sum()
23+
}
24+
25+
// Tests the quality of calling getrandom on two large buffers
1526
#[test]
1627
#[cfg(not(feature = "custom"))]
1728
fn test_diff() {
@@ -21,13 +32,35 @@ fn test_diff() {
2132
let mut v2 = [0u8; 1000];
2233
getrandom_impl(&mut v2).unwrap();
2334

24-
let mut n_diff_bits = 0;
25-
for i in 0..v1.len() {
26-
n_diff_bits += (v1[i] ^ v2[i]).count_ones();
27-
}
35+
// Between 3.5 and 4.5 bits per byte should differ. Probability of failure:
36+
// ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500]
37+
let d = num_diff_bits(&v1, &v2);
38+
assert!(d > 3500);
39+
assert!(d < 4500);
40+
}
2841

29-
// Check at least 1 bit per byte differs. p(failure) < 1e-1000 with random input.
30-
assert!(n_diff_bits >= v1.len() as u32);
42+
// Tests the quality of calling getrandom repeatedly on small buffers
43+
#[test]
44+
#[cfg(not(feature = "custom"))]
45+
fn test_small() {
46+
// For each buffer size, get at least 256 bytes and check that between
47+
// 3 and 5 bits per byte differ. Probability of failure:
48+
// ~ 2^(-91) = 64 * 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256]
49+
for size in 1..=64 {
50+
let mut num_bytes = 0;
51+
let mut diff_bits = 0;
52+
while num_bytes < 256 {
53+
let mut s1 = vec![0u8; size];
54+
getrandom_impl(&mut s1).unwrap();
55+
let mut s2 = vec![0u8; size];
56+
getrandom_impl(&mut s2).unwrap();
57+
58+
num_bytes += size;
59+
diff_bits += num_diff_bits(&s1, &s2);
60+
}
61+
assert!(diff_bits > 3 * num_bytes);
62+
assert!(diff_bits < 5 * num_bytes);
63+
}
3164
}
3265

3366
#[test]

0 commit comments

Comments
 (0)