Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'linux-kselftest-kunit-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull KUnit updates from Shuah Khan:
"Several enhancements, fixes, clean-ups, documentation updates,
improvements to logging and KTAP compliance of KUnit test output:

- log numbers in decimal and hex

- parse KTAP compliant test output

- allow conditionally exposing static symbols to tests when KUNIT is
enabled

- make static symbols visible during kunit testing

- clean-ups to remove unused structure definition"

* tag 'linux-kselftest-kunit-next-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (29 commits)
Documentation: dev-tools: Clarify requirements for result description
apparmor: test: make static symbols visible during kunit testing
kunit: add macro to allow conditionally exposing static symbols to tests
kunit: tool: make parser preserve whitespace when printing test log
Documentation: kunit: Fix "How Do I Use This" / "Next Steps" sections
kunit: tool: don't include KTAP headers and the like in the test log
kunit: improve KTAP compliance of KUnit test output
kunit: tool: parse KTAP compliant test output
mm: slub: test: Use the kunit_get_current_test() function
kunit: Use the static key when retrieving the current test
kunit: Provide a static key to check if KUnit is actively running tests
kunit: tool: make --json do nothing if --raw_ouput is set
kunit: tool: tweak error message when no KTAP found
kunit: remove KUNIT_INIT_MEM_ASSERTION macro
Documentation: kunit: Remove redundant 'tips.rst' page
Documentation: KUnit: reword description of assertions
Documentation: KUnit: make usage.rst a superset of tips.rst, remove duplication
kunit: eliminate KUNIT_INIT_*_ASSERT_STRUCT macros
kunit: tool: remove redundant file.close() call in unit test
kunit: tool: unit tests all check parser errors, standardize formatting a bit
...

+900 -699
+2 -2
Documentation/dev-tools/ktap.rst
··· 80 80 subtest within the same test at the same nesting level. 81 81 82 82 The description is a description of the test, generally the name of 83 - the test, and can be any string of words (can't include #). The 84 - description is optional, but recommended. 83 + the test, and can be any string of characters other than # or a 84 + newline. The description is optional, but recommended. 85 85 86 86 The directive and any diagnostic data is optional. If either are present, they 87 87 must follow a hash sign, "#".
+58 -57
Documentation/dev-tools/kunit/architecture.rst
··· 4 4 KUnit Architecture 5 5 ================== 6 6 7 - The KUnit architecture can be divided into two parts: 7 + The KUnit architecture is divided into two parts: 8 8 9 9 - `In-Kernel Testing Framework`_ 10 - - `kunit_tool (Command Line Test Harness)`_ 10 + - `kunit_tool (Command-line Test Harness)`_ 11 11 12 12 In-Kernel Testing Framework 13 13 =========================== 14 14 15 15 The kernel testing library supports KUnit tests written in C using 16 - KUnit. KUnit tests are kernel code. KUnit does several things: 16 + KUnit. These KUnit tests are kernel code. KUnit performs the following 17 + tasks: 17 18 18 19 - Organizes tests 19 20 - Reports test results ··· 23 22 Test Cases 24 23 ---------- 25 24 26 - The fundamental unit in KUnit is the test case. The KUnit test cases are 27 - grouped into KUnit suites. A KUnit test case is a function with type 28 - signature ``void (*)(struct kunit *test)``. 29 - These test case functions are wrapped in a struct called 30 - struct kunit_case. 25 + The test case is the fundamental unit in KUnit. KUnit test cases are organised 26 + into suites. A KUnit test case is a function with type signature 27 + ``void (*)(struct kunit *test)``. These test case functions are wrapped in a 28 + struct called struct kunit_case. 31 29 32 30 .. note: 33 31 ``generate_params`` is optional for non-parameterized tests. 34 32 35 - Each KUnit test case gets a ``struct kunit`` context 36 - object passed to it that tracks a running test. The KUnit assertion 37 - macros and other KUnit utilities use the ``struct kunit`` context 38 - object. As an exception, there are two fields: 33 + Each KUnit test case receives a ``struct kunit`` context object that tracks a 34 + running test. The KUnit assertion macros and other KUnit utilities use the 35 + ``struct kunit`` context object. As an exception, there are two fields: 39 36 40 37 - ``->priv``: The setup functions can use it to store arbitrary test 41 38 user data. ··· 76 77 77 78 The KUnit executor can list and run built-in KUnit tests on boot. 78 79 The Test suites are stored in a linker section 79 - called ``.kunit_test_suites``. For code, see: 80 - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v5.15#n945. 80 + called ``.kunit_test_suites``. For the code, see ``KUNIT_TABLE()`` macro 81 + definition in 82 + `include/asm-generic/vmlinux.lds.h <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v6.0#n950>`_. 81 83 The linker section consists of an array of pointers to 82 84 ``struct kunit_suite``, and is populated by the ``kunit_test_suites()`` 83 - macro. To run all tests compiled into the kernel, the KUnit executor 84 - iterates over the linker section array. 85 + macro. The KUnit executor iterates over the linker section array in order to 86 + run all the tests that are compiled into the kernel. 85 87 86 88 .. kernel-figure:: kunit_suitememorydiagram.svg 87 89 :alt: KUnit Suite Memory ··· 90 90 KUnit Suite Memory Diagram 91 91 92 92 On the kernel boot, the KUnit executor uses the start and end addresses 93 - of this section to iterate over and run all tests. For code, see: 94 - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c 95 - 93 + of this section to iterate over and run all tests. For the implementation of the 94 + executor, see 95 + `lib/kunit/executor.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c>`_. 96 96 When built as a module, the ``kunit_test_suites()`` macro defines a 97 97 ``module_init()`` function, which runs all the tests in the compilation 98 98 unit instead of utilizing the executor. 99 99 100 100 In KUnit tests, some error classes do not affect other tests 101 101 or parts of the kernel, each KUnit case executes in a separate thread 102 - context. For code, see: 103 - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58 102 + context. See the ``kunit_try_catch_run()`` function in 103 + `lib/kunit/try-catch.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58>`_. 104 104 105 105 Assertion Macros 106 106 ---------------- ··· 111 111 112 112 - ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an 113 113 expectation. 114 + In the event of a failure, the testing flow differs as follows: 114 115 115 - - For an expectation, if the check fails, marks the test as failed 116 - and logs the failure. 116 + - For expectations, the test is marked as failed and the failure is logged. 117 117 118 - - An assertion, on failure, causes the test case to terminate 119 - immediately. 118 + - Failing assertions, on the other hand, result in the test case being 119 + terminated immediately. 120 120 121 - - Assertions call function: 121 + - Assertions call the function: 122 122 ``void __noreturn kunit_abort(struct kunit *)``. 123 123 124 - - ``kunit_abort`` calls function: 124 + - ``kunit_abort`` calls the function: 125 125 ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``. 126 126 127 - - ``kunit_try_catch_throw`` calls function: 127 + - ``kunit_try_catch_throw`` calls the function: 128 128 ``void kthread_complete_and_exit(struct completion *, long) __noreturn;`` 129 129 and terminates the special thread context. 130 130 131 131 - ``<op>`` denotes a check with options: ``TRUE`` (supplied property 132 - has the boolean value “true”), ``EQ`` (two supplied properties are 132 + has the boolean value "true"), ``EQ`` (two supplied properties are 133 133 equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not 134 - contain an “err” value). 134 + contain an "err" value). 135 135 136 136 - ``[_MSG]`` prints a custom message on failure. 137 137 138 138 Test Result Reporting 139 139 --------------------- 140 - KUnit prints test results in KTAP format. KTAP is based on TAP14, see: 141 - https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md. 142 - KTAP (yet to be standardized format) works with KUnit and Kselftest. 143 - The KUnit executor prints KTAP results to dmesg, and debugfs 144 - (if configured). 140 + KUnit prints the test results in KTAP format. KTAP is based on TAP14, see 141 + Documentation/dev-tools/ktap.rst. 142 + KTAP works with KUnit and Kselftest. The KUnit executor prints KTAP results to 143 + dmesg, and debugfs (if configured). 145 144 146 145 Parameterized Tests 147 146 ------------------- ··· 149 150 parameters. The test is invoked multiple times, once for each parameter 150 151 value and the parameter is stored in the ``param_value`` field. 151 152 The test case includes a KUNIT_CASE_PARAM() macro that accepts a 152 - generator function. 153 - The generator function is passed the previous parameter and returns the next 154 - parameter. It also provides a macro to generate common-case generators based on 155 - arrays. 153 + generator function. The generator function is passed the previous parameter 154 + and returns the next parameter. It also includes a macro for generating 155 + array-based common-case generators. 156 156 157 - kunit_tool (Command Line Test Harness) 157 + kunit_tool (Command-line Test Harness) 158 158 ====================================== 159 159 160 - kunit_tool is a Python script ``(tools/testing/kunit/kunit.py)`` 161 - that can be used to configure, build, exec, parse and run (runs other 162 - commands in order) test results. You can either run KUnit tests using 163 - kunit_tool or can include KUnit in kernel and parse manually. 160 + ``kunit_tool`` is a Python script, found in ``tools/testing/kunit/kunit.py``. It 161 + is used to configure, build, execute, parse test results and run all of the 162 + previous commands in correct order (i.e., configure, build, execute and parse). 163 + You have two options for running KUnit tests: either build the kernel with KUnit 164 + enabled and manually parse the results (see 165 + Documentation/dev-tools/kunit/run_manual.rst) or use ``kunit_tool`` 166 + (see Documentation/dev-tools/kunit/run_wrapper.rst). 164 167 165 168 - ``configure`` command generates the kernel ``.config`` from a 166 169 ``.kunitconfig`` file (and any architecture-specific options). 167 - For some architectures, additional config options are specified in the 168 - ``qemu_config`` Python script 169 - (For example: ``tools/testing/kunit/qemu_configs/powerpc.py``). 170 + The Python scripts available in ``qemu_configs`` folder 171 + (for example, ``tools/testing/kunit/qemu configs/powerpc.py``) contains 172 + additional configuration options for specific architectures. 170 173 It parses both the existing ``.config`` and the ``.kunitconfig`` files 171 - and ensures that ``.config`` is a superset of ``.kunitconfig``. 172 - If this is not the case, it will combine the two and run 173 - ``make olddefconfig`` to regenerate the ``.config`` file. It then 174 - verifies that ``.config`` is now a superset. This checks if all 175 - Kconfig dependencies are correctly specified in ``.kunitconfig``. 176 - ``kunit_config.py`` includes the parsing Kconfigs code. The code which 177 - runs ``make olddefconfig`` is a part of ``kunit_kernel.py``. You can 178 - invoke this command via: ``./tools/testing/kunit/kunit.py config`` and 174 + to ensure that ``.config`` is a superset of ``.kunitconfig``. 175 + If not, it will combine the two and run ``make olddefconfig`` to regenerate 176 + the ``.config`` file. It then checks to see if ``.config`` has become a superset. 177 + This verifies that all the Kconfig dependencies are correctly specified in the 178 + file ``.kunitconfig``. The ``kunit_config.py`` script contains the code for parsing 179 + Kconfigs. The code which runs ``make olddefconfig`` is part of the 180 + ``kunit_kernel.py`` script. You can invoke this command through: 181 + ``./tools/testing/kunit/kunit.py config`` and 179 182 generate a ``.config`` file. 180 183 - ``build`` runs ``make`` on the kernel tree with required options 181 184 (depends on the architecture and some options, for example: build_dir) ··· 185 184 To build a KUnit kernel from the current ``.config``, you can use the 186 185 ``build`` argument: ``./tools/testing/kunit/kunit.py build``. 187 186 - ``exec`` command executes kernel results either directly (using 188 - User-mode Linux configuration), or via an emulator such 189 - as QEMU. It reads results from the log via standard 187 + User-mode Linux configuration), or through an emulator such 188 + as QEMU. It reads results from the log using standard 190 189 output (stdout), and passes them to ``parse`` to be parsed. 191 190 If you already have built a kernel with built-in KUnit tests, 192 191 you can run the kernel and display the test results with the ``exec``
+8 -12
Documentation/dev-tools/kunit/index.rst
··· 16 16 api/index 17 17 style 18 18 faq 19 - tips 20 19 running_tips 21 20 22 21 This section details the kernel unit testing framework. ··· 99 100 How do I use it? 100 101 ================ 101 102 102 - * Documentation/dev-tools/kunit/start.rst - for KUnit new users. 103 - * Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. 104 - * Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool. 105 - * Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool. 106 - * Documentation/dev-tools/kunit/usage.rst - write tests. 107 - * Documentation/dev-tools/kunit/tips.rst - best practices with 108 - examples. 109 - * Documentation/dev-tools/kunit/api/index.rst - KUnit APIs 110 - used for testing. 111 - * Documentation/dev-tools/kunit/faq.rst - KUnit common questions and 112 - answers. 103 + You can find a step-by-step guide to writing and running KUnit tests in 104 + Documentation/dev-tools/kunit/start.rst 105 + 106 + Alternatively, feel free to look through the rest of the KUnit documentation, 107 + or to experiment with tools/testing/kunit/kunit.py and the example test under 108 + lib/kunit/kunit-example-test.c 109 + 110 + Happy testing!
+8 -10
Documentation/dev-tools/kunit/start.rst
··· 294 294 Next Steps 295 295 ========== 296 296 297 - * Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. 298 - * Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool. 299 - * Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool. 300 - * Documentation/dev-tools/kunit/usage.rst - write tests. 301 - * Documentation/dev-tools/kunit/tips.rst - best practices with 302 - examples. 303 - * Documentation/dev-tools/kunit/api/index.rst - KUnit APIs 304 - used for testing. 305 - * Documentation/dev-tools/kunit/faq.rst - KUnit common questions and 306 - answers. 297 + If you're interested in using some of the more advanced features of kunit.py, 298 + take a look at Documentation/dev-tools/kunit/run_wrapper.rst 299 + 300 + If you'd like to run tests without using kunit.py, check out 301 + Documentation/dev-tools/kunit/run_manual.rst 302 + 303 + For more information on writing KUnit tests (including some common techniques 304 + for testing different things), see Documentation/dev-tools/kunit/usage.rst
-190
Documentation/dev-tools/kunit/tips.rst
··· 1 - .. SPDX-License-Identifier: GPL-2.0 2 - 3 - ============================ 4 - Tips For Writing KUnit Tests 5 - ============================ 6 - 7 - Exiting early on failed expectations 8 - ------------------------------------ 9 - 10 - ``KUNIT_EXPECT_EQ`` and friends will mark the test as failed and continue 11 - execution. 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 - 25 - Allocating memory 26 - ----------------- 27 - 28 - Where you would use ``kzalloc``, you should prefer ``kunit_kzalloc`` instead. 29 - KUnit will ensure the memory is freed once the test completes. 30 - 31 - This is particularly useful since it lets you use the ``KUNIT_ASSERT_EQ`` 32 - macros to exit early from a test without having to worry about remembering to 33 - call ``kfree``. 34 - 35 - Example: 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 - 49 - Testing static functions 50 - ------------------------ 51 - 52 - If you don't want to expose functions or variables just for testing, one option 53 - is 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 - 65 - Injecting test-only code 66 - ------------------------ 67 - 68 - Similarly 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 - 81 - This test-only code can be made more useful by accessing the current kunit 82 - test, see below. 83 - 84 - Accessing the current test 85 - -------------------------- 86 - 87 - In some cases, you need to call test-only code from outside the test file, e.g. 88 - like in the example above or if you're providing a fake implementation of an 89 - ops struct. 90 - There is a ``kunit_test`` field in ``task_struct``, so you can access it via 91 - ``current->kunit_test``. 92 - 93 - Here'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 - 127 - Note: here we're able to get away with using ``test->priv``, but if you wanted 128 - something more flexible you could use a named ``kunit_resource``, see 129 - Documentation/dev-tools/kunit/api/test.rst. 130 - 131 - Failing the current test 132 - ------------------------ 133 - 134 - But sometimes, you might just want to fail the current test. In that case, we 135 - have ``kunit_fail_current_test(fmt, args...)`` which is defined in ``<kunit/test-bug.h>`` and 136 - doesn't require pulling in ``<kunit/test.h>``. 137 - 138 - E.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 - 159 - Customizing error messages 160 - -------------------------- 161 - 162 - Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` variant. 163 - These 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 - 176 - Alternatively, 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 - 187 - Next Steps 188 - ========== 189 - * Optional: see the Documentation/dev-tools/kunit/usage.rst page for a more 190 - in-depth explanation of KUnit.
+60 -32
Documentation/dev-tools/kunit/usage.rst
··· 112 112 KUNIT_EXPECT_LE(test, a[i], a[i + 1]); 113 113 } 114 114 115 - In this example, the method under test should return pointer to a value. If the 116 - pointer returns null or an errno, we want to stop the test since the following 117 - expectation could crash the test case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us 118 - to bail out of the test case if the appropriate conditions are not satisfied to 119 - complete the test. 115 + In this example, we need to be able to allocate an array to test the ``sort()`` 116 + function. So we use ``KUNIT_ASSERT_NOT_ERR_OR_NULL()`` to abort the test if 117 + there's an allocation error. 118 + 119 + .. note:: 120 + In other test frameworks, ``ASSERT`` macros are often implemented by calling 121 + ``return`` so they only work from the test function. In KUnit, we stop the 122 + current kthread on failure, so you can call them from anywhere. 123 + 124 + Customizing error messages 125 + -------------------------- 126 + 127 + Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` 128 + variant. These take a format string and arguments to provide additional 129 + context to the automatically generated error messages. 130 + 131 + .. code-block:: c 132 + 133 + char some_str[41]; 134 + generate_sha1_hex_string(some_str); 135 + 136 + /* Before. Not easy to tell why the test failed. */ 137 + KUNIT_EXPECT_EQ(test, strlen(some_str), 40); 138 + 139 + /* After. Now we see the offending string. */ 140 + KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str); 141 + 142 + Alternatively, one can take full control over the error message by using 143 + ``KUNIT_FAIL()``, e.g. 144 + 145 + .. code-block:: c 146 + 147 + /* Before */ 148 + KUNIT_EXPECT_EQ(test, some_setup_function(), 0); 149 + 150 + /* After: full control over the failure message. */ 151 + if (some_setup_function()) 152 + KUNIT_FAIL(test, "Failed to setup thing for testing"); 153 + 120 154 121 155 Test Suites 122 156 ~~~~~~~~~~~ ··· 580 546 {} 581 547 }; 582 548 583 - Exiting Early on Failed Expectations 584 - ------------------------------------ 585 - 586 - We can use ``KUNIT_EXPECT_EQ`` to mark the test as failed and continue 587 - execution. In some cases, it is unsafe to continue. We can use the 588 - ``KUNIT_ASSERT`` variant to exit on failure. 589 - 590 - .. code-block:: c 591 - 592 - void example_test_user_alloc_function(struct kunit *test) 593 - { 594 - void *object = alloc_some_object_for_me(); 595 - 596 - /* Make sure we got a valid pointer back. */ 597 - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object); 598 - do_something_with_object(object); 599 - } 600 - 601 549 Allocating Memory 602 550 ----------------- 603 551 ··· 641 625 Accessing The Current Test 642 626 -------------------------- 643 627 644 - In some cases, we need to call test-only code from outside the test file. 645 - For example, see example in section *Injecting Test-Only Code* or if 646 - we are providing a fake implementation of an ops struct. Using 647 - ``kunit_test`` field in ``task_struct``, we can access it via 648 - ``current->kunit_test``. 628 + In some cases, we need to call test-only code from outside the test file. This 629 + is helpful, for example, when providing a fake implementation of a function, or 630 + to fail any current test from within an error handler. 631 + We can do this via the ``kunit_test`` field in ``task_struct``, which we can 632 + access using the ``kunit_get_current_test()`` function in ``kunit/test-bug.h``. 649 633 650 - The example below includes how to implement "mocking": 634 + ``kunit_get_current_test()`` is safe to call even if KUnit is not enabled. If 635 + KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is 636 + running in the current task, it will return ``NULL``. This compiles down to 637 + either a no-op or a static key check, so will have a negligible performance 638 + impact when no test is running. 639 + 640 + The example below uses this to implement a "mock" implementation of a function, ``foo``: 651 641 652 642 .. code-block:: c 653 643 654 - #include <linux/sched.h> /* for current */ 644 + #include <kunit/test-bug.h> /* for kunit_get_current_test */ 655 645 656 646 struct test_data { 657 647 int foo_result; ··· 666 644 667 645 static int fake_foo(int arg) 668 646 { 669 - struct kunit *test = current->kunit_test; 647 + struct kunit *test = kunit_get_current_test(); 670 648 struct test_data *test_data = test->priv; 671 649 672 650 KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg); ··· 697 675 flexibility as a ``priv`` member, but also, for example, allowing helper 698 676 functions to create resources without conflicting with each other. It is also 699 677 possible to define a clean up function for each resource, making it easy to 700 - avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/test.rst. 678 + avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/resource.rst. 701 679 702 680 Failing The Current Test 703 681 ------------------------ ··· 724 702 #else 725 703 static void my_debug_function(void) { } 726 704 #endif 705 + 706 + ``kunit_fail_current_test()`` is safe to call even if KUnit is not enabled. If 707 + KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is 708 + running in the current task, it will do nothing. This compiles down to either a 709 + no-op or a static key check, so will have a negligible performance impact when 710 + no test is running. 727 711
+6 -6
drivers/gpu/drm/tests/drm_format_helper_test.c
··· 315 315 iosys_map_set_vaddr(&src, xrgb8888); 316 316 317 317 drm_fb_xrgb8888_to_gray8(&dst, &result->dst_pitch, &src, &fb, &params->clip); 318 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); 318 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 319 319 } 320 320 321 321 static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test) ··· 345 345 iosys_map_set_vaddr(&src, xrgb8888); 346 346 347 347 drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, &params->clip); 348 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); 348 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 349 349 } 350 350 351 351 static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) ··· 375 375 iosys_map_set_vaddr(&src, xrgb8888); 376 376 377 377 drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false); 378 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); 378 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 379 379 380 380 drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true); 381 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected_swab, dst_size), 0); 381 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size); 382 382 } 383 383 384 384 static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) ··· 408 408 iosys_map_set_vaddr(&src, xrgb8888); 409 409 410 410 drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, &params->clip); 411 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); 411 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 412 412 } 413 413 414 414 static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) ··· 439 439 440 440 drm_fb_xrgb8888_to_xrgb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip); 441 441 buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32)); 442 - KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); 442 + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); 443 443 } 444 444 445 445 static struct kunit_case drm_format_helper_test_cases[] = {
+26 -48
include/kunit/assert.h
··· 91 91 struct string_stream *stream); 92 92 93 93 /** 94 - * KUNIT_INIT_UNARY_ASSERT_STRUCT() - Initializes &struct kunit_unary_assert. 95 - * @cond: A string representation of the expression asserted true or false. 96 - * @expect_true: True if of type KUNIT_{EXPECT|ASSERT}_TRUE, false otherwise. 97 - * 98 - * Initializes a &struct kunit_unary_assert. Intended to be used in 99 - * KUNIT_EXPECT_* and KUNIT_ASSERT_* macros. 100 - */ 101 - #define KUNIT_INIT_UNARY_ASSERT_STRUCT(cond, expect_true) { \ 102 - .condition = cond, \ 103 - .expected_true = expect_true \ 104 - } 105 - 106 - /** 107 94 * struct kunit_ptr_not_err_assert - An expectation/assertion that a pointer is 108 95 * not NULL and not a -errno. 109 96 * @assert: The parent of this type. ··· 109 122 void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert, 110 123 const struct va_format *message, 111 124 struct string_stream *stream); 112 - 113 - /** 114 - * KUNIT_INIT_PTR_NOT_ERR_ASSERT_STRUCT() - Initializes a 115 - * &struct kunit_ptr_not_err_assert. 116 - * @txt: A string representation of the expression passed to the expectation. 117 - * @val: The actual evaluated pointer value of the expression. 118 - * 119 - * Initializes a &struct kunit_ptr_not_err_assert. Intended to be used in 120 - * KUNIT_EXPECT_* and KUNIT_ASSERT_* macros. 121 - */ 122 - #define KUNIT_INIT_PTR_NOT_ERR_STRUCT(txt, val) { \ 123 - .text = txt, \ 124 - .value = val \ 125 - } 126 125 127 126 /** 128 127 * struct kunit_binary_assert_text - holds strings for &struct ··· 145 172 void kunit_binary_assert_format(const struct kunit_assert *assert, 146 173 const struct va_format *message, 147 174 struct string_stream *stream); 148 - 149 - /** 150 - * KUNIT_INIT_BINARY_ASSERT_STRUCT() - Initializes a binary assert like 151 - * kunit_binary_assert, kunit_binary_ptr_assert, etc. 152 - * 153 - * @text_: Pointer to a kunit_binary_assert_text. 154 - * @left_val: The actual evaluated value of the expression in the left slot. 155 - * @right_val: The actual evaluated value of the expression in the right slot. 156 - * 157 - * Initializes a binary assert like kunit_binary_assert, 158 - * kunit_binary_ptr_assert, etc. This relies on these structs having the same 159 - * fields but with different types for left_val/right_val. 160 - * This is ultimately used by binary assertion macros like KUNIT_EXPECT_EQ, etc. 161 - */ 162 - #define KUNIT_INIT_BINARY_ASSERT_STRUCT(text_, \ 163 - left_val, \ 164 - right_val) { \ 165 - .text = text_, \ 166 - .left_value = left_val, \ 167 - .right_value = right_val \ 168 - } 169 175 170 176 /** 171 177 * struct kunit_binary_ptr_assert - An expectation/assertion that compares two ··· 191 239 void kunit_binary_str_assert_format(const struct kunit_assert *assert, 192 240 const struct va_format *message, 193 241 struct string_stream *stream); 242 + 243 + /** 244 + * struct kunit_mem_assert - An expectation/assertion that compares two 245 + * memory blocks. 246 + * @assert: The parent of this type. 247 + * @text: Holds the textual representations of the operands and comparator. 248 + * @left_value: The actual evaluated value of the expression in the left slot. 249 + * @right_value: The actual evaluated value of the expression in the right slot. 250 + * @size: Size of the memory block analysed in bytes. 251 + * 252 + * Represents an expectation/assertion that compares two memory blocks. For 253 + * example, to expect that the first three bytes of foo is equal to the 254 + * first three bytes of bar, you can use the expectation 255 + * KUNIT_EXPECT_MEMEQ(test, foo, bar, 3); 256 + */ 257 + struct kunit_mem_assert { 258 + struct kunit_assert assert; 259 + const struct kunit_binary_assert_text *text; 260 + const void *left_value; 261 + const void *right_value; 262 + const size_t size; 263 + }; 264 + 265 + void kunit_mem_assert_format(const struct kunit_assert *assert, 266 + const struct va_format *message, 267 + struct string_stream *stream); 194 268 195 269 #endif /* _KUNIT_ASSERT_H */
+50 -3
include/kunit/test-bug.h
··· 9 9 #ifndef _KUNIT_TEST_BUG_H 10 10 #define _KUNIT_TEST_BUG_H 11 11 12 - #define kunit_fail_current_test(fmt, ...) \ 13 - __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) 14 - 15 12 #if IS_BUILTIN(CONFIG_KUNIT) 13 + 14 + #include <linux/jump_label.h> /* For static branch */ 15 + #include <linux/sched.h> 16 + 17 + /* Static key if KUnit is running any tests. */ 18 + DECLARE_STATIC_KEY_FALSE(kunit_running); 19 + 20 + /** 21 + * kunit_get_current_test() - Return a pointer to the currently running 22 + * KUnit test. 23 + * 24 + * If a KUnit test is running in the current task, returns a pointer to its 25 + * associated struct kunit. This pointer can then be passed to any KUnit 26 + * function or assertion. If no test is running (or a test is running in a 27 + * different task), returns NULL. 28 + * 29 + * This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT 30 + * is not enabled, it will compile down to nothing and will return quickly no 31 + * test is running. 32 + */ 33 + static inline struct kunit *kunit_get_current_test(void) 34 + { 35 + if (!static_branch_unlikely(&kunit_running)) 36 + return NULL; 37 + 38 + return current->kunit_test; 39 + } 40 + 41 + 42 + /** 43 + * kunit_fail_current_test() - If a KUnit test is running, fail it. 44 + * 45 + * If a KUnit test is running in the current task, mark that test as failed. 46 + * 47 + * This macro will only work if KUnit is built-in (though the tests 48 + * themselves can be modules). Otherwise, it compiles down to nothing. 49 + */ 50 + #define kunit_fail_current_test(fmt, ...) do { \ 51 + if (static_branch_unlikely(&kunit_running)) { \ 52 + __kunit_fail_current_test(__FILE__, __LINE__, \ 53 + fmt, ##__VA_ARGS__); \ 54 + } \ 55 + } while (0) 56 + 16 57 17 58 extern __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, 18 59 const char *fmt, ...); 19 60 20 61 #else 62 + 63 + static inline struct kunit *kunit_get_current_test(void) { return NULL; } 64 + 65 + /* We define this with an empty helper function so format string warnings work */ 66 + #define kunit_fail_current_test(fmt, ...) \ 67 + __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) 21 68 22 69 static inline __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, 23 70 const char *fmt, ...)
+106 -12
include/kunit/test.h
··· 16 16 #include <linux/container_of.h> 17 17 #include <linux/err.h> 18 18 #include <linux/init.h> 19 + #include <linux/jump_label.h> 19 20 #include <linux/kconfig.h> 20 21 #include <linux/kref.h> 21 22 #include <linux/list.h> ··· 27 26 #include <linux/types.h> 28 27 29 28 #include <asm/rwonce.h> 29 + 30 + /* Static key: true if any KUnit tests are currently running */ 31 + DECLARE_STATIC_KEY_FALSE(kunit_running); 30 32 31 33 struct kunit; 32 34 ··· 519 515 fmt, \ 520 516 ##__VA_ARGS__) 521 517 518 + /* Helper to safely pass around an initializer list to other macros. */ 519 + #define KUNIT_INIT_ASSERT(initializers...) { initializers } 520 + 522 521 #define KUNIT_UNARY_ASSERTION(test, \ 523 522 assert_type, \ 524 - condition, \ 525 - expected_true, \ 523 + condition_, \ 524 + expected_true_, \ 526 525 fmt, \ 527 526 ...) \ 528 527 do { \ 529 - if (likely(!!(condition) == !!expected_true)) \ 528 + if (likely(!!(condition_) == !!expected_true_)) \ 530 529 break; \ 531 530 \ 532 531 _KUNIT_FAILED(test, \ 533 532 assert_type, \ 534 533 kunit_unary_assert, \ 535 534 kunit_unary_assert_format, \ 536 - KUNIT_INIT_UNARY_ASSERT_STRUCT(#condition, \ 537 - expected_true), \ 535 + KUNIT_INIT_ASSERT(.condition = #condition_, \ 536 + .expected_true = expected_true_), \ 538 537 fmt, \ 539 538 ##__VA_ARGS__); \ 540 539 } while (0) ··· 597 590 assert_type, \ 598 591 assert_class, \ 599 592 format_func, \ 600 - KUNIT_INIT_BINARY_ASSERT_STRUCT(&__text, \ 601 - __left, \ 602 - __right), \ 593 + KUNIT_INIT_ASSERT(.text = &__text, \ 594 + .left_value = __left, \ 595 + .right_value = __right), \ 603 596 fmt, \ 604 597 ##__VA_ARGS__); \ 605 598 } while (0) ··· 658 651 assert_type, \ 659 652 kunit_binary_str_assert, \ 660 653 kunit_binary_str_assert_format, \ 661 - KUNIT_INIT_BINARY_ASSERT_STRUCT(&__text, \ 662 - __left, \ 663 - __right), \ 654 + KUNIT_INIT_ASSERT(.text = &__text, \ 655 + .left_value = __left, \ 656 + .right_value = __right), \ 657 + fmt, \ 658 + ##__VA_ARGS__); \ 659 + } while (0) 660 + 661 + #define KUNIT_MEM_ASSERTION(test, \ 662 + assert_type, \ 663 + left, \ 664 + op, \ 665 + right, \ 666 + size_, \ 667 + fmt, \ 668 + ...) \ 669 + do { \ 670 + const void *__left = (left); \ 671 + const void *__right = (right); \ 672 + const size_t __size = (size_); \ 673 + static const struct kunit_binary_assert_text __text = { \ 674 + .operation = #op, \ 675 + .left_text = #left, \ 676 + .right_text = #right, \ 677 + }; \ 678 + \ 679 + if (likely(memcmp(__left, __right, __size) op 0)) \ 680 + break; \ 681 + \ 682 + _KUNIT_FAILED(test, \ 683 + assert_type, \ 684 + kunit_mem_assert, \ 685 + kunit_mem_assert_format, \ 686 + KUNIT_INIT_ASSERT(.text = &__text, \ 687 + .left_value = __left, \ 688 + .right_value = __right, \ 689 + .size = __size), \ 664 690 fmt, \ 665 691 ##__VA_ARGS__); \ 666 692 } while (0) ··· 713 673 assert_type, \ 714 674 kunit_ptr_not_err_assert, \ 715 675 kunit_ptr_not_err_assert_format, \ 716 - KUNIT_INIT_PTR_NOT_ERR_STRUCT(#ptr, __ptr), \ 676 + KUNIT_INIT_ASSERT(.text = #ptr, .value = __ptr), \ 717 677 fmt, \ 718 678 ##__VA_ARGS__); \ 719 679 } while (0) ··· 967 927 left, !=, right, \ 968 928 fmt, \ 969 929 ##__VA_ARGS__) 930 + 931 + /** 932 + * KUNIT_EXPECT_MEMEQ() - Expects that the first @size bytes of @left and @right are equal. 933 + * @test: The test context object. 934 + * @left: An arbitrary expression that evaluates to the specified size. 935 + * @right: An arbitrary expression that evaluates to the specified size. 936 + * @size: Number of bytes compared. 937 + * 938 + * Sets an expectation that the values that @left and @right evaluate to are 939 + * equal. This is semantically equivalent to 940 + * KUNIT_EXPECT_TRUE(@test, !memcmp((@left), (@right), (@size))). See 941 + * KUNIT_EXPECT_TRUE() for more information. 942 + * 943 + * Although this expectation works for any memory block, it is not recommended 944 + * for comparing more structured data, such as structs. This expectation is 945 + * recommended for comparing, for example, data arrays. 946 + */ 947 + #define KUNIT_EXPECT_MEMEQ(test, left, right, size) \ 948 + KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, NULL) 949 + 950 + #define KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, fmt, ...) \ 951 + KUNIT_MEM_ASSERTION(test, \ 952 + KUNIT_EXPECTATION, \ 953 + left, ==, right, \ 954 + size, \ 955 + fmt, \ 956 + ##__VA_ARGS__) 957 + 958 + /** 959 + * KUNIT_EXPECT_MEMNEQ() - Expects that the first @size bytes of @left and @right are not equal. 960 + * @test: The test context object. 961 + * @left: An arbitrary expression that evaluates to the specified size. 962 + * @right: An arbitrary expression that evaluates to the specified size. 963 + * @size: Number of bytes compared. 964 + * 965 + * Sets an expectation that the values that @left and @right evaluate to are 966 + * not equal. This is semantically equivalent to 967 + * KUNIT_EXPECT_TRUE(@test, memcmp((@left), (@right), (@size))). See 968 + * KUNIT_EXPECT_TRUE() for more information. 969 + * 970 + * Although this expectation works for any memory block, it is not recommended 971 + * for comparing more structured data, such as structs. This expectation is 972 + * recommended for comparing, for example, data arrays. 973 + */ 974 + #define KUNIT_EXPECT_MEMNEQ(test, left, right, size) \ 975 + KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, NULL) 976 + 977 + #define KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, fmt, ...) \ 978 + KUNIT_MEM_ASSERTION(test, \ 979 + KUNIT_EXPECTATION, \ 980 + left, !=, right, \ 981 + size, \ 982 + fmt, \ 983 + ##__VA_ARGS__) 970 984 971 985 /** 972 986 * KUNIT_EXPECT_NULL() - Expects that @ptr is null.
+33
include/kunit/visibility.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * KUnit API to allow symbols to be conditionally visible during KUnit 4 + * testing 5 + * 6 + * Copyright (C) 2022, Google LLC. 7 + * Author: Rae Moar <rmoar@google.com> 8 + */ 9 + 10 + #ifndef _KUNIT_VISIBILITY_H 11 + #define _KUNIT_VISIBILITY_H 12 + 13 + #if IS_ENABLED(CONFIG_KUNIT) 14 + /** 15 + * VISIBLE_IF_KUNIT - A macro that sets symbols to be static if 16 + * CONFIG_KUNIT is not enabled. Otherwise if CONFIG_KUNIT is enabled 17 + * there is no change to the symbol definition. 18 + */ 19 + #define VISIBLE_IF_KUNIT 20 + /** 21 + * EXPORT_SYMBOL_IF_KUNIT(symbol) - Exports symbol into 22 + * EXPORTED_FOR_KUNIT_TESTING namespace only if CONFIG_KUNIT is 23 + * enabled. Must use MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING) 24 + * in test file in order to use symbols. 25 + */ 26 + #define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, \ 27 + EXPORTED_FOR_KUNIT_TESTING) 28 + #else 29 + #define VISIBLE_IF_KUNIT static 30 + #define EXPORT_SYMBOL_IF_KUNIT(symbol) 31 + #endif 32 + 33 + #endif /* _KUNIT_VISIBILITY_H */
+60 -2
lib/kunit/assert.c
··· 127 127 binary_assert->text->right_text); 128 128 if (!is_literal(stream->test, binary_assert->text->left_text, 129 129 binary_assert->left_value, stream->gfp)) 130 - string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n", 130 + string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n", 131 131 binary_assert->text->left_text, 132 + binary_assert->left_value, 132 133 binary_assert->left_value); 133 134 if (!is_literal(stream->test, binary_assert->text->right_text, 134 135 binary_assert->right_value, stream->gfp)) 135 - string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld", 136 + string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)", 136 137 binary_assert->text->right_text, 138 + binary_assert->right_value, 137 139 binary_assert->right_value); 138 140 kunit_assert_print_msg(message, stream); 139 141 } ··· 206 204 kunit_assert_print_msg(message, stream); 207 205 } 208 206 EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format); 207 + 208 + /* Adds a hexdump of a buffer to a string_stream comparing it with 209 + * a second buffer. The different bytes are marked with <>. 210 + */ 211 + static void kunit_assert_hexdump(struct string_stream *stream, 212 + const void *buf, 213 + const void *compared_buf, 214 + const size_t len) 215 + { 216 + size_t i; 217 + const u8 *buf1 = buf; 218 + const u8 *buf2 = compared_buf; 219 + 220 + string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT); 221 + 222 + for (i = 0; i < len; ++i) { 223 + if (!(i % 16) && i) 224 + string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT); 225 + 226 + if (buf1[i] != buf2[i]) 227 + string_stream_add(stream, "<%02x>", buf1[i]); 228 + else 229 + string_stream_add(stream, " %02x ", buf1[i]); 230 + } 231 + } 232 + 233 + void kunit_mem_assert_format(const struct kunit_assert *assert, 234 + const struct va_format *message, 235 + struct string_stream *stream) 236 + { 237 + struct kunit_mem_assert *mem_assert; 238 + 239 + mem_assert = container_of(assert, struct kunit_mem_assert, 240 + assert); 241 + 242 + string_stream_add(stream, 243 + KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 244 + mem_assert->text->left_text, 245 + mem_assert->text->operation, 246 + mem_assert->text->right_text); 247 + 248 + string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 249 + mem_assert->text->left_text); 250 + kunit_assert_hexdump(stream, mem_assert->left_value, 251 + mem_assert->right_value, mem_assert->size); 252 + 253 + string_stream_add(stream, "\n"); 254 + 255 + string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 256 + mem_assert->text->right_text); 257 + kunit_assert_hexdump(stream, mem_assert->right_value, 258 + mem_assert->left_value, mem_assert->size); 259 + 260 + kunit_assert_print_msg(message, stream); 261 + } 262 + EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
+1 -1
lib/kunit/debugfs.c
··· 63 63 kunit_suite_for_each_test_case(suite, test_case) 64 64 debugfs_print_result(seq, suite, test_case); 65 65 66 - seq_printf(seq, "%s %d - %s\n", 66 + seq_printf(seq, "%s %d %s\n", 67 67 kunit_status_to_ok_not_ok(success), 1, suite->name); 68 68 return 0; 69 69 }
+3 -3
lib/kunit/executor.c
··· 166 166 { 167 167 size_t num_suites = suite_set->end - suite_set->start; 168 168 169 - pr_info("TAP version 14\n"); 169 + pr_info("KTAP version 1\n"); 170 170 pr_info("1..%zu\n", num_suites); 171 171 172 172 __kunit_test_suites_init(suite_set->start, num_suites); ··· 177 177 struct kunit_suite * const *suites; 178 178 struct kunit_case *test_case; 179 179 180 - /* Hack: print a tap header so kunit.py can find the start of KUnit output. */ 181 - pr_info("TAP version 14\n"); 180 + /* Hack: print a ktap header so kunit.py can find the start of KUnit output. */ 181 + pr_info("KTAP version 1\n"); 182 182 183 183 for (suites = suite_set->start; suites < suite_set->end; suites++) 184 184 kunit_suite_for_each_test_case((*suites), test_case) {
+7
lib/kunit/kunit-example-test.c
··· 86 86 */ 87 87 static void example_all_expect_macros_test(struct kunit *test) 88 88 { 89 + const u32 array1[] = { 0x0F, 0xFF }; 90 + const u32 array2[] = { 0x1F, 0xFF }; 91 + 89 92 /* Boolean assertions */ 90 93 KUNIT_EXPECT_TRUE(test, true); 91 94 KUNIT_EXPECT_FALSE(test, false); ··· 111 108 /* String assertions */ 112 109 KUNIT_EXPECT_STREQ(test, "hi", "hi"); 113 110 KUNIT_EXPECT_STRNEQ(test, "hi", "bye"); 111 + 112 + /* Memory block assertions */ 113 + KUNIT_EXPECT_MEMEQ(test, array1, array1, sizeof(array1)); 114 + KUNIT_EXPECT_MEMNEQ(test, array1, array2, sizeof(array1)); 114 115 115 116 /* 116 117 * There are also ASSERT variants of all of the above that abort test
-5
lib/kunit/string-stream.c
··· 131 131 return list_empty(&stream->fragments); 132 132 } 133 133 134 - struct string_stream_alloc_context { 135 - struct kunit *test; 136 - gfp_t gfp; 137 - }; 138 - 139 134 struct string_stream *alloc_string_stream(struct kunit *test, gfp_t gfp) 140 135 { 141 136 struct string_stream *stream;
+12 -3
lib/kunit/test.c
··· 20 20 #include "string-stream.h" 21 21 #include "try-catch-impl.h" 22 22 23 + DEFINE_STATIC_KEY_FALSE(kunit_running); 24 + 23 25 #if IS_BUILTIN(CONFIG_KUNIT) 24 26 /* 25 27 * Fail the current test and print an error message to the log. ··· 151 149 152 150 static void kunit_print_suite_start(struct kunit_suite *suite) 153 151 { 152 + kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "KTAP version 1\n"); 154 153 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s", 155 154 suite->name); 156 155 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd", ··· 178 175 * representation. 179 176 */ 180 177 if (suite) 181 - pr_info("%s %zd - %s%s%s\n", 178 + pr_info("%s %zd %s%s%s\n", 182 179 kunit_status_to_ok_not_ok(status), 183 180 test_number, description, directive_header, 184 181 (status == KUNIT_SKIPPED) ? directive : ""); 185 182 else 186 183 kunit_log(KERN_INFO, test, 187 - KUNIT_SUBTEST_INDENT "%s %zd - %s%s%s", 184 + KUNIT_SUBTEST_INDENT "%s %zd %s%s%s", 188 185 kunit_status_to_ok_not_ok(status), 189 186 test_number, description, directive_header, 190 187 (status == KUNIT_SKIPPED) ? directive : ""); ··· 546 543 param_desc[0] = '\0'; 547 544 test.param_value = test_case->generate_params(NULL, param_desc); 548 545 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 546 + "KTAP version 1\n"); 547 + kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 549 548 "# Subtest: %s", test_case->name); 550 549 551 550 while (test.param_value) { ··· 560 555 561 556 kunit_log(KERN_INFO, &test, 562 557 KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 563 - "%s %d - %s", 558 + "%s %d %s", 564 559 kunit_status_to_ok_not_ok(test.status), 565 560 test.param_index + 1, param_desc); 566 561 ··· 617 612 return 0; 618 613 } 619 614 615 + static_branch_inc(&kunit_running); 616 + 620 617 for (i = 0; i < num_suites; i++) { 621 618 kunit_init_suite(suites[i]); 622 619 kunit_run_tests(suites[i]); 623 620 } 621 + 622 + static_branch_dec(&kunit_running); 624 623 return 0; 625 624 } 626 625 EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
+1
lib/slub_kunit.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <kunit/test.h> 3 + #include <kunit/test-bug.h> 3 4 #include <linux/mm.h> 4 5 #include <linux/slab.h> 5 6 #include <linux/module.h>
+2 -1
mm/slub.c
··· 39 39 #include <linux/memcontrol.h> 40 40 #include <linux/random.h> 41 41 #include <kunit/test.h> 42 + #include <kunit/test-bug.h> 42 43 #include <linux/sort.h> 43 44 44 45 #include <linux/debugfs.h> ··· 619 618 { 620 619 struct kunit_resource *resource; 621 620 622 - if (likely(!current->kunit_test)) 621 + if (!kunit_get_current_test()) 623 622 return false; 624 623 625 624 resource = kunit_find_named_resource(current->kunit_test, "slab_errors");
+2 -2
net/core/dev_addr_lists_test.c
··· 71 71 72 72 memset(addr, 2, sizeof(addr)); 73 73 eth_hw_addr_set(netdev, addr); 74 - KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr))); 74 + KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr)); 75 75 76 76 memset(addr, 3, sizeof(addr)); 77 77 dev_addr_set(netdev, addr); 78 - KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr))); 78 + KUNIT_EXPECT_MEMEQ(test, netdev->dev_addr, addr, sizeof(addr)); 79 79 } 80 80 81 81 static void dev_addr_test_sync_one(struct kunit *test)
+2 -2
security/apparmor/Kconfig
··· 106 106 Disabling the check will speed up policy loads. 107 107 108 108 config SECURITY_APPARMOR_KUNIT_TEST 109 - bool "Build KUnit tests for policy_unpack.c" if !KUNIT_ALL_TESTS 110 - depends on KUNIT=y && SECURITY_APPARMOR 109 + tristate "Build KUnit tests for policy_unpack.c" if !KUNIT_ALL_TESTS 110 + depends on KUNIT && SECURITY_APPARMOR 111 111 default KUNIT_ALL_TESTS 112 112 help 113 113 This builds the AppArmor KUnit tests.
+3
security/apparmor/Makefile
··· 8 8 resource.o secid.o file.o policy_ns.o label.o mount.o net.o 9 9 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 10 10 11 + obj-$(CONFIG_SECURITY_APPARMOR_KUNIT_TEST) += apparmor_policy_unpack_test.o 12 + apparmor_policy_unpack_test-objs += policy_unpack_test.o 13 + 11 14 clean-files := capability_names.h rlim_names.h net_names.h 12 15 13 16 # Build a lower case string table of address family names
+50
security/apparmor/include/policy_unpack.h
··· 49 49 }; 50 50 51 51 /* 52 + * The AppArmor interface treats data as a type byte followed by the 53 + * actual data. The interface has the notion of a named entry 54 + * which has a name (AA_NAME typecode followed by name string) followed by 55 + * the entries typecode and data. Named types allow for optional 56 + * elements and extensions to be added and tested for without breaking 57 + * backwards compatibility. 58 + */ 59 + 60 + enum aa_code { 61 + AA_U8, 62 + AA_U16, 63 + AA_U32, 64 + AA_U64, 65 + AA_NAME, /* same as string except it is items name */ 66 + AA_STRING, 67 + AA_BLOB, 68 + AA_STRUCT, 69 + AA_STRUCTEND, 70 + AA_LIST, 71 + AA_LISTEND, 72 + AA_ARRAY, 73 + AA_ARRAYEND, 74 + }; 75 + 76 + /* 77 + * aa_ext is the read of the buffer containing the serialized profile. The 78 + * data is copied into a kernel buffer in apparmorfs and then handed off to 79 + * the unpack routines. 80 + */ 81 + struct aa_ext { 82 + void *start; 83 + void *end; 84 + void *pos; /* pointer to current position in the buffer */ 85 + u32 version; 86 + }; 87 + 88 + /* 52 89 * struct aa_loaddata - buffer of policy raw_data set 53 90 * 54 91 * there is no loaddata ref for being on ns list, nor a ref from ··· 162 125 if (data) 163 126 kref_put(&data->count, aa_loaddata_kref); 164 127 } 128 + 129 + #if IS_ENABLED(CONFIG_KUNIT) 130 + bool aa_inbounds(struct aa_ext *e, size_t size); 131 + size_t aa_unpack_u16_chunk(struct aa_ext *e, char **chunk); 132 + bool aa_unpack_X(struct aa_ext *e, enum aa_code code); 133 + bool aa_unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name); 134 + bool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name); 135 + bool aa_unpack_u64(struct aa_ext *e, u64 *data, const char *name); 136 + size_t aa_unpack_array(struct aa_ext *e, const char *name); 137 + size_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name); 138 + int aa_unpack_str(struct aa_ext *e, const char **string, const char *name); 139 + int aa_unpack_strdup(struct aa_ext *e, char **string, const char *name); 140 + #endif 165 141 166 142 #endif /* __POLICY_INTERFACE_H */
+104 -134
security/apparmor/policy_unpack.c
··· 14 14 */ 15 15 16 16 #include <asm/unaligned.h> 17 + #include <kunit/visibility.h> 17 18 #include <linux/ctype.h> 18 19 #include <linux/errno.h> 19 20 #include <linux/zlib.h> ··· 37 36 #define v6 6 /* per entry policydb mediation check */ 38 37 #define v7 7 39 38 #define v8 8 /* full network masking */ 40 - 41 - /* 42 - * The AppArmor interface treats data as a type byte followed by the 43 - * actual data. The interface has the notion of a named entry 44 - * which has a name (AA_NAME typecode followed by name string) followed by 45 - * the entries typecode and data. Named types allow for optional 46 - * elements and extensions to be added and tested for without breaking 47 - * backwards compatibility. 48 - */ 49 - 50 - enum aa_code { 51 - AA_U8, 52 - AA_U16, 53 - AA_U32, 54 - AA_U64, 55 - AA_NAME, /* same as string except it is items name */ 56 - AA_STRING, 57 - AA_BLOB, 58 - AA_STRUCT, 59 - AA_STRUCTEND, 60 - AA_LIST, 61 - AA_LISTEND, 62 - AA_ARRAY, 63 - AA_ARRAYEND, 64 - }; 65 - 66 - /* 67 - * aa_ext is the read of the buffer containing the serialized profile. The 68 - * data is copied into a kernel buffer in apparmorfs and then handed off to 69 - * the unpack routines. 70 - */ 71 - struct aa_ext { 72 - void *start; 73 - void *end; 74 - void *pos; /* pointer to current position in the buffer */ 75 - u32 version; 76 - }; 77 39 78 40 /* audit callback for unpack fields */ 79 41 static void audit_cb(struct audit_buffer *ab, void *va) ··· 163 199 } 164 200 165 201 /* test if read will be in packed data bounds */ 166 - static bool inbounds(struct aa_ext *e, size_t size) 202 + VISIBLE_IF_KUNIT bool aa_inbounds(struct aa_ext *e, size_t size) 167 203 { 168 204 return (size <= e->end - e->pos); 169 205 } 206 + EXPORT_SYMBOL_IF_KUNIT(aa_inbounds); 170 207 171 208 static void *kvmemdup(const void *src, size_t len) 172 209 { ··· 179 214 } 180 215 181 216 /** 182 - * unpack_u16_chunk - test and do bounds checking for a u16 size based chunk 217 + * aa_unpack_u16_chunk - test and do bounds checking for a u16 size based chunk 183 218 * @e: serialized data read head (NOT NULL) 184 219 * @chunk: start address for chunk of data (NOT NULL) 185 220 * 186 221 * Returns: the size of chunk found with the read head at the end of the chunk. 187 222 */ 188 - static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk) 223 + VISIBLE_IF_KUNIT size_t aa_unpack_u16_chunk(struct aa_ext *e, char **chunk) 189 224 { 190 225 size_t size = 0; 191 226 void *pos = e->pos; 192 227 193 - if (!inbounds(e, sizeof(u16))) 228 + if (!aa_inbounds(e, sizeof(u16))) 194 229 goto fail; 195 230 size = le16_to_cpu(get_unaligned((__le16 *) e->pos)); 196 231 e->pos += sizeof(__le16); 197 - if (!inbounds(e, size)) 232 + if (!aa_inbounds(e, size)) 198 233 goto fail; 199 234 *chunk = e->pos; 200 235 e->pos += size; ··· 204 239 e->pos = pos; 205 240 return 0; 206 241 } 242 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_u16_chunk); 207 243 208 244 /* unpack control byte */ 209 - static bool unpack_X(struct aa_ext *e, enum aa_code code) 245 + VISIBLE_IF_KUNIT bool aa_unpack_X(struct aa_ext *e, enum aa_code code) 210 246 { 211 - if (!inbounds(e, 1)) 247 + if (!aa_inbounds(e, 1)) 212 248 return false; 213 249 if (*(u8 *) e->pos != code) 214 250 return false; 215 251 e->pos++; 216 252 return true; 217 253 } 254 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_X); 218 255 219 256 /** 220 - * unpack_nameX - check is the next element is of type X with a name of @name 257 + * aa_unpack_nameX - check is the next element is of type X with a name of @name 221 258 * @e: serialized data extent information (NOT NULL) 222 259 * @code: type code 223 260 * @name: name to match to the serialized element. (MAYBE NULL) ··· 234 267 * 235 268 * Returns: false if either match fails, the read head does not move 236 269 */ 237 - static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) 270 + VISIBLE_IF_KUNIT bool aa_unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) 238 271 { 239 272 /* 240 273 * May need to reset pos if name or type doesn't match ··· 244 277 * Check for presence of a tagname, and if present name size 245 278 * AA_NAME tag value is a u16. 246 279 */ 247 - if (unpack_X(e, AA_NAME)) { 280 + if (aa_unpack_X(e, AA_NAME)) { 248 281 char *tag = NULL; 249 - size_t size = unpack_u16_chunk(e, &tag); 282 + size_t size = aa_unpack_u16_chunk(e, &tag); 250 283 /* if a name is specified it must match. otherwise skip tag */ 251 284 if (name && (!size || tag[size-1] != '\0' || strcmp(name, tag))) 252 285 goto fail; ··· 256 289 } 257 290 258 291 /* now check if type code matches */ 259 - if (unpack_X(e, code)) 292 + if (aa_unpack_X(e, code)) 260 293 return true; 261 294 262 295 fail: 263 296 e->pos = pos; 264 297 return false; 265 298 } 299 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_nameX); 266 300 267 301 static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) 268 302 { 269 303 void *pos = e->pos; 270 304 271 - if (unpack_nameX(e, AA_U8, name)) { 272 - if (!inbounds(e, sizeof(u8))) 305 + if (aa_unpack_nameX(e, AA_U8, name)) { 306 + if (!aa_inbounds(e, sizeof(u8))) 273 307 goto fail; 274 308 if (data) 275 309 *data = *((u8 *)e->pos); ··· 283 315 return false; 284 316 } 285 317 286 - static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 318 + VISIBLE_IF_KUNIT bool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name) 287 319 { 288 320 void *pos = e->pos; 289 321 290 - if (unpack_nameX(e, AA_U32, name)) { 291 - if (!inbounds(e, sizeof(u32))) 322 + if (aa_unpack_nameX(e, AA_U32, name)) { 323 + if (!aa_inbounds(e, sizeof(u32))) 292 324 goto fail; 293 325 if (data) 294 326 *data = le32_to_cpu(get_unaligned((__le32 *) e->pos)); ··· 300 332 e->pos = pos; 301 333 return false; 302 334 } 335 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_u32); 303 336 304 - static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) 337 + VISIBLE_IF_KUNIT bool aa_unpack_u64(struct aa_ext *e, u64 *data, const char *name) 305 338 { 306 339 void *pos = e->pos; 307 340 308 - if (unpack_nameX(e, AA_U64, name)) { 309 - if (!inbounds(e, sizeof(u64))) 341 + if (aa_unpack_nameX(e, AA_U64, name)) { 342 + if (!aa_inbounds(e, sizeof(u64))) 310 343 goto fail; 311 344 if (data) 312 345 *data = le64_to_cpu(get_unaligned((__le64 *) e->pos)); ··· 319 350 e->pos = pos; 320 351 return false; 321 352 } 353 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_u64); 322 354 323 - static size_t unpack_array(struct aa_ext *e, const char *name) 355 + VISIBLE_IF_KUNIT size_t aa_unpack_array(struct aa_ext *e, const char *name) 324 356 { 325 357 void *pos = e->pos; 326 358 327 - if (unpack_nameX(e, AA_ARRAY, name)) { 359 + if (aa_unpack_nameX(e, AA_ARRAY, name)) { 328 360 int size; 329 - if (!inbounds(e, sizeof(u16))) 361 + if (!aa_inbounds(e, sizeof(u16))) 330 362 goto fail; 331 363 size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos)); 332 364 e->pos += sizeof(u16); ··· 338 368 e->pos = pos; 339 369 return 0; 340 370 } 371 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_array); 341 372 342 - static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) 373 + VISIBLE_IF_KUNIT size_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name) 343 374 { 344 375 void *pos = e->pos; 345 376 346 - if (unpack_nameX(e, AA_BLOB, name)) { 377 + if (aa_unpack_nameX(e, AA_BLOB, name)) { 347 378 u32 size; 348 - if (!inbounds(e, sizeof(u32))) 379 + if (!aa_inbounds(e, sizeof(u32))) 349 380 goto fail; 350 381 size = le32_to_cpu(get_unaligned((__le32 *) e->pos)); 351 382 e->pos += sizeof(u32); 352 - if (inbounds(e, (size_t) size)) { 383 + if (aa_inbounds(e, (size_t) size)) { 353 384 *blob = e->pos; 354 385 e->pos += size; 355 386 return size; ··· 361 390 e->pos = pos; 362 391 return 0; 363 392 } 393 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_blob); 364 394 365 - static int unpack_str(struct aa_ext *e, const char **string, const char *name) 395 + VISIBLE_IF_KUNIT int aa_unpack_str(struct aa_ext *e, const char **string, const char *name) 366 396 { 367 397 char *src_str; 368 398 size_t size = 0; 369 399 void *pos = e->pos; 370 400 *string = NULL; 371 - if (unpack_nameX(e, AA_STRING, name)) { 372 - size = unpack_u16_chunk(e, &src_str); 401 + if (aa_unpack_nameX(e, AA_STRING, name)) { 402 + size = aa_unpack_u16_chunk(e, &src_str); 373 403 if (size) { 374 404 /* strings are null terminated, length is size - 1 */ 375 405 if (src_str[size - 1] != 0) ··· 385 413 e->pos = pos; 386 414 return 0; 387 415 } 416 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_str); 388 417 389 - static int unpack_strdup(struct aa_ext *e, char **string, const char *name) 418 + VISIBLE_IF_KUNIT int aa_unpack_strdup(struct aa_ext *e, char **string, const char *name) 390 419 { 391 420 const char *tmp; 392 421 void *pos = e->pos; 393 - int res = unpack_str(e, &tmp, name); 422 + int res = aa_unpack_str(e, &tmp, name); 394 423 *string = NULL; 395 424 396 425 if (!res) ··· 405 432 406 433 return res; 407 434 } 435 + EXPORT_SYMBOL_IF_KUNIT(aa_unpack_strdup); 408 436 409 437 410 438 /** ··· 420 446 size_t size; 421 447 struct aa_dfa *dfa = NULL; 422 448 423 - size = unpack_blob(e, &blob, "aadfa"); 449 + size = aa_unpack_blob(e, &blob, "aadfa"); 424 450 if (size) { 425 451 /* 426 452 * The dfa is aligned with in the blob to 8 bytes ··· 456 482 void *saved_pos = e->pos; 457 483 458 484 /* exec table is optional */ 459 - if (unpack_nameX(e, AA_STRUCT, "xtable")) { 485 + if (aa_unpack_nameX(e, AA_STRUCT, "xtable")) { 460 486 int i, size; 461 487 462 - size = unpack_array(e, NULL); 488 + size = aa_unpack_array(e, NULL); 463 489 /* currently 4 exec bits and entries 0-3 are reserved iupcx */ 464 490 if (size > 16 - 4) 465 491 goto fail; ··· 471 497 profile->file.trans.size = size; 472 498 for (i = 0; i < size; i++) { 473 499 char *str; 474 - int c, j, pos, size2 = unpack_strdup(e, &str, NULL); 475 - /* unpack_strdup verifies that the last character is 500 + int c, j, pos, size2 = aa_unpack_strdup(e, &str, NULL); 501 + /* aa_unpack_strdup verifies that the last character is 476 502 * null termination byte. 477 503 */ 478 504 if (!size2) ··· 495 521 goto fail; 496 522 /* beginning with : requires an embedded \0, 497 523 * verify that exactly 1 internal \0 exists 498 - * trailing \0 already verified by unpack_strdup 524 + * trailing \0 already verified by aa_unpack_strdup 499 525 * 500 526 * convert \0 back to : for label_parse 501 527 */ ··· 507 533 /* fail - all other cases with embedded \0 */ 508 534 goto fail; 509 535 } 510 - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 536 + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL)) 511 537 goto fail; 512 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 538 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 513 539 goto fail; 514 540 } 515 541 return true; ··· 524 550 { 525 551 void *pos = e->pos; 526 552 527 - if (unpack_nameX(e, AA_STRUCT, "xattrs")) { 553 + if (aa_unpack_nameX(e, AA_STRUCT, "xattrs")) { 528 554 int i, size; 529 555 530 - size = unpack_array(e, NULL); 556 + size = aa_unpack_array(e, NULL); 531 557 profile->xattr_count = size; 532 558 profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL); 533 559 if (!profile->xattrs) 534 560 goto fail; 535 561 for (i = 0; i < size; i++) { 536 - if (!unpack_strdup(e, &profile->xattrs[i], NULL)) 562 + if (!aa_unpack_strdup(e, &profile->xattrs[i], NULL)) 537 563 goto fail; 538 564 } 539 - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 565 + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL)) 540 566 goto fail; 541 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 567 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 542 568 goto fail; 543 569 } 544 570 ··· 554 580 void *pos = e->pos; 555 581 int i, size; 556 582 557 - if (unpack_nameX(e, AA_STRUCT, "secmark")) { 558 - size = unpack_array(e, NULL); 583 + if (aa_unpack_nameX(e, AA_STRUCT, "secmark")) { 584 + size = aa_unpack_array(e, NULL); 559 585 560 586 profile->secmark = kcalloc(size, sizeof(struct aa_secmark), 561 587 GFP_KERNEL); ··· 569 595 goto fail; 570 596 if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) 571 597 goto fail; 572 - if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) 598 + if (!aa_unpack_strdup(e, &profile->secmark[i].label, NULL)) 573 599 goto fail; 574 600 } 575 - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 601 + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL)) 576 602 goto fail; 577 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 603 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 578 604 goto fail; 579 605 } 580 606 ··· 598 624 void *pos = e->pos; 599 625 600 626 /* rlimits are optional */ 601 - if (unpack_nameX(e, AA_STRUCT, "rlimits")) { 627 + if (aa_unpack_nameX(e, AA_STRUCT, "rlimits")) { 602 628 int i, size; 603 629 u32 tmp = 0; 604 - if (!unpack_u32(e, &tmp, NULL)) 630 + if (!aa_unpack_u32(e, &tmp, NULL)) 605 631 goto fail; 606 632 profile->rlimits.mask = tmp; 607 633 608 - size = unpack_array(e, NULL); 634 + size = aa_unpack_array(e, NULL); 609 635 if (size > RLIM_NLIMITS) 610 636 goto fail; 611 637 for (i = 0; i < size; i++) { 612 638 u64 tmp2 = 0; 613 639 int a = aa_map_resource(i); 614 - if (!unpack_u64(e, &tmp2, NULL)) 640 + if (!aa_unpack_u64(e, &tmp2, NULL)) 615 641 goto fail; 616 642 profile->rlimits.limits[a].rlim_max = tmp2; 617 643 } 618 - if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 644 + if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL)) 619 645 goto fail; 620 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 646 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 621 647 goto fail; 622 648 } 623 649 return true; ··· 665 691 *ns_name = NULL; 666 692 667 693 /* check that we have the right struct being passed */ 668 - if (!unpack_nameX(e, AA_STRUCT, "profile")) 694 + if (!aa_unpack_nameX(e, AA_STRUCT, "profile")) 669 695 goto fail; 670 - if (!unpack_str(e, &name, NULL)) 696 + if (!aa_unpack_str(e, &name, NULL)) 671 697 goto fail; 672 698 if (*name == '\0') 673 699 goto fail; ··· 687 713 return ERR_PTR(-ENOMEM); 688 714 689 715 /* profile renaming is optional */ 690 - (void) unpack_str(e, &profile->rename, "rename"); 716 + (void) aa_unpack_str(e, &profile->rename, "rename"); 691 717 692 718 /* attachment string is optional */ 693 - (void) unpack_str(e, &profile->attach, "attach"); 719 + (void) aa_unpack_str(e, &profile->attach, "attach"); 694 720 695 721 /* xmatch is optional and may be NULL */ 696 722 profile->xmatch = unpack_dfa(e); ··· 702 728 } 703 729 /* xmatch_len is not optional if xmatch is set */ 704 730 if (profile->xmatch) { 705 - if (!unpack_u32(e, &tmp, NULL)) { 731 + if (!aa_unpack_u32(e, &tmp, NULL)) { 706 732 info = "missing xmatch len"; 707 733 goto fail; 708 734 } ··· 710 736 } 711 737 712 738 /* disconnected attachment string is optional */ 713 - (void) unpack_str(e, &profile->disconnected, "disconnected"); 739 + (void) aa_unpack_str(e, &profile->disconnected, "disconnected"); 714 740 715 741 /* per profile debug flags (complain, audit) */ 716 - if (!unpack_nameX(e, AA_STRUCT, "flags")) { 742 + if (!aa_unpack_nameX(e, AA_STRUCT, "flags")) { 717 743 info = "profile missing flags"; 718 744 goto fail; 719 745 } 720 746 info = "failed to unpack profile flags"; 721 - if (!unpack_u32(e, &tmp, NULL)) 747 + if (!aa_unpack_u32(e, &tmp, NULL)) 722 748 goto fail; 723 749 if (tmp & PACKED_FLAG_HAT) 724 750 profile->label.flags |= FLAG_HAT; ··· 726 752 profile->label.flags |= FLAG_DEBUG1; 727 753 if (tmp & PACKED_FLAG_DEBUG2) 728 754 profile->label.flags |= FLAG_DEBUG2; 729 - if (!unpack_u32(e, &tmp, NULL)) 755 + if (!aa_unpack_u32(e, &tmp, NULL)) 730 756 goto fail; 731 757 if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) { 732 758 profile->mode = APPARMOR_COMPLAIN; ··· 740 766 } else { 741 767 goto fail; 742 768 } 743 - if (!unpack_u32(e, &tmp, NULL)) 769 + if (!aa_unpack_u32(e, &tmp, NULL)) 744 770 goto fail; 745 771 if (tmp) 746 772 profile->audit = AUDIT_ALL; 747 773 748 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 774 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 749 775 goto fail; 750 776 751 777 /* path_flags is optional */ 752 - if (unpack_u32(e, &profile->path_flags, "path_flags")) 778 + if (aa_unpack_u32(e, &profile->path_flags, "path_flags")) 753 779 profile->path_flags |= profile->label.flags & 754 780 PATH_MEDIATE_DELETED; 755 781 else ··· 757 783 profile->path_flags = PATH_MEDIATE_DELETED; 758 784 759 785 info = "failed to unpack profile capabilities"; 760 - if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 786 + if (!aa_unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 761 787 goto fail; 762 - if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) 788 + if (!aa_unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) 763 789 goto fail; 764 - if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) 790 + if (!aa_unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) 765 791 goto fail; 766 - if (!unpack_u32(e, &tmpcap.cap[0], NULL)) 792 + if (!aa_unpack_u32(e, &tmpcap.cap[0], NULL)) 767 793 goto fail; 768 794 769 795 info = "failed to unpack upper profile capabilities"; 770 - if (unpack_nameX(e, AA_STRUCT, "caps64")) { 796 + if (aa_unpack_nameX(e, AA_STRUCT, "caps64")) { 771 797 /* optional upper half of 64 bit caps */ 772 - if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) 798 + if (!aa_unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) 773 799 goto fail; 774 - if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) 800 + if (!aa_unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) 775 801 goto fail; 776 - if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) 802 + if (!aa_unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) 777 803 goto fail; 778 - if (!unpack_u32(e, &(tmpcap.cap[1]), NULL)) 804 + if (!aa_unpack_u32(e, &(tmpcap.cap[1]), NULL)) 779 805 goto fail; 780 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 806 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 781 807 goto fail; 782 808 } 783 809 784 810 info = "failed to unpack extended profile capabilities"; 785 - if (unpack_nameX(e, AA_STRUCT, "capsx")) { 811 + if (aa_unpack_nameX(e, AA_STRUCT, "capsx")) { 786 812 /* optional extended caps mediation mask */ 787 - if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) 813 + if (!aa_unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) 788 814 goto fail; 789 - if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 815 + if (!aa_unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 790 816 goto fail; 791 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 817 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 792 818 goto fail; 793 819 } 794 820 ··· 807 833 goto fail; 808 834 } 809 835 810 - if (unpack_nameX(e, AA_STRUCT, "policydb")) { 836 + if (aa_unpack_nameX(e, AA_STRUCT, "policydb")) { 811 837 /* generic policy dfa - optional and may be NULL */ 812 838 info = "failed to unpack policydb"; 813 839 profile->policy.dfa = unpack_dfa(e); ··· 819 845 error = -EPROTO; 820 846 goto fail; 821 847 } 822 - if (!unpack_u32(e, &profile->policy.start[0], "start")) 848 + if (!aa_unpack_u32(e, &profile->policy.start[0], "start")) 823 849 /* default start state */ 824 850 profile->policy.start[0] = DFA_START; 825 851 /* setup class index */ ··· 829 855 profile->policy.start[0], 830 856 i); 831 857 } 832 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 858 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 833 859 goto fail; 834 860 } else 835 861 profile->policy.dfa = aa_get_dfa(nulldfa); ··· 842 868 info = "failed to unpack profile file rules"; 843 869 goto fail; 844 870 } else if (profile->file.dfa) { 845 - if (!unpack_u32(e, &profile->file.start, "dfa_start")) 871 + if (!aa_unpack_u32(e, &profile->file.start, "dfa_start")) 846 872 /* default start state */ 847 873 profile->file.start = DFA_START; 848 874 } else if (profile->policy.dfa && ··· 857 883 goto fail; 858 884 } 859 885 860 - if (unpack_nameX(e, AA_STRUCT, "data")) { 886 + if (aa_unpack_nameX(e, AA_STRUCT, "data")) { 861 887 info = "out of memory"; 862 888 profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL); 863 889 if (!profile->data) ··· 875 901 goto fail; 876 902 } 877 903 878 - while (unpack_strdup(e, &key, NULL)) { 904 + while (aa_unpack_strdup(e, &key, NULL)) { 879 905 data = kzalloc(sizeof(*data), GFP_KERNEL); 880 906 if (!data) { 881 907 kfree_sensitive(key); ··· 883 909 } 884 910 885 911 data->key = key; 886 - data->size = unpack_blob(e, &data->data, NULL); 912 + data->size = aa_unpack_blob(e, &data->data, NULL); 887 913 data->data = kvmemdup(data->data, data->size); 888 914 if (data->size && !data->data) { 889 915 kfree_sensitive(data->key); ··· 895 921 profile->data->p); 896 922 } 897 923 898 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { 924 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) { 899 925 info = "failed to unpack end of key, value data table"; 900 926 goto fail; 901 927 } 902 928 } 903 929 904 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { 930 + if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) { 905 931 info = "failed to unpack end of profile"; 906 932 goto fail; 907 933 } ··· 934 960 *ns = NULL; 935 961 936 962 /* get the interface version */ 937 - if (!unpack_u32(e, &e->version, "version")) { 963 + if (!aa_unpack_u32(e, &e->version, "version")) { 938 964 if (required) { 939 965 audit_iface(NULL, NULL, NULL, "invalid profile format", 940 966 e, error); ··· 953 979 } 954 980 955 981 /* read the namespace if present */ 956 - if (unpack_str(e, &name, "namespace")) { 982 + if (aa_unpack_str(e, &name, "namespace")) { 957 983 if (*name == '\0') { 958 984 audit_iface(NULL, NULL, NULL, "invalid namespace name", 959 985 e, error); ··· 1225 1251 1226 1252 return error; 1227 1253 } 1228 - 1229 - #ifdef CONFIG_SECURITY_APPARMOR_KUNIT_TEST 1230 - #include "policy_unpack_test.c" 1231 - #endif /* CONFIG_SECURITY_APPARMOR_KUNIT_TEST */
+37 -32
security/apparmor/policy_unpack_test.c
··· 4 4 */ 5 5 6 6 #include <kunit/test.h> 7 + #include <kunit/visibility.h> 7 8 8 9 #include "include/policy.h" 9 10 #include "include/policy_unpack.h" ··· 43 42 (TEST_BLOB_BUF_OFFSET + 5 + TEST_BLOB_DATA_SIZE) 44 43 #define TEST_ARRAY_BUF_OFFSET \ 45 44 (TEST_NAMED_ARRAY_BUF_OFFSET + 3 + strlen(TEST_ARRAY_NAME) + 1) 45 + 46 + MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 46 47 47 48 struct policy_unpack_fixture { 48 49 struct aa_ext *e; ··· 128 125 { 129 126 struct policy_unpack_fixture *puf = test->priv; 130 127 131 - KUNIT_EXPECT_TRUE(test, inbounds(puf->e, 0)); 132 - KUNIT_EXPECT_TRUE(test, inbounds(puf->e, puf->e_size / 2)); 133 - KUNIT_EXPECT_TRUE(test, inbounds(puf->e, puf->e_size)); 128 + KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, 0)); 129 + KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, puf->e_size / 2)); 130 + KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, puf->e_size)); 134 131 } 135 132 136 133 static void policy_unpack_test_inbounds_when_out_of_bounds(struct kunit *test) 137 134 { 138 135 struct policy_unpack_fixture *puf = test->priv; 139 136 140 - KUNIT_EXPECT_FALSE(test, inbounds(puf->e, puf->e_size + 1)); 137 + KUNIT_EXPECT_FALSE(test, aa_inbounds(puf->e, puf->e_size + 1)); 141 138 } 142 139 143 140 static void policy_unpack_test_unpack_array_with_null_name(struct kunit *test) ··· 147 144 148 145 puf->e->pos += TEST_ARRAY_BUF_OFFSET; 149 146 150 - array_size = unpack_array(puf->e, NULL); 147 + array_size = aa_unpack_array(puf->e, NULL); 151 148 152 149 KUNIT_EXPECT_EQ(test, array_size, (u16)TEST_ARRAY_SIZE); 153 150 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 162 159 163 160 puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET; 164 161 165 - array_size = unpack_array(puf->e, name); 162 + array_size = aa_unpack_array(puf->e, name); 166 163 167 164 KUNIT_EXPECT_EQ(test, array_size, (u16)TEST_ARRAY_SIZE); 168 165 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 178 175 puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET; 179 176 puf->e->end = puf->e->start + TEST_ARRAY_BUF_OFFSET + sizeof(u16); 180 177 181 - array_size = unpack_array(puf->e, name); 178 + array_size = aa_unpack_array(puf->e, name); 182 179 183 180 KUNIT_EXPECT_EQ(test, array_size, 0); 184 181 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 192 189 size_t size; 193 190 194 191 puf->e->pos += TEST_BLOB_BUF_OFFSET; 195 - size = unpack_blob(puf->e, &blob, NULL); 192 + size = aa_unpack_blob(puf->e, &blob, NULL); 196 193 197 194 KUNIT_ASSERT_EQ(test, size, TEST_BLOB_DATA_SIZE); 198 195 KUNIT_EXPECT_TRUE(test, ··· 206 203 size_t size; 207 204 208 205 puf->e->pos += TEST_NAMED_BLOB_BUF_OFFSET; 209 - size = unpack_blob(puf->e, &blob, TEST_BLOB_NAME); 206 + size = aa_unpack_blob(puf->e, &blob, TEST_BLOB_NAME); 210 207 211 208 KUNIT_ASSERT_EQ(test, size, TEST_BLOB_DATA_SIZE); 212 209 KUNIT_EXPECT_TRUE(test, ··· 225 222 puf->e->end = puf->e->start + TEST_BLOB_BUF_OFFSET 226 223 + TEST_BLOB_DATA_SIZE - 1; 227 224 228 - size = unpack_blob(puf->e, &blob, TEST_BLOB_NAME); 225 + size = aa_unpack_blob(puf->e, &blob, TEST_BLOB_NAME); 229 226 230 227 KUNIT_EXPECT_EQ(test, size, 0); 231 228 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start); ··· 238 235 size_t size; 239 236 240 237 puf->e->pos += TEST_STRING_BUF_OFFSET; 241 - size = unpack_str(puf->e, &string, NULL); 238 + size = aa_unpack_str(puf->e, &string, NULL); 242 239 243 240 KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1); 244 241 KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA); ··· 250 247 const char *string = NULL; 251 248 size_t size; 252 249 253 - size = unpack_str(puf->e, &string, TEST_STRING_NAME); 250 + size = aa_unpack_str(puf->e, &string, TEST_STRING_NAME); 254 251 255 252 KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1); 256 253 KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA); ··· 266 263 puf->e->end = puf->e->pos + TEST_STRING_BUF_OFFSET 267 264 + strlen(TEST_STRING_DATA) - 1; 268 265 269 - size = unpack_str(puf->e, &string, TEST_STRING_NAME); 266 + size = aa_unpack_str(puf->e, &string, TEST_STRING_NAME); 270 267 271 268 KUNIT_EXPECT_EQ(test, size, 0); 272 269 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start); ··· 279 276 size_t size; 280 277 281 278 puf->e->pos += TEST_STRING_BUF_OFFSET; 282 - size = unpack_strdup(puf->e, &string, NULL); 279 + size = aa_unpack_strdup(puf->e, &string, NULL); 283 280 284 281 KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1); 285 282 KUNIT_EXPECT_FALSE(test, ··· 294 291 char *string = NULL; 295 292 size_t size; 296 293 297 - size = unpack_strdup(puf->e, &string, TEST_STRING_NAME); 294 + size = aa_unpack_strdup(puf->e, &string, TEST_STRING_NAME); 298 295 299 296 KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1); 300 297 KUNIT_EXPECT_FALSE(test, ··· 313 310 puf->e->end = puf->e->pos + TEST_STRING_BUF_OFFSET 314 311 + strlen(TEST_STRING_DATA) - 1; 315 312 316 - size = unpack_strdup(puf->e, &string, TEST_STRING_NAME); 313 + size = aa_unpack_strdup(puf->e, &string, TEST_STRING_NAME); 317 314 318 315 KUNIT_EXPECT_EQ(test, size, 0); 319 316 KUNIT_EXPECT_NULL(test, string); ··· 327 324 328 325 puf->e->pos += TEST_U32_BUF_OFFSET; 329 326 330 - success = unpack_nameX(puf->e, AA_U32, NULL); 327 + success = aa_unpack_nameX(puf->e, AA_U32, NULL); 331 328 332 329 KUNIT_EXPECT_TRUE(test, success); 333 330 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 341 338 342 339 puf->e->pos += TEST_U32_BUF_OFFSET; 343 340 344 - success = unpack_nameX(puf->e, AA_BLOB, NULL); 341 + success = aa_unpack_nameX(puf->e, AA_BLOB, NULL); 345 342 346 343 KUNIT_EXPECT_FALSE(test, success); 347 344 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 356 353 357 354 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 358 355 359 - success = unpack_nameX(puf->e, AA_U32, name); 356 + success = aa_unpack_nameX(puf->e, AA_U32, name); 360 357 361 358 KUNIT_EXPECT_TRUE(test, success); 362 359 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 371 368 372 369 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 373 370 374 - success = unpack_nameX(puf->e, AA_U32, name); 371 + success = aa_unpack_nameX(puf->e, AA_U32, name); 375 372 376 373 KUNIT_EXPECT_FALSE(test, success); 377 374 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 392 389 */ 393 390 puf->e->end += TEST_U16_DATA; 394 391 395 - size = unpack_u16_chunk(puf->e, &chunk); 392 + size = aa_unpack_u16_chunk(puf->e, &chunk); 396 393 397 394 KUNIT_EXPECT_PTR_EQ(test, chunk, 398 395 puf->e->start + TEST_U16_OFFSET + 2); ··· 409 406 410 407 puf->e->pos = puf->e->end - 1; 411 408 412 - size = unpack_u16_chunk(puf->e, &chunk); 409 + size = aa_unpack_u16_chunk(puf->e, &chunk); 413 410 414 411 KUNIT_EXPECT_EQ(test, size, 0); 415 412 KUNIT_EXPECT_NULL(test, chunk); ··· 431 428 */ 432 429 puf->e->end = puf->e->pos + TEST_U16_DATA - 1; 433 430 434 - size = unpack_u16_chunk(puf->e, &chunk); 431 + size = aa_unpack_u16_chunk(puf->e, &chunk); 435 432 436 433 KUNIT_EXPECT_EQ(test, size, 0); 437 434 KUNIT_EXPECT_NULL(test, chunk); ··· 446 443 447 444 puf->e->pos += TEST_U32_BUF_OFFSET; 448 445 449 - success = unpack_u32(puf->e, &data, NULL); 446 + success = aa_unpack_u32(puf->e, &data, NULL); 450 447 451 448 KUNIT_EXPECT_TRUE(test, success); 452 449 KUNIT_EXPECT_EQ(test, data, TEST_U32_DATA); ··· 463 460 464 461 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 465 462 466 - success = unpack_u32(puf->e, &data, name); 463 + success = aa_unpack_u32(puf->e, &data, name); 467 464 468 465 KUNIT_EXPECT_TRUE(test, success); 469 466 KUNIT_EXPECT_EQ(test, data, TEST_U32_DATA); ··· 481 478 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 482 479 puf->e->end = puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32); 483 480 484 - success = unpack_u32(puf->e, &data, name); 481 + success = aa_unpack_u32(puf->e, &data, name); 485 482 486 483 KUNIT_EXPECT_FALSE(test, success); 487 484 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 496 493 497 494 puf->e->pos += TEST_U64_BUF_OFFSET; 498 495 499 - success = unpack_u64(puf->e, &data, NULL); 496 + success = aa_unpack_u64(puf->e, &data, NULL); 500 497 501 498 KUNIT_EXPECT_TRUE(test, success); 502 499 KUNIT_EXPECT_EQ(test, data, TEST_U64_DATA); ··· 513 510 514 511 puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; 515 512 516 - success = unpack_u64(puf->e, &data, name); 513 + success = aa_unpack_u64(puf->e, &data, name); 517 514 518 515 KUNIT_EXPECT_TRUE(test, success); 519 516 KUNIT_EXPECT_EQ(test, data, TEST_U64_DATA); ··· 531 528 puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; 532 529 puf->e->end = puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64); 533 530 534 - success = unpack_u64(puf->e, &data, name); 531 + success = aa_unpack_u64(puf->e, &data, name); 535 532 536 533 KUNIT_EXPECT_FALSE(test, success); 537 534 KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, ··· 541 538 static void policy_unpack_test_unpack_X_code_match(struct kunit *test) 542 539 { 543 540 struct policy_unpack_fixture *puf = test->priv; 544 - bool success = unpack_X(puf->e, AA_NAME); 541 + bool success = aa_unpack_X(puf->e, AA_NAME); 545 542 546 543 KUNIT_EXPECT_TRUE(test, success); 547 544 KUNIT_EXPECT_TRUE(test, puf->e->pos == puf->e->start + 1); ··· 550 547 static void policy_unpack_test_unpack_X_code_mismatch(struct kunit *test) 551 548 { 552 549 struct policy_unpack_fixture *puf = test->priv; 553 - bool success = unpack_X(puf->e, AA_STRING); 550 + bool success = aa_unpack_X(puf->e, AA_STRING); 554 551 555 552 KUNIT_EXPECT_FALSE(test, success); 556 553 KUNIT_EXPECT_TRUE(test, puf->e->pos == puf->e->start); ··· 562 559 bool success; 563 560 564 561 puf->e->pos = puf->e->end; 565 - success = unpack_X(puf->e, AA_NAME); 562 + success = aa_unpack_X(puf->e, AA_NAME); 566 563 567 564 KUNIT_EXPECT_FALSE(test, success); 568 565 } ··· 608 605 }; 609 606 610 607 kunit_test_suite(apparmor_policy_unpack_test_module); 608 + 609 + MODULE_LICENSE("GPL");
+19 -17
tools/testing/kunit/kunit.py
··· 192 192 def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]: 193 193 parse_start = time.time() 194 194 195 - test_result = kunit_parser.Test() 196 - 197 195 if request.raw_output: 198 196 # Treat unparsed results as one passing test. 199 - test_result.status = kunit_parser.TestStatus.SUCCESS 200 - test_result.counts.passed = 1 197 + fake_test = kunit_parser.Test() 198 + fake_test.status = kunit_parser.TestStatus.SUCCESS 199 + fake_test.counts.passed = 1 201 200 202 201 output: Iterable[str] = input_data 203 202 if request.raw_output == 'all': 204 203 pass 205 204 elif request.raw_output == 'kunit': 206 - output = kunit_parser.extract_tap_lines(output, lstrip=False) 205 + output = kunit_parser.extract_tap_lines(output) 207 206 for line in output: 208 207 print(line.rstrip()) 208 + parse_time = time.time() - parse_start 209 + return KunitResult(KunitStatus.SUCCESS, parse_time), fake_test 209 210 210 - else: 211 - test_result = kunit_parser.parse_run_tests(input_data) 212 - parse_end = time.time() 211 + 212 + # Actually parse the test results. 213 + test = kunit_parser.parse_run_tests(input_data) 214 + parse_time = time.time() - parse_start 213 215 214 216 if request.json: 215 217 json_str = kunit_json.get_json_result( 216 - test=test_result, 218 + test=test, 217 219 metadata=metadata) 218 220 if request.json == 'stdout': 219 221 print(json_str) ··· 225 223 stdout.print_with_timestamp("Test results stored in %s" % 226 224 os.path.abspath(request.json)) 227 225 228 - if test_result.status != kunit_parser.TestStatus.SUCCESS: 229 - return KunitResult(KunitStatus.TEST_FAILURE, parse_end - parse_start), test_result 226 + if test.status != kunit_parser.TestStatus.SUCCESS: 227 + return KunitResult(KunitStatus.TEST_FAILURE, parse_time), test 230 228 231 - return KunitResult(KunitStatus.SUCCESS, parse_end - parse_start), test_result 229 + return KunitResult(KunitStatus.SUCCESS, parse_time), test 232 230 233 231 def run_tests(linux: kunit_kernel.LinuxSourceTree, 234 232 request: KunitRequest) -> KunitResult: ··· 361 359 choices=['suite', 'test']) 362 360 363 361 def add_parse_opts(parser) -> None: 364 - parser.add_argument('--raw_output', help='If set don\'t format output from kernel. ' 365 - 'If set to --raw_output=kunit, filters to just KUnit output.', 362 + parser.add_argument('--raw_output', help='If set don\'t parse output from kernel. ' 363 + 'By default, filters to just KUnit output. Use ' 364 + '--raw_output=all to show everything', 366 365 type=str, nargs='?', const='all', default=None, choices=['all', 'kunit']) 367 366 parser.add_argument('--json', 368 367 nargs='?', 369 - help='Stores test results in a JSON, and either ' 370 - 'prints to stdout or saves to file if a ' 371 - 'filename is specified', 368 + help='Prints parsed test results as JSON to stdout or a file if ' 369 + 'a filename is specified. Does nothing if --raw_output is set.', 372 370 type=str, const='stdout', default=None, metavar='FILE') 373 371 374 372
+123 -63
tools/testing/kunit/kunit_parser.py
··· 10 10 # Author: Rae Moar <rmoar@google.com> 11 11 12 12 from __future__ import annotations 13 + from dataclasses import dataclass 13 14 import re 14 15 import sys 16 + import textwrap 15 17 16 18 from enum import Enum, auto 17 19 from typing import Iterable, Iterator, List, Optional, Tuple ··· 60 58 self.counts.errors += 1 61 59 stdout.print_with_timestamp(stdout.red('[ERROR]') + f' Test: {self.name}: {error_message}') 62 60 61 + def ok_status(self) -> bool: 62 + """Returns true if the status was ok, i.e. passed or skipped.""" 63 + return self.status in (TestStatus.SUCCESS, TestStatus.SKIPPED) 64 + 63 65 class TestStatus(Enum): 64 66 """An enumeration class to represent the status of a test.""" 65 67 SUCCESS = auto() ··· 73 67 NO_TESTS = auto() 74 68 FAILURE_TO_PARSE_TESTS = auto() 75 69 70 + @dataclass 76 71 class TestCounts: 77 72 """ 78 73 Tracks the counts of statuses of all test cases and any errors within 79 74 a Test. 80 - 81 - Attributes: 82 - passed : int - the number of tests that have passed 83 - failed : int - the number of tests that have failed 84 - crashed : int - the number of tests that have crashed 85 - skipped : int - the number of tests that have skipped 86 - errors : int - the number of errors in the test and subtests 87 75 """ 88 - def __init__(self): 89 - """Creates TestCounts object with counts of all test 90 - statuses and test errors set to 0. 91 - """ 92 - self.passed = 0 93 - self.failed = 0 94 - self.crashed = 0 95 - self.skipped = 0 96 - self.errors = 0 76 + passed: int = 0 77 + failed: int = 0 78 + crashed: int = 0 79 + skipped: int = 0 80 + errors: int = 0 97 81 98 82 def __str__(self) -> str: 99 83 """Returns the string representation of a TestCounts object.""" ··· 209 213 210 214 # Parsing helper methods: 211 215 212 - KTAP_START = re.compile(r'KTAP version ([0-9]+)$') 213 - TAP_START = re.compile(r'TAP version ([0-9]+)$') 214 - KTAP_END = re.compile('(List of all partitions:|' 216 + KTAP_START = re.compile(r'\s*KTAP version ([0-9]+)$') 217 + TAP_START = re.compile(r'\s*TAP version ([0-9]+)$') 218 + KTAP_END = re.compile(r'\s*(List of all partitions:|' 215 219 'Kernel panic - not syncing: VFS:|reboot: System halted)') 216 220 217 - def extract_tap_lines(kernel_output: Iterable[str], lstrip=True) -> LineStream: 221 + def extract_tap_lines(kernel_output: Iterable[str]) -> LineStream: 218 222 """Extracts KTAP lines from the kernel output.""" 219 223 def isolate_ktap_output(kernel_output: Iterable[str]) \ 220 224 -> Iterator[Tuple[int, str]]: ··· 240 244 # stop extracting KTAP lines 241 245 break 242 246 elif started: 243 - # remove the prefix and optionally any leading 244 - # whitespace. Our parsing logic relies on this. 247 + # remove the prefix, if any. 245 248 line = line[prefix_len:] 246 - if lstrip: 247 - line = line.lstrip() 248 249 yield line_num, line 249 250 return LineStream(lines=isolate_ktap_output(kernel_output)) 250 251 ··· 293 300 check_version(version_num, TAP_VERSIONS, 'TAP', test) 294 301 else: 295 302 return False 296 - test.log.append(lines.pop()) 303 + lines.pop() 297 304 return True 298 305 299 - TEST_HEADER = re.compile(r'^# Subtest: (.*)$') 306 + TEST_HEADER = re.compile(r'^\s*# Subtest: (.*)$') 300 307 301 308 def parse_test_header(lines: LineStream, test: Test) -> bool: 302 309 """ ··· 316 323 match = TEST_HEADER.match(lines.peek()) 317 324 if not match: 318 325 return False 319 - test.log.append(lines.pop()) 320 326 test.name = match.group(1) 327 + lines.pop() 321 328 return True 322 329 323 - TEST_PLAN = re.compile(r'1\.\.([0-9]+)') 330 + TEST_PLAN = re.compile(r'^\s*1\.\.([0-9]+)') 324 331 325 332 def parse_test_plan(lines: LineStream, test: Test) -> bool: 326 333 """ ··· 343 350 if not match: 344 351 test.expected_count = None 345 352 return False 346 - test.log.append(lines.pop()) 347 353 expected_count = int(match.group(1)) 348 354 test.expected_count = expected_count 355 + lines.pop() 349 356 return True 350 357 351 - TEST_RESULT = re.compile(r'^(ok|not ok) ([0-9]+) (- )?([^#]*)( # .*)?$') 358 + TEST_RESULT = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?([^#]*)( # .*)?$') 352 359 353 - TEST_RESULT_SKIP = re.compile(r'^(ok|not ok) ([0-9]+) (- )?(.*) # SKIP(.*)$') 360 + TEST_RESULT_SKIP = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?(.*) # SKIP(.*)$') 354 361 355 362 def peek_test_name_match(lines: LineStream, test: Test) -> bool: 356 363 """ ··· 407 414 # Check if line matches test result line format 408 415 if not match: 409 416 return False 410 - test.log.append(lines.pop()) 417 + lines.pop() 411 418 412 419 # Set name of test object 413 420 if skip_match: ··· 439 446 - '# Subtest: [test name]' 440 447 - '[ok|not ok] [test number] [-] [test name] [optional skip 441 448 directive]' 449 + - 'KTAP version [version number]' 442 450 443 451 Parameters: 444 452 lines - LineStream of KTAP output to parse ··· 448 454 Log of diagnostic lines 449 455 """ 450 456 log = [] # type: List[str] 451 - while lines and not TEST_RESULT.match(lines.peek()) and not \ 452 - TEST_HEADER.match(lines.peek()): 457 + non_diagnostic_lines = [TEST_RESULT, TEST_HEADER, KTAP_START] 458 + while lines and not any(re.match(lines.peek()) 459 + for re in non_diagnostic_lines): 453 460 log.append(lines.pop()) 454 461 return log 455 462 ··· 496 501 test - Test object representing current test being printed 497 502 """ 498 503 message = test.name 504 + if message != "": 505 + # Add a leading space before the subtest counts only if a test name 506 + # is provided using a "# Subtest" header line. 507 + message += " " 499 508 if test.expected_count: 500 509 if test.expected_count == 1: 501 - message += ' (1 subtest)' 510 + message += '(1 subtest)' 502 511 else: 503 - message += f' ({test.expected_count} subtests)' 512 + message += f'({test.expected_count} subtests)' 504 513 stdout.print_with_timestamp(format_test_divider(message, len(message))) 505 514 506 515 def print_log(log: Iterable[str]) -> None: 507 516 """Prints all strings in saved log for test in yellow.""" 508 - for m in log: 509 - stdout.print_with_timestamp(stdout.yellow(m)) 517 + formatted = textwrap.dedent('\n'.join(log)) 518 + for line in formatted.splitlines(): 519 + stdout.print_with_timestamp(stdout.yellow(line)) 510 520 511 521 def format_test_result(test: Test) -> str: 512 522 """ ··· 565 565 stdout.print_with_timestamp(format_test_divider(message, 566 566 len(message) - stdout.color_len())) 567 567 568 + 569 + 570 + def _summarize_failed_tests(test: Test) -> str: 571 + """Tries to summarize all the failing subtests in `test`.""" 572 + 573 + def failed_names(test: Test, parent_name: str) -> List[str]: 574 + # Note: we use 'main' internally for the top-level test. 575 + if not parent_name or parent_name == 'main': 576 + full_name = test.name 577 + else: 578 + full_name = parent_name + '.' + test.name 579 + 580 + if not test.subtests: # this is a leaf node 581 + return [full_name] 582 + 583 + # If all the children failed, just say this subtest failed. 584 + # Don't summarize it down "the top-level test failed", though. 585 + failed_subtests = [sub for sub in test.subtests if not sub.ok_status()] 586 + if parent_name and len(failed_subtests) == len(test.subtests): 587 + return [full_name] 588 + 589 + all_failures = [] # type: List[str] 590 + for t in failed_subtests: 591 + all_failures.extend(failed_names(t, full_name)) 592 + return all_failures 593 + 594 + failures = failed_names(test, '') 595 + # If there are too many failures, printing them out will just be noisy. 596 + if len(failures) > 10: # this is an arbitrary limit 597 + return '' 598 + 599 + return 'Failures: ' + ', '.join(failures) 600 + 601 + 568 602 def print_summary_line(test: Test) -> None: 569 603 """ 570 604 Prints summary line of test object. Color of line is dependent on ··· 620 586 else: 621 587 color = stdout.red 622 588 stdout.print_with_timestamp(color(f'Testing complete. {test.counts}')) 589 + 590 + # Summarize failures that might have gone off-screen since we had a lot 591 + # of tests (arbitrarily defined as >=100 for now). 592 + if test.ok_status() or test.counts.total() < 100: 593 + return 594 + summarized = _summarize_failed_tests(test) 595 + if not summarized: 596 + return 597 + stdout.print_with_timestamp(color(summarized)) 623 598 624 599 # Other methods: 625 600 ··· 652 609 elif test.counts.get_status() == TestStatus.TEST_CRASHED: 653 610 test.status = TestStatus.TEST_CRASHED 654 611 655 - def parse_test(lines: LineStream, expected_num: int, log: List[str]) -> Test: 612 + def parse_test(lines: LineStream, expected_num: int, log: List[str], is_subtest: bool) -> Test: 656 613 """ 657 614 Finds next test to parse in LineStream, creates new Test object, 658 615 parses any subtests of the test, populates Test object with all ··· 670 627 1..4 671 628 [subtests] 672 629 673 - - Subtest header line 630 + - Subtest header (must include either the KTAP version line or 631 + "# Subtest" header line) 674 632 675 - Example: 633 + Example (preferred format with both KTAP version line and 634 + "# Subtest" line): 635 + 636 + KTAP version 1 637 + # Subtest: name 638 + 1..3 639 + [subtests] 640 + ok 1 name 641 + 642 + Example (only "# Subtest" line): 676 643 677 644 # Subtest: name 645 + 1..3 646 + [subtests] 647 + ok 1 name 648 + 649 + Example (only KTAP version line, compliant with KTAP v1 spec): 650 + 651 + KTAP version 1 678 652 1..3 679 653 [subtests] 680 654 ok 1 name ··· 707 647 expected_num - expected test number for test to be parsed 708 648 log - list of strings containing any preceding diagnostic lines 709 649 corresponding to the current test 650 + is_subtest - boolean indicating whether test is a subtest 710 651 711 652 Return: 712 653 Test object populated with characteristics and any subtests 713 654 """ 714 655 test = Test() 715 656 test.log.extend(log) 716 - parent_test = False 717 - main = parse_ktap_header(lines, test) 718 - if main: 719 - # If KTAP/TAP header is found, attempt to parse 657 + if not is_subtest: 658 + # If parsing the main/top-level test, parse KTAP version line and 720 659 # test plan 721 660 test.name = "main" 661 + ktap_line = parse_ktap_header(lines, test) 722 662 parse_test_plan(lines, test) 723 663 parent_test = True 724 664 else: 725 - # If KTAP/TAP header is not found, test must be subtest 726 - # header or test result line so parse attempt to parser 727 - # subtest header 728 - parent_test = parse_test_header(lines, test) 665 + # If not the main test, attempt to parse a test header containing 666 + # the KTAP version line and/or subtest header line 667 + ktap_line = parse_ktap_header(lines, test) 668 + subtest_line = parse_test_header(lines, test) 669 + parent_test = (ktap_line or subtest_line) 729 670 if parent_test: 730 - # If subtest header is found, attempt to parse 731 - # test plan and print header 671 + # If KTAP version line and/or subtest header is found, attempt 672 + # to parse test plan and print test header 732 673 parse_test_plan(lines, test) 733 674 print_test_header(test) 734 675 expected_count = test.expected_count ··· 744 683 sub_log = parse_diagnostic(lines) 745 684 sub_test = Test() 746 685 if not lines or (peek_test_name_match(lines, test) and 747 - not main): 686 + is_subtest): 748 687 if expected_count and test_num <= expected_count: 749 688 # If parser reaches end of test before 750 689 # parsing expected number of subtests, print ··· 758 697 test.log.extend(sub_log) 759 698 break 760 699 else: 761 - sub_test = parse_test(lines, test_num, sub_log) 700 + sub_test = parse_test(lines, test_num, sub_log, True) 762 701 subtests.append(sub_test) 763 702 test_num += 1 764 703 test.subtests = subtests 765 - if not main: 704 + if is_subtest: 766 705 # If not main test, look for test result line 767 706 test.log.extend(parse_diagnostic(lines)) 768 - if (parent_test and peek_test_name_match(lines, test)) or \ 769 - not parent_test: 770 - parse_test_result(lines, test, expected_num) 771 - else: 707 + if test.name != "" and not peek_test_name_match(lines, test): 772 708 test.add_error('missing subtest result line!') 709 + else: 710 + parse_test_result(lines, test, expected_num) 773 711 774 - # Check for there being no tests 712 + # Check for there being no subtests within parent test 775 713 if parent_test and len(subtests) == 0: 776 714 # Don't override a bad status if this test had one reported. 777 715 # Assumption: no subtests means CRASHED is from Test.__init__() ··· 780 720 781 721 # Add statuses to TestCounts attribute in Test object 782 722 bubble_up_test_results(test) 783 - if parent_test and not main: 723 + if parent_test and is_subtest: 784 724 # If test has subtests and is not the main test object, print 785 725 # footer. 786 726 print_test_footer(test) 787 - elif not main: 727 + elif is_subtest: 788 728 print_test_result(test) 789 729 return test 790 730 ··· 804 744 test = Test() 805 745 if not lines: 806 746 test.name = '<missing>' 807 - test.add_error('could not find any KTAP output!') 747 + test.add_error('Could not find any KTAP output. Did any KUnit tests run?') 808 748 test.status = TestStatus.FAILURE_TO_PARSE_TESTS 809 749 else: 810 - test = parse_test(lines, 0, []) 750 + test = parse_test(lines, 0, [], False) 811 751 if test.status != TestStatus.NO_TESTS: 812 752 test.status = test.counts.get_status() 813 753 stdout.print_with_timestamp(DIVIDER)
+102 -62
tools/testing/kunit/kunit_tool_test.py
··· 80 80 self.assertEqual(actual_kconfig, expected_kconfig) 81 81 82 82 class KUnitParserTest(unittest.TestCase): 83 + def setUp(self): 84 + self.print_mock = mock.patch('kunit_printer.Printer.print').start() 85 + self.addCleanup(mock.patch.stopall) 86 + 87 + def noPrintCallContains(self, substr: str): 88 + for call in self.print_mock.mock_calls: 89 + self.assertNotIn(substr, call.args[0]) 83 90 84 91 def assertContains(self, needle: str, haystack: kunit_parser.LineStream): 85 92 # Clone the iterator so we can print the contents on failure. ··· 140 133 all_passed_log = test_data_path('test_is_test_passed-all_passed.log') 141 134 with open(all_passed_log) as file: 142 135 result = kunit_parser.parse_run_tests(file.readlines()) 143 - self.assertEqual( 144 - kunit_parser.TestStatus.SUCCESS, 145 - result.status) 136 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 137 + self.assertEqual(result.counts.errors, 0) 146 138 147 139 def test_parse_successful_nested_tests_log(self): 148 140 all_passed_log = test_data_path('test_is_test_passed-all_passed_nested.log') 149 141 with open(all_passed_log) as file: 150 142 result = kunit_parser.parse_run_tests(file.readlines()) 151 - self.assertEqual( 152 - kunit_parser.TestStatus.SUCCESS, 153 - result.status) 143 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 144 + self.assertEqual(result.counts.errors, 0) 154 145 155 146 def test_kselftest_nested(self): 156 147 kselftest_log = test_data_path('test_is_test_passed-kselftest.log') 157 148 with open(kselftest_log) as file: 158 149 result = kunit_parser.parse_run_tests(file.readlines()) 159 - self.assertEqual( 160 - kunit_parser.TestStatus.SUCCESS, 161 - result.status) 150 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 151 + self.assertEqual(result.counts.errors, 0) 162 152 163 153 def test_parse_failed_test_log(self): 164 154 failed_log = test_data_path('test_is_test_passed-failure.log') 165 155 with open(failed_log) as file: 166 156 result = kunit_parser.parse_run_tests(file.readlines()) 167 - self.assertEqual( 168 - kunit_parser.TestStatus.FAILURE, 169 - result.status) 157 + self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 158 + self.assertEqual(result.counts.errors, 0) 170 159 171 160 def test_no_header(self): 172 161 empty_log = test_data_path('test_is_test_passed-no_tests_run_no_header.log') ··· 170 167 result = kunit_parser.parse_run_tests( 171 168 kunit_parser.extract_tap_lines(file.readlines())) 172 169 self.assertEqual(0, len(result.subtests)) 173 - self.assertEqual( 174 - kunit_parser.TestStatus.FAILURE_TO_PARSE_TESTS, 175 - result.status) 170 + self.assertEqual(kunit_parser.TestStatus.FAILURE_TO_PARSE_TESTS, result.status) 171 + self.assertEqual(result.counts.errors, 1) 176 172 177 173 def test_missing_test_plan(self): 178 174 missing_plan_log = test_data_path('test_is_test_passed-' ··· 181 179 kunit_parser.extract_tap_lines( 182 180 file.readlines())) 183 181 # A missing test plan is not an error. 184 - self.assertEqual(0, result.counts.errors) 185 - # All tests should be accounted for. 186 - self.assertEqual(10, result.counts.total()) 187 - self.assertEqual( 188 - kunit_parser.TestStatus.SUCCESS, 189 - result.status) 182 + self.assertEqual(result.counts, kunit_parser.TestCounts(passed=10, errors=0)) 183 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 190 184 191 185 def test_no_tests(self): 192 186 header_log = test_data_path('test_is_test_passed-no_tests_run_with_header.log') ··· 190 192 result = kunit_parser.parse_run_tests( 191 193 kunit_parser.extract_tap_lines(file.readlines())) 192 194 self.assertEqual(0, len(result.subtests)) 193 - self.assertEqual( 194 - kunit_parser.TestStatus.NO_TESTS, 195 - result.status) 195 + self.assertEqual(kunit_parser.TestStatus.NO_TESTS, result.status) 196 + self.assertEqual(result.counts.errors, 1) 196 197 197 198 def test_no_tests_no_plan(self): 198 199 no_plan_log = test_data_path('test_is_test_passed-no_tests_no_plan.log') ··· 202 205 self.assertEqual( 203 206 kunit_parser.TestStatus.NO_TESTS, 204 207 result.subtests[0].subtests[0].status) 205 - self.assertEqual(1, result.counts.errors) 208 + self.assertEqual(result.counts, kunit_parser.TestCounts(passed=1, errors=1)) 206 209 207 210 208 211 def test_no_kunit_output(self): ··· 211 214 with open(crash_log) as file: 212 215 result = kunit_parser.parse_run_tests( 213 216 kunit_parser.extract_tap_lines(file.readlines())) 214 - print_mock.assert_any_call(StrContains('could not find any KTAP output!')) 217 + print_mock.assert_any_call(StrContains('Could not find any KTAP output.')) 215 218 print_mock.stop() 216 219 self.assertEqual(0, len(result.subtests)) 220 + self.assertEqual(result.counts.errors, 1) 217 221 218 222 def test_skipped_test(self): 219 223 skipped_log = test_data_path('test_skip_tests.log') ··· 222 224 result = kunit_parser.parse_run_tests(file.readlines()) 223 225 224 226 # A skipped test does not fail the whole suite. 225 - self.assertEqual( 226 - kunit_parser.TestStatus.SUCCESS, 227 - result.status) 227 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 228 + self.assertEqual(result.counts, kunit_parser.TestCounts(passed=4, skipped=1)) 228 229 229 230 def test_skipped_all_tests(self): 230 231 skipped_log = test_data_path('test_skip_all_tests.log') 231 232 with open(skipped_log) as file: 232 233 result = kunit_parser.parse_run_tests(file.readlines()) 233 234 234 - self.assertEqual( 235 - kunit_parser.TestStatus.SKIPPED, 236 - result.status) 235 + self.assertEqual(kunit_parser.TestStatus.SKIPPED, result.status) 236 + self.assertEqual(result.counts, kunit_parser.TestCounts(skipped=5)) 237 237 238 238 def test_ignores_hyphen(self): 239 239 hyphen_log = test_data_path('test_strip_hyphen.log') ··· 239 243 result = kunit_parser.parse_run_tests(file.readlines()) 240 244 241 245 # A skipped test does not fail the whole suite. 242 - self.assertEqual( 243 - kunit_parser.TestStatus.SUCCESS, 244 - result.status) 246 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 245 247 self.assertEqual( 246 248 "sysctl_test", 247 249 result.subtests[0].name) 248 250 self.assertEqual( 249 251 "example", 250 252 result.subtests[1].name) 251 - file.close() 252 - 253 253 254 254 def test_ignores_prefix_printk_time(self): 255 255 prefix_log = test_data_path('test_config_printk_time.log') 256 256 with open(prefix_log) as file: 257 257 result = kunit_parser.parse_run_tests(file.readlines()) 258 - self.assertEqual( 259 - kunit_parser.TestStatus.SUCCESS, 260 - result.status) 261 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 258 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 259 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 260 + self.assertEqual(result.counts.errors, 0) 262 261 263 262 def test_ignores_multiple_prefixes(self): 264 263 prefix_log = test_data_path('test_multiple_prefixes.log') 265 264 with open(prefix_log) as file: 266 265 result = kunit_parser.parse_run_tests(file.readlines()) 267 - self.assertEqual( 268 - kunit_parser.TestStatus.SUCCESS, 269 - result.status) 270 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 266 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 267 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 268 + self.assertEqual(result.counts.errors, 0) 271 269 272 270 def test_prefix_mixed_kernel_output(self): 273 271 mixed_prefix_log = test_data_path('test_interrupted_tap_output.log') 274 272 with open(mixed_prefix_log) as file: 275 273 result = kunit_parser.parse_run_tests(file.readlines()) 276 - self.assertEqual( 277 - kunit_parser.TestStatus.SUCCESS, 278 - result.status) 279 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 274 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 275 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 276 + self.assertEqual(result.counts.errors, 0) 280 277 281 278 def test_prefix_poundsign(self): 282 279 pound_log = test_data_path('test_pound_sign.log') 283 280 with open(pound_log) as file: 284 281 result = kunit_parser.parse_run_tests(file.readlines()) 285 - self.assertEqual( 286 - kunit_parser.TestStatus.SUCCESS, 287 - result.status) 288 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 282 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 283 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 284 + self.assertEqual(result.counts.errors, 0) 289 285 290 286 def test_kernel_panic_end(self): 291 287 panic_log = test_data_path('test_kernel_panic_interrupt.log') 292 288 with open(panic_log) as file: 293 289 result = kunit_parser.parse_run_tests(file.readlines()) 294 - self.assertEqual( 295 - kunit_parser.TestStatus.TEST_CRASHED, 296 - result.status) 297 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 290 + self.assertEqual(kunit_parser.TestStatus.TEST_CRASHED, result.status) 291 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 292 + self.assertGreaterEqual(result.counts.errors, 1) 298 293 299 294 def test_pound_no_prefix(self): 300 295 pound_log = test_data_path('test_pound_no_prefix.log') 301 296 with open(pound_log) as file: 302 297 result = kunit_parser.parse_run_tests(file.readlines()) 303 - self.assertEqual( 304 - kunit_parser.TestStatus.SUCCESS, 305 - result.status) 306 - self.assertEqual('kunit-resource-test', result.subtests[0].name) 298 + self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 299 + self.assertEqual('kunit-resource-test', result.subtests[0].name) 300 + self.assertEqual(result.counts.errors, 0) 301 + 302 + def test_summarize_failures(self): 303 + output = """ 304 + KTAP version 1 305 + 1..2 306 + # Subtest: all_failed_suite 307 + 1..2 308 + not ok 1 - test1 309 + not ok 2 - test2 310 + not ok 1 - all_failed_suite 311 + # Subtest: some_failed_suite 312 + 1..2 313 + ok 1 - test1 314 + not ok 2 - test2 315 + not ok 1 - some_failed_suite 316 + """ 317 + result = kunit_parser.parse_run_tests(output.splitlines()) 318 + self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 319 + 320 + self.assertEqual(kunit_parser._summarize_failed_tests(result), 321 + 'Failures: all_failed_suite, some_failed_suite.test2') 322 + 323 + def test_ktap_format(self): 324 + ktap_log = test_data_path('test_parse_ktap_output.log') 325 + with open(ktap_log) as file: 326 + result = kunit_parser.parse_run_tests(file.readlines()) 327 + self.assertEqual(result.counts, kunit_parser.TestCounts(passed=3)) 328 + self.assertEqual('suite', result.subtests[0].name) 329 + self.assertEqual('case_1', result.subtests[0].subtests[0].name) 330 + self.assertEqual('case_2', result.subtests[0].subtests[1].name) 331 + 332 + def test_parse_subtest_header(self): 333 + ktap_log = test_data_path('test_parse_subtest_header.log') 334 + with open(ktap_log) as file: 335 + result = kunit_parser.parse_run_tests(file.readlines()) 336 + self.print_mock.assert_any_call(StrContains('suite (1 subtest)')) 337 + 338 + def test_show_test_output_on_failure(self): 339 + output = """ 340 + KTAP version 1 341 + 1..1 342 + Test output. 343 + Indented more. 344 + not ok 1 test1 345 + """ 346 + result = kunit_parser.parse_run_tests(output.splitlines()) 347 + self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 348 + 349 + self.print_mock.assert_any_call(StrContains('Test output.')) 350 + self.print_mock.assert_any_call(StrContains(' Indented more.')) 351 + self.noPrintCallContains('not ok 1 test1') 307 352 308 353 def line_stream_from_strs(strs: Iterable[str]) -> kunit_parser.LineStream: 309 354 return kunit_parser.LineStream(enumerate(strs, start=1)) ··· 522 485 523 486 524 487 class KUnitJsonTest(unittest.TestCase): 488 + def setUp(self): 489 + self.print_mock = mock.patch('kunit_printer.Printer.print').start() 490 + self.addCleanup(mock.patch.stopall) 525 491 526 492 def _json_for(self, log_file): 527 493 with open(test_data_path(log_file)) as file: ··· 621 581 self.assertEqual(e.exception.code, 1) 622 582 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 623 583 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 624 - self.print_mock.assert_any_call(StrContains('could not find any KTAP output!')) 584 + self.print_mock.assert_any_call(StrContains('Could not find any KTAP output.')) 625 585 626 586 def test_exec_no_tests(self): 627 587 self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0'])
+8
tools/testing/kunit/test_data/test_parse_ktap_output.log
··· 1 + KTAP version 1 2 + 1..1 3 + KTAP version 1 4 + 1..3 5 + ok 1 case_1 6 + ok 2 case_2 7 + ok 3 case_3 8 + ok 1 suite
+7
tools/testing/kunit/test_data/test_parse_subtest_header.log
··· 1 + KTAP version 1 2 + 1..1 3 + KTAP version 1 4 + # Subtest: suite 5 + 1..1 6 + ok 1 test 7 + ok 1 suite