Skip to content

Commit 817f9ef

Browse files
yahayaohinoyifacebook-github-bot
authored andcommitted
Listing should also output to json
Summary: The changes made before this diff in this stack, outputs executiont in json, this outputs listing in json as well Reviewed By: patskovn Differential Revision: D77318078 fbshipit-source-id: a2dbc7384f93f0f50984990a0ac980560105a087
1 parent 6e57f19 commit 817f9ef

File tree

2 files changed

+139
-2
lines changed

2 files changed

+139
-2
lines changed

fatal/test/driver.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,36 @@ int main(
6464
auto printer = fatal::test::default_printer{std::cout};
6565
return fatal::test::list(printer);
6666
}
67+
6768
auto const iter_gtest_list = opts.find(arg_gtest_list);
6869
if (iter_gtest_list != opts.end()) {
69-
auto printer = fatal::test::gtest_printer{std::cout};
70-
return fatal::test::list(printer);
70+
auto const iter_arg_output = opts.find(arg_gtest_output);
71+
auto const iter_env_output = envs.find(env_gtest_output);
72+
auto const &empty = std::string("");
73+
auto const &outspec =
74+
iter_arg_output != opts.end() ? iter_arg_output->second :
75+
iter_env_output != envs.end() ? iter_env_output->second :
76+
empty;
77+
78+
if (!outspec.empty() && outspec.find(xml_) != 0 && outspec.find(json_) != 0) {
79+
std::cerr << "error: gtest-output value requires prefix xml: or json:" << std::endl;
80+
return 1;
81+
}
82+
83+
if (outspec.empty()) {
84+
auto printer = fatal::test::gtest_printer{std::cout};
85+
return fatal::test::list(printer);
86+
}
87+
88+
if (outspec.find(json_) == 0) {
89+
std::ofstream out{outspec.substr(json_.size())};
90+
auto printer = fatal::test::gtest_json_list_printer{out};
91+
return fatal::test::list(printer);
92+
} else if (outspec.find(xml_) == 0) {
93+
// XML listing not implemented yet, fall back to regular gtest printer
94+
auto printer = fatal::test::gtest_printer{std::cout};
95+
return fatal::test::list(printer);
96+
}
7197
}
7298

7399
auto const iter_filter = opts.find(arg_filter);

fatal/test/test.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,117 @@ struct gtest_json_printer {
15761576
suite_list_info suite_list;
15771577
};
15781578

1579+
struct gtest_json_list_printer {
1580+
private:
1581+
struct test_info {
1582+
std::string name;
1583+
std::string file;
1584+
std::size_t line;
1585+
};
1586+
struct suite_info {
1587+
std::string name;
1588+
std::vector<test_info> tests;
1589+
};
1590+
std::vector<suite_info> suites;
1591+
1592+
public:
1593+
explicit gtest_json_list_printer(std::ostream &out_) : out{out_} {}
1594+
1595+
template <typename TGroup>
1596+
void list_start_group(TGroup const &group) {
1597+
suites.emplace_back();
1598+
auto &suite = suites.back();
1599+
suite.name = group;
1600+
}
1601+
1602+
template <typename TGroup, typename TName>
1603+
void list_entry(TGroup const &, TName const &name) {
1604+
auto &suite = suites.back();
1605+
suite.tests.emplace_back();
1606+
auto &test = suite.tests.back();
1607+
test.name = name;
1608+
// Note: file and line info not available in current listing interface
1609+
test.file = "";
1610+
test.line = 0;
1611+
}
1612+
1613+
template <typename TGroup>
1614+
void list_end_group(TGroup const &) {
1615+
// Nothing to do here
1616+
}
1617+
1618+
~gtest_json_list_printer() {
1619+
emit_json();
1620+
}
1621+
1622+
private:
1623+
static std::string json_escape(std::string const &text) {
1624+
std::ostringstream escaped;
1625+
for (char c : text) {
1626+
switch (c) {
1627+
case '"': escaped << "\\\""; break;
1628+
case '\\': escaped << "\\\\"; break;
1629+
case '\b': escaped << "\\b"; break;
1630+
case '\f': escaped << "\\f"; break;
1631+
case '\n': escaped << "\\n"; break;
1632+
case '\r': escaped << "\\r"; break;
1633+
case '\t': escaped << "\\t"; break;
1634+
default:
1635+
if (c >= 0 && c < 32) {
1636+
escaped << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
1637+
} else {
1638+
escaped << c;
1639+
}
1640+
break;
1641+
}
1642+
}
1643+
return escaped.str();
1644+
}
1645+
1646+
static std::string json_quote(std::string const &text) {
1647+
return "\"" + json_escape(text) + "\"";
1648+
}
1649+
1650+
void emit_json() {
1651+
out << "{\n";
1652+
out << " \"testsuites\": [";
1653+
1654+
bool first_suite = true;
1655+
for (auto const &suite : suites) {
1656+
if (!first_suite) {
1657+
out << ",";
1658+
}
1659+
out << "\n {\n";
1660+
out << " \"name\": " << json_quote(suite.name) << ",\n";
1661+
out << " \"testsuite\": [";
1662+
1663+
bool first_test = true;
1664+
for (auto const &test : suite.tests) {
1665+
if (!first_test) {
1666+
out << ",";
1667+
}
1668+
out << "\n {\n";
1669+
out << " \"name\": " << json_quote(test.name);
1670+
if (!test.file.empty()) {
1671+
out << ",\n \"file\": " << json_quote(test.file);
1672+
}
1673+
if (test.line > 0) {
1674+
out << ",\n \"line\": " << test.line;
1675+
}
1676+
out << "\n }";
1677+
first_test = false;
1678+
}
1679+
out << "\n ]\n";
1680+
out << " }";
1681+
first_suite = false;
1682+
}
1683+
out << "\n ]\n";
1684+
out << "}\n";
1685+
}
1686+
1687+
std::ostream &out;
1688+
};
1689+
15791690
struct gtest_xml_printer {
15801691
private:
15811692
struct case_info {

0 commit comments

Comments
 (0)