1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtTest module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qtestlogger_p.h"
43 #include "qtestelement.h"
44 #include "qtestxunitstreamer.h"
45 #include "qtestxmlstreamer.h"
46 #include "qtestlightxmlstreamer.h"
47 #include "qtestfilelogger.h"
49 #include "QtTest/qtestcase.h"
50 #include "QtTest/private/qtestresult_p.h"
51 #include "QtTest/private/qbenchmark_p.h"
57 QTestLogger::QTestLogger(int fm
)
58 :listOfTestcases(0), currentLogElement(0), errorLogElement(0),
59 logFormatter(0), format( (TestLoggerFormat
)fm
), filelogger(new QTestFileLogger
),
60 testCounter(0), passCounter(0),
61 failureCounter(0), errorCounter(0),
62 warningCounter(0), skipCounter(0),
63 systemCounter(0), qdebugCounter(0),
64 qwarnCounter(0), qfatalCounter(0),
69 QTestLogger::~QTestLogger()
71 if(format
== TLF_XunitXml
)
72 delete currentLogElement
;
74 delete listOfTestcases
;
80 void QTestLogger::startLogging()
84 logFormatter
= new QTestLightXmlStreamer
;
88 logFormatter
= new QTestXmlStreamer
;
92 logFormatter
= new QTestXunitStreamer
;
93 delete errorLogElement
;
94 errorLogElement
= new QTestElement(QTest::LET_SystemError
);
100 logFormatter
->setLogger(this);
101 logFormatter
->startStreaming();
104 void QTestLogger::stopLogging()
106 QTestElement
*iterator
= listOfTestcases
;
108 if(format
== TLF_XunitXml
){
111 currentLogElement
= new QTestElement(QTest::LET_TestSuite
);
112 currentLogElement
->addAttribute(QTest::AI_Name
, QTestResult::currentTestObjectName());
114 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", testCounter
);
115 currentLogElement
->addAttribute(QTest::AI_Tests
, buf
);
117 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", failureCounter
);
118 currentLogElement
->addAttribute(QTest::AI_Failures
, buf
);
120 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", errorCounter
);
121 currentLogElement
->addAttribute(QTest::AI_Errors
, buf
);
123 QTestElement
*property
;
124 QTestElement
*properties
= new QTestElement(QTest::LET_Properties
);
126 property
= new QTestElement(QTest::LET_Property
);
127 property
->addAttribute(QTest::AI_Name
, "QTestVersion");
128 property
->addAttribute(QTest::AI_PropertyValue
, QTEST_VERSION_STR
);
129 properties
->addLogElement(property
);
131 property
= new QTestElement(QTest::LET_Property
);
132 property
->addAttribute(QTest::AI_Name
, "QtVersion");
133 property
->addAttribute(QTest::AI_PropertyValue
, qVersion());
134 properties
->addLogElement(property
);
136 currentLogElement
->addLogElement(properties
);
138 currentLogElement
->addLogElement(iterator
);
140 /* For correct indenting, make sure every testcase knows its parent */
141 QTestElement
* testcase
= iterator
;
143 testcase
->setParent(currentLogElement
);
144 testcase
= testcase
->nextElement();
147 currentLogElement
->addLogElement(errorLogElement
);
149 QTestElement
*it
= currentLogElement
;
150 logFormatter
->output(it
);
152 logFormatter
->output(iterator
);
155 logFormatter
->stopStreaming();
158 void QTestLogger::enterTestFunction(const char *function
)
161 QTest::qt_snprintf(buf
, sizeof(buf
), "Entered test-function: %s\n", function
);
162 filelogger
->flush(buf
);
164 currentLogElement
= new QTestElement(QTest::LET_TestCase
);
165 currentLogElement
->addAttribute(QTest::AI_Name
, function
);
166 currentLogElement
->addToList(&listOfTestcases
);
171 void QTestLogger::leaveTestFunction()
175 void QTestLogger::addIncident(IncidentTypes type
, const char *description
,
176 const char *file
, int line
)
178 const char *typeBuf
= 0;
182 case QAbstractTestLogger::XPass
:
186 case QAbstractTestLogger::Pass
:
190 case QAbstractTestLogger::XFail
:
194 case QAbstractTestLogger::Fail
:
203 if (type
== QAbstractTestLogger::Fail
|| type
== QAbstractTestLogger::XPass
204 || ((format
!= TLF_XunitXml
) && (type
== QAbstractTestLogger::XFail
))) {
205 QTestElement
*failureElement
= new QTestElement(QTest::LET_Failure
);
206 failureElement
->addAttribute(QTest::AI_Result
, typeBuf
);
208 failureElement
->addAttribute(QTest::AI_File
, file
);
210 failureElement
->addAttribute(QTest::AI_File
, "");
211 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", line
);
212 failureElement
->addAttribute(QTest::AI_Line
, buf
);
213 failureElement
->addAttribute(QTest::AI_Description
, description
);
214 const char* tag
= QTestResult::currentDataTag();
216 failureElement
->addAttribute(QTest::AI_Tag
, tag
);
218 currentLogElement
->addLogElement(failureElement
);
222 Only one result can be shown for the whole testfunction.
223 Check if we currently have a result, and if so, overwrite it
224 iff the new result is worse.
226 QTestElementAttribute
* resultAttr
=
227 const_cast<QTestElementAttribute
*>(currentLogElement
->attribute(QTest::AI_Result
));
229 const char* oldResult
= resultAttr
->value();
230 bool overwrite
= false;
231 if (!strcmp(oldResult
, "pass")) {
234 else if (!strcmp(oldResult
, "xfail")) {
235 overwrite
= (type
== QAbstractTestLogger::XPass
|| type
== QAbstractTestLogger::Fail
);
237 else if (!strcmp(oldResult
, "xpass")) {
238 overwrite
= (type
== QAbstractTestLogger::Fail
);
241 resultAttr
->setPair(QTest::AI_Result
, typeBuf
);
245 currentLogElement
->addAttribute(QTest::AI_Result
, typeBuf
);
249 currentLogElement
->addAttribute(QTest::AI_File
, file
);
251 currentLogElement
->addAttribute(QTest::AI_File
, "");
253 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", line
);
254 currentLogElement
->addAttribute(QTest::AI_Line
, buf
);
257 Since XFAIL does not add a failure to the testlog in xunitxml, add a message, so we still
258 have some information about the expected failure.
260 if (format
== TLF_XunitXml
&& type
== QAbstractTestLogger::XFail
) {
261 QTestLogger::addMessage(QAbstractTestLogger::Info
, description
, file
, line
);
265 void QTestLogger::addBenchmarkResult(const QBenchmarkResult
&result
)
267 QTestElement
*benchmarkElement
= new QTestElement(QTest::LET_Benchmark
);
268 // printf("element %i", benchmarkElement->elementType());
270 benchmarkElement
->addAttribute(
272 QTest::benchmarkMetricName(QBenchmarkTestMethodData::current
->result
.metric
));
273 benchmarkElement
->addAttribute(QTest::AI_Tag
, result
.context
.tag
.toAscii().data());
274 benchmarkElement
->addAttribute(QTest::AI_Value
, QByteArray::number(result
.value
).constData());
277 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", result
.iterations
);
278 benchmarkElement
->addAttribute(QTest::AI_Iterations
, buf
);
279 currentLogElement
->addLogElement(benchmarkElement
);
282 void QTestLogger::addMessage(MessageTypes type
, const char *message
, const char *file
, int line
)
284 QTestElement
*errorElement
= new QTestElement(QTest::LET_Error
);
285 const char *typeBuf
= 0;
288 case QAbstractTestLogger::Warn
:
292 case QAbstractTestLogger::QSystem
:
296 case QAbstractTestLogger::QDebug
:
300 case QAbstractTestLogger::QWarning
:
302 typeBuf
= "qwarning";
304 case QAbstractTestLogger::QFatal
:
308 case QAbstractTestLogger::Skip
:
312 case QAbstractTestLogger::Info
:
321 errorElement
->addAttribute(QTest::AI_Type
, typeBuf
);
322 errorElement
->addAttribute(QTest::AI_Description
, message
);
325 errorElement
->addAttribute(QTest::AI_File
, file
);
327 errorElement
->addAttribute(QTest::AI_File
, "");
330 QTest::qt_snprintf(buf
, sizeof(buf
), "%i", line
);
331 errorElement
->addAttribute(QTest::AI_Line
, buf
);
333 currentLogElement
->addLogElement(errorElement
);
336 // Also add the message to the system error log (i.e. stderr), if one exists
337 if (errorLogElement
) {
338 QTestElement
*systemErrorElement
= new QTestElement(QTest::LET_Error
);
339 systemErrorElement
->addAttribute(QTest::AI_Description
, message
);
340 errorLogElement
->addLogElement(systemErrorElement
);
344 void QTestLogger::setLogFormat(TestLoggerFormat fm
)
349 QTestLogger::TestLoggerFormat
QTestLogger::logFormat()
354 int QTestLogger::passCount() const
359 int QTestLogger::failureCount() const
361 return failureCounter
;
364 int QTestLogger::errorCount() const
369 int QTestLogger::warningCount() const
371 return warningCounter
;
374 int QTestLogger::skipCount() const
379 int QTestLogger::systemCount() const
381 return systemCounter
;
384 int QTestLogger::qdebugCount() const
386 return qdebugCounter
;
389 int QTestLogger::qwarnCount() const
394 int QTestLogger::qfatalCount() const
396 return qfatalCounter
;
399 int QTestLogger::infoCount() const