blob: 115f52a52be3444904bcfe17fa4b30a5edafccc2 [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)
Max Morozd73e45f2018-04-24 18:32:4711- [Contacts](#contacts)
12- [FAQ](#faq)
Yuke Liaod3b46272018-03-14 18:25:1413
Yuke Liao1ffc8cb62018-04-06 19:09:0714Chromium uses Clang source-based code coverage, this [documentation] explains
15how to use Clangs source-based coverage features in general.
Yuke Liaod3b46272018-03-14 18:25:1416
Yuke Liao1ffc8cb62018-04-06 19:09:0717In this doc, we first introduce a code coverage script that can be used to
18generate code coverage reports for Chromium code in one command, and then dive
19into details to describe the code coverage reports generation workflow.
Yuke Liaod3b46272018-03-14 18:25:1420
Yuke Liao1ffc8cb62018-04-06 19:09:0721## Coverage Script
22The [coverage script] automates the process described below and provides a
23one-stop service to generate code coverage reports in just one command.
Yuke Liaod3b46272018-03-14 18:25:1424
Yuke Liao1ffc8cb62018-04-06 19:09:0725This script is currently supported on Linux, Mac, iOS and ChromeOS platforms.
26
27Here is an example usage:
28
Yuke Liaod3b46272018-03-14 18:25:1429```
Yuke Liao1ffc8cb62018-04-06 19:09:0730$ gn gen out/coverage \
31 --args='use_clang_coverage=true is_component_build=false'
32$ python tools/code_coverage/coverage.py \
33 crypto_unittests url_unittests \
34 -b out/coverage -o out/report \
35 -c 'out/coverage/crypto_unittests' \
36 -c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \
37 -f url/ -f crypto/
38```
39The command above builds `crypto_unittests` and `url_unittests` targets and then
40runs each with the command and arguments specified by the `-c` flag. For
41`url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report
42is filtered to include only files and sub-directories under `url/` and `crypto/`
43directories.
44
45Aside from automating the process, this script provides additional features to
46view code coverage breakdown by directories and by components, for example:
47
48Directory View:
49
50![code coverage report directory view]
51
52Component View:
53
54![code coverage report component view]
55
56## Workflow
57This section presents the workflow of generating code coverage reports using two
58unit test targets in Chromium repo as an example: `crypto_unittests` and
59`url_unittests`, and the following diagram shows a step-by-step overview of the
60process.
61
62![code coverage generation workflow](images/code_coverage_workflow.png)
63
64### Step 0 Download Tooling
65Generating code coverage reports requires llvm-profdata and llvm-cov tools.
66Currently, these two tools are not part of Chromiums Clang bundle,
67[coverage script] downloads and updates them automatically, you can also
68download the tools manually ([link]).
69
70### Step 1 Build
71In Chromium, to compile code with coverage enabled, one needs to add
72`use_clang_coverage=true` and `is_component_build=false` GN flags to the args.gn
73file in the build output directory. Under the hood, they ensure
74`-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to the
75compiler.
76
77```
78$ gn gen out/coverage \
79 --args='use_clang_coverage=true is_component_build=false'
80$ gclient runhooks
81$ ninja -C out/coverage crypto_unittests url_unittests
Yuke Liaod3b46272018-03-14 18:25:1482```
83
Yuke Liao1ffc8cb62018-04-06 19:09:0784### Step 2 Create Raw Profiles
85The next step is to run the instrumented binaries, and when the program exits it
86will write a raw profile for each process. Because Chromium runs tests in
87multiple processes, and the number of processes spawned can be as many as a few
88hundred, which results in the generation of a few hundred gigabytes raw
89profiles, to limit the number of raw profiles, `%Nm` pattern in
90`LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process
91mode, where `N` is the number of raw profiles. With `N = 4`, the total size of
92the raw profiles are limited to a few gigabytes.
93
94```
95$ export LLVM_PROFILE_FILE=”out/report/crypto_unittests.%4m.profraw”
96$ ./out/coverage/crypto_unittests
97$ ls out/report/
98crypto_unittests.3657994905831792357_0.profraw
99...
100crypto_unittests.3657994905831792357_3.profraw
101```
102
103### Step 3 Create Indexed Profile
104Raw profiles must be indexed before generating code coverage reports, and this
105is done using the `merge` command of `llvm-profdata` tool, which merges multiple
106raw profiles (.profraw) and index them to create a single profile (.profdata).
107
108At this point, all the raw profiles can be thrown away because their information
109are already contained in the indexed profile.
110
111```
112$ llvm-profdata merge -o out/report/coverage.profdata \
113 out/report/crypto_unittests.3657994905831792357_0.profraw
114...
115out/report/crypto_unittests.3657994905831792357_3.profraw
116out/report/url_unittests.714228855822523802_0.profraw
117...
118out/report/url_unittests.714228855822523802_3.profraw
119$ ls out/report/coverage.profdata
120out/report/coverage.profdata
121```
122
123### Step 4 Create Coverage Reports
124Finally, `llvm-cov` is used to render code coverage reports. There are different
125report generation modes, and all of them require the indexed profile, all the
126built binaries and all the exercised source files to be available.
127
128For example, following command can be used to generate per-file line-by-line
129code coverage report:
130
131```
132$ llvm-cov show -output-dir=out/report -format=html \
133 -instr-profile=out/report/coverage.profdata \
134 -object=out/coverage/url_unittests \
135 out/coverage/crypto_unittests
136```
137
138For more information on how to use llvm-cov, please refer to the [guide].
Yuke Liaod3b46272018-03-14 18:25:14139
Max Morozd73e45f2018-04-24 18:32:47140## Contacts
141
142### Reporting problems
Yuke Liaod3b46272018-03-14 18:25:14143For any breakage report and feature requests, please [file a bug].
144
Max Morozd73e45f2018-04-24 18:32:47145### Mailing list
Yuke Liao1ffc8cb62018-04-06 19:09:07146For questions and general discussions, please join [chrome-code-coverage group].
147
Max Morozd73e45f2018-04-24 18:32:47148## FAQ
149
150### Can I use `is_component_build=true` for code coverage build?
151
152Yes, code coverage instrumentation works with both component and non-component
153builds. Component build is usually faster to compile, but can be up to several
154times slower to run with code coverage instrumentation. For more information,
Max Morozc5e364a2018-04-25 23:19:49155see [crbug.com/831939].
156
157### I am getting some warnings while using the script, is that fine?
158
159Usually that is not a critical issue, but in general we tend not to have any
160warnings. Please check the list of [known issues], and if there is a similar
161bug, leave a comment with the command you run, the output you get, and Chromium
162revision you use. Otherwise, please [file a new issue] providing the same
163information.
164
165### How do crashes affect code coverage?
166
167If a crash of any type occurs (Segmentation Fault, CHECK failure, ASan error),
168the crashing process will not dump coverage information necessary to generate
169code coverage report. For single-process applications (e.g. fuzz targets), that
170means no coverage will be reported at all. For multi-process applications, the
171report will be incomplete.
Max Morozd73e45f2018-04-24 18:32:47172
Max Moroz63cd04d2018-05-02 16:40:23173### Is it possible to obtain code coverage from a full Chromium build?
174
175Yes, with some important caveats. It is possible to build `chrome` target with
176code coverage instrumentation enabled. However, there are some inconveniences
177involved:
178
179* Linking may take a while
180* The binary is huge (~4GB)
181* The browser "works", but is noticeably slow and laggy
182* The sandbox needs to be disabled (`--no-sandbox`)
183* Coverage can be incomplete for child processes
184
185For more information, please see [crbug.com/834781].
186
Max Morozd73e45f2018-04-24 18:32:47187
Max Morozc5e364a2018-04-25 23:19:49188[chrome-code-coverage group]: https://groups.google.com/a/google.com/forum/#!forum/chrome-code-coverage
Yuke Liao1ffc8cb62018-04-06 19:09:07189[coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py
190[code coverage report directory view]: images/code_coverage_directory_view.png
191[code coverage report component view]: images/code_coverage_component_view.png
Max Morozc5e364a2018-04-25 23:19:49192[crbug.com/831939]: https://crbug.com/831939
Max Moroz63cd04d2018-05-02 16:40:23193[crbug.com/834781]: https://crbug.com/834781
Max Morozc5e364a2018-04-25 23:19:49194[documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
Yuke Liao1ffc8cb62018-04-06 19:09:07195[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
Max Morozc5e364a2018-04-25 23:19:49196[file a new issue]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
197[guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
198[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Tools%3ECodeCoverage
199[link]: https://storage.googleapis.com/chromium-browser-clang-staging/