diff options
author | Mike Aizatsky <aizatsky@chromium.org> | 2016-03-18 00:12:14 +0000 |
---|---|---|
committer | Mike Aizatsky <aizatsky@chromium.org> | 2016-03-18 00:12:14 +0000 |
commit | 363d331f992d744c61c1d7b789d2b7f5f091fb79 (patch) | |
tree | 37db215893d61f86433c65ede0428bd09c77b37a /llvm/tools | |
parent | 37cbc43ecbbec0833c84037bedda14a8a885cebb (diff) | |
download | bcm5719-llvm-363d331f992d744c61c1d7b789d2b7f5f091fb79.tar.gz bcm5719-llvm-363d331f992d744c61c1d7b789d2b7f5f091fb79.zip |
[sancov] html report: replacing uncovered functions with function coverage % table.
Differential Revision: http://reviews.llvm.org/D18256
llvm-svn: 263767
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/sancov/sancov.cc | 113 |
1 files changed, 69 insertions, 44 deletions
diff --git a/llvm/tools/sancov/sancov.cc b/llvm/tools/sancov/sancov.cc index 200027677f1..4c9b7065461 100644 --- a/llvm/tools/sancov/sancov.cc +++ b/llvm/tools/sancov/sancov.cc @@ -628,32 +628,21 @@ public: CovAddrInfo = getAddrInfo(ObjectFile, Addrs, true); } - // Compute number of functions hit/total in a file. - // file_name -> <fn_coverage, all_fn_coverage> - std::map<std::string, std::pair<size_t, size_t>> computeFileFnCoverage() { + // Compute number of coverage points hit/total in a file. + // file_name -> <coverage, all_coverage> + std::map<std::string, std::pair<size_t, size_t>> computeFileCoverage() { std::map<std::string, std::pair<size_t, size_t>> FileCoverage; auto AllCovPointsByFile = group_by(AllAddrInfo, [](const AddrInfo &AI) { return AI.FileName; }); - auto CovPointByFile = + auto CovPointsByFile = group_by(CovAddrInfo, [](const AddrInfo &AI) { return AI.FileName; }); - for (auto P : AllCovPointsByFile) { + for (const auto &P : AllCovPointsByFile) { const std::string &FileName = P.first; - const auto &AllCovInfo = P.second; - - auto AllFns = group_by( - AllCovInfo, [](const AddrInfo &AI) { return AI.FunctionName; }); - size_t AllCoverage = AllFns.size(); - size_t Coverage = 0; - - auto It = CovPointByFile.find(FileName); - if (It != CovPointByFile.end()) { - const auto &CovInfo = It->second; - auto Fns = group_by(CovInfo, - [](const AddrInfo &AI) { return AI.FunctionName; }); - Coverage = Fns.size(); - } - FileCoverage[FileName] = std::make_pair(Coverage, AllCoverage); + + FileCoverage[FileName] = + std::make_pair(CovPointsByFile[FileName].size(), + AllCovPointsByFile[FileName].size()); } return FileCoverage; } @@ -688,6 +677,14 @@ public: return StatusMap; } + std::set<FileFn> computeAllFunctions() const { + std::set<FileFn> Fns; + for (const auto &AI : AllAddrInfo) { + Fns.insert(FileFn{AI.FileName, AI.FunctionName}); + } + return Fns; + } + std::set<FileFn> computeCoveredFunctions() const { std::set<FileFn> Fns; auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) { @@ -718,6 +715,25 @@ public: return Fns; } + // Compute % coverage for each function. + std::map<FileFn, int> computeFunctionsCoverage() const { + std::map<FileFn, int> FnCoverage; + auto AllFns = group_by(AllAddrInfo, [](const AddrInfo &AI) { + return FileFn{AI.FileName, AI.FunctionName}; + }); + + auto CovFns = group_by(CovAddrInfo, [](const AddrInfo &AI) { + return FileFn{AI.FileName, AI.FunctionName}; + }); + + for (const auto &P : AllFns) { + FileFn F = P.first; + FnCoverage[F] = CovFns[F].size() * 100 / P.second.size(); + } + + return FnCoverage; + } + typedef std::map<FileLoc, std::set<std::string>> FunctionLocs; // finds first line number in a file for each function. FunctionLocs resolveFunctions(const std::set<FileFn> &Fns) const { @@ -812,13 +828,16 @@ public: SourceCoverageData SCovData(ObjectFile, *Addrs); auto LineStatusMap = SCovData.computeLineStatusMap(); - // file_name -> [file_fn]. - auto NotCoveredFns = SCovData.computeNotCoveredFunctions(); - auto NotCoveredFnMap = group_by( - NotCoveredFns, [](const FileFn &FileFn) { return FileFn.FileName; }); + std::set<FileFn> AllFns = SCovData.computeAllFunctions(); // file_loc -> set[function_name] - auto NotCoveredFnByLoc = SCovData.resolveFunctions(NotCoveredFns); - auto FileFnCoverage = SCovData.computeFileFnCoverage(); + auto AllFnsByLoc = SCovData.resolveFunctions(AllFns); + auto FileCoverage = SCovData.computeFileCoverage(); + + auto FnCoverage = SCovData.computeFunctionsCoverage(); + auto FnCoverageByFile = + group_by(FnCoverage, [](const std::pair<FileFn, int> &FileFn) { + return FileFn.first.FileName; + }); // TOC @@ -828,10 +847,10 @@ public: // Covered Files. OS << "<details open><summary>Touched Files</summary>\n"; OS << "<table>\n"; - OS << "<tr><th>File</th><th>Hit Fns %</th>"; + OS << "<tr><th>File</th><th>Coverage %</th>"; OS << "<th>Hit (Total) Fns</th></tr>\n"; for (auto FileName : Files) { - std::pair<size_t, size_t> FC = FileFnCoverage[FileName]; + std::pair<size_t, size_t> FC = FileCoverage[FileName]; if (FC.first == 0) { NotCoveredFilesCount++; continue; @@ -852,7 +871,7 @@ public: OS << "<details><summary>Not Touched Files</summary>\n"; OS << "<table>\n"; for (auto FileName : Files) { - std::pair<size_t, size_t> FC = FileFnCoverage[FileName]; + std::pair<size_t, size_t> FC = FileCoverage[FileName]; if (FC.first == 0) OS << "<tr><td>" << stripPathPrefix(FileName) << "</td>\n"; } @@ -864,25 +883,27 @@ public: // Source for (auto FileName : Files) { - std::pair<size_t, size_t> FC = FileFnCoverage[FileName]; + std::pair<size_t, size_t> FC = FileCoverage[FileName]; if (FC.first == 0) continue; OS << "<a name=\"" << anchorName(FileName) << "\"></a>\n"; OS << "<h2>" << stripPathPrefix(FileName) << "</h2>\n"; + OS << "<details open><summary>Function Coverage</summary>"; + OS << "<div class='fnlist'>\n"; - auto NotCoveredFns = NotCoveredFnMap.find(FileName); - if (NotCoveredFns != NotCoveredFnMap.end()) { - OS << "<details open><summary>Not Covered Functions</summary>"; - OS << "<table>\n"; - for (auto FileFn : NotCoveredFns->second) { - OS << "<tr><td>"; - OS << "<a href=\"#" - << anchorName(FileName + "::" + FileFn.FunctionName) << "\">"; - OS << escapeHtml(FileFn.FunctionName) << "</a>"; - OS << "</td></tr>\n"; - } - OS << "</table></details>\n"; + auto &FileFnCoverage = FnCoverageByFile[FileName]; + + for (const auto &P : FileFnCoverage) { + std::string FunctionName = P.first.FunctionName; + + OS << "<div class='fn' style='order: " << P.second << "'>"; + OS << "<span class='pct'>" << P.second << "%</span> "; + OS << "<span class='name'><a href=\"#" + << anchorName(FileName + "::" + FunctionName) << "\">"; + OS << escapeHtml(FunctionName) << "</a></span>"; + OS << "</div>\n"; } + OS << "</div></details>\n"; ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = MemoryBuffer::getFile(FileName); @@ -900,8 +921,8 @@ public: uint32_t Line = I.line_number(); { // generate anchors (if any); FileLoc Loc = FileLoc{FileName, Line}; - auto It = NotCoveredFnByLoc.find(Loc); - if (It != NotCoveredFnByLoc.end()) { + auto It = AllFnsByLoc.find(Loc); + if (It != AllFnsByLoc.end()) { for (std::string Fn : It->second) { OS << "<a name=\"" << anchorName(FileName + "::" + Fn) << "\"></a>"; @@ -1041,6 +1062,10 @@ public: OS << ".mixed { background: #FF7; }\n"; OS << "summary { font-weight: bold; }\n"; OS << "details > summary + * { margin-left: 1em; }\n"; + OS << ".fnlist { display: flex; flex-flow: column nowrap; }\n"; + OS << ".fn { display: flex; flex-flow: row nowrap; }\n"; + OS << ".pct { width: 3em; text-align: right; margin-right: 1em; }\n"; + OS << ".name { flex: 2; }\n"; OS << "</style>\n"; OS << "<title>" << Title << "</title>\n"; OS << "</head>\n"; |