blob: 85d9f29704997bd31e92f4ab338b7fdecd9c856d [file] [log] [blame] [view]
Max Moroz3a928902018-05-15 14:39:501# Code Coverage in Chromium
2
Prakhare84bb3b2021-11-29 03:28:443### Coverage Dashboard: [link](https://analysis.chromium.org/coverage/p/chromium)
Yuke Liaod3b46272018-03-14 18:25:144
Yuke Liao1ffc8cb62018-04-06 19:09:075Table of contents:
Max Moroz3a928902018-05-15 14:39:506
Roberto Carrillo3b567862019-01-30 19:01:257- [Coverage Infrastructure](#coverage-infra)
8 * [Coverage Builders](#coverage-builders)
9 * [Coverage Service](#coverage-service)
10 * [Coverage Clients](#coverage-clients)
Roberto Carrillobc1560e2019-01-30 20:08:5811- [Local Coverage Script](#local-coverage-script)
Yuke Liao1ffc8cb62018-04-06 19:09:0712 * [Step 0 Download Tooling](#step-0-download-tooling)
13 * [Step 1 Build](#step-1-build)
14 * [Step 2 Create Raw Profiles](#step-2-create-raw-profiles)
15 * [Step 3 Create Indexed Profile](#step-3-create-indexed-profile)
16 * [Step 4 Create Coverage Reports](#step-4-create-coverage-reports)
Arthur Wang3cae9252024-08-27 19:47:2317- [Read The Artifact](#read-the-artifact)
Arthur Wang7eb6a482024-08-27 20:10:0918 * [HTML report](#html-report)
19 * [lcov report](#lcov-report)
Max Morozd73e45f2018-04-24 18:32:4720- [Contacts](#contacts)
21- [FAQ](#faq)
Yuke Liaod3b46272018-03-14 18:25:1422
Yuke Liaod3b46272018-03-14 18:25:1423
Arthur Wang3cae9252024-08-27 19:47:2324This document is divided into two parts.
Prakharf41864b02022-07-18 19:03:5125- The first part introduces the code coverage infrastructure that
Roberto Carrillo3b567862019-01-30 19:01:2526continuously generates code coverage information for the whole codebase and for
27specific CLs in Gerrit. For the latter, refer to
Roberto Carrillo5221fc12019-01-30 21:34:5028[code\_coverage\_in\_gerrit.md](code_coverage_in_gerrit.md).
Prakharf41864b02022-07-18 19:03:5129- The second part talks about how to generate code coverage locally for Clang-compiled languages like C++. Refer to [android code coverage instructions] for instructions for java code.
Roberto Carrillo3b567862019-01-30 19:01:2530
31## Coverage Infrastructure
32
33![coverage infra diagram]
34
35There are 3 layers in the system:
36
37### Coverage Builders
38
39The first layer is the LUCI builders that
40 - build instrumented targets,
41 - run the instrumented tests,
42 - merge the results into single streams,
43 - upload data to cloud storage.
44
45There are two types of builder:
46
47CI Builder
48
Yuke Liao43bbbcd52019-06-21 19:34:5049The code coverage CI Builders periodically build all the test targets and fuzzer
Roberto Carrillo3b567862019-01-30 19:01:2550targets for a given platform and instrument all available source files. Then
51save the coverage data to a dedicated storage bucket.
52
53CQ Builder
54
55The code coverage CQ builders instrument only the files changed for a given CL.
Yuke Liao43bbbcd52019-06-21 19:34:5056More information about per-cl coverage info in [this
Roberto Carrillo5221fc12019-01-30 21:34:5057doc](code_coverage_in_gerrit.md).
Roberto Carrillo3b567862019-01-30 19:01:2558
59### Coverage Service
60
61The second layer in the system consists of an AppEngine application that
62consumes the coverage data from the builders above, structures it and stores it
63in cloud datastore. It then serves the information to the clients below.
64
65### Coverage Clients
66
67In the last layer we currently have two clients that consume the service:
68
69#### Coverage Dashboard
70
71The [coverage dashboard] front end is hosted in the same application as the
72service above.
73It shows the full-code coverage reports with links to the builds that generated
74them, as well as per-directory and per-component aggregation, and can be drilled
75down to the single line of code level of detail.
76
Yuke Liao43bbbcd52019-06-21 19:34:5077Refer to the following screenshots:
Roberto Carrillo3b567862019-01-30 19:01:2578
79##### Directory View
80
Yuke Liao43bbbcd52019-06-21 19:34:5081See coverage breakdown by directories (default landing page).
82
Roberto Carrillo3b567862019-01-30 19:01:2583![coverage dashboard directory view]
84
85##### Component View
86
Yuke Liao43bbbcd52019-06-21 19:34:5087Use the view dropdown menu to switch between directory and component.
88
Roberto Carrillo3b567862019-01-30 19:01:2589![coverage dashboard component view]
90
91##### Source View
92
Yuke Liao43bbbcd52019-06-21 19:34:5093Click on a particular source file in one of the views above to see line-by-line
94coverage breakdown, and it's useful to identify:
95- Uncovered lines and code blocks that lack test coverage.
Roberto Carrillo3b567862019-01-30 19:01:2596- Potentially dead code. See [dead code example].
Yuke Liao43bbbcd52019-06-21 19:34:5097- Hot spots in your code.
Roberto Carrillo3b567862019-01-30 19:01:2598
99![coverage dashboard file view]
100
Yuke Liao43bbbcd52019-06-21 19:34:50101##### Project View
102
103Click on "Previous Reports" to check out the coverage history of the project.
104
105![coverage dashboard link to previous reports]
106
107List of historical coverage reports are in reverse chronological order.
108
109![coverage dashboard previous reports]
110
Roberto Carrillo3b567862019-01-30 19:01:25111#### Gerrit Coverage View
112
113The other client supported at the moment is the gerrit plugin for code coverage.
114
115![gerrit coverage view]
116
117See [this doc](code_coverage_in_gerrit.md) for information about the feature
118that allows gerrit to display code coverage information generated for a given CL
119by CQ bot. Or see this
Roberto Carrillo5221fc12019-01-30 21:34:50120[15-second video tutorial](https://www.youtube.com/watch?v=cxXlYcSgIPE).
Yuke Liaod3b46272018-03-14 18:25:14121
Roberto Carrillobc1560e2019-01-30 20:08:58122## Local Coverage Script
Prakharf41864b02022-07-18 19:03:51123This [documentation] explains how to use Clang’s source-based coverage
124features in general. The [coverage script] automates the process described below and provides a
Roberto Carrillo3b567862019-01-30 19:01:25125one-stop service to generate code coverage reports locally in just one command.
Yuke Liaod3b46272018-03-14 18:25:14126
Ben Joyce88282362021-01-29 23:53:31127This script is currently supported on Android, Linux, Mac, iOS and ChromeOS
128platforms.
Yuke Liao1ffc8cb62018-04-06 19:09:07129
130Here is an example usage:
131
Yuke Liaod3b46272018-03-14 18:25:14132```
Yuke Liao1ffc8cb62018-04-06 19:09:07133$ gn gen out/coverage \
Bryce Thomasc9137cf2020-03-31 19:47:17134 --args="use_clang_coverage=true is_component_build=false
135 dcheck_always_on=true is_debug=false"
Yuke Liao1ffc8cb62018-04-06 19:09:07136$ python tools/code_coverage/coverage.py \
137 crypto_unittests url_unittests \
138 -b out/coverage -o out/report \
139 -c 'out/coverage/crypto_unittests' \
140 -c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \
141 -f url/ -f crypto/
142```
143The command above builds `crypto_unittests` and `url_unittests` targets and then
Max Moroza5a95272018-08-31 16:20:55144runs them individually with their commands and arguments specified by the `-c` flag.
Abhishek Aryaaf9811f22018-05-11 22:17:48145For `url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report
Yuke Liao1ffc8cb62018-04-06 19:09:07146is filtered to include only files and sub-directories under `url/` and `crypto/`
147directories.
148
Abhishek Aryaaf9811f22018-05-11 22:17:48149Aside from automating the process, this script provides visualization features to
Roberto Carrillo3b567862019-01-30 19:01:25150view code coverage breakdown by directories and by components, similar to the
151views in the [coverage dashboard](#coverage-dashboard) above.
Abhishek Aryaaf9811f22018-05-11 22:17:48152
Yuke Liao1ffc8cb62018-04-06 19:09:07153## Workflow
154This section presents the workflow of generating code coverage reports using two
155unit test targets in Chromium repo as an example: `crypto_unittests` and
156`url_unittests`, and the following diagram shows a step-by-step overview of the
157process.
158
159![code coverage generation workflow](images/code_coverage_workflow.png)
160
161### Step 0 Download Tooling
162Generating code coverage reports requires llvm-profdata and llvm-cov tools.
Arthur Wang3cae9252024-08-27 19:47:23163You can get them by adding `"checkout_clang_coverage_tools": True,` to
Zequan Wu6d00cccd2021-03-15 22:40:44164`custom_vars` in the `.gclient` config and run `gclient runhooks`. You can also
165download the tools manually ([tools link])
Yuke Liao1ffc8cb62018-04-06 19:09:07166
167### Step 1 Build
168In Chromium, to compile code with coverage enabled, one needs to add
Yuke Liao8c0868fe62019-10-22 21:02:33169`use_clang_coverage=true`, `is_component_build=false` and `is_debug=false` GN
170flags to the args.gn file in the build output directory. Under the hood, they
171ensure `-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to
172the compiler.
Yuke Liao1ffc8cb62018-04-06 19:09:07173
174```
175$ gn gen out/coverage \
Yuke Liao8c0868fe62019-10-22 21:02:33176 --args='use_clang_coverage=true is_component_build=false is_debug=false'
Yuke Liao1ffc8cb62018-04-06 19:09:07177$ gclient runhooks
Max Morozf5b31fcd2018-08-10 21:55:48178$ autoninja -C out/coverage crypto_unittests url_unittests
Yuke Liaod3b46272018-03-14 18:25:14179```
180
Yuke Liao1ffc8cb62018-04-06 19:09:07181### Step 2 Create Raw Profiles
Yuke Liaobc35726b2018-10-31 22:16:21182The next step is to run the instrumented binaries. When the program exits, it
Abhishek Aryaaf9811f22018-05-11 22:17:48183writes a raw profile for each process. Because Chromium runs tests in
184multiple processes, the number of processes spawned can be as many as a few
185hundred, resulting in the generation of a few hundred gigabytes’ raw
186profiles. To limit the number of raw profiles, `%Nm` pattern in
Yuke Liao1ffc8cb62018-04-06 19:09:07187`LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process
188mode, where `N` is the number of raw profiles. With `N = 4`, the total size of
Ben Joyce88282362021-01-29 23:53:31189the raw profiles are limited to a few gigabytes. (If working on Android, the
190.profraw files will be located in ./out/coverage/coverage by default.)
Yuke Liao1ffc8cb62018-04-06 19:09:07191
Alan Zhaof8fa31302024-01-11 03:35:39192Additionally, we also recommend enabling the continuous mode by adding the `%c`
193pattern to `LLVM_PROFILE_FILE`. The continuous mode updates counters in real
194time instead of flushing to disk at process exit. This recovers coverage data
195from tests that exit abnormally (e.g. death tests). Furthermore, the continuous
196mode is required to recover coverage data for tests that run in sandboxed
197processes. For more information, see crbug.com/1468343.
198
Yuke Liao1ffc8cb62018-04-06 19:09:07199```
Alan Zhaof8fa31302024-01-11 03:35:39200$ export LLVM_PROFILE_FILE="out/report/crypto_unittests.%4m%c.profraw"
Yuke Liao1ffc8cb62018-04-06 19:09:07201$ ./out/coverage/crypto_unittests
202$ ls out/report/
203crypto_unittests.3657994905831792357_0.profraw
204...
205crypto_unittests.3657994905831792357_3.profraw
206```
207
208### Step 3 Create Indexed Profile
209Raw profiles must be indexed before generating code coverage reports, and this
210is done using the `merge` command of `llvm-profdata` tool, which merges multiple
Abhishek Aryaaf9811f22018-05-11 22:17:48211raw profiles (.profraw) and indexes them to create a single profile (.profdata).
Yuke Liao1ffc8cb62018-04-06 19:09:07212
213At this point, all the raw profiles can be thrown away because their information
Abhishek Aryaaf9811f22018-05-11 22:17:48214is already contained in the indexed profile.
Yuke Liao1ffc8cb62018-04-06 19:09:07215
216```
217$ llvm-profdata merge -o out/report/coverage.profdata \
218 out/report/crypto_unittests.3657994905831792357_0.profraw
219...
220out/report/crypto_unittests.3657994905831792357_3.profraw
221out/report/url_unittests.714228855822523802_0.profraw
222...
223out/report/url_unittests.714228855822523802_3.profraw
224$ ls out/report/coverage.profdata
225out/report/coverage.profdata
226```
227
228### Step 4 Create Coverage Reports
229Finally, `llvm-cov` is used to render code coverage reports. There are different
Abhishek Aryaaf9811f22018-05-11 22:17:48230report generation modes, and all of them require the following as input:
231- Indexed profile
232- All built target binaries
Roberto Carrillo5221fc12019-01-30 21:34:50233- All exercised source files
Yuke Liao1ffc8cb62018-04-06 19:09:07234
Abhishek Aryaaf9811f22018-05-11 22:17:48235For example, the following command can be used to generate per-file line-by-line
Yuke Liao1ffc8cb62018-04-06 19:09:07236code coverage report:
237
238```
239$ llvm-cov show -output-dir=out/report -format=html \
240 -instr-profile=out/report/coverage.profdata \
Choongwoo Han56752522021-06-10 17:38:34241 -compilation-dir=out/coverage \
Yuke Liao1ffc8cb62018-04-06 19:09:07242 -object=out/coverage/url_unittests \
243 out/coverage/crypto_unittests
244```
245
Ben Joyce88282362021-01-29 23:53:31246If creating a report for Android, the -object arg would be the lib.unstripped
247file, ie out/coverage/lib.unstripped/libcrypto_unittests__library.so
248
Yuke Liao1ffc8cb62018-04-06 19:09:07249For more information on how to use llvm-cov, please refer to the [guide].
Yuke Liaod3b46272018-03-14 18:25:14250
Arthur Wang3cae9252024-08-27 19:47:23251## Read The Artifact
252
253The code coverage tool generates some artifacts, and it is good to
254understand the data format to be used by automation tools.
255
256### HTML Report
257
258If the argument `--format=html` is used in the `llvm-cov export` command, it
259generates a report in html format. In this html report, it shows the source
260files, lists the functions and coverage metadata on whether the functions are
261executed or not.
262
263Reading a html report is straightforward: Just open up this html page with a
264Chrome browser.
265
266### lcov Report
267
268If the argument `--format=lcov` is used in the `llvm-cov export` command, it
269generates a report in lcov format.
270
271In the lcov file, the meaning of these keywords are listed below.
272
273* `SF`: source file name (typically beginning of one record)
274* `FN`: mangled function symbol
275* `FNDA`: functions execution
276* `FNF`: functions found
277* `FNH`: functions hit
278* `DA`: lines executed
279* `BRH`: branches hit
280* `BRF`: branches found
281* `LH`: lines hit
282* `LF`: lines found
283* `end_of_record` end of one record
284
285The number right after `FN` indicates the starting line number of this function.
286The number right after `FNDA` indicates the total number of execution of this
287function.
288
289In the following example record, it means that function `_ZN4apps18AppLifetimeMonitorC2EPN7content14BrowserContextE` is defined at line
29021 in file `app_lifetime_monitor.cc` and it is executed once.
291
292```
293SF:../../chromium/src/apps/app_lifetime_monitor.cc
294FN:21,_ZN4apps18AppLifetimeMonitorC2EPN7content14BrowserContextE
295FN:32,_ZN4apps18AppLifetimeMonitorD2Ev
296FNDA:1,_ZN4apps18AppLifetimeMonitorC2EPN7content14BrowserContextE
297FNF:7
298FNH:1
299DA:34,0
300BRF:0
301BRH:0
302LF:5
303LH:1
304end_of_record
305```
306
Max Morozd73e45f2018-04-24 18:32:47307## Contacts
308
309### Reporting problems
Yuke Liaod3b46272018-03-14 18:25:14310For any breakage report and feature requests, please [file a bug].
311
Max Morozd73e45f2018-04-24 18:32:47312### Mailing list
Yuke Liaobc35726b2018-10-31 22:16:21313For questions and general discussions, please join [code-coverage group].
Yuke Liao1ffc8cb62018-04-06 19:09:07314
Max Morozd73e45f2018-04-24 18:32:47315## FAQ
316
317### Can I use `is_component_build=true` for code coverage build?
318
319Yes, code coverage instrumentation works with both component and non-component
320builds. Component build is usually faster to compile, but can be up to several
321times slower to run with code coverage instrumentation. For more information,
Max Morozc5e364a2018-04-25 23:19:49322see [crbug.com/831939].
323
324### I am getting some warnings while using the script, is that fine?
325
Abhishek Aryaaf9811f22018-05-11 22:17:48326Usually this is not a critical issue, but in general we tend not to have any
Max Morozc5e364a2018-04-25 23:19:49327warnings. Please check the list of [known issues], and if there is a similar
328bug, leave a comment with the command you run, the output you get, and Chromium
Yuke Liao03c644072019-07-30 18:33:40329revision you use. Otherwise, please [file a bug] providing the same information.
Max Morozc5e364a2018-04-25 23:19:49330
331### How do crashes affect code coverage?
332
Max Moroza5a95272018-08-31 16:20:55333If a crash of any type occurs (e.g. Segmentation Fault or ASan error), the
334crashing process might not dump coverage information necessary to generate
Max Morozc5e364a2018-04-25 23:19:49335code coverage report. For single-process applications (e.g. fuzz targets), that
Max Moroza5a95272018-08-31 16:20:55336means no coverage might be reported at all. For multi-process applications, the
337report might be incomplete. It is important to fix the crash first. If this is
Abhishek Aryaaf9811f22018-05-11 22:17:48338happening only in the coverage instrumented build, please [file a bug].
Max Morozd73e45f2018-04-24 18:32:47339
Max Moroza5a95272018-08-31 16:20:55340### How do assertions affect code coverage?
341
342If a crash is caused by CHECK or DCHECK, the coverage dump will still be written
343on the disk ([crrev.com/c/1172932]). However, if a crashing process calls the
344standard [assert] directly or through a custom wrapper, the dump will not be
345written (see [How do crashes affect code coverage?]).
346
Max Moroz63cd04d2018-05-02 16:40:23347### Is it possible to obtain code coverage from a full Chromium build?
348
349Yes, with some important caveats. It is possible to build `chrome` target with
350code coverage instrumentation enabled. However, there are some inconveniences
351involved:
352
Kai Ninomiya6f537eb2023-01-04 23:43:47353* Linking may take a while, especially if you use a non-component build.
354* The binary is huge (2-4GB).
355* The browser may be noticeably slow and laggy.
Max Moroz63cd04d2018-05-02 16:40:23356
357For more information, please see [crbug.com/834781].
358
Max Moroz3a928902018-05-15 14:39:50359### Why do we see significantly different coverage reported on different revisions?
360
361There can be two possible scenarios:
362
363* It can be a one time flakiness due to a broken build or failing tests.
364* It can be caused by extension of the test suite used for generating code
365coverage reports. When we add new tests to the suite, the aggregate coverage
366reported usually grows after that.
367
368### How can I improve [coverage dashboard]?
369
Roberto Carrillo3b567862019-01-30 19:01:25370The code for the service and dashboard currently lives along with findit at
John Palmer046f9872021-05-24 01:24:56371[this location](https://chromium.googlesource.com/infra/infra/+/main/appengine/findit/)
Roberto Carrillo3b567862019-01-30 19:01:25372because of significant shared logic.
373
374The code used by the bots that generate the coverage data lives (among other
375places) in the
John Palmer046f9872021-05-24 01:24:56376[code coverage recipe module](https://chromium.googlesource.com/chromium/tools/build/+/main/scripts/slave/recipe_modules/code_coverage/).
Roberto Carrillo3b567862019-01-30 19:01:25377
Max Moroz3a928902018-05-15 14:39:50378### Why is coverage for X not reported or unreasonably low, even though there is a test for X?
379
380There are several reasons why coverage reports can be incomplete or incorrect:
381
382* A particular test is not used for code coverage report generation. Please
Roberto Carrillo5221fc12019-01-30 21:34:50383[file a bug].
Roberto Carrillo3b567862019-01-30 19:01:25384* A test may have a build failure or a runtime crash. Please check the build
385for that particular report (rightmost column on the [coverage dashboard]).
Max Moroz3a928902018-05-15 14:39:50386If there is any failure, please upload a CL with the fix. If you can't fix it,
387feel free to [file a bug].
388* A particular test may not be available on a particular platform. As of now,
Yuke Liao43bbbcd52019-06-21 19:34:50389only reports generated on Linux and CrOS are available on the
390[coverage dashboard].
Max Moroz3a928902018-05-15 14:39:50391
Max Moroz3a928902018-05-15 14:39:50392### Is coverage reported for the code executed inside the sandbox?
393
Yuke Liao8c0868fe62019-10-22 21:02:33394Yes!
Max Moroz3a928902018-05-15 14:39:50395
Max Morozd73e45f2018-04-24 18:32:47396
Max Moroza5a95272018-08-31 16:20:55397[assert]: http://man7.org/linux/man-pages/man3/assert.3.html
Yuke Liaobc35726b2018-10-31 22:16:21398[code-coverage group]: https://groups.google.com/a/chromium.org/forum/#!forum/code-coverage
Max Moroz3a928902018-05-15 14:39:50399[code-coverage repository]: https://chrome-internal.googlesource.com/chrome/tools/code-coverage
Prakhar74514ba2022-05-19 17:14:04400[coverage dashboard]: https://analysis.chromium.org/coverage/p/chromium
Yuke Liao1ffc8cb62018-04-06 19:09:07401[coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py
Roberto Carrillo3b567862019-01-30 19:01:25402[coverage infra diagram]: images/code_coverage_infra_diagram.png
403[coverage dashboard file view]: images/code_coverage_dashboard_file_view.png
404[coverage dashboard component view]: images/code_coverage_dashboard_component_view.png
405[coverage dashboard directory view]: images/code_coverage_dashboard_directory_view.png
Yuke Liao43bbbcd52019-06-21 19:34:50406[coverage dashboard link to previous reports]: images/code_coverage_dashboard_link_to_previous_reports.png
407[coverage dashboard previous reports]: images/code_coverage_dashboard_previous_reports.png
Max Moroz3a928902018-05-15 14:39:50408[crbug.com/821617]: https://crbug.com/821617
Max Morozc5e364a2018-04-25 23:19:49409[crbug.com/831939]: https://crbug.com/831939
Max Moroz63cd04d2018-05-02 16:40:23410[crbug.com/834781]: https://crbug.com/834781
Max Moroza5a95272018-08-31 16:20:55411[crrev.com/c/1172932]: https://crrev.com/c/1172932
Max Moroz3a928902018-05-15 14:39:50412[clang roll]: https://crbug.com/841908
Abhishek Aryab23b1a72018-05-17 20:11:09413[dead code example]: https://chromium.googlesource.com/chromium/src/+/ac6e09311fcc7e734be2ef21a9ccbbe04c4c4706
Max Morozc5e364a2018-04-25 23:19:49414[documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
Yuke Liao03c644072019-07-30 18:33:40415[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ETest%3ECodeCoverage
Yuke Liao43bbbcd52019-06-21 19:34:50416[gerrit coverage view]: images/code_coverage_annotations.png
Max Morozc5e364a2018-04-25 23:19:49417[guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
Max Moroza5a95272018-08-31 16:20:55418[How do crashes affect code coverage?]: #how-do-crashes-affect-code-coverage
Yuke Liao03c644072019-07-30 18:33:40419[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Infra%3ETest%3ECodeCoverage
Roberto Carrillo3b567862019-01-30 19:01:25420[tools link]: https://storage.googleapis.com/chromium-browser-clang-staging/
Prakharf41864b02022-07-18 19:03:51421[android code coverage instructions]: https://chromium.googlesource.com/chromium/src/+/HEAD/build/android/docs/coverage.md