@@ -13,10 +13,31 @@ namespace CppSpec::Formatters {
13
13
// JUnit XML header
14
14
constexpr static auto junit_xml_header = R"( <?xml version="1.0" encoding="UTF-8"?>)" ;
15
15
16
- struct XMLSerializable {
17
- virtual ~XMLSerializable () = default ;
18
- [[nodiscard]] virtual std::string to_xml () const = 0;
19
- };
16
+ inline std::string encode_xml (const std::string& data) {
17
+ std::string buffer;
18
+ for (char c : data) {
19
+ switch (c) {
20
+ case ' <' :
21
+ buffer += " <" ;
22
+ break ;
23
+ case ' >' :
24
+ buffer += " >" ;
25
+ break ;
26
+ case ' &' :
27
+ buffer += " &" ;
28
+ break ;
29
+ case ' "' :
30
+ buffer += " "" ;
31
+ break ;
32
+ case ' \' ' :
33
+ buffer += " '" ;
34
+ break ;
35
+ default :
36
+ buffer += c;
37
+ }
38
+ }
39
+ return buffer;
40
+ }
20
41
21
42
namespace JUnitNodes {
22
43
struct Result {
@@ -42,8 +63,8 @@ struct Result {
42
63
}
43
64
44
65
[[nodiscard]] std::string to_xml () const {
45
- return std::format (R"( <{} message="{}" type="{}">{}</{}>)" , status_string (), message, type, text ,
46
- status_string ());
66
+ return std::format (R"( <{} message="{}" type="{}">{}</{}>)" , status_string (), encode_xml ( message) ,
67
+ encode_xml (type), encode_xml (text), status_string ());
47
68
}
48
69
};
49
70
@@ -58,8 +79,8 @@ struct TestCase {
58
79
59
80
[[nodiscard]] std::string to_xml () const {
60
81
auto start =
61
- std::format (R"( <testcase name="{}" classname="{}" assertions="{}" time="{:f}" file="{}" line="{}")" , name,
62
- classname, assertions, time.count (), file, line);
82
+ std::format (R"( <testcase name="{}" classname="{}" assertions="{}" time="{:f}" file="{}" line="{}")" ,
83
+ encode_xml (name), encode_xml ( classname) , assertions, time.count (), file, line);
63
84
if (results.empty ()) {
64
85
return start + " />" ;
65
86
}
@@ -99,10 +120,10 @@ struct TestSuite {
99
120
100
121
std::stringstream ss;
101
122
ss << " "
102
- << std::format (R"( <testsuite id="{}" name="{}" time="{:f}" timestamp="{}" tests="{}" failures="{}">)" , id, name,
103
- time.count (), timestamp_str, tests, failures);
123
+ << std::format (R"( <testsuite id="{}" name="{}" time="{:f}" timestamp="{}" tests="{}" failures="{}">)" , id,
124
+ encode_xml (name), time.count (), timestamp_str, tests, failures);
104
125
ss << std::endl;
105
- for (const auto & test_case : cases) {
126
+ for (const TestCase & test_case : cases) {
106
127
ss << test_case.to_xml () << std::endl;
107
128
}
108
129
ss << " </testsuite>" ;
@@ -127,8 +148,8 @@ struct TestSuites {
127
148
[[nodiscard]] std::string to_xml () const {
128
149
std::stringstream ss;
129
150
auto timestamp_str = std::format (" {0:%F}T{0:%T}" , timestamp);
130
- ss << std::format (R"( <testsuites name="{}" tests="{}" failures="{}" time="{:f}" timestamp="{}">)" , name, tests ,
131
- failures, time.count (), timestamp_str);
151
+ ss << std::format (R"( <testsuites name="{}" tests="{}" failures="{}" time="{:f}" timestamp="{}">)" , encode_xml ( name) ,
152
+ tests, failures, time.count (), timestamp_str);
132
153
ss << std::endl;
133
154
for (const TestSuite& suite : suites) {
134
155
ss << suite.to_xml () << std::endl;
0 commit comments