Skip to content

Commit 3502c89

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 526aff1 commit 3502c89

File tree

7 files changed

+69
-22
lines changed

7 files changed

+69
-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_no_fallback -- --test-threads 1
57+
- run: cargo test --test linux_force_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,9 +10,8 @@ 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]
1513
- Cygwin support [#626]
14+
- Add tests for Linux fallback paths without hardcoding `cfg`s [#628]
1615

1716
### Changed
1817
- Remove `windows-targets` dependency and use [`raw-dylib`] directly [#627]
@@ -35,11 +34,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3534
[#597]: https://github.com/rust-random/getrandom/pull/597
3635
[#602]: https://github.com/rust-random/getrandom/pull/602
3736
[#603]: https://github.com/rust-random/getrandom/pull/603
38-
[#605]: https://github.com/rust-random/getrandom/pull/605
3937
[#610]: https://github.com/rust-random/getrandom/pull/610
4038
[#614]: https://github.com/rust-random/getrandom/pull/614
4139
[#626]: https://github.com/rust-random/getrandom/pull/626
4240
[#627]: https://github.com/rust-random/getrandom/pull/627
41+
[#628]: https://github.com/rust-random/getrandom/pull/628
4342
[`raw-dylib`]: https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=link#dylib-versus-raw-dylib
4443

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

Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,18 @@ 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
'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this.
9189
]
9290

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

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

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
let path = entry.path().canonicalize().expect("entry is valid");
34+
path.to_str() == Some("/dev/urandom")
35+
}
36+
let mut dir = read_dir("/proc/self/fd").expect("/proc/self exists");
37+
assert!(dir.any(|path| is_urandom(path.expect("entry exists"))));
38+
}

tests/linux_no_fallback.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
let path = entry.path().canonicalize().expect("entry is valid");
13+
path.to_str() == Some("/dev/urandom")
14+
}
15+
let mut dir = read_dir("/proc/self/fd").expect("/proc/self exists");
16+
assert!(dir.all(|path| !is_urandom(path.expect("entry exists"))));
17+
}

0 commit comments

Comments
 (0)