Skip to content

Commit 61ac0e1

Browse files
committed
Move custom impl tests into a separate helper crate
1 parent 2146a92 commit 61ac0e1

6 files changed

Lines changed: 127 additions & 121 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ jobs:
269269
targets: riscv32i-unknown-none-elf
270270
- uses: Swatinem/rust-cache@v2
271271
- env:
272-
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
272+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="unsupported"
273273
run: cargo build --target riscv32i-unknown-none-elf
274274

275275
unsupported:

.github/workflows/tests.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,21 @@ jobs:
7878
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
7979
run: cargo test --features=std,sys_rng
8080

81-
extern_impl:
82-
name: Extern Item Implementations
81+
custom_impl:
82+
name: Custom Implementations
8383
runs-on: ubuntu-24.04
8484
steps:
8585
- uses: actions/checkout@v6
8686
- uses: dtolnay/rust-toolchain@master
8787
with:
8888
toolchain: nightly
8989
- uses: Swatinem/rust-cache@v2
90+
- env:
91+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
92+
run: cargo test
9093
- env:
9194
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="extern_impl"
92-
run: cargo test --features=std
95+
run: cargo test
9396

9497
ios:
9598
name: iOS Simulator

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
**/*.rs.bk
33
nopanic_check/Cargo.lock
44
nopanic_check/target/
5+
custom_impl_test/Cargo.lock
6+
custom_impl_test/target/

custom_impl_test/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "custom_impl_test"
3+
description = "Helper crate for testing custom implementations"
4+
version = "0.1.0"
5+
edition = "2024"
6+
publish = false
7+
8+
[workspace]
9+
10+
[dependencies]
11+
getrandom = { path = ".." }
12+
13+
[lints.rust.unexpected_cfgs]
14+
level = "warn"
15+
check-cfg = [
16+
'cfg(getrandom_backend, values("custom", "extern_impl"))',
17+
]

custom_impl_test/src/lib.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use core::mem::MaybeUninit;
2+
use getrandom::Error;
3+
4+
/// Chosen by fair dice roll.
5+
const SEED: u64 = 0x9095_810F_1B2B_E175;
6+
7+
struct Xoshiro128PlusPlus {
8+
s: [u32; 4],
9+
}
10+
11+
impl Xoshiro128PlusPlus {
12+
fn new(mut seed: u64) -> Self {
13+
const PHI: u64 = 0x9e3779b97f4a7c15;
14+
let mut s = [0u32; 4];
15+
for val in s.iter_mut() {
16+
seed = seed.wrapping_add(PHI);
17+
let mut z = seed;
18+
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
19+
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
20+
z = z ^ (z >> 31);
21+
*val = z as u32;
22+
}
23+
Self { s }
24+
}
25+
26+
fn next_u32(&mut self) -> u32 {
27+
let res = self.s[0]
28+
.wrapping_add(self.s[3])
29+
.rotate_left(7)
30+
.wrapping_add(self.s[0]);
31+
32+
let t = self.s[1] << 9;
33+
34+
self.s[2] ^= self.s[0];
35+
self.s[3] ^= self.s[1];
36+
self.s[1] ^= self.s[2];
37+
self.s[0] ^= self.s[3];
38+
39+
self.s[2] ^= t;
40+
41+
self.s[3] = self.s[3].rotate_left(11);
42+
43+
res
44+
}
45+
}
46+
47+
pub fn custom_impl(dst: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
48+
let mut rng = Xoshiro128PlusPlus::new(SEED);
49+
50+
let mut chunks = dst.chunks_exact_mut(4);
51+
for chunk in &mut chunks {
52+
let val = rng.next_u32();
53+
let dst_ptr = chunk.as_mut_ptr().cast::<u32>();
54+
unsafe { core::ptr::write_unaligned(dst_ptr, val) };
55+
}
56+
let rem = chunks.into_remainder();
57+
if !rem.is_empty() {
58+
let val = rng.next_u32();
59+
let src_ptr = &val as *const u32 as *const MaybeUninit<u8>;
60+
assert!(rem.len() <= 4);
61+
unsafe { core::ptr::copy(src_ptr, rem.as_mut_ptr(), rem.len()) };
62+
}
63+
Ok(())
64+
}
65+
66+
#[cfg(getrandom_backend = "custom")]
67+
#[unsafe(no_mangle)]
68+
unsafe extern "Rust" fn __getrandom_v03_custom(dst_ptr: *mut u8, len: usize) -> Result<(), Error> {
69+
let dst = unsafe { core::slice::from_raw_parts_mut(dst_ptr.cast(), len) };
70+
custom_impl(dst)
71+
}
72+
73+
#[cfg(getrandom_backend = "extern_impl")]
74+
#[getrandom::implementation::fill_uninit]
75+
fn my_fill_uninit_implementation(dst: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
76+
custom_impl(dst)
77+
}
78+
79+
#[test]
80+
fn test_custom_fill() {
81+
let mut buf1 = [0u8; 256];
82+
getrandom::fill(&mut buf1).unwrap();
83+
84+
let mut buf2 = [0u8; 256];
85+
custom_impl(unsafe { core::slice::from_raw_parts_mut(buf2.as_mut_ptr().cast(), buf2.len()) })
86+
.unwrap();
87+
88+
assert_eq!(buf1, buf2);
89+
}
90+
91+
#[test]
92+
fn test_custom_u32() {
93+
let res = getrandom::u32().unwrap();
94+
assert_eq!(res, 0xEAD5_840A);
95+
}
96+
97+
#[test]
98+
fn test_custom_u64() {
99+
let res = getrandom::u64().unwrap();
100+
assert_eq!(res, 0xA856_FCC4_EAD5_840A);
101+
}

tests/mod.rs

Lines changed: 0 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -207,120 +207,3 @@ fn test_multithreading() {
207207
tx.send(()).unwrap();
208208
}
209209
}
210-
211-
#[cfg(getrandom_backend = "custom")]
212-
mod custom {
213-
use getrandom::Error;
214-
215-
struct Xoshiro128PlusPlus {
216-
s: [u32; 4],
217-
}
218-
219-
impl Xoshiro128PlusPlus {
220-
fn new(mut seed: u64) -> Self {
221-
const PHI: u64 = 0x9e3779b97f4a7c15;
222-
let mut s = [0u32; 4];
223-
for val in s.iter_mut() {
224-
seed = seed.wrapping_add(PHI);
225-
let mut z = seed;
226-
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
227-
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
228-
z = z ^ (z >> 31);
229-
*val = z as u32;
230-
}
231-
Self { s }
232-
}
233-
234-
fn next_u32(&mut self) -> u32 {
235-
let res = self.s[0]
236-
.wrapping_add(self.s[3])
237-
.rotate_left(7)
238-
.wrapping_add(self.s[0]);
239-
240-
let t = self.s[1] << 9;
241-
242-
self.s[2] ^= self.s[0];
243-
self.s[3] ^= self.s[1];
244-
self.s[1] ^= self.s[2];
245-
self.s[0] ^= self.s[3];
246-
247-
self.s[2] ^= t;
248-
249-
self.s[3] = self.s[3].rotate_left(11);
250-
251-
res
252-
}
253-
}
254-
255-
// This implementation uses current timestamp as a PRNG seed.
256-
//
257-
// WARNING: this custom implementation is for testing purposes ONLY!
258-
259-
#[unsafe(no_mangle)]
260-
unsafe extern "Rust" fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), Error> {
261-
use std::time::{SystemTime, UNIX_EPOCH};
262-
263-
assert_ne!(len, 0);
264-
265-
if len == 142 {
266-
return Err(Error::new_custom(142));
267-
}
268-
269-
let dest_u32 = dest.cast::<u32>();
270-
let ts = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
271-
let mut rng = Xoshiro128PlusPlus::new(ts.as_nanos() as u64);
272-
for i in 0..len / 4 {
273-
let val = rng.next_u32();
274-
unsafe { core::ptr::write_unaligned(dest_u32.add(i), val) };
275-
}
276-
if len % 4 != 0 {
277-
let start = 4 * (len / 4);
278-
for i in start..len {
279-
let val = rng.next_u32();
280-
unsafe { core::ptr::write_unaligned(dest.add(i), val as u8) };
281-
}
282-
}
283-
Ok(())
284-
}
285-
286-
// Test that enabling the custom feature indeed uses the custom implementation
287-
#[test]
288-
fn test_custom() {
289-
let mut buf = [0u8; 142];
290-
let res = getrandom::fill(&mut buf);
291-
assert!(res.is_err());
292-
}
293-
}
294-
295-
#[cfg(getrandom_backend = "extern_impl")]
296-
mod extern_item_impls {
297-
use core::mem::MaybeUninit;
298-
use getrandom::Error;
299-
300-
// This implementation for fill_uninit will always fail.
301-
//
302-
// WARNING: this custom implementation is for testing purposes ONLY!
303-
304-
#[getrandom::implementation::fill_uninit]
305-
fn my_fill_uninit_implementation(_dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
306-
Err(Error::new_custom(4))
307-
}
308-
309-
// This implementation returns a fixed value to demonstrate overriding defaults.
310-
//
311-
// WARNING: this custom implementation is for testing purposes ONLY!
312-
313-
#[getrandom::implementation::u32]
314-
fn my_u32_implementation() -> Result<u32, Error> {
315-
// Chosen by fair dice roll
316-
Ok(4)
317-
}
318-
319-
// Test that enabling the custom feature indeed uses the custom implementation
320-
#[test]
321-
fn test_extern_item_impls() {
322-
let mut buf = [0u8; 123];
323-
assert_eq!(getrandom::fill(&mut buf), Err(Error::new_custom(4)));
324-
assert_eq!(getrandom::u32(), Ok(4));
325-
}
326-
}

0 commit comments

Comments
 (0)