Re: [PATCH RFC 0/3] rust: kunit: #[should_panic] and same test name with different #[cfg(...)] support

From: David Gow

Date: Tue Sep 22 2026 - 12:12:39 EST


Le 22/09/2026 à 23:37, Gary Guo a écrit :
On Tue Sep 22, 2026 at 4:27 PM BST, David Gow wrote:
Le 22/09/2026 à 21:35, Gary Guo a écrit :
On Tue Sep 22, 2026 at 8:56 AM BST, David Gow wrote:
Le 16/09/2026 à 03:33, Nicolás Antinori a écrit :
- Is it ok to 'stringify' the configuration so it can be distinguished
in the report? Would you prefer something like `_case_1` `_case_2` ..
instead?

I also don't like the stringifcation of cfgs.


I don't _like_ this: my preference would be for us to keep the same
name, and just not emit a test_case for anything which should be
compiled out with cfg. Unfortunately, implementing that is a bit harder
than would be ideal: we need a way of evaluating the cfg() arguments in
a proc macro, I think. (Ultimately, because otherwise there's no way of
statically determining the length of the TEST_CASES array?)

This is possible with a trick. In pin-init we have a similar need, so what I do
is for

#[macro]
struct Foo {
#[cfg(a)]
bar: u32,
}

to be expanded to

#[cfg(a)]
#[macro]
struct Foo {
bar: u32
}

#[cfg(not(a))]
#[macro]
struct Foo {
}

However, for kunit I don't think that's needed. Deduplicating the names
should be sufficient?

The problem with (at least my naive implementation of) duplication is
that -- while it works great for switching between implementations -- it
doesn't handle the case where _no_ implementation is active.

(The current implementation just compiles to a skipped test if the
#[cfg(...)] isn't active, which sidesteps the problem until we have
multiple implementations...)

Even the expansion above could be problematic, as we really are trying
to add entries to a static array, so I don't know what we could put in
the not(a) case (particularly since there'd be potentially lots of them).

Maybe the trick is to generate the array size by using a big series of
something like:
static mut TEST_CASES: [...,
#[cfg(a)] 1
#[cfg(not(a))]0
+
#[cfg(b)] 1
#[cfg(not(b))]0
+
…] = {
#[cfg(a)] case1,
#[cfg(b)] case1,

}
}


For array sizes, you have the option of building a slice first.

Some thing like:

const TEST_CASES_UNIT: &[()] = [
#[cfg(a)] (),
#[cfg(b)] (),
];

static mut TEST_CASES: [...; TEST_CASES_SLICE.len()] = [...];


Neat: I hadn't thought of that, and it seems to work great.


You could also just build everything as a const slice of `&'static
[kunit_cases]`, if there is no need to make it `mut`. But I suppose it needs to
be `static mut` for some reason?

Yeah, the kunit_cases are modified at runtime to store the result, so this really does need to be `static mut`. And while these writes are all done behind the scenes from C, so they should _appear_ constant from Rust (modulo a couple of writes to status we can get rid of once we fix the cfg() stuff here), we still need to ensure they can't end up in read-only memory.

Cheers,
-- David