6#include <QtCore/qglobal.h>
7#include <QtCore/qlibraryinfo.h>
9#include <QtTest/private/qtestlog_p.h>
10#include <QtTest/private/qxmltestlogger_p.h>
11#include <QtTest/private/qtestresult_p.h>
12#include <QtTest/private/qbenchmark_p.h>
13#include <QtTest/private/qbenchmarkmetric_p.h>
14#include <QtTest/qtestcase.h>
23 case QAbstractTestLogger::QDebug:
25 case QAbstractTestLogger::QInfo:
27 case QAbstractTestLogger::QWarning:
29 case QAbstractTestLogger::QCritical:
31 case QAbstractTestLogger::QFatal:
33 case QAbstractTestLogger::Info:
35 case QAbstractTestLogger::Warn:
44 case QAbstractTestLogger::Skip:
46 case QAbstractTestLogger::Pass:
48 case QAbstractTestLogger::XFail:
50 case QAbstractTestLogger::Fail:
52 case QAbstractTestLogger::XPass:
54 case QAbstractTestLogger::BlacklistedPass:
56 case QAbstractTestLogger::BlacklistedFail:
58 case QAbstractTestLogger::BlacklistedXPass:
60 case QAbstractTestLogger::BlacklistedXFail:
69
70
71
72
73
74
75
77
78
79
80
81
82
83
84
85
86
87
89QXmlTestLogger::QXmlTestLogger(XmlMode mode,
const char *filename)
90 : QAbstractTestLogger(filename), xmlmode(mode)
94QXmlTestLogger::~QXmlTestLogger() =
default;
96void QXmlTestLogger::startLogging()
98 QAbstractTestLogger::startLogging();
101 if (xmlmode == QXmlTestLogger::Complete) {
102 QTestCharBuffer quotedTc;
103 QTest::qt_asprintf(&buf,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
104 outputString(buf.constData());
105 if (xmlQuote("edTc, QTestResult::currentTestObjectName())) {
106 QTest::qt_asprintf(&buf,
"<TestCase name=\"%s\">\n", quotedTc.constData());
107 outputString(buf.constData());
110 Q_ASSERT_X(
false,
"QXmlTestLogger::startLogging",
111 "Insanely long test-case name or OOM issue");
115 QTestCharBuffer quotedBuild;
116 if (!QLibraryInfo::build() || xmlQuote("edBuild, QLibraryInfo::build())) {
117 QTest::qt_asprintf(&buf,
119 " <QtVersion>%s</QtVersion>\n"
120 " <QtBuild>%s</QtBuild>\n"
121 " <QTestVersion>" QTEST_VERSION_STR
"</QTestVersion>\n"
122 " </Environment>\n", qVersion(), quotedBuild.constData());
123 outputString(buf.constData());
127void QXmlTestLogger::stopLogging()
131 QTest::qt_asprintf(&buf,
" <Duration msecs=\"%s\"/>\n",
132 QString::number(QTestLog::msecsTotalTime()).toUtf8().constData());
133 outputString(buf.constData());
134 if (xmlmode == QXmlTestLogger::Complete)
135 outputString(
"</TestCase>\n");
137 QAbstractTestLogger::stopLogging();
140void QXmlTestLogger::enterTestFunction(
const char *function)
142 QTestCharBuffer quotedFunction;
143 if (xmlQuote("edFunction, function)) {
145 QTest::qt_asprintf(&buf,
" <TestFunction name=\"%s\">\n", quotedFunction.constData());
146 outputString(buf.constData());
149 Q_ASSERT_X(
false,
"QXmlTestLogger::enterTestFunction",
150 "Insanely long test-function name or OOM issue");
154void QXmlTestLogger::leaveTestFunction()
157 QTest::qt_asprintf(&buf,
158 " <Duration msecs=\"%s\"/>\n"
159 " </TestFunction>\n",
160 QString::number(QTestLog::msecsFunctionTime()).toUtf8().constData());
162 outputString(buf.constData());
170 return !str || !str[0];
177 ?
" <Incident type=\"%s\" file=\"%s\" line=\"%d\" />\n"
178 :
" <Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
179 " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
183 ?
" <Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
184 " <Description><![CDATA[%s%s%s%s]]></Description>\n"
186 :
" <Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
187 " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
188 " <Description><![CDATA[%s]]></Description>\n"
194 return " <BenchmarkResult metric=\"%s\" tag=\"%s\" value=\"%.6g\" iterations=\"%d\" />\n";
201 return " <Message type=\"%s\" file=\"%s\" line=\"%d\" />\n";
203 return " <Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
204 " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
208 return " <Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
209 " <Description><![CDATA[%s%s%s%s]]></Description>\n"
212 return " <Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
213 " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
214 " <Description><![CDATA[%s]]></Description>\n"
221void QXmlTestLogger::addIncident(IncidentTypes type,
const char *description,
222 const char *file,
int line)
225 const char *tag = QTestResult::currentDataTag();
226 const char *gtag = QTestResult::currentGlobalDataTag();
227 const char *filler = (tag && gtag) ?
":" :
"";
228 const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
230 QTestCharBuffer quotedFile;
231 QTestCharBuffer cdataGtag;
232 QTestCharBuffer cdataTag;
233 QTestCharBuffer cdataDescription;
235 if (xmlQuote("edFile, file)
236 && xmlCdata(&cdataGtag, gtag)
237 && xmlCdata(&cdataTag, tag)
238 && xmlCdata(&cdataDescription, description)) {
240 QTest::qt_asprintf(&buf,
241 QTest::incidentFormatString(QTest::isEmpty(description), notag),
242 QTest::xmlIncidentType2String(type),
243 quotedFile.constData(), line,
244 cdataGtag.constData(),
246 cdataTag.constData(),
247 cdataDescription.constData());
249 outputString(buf.constData());
253void QXmlTestLogger::addBenchmarkResult(
const QBenchmarkResult &result)
255 QTestCharBuffer quotedMetric;
256 QTestCharBuffer quotedTag;
258 if (xmlQuote("edMetric, benchmarkMetricName(result.measurement.metric))
259 && xmlQuote("edTag, result.context.tag.toUtf8().constData())) {
261 QTest::qt_asprintf(&buf,
262 QTest::benchmarkResultFormatString(),
263 quotedMetric.constData(),
264 quotedTag.constData(),
265 result.measurement.value /
double(result.iterations),
267 outputString(buf.constData());
271void QXmlTestLogger::addMessage(MessageTypes type,
const QString &message,
272 const char *file,
int line)
275 const char *tag = QTestResult::currentDataTag();
276 const char *gtag = QTestResult::currentGlobalDataTag();
277 const char *filler = (tag && gtag) ?
":" :
"";
278 const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
280 QTestCharBuffer quotedFile;
281 QTestCharBuffer cdataGtag;
282 QTestCharBuffer cdataTag;
283 QTestCharBuffer cdataDescription;
285 if (xmlQuote("edFile, file)
286 && xmlCdata(&cdataGtag, gtag)
287 && xmlCdata(&cdataTag, tag)
288 && xmlCdata(&cdataDescription, message.toUtf8().constData())) {
289 QTest::qt_asprintf(&buf,
290 QTest::messageFormatString(message.isEmpty(), notag),
291 QTest::xmlMessageType2String(type),
292 quotedFile.constData(), line,
293 cdataGtag.constData(),
295 cdataTag.constData(),
296 cdataDescription.constData());
298 outputString(buf.constData());
302int QXmlTestLogger::xmlQuote(QTestCharBuffer *destBuf,
char const *src, qsizetype n)
306 Q_ASSERT(n >= 512 && destBuf->size() == n);
307 char *dest = destBuf->data();
315 char *end = dest + n;
320#define MAP_ENTITY(chr, ent)
322 if (dest + sizeof(ent) < end) {
324 dest += sizeof(ent) - 1
;
327 return dest + sizeof(ent) - begin;
357 Q_ASSERT(dest == end && end > begin);
362int QXmlTestLogger::xmlCdata(QTestCharBuffer *destBuf,
char const *src, qsizetype n)
364 Q_ASSERT(n >= 512 && destBuf->size() == n);
365 char *dest = destBuf->data();
372 static char const CDATA_END[] =
"]]>";
373 static char const CDATA_END_ESCAPED[] =
"]]]><![CDATA[]>";
374 const size_t CDATA_END_LEN =
sizeof(CDATA_END) - 1;
377 char *end = dest + n;
384 if (!strncmp(src, CDATA_END, CDATA_END_LEN)) {
385 if (dest +
sizeof(CDATA_END_ESCAPED) < end) {
386 strcpy(dest, CDATA_END_ESCAPED);
387 src += CDATA_END_LEN;
388 dest +=
sizeof(CDATA_END_ESCAPED) - 1;
391 return dest +
sizeof(CDATA_END_ESCAPED) - begin;
402 Q_ASSERT(dest == end && end > begin);
410
411
412
415 constexpr int MAXSIZE = 1024 * 1024 * 2;
416 int size = str->size();
417 Q_ASSERT(size >= 512 && !str->data()[0]);
420 const int res = func(str, src, size);
422 Q_ASSERT(res > 0 || (!res && (!src || !src[0])));
428 }
while (size <= MAXSIZE && str->reset(size));
434
435
436
437
438
439
440
441
442bool QXmlTestLogger::xmlQuote(QTestCharBuffer *str,
char const *src)
444 return allocateStringFn(str, src, QXmlTestLogger::xmlQuote);
448
449
450
451
452
453
454
455bool QXmlTestLogger::xmlCdata(QTestCharBuffer *str,
char const *src)
457 return allocateStringFn(str, src, QXmlTestLogger::xmlCdata);
static const char * xmlIncidentType2String(QAbstractTestLogger::IncidentTypes type)
static const char * incidentFormatString(bool noDescription, bool noTag)
static const char * benchmarkResultFormatString()
static bool isEmpty(const char *str)
static const char * xmlMessageType2String(QAbstractTestLogger::MessageTypes type)
static const char * messageFormatString(bool noDescription, bool noTag)
#define MAP_ENTITY(chr, ent)
static bool allocateStringFn(QTestCharBuffer *str, char const *src, StringFormatFunction func)
int(* StringFormatFunction)(QTestCharBuffer *, char const *, qsizetype)