From f13ecba04babc7b614d8ad896e987549c807e2de Mon Sep 17 00:00:00 2001 From: Sadiya Kazi Date: Tue, 18 Oct 2022 04:03:33 +0000 Subject: Documentation: Kunit: Update architecture.rst for minor fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated the architecture.rst page with the following changes: -Add missing article _the_ across the document. -Reword content across for style and standard. -Update all occurrences of Command Line to Command-line across the document. -Correct grammatical issues, for example, added _it_wherever missing. -Update all occurrences of “via" to either use “through” or “using”. -Update the text preceding the external links and pushed the full link to a new line for better readability. -Reword content under the config command to make it more clear and concise. Signed-off-by: Sadiya Kazi Reviewed-by: David Gow Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/architecture.rst | 115 +++++++++++++------------ 1 file changed, 58 insertions(+), 57 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/architecture.rst b/Documentation/dev-tools/kunit/architecture.rst index 8efe792bdcb9..e95ab05342bb 100644 --- a/Documentation/dev-tools/kunit/architecture.rst +++ b/Documentation/dev-tools/kunit/architecture.rst @@ -4,16 +4,17 @@ KUnit Architecture ================== -The KUnit architecture can be divided into two parts: +The KUnit architecture is divided into two parts: - `In-Kernel Testing Framework`_ -- `kunit_tool (Command Line Test Harness)`_ +- `kunit_tool (Command-line Test Harness)`_ In-Kernel Testing Framework =========================== The kernel testing library supports KUnit tests written in C using -KUnit. KUnit tests are kernel code. KUnit does several things: +KUnit. These KUnit tests are kernel code. KUnit performs the following +tasks: - Organizes tests - Reports test results @@ -22,19 +23,17 @@ KUnit. KUnit tests are kernel code. KUnit does several things: Test Cases ---------- -The fundamental unit in KUnit is the test case. The KUnit test cases are -grouped into KUnit suites. A KUnit test case is a function with type -signature ``void (*)(struct kunit *test)``. -These test case functions are wrapped in a struct called -struct kunit_case. +The test case is the fundamental unit in KUnit. KUnit test cases are organised +into suites. A KUnit test case is a function with type signature +``void (*)(struct kunit *test)``. These test case functions are wrapped in a +struct called struct kunit_case. .. note: ``generate_params`` is optional for non-parameterized tests. -Each KUnit test case gets a ``struct kunit`` context -object passed to it that tracks a running test. The KUnit assertion -macros and other KUnit utilities use the ``struct kunit`` context -object. As an exception, there are two fields: +Each KUnit test case receives a ``struct kunit`` context object that tracks a +running test. The KUnit assertion macros and other KUnit utilities use the +``struct kunit`` context object. As an exception, there are two fields: - ``->priv``: The setup functions can use it to store arbitrary test user data. @@ -77,12 +76,13 @@ Executor The KUnit executor can list and run built-in KUnit tests on boot. The Test suites are stored in a linker section -called ``.kunit_test_suites``. For code, see: -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v5.15#n945. +called ``.kunit_test_suites``. For the code, see ``KUNIT_TABLE()`` macro +definition in +`include/asm-generic/vmlinux.lds.h `_. The linker section consists of an array of pointers to ``struct kunit_suite``, and is populated by the ``kunit_test_suites()`` -macro. To run all tests compiled into the kernel, the KUnit executor -iterates over the linker section array. +macro. The KUnit executor iterates over the linker section array in order to +run all the tests that are compiled into the kernel. .. kernel-figure:: kunit_suitememorydiagram.svg :alt: KUnit Suite Memory @@ -90,17 +90,17 @@ iterates over the linker section array. KUnit Suite Memory Diagram On the kernel boot, the KUnit executor uses the start and end addresses -of this section to iterate over and run all tests. For code, see: -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c - +of this section to iterate over and run all tests. For the implementation of the +executor, see +`lib/kunit/executor.c `_. When built as a module, the ``kunit_test_suites()`` macro defines a ``module_init()`` function, which runs all the tests in the compilation unit instead of utilizing the executor. In KUnit tests, some error classes do not affect other tests or parts of the kernel, each KUnit case executes in a separate thread -context. For code, see: -https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58 +context. See the ``kunit_try_catch_run()`` function in +`lib/kunit/try-catch.c `_. Assertion Macros ---------------- @@ -111,37 +111,36 @@ All expectations/assertions are formatted as: - ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an expectation. + In the event of a failure, the testing flow differs as follows: - - For an expectation, if the check fails, marks the test as failed - and logs the failure. + - For expectations, the test is marked as failed and the failure is logged. - - An assertion, on failure, causes the test case to terminate - immediately. + - Failing assertions, on the other hand, result in the test case being + terminated immediately. - - Assertions call function: + - Assertions call the function: ``void __noreturn kunit_abort(struct kunit *)``. - - ``kunit_abort`` calls function: + - ``kunit_abort`` calls the function: ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``. - - ``kunit_try_catch_throw`` calls function: + - ``kunit_try_catch_throw`` calls the function: ``void kthread_complete_and_exit(struct completion *, long) __noreturn;`` and terminates the special thread context. - ```` denotes a check with options: ``TRUE`` (supplied property - has the boolean value “true”), ``EQ`` (two supplied properties are + has the boolean value "true"), ``EQ`` (two supplied properties are equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not - contain an “err” value). + contain an "err" value). - ``[_MSG]`` prints a custom message on failure. Test Result Reporting --------------------- -KUnit prints test results in KTAP format. KTAP is based on TAP14, see: -https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md. -KTAP (yet to be standardized format) works with KUnit and Kselftest. -The KUnit executor prints KTAP results to dmesg, and debugfs -(if configured). +KUnit prints the test results in KTAP format. KTAP is based on TAP14, see +Documentation/dev-tools/ktap.rst. +KTAP works with KUnit and Kselftest. The KUnit executor prints KTAP results to +dmesg, and debugfs (if configured). Parameterized Tests ------------------- @@ -150,33 +149,35 @@ Each KUnit parameterized test is associated with a collection of parameters. The test is invoked multiple times, once for each parameter value and the parameter is stored in the ``param_value`` field. The test case includes a KUNIT_CASE_PARAM() macro that accepts a -generator function. -The generator function is passed the previous parameter and returns the next -parameter. It also provides a macro to generate common-case generators based on -arrays. +generator function. The generator function is passed the previous parameter +and returns the next parameter. It also includes a macro for generating +array-based common-case generators. -kunit_tool (Command Line Test Harness) +kunit_tool (Command-line Test Harness) ====================================== -kunit_tool is a Python script ``(tools/testing/kunit/kunit.py)`` -that can be used to configure, build, exec, parse and run (runs other -commands in order) test results. You can either run KUnit tests using -kunit_tool or can include KUnit in kernel and parse manually. +``kunit_tool`` is a Python script, found in ``tools/testing/kunit/kunit.py``. It +is used to configure, build, execute, parse test results and run all of the +previous commands in correct order (i.e., configure, build, execute and parse). +You have two options for running KUnit tests: either build the kernel with KUnit +enabled and manually parse the results (see +Documentation/dev-tools/kunit/run_manual.rst) or use ``kunit_tool`` +(see Documentation/dev-tools/kunit/run_wrapper.rst). - ``configure`` command generates the kernel ``.config`` from a ``.kunitconfig`` file (and any architecture-specific options). - For some architectures, additional config options are specified in the - ``qemu_config`` Python script - (For example: ``tools/testing/kunit/qemu_configs/powerpc.py``). + The Python scripts available in ``qemu_configs`` folder + (for example, ``tools/testing/kunit/qemu configs/powerpc.py``) contains + additional configuration options for specific architectures. It parses both the existing ``.config`` and the ``.kunitconfig`` files - and ensures that ``.config`` is a superset of ``.kunitconfig``. - If this is not the case, it will combine the two and run - ``make olddefconfig`` to regenerate the ``.config`` file. It then - verifies that ``.config`` is now a superset. This checks if all - Kconfig dependencies are correctly specified in ``.kunitconfig``. - ``kunit_config.py`` includes the parsing Kconfigs code. The code which - runs ``make olddefconfig`` is a part of ``kunit_kernel.py``. You can - invoke this command via: ``./tools/testing/kunit/kunit.py config`` and + to ensure that ``.config`` is a superset of ``.kunitconfig``. + If not, it will combine the two and run ``make olddefconfig`` to regenerate + the ``.config`` file. It then checks to see if ``.config`` has become a superset. + This verifies that all the Kconfig dependencies are correctly specified in the + file ``.kunitconfig``. The ``kunit_config.py`` script contains the code for parsing + Kconfigs. The code which runs ``make olddefconfig`` is part of the + ``kunit_kernel.py`` script. You can invoke this command through: + ``./tools/testing/kunit/kunit.py config`` and generate a ``.config`` file. - ``build`` runs ``make`` on the kernel tree with required options (depends on the architecture and some options, for example: build_dir) @@ -184,8 +185,8 @@ kunit_tool or can include KUnit in kernel and parse manually. To build a KUnit kernel from the current ``.config``, you can use the ``build`` argument: ``./tools/testing/kunit/kunit.py build``. - ``exec`` command executes kernel results either directly (using - User-mode Linux configuration), or via an emulator such - as QEMU. It reads results from the log via standard + User-mode Linux configuration), or through an emulator such + as QEMU. It reads results from the log using standard output (stdout), and passes them to ``parse`` to be parsed. If you already have built a kernel with built-in KUnit tests, you can run the kernel and display the test results with the ``exec`` -- cgit v1.2.3 From 65c48a48ead042856525b92cedf673d2bf5bdfc9 Mon Sep 17 00:00:00 2001 From: Daniel Latypov Date: Fri, 11 Nov 2022 10:29:04 -0800 Subject: Documentation: KUnit: make usage.rst a superset of tips.rst, remove duplication usage.rst had most of the content of the tips.rst page copied over. But it's missing https://www.kernel.org/doc/html/v6.0/dev-tools/kunit/tips.html#customizing-error-messages Copy it over so we can retire tips.rst w/o losing content. And in that process, it also gained a duplicate section about how KUNIT_ASSERT_*() exit the test case early. Remove that. Signed-off-by: Daniel Latypov Reviewed-by: Sadiya Kazi Reviewed-by: David Gow Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/usage.rst | 49 +++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst index 2737863ef365..b0a6c3bc0eeb 100644 --- a/Documentation/dev-tools/kunit/usage.rst +++ b/Documentation/dev-tools/kunit/usage.rst @@ -118,6 +118,37 @@ expectation could crash the test case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us to bail out of the test case if the appropriate conditions are not satisfied to complete the test. +Customizing error messages +-------------------------- + +Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` +variant. These take a format string and arguments to provide additional +context to the automatically generated error messages. + +.. code-block:: c + + char some_str[41]; + generate_sha1_hex_string(some_str); + + /* Before. Not easy to tell why the test failed. */ + KUNIT_EXPECT_EQ(test, strlen(some_str), 40); + + /* After. Now we see the offending string. */ + KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str); + +Alternatively, one can take full control over the error message by using +``KUNIT_FAIL()``, e.g. + +.. code-block:: c + + /* Before */ + KUNIT_EXPECT_EQ(test, some_setup_function(), 0); + + /* After: full control over the failure message. */ + if (some_setup_function()) + KUNIT_FAIL(test, "Failed to setup thing for testing"); + + Test Suites ~~~~~~~~~~~ @@ -546,24 +577,6 @@ By reusing the same ``cases`` array from above, we can write the test as a {} }; -Exiting Early on Failed Expectations ------------------------------------- - -We can use ``KUNIT_EXPECT_EQ`` to mark the test as failed and continue -execution. In some cases, it is unsafe to continue. We can use the -``KUNIT_ASSERT`` variant to exit on failure. - -.. code-block:: c - - void example_test_user_alloc_function(struct kunit *test) - { - void *object = alloc_some_object_for_me(); - - /* Make sure we got a valid pointer back. */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object); - do_something_with_object(object); - } - Allocating Memory ----------------- -- cgit v1.2.3 From ec0a42a17e463ee5b1ebd2d60337e8ae8e5ace2b Mon Sep 17 00:00:00 2001 From: Daniel Latypov Date: Fri, 11 Nov 2022 10:29:05 -0800 Subject: Documentation: KUnit: reword description of assertions The existing wording implies that kunit_kmalloc_array() is "the method under test". We're actually testing the sort() function in that example. This is because the example was changed in commit 953574390634 ("Documentation: KUnit: Rework writing page to focus on writing tests"), but the wording was not. Also add a `note` telling people they can use the KUNIT_ASSERT_EQ() macros from any function. Some users might be coming from a framework like gUnit where that'll compile but silently do the wrong thing. Signed-off-by: Daniel Latypov Reviewed-by: Sadiya Kazi Reviewed-by: David Gow Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/usage.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst index b0a6c3bc0eeb..22416ebb94ab 100644 --- a/Documentation/dev-tools/kunit/usage.rst +++ b/Documentation/dev-tools/kunit/usage.rst @@ -112,11 +112,14 @@ terminates the test case if the condition is not satisfied. For example: KUNIT_EXPECT_LE(test, a[i], a[i + 1]); } -In this example, the method under test should return pointer to a value. If the -pointer returns null or an errno, we want to stop the test since the following -expectation could crash the test case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us -to bail out of the test case if the appropriate conditions are not satisfied to -complete the test. +In this example, we need to be able to allocate an array to test the ``sort()`` +function. So we use ``KUNIT_ASSERT_NOT_ERR_OR_NULL()`` to abort the test if +there's an allocation error. + +.. note:: + In other test frameworks, ``ASSERT`` macros are often implemented by calling + ``return`` so they only work from the test function. In KUnit, we stop the + current kthread on failure, so you can call them from anywhere. Customizing error messages -------------------------- -- cgit v1.2.3 From a5b9abaa6049340a93a852b1d6d069064fddb624 Mon Sep 17 00:00:00 2001 From: David Gow Date: Fri, 11 Nov 2022 10:29:06 -0800 Subject: Documentation: kunit: Remove redundant 'tips.rst' page The contents of 'tips.rst' was mostly included in 'usage.rst' way back in commit 953574390634 ("Documentation: KUnit: Rework writing page to focus on writing tests"), but the tips page remained behind as well. The parent patches in this series fill in the gaps, so now 'tips.rst' is redundant. Therefore, delete 'tips.rst'. While I regret breaking any links to 'tips' which might exist externally, it's confusing to have two subtly different versions of the same content around. Signed-off-by: David Gow Signed-off-by: Daniel Latypov Reviewed-by: Sadiya Kazi Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/index.rst | 1 - Documentation/dev-tools/kunit/tips.rst | 190 -------------------------------- 2 files changed, 191 deletions(-) delete mode 100644 Documentation/dev-tools/kunit/tips.rst (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst index f5d13f1d37be..d5629817cd72 100644 --- a/Documentation/dev-tools/kunit/index.rst +++ b/Documentation/dev-tools/kunit/index.rst @@ -16,7 +16,6 @@ KUnit - Linux Kernel Unit Testing api/index style faq - tips running_tips This section details the kernel unit testing framework. diff --git a/Documentation/dev-tools/kunit/tips.rst b/Documentation/dev-tools/kunit/tips.rst deleted file mode 100644 index 492d2ded2f5a..000000000000 --- a/Documentation/dev-tools/kunit/tips.rst +++ /dev/null @@ -1,190 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -============================ -Tips For Writing KUnit Tests -============================ - -Exiting early on failed expectations ------------------------------------- - -``KUNIT_EXPECT_EQ`` and friends will mark the test as failed and continue -execution. In some cases, it's unsafe to continue and you can use the -``KUNIT_ASSERT`` variant to exit on failure. - -.. code-block:: c - - void example_test_user_alloc_function(struct kunit *test) - { - void *object = alloc_some_object_for_me(); - - /* Make sure we got a valid pointer back. */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object); - do_something_with_object(object); - } - -Allocating memory ------------------ - -Where you would use ``kzalloc``, you should prefer ``kunit_kzalloc`` instead. -KUnit will ensure the memory is freed once the test completes. - -This is particularly useful since it lets you use the ``KUNIT_ASSERT_EQ`` -macros to exit early from a test without having to worry about remembering to -call ``kfree``. - -Example: - -.. code-block:: c - - void example_test_allocation(struct kunit *test) - { - char *buffer = kunit_kzalloc(test, 16, GFP_KERNEL); - /* Ensure allocation succeeded. */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer); - - KUNIT_ASSERT_STREQ(test, buffer, ""); - } - - -Testing static functions ------------------------- - -If you don't want to expose functions or variables just for testing, one option -is to conditionally ``#include`` the test file at the end of your .c file, e.g. - -.. code-block:: c - - /* In my_file.c */ - - static int do_interesting_thing(); - - #ifdef CONFIG_MY_KUNIT_TEST - #include "my_kunit_test.c" - #endif - -Injecting test-only code ------------------------- - -Similarly to the above, it can be useful to add test-specific logic. - -.. code-block:: c - - /* In my_file.h */ - - #ifdef CONFIG_MY_KUNIT_TEST - /* Defined in my_kunit_test.c */ - void test_only_hook(void); - #else - void test_only_hook(void) { } - #endif - -This test-only code can be made more useful by accessing the current kunit -test, see below. - -Accessing the current test --------------------------- - -In some cases, you need to call test-only code from outside the test file, e.g. -like in the example above or if you're providing a fake implementation of an -ops struct. -There is a ``kunit_test`` field in ``task_struct``, so you can access it via -``current->kunit_test``. - -Here's a slightly in-depth example of how one could implement "mocking": - -.. code-block:: c - - #include /* for current */ - - struct test_data { - int foo_result; - int want_foo_called_with; - }; - - static int fake_foo(int arg) - { - struct kunit *test = current->kunit_test; - struct test_data *test_data = test->priv; - - KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg); - return test_data->foo_result; - } - - static void example_simple_test(struct kunit *test) - { - /* Assume priv is allocated in the suite's .init */ - struct test_data *test_data = test->priv; - - test_data->foo_result = 42; - test_data->want_foo_called_with = 1; - - /* In a real test, we'd probably pass a pointer to fake_foo somewhere - * like an ops struct, etc. instead of calling it directly. */ - KUNIT_EXPECT_EQ(test, fake_foo(1), 42); - } - - -Note: here we're able to get away with using ``test->priv``, but if you wanted -something more flexible you could use a named ``kunit_resource``, see -Documentation/dev-tools/kunit/api/test.rst. - -Failing the current test ------------------------- - -But sometimes, you might just want to fail the current test. In that case, we -have ``kunit_fail_current_test(fmt, args...)`` which is defined in ```` and -doesn't require pulling in ````. - -E.g. say we had an option to enable some extra debug checks on some data structure: - -.. code-block:: c - - #include - - #ifdef CONFIG_EXTRA_DEBUG_CHECKS - static void validate_my_data(struct data *data) - { - if (is_valid(data)) - return; - - kunit_fail_current_test("data %p is invalid", data); - - /* Normal, non-KUnit, error reporting code here. */ - } - #else - static void my_debug_function(void) { } - #endif - - -Customizing error messages --------------------------- - -Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` variant. -These take a format string and arguments to provide additional context to the automatically generated error messages. - -.. code-block:: c - - char some_str[41]; - generate_sha1_hex_string(some_str); - - /* Before. Not easy to tell why the test failed. */ - KUNIT_EXPECT_EQ(test, strlen(some_str), 40); - - /* After. Now we see the offending string. */ - KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str); - -Alternatively, one can take full control over the error message by using ``KUNIT_FAIL()``, e.g. - -.. code-block:: c - - /* Before */ - KUNIT_EXPECT_EQ(test, some_setup_function(), 0); - - /* After: full control over the failure message. */ - if (some_setup_function()) - KUNIT_FAIL(test, "Failed to setup thing for testing"); - -Next Steps -========== -* Optional: see the Documentation/dev-tools/kunit/usage.rst page for a more - in-depth explanation of KUnit. -- cgit v1.2.3 From 91e93592219f74c4d5cd4f27006d726ac86ae15d Mon Sep 17 00:00:00 2001 From: David Gow Date: Fri, 25 Nov 2022 16:43:05 +0800 Subject: kunit: Use the static key when retrieving the current test In order to detect if a KUnit test is running, and to access its context, the 'kunit_test' member of the current task_struct is used. Usually, this is accessed directly or via the kunit_fail_current_task() function. In order to speed up the case where no test is running, add a wrapper, kunit_get_current_test(), which uses the static key to fail early. Equally, Speed up kunit_fail_current_test() by using the static key. This should make it convenient for code to call this unconditionally in fakes or error paths, without worrying that this will slow the code down significantly. If CONFIG_KUNIT=n (or m), this compiles away to nothing. If CONFIG_KUNIT=y, it will compile down to a NOP (on most architectures) if no KUnit test is currently running. Note that kunit_get_current_test() does not work if KUnit is built as a module. This mirrors the existing restriction on kunit_fail_current_test(). Note that the definition of kunit_fail_current_test() still wraps an empty, inline function if KUnit is not built-in. This is to ensure that the printf format string __attribute__ will still work. Also update the documentation to suggest users use the new kunit_get_current_test() function, update the example, and to describe the behaviour when KUnit is disabled better. Cc: Jonathan Corbet Cc: Sadiya Kazi Signed-off-by: David Gow Reviewed-by: Daniel Latypov Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/usage.rst | 30 +++++++++++++------ include/kunit/test-bug.h | 53 +++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 12 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst index 22416ebb94ab..48f8196d5aad 100644 --- a/Documentation/dev-tools/kunit/usage.rst +++ b/Documentation/dev-tools/kunit/usage.rst @@ -641,17 +641,23 @@ as shown in next section: *Accessing The Current Test*. Accessing The Current Test -------------------------- -In some cases, we need to call test-only code from outside the test file. -For example, see example in section *Injecting Test-Only Code* or if -we are providing a fake implementation of an ops struct. Using -``kunit_test`` field in ``task_struct``, we can access it via -``current->kunit_test``. +In some cases, we need to call test-only code from outside the test file. This +is helpful, for example, when providing a fake implementation of a function, or +to fail any current test from within an error handler. +We can do this via the ``kunit_test`` field in ``task_struct``, which we can +access using the ``kunit_get_current_test()`` function in ``kunit/test-bug.h``. -The example below includes how to implement "mocking": +``kunit_get_current_test()`` is safe to call even if KUnit is not enabled. If +KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is +running in the current task, it will return ``NULL``. This compiles down to +either a no-op or a static key check, so will have a negligible performance +impact when no test is running. + +The example below uses this to implement a "mock" implementation of a function, ``foo``: .. code-block:: c - #include /* for current */ + #include /* for kunit_get_current_test */ struct test_data { int foo_result; @@ -660,7 +666,7 @@ The example below includes how to implement "mocking": static int fake_foo(int arg) { - struct kunit *test = current->kunit_test; + struct kunit *test = kunit_get_current_test(); struct test_data *test_data = test->priv; KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg); @@ -691,7 +697,7 @@ Each test can have multiple resources which have string names providing the same flexibility as a ``priv`` member, but also, for example, allowing helper functions to create resources without conflicting with each other. It is also possible to define a clean up function for each resource, making it easy to -avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/test.rst. +avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/resource.rst. Failing The Current Test ------------------------ @@ -719,3 +725,9 @@ structures as shown below: static void my_debug_function(void) { } #endif +``kunit_fail_current_test()`` is safe to call even if KUnit is not enabled. If +KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is +running in the current task, it will do nothing. This compiles down to either a +no-op or a static key check, so will have a negligible performance impact when +no test is running. + diff --git a/include/kunit/test-bug.h b/include/kunit/test-bug.h index 5fc58081d511..c1b2e14eab64 100644 --- a/include/kunit/test-bug.h +++ b/include/kunit/test-bug.h @@ -9,16 +9,63 @@ #ifndef _KUNIT_TEST_BUG_H #define _KUNIT_TEST_BUG_H -#define kunit_fail_current_test(fmt, ...) \ - __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) - #if IS_BUILTIN(CONFIG_KUNIT) +#include /* For static branch */ +#include + +/* Static key if KUnit is running any tests. */ +DECLARE_STATIC_KEY_FALSE(kunit_running); + +/** + * kunit_get_current_test() - Return a pointer to the currently running + * KUnit test. + * + * If a KUnit test is running in the current task, returns a pointer to its + * associated struct kunit. This pointer can then be passed to any KUnit + * function or assertion. If no test is running (or a test is running in a + * different task), returns NULL. + * + * This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT + * is not enabled, it will compile down to nothing and will return quickly no + * test is running. + */ +static inline struct kunit *kunit_get_current_test(void) +{ + if (!static_branch_unlikely(&kunit_running)) + return NULL; + + return current->kunit_test; +} + + +/** + * kunit_fail_current_test() - If a KUnit test is running, fail it. + * + * If a KUnit test is running in the current task, mark that test as failed. + * + * This macro will only work if KUnit is built-in (though the tests + * themselves can be modules). Otherwise, it compiles down to nothing. + */ +#define kunit_fail_current_test(fmt, ...) do { \ + if (static_branch_unlikely(&kunit_running)) { \ + __kunit_fail_current_test(__FILE__, __LINE__, \ + fmt, ##__VA_ARGS__); \ + } \ + } while (0) + + extern __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...); #else +static inline struct kunit *kunit_get_current_test(void) { return NULL; } + +/* We define this with an empty helper function so format string warnings work */ +#define kunit_fail_current_test(fmt, ...) \ + __kunit_fail_current_test(__FILE__, __LINE__, fmt, ##__VA_ARGS__) + static inline __printf(3, 4) void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...) { -- cgit v1.2.3 From a81fe7ecf717e5ae16892c282378ca380d4e99c9 Mon Sep 17 00:00:00 2001 From: David Gow Date: Wed, 7 Dec 2022 12:33:19 +0800 Subject: Documentation: kunit: Fix "How Do I Use This" / "Next Steps" sections The "How Do I Use This" section of index.rst and "Next Steps" section of start.rst were just copies of the table of contents, and therefore weren't really useful either when looking a sphinx generated output (which already had the TOC visible) or when reading the source (where it's just a list of files that ls could give you). Instead, provide a small number of concrete next steps, and a bit more description about what the pages contain. This also removes the broken reference to 'tips.rst', which was previously removed. Fixed git am whitespace complaints during commit: Shuah Khan Fixes: 4399c737a97d ("Documentation: kunit: Remove redundant 'tips.rst' page") Signed-off-by: David Gow Reviewed-by: Sadiya Kazi Reviewed-by: Bagas Sanjaya Signed-off-by: Shuah Khan --- Documentation/dev-tools/kunit/index.rst | 19 ++++++++----------- Documentation/dev-tools/kunit/start.rst | 18 ++++++++---------- 2 files changed, 16 insertions(+), 21 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst index d5629817cd72..b3593ae29ace 100644 --- a/Documentation/dev-tools/kunit/index.rst +++ b/Documentation/dev-tools/kunit/index.rst @@ -99,14 +99,11 @@ Read also :ref:`kinds-of-tests`. How do I use it? ================ -* Documentation/dev-tools/kunit/start.rst - for KUnit new users. -* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. -* Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool. -* Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool. -* Documentation/dev-tools/kunit/usage.rst - write tests. -* Documentation/dev-tools/kunit/tips.rst - best practices with - examples. -* Documentation/dev-tools/kunit/api/index.rst - KUnit APIs - used for testing. -* Documentation/dev-tools/kunit/faq.rst - KUnit common questions and - answers. +You can find a step-by-step guide to writing and running KUnit tests in +Documentation/dev-tools/kunit/start.rst + +Alternatively, feel free to look through the rest of the KUnit documentation, +or to experiment with tools/testing/kunit/kunit.py and the example test under +lib/kunit/kunit-example-test.c + +Happy testing! diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst index f4f504f1fb15..c736613c9b19 100644 --- a/Documentation/dev-tools/kunit/start.rst +++ b/Documentation/dev-tools/kunit/start.rst @@ -294,13 +294,11 @@ Congrats! You just wrote your first KUnit test. Next Steps ========== -* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. -* Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool. -* Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool. -* Documentation/dev-tools/kunit/usage.rst - write tests. -* Documentation/dev-tools/kunit/tips.rst - best practices with - examples. -* Documentation/dev-tools/kunit/api/index.rst - KUnit APIs - used for testing. -* Documentation/dev-tools/kunit/faq.rst - KUnit common questions and - answers. +If you're interested in using some of the more advanced features of kunit.py, +take a look at Documentation/dev-tools/kunit/run_wrapper.rst + +If you'd like to run tests without using kunit.py, check out +Documentation/dev-tools/kunit/run_manual.rst + +For more information on writing KUnit tests (including some common techniques +for testing different things), see Documentation/dev-tools/kunit/usage.rst -- cgit v1.2.3 From 054be257f28ca8eeb8e3620766501b81ceb4b293 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 7 Dec 2022 13:03:02 +0000 Subject: Documentation: dev-tools: Clarify requirements for result description Currently the KTAP specification says that a test result line is [][ # [] []] and the description of a test can be "any sequence of words (can't include #)" which specifies that there may be more than one word but does not specify anything other than those words which might be used to separate the words which probably isn't what we want. Given that practically we have tests using a range of separators for words including combinations of spaces and combinations of other symbols like underscores or punctuation let's just clarify that the description can contain any character other than # (marking the start of the directive/diagnostic) or newline (marking the end of this test result). Signed-off-by: Mark Brown Reviewed-by: Kees Cook Reviewed-by: David Gow Signed-off-by: Shuah Khan --- Documentation/dev-tools/ktap.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation/dev-tools') diff --git a/Documentation/dev-tools/ktap.rst b/Documentation/dev-tools/ktap.rst index d0a9565b0f44..414c105b10a9 100644 --- a/Documentation/dev-tools/ktap.rst +++ b/Documentation/dev-tools/ktap.rst @@ -80,8 +80,8 @@ have the number 1 and the number then must increase by 1 for each additional subtest within the same test at the same nesting level. The description is a description of the test, generally the name of -the test, and can be any string of words (can't include #). The -description is optional, but recommended. +the test, and can be any string of characters other than # or a +newline. The description is optional, but recommended. The directive and any diagnostic data is optional. If either are present, they must follow a hash sign, "#". -- cgit v1.2.3