Skip to content

Commit

Permalink
[llvm-cov] Add the project summary to each source file coverage report.
Browse files Browse the repository at this point in the history
This patch includes the following changes:
- Included header "Code coverage report" and include the date that the report was created.
- Included title (as specified in a command line option, (i.e llvm-cov  -project-title="Simple Test")
- In the summary, list the elf files that the source code file has contributed to.
- Used column heading for "Line No.", "Count No.", Source".

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

llvm-svn: 279628
  • Loading branch information
MaggieYingYi committed Aug 24, 2016
1 parent c22e32d commit 84dc971
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 40 deletions.
Binary file not shown.
10 changes: 10 additions & 0 deletions llvm/test/tools/llvm-cov/Inputs/showProjectSummary.proftext
@@ -0,0 +1,10 @@
main
# Func Hash:
266
# Num Counters:
3
# Counter Values:
1
20
0

46 changes: 46 additions & 0 deletions llvm/test/tools/llvm-cov/showProjectSummary.cpp
@@ -0,0 +1,46 @@
// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/showProjectSummary.proftext

int main(int argc, char ** argv) {
int x=0;
for (int i = 0; i < 20; ++i)
x *= 2;
if (x >= 100)
x = x / 2;
else
x = x * 2;
return x;
}

// Test console output.
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefixes=TEXT,TEXT-FILE,TEXT-HEADER %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s | FileCheck -check-prefixes=TEXT-TITLE,TEXT,TEXT-FILE,TEXT-HEADER %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -instr-profile %t.profdata -project-title "Test Suite" -name=main -filename-equivalence %s | FileCheck -check-prefixes=TEXT-FUNCTION,TEXT-HEADER %s
// TEXT-TITLE: Test Suite
// TEXT: Code Coverage Report
// TEXT: Created:
// TEXT-FILE: showProjectSummary.cpp:
// TEXT-FILE: showProjectSummary.covmapping:
// TEXT-FUNCTION: main:

// Test html output.
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -filename-equivalence %s
// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML -input-file %t.dir/index.html %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence -name=main %s
// RUN: FileCheck -check-prefixes=HTML-FUNCTION,HTML-HEADER -input-file %t.dir/functions.html %s
// HTML-TITLE: <div class='project-title'>
// HTML-TITLE: <span>Test Suite</span>
// HTML: <div class='report-title'>
// HTML: <span>Code Coverage Report</span>
// HTML: <div class='created-time'>
// HTML: <span>Created:
// HTML-FILE: <pre>Source:
// HTML-FILE: showProjectSummary.cpp</pre>
// HTML-FILE: <pre>Binary:
// HTML-FILE: showProjectSummary.covmapping</pre>
// HTML-FUNCTION: <pre>Function: main</pre>
// HTML-HEADER: <tr><td><span><pre>Line No.</pre></span></td>
// HTML-HEADER: <td><span><pre>Count No.</pre></span></td>
// HTML-HEADER: <td><span><pre>Source</pre></span></td>
8 changes: 4 additions & 4 deletions llvm/test/tools/llvm-cov/showTemplateInstantiations.cpp
Expand Up @@ -13,7 +13,7 @@ int func(T x) { // ALL-NEXT: [[@LINE]]| 2|int func(T x) {
} // ALL-NEXT: [[@LINE]]| 2|}

// SHARED: {{^ *(\| )?}}_Z4funcIbEiT_:
// SHARED-NEXT: [[@LINE-9]]| 1|int func(T x) {
// SHARED: [[@LINE-9]]| 1|int func(T x) {
// SHARED-NEXT: [[@LINE-9]]| 1| if(x)
// SHARED-NEXT: [[@LINE-9]]| 1| return 0;
// SHARED-NEXT: [[@LINE-9]]| 1| else
Expand All @@ -23,7 +23,7 @@ int func(T x) { // ALL-NEXT: [[@LINE]]| 2|int func(T x) {

// ALL: {{^ *}}| _Z4funcIiEiT_:
// FILTER-NOT: {{^ *(\| )?}} _Z4funcIiEiT_:
// ALL-NEXT: [[@LINE-19]]| 1|int func(T x) {
// ALL: [[@LINE-19]]| 1|int func(T x) {
// ALL-NEXT: [[@LINE-19]]| 1| if(x)
// ALL-NEXT: [[@LINE-19]]| 0| return 0;
// ALL-NEXT: [[@LINE-19]]| 1| else
Expand Down Expand Up @@ -56,7 +56,7 @@ int main() { // ALL: [[@LINE]]| 1|int main() {
// HTML-ALL: <td class='line-number'><a name='L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML-ALL: <td class='line-number'><a name='L[[@LINE-44]]'><pre>[[@LINE-44]]</pre></a></td><td class='covered-line'><pre>2</pre></td><td class='code'><pre>}

// HTML-SHARED: <div class='source-name-title'><pre>_Z4funcIbEiT_</pre></div><table>
// HTML-SHARED: <div class='source-name-title'><pre>Function: _Z4funcIbEiT_</pre></div>
// HTML-SHARED: <td class='line-number'><a name='L[[@LINE-53]]'><pre>[[@LINE-53]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre>int func(T x) {
// HTML-SHARED: <td class='line-number'><a name='L[[@LINE-53]]'><pre>[[@LINE-53]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre> if(x)
// HTML-SHARED: <td class='line-number'><a name='L[[@LINE-53]]'><pre>[[@LINE-53]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre> ret
Expand All @@ -65,7 +65,7 @@ int main() { // ALL: [[@LINE]]| 1|int main() {
// HTML-SHARED: <td class='line-number'><a name='L[[@LINE-53]]'><pre>[[@LINE-53]]</pre></a></td><td class='uncovered-line'><pre>0</pre></td><td class='code'><pre>
// HTML-SHARED: <td class='line-number'><a name='L[[@LINE-53]]'><pre>[[@LINE-53]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre>}

// HTML-ALL: <div class='source-name-title'><pre>_Z4funcIiEiT_</pre></div><table>
// HTML-ALL: <div class='source-name-title'><pre>Function: _Z4funcIiEiT_</pre></div>
// HTML-FILTER-NOT: <div class='source-name-title'><pre>_Z4funcIiEiT_</pre></div><table>
// HTML-ALL: <td class='line-number'><a name='L[[@LINE-63]]'><pre>[[@LINE-63]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre>int func(T x) {
// HTML-ALL: <td class='line-number'><a name='L[[@LINE-63]]'><pre>[[@LINE-63]]</pre></a></td><td class='covered-line'><pre>1</pre></td><td class='code'><pre> if(x)
Expand Down
36 changes: 31 additions & 5 deletions llvm/tools/llvm-cov/CodeCoverage.cpp
Expand Up @@ -210,9 +210,9 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
return nullptr;

auto Expansions = FunctionCoverage.getExpansions();
auto View = SourceCoverageView::create(getSymbolForHumans(Function.Name),
SourceBuffer.get(), ViewOpts,
std::move(FunctionCoverage));
auto View = SourceCoverageView::create(
getSymbolForHumans(Function.Name), SourceBuffer.get(), ViewOpts,
std::move(FunctionCoverage), /*FunctionView=*/true);
attachExpansionSubViews(*View, Expansions, Coverage);

return View;
Expand All @@ -238,7 +238,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
auto SubViewExpansions = SubViewCoverage.getExpansions();
auto SubView = SourceCoverageView::create(
getSymbolForHumans(Function->Name), SourceBuffer.get(), ViewOpts,
std::move(SubViewCoverage));
std::move(SubViewCoverage), /*FunctionView=*/true);
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);

if (SubView) {
Expand Down Expand Up @@ -463,6 +463,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
CompareFilenamesOnly = FilenameEquivalence;

ViewOpts.Format = Format;
SmallString<128> ObjectFilePath(this->ObjectFilename);
if (std::error_code EC = sys::fs::make_absolute(ObjectFilePath)) {
error(EC.message(), this->ObjectFilename);
return 1;
}
ViewOpts.ObjectFilename = ObjectFilePath.c_str();
switch (ViewOpts.Format) {
case CoverageViewOptions::OutputFormat::Text:
ViewOpts.Colors = UseColor == cl::BOU_UNSET
Expand Down Expand Up @@ -589,6 +595,10 @@ int CodeCoverageTool::show(int argc, const char **argv,
cl::desc(
"Set tab expansion size for html coverage reports (default = 2)"));

cl::opt<std::string> ProjectTitle(
"project-title", cl::Optional,
cl::desc("Set project title for the coverage report"));

auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
Expand All @@ -602,6 +612,7 @@ int CodeCoverageTool::show(int argc, const char **argv,
ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
ViewOpts.TabSize = TabSize;
ViewOpts.ProjectTitle = ProjectTitle;

if (ViewOpts.hasOutputDirectory()) {
if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
Expand All @@ -610,6 +621,19 @@ int CodeCoverageTool::show(int argc, const char **argv,
}
}

sys::fs::file_status Status;
if (sys::fs::status(PGOFilename, Status)) {
error("profdata file error: can not get the file status. \n");
return 1;
}

auto ModifiedTime = Status.getLastModificationTime();
std::string ModifiedTimeStr = ModifiedTime.str();
size_t found = ModifiedTimeStr.rfind(":");
ViewOpts.CreatedTimeStr = (found != std::string::npos)
? "Created: " + ModifiedTimeStr.substr(0, found)
: "Created: " + ModifiedTimeStr;

auto Coverage = load();
if (!Coverage)
return 1;
Expand Down Expand Up @@ -643,7 +667,9 @@ int CodeCoverageTool::show(int argc, const char **argv,
}

// Show files
bool ShowFilenames = SourceFiles.size() != 1;
bool ShowFilenames =
(SourceFiles.size() != 1) ||
(ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML);

if (SourceFiles.empty())
// Get the source files from the function coverage mapping.
Expand Down
9 changes: 9 additions & 0 deletions llvm/tools/llvm-cov/CoverageViewOptions.h
Expand Up @@ -35,6 +35,9 @@ struct CoverageViewOptions {
std::string ShowOutputDirectory;
std::vector<std::string> DemanglerOpts;
uint32_t TabSize;
std::string ProjectTitle;
std::string ObjectFilename;
std::string CreatedTimeStr;

/// \brief Change the output's stream color if the colors are enabled.
ColoredRawOstream colored_ostream(raw_ostream &OS,
Expand All @@ -47,6 +50,12 @@ struct CoverageViewOptions {

/// \brief Check if a demangler has been specified.
bool hasDemangler() const { return !DemanglerOpts.empty(); }

/// \brief Check if a project title has been specified.
bool hasProjectTitle() const { return !ProjectTitle.empty(); }

/// \brief Check if the created time of the profile data file is available.
bool hasCreatedTime() const { return !CreatedTimeStr.empty(); }
};
}

Expand Down
19 changes: 12 additions & 7 deletions llvm/tools/llvm-cov/SourceCoverageView.cpp
Expand Up @@ -109,14 +109,15 @@ bool SourceCoverageView::hasSubViews() const {
std::unique_ptr<SourceCoverageView>
SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File,
const CoverageViewOptions &Options,
coverage::CoverageData &&CoverageInfo) {
coverage::CoverageData &&CoverageInfo,
bool FunctionView) {
switch (Options.Format) {
case CoverageViewOptions::OutputFormat::Text:
return llvm::make_unique<SourceCoverageViewText>(SourceName, File, Options,
std::move(CoverageInfo));
return llvm::make_unique<SourceCoverageViewText>(
SourceName, File, Options, std::move(CoverageInfo), FunctionView);
case CoverageViewOptions::OutputFormat::HTML:
return llvm::make_unique<SourceCoverageViewHTML>(SourceName, File, Options,
std::move(CoverageInfo));
return llvm::make_unique<SourceCoverageViewHTML>(
SourceName, File, Options, std::move(CoverageInfo), FunctionView);
}
llvm_unreachable("Unknown coverage output format!");
}
Expand All @@ -135,11 +136,15 @@ void SourceCoverageView::addInstantiation(

void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
bool ShowSourceName, unsigned ViewDepth) {
if (ShowSourceName)
renderSourceName(OS);
if (WholeFile)
renderCellInTitle(OS, "Code Coverage Report");

renderViewHeader(OS);

if (ShowSourceName)
renderSourceName(OS, WholeFile);

renderTableHeader(OS, ViewDepth);
// We need the expansions and instantiations sorted so we can go through them
// while we iterate lines.
std::sort(ExpansionSubViews.begin(), ExpansionSubViews.end());
Expand Down
20 changes: 16 additions & 4 deletions llvm/tools/llvm-cov/SourceCoverageView.h
Expand Up @@ -172,6 +172,9 @@ class SourceCoverageView {
/// on display.
std::vector<InstantiationView> InstantiationSubViews;

/// Specifies whether or not the view is a function view.
bool FunctionView;

protected:
struct LineRef {
StringRef Line;
Expand All @@ -192,7 +195,7 @@ class SourceCoverageView {
virtual void renderViewFooter(raw_ostream &OS) = 0;

/// \brief Render the source name for the view.
virtual void renderSourceName(raw_ostream &OS) = 0;
virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;

/// \brief Render the line prefix at the given \p ViewDepth.
virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
Expand Down Expand Up @@ -236,6 +239,13 @@ class SourceCoverageView {
virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
unsigned ViewDepth) = 0;

/// \brief Render the project title, the report title \p CellText and the
/// created time for the view.
virtual void renderCellInTitle(raw_ostream &OS, StringRef CellText) = 0;

/// \brief Render the table header for a given source file
virtual void renderTableHeader(raw_ostream &OS, unsigned IndentLevel = 0) = 0;

/// @}

/// \brief Format a count using engineering notation with 3 significant
Expand All @@ -250,20 +260,22 @@ class SourceCoverageView {

SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
const CoverageViewOptions &Options,
coverage::CoverageData &&CoverageInfo)
coverage::CoverageData &&CoverageInfo, bool FunctionView)
: SourceName(SourceName), File(File), Options(Options),
CoverageInfo(std::move(CoverageInfo)) {}
CoverageInfo(std::move(CoverageInfo)), FunctionView(FunctionView) {}

public:
static std::unique_ptr<SourceCoverageView>
create(StringRef SourceName, const MemoryBuffer &File,
const CoverageViewOptions &Options,
coverage::CoverageData &&CoverageInfo);
coverage::CoverageData &&CoverageInfo, bool FucntionView = false);

virtual ~SourceCoverageView() {}

StringRef getSourceName() const { return SourceName; }

bool isFunctionView() const { return FunctionView; }

const CoverageViewOptions &getOptions() const { return Options; }

/// \brief Add an expansion subview to this view.
Expand Down

0 comments on commit 84dc971

Please sign in to comment.