On Mon, 2026-08-17 at 12:52 +0200, Nam Cao wrote:
> [email protected] writes:
> > +/*
> > + * Use a fixed-size array so sizeof() gives the exact byte count at
> > + * compile time.
> > + */
>
> There is no need for a comment. This is obvious from the code itself.
>
> > +static const char long_reactor_name[] = "kunit_reactor_name_too_long_xxx_";
> > +_Static_assert(sizeof(long_reactor_name) - 1 >= MAX_RV_REACTOR_NAME_SIZE,
> > + "long_reactor_name must be at least MAX_RV_REACTOR_NAME_SIZE
> > chars");
> > +
> > +static void test_name_too_long(struct kunit *test)
> > +{
> > + static struct rv_reactor long_reactor = {
> > + .name = long_reactor_name,
> > + };
> > +
> > + KUNIT_EXPECT_EQ(test, rv_register_reactor(&long_reactor), -EINVAL);
> > +}
> > +
> > +static struct kunit_case rv_reactor_registration_cases[] = {
> > + KUNIT_CASE(test_double_register),
> > + KUNIT_CASE(test_name_too_long),
> > + {}
> > +};
>
> I am not sure about the usefulness of these test cases.
> rv_register_reactor() is not an user API that we have to prepare
> for corner case usage. We can expect its users to be sane since the
> users are us.
>
> But well, if Gabriele wants to keep them..
>
That's right, it can be a bit of an overkill, but I'm thinking one day reactors
could come from (out-of-tree) kernel modules, it wouldn't hurt to have this path
tested, especially if it doesn't require much effort.
> > +
> > +static struct kunit_suite rv_reactor_registration_suite = {
> > + .name = "rv_reactor_registration",
> > + .test_cases = rv_reactor_registration_cases,
> > +};
> > +
> > +static atomic_t react_call_count;
>
> Do we really need atomic_t? Does int work?
Missed that, yes, it should work just fine since KUnit runs in a single thread.
>
> > +
> > +__printf(1, 0) static void mock_react(const char *msg, va_list args)
> > +{
> > + atomic_inc(&react_call_count);
> > + /*
> > + * Hold the CPU for 5 ms so a timer interrupt is likely to fire
> > + * inside rv_react()'s lockdep context, exercising the LD_WAIT_SPIN
> > + * constraint. mdelay() is a calibrated busy-wait with no
> > scheduler
> > + * interaction.
> > + */
>
> The comment above mdelay()'s definition already explains what it does.
>
> > + mdelay(5);
> > +}
> > +
> > +static void test_react_no_callback(struct kunit *test)
> > +{
> > + struct rv_monitor monitor = {
> > + .name = "kunit_null_react",
> > + };
> > +
> > + atomic_set(&react_call_count, 0);
> > + rv_react(&monitor, "no callback");
> > +
> > + /*
> > + * The only possible failure in this test case is a kernel panic.
> > + * NULL react guard: callback must NOT have been invoked
> > + */
>
> Obvious comment.
>
> > + KUNIT_EXPECT_EQ(test, atomic_read(&react_call_count), 0);
> > +}
> > +
> > +static void test_react_callback_invoked(struct kunit *test)
> > +{
> > + struct rv_monitor monitor = {
> > + .name = "kunit_dispatch_monitor",
> > + .react = mock_react,
> > + };
> > +
> > + atomic_set(&react_call_count, 0);
> > + rv_react(&monitor, "callback invocation test");
> > + KUNIT_EXPECT_EQ(test, atomic_read(&react_call_count), 1);
> > +}
>
> So the test calls rv_react(), and validates that the reactor is called?
> Honestly I am not sure how useful that is. Especially since Gabriele
> already made the selftest which validates that the reactor is invoked.
>From what I understood, the value in this test suite isn't really about the
assertions (especially in test_react_no_callback). It triggers cases that should
not produce a splat (panic/lockdep) and a pass should consider that too.
This makes them not quite pure KUnit, but again, I think it doesn't hurt to have
this kind of test since KUnit output is in dmesg anyway, so a splat would hardly
slip.
What do you think?
Gabriele