Fix binary incompatibility between openssl versions
[profile/ivi/qtbase.git] / src / testlib / qxunittestlogger.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtTest module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/private/qxunittestlogger_p.h>
43 #include <QtTest/private/qtestelement_p.h>
44 #include <QtTest/private/qtestxunitstreamer_p.h>
45 #include <QtTest/qtestcase.h>
46 #include <QtTest/private/qtestresult_p.h>
47 #include <QtTest/private/qbenchmark_p.h>
48
49 #include <string.h>
50
51 QT_BEGIN_NAMESPACE
52
53 QXunitTestLogger::QXunitTestLogger(const char *filename)
54     : QAbstractTestLogger(filename)
55     , listOfTestcases(0)
56     , currentLogElement(0)
57     , errorLogElement(0)
58     , logFormatter(0)
59     , testCounter(0)
60     , failureCounter(0)
61     , errorCounter(0)
62 {
63 }
64
65 QXunitTestLogger::~QXunitTestLogger()
66 {
67     delete currentLogElement;
68     delete logFormatter;
69 }
70
71 void QXunitTestLogger::startLogging()
72 {
73     QAbstractTestLogger::startLogging();
74
75     logFormatter = new QTestXunitStreamer(this);
76     delete errorLogElement;
77     errorLogElement = new QTestElement(QTest::LET_SystemError);
78 }
79
80 void QXunitTestLogger::stopLogging()
81 {
82     QTestElement *iterator = listOfTestcases;
83
84     char buf[10];
85
86     currentLogElement = new QTestElement(QTest::LET_TestSuite);
87     currentLogElement->addAttribute(QTest::AI_Name, QTestResult::currentTestObjectName());
88
89     qsnprintf(buf, sizeof(buf), "%i", testCounter);
90     currentLogElement->addAttribute(QTest::AI_Tests, buf);
91
92     qsnprintf(buf, sizeof(buf), "%i", failureCounter);
93     currentLogElement->addAttribute(QTest::AI_Failures, buf);
94
95     qsnprintf(buf, sizeof(buf), "%i", errorCounter);
96     currentLogElement->addAttribute(QTest::AI_Errors, buf);
97
98     QTestElement *property;
99     QTestElement *properties = new QTestElement(QTest::LET_Properties);
100
101     property = new QTestElement(QTest::LET_Property);
102     property->addAttribute(QTest::AI_Name, "QTestVersion");
103     property->addAttribute(QTest::AI_PropertyValue, QTEST_VERSION_STR);
104     properties->addLogElement(property);
105
106     property = new QTestElement(QTest::LET_Property);
107     property->addAttribute(QTest::AI_Name, "QtVersion");
108     property->addAttribute(QTest::AI_PropertyValue, qVersion());
109     properties->addLogElement(property);
110
111     currentLogElement->addLogElement(properties);
112
113     currentLogElement->addLogElement(iterator);
114
115     /* For correct indenting, make sure every testcase knows its parent */
116     QTestElement* testcase = iterator;
117     while (testcase) {
118         testcase->setParent(currentLogElement);
119         testcase = testcase->nextElement();
120     }
121
122     currentLogElement->addLogElement(errorLogElement);
123
124     QTestElement *it = currentLogElement;
125     logFormatter->output(it);
126
127     QAbstractTestLogger::stopLogging();
128 }
129
130 void QXunitTestLogger::enterTestFunction(const char *function)
131 {
132     currentLogElement = new QTestElement(QTest::LET_TestCase);
133     currentLogElement->addAttribute(QTest::AI_Name, function);
134     currentLogElement->addToList(&listOfTestcases);
135
136     ++testCounter;
137 }
138
139 void QXunitTestLogger::leaveTestFunction()
140 {
141 }
142
143 void QXunitTestLogger::addIncident(IncidentTypes type, const char *description,
144                                    const char *file, int line)
145 {
146     const char *typeBuf = 0;
147     char buf[100];
148
149     switch (type) {
150     case QAbstractTestLogger::XPass:
151         ++failureCounter;
152         typeBuf = "xpass";
153         break;
154     case QAbstractTestLogger::Pass:
155         typeBuf = "pass";
156         break;
157     case QAbstractTestLogger::XFail:
158         typeBuf = "xfail";
159         break;
160     case QAbstractTestLogger::Fail:
161         ++failureCounter;
162         typeBuf = "fail";
163         break;
164     default:
165         typeBuf = "??????";
166         break;
167     }
168
169     if (type == QAbstractTestLogger::Fail || type == QAbstractTestLogger::XPass) {
170         QTestElement *failureElement = new QTestElement(QTest::LET_Failure);
171         failureElement->addAttribute(QTest::AI_Result, typeBuf);
172         if (file)
173             failureElement->addAttribute(QTest::AI_File, file);
174         else
175             failureElement->addAttribute(QTest::AI_File, "");
176         qsnprintf(buf, sizeof(buf), "%i", line);
177         failureElement->addAttribute(QTest::AI_Line, buf);
178         failureElement->addAttribute(QTest::AI_Description, description);
179         addTag(failureElement);
180         currentLogElement->addLogElement(failureElement);
181     }
182
183     /*
184         Only one result can be shown for the whole testfunction.
185         Check if we currently have a result, and if so, overwrite it
186         iff the new result is worse.
187     */
188     QTestElementAttribute* resultAttr =
189         const_cast<QTestElementAttribute*>(currentLogElement->attribute(QTest::AI_Result));
190     if (resultAttr) {
191         const char* oldResult = resultAttr->value();
192         bool overwrite = false;
193         if (!strcmp(oldResult, "pass")) {
194             overwrite = true;
195         }
196         else if (!strcmp(oldResult, "xfail")) {
197             overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail);
198         }
199         else if (!strcmp(oldResult, "xpass")) {
200             overwrite = (type == QAbstractTestLogger::Fail);
201         }
202         if (overwrite) {
203             resultAttr->setPair(QTest::AI_Result, typeBuf);
204         }
205     }
206     else {
207         currentLogElement->addAttribute(QTest::AI_Result, typeBuf);
208     }
209
210     if (file)
211         currentLogElement->addAttribute(QTest::AI_File, file);
212     else
213         currentLogElement->addAttribute(QTest::AI_File, "");
214
215     qsnprintf(buf, sizeof(buf), "%i", line);
216     currentLogElement->addAttribute(QTest::AI_Line, buf);
217
218     /*
219         Since XFAIL does not add a failure to the testlog in xunitxml, add a message, so we still
220         have some information about the expected failure.
221     */
222     if (type == QAbstractTestLogger::XFail) {
223         QXunitTestLogger::addMessage(QAbstractTestLogger::Info, description, file, line);
224     }
225 }
226
227 void QXunitTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
228 {
229     QTestElement *benchmarkElement = new QTestElement(QTest::LET_Benchmark);
230
231     benchmarkElement->addAttribute(
232         QTest::AI_Metric,
233         QTest::benchmarkMetricName(QBenchmarkTestMethodData::current->result.metric));
234     benchmarkElement->addAttribute(QTest::AI_Tag, result.context.tag.toUtf8().data());
235     benchmarkElement->addAttribute(QTest::AI_Value, QByteArray::number(result.value).constData());
236
237     char buf[100];
238     qsnprintf(buf, sizeof(buf), "%i", result.iterations);
239     benchmarkElement->addAttribute(QTest::AI_Iterations, buf);
240     currentLogElement->addLogElement(benchmarkElement);
241 }
242
243 void QXunitTestLogger::addTag(QTestElement* element)
244 {
245     const char *tag = QTestResult::currentDataTag();
246     const char *gtag = QTestResult::currentGlobalDataTag();
247     const char *filler = (tag && gtag) ? ":" : "";
248     if ((!tag || !tag[0]) && (!gtag || !gtag[0])) {
249         return;
250     }
251
252     if (!tag) {
253         tag = "";
254     }
255     if (!gtag) {
256         gtag = "";
257     }
258
259     QTestCharBuffer buf;
260     QTest::qt_asprintf(&buf, "%s%s%s", gtag, filler, tag);
261     element->addAttribute(QTest::AI_Tag, buf.constData());
262 }
263
264 void QXunitTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line)
265 {
266     QTestElement *errorElement = new QTestElement(QTest::LET_Error);
267     const char *typeBuf = 0;
268
269     switch (type) {
270     case QAbstractTestLogger::Warn:
271         typeBuf = "warn";
272         break;
273     case QAbstractTestLogger::QSystem:
274         typeBuf = "system";
275         break;
276     case QAbstractTestLogger::QDebug:
277         typeBuf = "qdebug";
278         break;
279     case QAbstractTestLogger::QWarning:
280         typeBuf = "qwarn";
281         break;
282     case QAbstractTestLogger::QFatal:
283         typeBuf = "qfatal";
284         break;
285     case QAbstractTestLogger::Skip:
286         typeBuf = "skip";
287         break;
288     case QAbstractTestLogger::Info:
289         typeBuf = "info";
290         break;
291     default:
292         typeBuf = "??????";
293         break;
294     }
295
296     errorElement->addAttribute(QTest::AI_Type, typeBuf);
297     errorElement->addAttribute(QTest::AI_Description, message);
298     addTag(errorElement);
299
300     if (file)
301         errorElement->addAttribute(QTest::AI_File, file);
302     else
303         errorElement->addAttribute(QTest::AI_File, "");
304
305     char buf[100];
306     qsnprintf(buf, sizeof(buf), "%i", line);
307     errorElement->addAttribute(QTest::AI_Line, buf);
308
309     currentLogElement->addLogElement(errorElement);
310     ++errorCounter;
311
312     // Also add the message to the system error log (i.e. stderr), if one exists
313     if (errorLogElement) {
314         QTestElement *systemErrorElement = new QTestElement(QTest::LET_Error);
315         systemErrorElement->addAttribute(QTest::AI_Description, message);
316         errorLogElement->addLogElement(systemErrorElement);
317     }
318 }
319
320 QT_END_NAMESPACE
321