Tips For Writing KUnit Tests

Exiting early on failed expectations

KUNIT_EXPECT_EQ and friends will mark the test as failed and continue execution. In some cases, it’s unsafe to continue and you can use the KUNIT_ASSERT variant to exit on failure.

void example_test_user_alloc_function(struct kunit *test)
        void *object = alloc_some_object_for_me();

        /* Make sure we got a valid pointer back. */
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object);

Allocating memory

Where you would use kzalloc, you should prefer kunit_kzalloc instead. KUnit will ensure the memory is freed once the test completes.

This is particularly useful since it lets you use the KUNIT_ASSERT_EQ macros to exit early from a test without having to worry about remembering to call kfree.


void example_test_allocation(struct kunit *test)
        char *buffer = kunit_kzalloc(test, 16, GFP_KERNEL);
        /* Ensure allocation succeeded. */
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);

        KUNIT_ASSERT_STREQ(test, buffer, "");

Testing static functions

If you don’t want to expose functions or variables just for testing, one option is to conditionally #include the test file at the end of your .c file, e.g.

/* In my_file.c */

static int do_interesting_thing();

#include "my_kunit_test.c"

Injecting test-only code

Similarly to the above, it can be useful to add test-specific logic.

/* In my_file.h */

/* Defined in my_kunit_test.c */
void test_only_hook(void);
void test_only_hook(void) { }

TODO( add an example of using current->kunit_test in such a hook when it’s not only updated for CONFIG_KASAN=y.

Customizing error messages

Each of the KUNIT_EXPECT and KUNIT_ASSERT macros have a _MSG variant. These take a format string and arguments to provide additional context to the automatically generated error messages.

char some_str[41];

/* Before. Not easy to tell why the test failed. */
KUNIT_EXPECT_EQ(test, strlen(some_str), 40);

/* After. Now we see the offending string. */
KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str);

Alternatively, one can take full control over the error message by using KUNIT_FAIL(), e.g.

/* Before */
KUNIT_EXPECT_EQ(test, some_setup_function(), 0);

/* After: full control over the failure message. */
if (some_setup_function())
        KUNIT_FAIL(test, "Failed to setup thing for testing");

Next Steps

  • Optional: see the Using KUnit page for a more in-depth explanation of KUnit.