Skip to content

Commit a04b6f3

Browse files
committed
Cleanup common tests
Signed-off-by: Joe Richey <[email protected]>
1 parent f345775 commit a04b6f3

File tree

8 files changed

+151
-139
lines changed

8 files changed

+151
-139
lines changed

.github/workflows/tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ jobs:
3838
toolchain: ${{ matrix.toolchain }}
3939
- uses: Swatinem/rust-cache@v2
4040
- run: cargo test
41-
# Make sure enabling the std and custom features don't break anything
42-
- run: cargo test --features=std,custom
41+
# Ensure enabling features works, and run feature-specific tests.
42+
- run: cargo test --features=std,custom,rdrand
4343
- run: cargo test --features=linux_disable_fallback
4444
- if: ${{ matrix.toolchain == 'nightly' }}
4545
run: cargo test --benches
@@ -258,8 +258,8 @@ jobs:
258258
- name: Test (Safari)
259259
if: runner.os == 'macOS'
260260
run: wasm-pack test --headless --safari --features=js,test-in-browser
261-
- name: Test (custom getrandom)
262-
run: wasm-pack test --node --features=custom
261+
- name: Test (custom getrandom, no unit tests)
262+
run: wasm-pack test --node --features=custom --test=custom
263263
- name: Test (JS overrides custom)
264264
run: wasm-pack test --node --features=custom,js
265265

src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ mod util;
224224
mod custom;
225225
#[cfg(feature = "std")]
226226
mod error_impls;
227+
#[cfg(all(
228+
any(target_env = "sgx", feature = "rdrand"),
229+
any(target_arch = "x86_64", target_arch = "x86"),
230+
))]
231+
mod rdrand;
227232

228233
pub use crate::error::Error;
229234

@@ -330,10 +335,10 @@ cfg_if! {
330335
} else if #[cfg(windows)] {
331336
#[path = "windows.rs"] mod imp;
332337
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
333-
#[path = "rdrand.rs"] mod imp;
338+
use rdrand as imp;
334339
} else if #[cfg(all(feature = "rdrand",
335340
any(target_arch = "x86_64", target_arch = "x86")))] {
336-
#[path = "rdrand.rs"] mod imp;
341+
use rdrand as imp;
337342
} else if #[cfg(all(feature = "js",
338343
any(target_arch = "wasm32", target_arch = "wasm64"),
339344
target_os = "unknown"))] {
@@ -404,3 +409,6 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error
404409
// since it returned `Ok`.
405410
Ok(unsafe { slice_assume_init_mut(dest) })
406411
}
412+
413+
#[cfg(test)]
414+
pub(crate) mod tests;

src/rdrand.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn is_rdrand_good() -> bool {
9393
unsafe { self_test() }
9494
}
9595

96+
#[allow(dead_code)]
9697
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
9798
static RDRAND_GOOD: LazyBool = LazyBool::new();
9899
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
@@ -121,3 +122,8 @@ unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
121122
}
122123
Some(())
123124
}
125+
126+
#[cfg(test)]
127+
mod tests {
128+
crate::tests::define_tests!(super::getrandom_inner as fn(&mut _) -> _);
129+
}

src/tests.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//! Common tests and testing utilities
2+
extern crate std;
3+
4+
use crate::Error;
5+
use std::{mem::MaybeUninit, sync::mpsc, thread, vec, vec::Vec};
6+
7+
#[cfg(feature = "test-in-browser")]
8+
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
9+
10+
fn num_diff_bits(s1: &[u8], s2: &[u8]) -> usize {
11+
assert_eq!(s1.len(), s2.len());
12+
s1.iter()
13+
.zip(s2.iter())
14+
.map(|(a, b)| (a ^ b).count_ones() as usize)
15+
.sum()
16+
}
17+
18+
pub(crate) trait FillFn: Copy + Send + 'static {
19+
fn make_vec(self, len: usize) -> Vec<u8>;
20+
}
21+
impl FillFn for fn(&mut [u8]) -> Result<(), Error> {
22+
fn make_vec(self, len: usize) -> Vec<u8> {
23+
let mut v = vec![0; len];
24+
self(&mut v).unwrap();
25+
v
26+
}
27+
}
28+
impl FillFn for fn(&mut [MaybeUninit<u8>]) -> Result<(), Error> {
29+
fn make_vec(self, len: usize) -> Vec<u8> {
30+
let mut v = Vec::with_capacity(len);
31+
self(v.spare_capacity_mut()).unwrap();
32+
unsafe { v.set_len(len) };
33+
v
34+
}
35+
}
36+
impl FillFn for fn(&mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
37+
fn make_vec(self, len: usize) -> Vec<u8> {
38+
let mut v = Vec::with_capacity(len);
39+
let ret = self(v.spare_capacity_mut()).unwrap();
40+
assert_eq!(ret.len(), len);
41+
assert_eq!(ret.as_ptr(), v.as_ptr());
42+
unsafe { v.set_len(len) };
43+
v
44+
}
45+
}
46+
47+
// For calls of size `len`, count the number of bits which differ between calls
48+
// and check that between 3 and 5 bits per byte differ. Probability of failure:
49+
// ~ 10^(-30) = 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256]
50+
pub(crate) fn check_bits(len: usize, fill: impl FillFn) {
51+
let mut num_bytes = 0;
52+
let mut diff_bits = 0;
53+
while num_bytes < 256 {
54+
let v1 = fill.make_vec(len);
55+
let v2 = fill.make_vec(len);
56+
57+
num_bytes += len;
58+
diff_bits += num_diff_bits(&v1, &v2);
59+
}
60+
61+
// When the custom feature is enabled, don't check RNG quality.
62+
assert!(diff_bits > 3 * num_bytes);
63+
assert!(diff_bits < 5 * num_bytes);
64+
}
65+
66+
pub(crate) fn check_multithreading(fill: impl FillFn) {
67+
let mut txs = vec![];
68+
for _ in 0..20 {
69+
let (tx, rx) = mpsc::channel();
70+
txs.push(tx);
71+
72+
thread::spawn(move || {
73+
// wait until all the tasks are ready to go.
74+
rx.recv().unwrap();
75+
for _ in 0..100 {
76+
check_bits(1000, fill);
77+
thread::yield_now();
78+
}
79+
});
80+
}
81+
82+
// start all the tasks
83+
for tx in txs.iter() {
84+
tx.send(()).unwrap();
85+
}
86+
}
87+
88+
macro_rules! define_tests {
89+
($fill:expr) => {
90+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
91+
use wasm_bindgen_test::wasm_bindgen_test as test;
92+
93+
#[test]
94+
fn fill_zero() {
95+
crate::tests::FillFn::make_vec($fill, 0);
96+
}
97+
#[test]
98+
fn fill_small() {
99+
for len in 1..=64 {
100+
crate::tests::check_bits(len, $fill);
101+
}
102+
}
103+
#[test]
104+
fn fill_large() {
105+
crate::tests::check_bits(1_000, $fill);
106+
}
107+
#[test]
108+
fn fill_huge() {
109+
crate::tests::check_bits(1_000_000, $fill);
110+
}
111+
// On WASM, the thread API always fails/panics.
112+
#[test]
113+
#[cfg_attr(target_family = "wasm", ignore)]
114+
fn multithreading() {
115+
crate::tests::check_multithreading($fill)
116+
}
117+
};
118+
}
119+
pub(crate) use define_tests;
120+
121+
mod init {
122+
super::define_tests!(crate::getrandom as fn(&mut _) -> _);
123+
}
124+
mod uninit {
125+
super::define_tests!(crate::getrandom_uninit as fn(&mut _) -> Result<&mut _, _>);
126+
}

src/use_file.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,8 @@ impl<F: FnMut()> Drop for DropGuard<F> {
174174
self.0()
175175
}
176176
}
177+
178+
#[cfg(test)]
179+
mod tests {
180+
crate::tests::define_tests!(super::getrandom_inner as fn(&mut _) -> _);
181+
}

tests/common/mod.rs

Lines changed: 0 additions & 100 deletions
This file was deleted.

tests/normal.rs

Lines changed: 0 additions & 11 deletions
This file was deleted.

tests/rdrand.rs

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)