diff options
Diffstat (limited to 'Documentation/dev-tools/kunit/running_tips.rst')
| -rw-r--r-- | Documentation/dev-tools/kunit/running_tips.rst | 225 |
1 files changed, 207 insertions, 18 deletions
diff --git a/Documentation/dev-tools/kunit/running_tips.rst b/Documentation/dev-tools/kunit/running_tips.rst index 7d99386cf94a..bd689db6fdd2 100644 --- a/Documentation/dev-tools/kunit/running_tips.rst +++ b/Documentation/dev-tools/kunit/running_tips.rst @@ -15,7 +15,7 @@ It can be handy to create a bash function like: .. code-block:: bash function run_kunit() { - ( cd "$(git rev-parse --show-toplevel)" && ./tools/testing/kunit/kunit.py run $@ ) + ( cd "$(git rev-parse --show-toplevel)" && ./tools/testing/kunit/kunit.py run "$@" ) } .. note:: @@ -25,8 +25,8 @@ It can be handy to create a bash function like: Running a subset of tests ------------------------- -``kunit.py run`` accepts an optional glob argument to filter tests. Currently -this only matches against suite names, but this may change in the future. +``kunit.py run`` accepts an optional glob argument to filter tests. The format +is ``"<suite_glob>[.test_glob]"``. Say that we wanted to run the sysctl tests, we could do so via: @@ -35,6 +35,13 @@ Say that we wanted to run the sysctl tests, we could do so via: $ echo -e 'CONFIG_KUNIT=y\nCONFIG_KUNIT_ALL_TESTS=y' > .kunit/.kunitconfig $ ./tools/testing/kunit/kunit.py run 'sysctl*' +We can filter down to just the "write" tests via: + +.. code-block:: bash + + $ echo -e 'CONFIG_KUNIT=y\nCONFIG_KUNIT_ALL_TESTS=y' > .kunit/.kunitconfig + $ ./tools/testing/kunit/kunit.py run 'sysctl*.*write*' + We're paying the cost of building more tests than we need this way, but it's easier than fiddling with ``.kunitconfig`` files or commenting out ``kunit_suite``'s. @@ -80,25 +87,23 @@ file ``.kunitconfig``, you can just pass in the dir, e.g. automagically, but tests could theoretically depend on incompatible options, so handling that would be tricky. +Setting kernel commandline parameters +------------------------------------- + +You can use ``--kernel_args`` to pass arbitrary kernel arguments, e.g. + +.. code-block:: bash + + $ ./tools/testing/kunit/kunit.py run --kernel_args=param=42 --kernel_args=param2=false + + Generating code coverage reports under UML ------------------------------------------ .. note:: TODO(brendanhiggins@google.com): There are various issues with UML and versions of gcc 7 and up. You're likely to run into missing ``.gcda`` - files or compile errors. We know one `faulty GCC commit - <https://github.com/gcc-mirror/gcc/commit/8c9434c2f9358b8b8bad2c1990edf10a21645f9d>`_ - but not how we'd go about getting this fixed. The compile errors still - need some investigation. - -.. note:: - TODO(brendanhiggins@google.com): for recent versions of Linux - (5.10-5.12, maybe earlier), there's a bug with gcov counters not being - flushed in UML. This translates to very low (<1%) reported coverage. This is - related to the above issue and can be worked around by replacing the - one call to ``uml_abort()`` (it's in ``os_dump_core()``) with a plain - ``exit()``. - + files or compile errors. This is different from the "normal" way of getting coverage information that is documented in Documentation/dev-tools/gcov.rst. @@ -109,6 +114,7 @@ Instead of enabling ``CONFIG_GCOV_KERNEL=y``, we can set these options: CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO=y + CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_GCOV=y @@ -117,8 +123,7 @@ Putting it together into a copy-pastable sequence of commands: .. code-block:: bash # Append coverage options to the current config - $ echo -e "CONFIG_DEBUG_KERNEL=y\nCONFIG_DEBUG_INFO=y\nCONFIG_GCOV=y" >> .kunit/.kunitconfig - $ ./tools/testing/kunit/kunit.py run + $ ./tools/testing/kunit/kunit.py run --kunitconfig=.kunit/ --kunitconfig=tools/testing/kunit/configs/coverage_uml.config # Extract the coverage information from the build dir (.kunit/) $ lcov -t "my_kunit_tests" -o coverage.info -c -d .kunit/ @@ -134,6 +139,17 @@ If your installed version of gcc doesn't work, you can tweak the steps: $ ./tools/testing/kunit/kunit.py run --make_options=CC=/usr/bin/gcc-6 $ lcov -t "my_kunit_tests" -o coverage.info -c -d .kunit/ --gcov-tool=/usr/bin/gcov-6 +Alternatively, LLVM-based toolchains can also be used: + +.. code-block:: bash + + # Build with LLVM and append coverage options to the current config + $ ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --kunitconfig=.kunit/ --kunitconfig=tools/testing/kunit/configs/coverage_uml.config + $ llvm-profdata merge -sparse default.profraw -o default.profdata + $ llvm-cov export --format=lcov .kunit/vmlinux -instr-profile default.profdata > coverage.info + # The coverage.info file is in lcov-compatible format and it can be used to e.g. generate HTML report + $ genhtml -o /tmp/coverage_html coverage.info + Running tests manually ====================== @@ -257,3 +273,176 @@ other code executed during boot, e.g. # Reset coverage counters before running the test. $ echo 0 > /sys/kernel/debug/gcov/reset $ modprobe kunit-example-test + + +Test Attributes and Filtering +============================= + +Test suites and cases can be marked with test attributes, such as speed of +test. These attributes will later be printed in test output and can be used to +filter test execution. + +Marking Test Attributes +----------------------- + +Tests are marked with an attribute by including a ``kunit_attributes`` object +in the test definition. + +Test cases can be marked using the ``KUNIT_CASE_ATTR(test_name, attributes)`` +macro to define the test case instead of ``KUNIT_CASE(test_name)``. + +.. code-block:: c + + static const struct kunit_attributes example_attr = { + .speed = KUNIT_VERY_SLOW, + }; + + static struct kunit_case example_test_cases[] = { + KUNIT_CASE_ATTR(example_test, example_attr), + }; + +.. note:: + To mark a test case as slow, you can also use ``KUNIT_CASE_SLOW(test_name)``. + This is a helpful macro as the slow attribute is the most commonly used. + +Test suites can be marked with an attribute by setting the "attr" field in the +suite definition. + +.. code-block:: c + + static const struct kunit_attributes example_attr = { + .speed = KUNIT_VERY_SLOW, + }; + + static struct kunit_suite example_test_suite = { + ..., + .attr = example_attr, + }; + +.. note:: + Not all attributes need to be set in a ``kunit_attributes`` object. Unset + attributes will remain uninitialized and act as though the attribute is set + to 0 or NULL. Thus, if an attribute is set to 0, it is treated as unset. + These unset attributes will not be reported and may act as a default value + for filtering purposes. + +Reporting Attributes +-------------------- + +When a user runs tests, attributes will be present in the raw kernel output (in +KTAP format). Note that attributes will be hidden by default in kunit.py output +for all passing tests but the raw kernel output can be accessed using the +``--raw_output`` flag. This is an example of how test attributes for test cases +will be formatted in kernel output: + +.. code-block:: none + + # example_test.speed: slow + ok 1 example_test + +This is an example of how test attributes for test suites will be formatted in +kernel output: + +.. code-block:: none + + KTAP version 2 + # Subtest: example_suite + # module: kunit_example_test + 1..3 + ... + ok 1 example_suite + +Additionally, users can output a full attribute report of tests with their +attributes, using the command line flag ``--list_tests_attr``: + +.. code-block:: bash + + kunit.py run "example" --list_tests_attr + +.. note:: + This report can be accessed when running KUnit manually by passing in the + module_param ``kunit.action=list_attr``. + +Filtering +--------- + +Users can filter tests using the ``--filter`` command line flag when running +tests. As an example: + +.. code-block:: bash + + kunit.py run --filter speed=slow + + +You can also use the following operations on filters: "<", ">", "<=", ">=", +"!=", and "=". Example: + +.. code-block:: bash + + kunit.py run --filter "speed>slow" + +This example will run all tests with speeds faster than slow. Note that the +characters < and > are often interpreted by the shell, so they may need to be +quoted or escaped, as above. + +Additionally, you can use multiple filters at once. Simply separate filters +using commas. Example: + +.. code-block:: bash + + kunit.py run --filter "speed>slow, module=kunit_example_test" + +.. note:: + You can use this filtering feature when running KUnit manually by passing + the filter as a module param: ``kunit.filter="speed>slow, speed<=normal"``. + +Filtered tests will not run or show up in the test output. You can use the +``--filter_action=skip`` flag to skip filtered tests instead. These tests will be +shown in the test output in the test but will not run. To use this feature when +running KUnit manually, use the module param ``kunit.filter_action=skip``. + +Rules of Filtering Procedure +---------------------------- + +Since both suites and test cases can have attributes, there may be conflicts +between attributes during filtering. The process of filtering follows these +rules: + +- Filtering always operates at a per-test level. + +- If a test has an attribute set, then the test's value is filtered on. + +- Otherwise, the value falls back to the suite's value. + +- If neither are set, the attribute has a global "default" value, which is used. + +List of Current Attributes +-------------------------- + +``speed`` + +This attribute indicates the speed of a test's execution (how slow or fast the +test is). + +This attribute is saved as an enum with the following categories: "normal", +"slow", or "very_slow". The assumed default speed for tests is "normal". This +indicates that the test takes a relatively trivial amount of time (less than +1 second), regardless of the machine it is running on. Any test slower than +this could be marked as "slow" or "very_slow". + +The macro ``KUNIT_CASE_SLOW(test_name)`` can be easily used to set the speed +of a test case to "slow". + +``module`` + +This attribute indicates the name of the module associated with the test. + +This attribute is automatically saved as a string and is printed for each suite. +Tests can also be filtered using this attribute. + +``is_init`` + +This attribute indicates whether the test uses init data or functions. + +This attribute is automatically saved as a boolean and tests can also be +filtered using this attribute. |
