20#ifndef WIN32_LEAN_AND_MEAN
21#define WIN32_LEAN_AND_MEAN
22#define UTPP_MUST_UNDEF_LEAN_AND_MEAN
27#define UTPP_MUST_UNDEF_NOMINMAX
32#ifdef UTPP_MUST_UNDEF_NOMINMAX
36#ifdef UTPP_MUST_UNDEF_LEAN_AND_MEAN
37#undef WIN32_LEAN_AND_MEAN
40#undef UTPP_MUST_UNDEF_LEAN_AND_MEAN
41#undef UTPP_MUST_UNDEF_NOMINMAX
51 explicit ReporterXml (std::ostream& ostream = std::cout);
54 void Clear ()
override;
62 std::string xml_escape (
const std::string& value);
63 std::string build_failure_message (
const std::string& file,
int line, std::string
const& message);
69 std::chrono::system_clock::time_point start_time;
74std::string ReporterXml::xml_escape (
const std::string& value)
77 std::string escaped = value;
78 auto replace_char = [&escaped] (
char c,
const char* repl){
79 for (
auto pos = escaped.find(c); pos != std::string::npos; pos = escaped.find(c, pos + 1))
80 escaped.replace(pos, 1, repl);
83 replace_char (
'&',
"&");
84 replace_char (
'<',
"<");
85 replace_char (
'>',
">");
86 replace_char (
'\'',
"'");
87 replace_char (
'\"',
""");
93std::string ReporterXml::build_failure_message (
const std::string& file,
int line, std::string
const& message)
95 std::ostringstream failureMessage;
96 failureMessage << file <<
"(" << line <<
") : " << message;
97 return failureMessage.str();
108 , orig_state (nullptr)
110 start_time = std::chrono::system_clock::now();
111 orig_state.copyfmt (os);
112 os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
120 using namespace std::chrono;
123 os.copyfmt (orig_state);
124 auto end_time = time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now ());
125 auto total_time_s = duration_cast<duration<float, std::chrono::seconds::period>>(
total_time);
127 os <<
"<utpp-results"
130 <<
" failures=\"" <<
total_failures_count <<
'\"' <<
" duration=\"" << std::fixed << std::setprecision (3)
131#if UTPP_STD_CHRONO_OSTREAM_AVAILABLE
132 << total_time_s <<
'\"'
134 << total_time_s.count() <<
"s\""
137#if defined(__cpp_lib_format)
138 auto start_time_sec = time_point_cast<std::chrono::seconds>(start_time);
139 os <<
" <start-time>" << std::format(
"{0:%F} {0:%T}Z", start_time_sec) <<
"</start-time>" << std::endl;
143 time_t t = system_clock::to_time_t (start_time);
144 timeinfo = gmtime (&t);
145 strftime (buffer,
sizeof(buffer),
"%F %TZ", timeinfo);
146 os <<
" <start-time>" << buffer <<
"</start-time>" << std::endl;
151 std::wstring wcmd{ GetCommandLineW () };
152 int nsz = WideCharToMultiByte (CP_UTF8, 0, wcmd.c_str (), -1, 0, 0, 0, 0);
156 WideCharToMultiByte (CP_UTF8, 0, wcmd.c_str (), -1, &cmd[0], nsz, 0, 0);
157 cmd.resize (nsz - 1);
159 os <<
" <command-line>" << xml_escape (cmd) <<
"</command-line>" << std::endl;
161 std::ifstream cmd_stream(
"/proc/self/cmdline");
162 if (cmd_stream.good ())
165 std::getline(cmd_stream, cmd,
'\0');
166 os <<
" <command-line>" << xml_escape (cmd) <<
"</command-line>" << std::endl;
172 if (i->test_name.empty ())
175 os <<
" </suite>" << std::endl;
176 suite = i->suite_name;
180 os <<
" <suite name=\"" << suite <<
'\"';
181 if ((i + 1) ==
results.cend () || (i + 1)->test_name.empty ())
187 os <<
'>' << std::endl;
193 if (!i->failures.empty ())
200 os <<
" </suite>" << std::endl;
201#if defined(__cpp_lib_format)
202 os <<
" <end-time>" << std::format (
"{0:%F} {0:%T}Z", end_time) <<
"</end-time>" << std::endl;
204 t = system_clock::to_time_t (end_time);
205 timeinfo = gmtime (&t);
206 strftime (buffer,
sizeof (buffer),
"%F %TZ", timeinfo);
207 os <<
" <end-time>" << buffer <<
"</end-time>" << std::endl;
209 os <<
"</utpp-results>" << std::endl;
217 os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
218 start_time = std::chrono::system_clock::now();
227 <<
" name=\"" << result.
test_name <<
"\""
228#if UTPP_STD_CHRONO_OSTREAM_AVAILABLE
229 <<
" time=\"" << result.
test_time <<
"\"";
231 <<
" time=\"" << result.
test_time.count() <<
"ms\"";
236void ReporterXml::EndTest (
const ReporterDeferred::TestResult& result)
238 if (result.failures.empty ())
249 os <<
">" << std::endl;
251 for (
auto& fail : result.failures)
253 std::string escapedMessage = xml_escape (fail.message);
254 std::string message = build_failure_message (fail.filename, fail.line_number, escapedMessage);
256 os <<
" <failure" <<
" message=\"" << message <<
"\"" <<
"/>" << std::endl;
void Clear() override
Reset all statistics.
Definition utpp.h:709
std::deque< TestResult > results
Results of all tests.
Definition utpp.h:352
int total_failures_count
total number of failures
Definition utpp.h:320
std::chrono::milliseconds total_time
total running time in milliseconds
Definition utpp.h:321
int total_test_count
total number of tests
Definition utpp.h:318
virtual int Summary()
Generate results report.
Definition utpp.h:307
int total_failed_count
total number of failed tests
Definition utpp.h:319
int Summary() override
Generate XML report.
Definition reporter_xml.h:118
void Clear() override
Reset all statistics.
Definition reporter_xml.h:214
ReporterXml(std::ostream &ostream=std::cout)
Definition reporter_xml.h:106
Test results including all failure messages
Definition utpp.h:342
std::string test_name
test name
Definition utpp.h:347
std::chrono::milliseconds test_time
test running time in milliseconds
Definition utpp.h:348
#define DEFAULT_SUITE
Name of default suite.
Definition utpp.h:64