tips.rst (5080B)
1.. SPDX-License-Identifier: GPL-2.0 2 3============================ 4Tips For Writing KUnit Tests 5============================ 6 7Exiting early on failed expectations 8------------------------------------ 9 10``KUNIT_EXPECT_EQ`` and friends will mark the test as failed and continue 11execution. In some cases, it's unsafe to continue and you can use the 12``KUNIT_ASSERT`` variant to exit on failure. 13 14.. code-block:: c 15 16 void example_test_user_alloc_function(struct kunit *test) 17 { 18 void *object = alloc_some_object_for_me(); 19 20 /* Make sure we got a valid pointer back. */ 21 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object); 22 do_something_with_object(object); 23 } 24 25Allocating memory 26----------------- 27 28Where you would use ``kzalloc``, you should prefer ``kunit_kzalloc`` instead. 29KUnit will ensure the memory is freed once the test completes. 30 31This is particularly useful since it lets you use the ``KUNIT_ASSERT_EQ`` 32macros to exit early from a test without having to worry about remembering to 33call ``kfree``. 34 35Example: 36 37.. code-block:: c 38 39 void example_test_allocation(struct kunit *test) 40 { 41 char *buffer = kunit_kzalloc(test, 16, GFP_KERNEL); 42 /* Ensure allocation succeeded. */ 43 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer); 44 45 KUNIT_ASSERT_STREQ(test, buffer, ""); 46 } 47 48 49Testing static functions 50------------------------ 51 52If you don't want to expose functions or variables just for testing, one option 53is to conditionally ``#include`` the test file at the end of your .c file, e.g. 54 55.. code-block:: c 56 57 /* In my_file.c */ 58 59 static int do_interesting_thing(); 60 61 #ifdef CONFIG_MY_KUNIT_TEST 62 #include "my_kunit_test.c" 63 #endif 64 65Injecting test-only code 66------------------------ 67 68Similarly to the above, it can be useful to add test-specific logic. 69 70.. code-block:: c 71 72 /* In my_file.h */ 73 74 #ifdef CONFIG_MY_KUNIT_TEST 75 /* Defined in my_kunit_test.c */ 76 void test_only_hook(void); 77 #else 78 void test_only_hook(void) { } 79 #endif 80 81This test-only code can be made more useful by accessing the current kunit 82test, see below. 83 84Accessing the current test 85-------------------------- 86 87In some cases, you need to call test-only code from outside the test file, e.g. 88like in the example above or if you're providing a fake implementation of an 89ops struct. 90There is a ``kunit_test`` field in ``task_struct``, so you can access it via 91``current->kunit_test``. 92 93Here's a slightly in-depth example of how one could implement "mocking": 94 95.. code-block:: c 96 97 #include <linux/sched.h> /* for current */ 98 99 struct test_data { 100 int foo_result; 101 int want_foo_called_with; 102 }; 103 104 static int fake_foo(int arg) 105 { 106 struct kunit *test = current->kunit_test; 107 struct test_data *test_data = test->priv; 108 109 KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg); 110 return test_data->foo_result; 111 } 112 113 static void example_simple_test(struct kunit *test) 114 { 115 /* Assume priv is allocated in the suite's .init */ 116 struct test_data *test_data = test->priv; 117 118 test_data->foo_result = 42; 119 test_data->want_foo_called_with = 1; 120 121 /* In a real test, we'd probably pass a pointer to fake_foo somewhere 122 * like an ops struct, etc. instead of calling it directly. */ 123 KUNIT_EXPECT_EQ(test, fake_foo(1), 42); 124 } 125 126 127Note: here we're able to get away with using ``test->priv``, but if you wanted 128something more flexible you could use a named ``kunit_resource``, see 129Documentation/dev-tools/kunit/api/test.rst. 130 131Failing the current test 132------------------------ 133 134But sometimes, you might just want to fail the current test. In that case, we 135have ``kunit_fail_current_test(fmt, args...)`` which is defined in ``<kunit/test-bug.h>`` and 136doesn't require pulling in ``<kunit/test.h>``. 137 138E.g. say we had an option to enable some extra debug checks on some data structure: 139 140.. code-block:: c 141 142 #include <kunit/test-bug.h> 143 144 #ifdef CONFIG_EXTRA_DEBUG_CHECKS 145 static void validate_my_data(struct data *data) 146 { 147 if (is_valid(data)) 148 return; 149 150 kunit_fail_current_test("data %p is invalid", data); 151 152 /* Normal, non-KUnit, error reporting code here. */ 153 } 154 #else 155 static void my_debug_function(void) { } 156 #endif 157 158 159Customizing error messages 160-------------------------- 161 162Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` variant. 163These take a format string and arguments to provide additional context to the automatically generated error messages. 164 165.. code-block:: c 166 167 char some_str[41]; 168 generate_sha1_hex_string(some_str); 169 170 /* Before. Not easy to tell why the test failed. */ 171 KUNIT_EXPECT_EQ(test, strlen(some_str), 40); 172 173 /* After. Now we see the offending string. */ 174 KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str); 175 176Alternatively, one can take full control over the error message by using ``KUNIT_FAIL()``, e.g. 177 178.. code-block:: c 179 180 /* Before */ 181 KUNIT_EXPECT_EQ(test, some_setup_function(), 0); 182 183 /* After: full control over the failure message. */ 184 if (some_setup_function()) 185 KUNIT_FAIL(test, "Failed to setup thing for testing"); 186 187Next Steps 188========== 189* Optional: see the Documentation/dev-tools/kunit/usage.rst page for a more 190 in-depth explanation of KUnit.