File src/GcovImporter.cpp changed (mode: 100644) (index 86dc01c..3276d69) |
... |
... |
namespace pt = boost::property_tree; |
54 |
54 |
static const char GcovJsonFormat[] = "--json-format"; |
static const char GcovJsonFormat[] = "--json-format"; |
55 |
55 |
//! `gcov` option to generate coverage in plain text format. |
//! `gcov` option to generate coverage in plain text format. |
56 |
56 |
static const char GcovIntermediateFormat[] = "--intermediate-format"; |
static const char GcovIntermediateFormat[] = "--intermediate-format"; |
|
57 |
|
//! `gcov` option to dump coverage onto standard output. |
|
58 |
|
static const char GcovStdOut[] = "--stdout"; |
57 |
59 |
|
|
58 |
60 |
//! First version of `gcov` which has broken `--preserve-paths` option. |
//! First version of `gcov` which has broken `--preserve-paths` option. |
59 |
61 |
static int FirstBrokenGcovVersion = 8; |
static int FirstBrokenGcovVersion = 8; |
|
... |
... |
namespace { |
112 |
114 |
} |
} |
113 |
115 |
|
|
114 |
116 |
GcovInfo::GcovInfo() |
GcovInfo::GcovInfo() |
115 |
|
: employBinning(true), jsonFormat(false), intermediateFormat(false) |
|
|
117 |
|
: employBinning(true), |
|
118 |
|
jsonFormat(false), intermediateFormat(false), stdOut(false) |
116 |
119 |
{ |
{ |
117 |
120 |
const std::regex optionRegex("--[-a-z]+"); |
const std::regex optionRegex("--[-a-z]+"); |
118 |
121 |
const std::regex versionRegex("gcov \\(GCC\\) (.*)"); |
const std::regex versionRegex("gcov \\(GCC\\) (.*)"); |
|
... |
... |
GcovInfo::GcovInfo() |
128 |
131 |
jsonFormat = true; |
jsonFormat = true; |
129 |
132 |
} else if (str == GcovIntermediateFormat) { |
} else if (str == GcovIntermediateFormat) { |
130 |
133 |
intermediateFormat = true; |
intermediateFormat = true; |
|
134 |
|
} else if (str == GcovStdOut) { |
|
135 |
|
stdOut = true; |
131 |
136 |
} |
} |
132 |
137 |
|
|
133 |
138 |
from += match.position() + match.length(); |
from += match.position() + match.length(); |
|
... |
... |
GcovInfo::GcovInfo() |
140 |
145 |
} |
} |
141 |
146 |
} |
} |
142 |
147 |
|
|
143 |
|
GcovInfo::GcovInfo(bool employBinning, bool jsonFormat, |
|
144 |
|
bool intermediateFormat) |
|
145 |
|
: employBinning(employBinning), jsonFormat(jsonFormat), |
|
146 |
|
intermediateFormat(intermediateFormat) |
|
|
148 |
|
GcovInfo::GcovInfo(bool employBinning, |
|
149 |
|
bool jsonFormat, |
|
150 |
|
bool intermediateFormat, |
|
151 |
|
bool stdOut) |
|
152 |
|
: employBinning(employBinning), |
|
153 |
|
jsonFormat(jsonFormat), |
|
154 |
|
intermediateFormat(intermediateFormat), |
|
155 |
|
stdOut(stdOut) |
147 |
156 |
{ } |
{ } |
148 |
157 |
|
|
149 |
158 |
std::function<GcovImporter::runner_f> |
std::function<GcovImporter::runner_f> |
|
... |
... |
GcovImporter::getFiles() && |
255 |
264 |
void |
void |
256 |
265 |
GcovImporter::importFiles(std::vector<fs::path> gcnoFiles) |
GcovImporter::importFiles(std::vector<fs::path> gcnoFiles) |
257 |
266 |
{ |
{ |
258 |
|
importAsFiles(std::move(gcnoFiles)); |
|
|
267 |
|
if (gcovInfo.hasJsonFormat() && gcovInfo.canPrintToStdOut()) { |
|
268 |
|
importAsOutput(std::move(gcnoFiles)); |
|
269 |
|
} else { |
|
270 |
|
importAsFiles(std::move(gcnoFiles)); |
|
271 |
|
} |
|
272 |
|
} |
|
273 |
|
|
|
274 |
|
void |
|
275 |
|
GcovImporter::importAsOutput(std::vector<fs::path> gcnoFiles) |
|
276 |
|
{ |
|
277 |
|
std::vector<std::string> cmd = { |
|
278 |
|
"gcov", GcovJsonFormat, GcovStdOut, "--" |
|
279 |
|
}; |
|
280 |
|
|
|
281 |
|
cmd.reserve(cmd.size() + gcnoFiles.size()); |
|
282 |
|
for (const fs::path &gcnoFile : gcnoFiles) { |
|
283 |
|
cmd.push_back(gcnoFile.string()); |
|
284 |
|
} |
|
285 |
|
|
|
286 |
|
const std::string output = getRunner()(std::move(cmd), "-"); |
|
287 |
|
|
|
288 |
|
for (std::string &json : split(output, '\n')) { |
|
289 |
|
if (!json.empty()) { |
|
290 |
|
std::istringstream iss(std::move(json)); |
|
291 |
|
parseGcovJson(iss); |
|
292 |
|
} |
|
293 |
|
} |
259 |
294 |
} |
} |
260 |
295 |
|
|
261 |
296 |
void |
void |
File src/GcovImporter.hpp changed (mode: 100644) (index 865a8c1..0575e7e) |
... |
... |
public: |
44 |
44 |
* @param employBinning No calling `gcov` with identically named files. |
* @param employBinning No calling `gcov` with identically named files. |
45 |
45 |
* @param jsonFormat If JSON format is available. |
* @param jsonFormat If JSON format is available. |
46 |
46 |
* @param intermediateFormat If plain text format is available. |
* @param intermediateFormat If plain text format is available. |
|
47 |
|
* @param stdOut If dumping to stdout is available. |
47 |
48 |
*/ |
*/ |
48 |
|
GcovInfo(bool employBinning, bool jsonFormat, bool intermediateFormat); |
|
|
49 |
|
GcovInfo(bool employBinning, |
|
50 |
|
bool jsonFormat, bool intermediateFormat, bool stdOut); |
49 |
51 |
|
|
50 |
52 |
public: |
public: |
51 |
53 |
/** |
/** |
|
... |
... |
public: |
69 |
71 |
*/ |
*/ |
70 |
72 |
bool hasIntermediateFormat() const |
bool hasIntermediateFormat() const |
71 |
73 |
{ return intermediateFormat; } |
{ return intermediateFormat; } |
|
74 |
|
/** |
|
75 |
|
* @brief Checks whether result can be dumped to standard output. |
|
76 |
|
* |
|
77 |
|
* @returns `true` if so. |
|
78 |
|
*/ |
|
79 |
|
bool canPrintToStdOut() const |
|
80 |
|
{ return jsonFormat && stdOut; } |
72 |
81 |
|
|
73 |
82 |
private: |
private: |
74 |
83 |
//! Whether `gcov` command doesn't handle identically-named files properly. |
//! Whether `gcov` command doesn't handle identically-named files properly. |
|
... |
... |
private: |
77 |
86 |
bool jsonFormat; |
bool jsonFormat; |
78 |
87 |
//! Whether plain text intermediate format is supported. |
//! Whether plain text intermediate format is supported. |
79 |
88 |
bool intermediateFormat; |
bool intermediateFormat; |
|
89 |
|
//! Whether result can be dumpted to stdout. |
|
90 |
|
bool stdOut; |
80 |
91 |
}; |
}; |
81 |
92 |
|
|
82 |
93 |
/** |
/** |
|
... |
... |
private: |
133 |
144 |
* @param gcnoFiles Absolute paths to `*.gcno` files. |
* @param gcnoFiles Absolute paths to `*.gcno` files. |
134 |
145 |
*/ |
*/ |
135 |
146 |
void importFiles(std::vector<boost::filesystem::path> gcnoFiles); |
void importFiles(std::vector<boost::filesystem::path> gcnoFiles); |
|
147 |
|
/** |
|
148 |
|
* @brief Calls `gcov` to print output to stdout and processes it. |
|
149 |
|
* |
|
150 |
|
* @param gcnoFiles Absolute paths to `*.gcno` files. |
|
151 |
|
*/ |
|
152 |
|
void importAsOutput(std::vector<boost::filesystem::path> gcnoFiles); |
136 |
153 |
/** |
/** |
137 |
154 |
* @brief Calls `gcov` to generate output files and processes them. |
* @brief Calls `gcov` to generate output files and processes them. |
138 |
155 |
* |
* |
File tests/GcovImporter.cpp changed (mode: 100644) (index e134e09..e1fa923) |
... |
... |
namespace fs = boost::filesystem; |
34 |
34 |
TEST_CASE("Need support for at least one intermediate format", "[GcovImporter]") |
TEST_CASE("Need support for at least one intermediate format", "[GcovImporter]") |
35 |
35 |
{ |
{ |
36 |
36 |
GcovInfo gcovInfo(/*employBinning=*/false, /*jsonFormat=*/false, |
GcovInfo gcovInfo(/*employBinning=*/false, /*jsonFormat=*/false, |
37 |
|
/*intermediateFormat=*/false); |
|
|
37 |
|
/*intermediateFormat=*/false, /*stdOut=*/false); |
38 |
38 |
REQUIRE_THROWS_AS(GcovImporter("", "", {}, "", gcovInfo), |
REQUIRE_THROWS_AS(GcovImporter("", "", {}, "", gcovInfo), |
39 |
39 |
const std::runtime_error &); |
const std::runtime_error &); |
40 |
40 |
} |
} |
|
... |
... |
TEST_CASE("Plain text format parsed and binning is performed", "[GcovImporter]") |
73 |
73 |
}; |
}; |
74 |
74 |
|
|
75 |
75 |
GcovInfo gcovInfo(/*employBinning=*/true, /*jsonFormat=*/false, |
GcovInfo gcovInfo(/*employBinning=*/true, /*jsonFormat=*/false, |
76 |
|
/*intermediateFormat=*/true); |
|
|
76 |
|
/*intermediateFormat=*/true, /*stdOut=*/false); |
77 |
77 |
std::vector<File> files = |
std::vector<File> files = |
78 |
78 |
GcovImporter(tempDirPath, tempDirPath, {}, tempDirPath, |
GcovImporter(tempDirPath, tempDirPath, {}, tempDirPath, |
79 |
79 |
gcovInfo).getFiles(); |
gcovInfo).getFiles(); |
|
... |
... |
TEST_CASE("JSON format is parsed", "[GcovImporter]") |
119 |
119 |
}; |
}; |
120 |
120 |
|
|
121 |
121 |
GcovInfo gcovInfo(/*employBinning=*/false, /*jsonFormat=*/true, |
GcovInfo gcovInfo(/*employBinning=*/false, /*jsonFormat=*/true, |
122 |
|
/*intermediateFormat=*/true); |
|
|
122 |
|
/*intermediateFormat=*/true, /*stdOut=*/false); |
|
123 |
|
std::vector<File> files = |
|
124 |
|
GcovImporter(tempDirPath, tempDirPath, {}, tempDirPath, |
|
125 |
|
gcovInfo).getFiles(); |
|
126 |
|
|
|
127 |
|
REQUIRE(files.size() == 1); |
|
128 |
|
CHECK(files[0].getCoveredCount() == 1); |
|
129 |
|
CHECK(files[0].getMissedCount() == 1); |
|
130 |
|
} |
|
131 |
|
|
|
132 |
|
TEST_CASE("JSON on stdout is parsed", "[GcovImporter]") |
|
133 |
|
{ |
|
134 |
|
TempDir tempDir("gcovimporter"); |
|
135 |
|
std::string tempDirPath = tempDir; |
|
136 |
|
|
|
137 |
|
std::ofstream{tempDirPath + "/file.gcno"} << "\n"; |
|
138 |
|
|
|
139 |
|
auto runner = [&tempDirPath](std::vector<std::string> &&/*cmd*/, |
|
140 |
|
const std::string &from) { |
|
141 |
|
CHECK(from == "-"); |
|
142 |
|
|
|
143 |
|
std::string json = R"({ |
|
144 |
|
"current_working_directory": ")" + tempDirPath + R"(", |
|
145 |
|
"files": [ |
|
146 |
|
{ |
|
147 |
|
"file": "file.gcno", |
|
148 |
|
"lines": [ |
|
149 |
|
{ "line_number": 1, "count": 1 }, |
|
150 |
|
{ "line_number": 2, "count": 0 } |
|
151 |
|
] |
|
152 |
|
}, |
|
153 |
|
{ |
|
154 |
|
"file": "/usr/include/whatever.h", |
|
155 |
|
"lines": [ { "line_number": 1, "count": 1 } ] |
|
156 |
|
} |
|
157 |
|
] |
|
158 |
|
})"; |
|
159 |
|
removeChars(json, '\n'); |
|
160 |
|
|
|
161 |
|
return json; |
|
162 |
|
}; |
|
163 |
|
auto prevRunner = GcovImporter::setRunner(runner); |
|
164 |
|
BOOST_SCOPE_EXIT_ALL(prevRunner) { |
|
165 |
|
GcovImporter::setRunner(prevRunner); |
|
166 |
|
}; |
|
167 |
|
|
|
168 |
|
GcovInfo gcovInfo(/*employBinning=*/false, /*jsonFormat=*/true, |
|
169 |
|
/*intermediateFormat=*/true, /*stdOut=*/true); |
123 |
170 |
std::vector<File> files = |
std::vector<File> files = |
124 |
171 |
GcovImporter(tempDirPath, tempDirPath, {}, tempDirPath, |
GcovImporter(tempDirPath, tempDirPath, {}, tempDirPath, |
125 |
172 |
gcovInfo).getFiles(); |
gcovInfo).getFiles(); |