linux-kpi: test pci_register_error_handler contract (env missing, malformed, double-register)
Per v4.4 plan: 'no shipped driver daemon opts in yet'. Before integration, the C-callable opt-in function should have explicit contract tests on host (the function is host-callable; the worker thread that it spawns is target-only). Three new unit tests in rust_impl/error.rs: - register_returns_false_without_env_var: confirms pci_register_error_handler returns false when REDBEAR_DRIVER_ERROR_FD is unset (the daemon was not passed a sidecar fd by its parent). May also be false because the process-global OnceLock was already filled by a sibling test. - register_returns_true_with_valid_fd_then_false: creates a UnixStream::pair, exports the child fd as REDBEAR_DRIVER_ERROR_FD, verifies the second registration always returns false (OnceLock semantics — handlers are process-global). - register_returns_false_with_malformed_fd: sets the env var to 'not-a-number' and verifies the helper returns false rather than panicking. The first-call result (true/false) is intentionally not asserted because the OnceLock<ErrorHandlerFn> is process-global and test ordering is non-deterministic under cargo test. The second-call result is the deterministic invariant: registering a second handler always fails regardless of the first-call result. Tests run on host (the function is host-callable; the spawned worker thread is target-only and observes EOF when the parent end is dropped at end of test). Target build also clean. No production code changed.
This commit is contained in:
@@ -193,6 +193,8 @@ pub extern "C" fn pci_register_error_handler(handler: ErrorHandlerFn) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::net::UnixStream;
|
||||
|
||||
#[test]
|
||||
fn driver_error_report_round_trip() {
|
||||
@@ -212,4 +214,56 @@ mod tests {
|
||||
let bytes = r.encode();
|
||||
assert_eq!(bytes, vec![1]);
|
||||
}
|
||||
|
||||
/// `pci_register_error_handler` returns false when the env var is
|
||||
/// missing, regardless of the handler argument. This is the
|
||||
/// expected behavior when the spawned driver has not been passed
|
||||
/// the sidecar fd by its parent.
|
||||
#[test]
|
||||
fn register_returns_false_without_env_var() {
|
||||
std::env::remove_var("REDBEAR_DRIVER_ERROR_FD");
|
||||
let result = pci_register_error_handler(test_handler);
|
||||
// May be false (env missing) OR false (handler slot taken by
|
||||
// an earlier test in the same run). Either way, false.
|
||||
assert!(!result);
|
||||
}
|
||||
|
||||
/// With a valid `REDBEAR_DRIVER_ERROR_FD` pointing at a real fd
|
||||
/// (the child end of a socketpair), `pci_register_error_handler`
|
||||
/// returns true on the FIRST call. Subsequent calls return false
|
||||
/// because the global HANDLER slot is already filled.
|
||||
#[test]
|
||||
fn register_returns_true_with_valid_fd_then_false() {
|
||||
let (parent, child) = UnixStream::pair().unwrap();
|
||||
std::env::set_var("REDBEAR_DRIVER_ERROR_FD", child.as_raw_fd().to_string());
|
||||
// The OnceLock<ErrorHandlerFn> is process-global. Some
|
||||
// earlier test in the same process may have already filled
|
||||
// the slot, in which case this returns false. The negative
|
||||
// case is exercised in the no-env-var test.
|
||||
let first = pci_register_error_handler(test_handler);
|
||||
let second = pci_register_error_handler(test_handler);
|
||||
assert!(!second, "second registration must always return false");
|
||||
// The parent end stays open for the test; the test ends and
|
||||
// the worker thread observes EOF and exits. The child end is
|
||||
// not closed here (we don't own a copy of it), but
|
||||
// RAII-from-fd ensures the kernel-level cleanup happens when
|
||||
// the worker thread drops its `UnixStream`.
|
||||
drop(parent);
|
||||
let _ = first; // may be true or false depending on test order
|
||||
std::env::remove_var("REDBEAR_DRIVER_ERROR_FD");
|
||||
}
|
||||
|
||||
/// With a malformed `REDBEAR_DRIVER_ERROR_FD` value, the helper
|
||||
/// must return false rather than crashing or panicking.
|
||||
#[test]
|
||||
fn register_returns_false_with_malformed_fd() {
|
||||
std::env::set_var("REDBEAR_DRIVER_ERROR_FD", "not-a-number");
|
||||
let result = pci_register_error_handler(test_handler);
|
||||
assert!(!result);
|
||||
std::env::remove_var("REDBEAR_DRIVER_ERROR_FD");
|
||||
}
|
||||
|
||||
fn test_handler(_severity: u8, _bdf: *const u8, _bdf_len: usize) -> u8 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user