blob: 565afc43a6e1016d194f95b7fded5af53c54d735 [file] [log] [blame] [view]
Max Moroz3a928902018-05-15 14:39:501# Code Coverage in Chromium
2
3### Coverage Dashboard: [https://chromium-coverage.appspot.com/]
Yuke Liaod3b46272018-03-14 18:25:144
Yuke Liao1ffc8cb62018-04-06 19:09:075Table of contents:
Max Moroz3a928902018-05-15 14:39:506
Yuke Liao1ffc8cb62018-04-06 19:09:077- [Coverage Script](#coverage-script)
8- [Workflow](#workflow)
9 * [Step 0 Download Tooling](#step-0-download-tooling)
10 * [Step 1 Build](#step-1-build)
11 * [Step 2 Create Raw Profiles](#step-2-create-raw-profiles)
12 * [Step 3 Create Indexed Profile](#step-3-create-indexed-profile)
13 * [Step 4 Create Coverage Reports](#step-4-create-coverage-reports)
Max Morozd73e45f2018-04-24 18:32:4714- [Contacts](#contacts)
15- [FAQ](#faq)
Yuke Liaod3b46272018-03-14 18:25:1416
Abhishek Aryaaf9811f22018-05-11 22:17:4817Chromium uses Clang source-based code coverage. This [documentation] explains
Yuke Liao1ffc8cb62018-04-06 19:09:0718how to use Clangs source-based coverage features in general.
Yuke Liaod3b46272018-03-14 18:25:1419
Abhishek Aryaaf9811f22018-05-11 22:17:4820In this document, we first introduce a code coverage script that can be used to
21generate code coverage reports for Chromium code in one command, and then
22describe the code coverage reports generation workflow.
Yuke Liaod3b46272018-03-14 18:25:1423
Yuke Liao1ffc8cb62018-04-06 19:09:0724## Coverage Script
25The [coverage script] automates the process described below and provides a
26one-stop service to generate code coverage reports in just one command.
Yuke Liaod3b46272018-03-14 18:25:1427
Yuke Liao1ffc8cb62018-04-06 19:09:0728This script is currently supported on Linux, Mac, iOS and ChromeOS platforms.
29
30Here is an example usage:
31
Yuke Liaod3b46272018-03-14 18:25:1432```
Yuke Liao1ffc8cb62018-04-06 19:09:0733$ gn gen out/coverage \
34 --args='use_clang_coverage=true is_component_build=false'
35$ python tools/code_coverage/coverage.py \
36 crypto_unittests url_unittests \
37 -b out/coverage -o out/report \
38 -c 'out/coverage/crypto_unittests' \
39 -c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \
40 -f url/ -f crypto/
41```
42The command above builds `crypto_unittests` and `url_unittests` targets and then
Abhishek Aryaaf9811f22018-05-11 22:17:4843runs them individually with their commands and arguments specified by the `-c` flag.
44For `url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report
Yuke Liao1ffc8cb62018-04-06 19:09:0745is filtered to include only files and sub-directories under `url/` and `crypto/`
46directories.
47
Abhishek Aryaaf9811f22018-05-11 22:17:4848Aside from automating the process, this script provides visualization features to
Yuke Liao1ffc8cb62018-04-06 19:09:0749view code coverage breakdown by directories and by components, for example:
50
Abhishek Aryaaf9811f22018-05-11 22:17:4851### Directory View
Yuke Liao1ffc8cb62018-04-06 19:09:0752
53![code coverage report directory view]
54
Abhishek Aryaaf9811f22018-05-11 22:17:4855### Component View
Yuke Liao1ffc8cb62018-04-06 19:09:0756
57![code coverage report component view]
58
Abhishek Aryaaf9811f22018-05-11 22:17:4859### Source View
60
61When you click on a particular source file in one of the views above, you can check
62per-line coverage information such as
63
64- Uncovered / Covered line fragments, lines and code blocks. This information can be
65useful to identify areas of code that lack test coverage.
66- Per-line hit counts indicating how many times this line was hit by all tested targets.
67This information can be useful to determine hot spots in your code.
68
69![code coverage source view]
70
Yuke Liao1ffc8cb62018-04-06 19:09:0771## Workflow
72This section presents the workflow of generating code coverage reports using two
73unit test targets in Chromium repo as an example: `crypto_unittests` and
74`url_unittests`, and the following diagram shows a step-by-step overview of the
75process.
76
77![code coverage generation workflow](images/code_coverage_workflow.png)
78
79### Step 0 Download Tooling
80Generating code coverage reports requires llvm-profdata and llvm-cov tools.
81Currently, these two tools are not part of Chromiums Clang bundle,
82[coverage script] downloads and updates them automatically, you can also
83download the tools manually ([link]).
84
85### Step 1 Build
86In Chromium, to compile code with coverage enabled, one needs to add
87`use_clang_coverage=true` and `is_component_build=false` GN flags to the args.gn
88file in the build output directory. Under the hood, they ensure
89`-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to the
90compiler.
91
92```
93$ gn gen out/coverage \
94 --args='use_clang_coverage=true is_component_build=false'
95$ gclient runhooks
96$ ninja -C out/coverage crypto_unittests url_unittests
Yuke Liaod3b46272018-03-14 18:25:1497```
98
Yuke Liao1ffc8cb62018-04-06 19:09:0799### Step 2 Create Raw Profiles
Abhishek Aryaaf9811f22018-05-11 22:17:48100The next step is to run the instrumented binaries. When the program exits, it
101writes a raw profile for each process. Because Chromium runs tests in
102multiple processes, the number of processes spawned can be as many as a few
103hundred, resulting in the generation of a few hundred gigabytes raw
104profiles. To limit the number of raw profiles, `%Nm` pattern in
Yuke Liao1ffc8cb62018-04-06 19:09:07105`LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process
106mode, where `N` is the number of raw profiles. With `N = 4`, the total size of
107the raw profiles are limited to a few gigabytes.
108
109```
110$ export LLVM_PROFILE_FILE=”out/report/crypto_unittests.%4m.profraw”
111$ ./out/coverage/crypto_unittests
112$ ls out/report/
113crypto_unittests.3657994905831792357_0.profraw
114...
115crypto_unittests.3657994905831792357_3.profraw
116```
117
118### Step 3 Create Indexed Profile
119Raw profiles must be indexed before generating code coverage reports, and this
120is done using the `merge` command of `llvm-profdata` tool, which merges multiple
Abhishek Aryaaf9811f22018-05-11 22:17:48121raw profiles (.profraw) and indexes them to create a single profile (.profdata).
Yuke Liao1ffc8cb62018-04-06 19:09:07122
123At this point, all the raw profiles can be thrown away because their information
Abhishek Aryaaf9811f22018-05-11 22:17:48124is already contained in the indexed profile.
Yuke Liao1ffc8cb62018-04-06 19:09:07125
126```
127$ llvm-profdata merge -o out/report/coverage.profdata \
128 out/report/crypto_unittests.3657994905831792357_0.profraw
129...
130out/report/crypto_unittests.3657994905831792357_3.profraw
131out/report/url_unittests.714228855822523802_0.profraw
132...
133out/report/url_unittests.714228855822523802_3.profraw
134$ ls out/report/coverage.profdata
135out/report/coverage.profdata
136```
137
138### Step 4 Create Coverage Reports
139Finally, `llvm-cov` is used to render code coverage reports. There are different
Abhishek Aryaaf9811f22018-05-11 22:17:48140report generation modes, and all of them require the following as input:
141- Indexed profile
142- All built target binaries
143- All exercised source files.
Yuke Liao1ffc8cb62018-04-06 19:09:07144
Abhishek Aryaaf9811f22018-05-11 22:17:48145For example, the following command can be used to generate per-file line-by-line
Yuke Liao1ffc8cb62018-04-06 19:09:07146code coverage report:
147
148```
149$ llvm-cov show -output-dir=out/report -format=html \
150 -instr-profile=out/report/coverage.profdata \
151 -object=out/coverage/url_unittests \
152 out/coverage/crypto_unittests
153```
154
155For more information on how to use llvm-cov, please refer to the [guide].
Yuke Liaod3b46272018-03-14 18:25:14156
Max Morozd73e45f2018-04-24 18:32:47157## Contacts
158
159### Reporting problems
Yuke Liaod3b46272018-03-14 18:25:14160For any breakage report and feature requests, please [file a bug].
161
Max Morozd73e45f2018-04-24 18:32:47162### Mailing list
Yuke Liao1ffc8cb62018-04-06 19:09:07163For questions and general discussions, please join [chrome-code-coverage group].
164
Max Morozd73e45f2018-04-24 18:32:47165## FAQ
166
167### Can I use `is_component_build=true` for code coverage build?
168
169Yes, code coverage instrumentation works with both component and non-component
170builds. Component build is usually faster to compile, but can be up to several
171times slower to run with code coverage instrumentation. For more information,
Max Morozc5e364a2018-04-25 23:19:49172see [crbug.com/831939].
173
174### I am getting some warnings while using the script, is that fine?
175
Abhishek Aryaaf9811f22018-05-11 22:17:48176Usually this is not a critical issue, but in general we tend not to have any
Max Morozc5e364a2018-04-25 23:19:49177warnings. Please check the list of [known issues], and if there is a similar
178bug, leave a comment with the command you run, the output you get, and Chromium
179revision you use. Otherwise, please [file a new issue] providing the same
180information.
181
182### How do crashes affect code coverage?
183
184If a crash of any type occurs (Segmentation Fault, CHECK failure, ASan error),
185the crashing process will not dump coverage information necessary to generate
186code coverage report. For single-process applications (e.g. fuzz targets), that
187means no coverage will be reported at all. For multi-process applications, the
Abhishek Aryaaf9811f22018-05-11 22:17:48188report will be incomplete. It is important to fix the crash first. If this is
189happening only in the coverage instrumented build, please [file a bug].
Max Morozd73e45f2018-04-24 18:32:47190
Max Moroz63cd04d2018-05-02 16:40:23191### Is it possible to obtain code coverage from a full Chromium build?
192
193Yes, with some important caveats. It is possible to build `chrome` target with
194code coverage instrumentation enabled. However, there are some inconveniences
195involved:
196
197* Linking may take a while
198* The binary is huge (~4GB)
199* The browser "works", but is noticeably slow and laggy
200* The sandbox needs to be disabled (`--no-sandbox`)
201* Coverage can be incomplete for child processes
202
203For more information, please see [crbug.com/834781].
204
Max Moroz3a928902018-05-15 14:39:50205### Why do we see significantly different coverage reported on different revisions?
206
207There can be two possible scenarios:
208
209* It can be a one time flakiness due to a broken build or failing tests.
210* It can be caused by extension of the test suite used for generating code
211coverage reports. When we add new tests to the suite, the aggregate coverage
212reported usually grows after that.
213
214### How can I improve [coverage dashboard]?
215
216Source code of the dashboard is not open sourced at the moment, but if you are a
217Googler, you should have access to the code-coverage repository. There is a
218documentation and scripts for running it locally. To get access and report
219issues, ping chrome-code-coverage@ list.
220
221### Why is coverage for X not reported or unreasonably low, even though there is a test for X?
222
223There are several reasons why coverage reports can be incomplete or incorrect:
224
225* A particular test is not used for code coverage report generation. Please
226check the [test suite], and if the test is missing, upload a CL to add it.
227* A test may have a build failure or a runtime crash. Please check [the logs]
228for that particular test target (rightmost column on the [coverage dashboard]).
229If there is any failure, please upload a CL with the fix. If you can't fix it,
230feel free to [file a bug].
231* A particular test may not be available on a particular platform. As of now,
232only reports generated on Linux are available on the [coverage dashboard].
233
234### Why is coverage for X_fuzzer.cc file not reported, even though there are no errors in the log?
235
236There was an issue with merging coverage data for multiple definitions of the
237same symbol ([crbug.com/821617]). Given that every fuzz target defines its own
238`LLVMFuzzerTestOneInput` function, most of those functions are not presented in
239the report as of now. Please note that this issue does not affect coverage of
240the functions that are called from a fuzz target, i.e. the code that is actually
241being fuzzed. We have landed the fix upstream. In Chromium the issue will get
242resolved after the next [clang roll].
243
244### Is coverage reported for the code executed inside the sandbox?
245
246Not at the moment until [crbug.com/842424] is resolved. We do not disable the
247sandbox when running the tests. However, if there are any other non-sandbox'ed
248tests for the same code, the coverage should be reported from those. For more
249information, see [crbug.com/842424].
250
Max Morozd73e45f2018-04-24 18:32:47251
Max Morozc5e364a2018-04-25 23:19:49252[chrome-code-coverage group]: https://groups.google.com/a/google.com/forum/#!forum/chrome-code-coverage
Max Moroz3a928902018-05-15 14:39:50253[code-coverage repository]: https://chrome-internal.googlesource.com/chrome/tools/code-coverage
254[coverage dashboard]: https://chromium-coverage.appspot.com/
Yuke Liao1ffc8cb62018-04-06 19:09:07255[coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py
256[code coverage report directory view]: images/code_coverage_directory_view.png
257[code coverage report component view]: images/code_coverage_component_view.png
Abhishek Aryaaf9811f22018-05-11 22:17:48258[code coverage source view]: images/code_coverage_source_view.png
Max Moroz3a928902018-05-15 14:39:50259[crbug.com/821617]: https://crbug.com/821617
Max Morozc5e364a2018-04-25 23:19:49260[crbug.com/831939]: https://crbug.com/831939
Max Moroz63cd04d2018-05-02 16:40:23261[crbug.com/834781]: https://crbug.com/834781
Max Moroz3a928902018-05-15 14:39:50262[crbug.com/842424]: https://crbug.com/842424
263[clang roll]: https://crbug.com/841908
Max Morozc5e364a2018-04-25 23:19:49264[documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
Yuke Liao1ffc8cb62018-04-06 19:09:07265[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
Max Morozc5e364a2018-04-25 23:19:49266[file a new issue]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
267[guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
Max Moroz3a928902018-05-15 14:39:50268[https://chromium-coverage.appspot.com/]: https://chromium-coverage.appspot.com/
Max Morozc5e364a2018-04-25 23:19:49269[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Tools%3ECodeCoverage
270[link]: https://storage.googleapis.com/chromium-browser-clang-staging/
Max Moroz3a928902018-05-15 14:39:50271[test suite]: https://cs.chromium.org/chromium/src/tools/code_coverage/test_suite.txt
272[the logs]: https://chromium-coverage.appspot.com/reports/latest/linux/metadata/index.html