7 #include "../src/check.h"
10 #include "../src/benchmark_api_internal.h"
18 using TestCaseList = std::vector<TestCase>;
25 using SubMap = std::vector<std::pair<std::string, std::string>>;
34 SubMap& GetSubstitutions() {
36 static std::string safe_dec_re =
"[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
38 {
"%float",
"[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"},
40 {
"%hrfloat",
"[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"},
41 {
"%int",
"[ ]*[0-9]+"},
43 {
"%time",
"[ ]*[0-9]{1,5} ns"},
44 {
"%console_report",
"[ ]*[0-9]{1,5} ns [ ]*[0-9]{1,5} ns [ ]*[0-9]+"},
45 {
"%console_us_report",
"[ ]*[0-9] us [ ]*[0-9] us [ ]*[0-9]+"},
47 "name,iterations,real_time,cpu_time,time_unit,bytes_per_second,"
48 "items_per_second,label,error_occurred,error_message"},
49 {
"%csv_report",
"[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",ns,,,,,"},
50 {
"%csv_us_report",
"[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",us,,,,,"},
52 "[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",ns," + safe_dec_re +
",,,,"},
54 "[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",ns,," + safe_dec_re +
",,,"},
55 {
"%csv_bytes_items_report",
56 "[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",ns," + safe_dec_re +
57 "," + safe_dec_re +
",,,"},
58 {
"%csv_label_report_begin",
"[0-9]+," + safe_dec_re +
"," + safe_dec_re +
",ns,,,"},
59 {
"%csv_label_report_end",
",,"}};
64 SubMap
const& subs = GetSubstitutions();
65 using SizeT = std::string::size_type;
66 for (
auto const& KV : subs) {
69 while ((pos =
source.find(KV.first, next_start)) != std::string::npos) {
70 next_start = pos + KV.second.size();
71 source.replace(pos, KV.first.size(), KV.second);
77 void CheckCase(std::stringstream& remaining_output,
TestCase const& TC,
78 TestCaseList
const& not_checks) {
82 while (remaining_output.eof() ==
false) {
83 CHECK(remaining_output.good());
84 std::getline(remaining_output, line);
89 for (
const auto& NC : not_checks) {
90 CHECK(!NC.regex->Match(line))
91 <<
"Unexpected match for line \"" << line <<
"\" for MR_Not regex \""
92 << NC.regex_str <<
"\""
94 <<
"\n started matching near: " << first_line;
96 if (TC.
regex->Match(line))
return;
98 <<
"Expected line \"" << line <<
"\" to match regex \"" << TC.
regex_str
101 <<
"\n started matching near: " << first_line;
103 CHECK(remaining_output.eof() ==
false)
104 <<
"End of output reached before match for regex \"" << TC.
regex_str
107 <<
"\n started matching near: " << first_line;
110 void CheckCases(TestCaseList
const& checks, std::stringstream&
output) {
111 std::vector<TestCase> not_checks;
112 for (
size_t i = 0;
i < checks.size(); ++
i) {
113 const auto& TC = checks[
i];
115 not_checks.push_back(TC);
118 CheckCase(
output, TC, not_checks);
125 TestReporter(std::vector<benchmark::BenchmarkReporter*> reps)
128 virtual bool ReportContext(
const Context& context) {
129 bool last_ret =
false;
132 bool new_ret =
rep->ReportContext(context);
134 <<
"Reports return different values for ReportContext";
142 void ReportRuns(
const std::vector<Run>& report) {
206 auto start = std::ios::streampos(0);
216 bool on_first =
true;
217 while (
output.eof() ==
false) {
219 std::getline(
output, line);
229 VLOG(2) <<
"--------------------------------\n";
230 VLOG(2) <<
"checking for benchmarks matching " <<
p.regex_str <<
"...\n";
232 if(!
p.regex->Match(
r.name)) {
233 VLOG(2) <<
p.regex_str <<
" is not matched by " <<
r.name <<
"\n";
236 VLOG(2) <<
p.regex_str <<
" is matched by " <<
r.name <<
"\n";
238 VLOG(1) <<
"Checking results of " <<
r.name <<
": ... \n";
240 VLOG(1) <<
"Checking results of " <<
r.name <<
": OK.\n";
252 if(entry_csv_line.empty())
return;
258 for (
size_t i = 1, e = vals.size();
i < e; ++
i) {
265 std::vector< std::string > out;
266 if(line.empty())
return out;
268 size_t prev = 0, pos = line.find_first_of(
','), curr = pos;
269 while(pos != line.npos) {
271 if(line[prev] ==
'"') ++prev;
272 if(line[curr-1] ==
'"') --curr;
273 out.push_back(line.substr(prev, curr-prev));
275 pos = line.find_first_of(
',', pos + 1);
279 if(line[prev] ==
'"') ++prev;
280 if(line[curr-1] ==
'"') --curr;
281 out.push_back(line.substr(prev, curr-prev));
291 return rc.results.size();
295 auto pos =
name.find(
"/threads:");
296 if(pos ==
name.npos)
return 1;
297 auto end =
name.find(
'/', pos + 9);
298 std::stringstream ss;
299 ss <<
name.substr(pos + 9,
end);
308 const char *which_str =
which ==
kCpuTime ?
"cpu_time" :
"real_time";
309 double val = GetAs< double >(which_str);
310 auto unit =
Get(
"time_unit");
314 }
else if(*unit ==
"us") {
316 }
else if(*unit ==
"ms") {
318 }
else if(*unit ==
"s") {
321 CHECK(1 == 0) <<
"unknown time unit: " << *unit;
331 : regex_str(
std::move(re)),
333 substituted_regex(
internal::PerformSubstitutions(regex_str)),
339 <<
"\n originally \"" <<
regex_str <<
"\""
340 <<
"\n got error: " << err_str;
344 auto& L = internal::GetTestCaseList(ID);
345 L.insert(L.end(), il);
350 std::initializer_list<std::pair<std::string, std::string>> il) {
351 auto& subs = internal::GetSubstitutions();
354 KV.second = internal::PerformSubstitutions(KV.second);
355 for (
auto& EKV : subs) {
356 if (EKV.first == KV.first) {
357 EKV.second = std::move(KV.second);
362 if (!
exists) subs.push_back(std::move(KV));
368 using internal::GetTestCaseList;
374 struct ReporterTest {
376 std::vector<TestCase>& output_cases;
377 std::vector<TestCase>& error_cases;
379 std::stringstream out_stream;
380 std::stringstream err_stream;
382 ReporterTest(
const char*
n, std::vector<TestCase>& out_tc,
383 std::vector<TestCase>& err_tc,
385 :
name(
n), output_cases(out_tc), error_cases(err_tc), reporter(br) {
399 std::cout <<
"Running benchmarks...\n";
400 internal::TestReporter test_rep({&CR, &JR, &CSVR});
403 for (
auto& rep_test : TestCases) {
406 std::cout << banner << msg << banner <<
"\n";
408 std::cerr << rep_test.err_stream.str();
409 std::cout << rep_test.out_stream.str();
411 internal::CheckCases(rep_test.error_cases, rep_test.err_stream);
412 internal::CheckCases(rep_test.output_cases, rep_test.out_stream);
419 auto &csv = TestCases[2];
421 CHECK(std::strcmp(csv.name,
"CSVReporter") == 0);