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:The problem with (at least my naive implementation of) duplication is
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?
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 `&'staticYeah, 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.
[kunit_cases]`, if there is no need to make it `mut`. But I suppose it needs to
be `static mut` for some reason?
Cheers,
-- David