Skip to content

Commit

Permalink
[llvm-cov] Add an option for "export" command to emit only file summa…
Browse files Browse the repository at this point in the history
…ry data.

Summary:
That allows to get the same data as produced by "llvm-cov report",
but in JSON format, which is better for further processing by end users.

Reviewers: vsk

Reviewed By: vsk

Differential Revision: https://reviews.llvm.org/D41085

llvm-svn: 320435
  • Loading branch information
Dor1s committed Dec 11, 2017
1 parent b59ceb1 commit fe4d904
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 40 deletions.
7 changes: 7 additions & 0 deletions llvm/docs/CommandGuide/llvm-cov.rst
Expand Up @@ -382,3 +382,10 @@ OPTIONS
It is an error to specify an architecture that is not included in the
universal binary or to use an architecture that does not match a
non-universal binary.

.. option:: -summary-only

Export only summary information for each file in the coverage data. This mode
will not export coverage information for smaller units such as individual
functions or regions. The result will be the same as produced by :program:
`llvm-cov report` command, but presented in JSON format rather than text.
51 changes: 27 additions & 24 deletions llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
Expand Up @@ -39,36 +39,39 @@ int main() { // TEXT: [[@LINE]]| 161|int main(
// RUN: FileCheck -input-file %t.export.json %S/Inputs/lineExecutionCounts.json
// RUN: cat %t.export.json | %python -c "import json, sys; json.loads(sys.stdin.read())"
//
// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
// RUN: not grep '"name":"main"' %t.export-summary.json
//
// Test html output.
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
//
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-45]]' href='#L[[@LINE-45]]'><pre>[[@LINE-45]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> int x = 0
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> if (x)
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre><span class='red'> }</span>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.2k</pre></td><td class='code'><pre> for (int i = 0; i &lt; 100; ++i)
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &lt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &gt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre> <span class='red'>x - 1</span>:
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x + 1;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> return 0;
// HTML: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>}
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-44]]' href='#L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-45]]' href='#L[[@LINE-45]]'><pre>[[@LINE-45]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-48]]' href='#L[[@LINE-48]]'><pre>[[@LINE-48]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// before
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> int x = 0
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> if (x)
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre><span class='red'> }</span>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>16.2k</pre></td><td class='code'><pre> for (int i = 0; i &lt; 100; ++i)
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> x = 1;
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>16.1k</pre></td><td class='code'><pre> }
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &lt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x = x &gt; 10
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre> <span class='red'>x - 1</span>:
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> x + 1;
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre> return 0;
// HTML: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>}
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-47]]' href='#L[[@LINE-47]]'><pre>[[@LINE-47]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-48]]' href='#L[[@LINE-48]]'><pre>[[@LINE-48]]</pre></a></td><td class='uncovered-line'></td><td class='code'><pre>// after
//
// Test index creation.
// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
Expand Down
5 changes: 5 additions & 0 deletions llvm/tools/llvm-cov/CodeCoverage.cpp
Expand Up @@ -631,6 +631,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"show-instantiation-summary", cl::Optional,
cl::desc("Show instantiation statistics in summary table"));

cl::opt<bool> SummaryOnly(
"summary-only", cl::Optional,
cl::desc("Export only summary information for each source file"));

auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
Expand Down Expand Up @@ -743,6 +747,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {

ViewOpts.ShowRegionSummary = RegionSummary;
ViewOpts.ShowInstantiationSummary = InstantiationSummary;
ViewOpts.ExportSummaryOnly = SummaryOnly;

return 0;
};
Expand Down
39 changes: 23 additions & 16 deletions llvm/tools/llvm-cov/CoverageExporterJson.cpp
Expand Up @@ -177,8 +177,11 @@ class CoverageExporterJson {
SourceFiles, Options);
renderFiles(SourceFiles, FileReports);

emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
// Skip functions-level information for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
}

emitDictKey("totals");
renderSummary(Totals);
Expand Down Expand Up @@ -254,27 +257,31 @@ class CoverageExporterJson {
emitDictStart();

emitDictElement("filename", FileCoverage.getFilename());
emitDictKey("segments");

// Start List of Segments.
emitArrayStart();
// Skip segments and expansions for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("segments");

for (const auto &Segment : FileCoverage)
renderSegment(Segment);
// Start List of Segments.
emitArrayStart();

// End List of Segments.
emitArrayEnd();
for (const auto &Segment : FileCoverage)
renderSegment(Segment);

// End List of Segments.
emitArrayEnd();

emitDictKey("expansions");
emitDictKey("expansions");

// Start List of Expansions.
emitArrayStart();
// Start List of Expansions.
emitArrayStart();

for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);
for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);

// End List of Expansions.
emitArrayEnd();
// End List of Expansions.
emitArrayEnd();
}

emitDictKey("summary");
renderSummary(FileReport);
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-cov/CoverageViewOptions.h
Expand Up @@ -32,6 +32,7 @@ struct CoverageViewOptions {
bool ShowFullFilenames;
bool ShowRegionSummary;
bool ShowInstantiationSummary;
bool ExportSummaryOnly;
OutputFormat Format;
std::string ShowOutputDirectory;
std::vector<std::string> DemanglerOpts;
Expand Down

0 comments on commit fe4d904

Please sign in to comment.