source: trunk/src/testlib/qxmltestlogger.cpp@ 1014

Last change on this file since 1014 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 13.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtTest module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <stdio.h>
43#include <string.h>
44#include <QtCore/qglobal.h>
45
46#include "QtTest/private/qxmltestlogger_p.h"
47#include "QtTest/private/qtestresult_p.h"
48#include "QtTest/private/qbenchmark_p.h"
49#include "QtTest/private/qbenchmarkmetric_p.h"
50#include "QtTest/qtestcase.h"
51
52QT_BEGIN_NAMESPACE
53
54namespace QTest {
55
56 static const char* xmlMessageType2String(QAbstractTestLogger::MessageTypes type)
57 {
58 switch (type) {
59 case QAbstractTestLogger::Warn:
60 return "warn";
61 case QAbstractTestLogger::QSystem:
62 return "system";
63 case QAbstractTestLogger::QDebug:
64 return "qdebug";
65 case QAbstractTestLogger::QWarning:
66 return "qwarn";
67 case QAbstractTestLogger::QFatal:
68 return "qfatal";
69 case QAbstractTestLogger::Skip:
70 return "skip";
71 case QAbstractTestLogger::Info:
72 return "info";
73 }
74 return "??????";
75 }
76
77 static const char* xmlIncidentType2String(QAbstractTestLogger::IncidentTypes type)
78 {
79 switch (type) {
80 case QAbstractTestLogger::Pass:
81 return "pass";
82 case QAbstractTestLogger::XFail:
83 return "xfail";
84 case QAbstractTestLogger::Fail:
85 return "fail";
86 case QAbstractTestLogger::XPass:
87 return "xpass";
88 }
89 return "??????";
90 }
91
92}
93
94
95QXmlTestLogger::QXmlTestLogger(XmlMode mode )
96 :xmlmode(mode)
97{
98
99}
100
101QXmlTestLogger::~QXmlTestLogger()
102{
103}
104
105void QXmlTestLogger::startLogging()
106{
107 QAbstractTestLogger::startLogging();
108 QTestCharBuffer buf;
109
110 if (xmlmode == QXmlTestLogger::Complete) {
111 QTestCharBuffer quotedTc;
112 xmlQuote(&quotedTc, QTestResult::currentTestObjectName());
113 QTest::qt_asprintf(&buf,
114 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
115 "<TestCase name=\"%s\">\n", quotedTc.constData());
116 outputString(buf.constData());
117 }
118
119 QTest::qt_asprintf(&buf,
120 "<Environment>\n"
121 " <QtVersion>%s</QtVersion>\n"
122 " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n"
123 "</Environment>\n", qVersion());
124 outputString(buf.constData());
125}
126
127void QXmlTestLogger::stopLogging()
128{
129 if (xmlmode == QXmlTestLogger::Complete) {
130 outputString("</TestCase>\n");
131 }
132
133 QAbstractTestLogger::stopLogging();
134}
135
136void QXmlTestLogger::enterTestFunction(const char *function)
137{
138 QTestCharBuffer buf;
139 QTestCharBuffer quotedFunction;
140 xmlQuote(&quotedFunction, function);
141 QTest::qt_asprintf(&buf, "<TestFunction name=\"%s\">\n", quotedFunction.constData());
142 outputString(buf.constData());
143}
144
145void QXmlTestLogger::leaveTestFunction()
146{
147 outputString("</TestFunction>\n");
148}
149
150namespace QTest
151{
152
153inline static bool isEmpty(const char *str)
154{
155 return !str || !str[0];
156}
157
158static const char *incidentFormatString(bool noDescription, bool noTag)
159{
160 if (noDescription) {
161 if (noTag)
162 return "<Incident type=\"%s\" file=\"%s\" line=\"%d\" />\n";
163 else
164 return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
165 " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
166 "</Incident>\n";
167 } else {
168 if (noTag)
169 return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
170 " <Description><![CDATA[%s%s%s%s]]></Description>\n"
171 "</Incident>\n";
172 else
173 return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
174 " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
175 " <Description><![CDATA[%s]]></Description>\n"
176 "</Incident>\n";
177 }
178}
179
180static const char *benchmarkResultFormatString()
181{
182 return "<BenchmarkResult metric=\"%s\" tag=\"%s\" value=\"%s\" iterations=\"%d\" />\n";
183}
184
185static const char *messageFormatString(bool noDescription, bool noTag)
186{
187 if (noDescription) {
188 if (noTag)
189 return "<Message type=\"%s\" file=\"%s\" line=\"%d\" />\n";
190 else
191 return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
192 " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
193 "</Message>\n";
194 } else {
195 if (noTag)
196 return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
197 " <Description><![CDATA[%s%s%s%s]]></Description>\n"
198 "</Message>\n";
199 else
200 return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
201 " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
202 " <Description><![CDATA[%s]]></Description>\n"
203 "</Message>\n";
204 }
205}
206
207} // namespace
208
209void QXmlTestLogger::addIncident(IncidentTypes type, const char *description,
210 const char *file, int line)
211{
212 QTestCharBuffer buf;
213 const char *tag = QTestResult::currentDataTag();
214 const char *gtag = QTestResult::currentGlobalDataTag();
215 const char *filler = (tag && gtag) ? ":" : "";
216 const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
217
218 QTestCharBuffer quotedFile;
219 QTestCharBuffer cdataGtag;
220 QTestCharBuffer cdataTag;
221 QTestCharBuffer cdataDescription;
222
223 xmlQuote(&quotedFile, file);
224 xmlCdata(&cdataGtag, gtag);
225 xmlCdata(&cdataTag, tag);
226 xmlCdata(&cdataDescription, description);
227
228 QTest::qt_asprintf(&buf,
229 QTest::incidentFormatString(QTest::isEmpty(description), notag),
230 QTest::xmlIncidentType2String(type),
231 quotedFile.constData(), line,
232 cdataGtag.constData(),
233 filler,
234 cdataTag.constData(),
235 cdataDescription.constData());
236
237 outputString(buf.constData());
238}
239
240void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
241{
242 QTestCharBuffer buf;
243 QTestCharBuffer quotedMetric;
244 QTestCharBuffer quotedTag;
245
246 xmlQuote(&quotedMetric,
247 benchmarkMetricName(result.metric));
248 xmlQuote(&quotedTag, result.context.tag.toAscii().constData());
249
250 QTest::qt_asprintf(
251 &buf,
252 QTest::benchmarkResultFormatString(),
253 quotedMetric.constData(),
254 quotedTag.constData(),
255 QByteArray::number(result.value).constData(), //no 64-bit qt_snprintf support
256 result.iterations);
257 outputString(buf.constData());
258}
259
260void QXmlTestLogger::addMessage(MessageTypes type, const char *message,
261 const char *file, int line)
262{
263 QTestCharBuffer buf;
264 const char *tag = QTestResult::currentDataTag();
265 const char *gtag = QTestResult::currentGlobalDataTag();
266 const char *filler = (tag && gtag) ? ":" : "";
267 const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
268
269 QTestCharBuffer quotedFile;
270 QTestCharBuffer cdataGtag;
271 QTestCharBuffer cdataTag;
272 QTestCharBuffer cdataDescription;
273
274 xmlQuote(&quotedFile, file);
275 xmlCdata(&cdataGtag, gtag);
276 xmlCdata(&cdataTag, tag);
277 xmlCdata(&cdataDescription, message);
278
279 QTest::qt_asprintf(&buf,
280 QTest::messageFormatString(QTest::isEmpty(message), notag),
281 QTest::xmlMessageType2String(type),
282 quotedFile.constData(), line,
283 cdataGtag.constData(),
284 filler,
285 cdataTag.constData(),
286 cdataDescription.constData());
287
288 outputString(buf.constData());
289}
290
291/*
292 Copy up to n characters from the src string into dest, escaping any special
293 XML characters as necessary so that dest is suitable for use in an XML
294 quoted attribute string.
295*/
296int QXmlTestLogger::xmlQuote(QTestCharBuffer* destBuf, char const* src, size_t n)
297{
298 if (n == 0) return 0;
299
300 char *dest = destBuf->data();
301 *dest = 0;
302 if (!src) return 0;
303
304 char* begin = dest;
305 char* end = dest + n;
306
307 while (dest < end) {
308 switch (*src) {
309
310#define MAP_ENTITY(chr, ent) \
311 case chr: \
312 if (dest + sizeof(ent) < end) { \
313 strcpy(dest, ent); \
314 dest += sizeof(ent) - 1; \
315 } \
316 else { \
317 *dest = 0; \
318 return (dest+sizeof(ent)-begin); \
319 } \
320 ++src; \
321 break;
322
323 MAP_ENTITY('>', "&gt;");
324 MAP_ENTITY('<', "&lt;");
325 MAP_ENTITY('\'', "&apos;");
326 MAP_ENTITY('"', "&quot;");
327 MAP_ENTITY('&', "&amp;");
328
329 // not strictly necessary, but allows handling of comments without
330 // having to explicitly look for `--'
331 MAP_ENTITY('-', "&#x002D;");
332
333#undef MAP_ENTITY
334
335 case 0:
336 *dest = 0;
337 return (dest-begin);
338
339 default:
340 *dest = *src;
341 ++dest;
342 ++src;
343 break;
344 }
345 }
346
347 // If we get here, dest was completely filled (dest == end)
348 *(dest-1) = 0;
349 return (dest-begin);
350}
351
352/*
353 Copy up to n characters from the src string into dest, escaping any
354 special strings such that dest is suitable for use in an XML CDATA section.
355*/
356int QXmlTestLogger::xmlCdata(QTestCharBuffer *destBuf, char const* src, size_t n)
357{
358 if (!n) return 0;
359
360 char *dest = destBuf->data();
361
362 if (!src || n == 1) {
363 *dest = 0;
364 return 0;
365 }
366
367 static char const CDATA_END[] = "]]>";
368 static char const CDATA_END_ESCAPED[] = "]]]><![CDATA[]>";
369
370 char* begin = dest;
371 char* end = dest + n;
372 while (dest < end) {
373 if (!*src) {
374 *dest = 0;
375 return (dest-begin);
376 }
377
378 if (!strncmp(src, CDATA_END, sizeof(CDATA_END)-1)) {
379 if (dest + sizeof(CDATA_END_ESCAPED) < end) {
380 strcpy(dest, CDATA_END_ESCAPED);
381 src += sizeof(CDATA_END)-1;
382 dest += sizeof(CDATA_END_ESCAPED) - 1;
383 }
384 else {
385 *dest = 0;
386 return (dest+sizeof(CDATA_END_ESCAPED)-begin);
387 }
388 continue;
389 }
390
391 *dest = *src;
392 ++src;
393 ++dest;
394 }
395
396 // If we get here, dest was completely filled (dest == end)
397 *(dest-1) = 0;
398 return (dest-begin);
399}
400
401typedef int (*StringFormatFunction)(QTestCharBuffer*,char const*,size_t);
402
403/*
404 A wrapper for string functions written to work with a fixed size buffer so they can be called
405 with a dynamically allocated buffer.
406*/
407int allocateStringFn(QTestCharBuffer* str, char const* src, StringFormatFunction func)
408{
409 static const int MAXSIZE = 1024*1024*2;
410
411 int size = str->size();
412
413 int res = 0;
414
415 for (;;) {
416 res = func(str, src, size);
417 str->data()[size - 1] = '\0';
418 if (res < size) {
419 // We succeeded or fatally failed
420 break;
421 }
422 // buffer wasn't big enough, try again
423 size *= 2;
424 if (size > MAXSIZE) {
425 break;
426 }
427 if (!str->reset(size))
428 break; // ran out of memory - bye
429 }
430
431 return res;
432}
433
434int QXmlTestLogger::xmlQuote(QTestCharBuffer* str, char const* src)
435{
436 return allocateStringFn(str, src, QXmlTestLogger::xmlQuote);
437}
438
439int QXmlTestLogger::xmlCdata(QTestCharBuffer* str, char const* src)
440{
441 return allocateStringFn(str, src, QXmlTestLogger::xmlCdata);
442}
443
444QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.