Skip to content

Commit

Permalink
Cleanup common tests
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Richey <[email protected]>
  • Loading branch information
josephlr committed Jun 20, 2024
1 parent f345775 commit a04b6f3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 139 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ jobs:
toolchain: ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2
- run: cargo test
# Make sure enabling the std and custom features don't break anything
- run: cargo test --features=std,custom
# Ensure enabling features works, and run feature-specific tests.
- run: cargo test --features=std,custom,rdrand
- run: cargo test --features=linux_disable_fallback
- if: ${{ matrix.toolchain == 'nightly' }}
run: cargo test --benches
Expand Down Expand Up @@ -258,8 +258,8 @@ jobs:
- name: Test (Safari)
if: runner.os == 'macOS'
run: wasm-pack test --headless --safari --features=js,test-in-browser
- name: Test (custom getrandom)
run: wasm-pack test --node --features=custom
- name: Test (custom getrandom, no unit tests)
run: wasm-pack test --node --features=custom --test=custom
- name: Test (JS overrides custom)
run: wasm-pack test --node --features=custom,js

Expand Down
12 changes: 10 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ mod util;
mod custom;
#[cfg(feature = "std")]
mod error_impls;
#[cfg(all(
any(target_env = "sgx", feature = "rdrand"),
any(target_arch = "x86_64", target_arch = "x86"),
))]
mod rdrand;

pub use crate::error::Error;

Expand Down Expand Up @@ -330,10 +335,10 @@ cfg_if! {
} else if #[cfg(windows)] {
#[path = "windows.rs"] mod imp;
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
#[path = "rdrand.rs"] mod imp;
use rdrand as imp;
} else if #[cfg(all(feature = "rdrand",
any(target_arch = "x86_64", target_arch = "x86")))] {
#[path = "rdrand.rs"] mod imp;
use rdrand as imp;
} else if #[cfg(all(feature = "js",
any(target_arch = "wasm32", target_arch = "wasm64"),
target_os = "unknown"))] {
Expand Down Expand Up @@ -404,3 +409,6 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error
// since it returned `Ok`.
Ok(unsafe { slice_assume_init_mut(dest) })
}

#[cfg(test)]
pub(crate) mod tests;
6 changes: 6 additions & 0 deletions src/rdrand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fn is_rdrand_good() -> bool {
unsafe { self_test() }
}

#[allow(dead_code)]
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
static RDRAND_GOOD: LazyBool = LazyBool::new();
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
Expand Down Expand Up @@ -121,3 +122,8 @@ unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
}
Some(())
}

#[cfg(test)]
mod tests {
crate::tests::define_tests!(super::getrandom_inner as fn(&mut _) -> _);
}
126 changes: 126 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//! Common tests and testing utilities
extern crate std;

use crate::Error;
use std::{mem::MaybeUninit, sync::mpsc, thread, vec, vec::Vec};

#[cfg(feature = "test-in-browser")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

fn num_diff_bits(s1: &[u8], s2: &[u8]) -> usize {
assert_eq!(s1.len(), s2.len());
s1.iter()
.zip(s2.iter())
.map(|(a, b)| (a ^ b).count_ones() as usize)
.sum()
}

pub(crate) trait FillFn: Copy + Send + 'static {
fn make_vec(self, len: usize) -> Vec<u8>;
}
impl FillFn for fn(&mut [u8]) -> Result<(), Error> {
fn make_vec(self, len: usize) -> Vec<u8> {
let mut v = vec![0; len];
self(&mut v).unwrap();
v
}
}
impl FillFn for fn(&mut [MaybeUninit<u8>]) -> Result<(), Error> {
fn make_vec(self, len: usize) -> Vec<u8> {
let mut v = Vec::with_capacity(len);
self(v.spare_capacity_mut()).unwrap();
unsafe { v.set_len(len) };
v
}
}
impl FillFn for fn(&mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
fn make_vec(self, len: usize) -> Vec<u8> {
let mut v = Vec::with_capacity(len);
let ret = self(v.spare_capacity_mut()).unwrap();
assert_eq!(ret.len(), len);
assert_eq!(ret.as_ptr(), v.as_ptr());
unsafe { v.set_len(len) };
v
}
}

// For calls of size `len`, count the number of bits which differ between calls
// and check that between 3 and 5 bits per byte differ. Probability of failure:
// ~ 10^(-30) = 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256]
pub(crate) fn check_bits(len: usize, fill: impl FillFn) {
let mut num_bytes = 0;
let mut diff_bits = 0;
while num_bytes < 256 {
let v1 = fill.make_vec(len);
let v2 = fill.make_vec(len);

num_bytes += len;
diff_bits += num_diff_bits(&v1, &v2);
}

// When the custom feature is enabled, don't check RNG quality.
assert!(diff_bits > 3 * num_bytes);
assert!(diff_bits < 5 * num_bytes);
}

pub(crate) fn check_multithreading(fill: impl FillFn) {
let mut txs = vec![];
for _ in 0..20 {
let (tx, rx) = mpsc::channel();
txs.push(tx);

thread::spawn(move || {
// wait until all the tasks are ready to go.
rx.recv().unwrap();
for _ in 0..100 {
check_bits(1000, fill);
thread::yield_now();
}
});
}

// start all the tasks
for tx in txs.iter() {
tx.send(()).unwrap();
}
}

macro_rules! define_tests {
($fill:expr) => {
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
fn fill_zero() {
crate::tests::FillFn::make_vec($fill, 0);
}
#[test]
fn fill_small() {
for len in 1..=64 {
crate::tests::check_bits(len, $fill);
}
}
#[test]
fn fill_large() {
crate::tests::check_bits(1_000, $fill);
}
#[test]
fn fill_huge() {
crate::tests::check_bits(1_000_000, $fill);
}
// On WASM, the thread API always fails/panics.
#[test]
#[cfg_attr(target_family = "wasm", ignore)]
fn multithreading() {
crate::tests::check_multithreading($fill)
}
};
}
pub(crate) use define_tests;

mod init {
super::define_tests!(crate::getrandom as fn(&mut _) -> _);
}
mod uninit {
super::define_tests!(crate::getrandom_uninit as fn(&mut _) -> Result<&mut _, _>);
}
5 changes: 5 additions & 0 deletions src/use_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,8 @@ impl<F: FnMut()> Drop for DropGuard<F> {
self.0()
}
}

#[cfg(test)]
mod tests {
crate::tests::define_tests!(super::getrandom_inner as fn(&mut _) -> _);
}
100 changes: 0 additions & 100 deletions tests/common/mod.rs

This file was deleted.

11 changes: 0 additions & 11 deletions tests/normal.rs

This file was deleted.

22 changes: 0 additions & 22 deletions tests/rdrand.rs

This file was deleted.

0 comments on commit a04b6f3

Please sign in to comment.