116 lines
3.0 KiB
ReStructuredText
116 lines
3.0 KiB
ReStructuredText
.. 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.
|