| .. SPDX-License-Identifier: GPL-2.0 | |
| ============================ | |
| 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. | |
| .. code-block:: c | |
| 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); | |
| do_something_with_object(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``. | |
| Example: | |
| .. code-block:: c | |
| 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. | |
| .. code-block:: c | |
| /* In my_file.c */ | |
| static int do_interesting_thing(); | |
| #ifdef CONFIG_MY_KUNIT_TEST | |
| #include "my_kunit_test.c" | |
| #endif | |
| Injecting test-only code | |
| ------------------------ | |
| Similarly to the above, it can be useful to add test-specific logic. | |
| .. code-block:: c | |
| /* In my_file.h */ | |
| #ifdef CONFIG_MY_KUNIT_TEST | |
| /* Defined in my_kunit_test.c */ | |
| void test_only_hook(void); | |
| #else | |
| void test_only_hook(void) { } | |
| #endif | |
| This test-only code can be made more useful by accessing the current kunit | |
| test, see below. | |
| Accessing the current test | |
| -------------------------- | |
| In some cases, you need to call test-only code from outside the test file, e.g. | |
| like in the example above or if you're providing a fake implementation of an | |
| ops struct. | |
| There is a ``kunit_test`` field in ``task_struct``, so you can access it via | |
| ``current->kunit_test``. | |
| Here's a slightly in-depth example of how one could implement "mocking": | |
| .. code-block:: c | |
| #include <linux/sched.h> /* for current */ | |
| struct test_data { | |
| int foo_result; | |
| int want_foo_called_with; | |
| }; | |
| static int fake_foo(int arg) | |
| { | |
| struct kunit *test = current->kunit_test; | |
| struct test_data *test_data = test->priv; | |
| KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg); | |
| return test_data->foo_result; | |
| } | |
| static void example_simple_test(struct kunit *test) | |
| { | |
| /* Assume priv is allocated in the suite's .init */ | |
| struct test_data *test_data = test->priv; | |
| test_data->foo_result = 42; | |
| test_data->want_foo_called_with = 1; | |
| /* In a real test, we'd probably pass a pointer to fake_foo somewhere | |
| * like an ops struct, etc. instead of calling it directly. */ | |
| KUNIT_EXPECT_EQ(test, fake_foo(1), 42); | |
| } | |
| Note: here we're able to get away with using ``test->priv``, but if you wanted | |
| something more flexible you could use a named ``kunit_resource``, see | |
| Documentation/dev-tools/kunit/api/test.rst. | |
| Failing the current test | |
| ------------------------ | |
| But sometimes, you might just want to fail the current test. In that case, we | |
| have ``kunit_fail_current_test(fmt, args...)`` which is defined in ``<kunit/test-bug.h>`` and | |
| doesn't require pulling in ``<kunit/test.h>``. | |
| E.g. say we had an option to enable some extra debug checks on some data structure: | |
| .. code-block:: c | |
| #include <kunit/test-bug.h> | |
| #ifdef CONFIG_EXTRA_DEBUG_CHECKS | |
| static void validate_my_data(struct data *data) | |
| { | |
| if (is_valid(data)) | |
| return; | |
| kunit_fail_current_test("data %p is invalid", data); | |
| /* Normal, non-KUnit, error reporting code here. */ | |
| } | |
| #else | |
| static void my_debug_function(void) { } | |
| #endif | |
| 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. | |
| .. code-block:: c | |
| char some_str[41]; | |
| generate_sha1_hex_string(some_str); | |
| /* 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. | |
| .. code-block:: c | |
| /* 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 Documentation/dev-tools/kunit/usage.rst page for a more | |
| in-depth explanation of KUnit. |