blob: bbc7e8b89857855eebb92f3e23efb96f3e147b33 [file] [log] [blame] [view]
Yuke Liaod3b46272018-03-14 18:25:141# Code coverage in Chromium
2
Yuke Liao1ffc8cb62018-04-06 19:09:073Table of contents:
4- [Coverage Script](#coverage-script)
5- [Workflow](#workflow)
6 * [Step 0 Download Tooling](#step-0-download-tooling)
7 * [Step 1 Build](#step-1-build)
8 * [Step 2 Create Raw Profiles](#step-2-create-raw-profiles)
9 * [Step 3 Create Indexed Profile](#step-3-create-indexed-profile)
10 * [Step 4 Create Coverage Reports](#step-4-create-coverage-reports)
Yuke Liaod3b46272018-03-14 18:25:1411
Yuke Liao1ffc8cb62018-04-06 19:09:0712Chromium uses Clang source-based code coverage, this [documentation] explains
13how to use Clangs source-based coverage features in general.
Yuke Liaod3b46272018-03-14 18:25:1414
Yuke Liao1ffc8cb62018-04-06 19:09:0715In this doc, we first introduce a code coverage script that can be used to
16generate code coverage reports for Chromium code in one command, and then dive
17into details to describe the code coverage reports generation workflow.
Yuke Liaod3b46272018-03-14 18:25:1418
Yuke Liao1ffc8cb62018-04-06 19:09:0719## Coverage Script
20The [coverage script] automates the process described below and provides a
21one-stop service to generate code coverage reports in just one command.
Yuke Liaod3b46272018-03-14 18:25:1422
Yuke Liao1ffc8cb62018-04-06 19:09:0723This script is currently supported on Linux, Mac, iOS and ChromeOS platforms.
24
25Here is an example usage:
26
Yuke Liaod3b46272018-03-14 18:25:1427```
Yuke Liao1ffc8cb62018-04-06 19:09:0728$ gn gen out/coverage \
29 --args='use_clang_coverage=true is_component_build=false'
30$ python tools/code_coverage/coverage.py \
31 crypto_unittests url_unittests \
32 -b out/coverage -o out/report \
33 -c 'out/coverage/crypto_unittests' \
34 -c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \
35 -f url/ -f crypto/
36```
37The command above builds `crypto_unittests` and `url_unittests` targets and then
38runs each with the command and arguments specified by the `-c` flag. For
39`url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report
40is filtered to include only files and sub-directories under `url/` and `crypto/`
41directories.
42
43Aside from automating the process, this script provides additional features to
44view code coverage breakdown by directories and by components, for example:
45
46Directory View:
47
48![code coverage report directory view]
49
50Component View:
51
52![code coverage report component view]
53
54## Workflow
55This section presents the workflow of generating code coverage reports using two
56unit test targets in Chromium repo as an example: `crypto_unittests` and
57`url_unittests`, and the following diagram shows a step-by-step overview of the
58process.
59
60![code coverage generation workflow](images/code_coverage_workflow.png)
61
62### Step 0 Download Tooling
63Generating code coverage reports requires llvm-profdata and llvm-cov tools.
64Currently, these two tools are not part of Chromiums Clang bundle,
65[coverage script] downloads and updates them automatically, you can also
66download the tools manually ([link]).
67
68### Step 1 Build
69In Chromium, to compile code with coverage enabled, one needs to add
70`use_clang_coverage=true` and `is_component_build=false` GN flags to the args.gn
71file in the build output directory. Under the hood, they ensure
72`-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to the
73compiler.
74
75```
76$ gn gen out/coverage \
77 --args='use_clang_coverage=true is_component_build=false'
78$ gclient runhooks
79$ ninja -C out/coverage crypto_unittests url_unittests
Yuke Liaod3b46272018-03-14 18:25:1480```
81
Yuke Liao1ffc8cb62018-04-06 19:09:0782### Step 2 Create Raw Profiles
83The next step is to run the instrumented binaries, and when the program exits it
84will write a raw profile for each process. Because Chromium runs tests in
85multiple processes, and the number of processes spawned can be as many as a few
86hundred, which results in the generation of a few hundred gigabytes raw
87profiles, to limit the number of raw profiles, `%Nm` pattern in
88`LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process
89mode, where `N` is the number of raw profiles. With `N = 4`, the total size of
90the raw profiles are limited to a few gigabytes.
91
92```
93$ export LLVM_PROFILE_FILE=”out/report/crypto_unittests.%4m.profraw”
94$ ./out/coverage/crypto_unittests
95$ ls out/report/
96crypto_unittests.3657994905831792357_0.profraw
97...
98crypto_unittests.3657994905831792357_3.profraw
99```
100
101### Step 3 Create Indexed Profile
102Raw profiles must be indexed before generating code coverage reports, and this
103is done using the `merge` command of `llvm-profdata` tool, which merges multiple
104raw profiles (.profraw) and index them to create a single profile (.profdata).
105
106At this point, all the raw profiles can be thrown away because their information
107are already contained in the indexed profile.
108
109```
110$ llvm-profdata merge -o out/report/coverage.profdata \
111 out/report/crypto_unittests.3657994905831792357_0.profraw
112...
113out/report/crypto_unittests.3657994905831792357_3.profraw
114out/report/url_unittests.714228855822523802_0.profraw
115...
116out/report/url_unittests.714228855822523802_3.profraw
117$ ls out/report/coverage.profdata
118out/report/coverage.profdata
119```
120
121### Step 4 Create Coverage Reports
122Finally, `llvm-cov` is used to render code coverage reports. There are different
123report generation modes, and all of them require the indexed profile, all the
124built binaries and all the exercised source files to be available.
125
126For example, following command can be used to generate per-file line-by-line
127code coverage report:
128
129```
130$ llvm-cov show -output-dir=out/report -format=html \
131 -instr-profile=out/report/coverage.profdata \
132 -object=out/coverage/url_unittests \
133 out/coverage/crypto_unittests
134```
135
136For more information on how to use llvm-cov, please refer to the [guide].
Yuke Liaod3b46272018-03-14 18:25:14137
138## Reporting problems
Yuke Liaod3b46272018-03-14 18:25:14139For any breakage report and feature requests, please [file a bug].
140
Yuke Liao1ffc8cb62018-04-06 19:09:07141## Mail list
142For questions and general discussions, please join [chrome-code-coverage group].
143
144[documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
145[coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py
146[code coverage report directory view]: images/code_coverage_directory_view.png
147[code coverage report component view]: images/code_coverage_component_view.png
148[link]: https://storage.googleapis.com/chromium-browser-clang-staging/
149[guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
150[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
151[chrome-code-coverage group]: https://groups.google.com/a/google.com/forum/#!forum/chrome-code-coverage