UPSTREAM: 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 <jose.exposito89@gmail.com> Co-developed-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Miguel Ojeda <ojeda@kernel.org> Co-developed-by: David Gow <davidgow@google.com> Signed-off-by: David Gow <davidgow@google.com> Link: https://lore.kernel.org/r/20250307090103.918788-4-davidgow@google.com Signed-off-by: Miguel Ojeda <ojeda@kernel.org> Bug: 414994413 (cherry picked from commit 100af58c8d5822750ef9ba65f5d5ea3367c669de) Change-Id: I2810872e70593e1bae0c259c495006beba14d1e3 Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Matthew Maurer
parent
86603276f4
commit
025e0fc417
@@ -294,11 +294,47 @@ macro_rules! kunit_unsafe_test_suite {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether we are currently running a KUnit test.
|
||||||
|
///
|
||||||
|
/// In some cases, you need to call test-only code from outside the test case, for example, to
|
||||||
|
/// create a function mock. This function allows to change behavior depending on whether we are
|
||||||
|
/// currently running a KUnit test or not.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// This example shows how a function can be mocked to return a well-known value while testing:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use kernel::kunit::in_kunit_test;
|
||||||
|
/// fn fn_mock_example(n: i32) -> i32 {
|
||||||
|
/// if in_kunit_test() {
|
||||||
|
/// return 100;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// n + 1
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let mock_res = fn_mock_example(5);
|
||||||
|
/// assert_eq!(mock_res, 100);
|
||||||
|
/// ```
|
||||||
|
pub fn in_kunit_test() -> bool {
|
||||||
|
// SAFETY: `kunit_get_current_test()` is always safe to call (it has fallbacks for
|
||||||
|
// when KUnit is not enabled).
|
||||||
|
!unsafe { bindings::kunit_get_current_test() }.is_null()
|
||||||
|
}
|
||||||
|
|
||||||
#[kunit_tests(rust_kernel_kunit)]
|
#[kunit_tests(rust_kernel_kunit)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rust_test_kunit_example_test() {
|
fn rust_test_kunit_example_test() {
|
||||||
#![expect(clippy::eq_op)]
|
#![expect(clippy::eq_op)]
|
||||||
assert_eq!(1 + 1, 2);
|
assert_eq!(1 + 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rust_test_kunit_in_kunit_test() {
|
||||||
|
assert!(in_kunit_test());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user