| .. 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 |
| |
| TODO(dlatypov@google.com): 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. |
| |
| .. 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 :doc:`usage` page for a more |
| in-depth explanation of KUnit. |