|  | # Code Coverage in Chromium | 
|  |  | 
|  | ### Coverage Dashboard: [link](https://analysis.chromium.org/p/chromium/coverage) | 
|  |  | 
|  | Table of contents: | 
|  |  | 
|  | - [Coverage Infrastructure](#coverage-infra) | 
|  | * [Coverage Builders](#coverage-builders) | 
|  | * [Coverage Service](#coverage-service) | 
|  | * [Coverage Clients](#coverage-clients) | 
|  | - [Local Coverage Script](#local-coverage-script) | 
|  | * [Step 0 Download Tooling](#step-0-download-tooling) | 
|  | * [Step 1 Build](#step-1-build) | 
|  | * [Step 2 Create Raw Profiles](#step-2-create-raw-profiles) | 
|  | * [Step 3 Create Indexed Profile](#step-3-create-indexed-profile) | 
|  | * [Step 4 Create Coverage Reports](#step-4-create-coverage-reports) | 
|  | - [Contacts](#contacts) | 
|  | - [FAQ](#faq) | 
|  |  | 
|  | Chromium uses source-based code coverage for clang-compiled languages such as | 
|  | C++. This [documentation] explains how to use Clang’s source-based coverage | 
|  | features in general. | 
|  |  | 
|  | In this document, we first introduce the code coverage infrastructure that | 
|  | continuously generates code coverage information for the whole codebase and for | 
|  | specific CLs in Gerrit. For the latter, refer to | 
|  | [code\_coverage\_in\_gerrit.md](code_coverage_in_gerrit.md). | 
|  | We then present a script that can be used to locally generate code coverage | 
|  | reports with one command, and finally we provide a description of the | 
|  | process of producing these reports. | 
|  |  | 
|  | ## Coverage Infrastructure | 
|  |  | 
|  | ![coverage infra diagram] | 
|  |  | 
|  | There are 3 layers in the system: | 
|  |  | 
|  | ### Coverage Builders | 
|  |  | 
|  | The first layer is the LUCI builders that | 
|  | - build instrumented targets, | 
|  | - run the instrumented tests, | 
|  | - merge the results into single streams, | 
|  | - upload data to cloud storage. | 
|  |  | 
|  | There are two types of builder: | 
|  |  | 
|  | CI Builder | 
|  |  | 
|  | The code coverage CI Builders periodically build all the test targets and fuzzer | 
|  | targets for a given platform and instrument all available source files. Then | 
|  | save the coverage data to a dedicated storage bucket. | 
|  |  | 
|  | CQ Builder | 
|  |  | 
|  | The code coverage CQ builders instrument only the files changed for a given CL. | 
|  | More information about per-cl coverage info in [this | 
|  | doc](code_coverage_in_gerrit.md). | 
|  |  | 
|  | ### Coverage Service | 
|  |  | 
|  | The second layer in the system consists of an AppEngine application that | 
|  | consumes the coverage data from the builders above, structures it and stores it | 
|  | in cloud datastore. It then serves the information to the clients below. | 
|  |  | 
|  | ### Coverage Clients | 
|  |  | 
|  | In the last layer we currently have two clients that consume the service: | 
|  |  | 
|  | #### Coverage Dashboard | 
|  |  | 
|  | The [coverage dashboard] front end is hosted in the same application as the | 
|  | service above. | 
|  | It shows the full-code coverage reports with links to the builds that generated | 
|  | them, as well as per-directory and per-component aggregation, and can be drilled | 
|  | down to the single line of code level of detail. | 
|  |  | 
|  | Refer to the following screenshots: | 
|  |  | 
|  | ##### Directory View | 
|  |  | 
|  | See coverage breakdown by directories (default landing page). | 
|  |  | 
|  | ![coverage dashboard directory view] | 
|  |  | 
|  | ##### Component View | 
|  |  | 
|  | Use the view dropdown menu to switch between directory and component. | 
|  |  | 
|  | ![coverage dashboard component view] | 
|  |  | 
|  | ##### Source View | 
|  |  | 
|  | Click on a particular source file in one of the views above to see line-by-line | 
|  | coverage breakdown, and it's useful to identify: | 
|  | - Uncovered lines and code blocks that lack test coverage. | 
|  | - Potentially dead code. See [dead code example]. | 
|  | - Hot spots in your code. | 
|  |  | 
|  | ![coverage dashboard file view] | 
|  |  | 
|  | ##### Project View | 
|  |  | 
|  | Click on "Previous Reports" to check out the coverage history of the project. | 
|  |  | 
|  | ![coverage dashboard link to previous reports] | 
|  |  | 
|  | List of historical coverage reports are in reverse chronological order. | 
|  |  | 
|  | ![coverage dashboard previous reports] | 
|  |  | 
|  | #### Gerrit Coverage View | 
|  |  | 
|  | The other client supported at the moment is the gerrit plugin for code coverage. | 
|  |  | 
|  | ![gerrit coverage view] | 
|  |  | 
|  | See [this doc](code_coverage_in_gerrit.md) for information about the feature | 
|  | that allows gerrit to display code coverage information generated for a given CL | 
|  | by CQ bot. Or see this | 
|  | [15-second video tutorial](https://www.youtube.com/watch?v=cxXlYcSgIPE). | 
|  |  | 
|  | ## Local Coverage Script | 
|  | The [coverage script] automates the process described below and provides a | 
|  | one-stop service to generate code coverage reports locally in just one command. | 
|  |  | 
|  | This script is currently supported on Linux, Mac, iOS and ChromeOS platforms. | 
|  |  | 
|  | Here is an example usage: | 
|  |  | 
|  | ``` | 
|  | $ gn gen out/coverage \ | 
|  | --args='use_clang_coverage=true is_component_build=false dcheck_always_on=true' | 
|  | $ python tools/code_coverage/coverage.py \ | 
|  | crypto_unittests url_unittests \ | 
|  | -b out/coverage -o out/report \ | 
|  | -c 'out/coverage/crypto_unittests' \ | 
|  | -c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \ | 
|  | -f url/ -f crypto/ | 
|  | ``` | 
|  | The command above builds `crypto_unittests` and `url_unittests` targets and then | 
|  | runs them individually with their commands and arguments specified by the `-c` flag. | 
|  | For `url_unittests`, it only runs the test `URLParser.PathURL`. The coverage report | 
|  | is filtered to include only files and sub-directories under `url/` and `crypto/` | 
|  | directories. | 
|  |  | 
|  | Aside from automating the process, this script provides visualization features to | 
|  | view code coverage breakdown by directories and by components, similar to the | 
|  | views in the [coverage dashboard](#coverage-dashboard) above. | 
|  |  | 
|  | ## Workflow | 
|  | This section presents the workflow of generating code coverage reports using two | 
|  | unit test targets in Chromium repo as an example: `crypto_unittests` and | 
|  | `url_unittests`, and the following diagram shows a step-by-step overview of the | 
|  | process. | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Step 0 Download Tooling | 
|  | Generating code coverage reports requires llvm-profdata and llvm-cov tools. | 
|  | Currently, these two tools are not part of Chromium’s Clang bundle, | 
|  | [coverage script] downloads and updates them automatically, you can also | 
|  | download the tools manually ([tools link]). | 
|  |  | 
|  | ### Step 1 Build | 
|  | In Chromium, to compile code with coverage enabled, one needs to add | 
|  | `use_clang_coverage=true` and `is_component_build=false` GN flags to the args.gn | 
|  | file in the build output directory. Under the hood, they ensure | 
|  | `-fprofile-instr-generate` and `-fcoverage-mapping` flags are passed to the | 
|  | compiler. | 
|  |  | 
|  | ``` | 
|  | $ gn gen out/coverage \ | 
|  | --args='use_clang_coverage=true is_component_build=false' | 
|  | $ gclient runhooks | 
|  | $ autoninja -C out/coverage crypto_unittests url_unittests | 
|  | ``` | 
|  |  | 
|  | ### Step 2 Create Raw Profiles | 
|  | The next step is to run the instrumented binaries. When the program exits, it | 
|  | writes a raw profile for each process. Because Chromium runs tests in | 
|  | multiple processes, the number of processes spawned can be as many as a few | 
|  | hundred, resulting in the generation of a few hundred gigabytes’ raw | 
|  | profiles. To limit the number of raw profiles, `%Nm` pattern in | 
|  | `LLVM_PROFILE_FILE` environment variable is used to run tests in multi-process | 
|  | mode, where `N` is the number of raw profiles. With `N = 4`, the total size of | 
|  | the raw profiles are limited to a few gigabytes. | 
|  |  | 
|  | ``` | 
|  | $ export LLVM_PROFILE_FILE=”out/report/crypto_unittests.%4m.profraw” | 
|  | $ ./out/coverage/crypto_unittests | 
|  | $ ls out/report/ | 
|  | crypto_unittests.3657994905831792357_0.profraw | 
|  | ... | 
|  | crypto_unittests.3657994905831792357_3.profraw | 
|  | ``` | 
|  |  | 
|  | ### Step 3 Create Indexed Profile | 
|  | Raw profiles must be indexed before generating code coverage reports, and this | 
|  | is done using the `merge` command of `llvm-profdata` tool, which merges multiple | 
|  | raw profiles (.profraw) and indexes them to create a single profile (.profdata). | 
|  |  | 
|  | At this point, all the raw profiles can be thrown away because their information | 
|  | is already contained in the indexed profile. | 
|  |  | 
|  | ``` | 
|  | $ llvm-profdata merge -o out/report/coverage.profdata \ | 
|  | out/report/crypto_unittests.3657994905831792357_0.profraw | 
|  | ... | 
|  | out/report/crypto_unittests.3657994905831792357_3.profraw | 
|  | out/report/url_unittests.714228855822523802_0.profraw | 
|  | ... | 
|  | out/report/url_unittests.714228855822523802_3.profraw | 
|  | $ ls out/report/coverage.profdata | 
|  | out/report/coverage.profdata | 
|  | ``` | 
|  |  | 
|  | ### Step 4 Create Coverage Reports | 
|  | Finally, `llvm-cov` is used to render code coverage reports. There are different | 
|  | report generation modes, and all of them require the following as input: | 
|  | - Indexed profile | 
|  | - All built target binaries | 
|  | - All exercised source files | 
|  |  | 
|  | For example, the following command can be used to generate per-file line-by-line | 
|  | code coverage report: | 
|  |  | 
|  | ``` | 
|  | $ llvm-cov show -output-dir=out/report -format=html \ | 
|  | -instr-profile=out/report/coverage.profdata \ | 
|  | -object=out/coverage/url_unittests \ | 
|  | out/coverage/crypto_unittests | 
|  | ``` | 
|  |  | 
|  | For more information on how to use llvm-cov, please refer to the [guide]. | 
|  |  | 
|  | ## Contacts | 
|  |  | 
|  | ### Reporting problems | 
|  | For any breakage report and feature requests, please [file a bug]. | 
|  |  | 
|  | ### Mailing list | 
|  | For questions and general discussions, please join [code-coverage group]. | 
|  |  | 
|  | ## FAQ | 
|  |  | 
|  | ### Can I use `is_component_build=true` for code coverage build? | 
|  |  | 
|  | Yes, code coverage instrumentation works with both component and non-component | 
|  | builds. Component build is usually faster to compile, but can be up to several | 
|  | times slower to run with code coverage instrumentation. For more information, | 
|  | see [crbug.com/831939]. | 
|  |  | 
|  | ### I am getting some warnings while using the script, is that fine? | 
|  |  | 
|  | Usually this is not a critical issue, but in general we tend not to have any | 
|  | warnings. Please check the list of [known issues], and if there is a similar | 
|  | bug, leave a comment with the command you run, the output you get, and Chromium | 
|  | revision you use. Otherwise, please [file a new issue] providing the same | 
|  | information. | 
|  |  | 
|  | ### How do crashes affect code coverage? | 
|  |  | 
|  | If a crash of any type occurs (e.g. Segmentation Fault or ASan error), the | 
|  | crashing process might not dump coverage information necessary to generate | 
|  | code coverage report. For single-process applications (e.g. fuzz targets), that | 
|  | means no coverage might be reported at all. For multi-process applications, the | 
|  | report might be incomplete. It is important to fix the crash first. If this is | 
|  | happening only in the coverage instrumented build, please [file a bug]. | 
|  |  | 
|  | ### How do assertions affect code coverage? | 
|  |  | 
|  | If a crash is caused by CHECK or DCHECK, the coverage dump will still be written | 
|  | on the disk ([crrev.com/c/1172932]). However, if a crashing process calls the | 
|  | standard [assert] directly or through a custom wrapper, the dump will not be | 
|  | written (see [How do crashes affect code coverage?]). | 
|  |  | 
|  | ### Is it possible to obtain code coverage from a full Chromium build? | 
|  |  | 
|  | Yes, with some important caveats. It is possible to build `chrome` target with | 
|  | code coverage instrumentation enabled. However, there are some inconveniences | 
|  | involved: | 
|  |  | 
|  | * Linking may take a while | 
|  | * The binary is huge (~4GB) | 
|  | * The browser "works", but is noticeably slow and laggy | 
|  | * The sandbox needs to be disabled (`--no-sandbox`) | 
|  |  | 
|  | For more information, please see [crbug.com/834781]. | 
|  |  | 
|  | ### Why do we see significantly different coverage reported on different revisions? | 
|  |  | 
|  | There can be two possible scenarios: | 
|  |  | 
|  | * It can be a one time flakiness due to a broken build or failing tests. | 
|  | * It can be caused by extension of the test suite used for generating code | 
|  | coverage reports. When we add new tests to the suite, the aggregate coverage | 
|  | reported usually grows after that. | 
|  |  | 
|  | ### How can I improve [coverage dashboard]? | 
|  |  | 
|  | The code for the service and dashboard currently lives along with findit at | 
|  | [this location](https://chromium.googlesource.com/infra/infra/+/master/appengine/findit/) | 
|  | because of significant shared logic. | 
|  |  | 
|  | The code used by the bots that generate the coverage data lives (among other | 
|  | places) in the | 
|  | [code coverage recipe module](https://chromium.googlesource.com/chromium/tools/build/+/master/scripts/slave/recipe_modules/code_coverage/). | 
|  |  | 
|  | ### Why is coverage for X not reported or unreasonably low, even though there is a test for X? | 
|  |  | 
|  | There are several reasons why coverage reports can be incomplete or incorrect: | 
|  |  | 
|  | * A particular test is not used for code coverage report generation. Please | 
|  | [file a bug]. | 
|  | * A test may have a build failure or a runtime crash. Please check the build | 
|  | for that particular report (rightmost column on the [coverage dashboard]). | 
|  | If there is any failure, please upload a CL with the fix. If you can't fix it, | 
|  | feel free to [file a bug]. | 
|  | * A particular test may not be available on a particular platform. As of now, | 
|  | only reports generated on Linux and CrOS are available on the | 
|  | [coverage dashboard]. | 
|  |  | 
|  | ### Is coverage reported for the code executed inside the sandbox? | 
|  |  | 
|  | Not at the moment until [crbug.com/842424] is resolved. We do not disable the | 
|  | sandbox when running the tests. However, if there are any other non-sandbox'ed | 
|  | tests for the same code, the coverage should be reported from those. For more | 
|  | information, see [crbug.com/842424]. | 
|  |  | 
|  |  | 
|  | [assert]: http://man7.org/linux/man-pages/man3/assert.3.html | 
|  | [code-coverage group]: https://groups.google.com/a/chromium.org/forum/#!forum/code-coverage | 
|  | [code-coverage repository]: https://chrome-internal.googlesource.com/chrome/tools/code-coverage | 
|  | [coverage dashboard]: https://analysis.chromium.org/p/chromium/coverage | 
|  | [coverage script]: https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py | 
|  | [coverage infra diagram]: images/code_coverage_infra_diagram.png | 
|  | [coverage dashboard file view]: images/code_coverage_dashboard_file_view.png | 
|  | [coverage dashboard component view]: images/code_coverage_dashboard_component_view.png | 
|  | [coverage dashboard directory view]: images/code_coverage_dashboard_directory_view.png | 
|  | [coverage dashboard link to previous reports]: images/code_coverage_dashboard_link_to_previous_reports.png | 
|  | [coverage dashboard previous reports]: images/code_coverage_dashboard_previous_reports.png | 
|  | [crbug.com/821617]: https://crbug.com/821617 | 
|  | [crbug.com/831939]: https://crbug.com/831939 | 
|  | [crbug.com/834781]: https://crbug.com/834781 | 
|  | [crbug.com/842424]: https://crbug.com/842424 | 
|  | [crrev.com/c/1172932]: https://crrev.com/c/1172932 | 
|  | [clang roll]: https://crbug.com/841908 | 
|  | [dead code example]: https://chromium.googlesource.com/chromium/src/+/ac6e09311fcc7e734be2ef21a9ccbbe04c4c4706 | 
|  | [documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html | 
|  | [file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage | 
|  | [file a new issue]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage | 
|  | [gerrit coverage view]: images/code_coverage_annotations.png | 
|  | [guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html | 
|  | [How do crashes affect code coverage?]: #how-do-crashes-affect-code-coverage | 
|  | [known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Tools%3ECodeCoverage | 
|  | [tools link]: https://storage.googleapis.com/chromium-browser-clang-staging/ | 
|  | [test suite]: https://cs.chromium.org/chromium/src/tools/code_coverage/test_suite.txt |