diff options
Diffstat (limited to 'Source/CTest/cmParseMumpsCoverage.cxx')
-rw-r--r-- | Source/CTest/cmParseMumpsCoverage.cxx | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx new file mode 100644 index 0000000..dc3064d --- /dev/null +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -0,0 +1,144 @@ +#include "cmParseMumpsCoverage.h" + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" + +#include "cmCTest.h" +#include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cmParseMumpsCoverage::cmParseMumpsCoverage( + cmCTestCoverageHandlerContainer& cont, cmCTest* ctest) + : Coverage(cont) + , CTest(ctest) +{ +} + +cmParseMumpsCoverage::~cmParseMumpsCoverage() = default; + +bool cmParseMumpsCoverage::ReadCoverageFile(const char* file) +{ + // Read the gtm_coverage.mcov file, that has two lines of data: + // packages:/full/path/to/Vista/Packages + // coverage_dir:/full/path/to/dir/with/*.mcov + cmsys::ifstream in(file); + if (!in) { + return false; + } + std::string line; + while (cmSystemTools::GetLineFromStream(in, line)) { + std::string::size_type pos = line.find(':', 0); + std::string packages; + if (pos != std::string::npos) { + std::string type = line.substr(0, pos); + std::string path = line.substr(pos + 1); + if (type == "packages") { + this->LoadPackages(path); + } else if (type == "coverage_dir") { + this->LoadCoverageData(path); + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Parse Error in Mumps coverage file :\n" + << file << "\ntype: [" << type << "]\npath:[" << path + << "]\n" + "input line: [" + << line << "]\n"); + } + } + } + return true; +} + +void cmParseMumpsCoverage::InitializeMumpsFile(std::string& file) +{ + // initialize the coverage information for a given mumps file + cmsys::ifstream in(file.c_str()); + if (!in) { + return; + } + std::string line; + cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector = + this->Coverage.TotalCoverage[file]; + if (!cmSystemTools::GetLineFromStream(in, line)) { + return; + } + // first line of a .m file can never be run + coverageVector.push_back(-1); + while (cmSystemTools::GetLineFromStream(in, line)) { + // putting in a 0 for a line means it is executable code + // putting in a -1 for a line means it is not executable code + int val = -1; // assume line is not executable + bool found = false; + std::string::size_type i = 0; + // (1) Search for the first whitespace or semicolon character on a line. + // This will skip over labels if the line starts with one, or will simply + // be the first character on the line for non-label lines. + for (; i < line.size(); ++i) { + if (line[i] == ' ' || line[i] == '\t' || line[i] == ';') { + found = true; + break; + } + } + if (found) { + // (2) If the first character found above is whitespace or a period + // then continue the search for the first following non-whitespace + // character. + if (line[i] == ' ' || line[i] == '\t') { + while (i < line.size() && + (line[i] == ' ' || line[i] == '\t' || line[i] == '.')) { + i++; + } + } + // (3) If the character found is not a semicolon then the line counts for + // coverage. + if (i < line.size() && line[i] != ';') { + val = 0; + } + } + coverageVector.push_back(val); + } +} + +bool cmParseMumpsCoverage::LoadPackages(std::string const& d) +{ + cmsys::Glob glob; + glob.RecurseOn(); + std::string pat = cmStrCat(d, "/*.m"); + glob.FindFiles(pat); + for (std::string& file : glob.GetFiles()) { + std::string name = cmSystemTools::GetFilenameName(file); + name.erase(name.size() - 2); + this->RoutineToDirectory[name] = file; + // initialize each file, this is left out until CDash is fixed + // to handle large numbers of files + this->InitializeMumpsFile(file); + } + return true; +} + +bool cmParseMumpsCoverage::FindMumpsFile(std::string const& routine, + std::string& filepath) +{ + auto i = this->RoutineToDirectory.find(routine); + if (i != this->RoutineToDirectory.end()) { + filepath = i->second; + return true; + } + // try some alternate names + const char* tryname[] = { "GUX", "GTM", "ONT", nullptr }; + for (int k = 0; tryname[k] != nullptr; k++) { + std::string routine2 = routine + tryname[k]; + i = this->RoutineToDirectory.find(routine2); + if (i != this->RoutineToDirectory.end()) { + filepath = i->second; + return true; + } + } + return false; +} |