[llvm] r263767 - [sancov] html report: replacing uncovered functions with function coverage % table.

Mike Aizatsky via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 17 17:12:15 PDT 2016


Author: aizatsky
Date: Thu Mar 17 19:12:14 2016
New Revision: 263767

URL: http://llvm.org/viewvc/llvm-project?rev=263767&view=rev
Log:
[sancov] html report: replacing uncovered functions with function coverage % table.

Differential Revision: http://reviews.llvm.org/D18256

Modified:
    llvm/trunk/tools/sancov/sancov.cc

Modified: llvm/trunk/tools/sancov/sancov.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sancov/sancov.cc?rev=263767&r1=263766&r2=263767&view=diff
==============================================================================
--- llvm/trunk/tools/sancov/sancov.cc (original)
+++ llvm/trunk/tools/sancov/sancov.cc Thu Mar 17 19:12:14 2016
@@ -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";




More information about the llvm-commits mailing list