blob: 1721890557ce2f74b53d56de5b92d5bd02dddd29 [file] [log] [blame]
Martin Hořeňovský45a46572017-12-03 13:03:52 +01001#include <algorithm>
2#include <array>
3#include <cassert>
4#include <fstream>
5#include <iostream>
6#include <memory>
7#include <numeric>
8#include <regex>
9#include <string>
10#include <vector>
11
12
13void create_empty_file(std::string const& path) {
14 std::ofstream ofs(path);
15 ofs << '\n';
16}
17
18const std::string separator = "--sep--";
19const std::string logfile_prefix = "--log-file=";
20
21bool starts_with(std::string const& str, std::string const& pref) {
22 return str.find(pref) == 0;
23}
24
25int parse_log_file_arg(std::string const& arg) {
26 assert(starts_with(arg, logfile_prefix) && "Attempting to parse incorrect arg!");
27 auto fname = arg.substr(logfile_prefix.size());
28 create_empty_file(fname);
29 std::regex regex("MemoryChecker\\.(\\d+)\\.log", std::regex::icase);
30 std::smatch match;
31 if (std::regex_search(fname, match, regex)) {
32 return std::stoi(match[1]);
33 } else {
34 throw std::domain_error("Couldn't find desired expression in string: " + fname);
35 }
36}
37
38std::string catch_path(std::string path) {
39 auto start = path.find("catch");
40 // try capitalized instead
41 if (start == std::string::npos) {
42 start = path.find("Catch");
43 }
44 if (start == std::string::npos) {
45 throw std::domain_error("Couldn't find Catch's base path");
46 }
47 auto end = path.find_first_of("\\/", start);
48 return path.substr(0, end);
49}
50
51std::string windowsify_path(std::string path) {
52 for (auto& c : path) {
53 if (c == '/') {
54 c = '\\';
55 }
56 }
57 return path;
58}
59
60void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
61 std::array<char, 128> buffer;
62#if defined(_WIN32)
63 auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
64 + ".bin --quiet " + "--sources " + path + " --cover_children -- " + cmd;
65 std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
66 std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
67#else // Just for testing, in the real world we will always work under WIN32
68 (void)log_num; (void)path;
69 std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
70#endif
71
72 if (!pipe) {
73 throw std::runtime_error("popen() failed!");
74 }
75 while (!feof(pipe.get())) {
76 if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
77 std::cout << buffer.data();
78 }
79 }
80}
81
82// argv should be:
83// [0]: our path
84// [1]: "--log-file=<path>"
85// [2]: "--sep--"
86// [3]+: the actual command
87
88int main(int argc, char** argv) {
89 std::vector<std::string> args(argv, argv + argc);
90 auto sep = std::find(begin(args), end(args), separator);
91 assert(sep - begin(args) == 2 && "Structure differs from expected!");
92
93 auto num = parse_log_file_arg(args[1]);
94
95 auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
96 return lhs + ' ' + rhs;
97 });
98
Martin Hořeňovský2f15ccd2018-02-09 16:54:10 +010099 try {
100 return exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
101 } catch (std::exception const& ex) {
102 std::cerr << "Helper failed with: '" << ex.what() << "'\n";
103 return 12;
104 }
Martin Hořeňovský45a46572017-12-03 13:03:52 +0100105}