Skip to content

Commit 100af58

Browse files
JoseExpositoojeda
authored andcommitted
rust: kunit: allow to know if we are in a test
In some cases, we need to call test-only code from outside the test case, for example, to mock a function or a module. In order to check whether we are in a test or not, we need to test if `CONFIG_KUNIT` is set. Unfortunately, we cannot rely only on this condition because: - a test could be running in another thread, - some distros compile KUnit in production kernels, so checking at runtime that `current->kunit_test != NULL` is required. Forturately, KUnit provides an optimised check in `kunit_get_current_test()`, which checks CONFIG_KUNIT, a global static key, and then the current thread's running KUnit test. Add a safe wrapper function around this to know whether or not we are in a KUnit test and examples showing how to mock a function and a module. Signed-off-by: José Expósito <[email protected]> Co-developed-by: Miguel Ojeda <[email protected]> Signed-off-by: Miguel Ojeda <[email protected]> Co-developed-by: David Gow <[email protected]> Signed-off-by: David Gow <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent c001045 commit 100af58

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

rust/kernel/kunit.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,47 @@ macro_rules! kunit_unsafe_test_suite {
288288
};
289289
}
290290

291+
/// Returns whether we are currently running a KUnit test.
292+
///
293+
/// In some cases, you need to call test-only code from outside the test case, for example, to
294+
/// create a function mock. This function allows to change behavior depending on whether we are
295+
/// currently running a KUnit test or not.
296+
///
297+
/// # Examples
298+
///
299+
/// This example shows how a function can be mocked to return a well-known value while testing:
300+
///
301+
/// ```
302+
/// # use kernel::kunit::in_kunit_test;
303+
/// fn fn_mock_example(n: i32) -> i32 {
304+
/// if in_kunit_test() {
305+
/// return 100;
306+
/// }
307+
///
308+
/// n + 1
309+
/// }
310+
///
311+
/// let mock_res = fn_mock_example(5);
312+
/// assert_eq!(mock_res, 100);
313+
/// ```
314+
pub fn in_kunit_test() -> bool {
315+
// SAFETY: `kunit_get_current_test()` is always safe to call (it has fallbacks for
316+
// when KUnit is not enabled).
317+
!unsafe { bindings::kunit_get_current_test() }.is_null()
318+
}
319+
291320
#[kunit_tests(rust_kernel_kunit)]
292321
mod tests {
322+
use super::*;
323+
293324
#[test]
294325
fn rust_test_kunit_example_test() {
295326
#![expect(clippy::eq_op)]
296327
assert_eq!(1 + 1, 2);
297328
}
329+
330+
#[test]
331+
fn rust_test_kunit_in_kunit_test() {
332+
assert!(in_kunit_test());
333+
}
298334
}

0 commit comments

Comments
 (0)