blob: c9df271cc49093fb1d5af54ea66e43c8939c879f [file] [log] [blame] [view] [edit]
HOW TO COLLECT KERNEL CODE COVERAGE FROM A TEST RUN
===================================================
## 1. Build and use a kernel with GCOV profile enabled
### Build and install with scripts
Build and install a GCOV kernel on a Cuttlefish or physical device with one of
the following commands:
```
$ kernel/tests/tools/launch_cvd.sh --gcov
```
```
$ kernel/tests/tools/flash_device.sh --gcov
```
To view available options, run the scripts with `--help`.
### Build on your own
Build a kernel with
[`--gcov`](https://android.googlesource.com/kernel/build/+/refs/heads/main/kleaf/docs/gcov.md)
option. This will also trigger the build to save the required *.gcno files
needed to viewing the collected count data.
For example, build a Cuttlefish kernel with GCOV:
```
$ tools/bazel run --gcov //common-modules/virtual-device:virtual_device_x86_64_dist
```
## 2. Run tests with kernel coverage collection enabled
### `run_test_only.sh`
Collect test coverage data with `run_test_only.sh --gcov` and the required
options. For example,
```
$ kernel/tests/tools/run_test_only.sh --gcov \
--serial 0.0.0.0:6520 --test='selftests kselftest_net_socket'
```
To view available options, run the script with `--help`.
### `tradefed.sh`
Adding the appropriate coverage flags to the tradefed call will trigger it to
take care of mounting debugfs, reseting the gcov counts prior to test run, and
collecting gcov data files from debugfs after test completion. These coverage
arguments are:
```
--coverage --coverage-toolchain GCOV_KERNEL --auto-collect GCOV_KERNEL_COVERAGE
```
The following is a full example call running just the `kselftest_net_socket`
test in the selftests test suite that exists under the `out/tests/testcases`
directory. The artifact output has been redirected to `tf-logs` for easier
reference needed in the next step.
```
$ prebuilts/tradefed/filegroups/tradefed/tradefed.sh run commandAndExit \
template/local_min --template:map test=suite/test_mapping_suite \
--include-filter 'selftests kselftest_net_socket' \
--tests-dir=out/tests/testcases \
--primary-abi-only --log-file-path tf-logs \
--coverage --coverage-toolchain GCOV_KERNEL \
--auto-collect GCOV_KERNEL_COVERAGE
```
## 3. Create an lcov tracefile out of the gcov tar artifact from test run
The previously mentioned `run_test_only.sh` or `tradefed.sh` run will produce
a tar file artifact in the log folder with a name like
`<test>_kernel_coverage_*.tar.gz`. This tar file is an archive of all the gcov
data files collected into debugfs from the profiled device. In order to make
it easier to work with this data, it needs to be converted to a single lcov
tracefile.
The script `create-tracefile.py` facilitates this generation by handling the
required unpacking, file path corrections and ultimate `lcov` call.
`run_test_only.sh` calls `create-tracefile.py` automatically if it can locate
the kernel source. Otherwise, it shows the arguments for you to run
`create-tracefile.py` in the kernel source tree.
If you use `tradefed.sh`, you need to issue the `create-tracefile.py` command.
The following is an example where we generate a tracefile named `cov.info`
only including results from `net/socket.c`. (If no source files are specified
as included, then all source file data is used.)
```
$ kernel/tests/tools/create-tracefile.py -t tf-logs --include net/socket.c
```
## 4. Visualizing results
With the created tracefile, there are a number of different ways to view
coverage data from it. Check out `man lcov` for more options.
### Summary
```
$ lcov --summary --rc lcov_branch_coverage=1 cov.info
Reading tracefile cov.info_fix
Summary coverage rate:
lines......: 6.0% (81646 of 1370811 lines)
functions..: 9.6% (10285 of 107304 functions)
branches...: 3.7% (28639 of 765538 branches)
```
### List
```
$ lcov --list --rc lcov_branch_coverage=1 cov.info
Reading tracefile cov.info_fix
|Lines |Functions|Branches
Filename |Rate Num|Rate Num|Rate Num
================================================================================
[/usr/local/google/home/joefradley/dev/common-android-mainline-2/common/]
arch/x86/crypto/aesni-intel_glue.c |23.9% 623|22.2% 36|15.0% 240
arch/x86/crypto/blake2s-glue.c |50.0% 28|50.0% 2|16.7% 30
arch/x86/crypto/chacha_glue.c | 0.0% 157| 0.0% 10| 0.0% 80
<truncated>
virt/lib/irqbypass.c | 0.0% 137| 0.0% 6| 0.0% 88
================================================================================
Total:| 6.0% 1369k| 9.6% 0M| 3.7% 764k
```
### HTML
The `lcov` tool `genhtml` is used to generate html. To create html with the
default settings:
```
$ genhtml --branch-coverage -o html cov.info
```
The page can be viewed at `html/index.html`.
Options of interest:
* `--frame`: Creates a left hand macro view in a source file view.
* `--missed`: Helpful if you want to sort by what source is missing the most
as opposed to the default coverage percentages.