blob: 50eb72ae67837c8891b763325df9b0ff579b9e88 [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
Abhishek Aryaaf9811f22018-05-11 22:17:4814Chromium uses Clang source-based code coverage. This [documentation] explains
Yuke Liao1ffc8cb62018-04-06 19:09:0715how to use Clangs source-based coverage features in general.
Yuke Liaod3b46272018-03-14 18:25:1416
Abhishek Aryaaf9811f22018-05-11 22:17:4817In this document, we first introduce a code coverage script that can be used to
18generate code coverage reports for Chromium code in one command, and then
19describe 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
Abhishek Aryaaf9811f22018-05-11 22:17:4840runs them individually with their commands and arguments specified by the `-c` flag.
41For `url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report
Yuke Liao1ffc8cb62018-04-06 19:09:0742is filtered to include only files and sub-directories under `url/` and `crypto/`
43directories.
44
Abhishek Aryaaf9811f22018-05-11 22:17:4845Aside from automating the process, this script provides visualization features to
Yuke Liao1ffc8cb62018-04-06 19:09:0746view code coverage breakdown by directories and by components, for example:
47
Abhishek Aryaaf9811f22018-05-11 22:17:4848### Directory View
Yuke Liao1ffc8cb62018-04-06 19:09:0749
50![code coverage report directory view]
51
Abhishek Aryaaf9811f22018-05-11 22:17:4852### Component View
Yuke Liao1ffc8cb62018-04-06 19:09:0753
54![code coverage report component view]
55
Abhishek Aryaaf9811f22018-05-11 22:17:4856### Source View
57
58When you click on a particular source file in one of the views above, you can check
59per-line coverage information such as
60
61- Uncovered / Covered line fragments, lines and code blocks. This information can be
62useful to identify areas of code that lack test coverage.
63- Per-line hit counts indicating how many times this line was hit by all tested targets.
64This information can be useful to determine hot spots in your code.
65
66![code coverage source view]
67
Yuke Liao1ffc8cb62018-04-06 19:09:0768## Workflow
69This section presents the workflow of generating code coverage reports using two
70unit test targets in Chromium repo as an example: `crypto_unittests` and
71`url_unittests`, and the following diagram shows a step-by-step overview of the
72process.
73
74![code coverage generation workflow](images/code_coverage_workflow.png)
75
76### Step 0 Download Tooling
77Generating code coverage reports requires llvm-profdata and llvm-cov tools.
78Currently, these two tools are not part of Chromiums Clang bundle,
79[coverage script] downloads and updates them automatically, you can also
80download the tools manually ([link]).
81
82### Step 1 Build
83In Chromium, to compile code with coverage enabled, one needs to add
84`use_clang_coverage=true` and `is_component_build=false` GN flags to the args.gn
85file in the build output directory. Under the hood, they ensure
86`-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to the
87compiler.
88
89```
90$ gn gen out/coverage \
91 --args='use_clang_coverage=true is_component_build=false'
92$ gclient runhooks
93$ ninja -C out/coverage crypto_unittests url_unittests
Yuke Liaod3b46272018-03-14 18:25:1494```
95
Yuke Liao1ffc8cb62018-04-06 19:09:0796### Step 2 Create Raw Profiles
Abhishek Aryaaf9811f22018-05-11 22:17:4897The next step is to run the instrumented binaries. When the program exits, it
98writes a raw profile for each process. Because Chromium runs tests in
99multiple processes, the number of processes spawned can be as many as a few
100hundred, resulting in the generation of a few hundred gigabytes raw
101profiles. To limit the number of raw profiles, `%Nm` pattern in
Yuke Liao1ffc8cb62018-04-06 19:09:07102`LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process
103mode, where `N` is the number of raw profiles. With `N = 4`, the total size of
104the raw profiles are limited to a few gigabytes.
105
106```
107$ export LLVM_PROFILE_FILE=”out/report/crypto_unittests.%4m.profraw”
108$ ./out/coverage/crypto_unittests
109$ ls out/report/
110crypto_unittests.3657994905831792357_0.profraw
111...
112crypto_unittests.3657994905831792357_3.profraw
113```
114
115### Step 3 Create Indexed Profile
116Raw profiles must be indexed before generating code coverage reports, and this
117is done using the `merge` command of `llvm-profdata` tool, which merges multiple
Abhishek Aryaaf9811f22018-05-11 22:17:48118raw profiles (.profraw) and indexes them to create a single profile (.profdata).
Yuke Liao1ffc8cb62018-04-06 19:09:07119
120At this point, all the raw profiles can be thrown away because their information
Abhishek Aryaaf9811f22018-05-11 22:17:48121is already contained in the indexed profile.
Yuke Liao1ffc8cb62018-04-06 19:09:07122
123```
124$ llvm-profdata merge -o out/report/coverage.profdata \
125 out/report/crypto_unittests.3657994905831792357_0.profraw
126...
127out/report/crypto_unittests.3657994905831792357_3.profraw
128out/report/url_unittests.714228855822523802_0.profraw
129...
130out/report/url_unittests.714228855822523802_3.profraw
131$ ls out/report/coverage.profdata
132out/report/coverage.profdata
133```
134
135### Step 4 Create Coverage Reports
136Finally, `llvm-cov` is used to render code coverage reports. There are different
Abhishek Aryaaf9811f22018-05-11 22:17:48137report generation modes, and all of them require the following as input:
138- Indexed profile
139- All built target binaries
140- All exercised source files.
Yuke Liao1ffc8cb62018-04-06 19:09:07141
Abhishek Aryaaf9811f22018-05-11 22:17:48142For example, the following command can be used to generate per-file line-by-line
Yuke Liao1ffc8cb62018-04-06 19:09:07143code coverage report:
144
145```
146$ llvm-cov show -output-dir=out/report -format=html \
147 -instr-profile=out/report/coverage.profdata \
148 -object=out/coverage/url_unittests \
149 out/coverage/crypto_unittests
150```
151
152For more information on how to use llvm-cov, please refer to the [guide].
Yuke Liaod3b46272018-03-14 18:25:14153
Max Morozd73e45f2018-04-24 18:32:47154## Contacts
155
156### Reporting problems
Yuke Liaod3b46272018-03-14 18:25:14157For any breakage report and feature requests, please [file a bug].
158
Max Morozd73e45f2018-04-24 18:32:47159### Mailing list
Yuke Liao1ffc8cb62018-04-06 19:09:07160For questions and general discussions, please join [chrome-code-coverage group].
161
Max Morozd73e45f2018-04-24 18:32:47162## FAQ
163
164### Can I use `is_component_build=true` for code coverage build?
165
166Yes, code coverage instrumentation works with both component and non-component
167builds. Component build is usually faster to compile, but can be up to several
168times slower to run with code coverage instrumentation. For more information,
Max Morozc5e364a2018-04-25 23:19:49169see [crbug.com/831939].
170
171### I am getting some warnings while using the script, is that fine?
172
Abhishek Aryaaf9811f22018-05-11 22:17:48173Usually this is not a critical issue, but in general we tend not to have any
Max Morozc5e364a2018-04-25 23:19:49174warnings. Please check the list of [known issues], and if there is a similar
175bug, leave a comment with the command you run, the output you get, and Chromium
176revision you use. Otherwise, please [file a new issue] providing the same
177information.
178
179### How do crashes affect code coverage?
180
181If a crash of any type occurs (Segmentation Fault, CHECK failure, ASan error),
182the crashing process will not dump coverage information necessary to generate
183code coverage report. For single-process applications (e.g. fuzz targets), that
184means no coverage will be reported at all. For multi-process applications, the
Abhishek Aryaaf9811f22018-05-11 22:17:48185report will be incomplete. It is important to fix the crash first. If this is
186happening only in the coverage instrumented build, please [file a bug].
Max Morozd73e45f2018-04-24 18:32:47187
Max Moroz63cd04d2018-05-02 16:40:23188### Is it possible to obtain code coverage from a full Chromium build?
189
190Yes, with some important caveats. It is possible to build `chrome` target with
191code coverage instrumentation enabled. However, there are some inconveniences
192involved:
193
194* Linking may take a while
195* The binary is huge (~4GB)
196* The browser "works", but is noticeably slow and laggy
197* The sandbox needs to be disabled (`--no-sandbox`)
198* Coverage can be incomplete for child processes
199
200For more information, please see [crbug.com/834781].
201
Max Morozd73e45f2018-04-24 18:32:47202
Max Morozc5e364a2018-04-25 23:19:49203[chrome-code-coverage group]: https://groups.google.com/a/google.com/forum/#!forum/chrome-code-coverage
Yuke Liao1ffc8cb62018-04-06 19:09:07204[coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py
205[code coverage report directory view]: images/code_coverage_directory_view.png
206[code coverage report component view]: images/code_coverage_component_view.png
Abhishek Aryaaf9811f22018-05-11 22:17:48207[code coverage source view]: images/code_coverage_source_view.png
Max Morozc5e364a2018-04-25 23:19:49208[crbug.com/831939]: https://crbug.com/831939
Max Moroz63cd04d2018-05-02 16:40:23209[crbug.com/834781]: https://crbug.com/834781
Max Morozc5e364a2018-04-25 23:19:49210[documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
Yuke Liao1ffc8cb62018-04-06 19:09:07211[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
Max Morozc5e364a2018-04-25 23:19:49212[file a new issue]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
213[guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
214[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Tools%3ECodeCoverage
215[link]: https://storage.googleapis.com/chromium-browser-clang-staging/