Skip to content

Commit 5ab8c6e

Browse files
committed
Test Linux fallback paths without use of cfg()s
This PR changes our Linux fallback tests to test the "real" fallback paths rather than using various `cfg()`s within the implementation. As these tests require being run sequentally and only work on Linux, they are configured to require manual invocation. Also renames `tests/mod.rs` to `tests/common.rs` to reuse our tests. Actually testing the netbsd fallback is harder, so that's best left for a future PR. Signed-off-by: Joe Richey <[email protected]>
1 parent b160ef6 commit 5ab8c6e

File tree

7 files changed

+67
-22
lines changed

7 files changed

+67
-22
lines changed

.github/workflows/tests.yml

+3-9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ jobs:
5353
targets: ${{ matrix.target }}
5454
- uses: Swatinem/rust-cache@v2
5555
- run: cargo test --target=${{ matrix.target }} --features=std
56+
- run: cargo test --test linux_force_fallback -- --test-threads 1
57+
- run: cargo test --test linux_no_fallback -- --test-threads 1
5658
- env:
5759
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
5860
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
@@ -61,18 +63,10 @@ jobs:
6163
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
6264
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
6365
run: cargo test --target=${{ matrix.target }} --features=std
64-
- env:
65-
RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback
66-
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback
67-
run: cargo test --features=std
68-
- env:
69-
RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback
70-
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback
71-
run: cargo test --features=std
7266
- env:
7367
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
7468
RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
75-
run: cargo test --features=std
69+
run: cargo test --target=${{ matrix.target }} --features=std
7670

7771
ios:
7872
name: iOS Simulator

CHANGELOG.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- `efi_rng` opt-in backend [#570]
1111
- `linux_raw` opt-in backend [#572]
1212
- `.cargo/config.toml` example in the crate-level docs [#591]
13-
- `getrandom_test_linux_without_fallback` configuration flag to test that file fallback
14-
is not triggered in the `linux_android_with_fallback` backend [#605]
13+
- Add tests for Linux fallback paths without hardcoding `cfg`s [#999]
1514

1615
### Changed
1716
- Remove `windows-targets` dependency and use [`raw-dylib`] directly [#627]
@@ -34,10 +33,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3433
[#597]: https://github.com/rust-random/getrandom/pull/597
3534
[#602]: https://github.com/rust-random/getrandom/pull/602
3635
[#603]: https://github.com/rust-random/getrandom/pull/603
37-
[#605]: https://github.com/rust-random/getrandom/pull/605
3836
[#610]: https://github.com/rust-random/getrandom/pull/610
3937
[#614]: https://github.com/rust-random/getrandom/pull/614
4038
[#627]: https://github.com/rust-random/getrandom/pull/627
39+
[#999]: https://github.com/rust-random/getrandom/pull/999
4140
[`raw-dylib`]: https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=link#dylib-versus-raw-dylib
4241

4342
## [0.3.1] - 2025-01-28

Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,17 @@ check-cfg = [
8484
'cfg(getrandom_backend, values("custom", "efi_rng", "rdrand", "rndr", "linux_getrandom", "linux_raw", "wasm_js"))',
8585
'cfg(getrandom_msan)',
8686
'cfg(getrandom_windows_legacy)',
87-
'cfg(getrandom_test_linux_fallback)',
88-
'cfg(getrandom_test_linux_without_fallback)',
8987
'cfg(getrandom_test_netbsd_fallback)',
9088
]
9189

90+
# Linux-specific fallback tests
91+
[[test]]
92+
name = "linux_force_fallback"
93+
test = false
94+
[[test]]
95+
name = "linux_no_fallback"
96+
test = false
97+
9298
[package.metadata.docs.rs]
9399
features = ["std"]
94100

src/backends/linux_android_with_fallback.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ fn init() -> NonNull<c_void> {
4141
let dangling_ptr = NonNull::dangling().as_ptr();
4242
// Check that `getrandom` syscall is supported by kernel
4343
let res = unsafe { getrandom_fn(dangling_ptr, 0, 0) };
44-
if cfg!(getrandom_test_linux_fallback) {
45-
NOT_AVAILABLE
46-
} else if res.is_negative() {
44+
if res.is_negative() {
4745
match util_libc::last_os_error().raw_os_error() {
4846
Some(libc::ENOSYS) => NOT_AVAILABLE, // No kernel support
4947
// The fallback on EPERM is intentionally not done on Android since this workaround
@@ -60,11 +58,6 @@ fn init() -> NonNull<c_void> {
6058
None => NOT_AVAILABLE,
6159
};
6260

63-
#[cfg(getrandom_test_linux_without_fallback)]
64-
if res_ptr == NOT_AVAILABLE {
65-
panic!("Fallback is triggered with enabled `getrandom_test_linux_without_fallback`")
66-
}
67-
6861
GETRANDOM_FN.store(res_ptr.as_ptr(), Ordering::Release);
6962
res_ptr
7063
}
File renamed without changes.

tests/linux_force_fallback.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! This test forces the Linux fallback path to be taken. This test must be
2+
//! run manually and sequentally:
3+
//!
4+
//! cargo test --test linux_force_fallback -- --test-threads 1
5+
use std::{
6+
ffi::c_void,
7+
fs::{read_dir, DirEntry},
8+
sync::atomic::{AtomicBool, Ordering},
9+
};
10+
11+
use libc::{__errno_location, c_uint, size_t, ssize_t, ENOSYS};
12+
13+
static FAKE_GETRANDOM_CALLED: AtomicBool = AtomicBool::new(false);
14+
15+
// Override libc::getrandom to simulate failure
16+
#[export_name = "getrandom"]
17+
pub unsafe extern "C" fn fake_getrandom(_: *mut c_void, _: size_t, _: c_uint) -> ssize_t {
18+
FAKE_GETRANDOM_CALLED.store(true, Ordering::SeqCst);
19+
unsafe { *__errno_location() = ENOSYS };
20+
-1
21+
}
22+
23+
mod common;
24+
25+
#[test]
26+
fn fake_getrandom_is_called() {
27+
assert!(FAKE_GETRANDOM_CALLED.load(Ordering::SeqCst));
28+
}
29+
30+
#[test]
31+
fn dev_urandom_is_open() {
32+
fn is_urandom(entry: DirEntry) -> bool {
33+
entry.path().canonicalize().unwrap().to_str() == Some("/dev/urandom")
34+
}
35+
let mut dir = read_dir("/proc/self/fd").unwrap();
36+
assert!(dir.any(|path| is_urandom(path.unwrap())));
37+
}

tests/linux_no_fallback.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! This test ensures the Linux fallback path is not taken. As this test will
2+
//! fail in some Linux configurations, it must be run manually and sequentally:
3+
//!
4+
//! cargo test --test linux_no_fallback -- --test-threads 1
5+
use std::fs::{read_dir, DirEntry};
6+
7+
mod common;
8+
9+
#[test]
10+
fn dev_urandom_is_not_open() {
11+
fn is_urandom(entry: DirEntry) -> bool {
12+
entry.path().canonicalize().unwrap().to_str() == Some("/dev/urandom")
13+
}
14+
let mut dir = read_dir("/proc/self/fd").unwrap();
15+
assert!(dir.all(|path| !is_urandom(path.unwrap())));
16+
}

0 commit comments

Comments
 (0)