diff options
Diffstat (limited to 'src/testlib/qxmltestlogger.cpp')
-rw-r--r-- | src/testlib/qxmltestlogger.cpp | 205 |
1 files changed, 168 insertions, 37 deletions
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index bba98da..0606ced 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -46,6 +46,7 @@ #include "QtTest/private/qxmltestlogger_p.h" #include "QtTest/private/qtestresult_p.h" #include "QtTest/private/qbenchmark_p.h" +#include "QtTest/qtestcase.h" QT_BEGIN_NAMESPACE @@ -90,27 +91,27 @@ namespace QTest { } -QXmlTestLogger::QXmlTestLogger(XmlMode mode ): - xmlmode(mode) +QXmlTestLogger::QXmlTestLogger(XmlMode mode ) + :xmlmode(mode) { } QXmlTestLogger::~QXmlTestLogger() { - } - void QXmlTestLogger::startLogging() { QAbstractTestLogger::startLogging(); char buf[1024]; if (xmlmode == QXmlTestLogger::Complete) { + char quotedTc[900]; + xmlQuote(quotedTc, QTestResult::currentTestObjectName(), sizeof(quotedTc)); QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" - "<TestCase name=\"%s\">\n", QTestResult::currentTestObjectName()); + "<TestCase name=\"%s\">\n", quotedTc); outputString(buf); } @@ -134,7 +135,9 @@ void QXmlTestLogger::stopLogging() void QXmlTestLogger::enterTestFunction(const char *function) { char buf[1024]; - QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", function); + char quotedFunction[950]; + xmlQuote(quotedFunction, function, sizeof(quotedFunction)); + QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", quotedFunction); outputString(buf); } @@ -158,18 +161,18 @@ static const char *incidentFormatString(bool noDescription, bool noTag) return "<Incident type=\"%s\" file=\"%s\" line=\"%d\" />\n"; else return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" - "</Incident>\n"; + " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" + "</Incident>\n"; } else { if (noTag) return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <Description><![CDATA[%s%s%s%s]]></Description>\n" - "</Incident>\n"; + " <Description><![CDATA[%s%s%s%s]]></Description>\n" + "</Incident>\n"; else return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" - " <Description><![CDATA[%s]]></Description>\n" - "</Incident>\n"; + " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Incident>\n"; } } @@ -185,40 +188,51 @@ static const char *messageFormatString(bool noDescription, bool noTag) return "<Message type=\"%s\" file=\"%s\" line=\"%d\" />\n"; else return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" - "</Message>\n"; + " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n" + "</Message>\n"; } else { if (noTag) return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <Description><![CDATA[%s%s%s%s]]></Description>\n" - "</Message>\n"; + " <Description><![CDATA[%s%s%s%s]]></Description>\n" + "</Message>\n"; else return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n" - " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" - " <Description><![CDATA[%s]]></Description>\n" - "</Message>\n"; + " <DataTag><![CDATA[%s%s%s]]></DataTag>\n" + " <Description><![CDATA[%s]]></Description>\n" + "</Message>\n"; } } } // namespace void QXmlTestLogger::addIncident(IncidentTypes type, const char *description, - const char *file, int line) + const char *file, int line) { - char buf[1536]; + // buffer must be large enough to hold all quoted/cdata buffers plus the format string itself + char buf[5000]; const char *tag = QTestResult::currentDataTag(); const char *gtag = QTestResult::currentGlobalDataTag(); const char *filler = (tag && gtag) ? ":" : ""; const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag); + char quotedFile[1024]; + char cdataGtag[1024]; + char cdataTag[1024]; + char cdataDescription[1024]; + + xmlQuote(quotedFile, file, sizeof(quotedFile)); + xmlCdata(cdataGtag, gtag, sizeof(cdataGtag)); + xmlCdata(cdataTag, tag, sizeof(cdataTag)); + xmlCdata(cdataDescription, description, sizeof(cdataDescription)); + QTest::qt_snprintf(buf, sizeof(buf), QTest::incidentFormatString(QTest::isEmpty(description), notag), QTest::xmlIncidentType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile, line, + cdataGtag, filler, - tag ? tag : "", - description ? description : ""); + cdataTag, + cdataDescription); outputString(buf); } @@ -226,39 +240,156 @@ void QXmlTestLogger::addIncident(IncidentTypes type, const char *description, void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result) { char buf[1536]; + char quotedMetric[64]; + char quotedTag[1024]; + + xmlQuote(quotedMetric, + QBenchmarkGlobalData::current->measurer->metricText().toAscii().constData(), + sizeof(quotedMetric)); + xmlQuote(quotedTag, result.context.tag.toAscii().constData(), sizeof(quotedTag)); + QTest::qt_snprintf( buf, sizeof(buf), QTest::benchmarkResultFormatString(), - QBenchmarkGlobalData::current->measurer->metricText().toAscii().data(), - result.context.tag.toAscii().data(), + quotedMetric, + quotedTag, QByteArray::number(result.value).constData(), //no 64-bit qt_snprintf support - result.iterations); + result.iterations); outputString(buf); } void QXmlTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line) { - char buf[1536]; - char msgbuf[1024]; + char buf[5000]; const char *tag = QTestResult::currentDataTag(); const char *gtag = QTestResult::currentGlobalDataTag(); const char *filler = (tag && gtag) ? ":" : ""; const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag); - QTest::qt_snprintf(msgbuf, sizeof(msgbuf), "%s", - message ? message : ""); + char quotedFile[1024]; + char cdataGtag[1024]; + char cdataTag[1024]; + char cdataDescription[1024]; + + xmlQuote(quotedFile, file, sizeof(quotedFile)); + xmlCdata(cdataGtag, gtag, sizeof(cdataGtag)); + xmlCdata(cdataTag, tag, sizeof(cdataTag)); + xmlCdata(cdataDescription, message, sizeof(cdataDescription)); QTest::qt_snprintf(buf, sizeof(buf), QTest::messageFormatString(QTest::isEmpty(message), notag), QTest::xmlMessageType2String(type), - file ? file : "", line, - gtag ? gtag : "", + quotedFile, line, + cdataGtag, filler, - tag ? tag : "", - msgbuf); + cdataTag, + cdataDescription); outputString(buf); } +/* + Copy up to n characters from the src string into dest, escaping any special + XML characters as necessary so that dest is suitable for use in an XML + quoted attribute string. +*/ +void QXmlTestLogger::xmlQuote(char* dest, char const* src, size_t n) +{ + if (n == 0) return; + + *dest = 0; + if (!src) return; + + char* end = dest + n; + + while (dest < end) { + switch (*src) { + +#define MAP_ENTITY(chr, ent) \ + case chr: \ + if (dest + sizeof(ent) < end) { \ + strcpy(dest, ent); \ + dest += sizeof(ent) - 1; \ + } \ + else { \ + *dest = 0; \ + return; \ + } \ + ++src; \ + break; + + MAP_ENTITY('>', ">"); + MAP_ENTITY('<', "<"); + MAP_ENTITY('\'', "'"); + MAP_ENTITY('"', """); + MAP_ENTITY('&', "&"); + + // not strictly necessary, but allows handling of comments without + // having to explicitly look for `--' + MAP_ENTITY('-', "-"); + +#undef MAP_ENTITY + + case 0: + *dest = 0; + return; + + default: + *dest = *src; + ++dest; + ++src; + break; + } + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; +} + +/* + Copy up to n characters from the src string into dest, escaping any + special strings such that dest is suitable for use in an XML CDATA section. +*/ +void QXmlTestLogger::xmlCdata(char* dest, char const* src, size_t n) +{ + if (!n) return; + + if (!src || n == 1) { + *dest = 0; + return; + } + + char const CDATA_END[] = "]]>"; + char const CDATA_END_ESCAPED[] = "]]]><![CDATA[]>"; + + char* end = dest + n; + while (dest < end) { + if (!*src) { + *dest = 0; + return; + } + + if (!strncmp(src, CDATA_END, sizeof(CDATA_END)-1)) { + if (dest + sizeof(CDATA_END_ESCAPED) < end) { + strcpy(dest, CDATA_END_ESCAPED); + src += sizeof(CDATA_END)-1; + dest += sizeof(CDATA_END_ESCAPED) - 1; + } + else { + *dest = 0; + return; + } + continue; + } + + *dest = *src; + ++src; + ++dest; + } + + // If we get here, dest was completely filled (dest == end) + *(dest-1) = 0; +} + QT_END_NAMESPACE |