Remove code related to test location.
[profile/ivi/qtdeclarative.git] / src / qmltest / quicktestresult.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "quicktestresult_p.h"
43 #include <QtTest/qtestcase.h>
44 #include <QtTest/qtestsystem.h>
45 #include <QtTest/private/qtestresult_p.h>
46 #include <QtTest/private/qtesttable_p.h>
47 #include <QtTest/private/qtestlog_p.h>
48 #include "qtestoptions_p.h"
49 #include <QtTest/qbenchmark.h>
50 #include <QtTest/private/qbenchmark_p.h>
51 #include <QtCore/qset.h>
52 #include <QtCore/qmap.h>
53 #include <QtCore/qbytearray.h>
54 #include <QtCore/qcoreapplication.h>
55 #include <QtCore/qdebug.h>
56 #include <QtCore/QUrl>
57 #include <QtCore/QDir>
58
59 QT_BEGIN_NAMESPACE
60
61 static const char *globalProgramName = 0;
62 static bool loggingStarted = false;
63 static QBenchmarkGlobalData globalBenchmarkData;
64
65 class QuickTestResultPrivate
66 {
67 public:
68     QuickTestResultPrivate()
69         : table(0)
70         , benchmarkIter(0)
71         , benchmarkData(0)
72         , iterCount(0)
73     {
74     }
75     ~QuickTestResultPrivate()
76     {
77         delete table;
78         delete benchmarkIter;
79         delete benchmarkData;
80     }
81
82     QByteArray intern(const QString &str);
83
84     QString testCaseName;
85     QString functionName;
86     QSet<QByteArray> internedStrings;
87     QTestTable *table;
88     QTest::QBenchmarkIterationController *benchmarkIter;
89     QBenchmarkTestMethodData *benchmarkData;
90     int iterCount;
91     QList<QBenchmarkResult> results;
92 };
93
94 QByteArray QuickTestResultPrivate::intern(const QString &str)
95 {
96     QByteArray bstr = str.toUtf8();
97     return *(internedStrings.insert(bstr));
98 }
99
100 QuickTestResult::QuickTestResult(QObject *parent)
101     : QObject(parent), d_ptr(new QuickTestResultPrivate)
102 {
103     if (!QBenchmarkGlobalData::current)
104         QBenchmarkGlobalData::current = &globalBenchmarkData;
105 }
106
107 QuickTestResult::~QuickTestResult()
108 {
109 }
110
111 /*!
112     \qmlproperty string TestResult::testCaseName
113
114     This property defines the name of current TestCase element
115     that is running test cases.
116
117     \sa functionName
118 */
119 QString QuickTestResult::testCaseName() const
120 {
121     Q_D(const QuickTestResult);
122     return d->testCaseName;
123 }
124
125 void QuickTestResult::setTestCaseName(const QString &name)
126 {
127     Q_D(QuickTestResult);
128     d->testCaseName = name;
129     emit testCaseNameChanged();
130 }
131
132 /*!
133     \qmlproperty string TestResult::functionName
134
135     This property defines the name of current test function
136     within a TestCase element that is running.  If this string is
137     empty, then no function is currently running.
138
139     \sa testCaseName
140 */
141 QString QuickTestResult::functionName() const
142 {
143     Q_D(const QuickTestResult);
144     return d->functionName;
145 }
146
147 void QuickTestResult::setFunctionName(const QString &name)
148 {
149     Q_D(QuickTestResult);
150     if (!name.isEmpty()) {
151         if (d->testCaseName.isEmpty()) {
152             QTestResult::setCurrentTestFunction
153                 (d->intern(name).constData());
154         } else {
155             QString fullName = d->testCaseName + QLatin1String("::") + name;
156             QTestResult::setCurrentTestFunction
157                 (d->intern(fullName).constData());
158         }
159     } else {
160         QTestResult::setCurrentTestFunction(0);
161     }
162     d->functionName = name;
163     emit functionNameChanged();
164 }
165
166 /*!
167     \qmlproperty string TestResult::dataTag
168
169     This property defines the tag for the current row in a
170     data-driven test, or an empty string if not a data-driven test.
171 */
172 QString QuickTestResult::dataTag() const
173 {
174     const char *tag = QTestResult::currentDataTag();
175     if (tag)
176         return QString::fromUtf8(tag);
177     else
178         return QString();
179 }
180
181 void QuickTestResult::setDataTag(const QString &tag)
182 {
183     if (!tag.isEmpty()) {
184         QTestData *data = &(QTest::newRow(tag.toUtf8().constData()));
185         QTestResult::setCurrentTestData(data);
186         emit dataTagChanged();
187     } else {
188         QTestResult::setCurrentTestData(0);
189     }
190 }
191
192 /*!
193     \qmlproperty bool TestResult::failed
194
195     This property returns true if the current test function has
196     failed; false otherwise.  The fail state is reset when
197     functionName is changed or finishTestFunction() is called.
198
199     \sa skipped, dataFailed
200 */
201 bool QuickTestResult::isFailed() const
202 {
203     return QTestResult::testFailed();
204 }
205
206 /*!
207     \qmlproperty bool TestResult::dataFailed
208
209     This property returns true if the current data function has
210     failed; false otherwise.  The fail state is reset when
211     functionName is changed or finishTestFunction() is called.
212
213     \sa failed
214 */
215 bool QuickTestResult::isDataFailed() const
216 {
217     return QTestResult::currentTestFailed();
218 }
219
220 /*!
221     \qmlproperty bool TestResult::skipped
222
223     This property returns true if the current test function was
224     marked as skipped; false otherwise.
225
226     \sa failed
227 */
228 bool QuickTestResult::isSkipped() const
229 {
230     return QTestResult::skipCurrentTest();
231 }
232
233 void QuickTestResult::setSkipped(bool skip)
234 {
235     QTestResult::setSkipCurrentTest(skip);
236     emit skippedChanged();
237 }
238
239 /*!
240     \qmlproperty int TestResult::passCount
241
242     This property returns the number of tests that have passed.
243
244     \sa failCount, skipCount
245 */
246 int QuickTestResult::passCount() const
247 {
248     return QTestLog::passCount();
249 }
250
251 /*!
252     \qmlproperty int TestResult::failCount
253
254     This property returns the number of tests that have failed.
255
256     \sa passCount, skipCount
257 */
258 int QuickTestResult::failCount() const
259 {
260     return QTestLog::failCount();
261 }
262
263 /*!
264     \qmlproperty int TestResult::skipCount
265
266     This property returns the number of tests that have been skipped.
267
268     \sa passCount, failCount
269 */
270 int QuickTestResult::skipCount() const
271 {
272     return QTestLog::skipCount();
273 }
274
275 /*!
276     \qmlproperty list<string> TestResult::functionsToRun
277
278     This property returns the list of function names to be run.
279 */
280 QStringList QuickTestResult::functionsToRun() const
281 {
282     return QTest::testFunctions;
283 }
284
285 /*!
286     \qmlmethod TestResult::reset()
287
288     Resets all pass/fail/skip counters and prepare for testing.
289 */
290 void QuickTestResult::reset()
291 {
292     if (!globalProgramName)     // Only if run via qmlviewer.
293         QTestResult::reset();
294 }
295
296 /*!
297     \qmlmethod TestResult::startLogging()
298
299     Starts logging to the test output stream and writes the
300     test header.
301
302     \sa stopLogging()
303 */
304 void QuickTestResult::startLogging()
305 {
306     // The program name is used for logging headers and footers if it
307     // is set.  Otherwise the test case name is used.
308     if (loggingStarted)
309         return;
310     QTestLog::startLogging();
311     loggingStarted = true;
312 }
313
314 /*!
315     \qmlmethod TestResult::stopLogging()
316
317     Writes the test footer to the test output stream and then stops logging.
318
319     \sa startLogging()
320 */
321 void QuickTestResult::stopLogging()
322 {
323     Q_D(QuickTestResult);
324     if (globalProgramName)
325         return;     // Logging will be stopped by setProgramName(0).
326     QTestResult::setCurrentTestObject(d->intern(d->testCaseName).constData());
327     QTestLog::stopLogging();
328 }
329
330 void QuickTestResult::initTestTable()
331 {
332     Q_D(QuickTestResult);
333     delete d->table;
334     d->table = new QTestTable;
335     //qmltest does not really need the column for data driven test
336     //add this to avoid warnings.
337     d->table->addColumn(qMetaTypeId<QString>(), "qmltest_dummy_data_column");
338 }
339
340 void QuickTestResult::clearTestTable()
341 {
342     Q_D(QuickTestResult);
343     delete d->table;
344     d->table = 0;
345 }
346
347 void QuickTestResult::finishTestData()
348 {
349     QTestResult::finishedCurrentTestData();
350 }
351
352 void QuickTestResult::finishTestFunction()
353 {
354     QTestResult::finishedCurrentTestFunction();
355 }
356
357 static QString qtestFixUrl(const QUrl &location)
358 {
359     if (location.isLocalFile()) // Use QUrl's logic for Windows drive letters.
360         return QDir::toNativeSeparators(location.toLocalFile());
361     return location.toString();
362 }
363
364 void QuickTestResult::fail
365     (const QString &message, const QUrl &location, int line)
366 {
367     QTestResult::addFailure(message.toLatin1().constData(),
368                             qtestFixUrl(location).toLatin1().constData(), line);
369 }
370
371 bool QuickTestResult::verify
372     (bool success, const QString &message, const QUrl &location, int line)
373 {
374     if (!success && message.isEmpty()) {
375         return QTestResult::verify
376             (success, "verify()", "",
377              qtestFixUrl(location).toLatin1().constData(), line);
378     } else {
379         return QTestResult::verify
380             (success, message.toLatin1().constData(), "",
381              qtestFixUrl(location).toLatin1().constData(), line);
382     }
383 }
384
385 bool QuickTestResult::compare
386     (bool success, const QString &message,
387      const QString &val1, const QString &val2,
388      const QUrl &location, int line)
389 {
390     if (success) {
391         return QTestResult::compare
392             (success, message.toLocal8Bit().constData(),
393              qtestFixUrl(location).toLatin1().constData(), line);
394     } else {
395         return QTestResult::compare
396             (success, message.toLocal8Bit().constData(),
397              QTest::toString(val1.toLatin1().constData()),
398              QTest::toString(val2.toLatin1().constData()),
399              "", "",
400              qtestFixUrl(location).toLatin1().constData(), line);
401     }
402 }
403
404 void QuickTestResult::skip
405     (const QString &message, const QUrl &location, int line)
406 {
407     QTestResult::addSkip(message.toLatin1().constData(),
408                          qtestFixUrl(location).toLatin1().constData(), line);
409     QTestResult::setSkipCurrentTest(true);
410 }
411
412 bool QuickTestResult::expectFail
413     (const QString &tag, const QString &comment, const QUrl &location, int line)
414 {
415     return QTestResult::expectFail
416         (tag.toLatin1().constData(),
417          QTest::toString(comment.toLatin1().constData()),
418          QTest::Abort, qtestFixUrl(location).toLatin1().constData(), line);
419 }
420
421 bool QuickTestResult::expectFailContinue
422     (const QString &tag, const QString &comment, const QUrl &location, int line)
423 {
424     return QTestResult::expectFail
425         (tag.toLatin1().constData(),
426          QTest::toString(comment.toLatin1().constData()),
427          QTest::Continue, qtestFixUrl(location).toLatin1().constData(), line);
428 }
429
430 void QuickTestResult::warn(const QString &message, const QUrl &location, int line)
431 {
432     QTestLog::warn(message.toLatin1().constData(), qtestFixUrl(location).toLatin1().constData(), line);
433 }
434
435 void QuickTestResult::ignoreWarning(const QString &message)
436 {
437     QTestLog::ignoreMessage(QtWarningMsg, message.toLatin1().constData());
438 }
439
440 void QuickTestResult::wait(int ms)
441 {
442     QTest::qWait(ms);
443 }
444
445 void QuickTestResult::sleep(int ms)
446 {
447     QTest::qSleep(ms);
448 }
449
450 void QuickTestResult::startMeasurement()
451 {
452     Q_D(QuickTestResult);
453     delete d->benchmarkData;
454     d->benchmarkData = new QBenchmarkTestMethodData();
455     QBenchmarkTestMethodData::current = d->benchmarkData;
456     d->iterCount = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
457     d->results.clear();
458 }
459
460 void QuickTestResult::beginDataRun()
461 {
462     QBenchmarkTestMethodData::current->beginDataRun();
463 }
464
465 void QuickTestResult::endDataRun()
466 {
467     Q_D(QuickTestResult);
468     QBenchmarkTestMethodData::current->endDataRun();
469     if (d->iterCount > -1)  // iteration -1 is the warmup iteration.
470         d->results.append(QBenchmarkTestMethodData::current->result);
471
472     if (QBenchmarkGlobalData::current->verboseOutput) {
473         if (d->iterCount == -1) {
474             qDebug() << "warmup stage result      :" << QBenchmarkTestMethodData::current->result.value;
475         } else {
476             qDebug() << "accumulation stage result:" << QBenchmarkTestMethodData::current->result.value;
477         }
478     }
479 }
480
481 bool QuickTestResult::measurementAccepted()
482 {
483     return QBenchmarkTestMethodData::current->resultsAccepted();
484 }
485
486 static QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container)
487 {
488     const int count = container.count();
489     if (count == 0)
490         return QBenchmarkResult();
491
492     if (count == 1)
493         return container.at(0);
494
495     QList<QBenchmarkResult> containerCopy = container;
496     qSort(containerCopy);
497
498     const int middle = count / 2;
499
500     // ### handle even-sized containers here by doing an aritmetic mean of the two middle items.
501     return containerCopy.at(middle);
502 }
503
504 bool QuickTestResult::needsMoreMeasurements()
505 {
506     Q_D(QuickTestResult);
507     ++(d->iterCount);
508     if (d->iterCount < QBenchmarkGlobalData::current->adjustMedianIterationCount())
509         return true;
510     if (QBenchmarkTestMethodData::current->resultsAccepted())
511         QTestLog::addBenchmarkResult(qMedian(d->results));
512     return false;
513 }
514
515 void QuickTestResult::startBenchmark(RunMode runMode, const QString &tag)
516 {
517     QBenchmarkTestMethodData::current->result = QBenchmarkResult();
518     QBenchmarkTestMethodData::current->resultAccepted = false;
519     QBenchmarkGlobalData::current->context.tag = tag;
520     QBenchmarkGlobalData::current->context.slotName = functionName();
521
522     Q_D(QuickTestResult);
523     delete d->benchmarkIter;
524     d->benchmarkIter = new QTest::QBenchmarkIterationController
525         (QTest::QBenchmarkIterationController::RunMode(runMode));
526 }
527
528 bool QuickTestResult::isBenchmarkDone() const
529 {
530     Q_D(const QuickTestResult);
531     if (d->benchmarkIter)
532         return d->benchmarkIter->isDone();
533     else
534         return true;
535 }
536
537 void QuickTestResult::nextBenchmark()
538 {
539     Q_D(QuickTestResult);
540     if (d->benchmarkIter)
541         d->benchmarkIter->next();
542 }
543
544 void QuickTestResult::stopBenchmark()
545 {
546     Q_D(QuickTestResult);
547     delete d->benchmarkIter;
548     d->benchmarkIter = 0;
549 }
550
551 namespace QTest {
552     void qtest_qParseArgs(int argc, char *argv[], bool qml);
553 };
554
555 void QuickTestResult::parseArgs(int argc, char *argv[])
556 {
557     if (!QBenchmarkGlobalData::current)
558         QBenchmarkGlobalData::current = &globalBenchmarkData;
559     QTest::qtest_qParseArgs(argc, argv, true);
560 }
561
562 void QuickTestResult::setProgramName(const char *name)
563 {
564     if (name) {
565         QTestResult::reset();
566     } else if (!name && loggingStarted) {
567         QTestResult::setCurrentTestObject(globalProgramName);
568         QTestLog::stopLogging();
569         QTestResult::setCurrentTestObject(0);
570     }
571     globalProgramName = name;
572     QTestResult::setCurrentTestObject(globalProgramName);
573 }
574
575 int QuickTestResult::exitCode()
576 {
577 #if defined(QTEST_NOEXITCODE)
578     return 0;
579 #else
580     // make sure our exit code is never going above 127
581     // since that could wrap and indicate 0 test fails
582     return qMin(QTestLog::failCount(), 127);
583 #endif
584 }
585
586 QT_END_NAMESPACE