* [PATCH 1/2] gpu: nova-core: add a KUnit test configuration option
2026-08-18 15:23 [PATCH 0/2] rust: kunit: enforce test configurability Yury Norov
@ 2026-08-18 15:23 ` Yury Norov
2026-08-18 15:23 ` [PATCH 2/2] rust: kunit: move test configuration gating into macro Yury Norov
1 sibling, 0 replies; 3+ messages in thread
From: Yury Norov @ 2026-08-18 15:23 UTC (permalink / raw)
To: Miguel Ojeda, Danilo Krummrich, Alexandre Courbot, rust-for-linux,
nova-gpu
Cc: Yury Norov, Gary Guo, John Hubbard, Alice Ryhl, Burak Emir,
Brendan Higgins, David Gow, Rae Moar, Yury Norov, linux-kselftest,
kunit-dev, linux-doc, linux-kernel
The continuation-record KUnit tests are currently built whenever both
Nova Core and KUnit are enabled, providing no way to select the tests
independently.
Add CONFIG_NOVA_CORE_KUNIT_TEST and use it to guard the test suite.
Follow the usual KUnit convention of enabling the option through
CONFIG_KUNIT_ALL_TESTS.
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
drivers/gpu/nova-core/Kconfig | 12 ++++++++++++
drivers/gpu/nova-core/gsp/cmdq/continuation.rs | 1 +
2 files changed, 13 insertions(+)
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index f918f69e0599..d05c2c1d46d9 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -15,3 +15,15 @@ config NOVA_CORE
This driver is work in progress and may not be functional.
If M is selected, the module will be called nova-core.
+
+config NOVA_CORE_KUNIT_TEST
+ bool "KUnit tests for Nova Core" if !KUNIT_ALL_TESTS
+ depends on NOVA_CORE && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ This option enables KUnit tests for internal components of the Nova
+ Core driver. The tests currently do not require GPU hardware. These
+ are only for development and testing, not for regular kernel use
+ cases.
+
+ If unsure, say N.
diff --git a/drivers/gpu/nova-core/gsp/cmdq/continuation.rs b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
index 05e904f18097..c0aa16c8fbf4 100644
--- a/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
@@ -167,6 +167,7 @@ fn init_variable_payload(
}
}
+#[cfg(CONFIG_NOVA_CORE_KUNIT_TEST)]
#[kunit_tests(nova_core_gsp_continuation)]
mod tests {
use super::*;
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/2] rust: kunit: move test configuration gating into macro
2026-08-18 15:23 [PATCH 0/2] rust: kunit: enforce test configurability Yury Norov
2026-08-18 15:23 ` [PATCH 1/2] gpu: nova-core: add a KUnit test configuration option Yury Norov
@ 2026-08-18 15:23 ` Yury Norov
1 sibling, 0 replies; 3+ messages in thread
From: Yury Norov @ 2026-08-18 15:23 UTC (permalink / raw)
To: Miguel Ojeda, Danilo Krummrich, Alexandre Courbot, rust-for-linux,
nova-gpu
Cc: Yury Norov, Gary Guo, John Hubbard, Alice Ryhl, Burak Emir,
Brendan Higgins, David Gow, Rae Moar, Yury Norov, linux-kselftest,
kunit-dev, linux-doc, linux-kernel
KUnit test modules currently need a separate cfg attribute in addition to
the kunit_tests attribute. This makes every test suite repeat the same
two-attribute pattern.
Declaring a KUnit test without a preceding `#[cfg]` attribute is also
possible, causing it to be built whenever KUnit and its containing code are
enabled.
Require the controlling Kconfig symbol as the second kunit_tests argument
and have the macro emit the cfg attribute itself. Update all existing users
to the new form.
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
Documentation/rust/testing.rst | 11 ++++---
.../gpu/nova-core/gsp/cmdq/continuation.rs | 3 +-
rust/kernel/alloc/allocator.rs | 3 +-
rust/kernel/alloc/kvec.rs | 3 +-
rust/kernel/bitfield.rs | 3 +-
rust/kernel/bitmap.rs | 3 +-
rust/kernel/kunit.rs | 3 +-
rust/kernel/str.rs | 3 +-
rust/kernel/sync/atomic/predefine.rs | 3 +-
rust/macros/kunit.rs | 30 +++++++++++++++++--
rust/macros/lib.rs | 6 ++--
11 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/Documentation/rust/testing.rst b/Documentation/rust/testing.rst
index e3943aceceb9..767b111afd41 100644
--- a/Documentation/rust/testing.rst
+++ b/Documentation/rust/testing.rst
@@ -138,9 +138,10 @@ these are also fairly similar to what you would expect from userspace, and they
are also mapped to KUnit.
These tests are introduced by the ``kunit_tests`` procedural macro, which takes
-the name of the test suite as an argument.
+the name of the test suite and its controlling Kconfig option as arguments. The
+Kconfig option is required, and the macro uses it to guard the test suite.
-Each test suite should be guarded by a Kconfig option in
+Each test suite should have a Kconfig option, typically in
``rust/kernel/Kconfig.test``.
For instance, assume we want to test the function ``f`` from the documentation
@@ -148,8 +149,7 @@ tests section. We could write, in the same file where we have our function:
.. code-block:: rust
- #[cfg(CONFIG_RUST_MYMOD_KUNIT_TEST)]
- #[kunit_tests(rust_kernel_mymod)]
+ #[kunit_tests(rust_kernel_mymod, CONFIG_RUST_MYMOD_KUNIT_TEST)]
mod tests {
use super::*;
@@ -177,8 +177,7 @@ the unit type ``()``) or ``Result`` (i.e. any ``Result<T, E>``). For instance:
.. code-block:: rust
- #[cfg(CONFIG_RUST_MYMOD_KUNIT_TEST)]
- #[kunit_tests(rust_kernel_mymod)]
+ #[kunit_tests(rust_kernel_mymod, CONFIG_RUST_MYMOD_KUNIT_TEST)]
mod tests {
use super::*;
diff --git a/drivers/gpu/nova-core/gsp/cmdq/continuation.rs b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
index c0aa16c8fbf4..2e4b21f2002f 100644
--- a/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq/continuation.rs
@@ -167,8 +167,7 @@ fn init_variable_payload(
}
}
-#[cfg(CONFIG_NOVA_CORE_KUNIT_TEST)]
-#[kunit_tests(nova_core_gsp_continuation)]
+#[kunit_tests(nova_core_gsp_continuation, CONFIG_NOVA_CORE_KUNIT_TEST)]
mod tests {
use super::*;
diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs
index cd4203f27aed..b2c235801a3f 100644
--- a/rust/kernel/alloc/allocator.rs
+++ b/rust/kernel/alloc/allocator.rs
@@ -265,8 +265,7 @@ unsafe fn realloc(
}
}
-#[cfg(CONFIG_RUST_ALLOCATOR_KUNIT_TEST)]
-#[macros::kunit_tests(rust_allocator)]
+#[macros::kunit_tests(rust_allocator, CONFIG_RUST_ALLOCATOR_KUNIT_TEST)]
mod tests {
use super::*;
use core::mem::MaybeUninit;
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index f7af62835aa8..4b77425950d3 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -1508,8 +1508,7 @@ fn drop(&mut self) {
}
}
-#[cfg(CONFIG_RUST_KVEC_KUNIT_TEST)]
-#[macros::kunit_tests(rust_kvec)]
+#[macros::kunit_tests(rust_kvec, CONFIG_RUST_KVEC_KUNIT_TEST)]
mod tests {
use super::*;
use crate::prelude::*;
diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
index 35ede53f2b8e..8b329b6e4f8d 100644
--- a/rust/kernel/bitfield.rs
+++ b/rust/kernel/bitfield.rs
@@ -548,8 +548,7 @@ fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
};
}
-#[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)]
-#[::kernel::macros::kunit_tests(rust_kernel_bitfield)]
+#[::kernel::macros::kunit_tests(rust_kernel_bitfield, CONFIG_RUST_BITFIELD_KUNIT_TEST)]
mod tests {
use core::convert::TryFrom;
diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs
index b27e0ec80d64..c4195e00d895 100644
--- a/rust/kernel/bitmap.rs
+++ b/rust/kernel/bitmap.rs
@@ -499,8 +499,7 @@ pub fn next_zero_bit(&self, start: usize) -> Option<usize> {
}
}
-#[cfg(CONFIG_RUST_BITMAP_KUNIT_TEST)]
-#[macros::kunit_tests(rust_kernel_bitmap)]
+#[macros::kunit_tests(rust_kernel_bitmap, CONFIG_RUST_BITMAP_KUNIT_TEST)]
mod tests {
use super::*;
use kernel::alloc::flags::GFP_KERNEL;
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 91eaff8c186a..52f2ccbfba49 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -330,8 +330,7 @@ pub fn in_kunit_test() -> bool {
!unsafe { bindings::kunit_get_current_test() }.is_null()
}
-#[cfg(CONFIG_RUST_KUNIT_SELFTEST)]
-#[kunit_tests(rust_kernel_kunit)]
+#[kunit_tests(rust_kernel_kunit, CONFIG_RUST_KUNIT_SELFTEST)]
mod tests {
use super::*;
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index b3caa9a1c898..404418504c13 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -428,8 +428,7 @@ macro_rules! c_str {
}};
}
-#[cfg(CONFIG_RUST_STR_KUNIT_TEST)]
-#[kunit_tests(rust_kernel_str)]
+#[kunit_tests(rust_kernel_str, CONFIG_RUST_STR_KUNIT_TEST)]
mod tests {
use super::*;
diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
index 3d63f40791fa..e92194b37de8 100644
--- a/rust/kernel/sync/atomic/predefine.rs
+++ b/rust/kernel/sync/atomic/predefine.rs
@@ -152,8 +152,7 @@ fn rhs_into_delta(rhs: usize) -> isize_atomic_repr {
}
}
-#[cfg(CONFIG_RUST_ATOMICS_KUNIT_TEST)]
-#[macros::kunit_tests(rust_atomics)]
+#[macros::kunit_tests(rust_atomics, CONFIG_RUST_ATOMICS_KUNIT_TEST)]
mod tests {
use super::super::*;
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index ae20ed6768f1..7c7ba30f58c0 100644
--- a/rust/macros/kunit.rs
+++ b/rust/macros/kunit.rs
@@ -13,6 +13,10 @@
ToTokens, //
};
use syn::{
+ parse::{
+ Parse,
+ ParseStream, //
+ },
parse_quote,
Error,
Ident,
@@ -20,9 +24,28 @@
ItemMod,
LitCStr,
Result, //
+ Token,
};
-pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<TokenStream> {
+pub(crate) struct KunitTestArgs {
+ test_suite: Ident,
+ config: Ident,
+}
+
+impl Parse for KunitTestArgs {
+ fn parse(input: ParseStream<'_>) -> Result<Self> {
+ let test_suite = input.parse()?;
+ input.parse::<Token![,]>()?;
+ let config = input.parse()?;
+
+ Ok(Self { test_suite, config })
+ }
+}
+
+pub(crate) fn kunit_tests(
+ KunitTestArgs { test_suite, config }: KunitTestArgs,
+ mut module: ItemMod,
+) -> Result<TokenStream> {
if test_suite.to_string().len() > 255 {
return Err(Error::new_spanned(
test_suite,
@@ -34,7 +57,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
let Some((module_brace, module_items)) = module.content.take() else {
Err(Error::new_spanned(
module,
- "`#[kunit_tests(test_name)]` attribute should only be applied to inline modules",
+ "`#[kunit_tests(test_name, CONFIG_KUNIT_TEST)]` attribute should only be applied to inline modules",
))?
};
@@ -42,6 +65,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
module
.attrs
.insert(0, parse_quote!(#[cfg(CONFIG_KUNIT="y")]));
+ module.attrs.insert(0, parse_quote!(#[cfg(#config)]));
let mut processed_items = Vec::new();
let mut test_cases = Vec::new();
@@ -51,7 +75,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
// The code generated for the following test module:
//
// ```
- // #[kunit_tests(kunit_test_suit_name)]
+ // #[kunit_tests(kunit_test_suite_name, CONFIG_KUNIT_TEST)]
// mod tests {
// #[test]
// fn foo() {
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 4a48fabbc268..a660296d5dbd 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -464,14 +464,14 @@ pub fn paste(input: TokenStream) -> TokenStream {
/// Registers a KUnit test suite and its test cases using a user-space like syntax.
///
-/// This macro should be used on modules. If `CONFIG_KUNIT` (in `.config`) is `n`, the target module
-/// is ignored.
+/// This macro should be used on modules. The second argument is the Kconfig symbol that controls
+/// the test suite. If it or `CONFIG_KUNIT` (in `.config`) is `n`, the target module is ignored.
///
/// # Examples
///
/// ```ignore
/// # use kernel::prelude::*;
-/// #[kunit_tests(kunit_test_suit_name)]
+/// #[kunit_tests(kunit_test_suite_name, CONFIG_KUNIT_TEST)]
/// mod tests {
/// #[test]
/// fn foo() {
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread