mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Introduce the capability to use the Clang Source code coverage capability
to generate coverage information for a submission to CDash.
This handler will:
* Recursively glob the binary directory for coverage files (`*.profdata`)
* Use the `llvm-profdata` tool to merge all found files into a single
`default.profdata` file
* Recursively glob the binary directory for .o files
* Use the `llvm-cov export` capability to parse the coverage information
found for each object file
Since the coverage information contains branch coverage, add new attributes
to the CoverageLog Line object to capture the number of branches that are
covered and uncovered
See documentation page here
https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
159 lines
5.6 KiB
C++
159 lines
5.6 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#pragma once
|
|
|
|
#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
|
#include <array>
|
|
#include <iosfwd>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "cmsys/RegularExpression.hxx"
|
|
|
|
#include "cmCTestGenericHandler.h"
|
|
|
|
class cmGeneratedFileStream;
|
|
class cmXMLWriter;
|
|
class cmCTest;
|
|
|
|
class cmCTestCoverageHandlerContainer
|
|
{
|
|
public:
|
|
int Error;
|
|
std::string SourceDir;
|
|
std::string BinaryDir;
|
|
using SingleFileCoverageVector = std::vector<int>;
|
|
using SingleFileBranchCoverageVector = std::vector<std::array<int, 2>>;
|
|
using TotalCoverageMap = std::map<std::string, SingleFileCoverageVector>;
|
|
using TotalBranchCoverageMap =
|
|
std::map<std::string, SingleFileBranchCoverageVector>;
|
|
TotalCoverageMap TotalCoverage;
|
|
TotalBranchCoverageMap TotalBranchCoverage;
|
|
std::ostream* OFS;
|
|
bool Quiet;
|
|
};
|
|
/** \class cmCTestCoverageHandler
|
|
* \brief A class that handles coverage computation for ctest
|
|
*
|
|
*/
|
|
class cmCTestCoverageHandler : public cmCTestGenericHandler
|
|
{
|
|
public:
|
|
using Superclass = cmCTestGenericHandler;
|
|
|
|
/*
|
|
* The main entry point for this class
|
|
*/
|
|
int ProcessHandler() override;
|
|
|
|
cmCTestCoverageHandler(cmCTest* ctest);
|
|
|
|
/**
|
|
* This method is called when reading CTest custom file
|
|
*/
|
|
void PopulateCustomVectors(cmMakefile* mf) override;
|
|
|
|
/** Report coverage only for sources with these labels. */
|
|
void SetLabelFilter(std::set<std::string> const& labels);
|
|
|
|
private:
|
|
bool ShouldIDoCoverage(std::string const& file, std::string const& srcDir,
|
|
std::string const& binDir);
|
|
void CleanCoverageLogFiles(std::ostream& log);
|
|
bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
|
|
void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
|
|
|
|
void StartCoverageLogXML(cmXMLWriter& xml);
|
|
void EndCoverageLogXML(cmXMLWriter& xml);
|
|
|
|
//! Handle coverage using GCC's GCov
|
|
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
void FindGCovFiles(std::vector<std::string>& files);
|
|
|
|
//! Handle coverage using Intel's LCov
|
|
int HandleLCovCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
bool FindLCovFiles(std::vector<std::string>& files);
|
|
|
|
//! Handle coverage using xdebug php coverage
|
|
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage for Clang with llvm function
|
|
int HandleClangSourceCodeCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
void HandleClangSourceCodeCoverageFile(cmCTestCoverageHandlerContainer* cont,
|
|
std::string output);
|
|
//! Handle coverage for Python with coverage.py
|
|
int HandleCoberturaCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage for mumps
|
|
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage for Jacoco
|
|
int HandleJacocoCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage for Delphi (Pascal)
|
|
int HandleDelphiCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage for Jacoco
|
|
int HandleBlanketJSCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
//! Handle coverage using Bullseye
|
|
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
int RunBullseyeSourceSummary(cmCTestCoverageHandlerContainer* cont);
|
|
int RunBullseyeCoverageBranch(cmCTestCoverageHandlerContainer* cont,
|
|
std::set<std::string>& coveredFileNames,
|
|
std::vector<std::string>& files,
|
|
std::vector<std::string>& filesFullPath);
|
|
|
|
int RunBullseyeCommand(cmCTestCoverageHandlerContainer* cont,
|
|
char const* cmd, char const* arg,
|
|
std::string& outputFile);
|
|
bool ParseBullsEyeCovsrcLine(std::string const& inputLine,
|
|
std::string& sourceFile, int& functionsCalled,
|
|
int& totalFunctions, int& percentFunction,
|
|
int& branchCovered, int& totalBranches,
|
|
int& percentBranch);
|
|
bool GetNextInt(std::string const& inputLine, std::string::size_type& pos,
|
|
int& value);
|
|
//! Handle Python coverage using Python's Trace.py
|
|
int HandleTracePyCoverage(cmCTestCoverageHandlerContainer* cont);
|
|
|
|
// Find the source file based on the source and build tree. This is used for
|
|
// Trace.py mode, since that one does not tell us where the source file is.
|
|
std::string FindFile(cmCTestCoverageHandlerContainer* cont,
|
|
std::string const& fileName);
|
|
|
|
std::set<std::string> FindUncoveredFiles(
|
|
cmCTestCoverageHandlerContainer* cont);
|
|
std::vector<std::string> CustomCoverageExclude;
|
|
std::vector<cmsys::RegularExpression> CustomCoverageExcludeRegex;
|
|
std::vector<std::string> ExtraCoverageGlobs;
|
|
|
|
// Map from source file to label ids.
|
|
class LabelSet : public std::set<int>
|
|
{
|
|
};
|
|
using LabelMapType = std::map<std::string, LabelSet>;
|
|
LabelMapType SourceLabels;
|
|
LabelMapType TargetDirs;
|
|
|
|
// Map from label name to label id.
|
|
using LabelIdMapType = std::map<std::string, int>;
|
|
LabelIdMapType LabelIdMap;
|
|
std::vector<std::string> Labels;
|
|
int GetLabelId(std::string const& label);
|
|
|
|
// Label reading and writing methods.
|
|
void LoadLabels();
|
|
void LoadLabels(char const* dir);
|
|
void WriteXMLLabels(cmXMLWriter& xml, std::string const& source);
|
|
|
|
// Label-based filtering.
|
|
std::set<int> LabelFilter;
|
|
bool IntersectsFilter(LabelSet const& labels);
|
|
bool IsFilteredOut(std::string const& source);
|
|
};
|