1HOW TO COLLECT KERNEL CODE COVERAGE FROM A TEST RUN 2=================================================== 3 4 5## 1. Build and use a kernel with GCOV profile enabled 6### Build and install with scripts 7Build and install a GCOV kernel on a Cuttlefish or physical device with one of 8the following commands: 9``` 10$ kernel/tests/tools/launch_cvd.sh --gcov 11``` 12``` 13$ kernel/tests/tools/flash_device.sh --gcov 14``` 15To view available options, run the scripts with `--help`. 16 17### Build on your own 18Build a kernel with 19[`--gcov`](https://android.googlesource.com/kernel/build/+/refs/heads/main/kleaf/docs/gcov.md) 20option. This will also trigger the build to save the required *.gcno files 21needed to viewing the collected count data. 22 23For example, build a Cuttlefish kernel with GCOV: 24``` 25$ tools/bazel run --gcov //common-modules/virtual-device:virtual_device_x86_64_dist 26``` 27 28## 2. Run tests with kernel coverage collection enabled 29### `run_test_only.sh` 30Collect test coverage data with `run_test_only.sh --gcov` and the required 31options. For example, 32 33``` 34$ kernel/tests/tools/run_test_only.sh --gcov \ 35 --serial 0.0.0.0:6520 --test='selftests kselftest_net_socket' 36``` 37 38To view available options, run the script with `--help`. 39 40### `tradefed.sh` 41Adding the appropriate coverage flags to the tradefed call will trigger it to 42take care of mounting debugfs, reseting the gcov counts prior to test run, and 43collecting gcov data files from debugfs after test completion. These coverage 44arguments are: 45``` 46--coverage --coverage-toolchain GCOV_KERNEL --auto-collect GCOV_KERNEL_COVERAGE 47``` 48 49The following is a full example call running just the `kselftest_net_socket` 50test in the selftests test suite that exists under the `out/tests/testcases` 51directory. The artifact output has been redirected to `tf-logs` for easier 52reference needed in the next step. 53``` 54$ prebuilts/tradefed/filegroups/tradefed/tradefed.sh run commandAndExit \ 55 template/local_min --template:map test=suite/test_mapping_suite \ 56 --include-filter 'selftests kselftest_net_socket' \ 57 --tests-dir=out/tests/testcases \ 58 --primary-abi-only --log-file-path tf-logs \ 59 --coverage --coverage-toolchain GCOV_KERNEL \ 60 --auto-collect GCOV_KERNEL_COVERAGE 61``` 62 63## 3. Create an lcov tracefile out of the gcov tar artifact from test run 64The previously mentioned `run_test_only.sh` or `tradefed.sh` run will produce 65a tar file artifact in the log folder with a name like 66`<test>_kernel_coverage_*.tar.gz`. This tar file is an archive of all the gcov 67data files collected into debugfs from the profiled device. In order to make 68it easier to work with this data, it needs to be converted to a single lcov 69tracefile. 70 71The script `create-tracefile.py` facilitates this generation by handling the 72required unpacking, file path corrections and ultimate `lcov` call. 73`run_test_only.sh` calls `create-tracefile.py` automatically if it can locate 74the kernel source. Otherwise, it shows the arguments for you to run 75`create-tracefile.py` in the kernel source tree. 76 77If you use `tradefed.sh`, you need to issue the `create-tracefile.py` command. 78The following is an example where we generate a tracefile named `cov.info` 79only including results from `net/socket.c`. (If no source files are specified 80as included, then all source file data is used.) 81``` 82$ kernel/tests/tools/create-tracefile.py -t tf-logs --include net/socket.c 83``` 84 85## 4. Visualizing results 86With the created tracefile, there are a number of different ways to view 87coverage data from it. Check out `man lcov` for more options. 88### Summary 89``` 90$ lcov --summary --rc lcov_branch_coverage=1 cov.info 91Reading tracefile cov.info_fix 92Summary coverage rate: 93 lines......: 6.0% (81646 of 1370811 lines) 94 functions..: 9.6% (10285 of 107304 functions) 95 branches...: 3.7% (28639 of 765538 branches) 96``` 97### List 98``` 99$ lcov --list --rc lcov_branch_coverage=1 cov.info 100Reading tracefile cov.info_fix 101 |Lines |Functions|Branches 102Filename |Rate Num|Rate Num|Rate Num 103================================================================================ 104[/usr/local/google/home/joefradley/dev/common-android-mainline-2/common/] 105arch/x86/crypto/aesni-intel_glue.c |23.9% 623|22.2% 36|15.0% 240 106arch/x86/crypto/blake2s-glue.c |50.0% 28|50.0% 2|16.7% 30 107arch/x86/crypto/chacha_glue.c | 0.0% 157| 0.0% 10| 0.0% 80 108<truncated> 109virt/lib/irqbypass.c | 0.0% 137| 0.0% 6| 0.0% 88 110================================================================================ 111 Total:| 6.0% 1369k| 9.6% 0M| 3.7% 764k 112``` 113### HTML 114The `lcov` tool `genhtml` is used to generate html. To create html with the 115default settings: 116 117``` 118$ genhtml --branch-coverage -o html cov.info 119``` 120 121The page can be viewed at `html/index.html`. 122 123Options of interest: 124 * `--frame`: Creates a left hand macro view in a source file view. 125 * `--missed`: Helpful if you want to sort by what source is missing the most 126 as opposed to the default coverage percentages. 127