Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: GPL-2.0
0002 
0003 ============================
0004 Tips For Running KUnit Tests
0005 ============================
0006 
0007 Using ``kunit.py run`` ("kunit tool")
0008 =====================================
0009 
0010 Running from any directory
0011 --------------------------
0012 
0013 It can be handy to create a bash function like:
0014 
0015 .. code-block:: bash
0016 
0017         function run_kunit() {
0018           ( cd "$(git rev-parse --show-toplevel)" && ./tools/testing/kunit/kunit.py run "$@" )
0019         }
0020 
0021 .. note::
0022         Early versions of ``kunit.py`` (before 5.6) didn't work unless run from
0023         the kernel root, hence the use of a subshell and ``cd``.
0024 
0025 Running a subset of tests
0026 -------------------------
0027 
0028 ``kunit.py run`` accepts an optional glob argument to filter tests. The format
0029 is ``"<suite_glob>[.test_glob]"``.
0030 
0031 Say that we wanted to run the sysctl tests, we could do so via:
0032 
0033 .. code-block:: bash
0034 
0035         $ echo -e 'CONFIG_KUNIT=y\nCONFIG_KUNIT_ALL_TESTS=y' > .kunit/.kunitconfig
0036         $ ./tools/testing/kunit/kunit.py run 'sysctl*'
0037 
0038 We can filter down to just the "write" tests via:
0039 
0040 .. code-block:: bash
0041 
0042         $ echo -e 'CONFIG_KUNIT=y\nCONFIG_KUNIT_ALL_TESTS=y' > .kunit/.kunitconfig
0043         $ ./tools/testing/kunit/kunit.py run 'sysctl*.*write*'
0044 
0045 We're paying the cost of building more tests than we need this way, but it's
0046 easier than fiddling with ``.kunitconfig`` files or commenting out
0047 ``kunit_suite``'s.
0048 
0049 However, if we wanted to define a set of tests in a less ad hoc way, the next
0050 tip is useful.
0051 
0052 Defining a set of tests
0053 -----------------------
0054 
0055 ``kunit.py run`` (along with ``build``, and ``config``) supports a
0056 ``--kunitconfig`` flag. So if you have a set of tests that you want to run on a
0057 regular basis (especially if they have other dependencies), you can create a
0058 specific ``.kunitconfig`` for them.
0059 
0060 E.g. kunit has one for its tests:
0061 
0062 .. code-block:: bash
0063 
0064         $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit/.kunitconfig
0065 
0066 Alternatively, if you're following the convention of naming your
0067 file ``.kunitconfig``, you can just pass in the dir, e.g.
0068 
0069 .. code-block:: bash
0070 
0071         $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit
0072 
0073 .. note::
0074         This is a relatively new feature (5.12+) so we don't have any
0075         conventions yet about on what files should be checked in versus just
0076         kept around locally. It's up to you and your maintainer to decide if a
0077         config is useful enough to submit (and therefore have to maintain).
0078 
0079 .. note::
0080         Having ``.kunitconfig`` fragments in a parent and child directory is
0081         iffy. There's discussion about adding an "import" statement in these
0082         files to make it possible to have a top-level config run tests from all
0083         child directories. But that would mean ``.kunitconfig`` files are no
0084         longer just simple .config fragments.
0085 
0086         One alternative would be to have kunit tool recursively combine configs
0087         automagically, but tests could theoretically depend on incompatible
0088         options, so handling that would be tricky.
0089 
0090 Setting kernel commandline parameters
0091 -------------------------------------
0092 
0093 You can use ``--kernel_args`` to pass arbitrary kernel arguments, e.g.
0094 
0095 .. code-block:: bash
0096 
0097         $ ./tools/testing/kunit/kunit.py run --kernel_args=param=42 --kernel_args=param2=false
0098 
0099 
0100 Generating code coverage reports under UML
0101 ------------------------------------------
0102 
0103 .. note::
0104         TODO(brendanhiggins@google.com): There are various issues with UML and
0105         versions of gcc 7 and up. You're likely to run into missing ``.gcda``
0106         files or compile errors.
0107 
0108 This is different from the "normal" way of getting coverage information that is
0109 documented in Documentation/dev-tools/gcov.rst.
0110 
0111 Instead of enabling ``CONFIG_GCOV_KERNEL=y``, we can set these options:
0112 
0113 .. code-block:: none
0114 
0115         CONFIG_DEBUG_KERNEL=y
0116         CONFIG_DEBUG_INFO=y
0117         CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
0118         CONFIG_GCOV=y
0119 
0120 
0121 Putting it together into a copy-pastable sequence of commands:
0122 
0123 .. code-block:: bash
0124 
0125         # Append coverage options to the current config
0126         $ ./tools/testing/kunit/kunit.py run --kunitconfig=.kunit/ --kunitconfig=tools/testing/kunit/configs/coverage_uml.config
0127         # Extract the coverage information from the build dir (.kunit/)
0128         $ lcov -t "my_kunit_tests" -o coverage.info -c -d .kunit/
0129 
0130         # From here on, it's the same process as with CONFIG_GCOV_KERNEL=y
0131         # E.g. can generate an HTML report in a tmp dir like so:
0132         $ genhtml -o /tmp/coverage_html coverage.info
0133 
0134 
0135 If your installed version of gcc doesn't work, you can tweak the steps:
0136 
0137 .. code-block:: bash
0138 
0139         $ ./tools/testing/kunit/kunit.py run --make_options=CC=/usr/bin/gcc-6
0140         $ lcov -t "my_kunit_tests" -o coverage.info -c -d .kunit/ --gcov-tool=/usr/bin/gcov-6
0141 
0142 
0143 Running tests manually
0144 ======================
0145 
0146 Running tests without using ``kunit.py run`` is also an important use case.
0147 Currently it's your only option if you want to test on architectures other than
0148 UML.
0149 
0150 As running the tests under UML is fairly straightforward (configure and compile
0151 the kernel, run the ``./linux`` binary), this section will focus on testing
0152 non-UML architectures.
0153 
0154 
0155 Running built-in tests
0156 ----------------------
0157 
0158 When setting tests to ``=y``, the tests will run as part of boot and print
0159 results to dmesg in TAP format. So you just need to add your tests to your
0160 ``.config``, build and boot your kernel as normal.
0161 
0162 So if we compiled our kernel with:
0163 
0164 .. code-block:: none
0165 
0166         CONFIG_KUNIT=y
0167         CONFIG_KUNIT_EXAMPLE_TEST=y
0168 
0169 Then we'd see output like this in dmesg signaling the test ran and passed:
0170 
0171 .. code-block:: none
0172 
0173         TAP version 14
0174         1..1
0175             # Subtest: example
0176             1..1
0177             # example_simple_test: initializing
0178             ok 1 - example_simple_test
0179         ok 1 - example
0180 
0181 Running tests as modules
0182 ------------------------
0183 
0184 Depending on the tests, you can build them as loadable modules.
0185 
0186 For example, we'd change the config options from before to
0187 
0188 .. code-block:: none
0189 
0190         CONFIG_KUNIT=y
0191         CONFIG_KUNIT_EXAMPLE_TEST=m
0192 
0193 Then after booting into our kernel, we can run the test via
0194 
0195 .. code-block:: none
0196 
0197         $ modprobe kunit-example-test
0198 
0199 This will then cause it to print TAP output to stdout.
0200 
0201 .. note::
0202         The ``modprobe`` will *not* have a non-zero exit code if any test
0203         failed (as of 5.13). But ``kunit.py parse`` would, see below.
0204 
0205 .. note::
0206         You can set ``CONFIG_KUNIT=m`` as well, however, some features will not
0207         work and thus some tests might break. Ideally tests would specify they
0208         depend on ``KUNIT=y`` in their ``Kconfig``'s, but this is an edge case
0209         most test authors won't think about.
0210         As of 5.13, the only difference is that ``current->kunit_test`` will
0211         not exist.
0212 
0213 Pretty-printing results
0214 -----------------------
0215 
0216 You can use ``kunit.py parse`` to parse dmesg for test output and print out
0217 results in the same familiar format that ``kunit.py run`` does.
0218 
0219 .. code-block:: bash
0220 
0221         $ ./tools/testing/kunit/kunit.py parse /var/log/dmesg
0222 
0223 
0224 Retrieving per suite results
0225 ----------------------------
0226 
0227 Regardless of how you're running your tests, you can enable
0228 ``CONFIG_KUNIT_DEBUGFS`` to expose per-suite TAP-formatted results:
0229 
0230 .. code-block:: none
0231 
0232         CONFIG_KUNIT=y
0233         CONFIG_KUNIT_EXAMPLE_TEST=m
0234         CONFIG_KUNIT_DEBUGFS=y
0235 
0236 The results for each suite will be exposed under
0237 ``/sys/kernel/debug/kunit/<suite>/results``.
0238 So using our example config:
0239 
0240 .. code-block:: bash
0241 
0242         $ modprobe kunit-example-test > /dev/null
0243         $ cat /sys/kernel/debug/kunit/example/results
0244         ... <TAP output> ...
0245 
0246         # After removing the module, the corresponding files will go away
0247         $ modprobe -r kunit-example-test
0248         $ cat /sys/kernel/debug/kunit/example/results
0249         /sys/kernel/debug/kunit/example/results: No such file or directory
0250 
0251 Generating code coverage reports
0252 --------------------------------
0253 
0254 See Documentation/dev-tools/gcov.rst for details on how to do this.
0255 
0256 The only vaguely KUnit-specific advice here is that you probably want to build
0257 your tests as modules. That way you can isolate the coverage from tests from
0258 other code executed during boot, e.g.
0259 
0260 .. code-block:: bash
0261 
0262         # Reset coverage counters before running the test.
0263         $ echo 0 > /sys/kernel/debug/gcov/reset
0264         $ modprobe kunit-example-test