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 test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
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>
59 static const char *globalProgramName = 0;
60 static bool loggingStarted = false;
61 static QBenchmarkGlobalData globalBenchmarkData;
63 class QuickTestResultPrivate
66 QuickTestResultPrivate()
73 ~QuickTestResultPrivate()
80 QByteArray intern(const QString &str);
84 QSet<QByteArray> internedStrings;
86 QTest::QBenchmarkIterationController *benchmarkIter;
87 QBenchmarkTestMethodData *benchmarkData;
89 QList<QBenchmarkResult> results;
92 QByteArray QuickTestResultPrivate::intern(const QString &str)
94 QByteArray bstr = str.toUtf8();
95 return *(internedStrings.insert(bstr));
98 QuickTestResult::QuickTestResult(QObject *parent)
99 : QObject(parent), d_ptr(new QuickTestResultPrivate)
101 if (!QBenchmarkGlobalData::current)
102 QBenchmarkGlobalData::current = &globalBenchmarkData;
105 QuickTestResult::~QuickTestResult()
110 \qmlproperty string TestResult::testCaseName
112 This property defines the name of current TestCase element
113 that is running test cases.
117 QString QuickTestResult::testCaseName() const
119 Q_D(const QuickTestResult);
120 return d->testCaseName;
123 void QuickTestResult::setTestCaseName(const QString &name)
125 Q_D(QuickTestResult);
126 d->testCaseName = name;
127 emit testCaseNameChanged();
131 \qmlproperty string TestResult::functionName
133 This property defines the name of current test function
134 within a TestCase element that is running. If this string is
135 empty, then no function is currently running.
139 QString QuickTestResult::functionName() const
141 Q_D(const QuickTestResult);
142 return d->functionName;
145 void QuickTestResult::setFunctionName(const QString &name)
147 Q_D(QuickTestResult);
148 if (!name.isEmpty()) {
149 if (d->testCaseName.isEmpty()) {
150 QTestResult::setCurrentTestFunction
151 (d->intern(name).constData());
153 QString fullName = d->testCaseName + QLatin1String("::") + name;
154 QTestResult::setCurrentTestFunction
155 (d->intern(fullName).constData());
158 QTestResult::setCurrentTestFunction(0);
160 d->functionName = name;
161 emit functionNameChanged();
164 QuickTestResult::FunctionType QuickTestResult::functionType() const
166 return FunctionType(QTestResult::currentTestLocation());
169 void QuickTestResult::setFunctionType(FunctionType type)
171 QTestResult::setCurrentTestLocation(QTestResult::TestLocation(type));
172 emit functionTypeChanged();
176 \qmlproperty string TestResult::dataTag
178 This property defines the tag for the current row in a
179 data-driven test, or an empty string if not a data-driven test.
181 QString QuickTestResult::dataTag() const
183 const char *tag = QTestResult::currentDataTag();
185 return QString::fromUtf8(tag);
190 void QuickTestResult::setDataTag(const QString &tag)
192 if (!tag.isEmpty()) {
193 QTestData *data = &(QTest::newRow(tag.toUtf8().constData()));
194 QTestResult::setCurrentTestData(data);
195 emit dataTagChanged();
197 QTestResult::setCurrentTestData(0);
202 \qmlproperty bool TestResult::failed
204 This property returns true if the current test function has
205 failed; false otherwise. The fail state is reset when
206 functionName is changed or finishTestFunction() is called.
208 \sa skipped, dataFailed
210 bool QuickTestResult::isFailed() const
212 return QTestResult::testFailed();
216 \qmlproperty bool TestResult::dataFailed
218 This property returns true if the current data function has
219 failed; false otherwise. The fail state is reset when
220 functionName is changed or finishTestFunction() is called.
224 bool QuickTestResult::isDataFailed() const
226 return QTestResult::currentTestFailed();
230 \qmlproperty bool TestResult::skipped
232 This property returns true if the current test function was
233 marked as skipped; false otherwise.
237 bool QuickTestResult::isSkipped() const
239 return QTestResult::skipCurrentTest();
242 void QuickTestResult::setSkipped(bool skip)
244 QTestResult::setSkipCurrentTest(skip);
245 emit skippedChanged();
249 \qmlproperty int TestResult::passCount
251 This property returns the number of tests that have passed.
253 \sa failCount, skipCount
255 int QuickTestResult::passCount() const
257 return QTestResult::passCount();
261 \qmlproperty int TestResult::failCount
263 This property returns the number of tests that have failed.
265 \sa passCount, skipCount
267 int QuickTestResult::failCount() const
269 return QTestResult::failCount();
273 \qmlproperty int TestResult::skipCount
275 This property returns the number of tests that have been skipped.
277 \sa passCount, failCount
279 int QuickTestResult::skipCount() const
281 return QTestResult::skipCount();
285 \qmlproperty list<string> TestResult::functionsToRun
287 This property returns the list of function names to be run.
289 QStringList QuickTestResult::functionsToRun() const
291 return QTest::testFunctions;
295 \qmlmethod TestResult::reset()
297 Resets all pass/fail/skip counters and prepare for testing.
299 void QuickTestResult::reset()
301 if (!globalProgramName) // Only if run via qmlviewer.
302 QTestResult::reset();
306 \qmlmethod TestResult::startLogging()
308 Starts logging to the test output stream and writes the
313 void QuickTestResult::startLogging()
315 // The program name is used for logging headers and footers if it
316 // is set. Otherwise the test case name is used.
319 QTestLog::startLogging();
320 loggingStarted = true;
324 \qmlmethod TestResult::stopLogging()
326 Writes the test footer to the test output stream and then stops logging.
330 void QuickTestResult::stopLogging()
332 Q_D(QuickTestResult);
333 if (globalProgramName)
334 return; // Logging will be stopped by setProgramName(0).
335 QTestResult::setCurrentTestObject(d->intern(d->testCaseName).constData());
336 QTestLog::stopLogging();
339 void QuickTestResult::initTestTable()
341 Q_D(QuickTestResult);
343 d->table = new QTestTable;
346 void QuickTestResult::clearTestTable()
348 Q_D(QuickTestResult);
353 void QuickTestResult::finishTestFunction()
355 QTestResult::finishedCurrentTestFunction();
358 static QString qtest_fixFile(const QString &file)
360 if (file.startsWith(QLatin1String("file://")))
366 void QuickTestResult::fail
367 (const QString &message, const QString &file, int line)
369 QTestResult::addFailure(message.toLatin1().constData(),
370 qtest_fixFile(file).toLatin1().constData(), line);
373 bool QuickTestResult::verify
374 (bool success, const QString &message, const QString &file, int line)
376 if (!success && message.isEmpty()) {
377 return QTestResult::verify
378 (success, "verify()", "",
379 qtest_fixFile(file).toLatin1().constData(), line);
381 return QTestResult::verify
382 (success, message.toLatin1().constData(), "",
383 qtest_fixFile(file).toLatin1().constData(), line);
387 bool QuickTestResult::compare
388 (bool success, const QString &message,
389 const QString &val1, const QString &val2,
390 const QString &file, int line)
393 return QTestResult::compare
394 (success, message.toLocal8Bit().constData(),
395 qtest_fixFile(file).toLatin1().constData(), line);
397 return QTestResult::compare
398 (success, message.toLocal8Bit().constData(),
399 QTest::toString(val1.toLatin1().constData()),
400 QTest::toString(val2.toLatin1().constData()),
402 qtest_fixFile(file).toLatin1().constData(), line);
406 void QuickTestResult::skip
407 (const QString &message, const QString &file, int line)
409 QTestResult::addSkip(message.toLatin1().constData(),
410 qtest_fixFile(file).toLatin1().constData(), line);
411 QTestResult::setSkipCurrentTest(true);
414 bool QuickTestResult::expectFail
415 (const QString &tag, const QString &comment, const QString &file, int line)
417 return QTestResult::expectFail
418 (tag.toLatin1().constData(),
419 QTest::toString(comment.toLatin1().constData()),
420 QTest::Abort, qtest_fixFile(file).toLatin1().constData(), line);
423 bool QuickTestResult::expectFailContinue
424 (const QString &tag, const QString &comment, const QString &file, int line)
426 return QTestResult::expectFail
427 (tag.toLatin1().constData(),
428 QTest::toString(comment.toLatin1().constData()),
429 QTest::Continue, qtest_fixFile(file).toLatin1().constData(), line);
432 void QuickTestResult::warn(const QString &message, const QString &file, int line)
434 QTestLog::warn(message.toLatin1().constData(), qtest_fixFile(file).toLatin1().constData(), line);
437 void QuickTestResult::ignoreWarning(const QString &message)
439 QTestResult::ignoreMessage(QtWarningMsg, message.toLatin1().constData());
442 void QuickTestResult::wait(int ms)
447 void QuickTestResult::sleep(int ms)
452 void QuickTestResult::startMeasurement()
454 Q_D(QuickTestResult);
455 delete d->benchmarkData;
456 d->benchmarkData = new QBenchmarkTestMethodData();
457 QBenchmarkTestMethodData::current = d->benchmarkData;
458 d->iterCount = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
462 void QuickTestResult::beginDataRun()
464 QBenchmarkTestMethodData::current->beginDataRun();
467 void QuickTestResult::endDataRun()
469 Q_D(QuickTestResult);
470 QBenchmarkTestMethodData::current->endDataRun();
471 if (d->iterCount > -1) // iteration -1 is the warmup iteration.
472 d->results.append(QBenchmarkTestMethodData::current->result);
474 if (QBenchmarkGlobalData::current->verboseOutput) {
475 if (d->iterCount == -1) {
476 qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value;
478 qDebug() << "accumulation stage result:" << QBenchmarkTestMethodData::current->result.value;
483 bool QuickTestResult::measurementAccepted()
485 return QBenchmarkTestMethodData::current->resultsAccepted();
488 static QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container)
490 const int count = container.count();
492 return QBenchmarkResult();
495 return container.at(0);
497 QList<QBenchmarkResult> containerCopy = container;
498 qSort(containerCopy);
500 const int middle = count / 2;
502 // ### handle even-sized containers here by doing an aritmetic mean of the two middle items.
503 return containerCopy.at(middle);
506 bool QuickTestResult::needsMoreMeasurements()
508 Q_D(QuickTestResult);
510 if (d->iterCount < QBenchmarkGlobalData::current->adjustMedianIterationCount())
512 if (QBenchmarkTestMethodData::current->resultsAccepted())
513 QTestLog::addBenchmarkResult(qMedian(d->results));
517 void QuickTestResult::startBenchmark(RunMode runMode, const QString &tag)
519 QBenchmarkTestMethodData::current->result = QBenchmarkResult();
520 QBenchmarkTestMethodData::current->resultAccepted = false;
521 QBenchmarkGlobalData::current->context.tag = tag;
522 QBenchmarkGlobalData::current->context.slotName = functionName();
524 Q_D(QuickTestResult);
525 delete d->benchmarkIter;
526 d->benchmarkIter = new QTest::QBenchmarkIterationController
527 (QTest::QBenchmarkIterationController::RunMode(runMode));
530 bool QuickTestResult::isBenchmarkDone() const
532 Q_D(const QuickTestResult);
533 if (d->benchmarkIter)
534 return d->benchmarkIter->isDone();
539 void QuickTestResult::nextBenchmark()
541 Q_D(QuickTestResult);
542 if (d->benchmarkIter)
543 d->benchmarkIter->next();
546 void QuickTestResult::stopBenchmark()
548 Q_D(QuickTestResult);
549 delete d->benchmarkIter;
550 d->benchmarkIter = 0;
554 void qtest_qParseArgs(int argc, char *argv[], bool qml);
557 void QuickTestResult::parseArgs(int argc, char *argv[])
559 if (!QBenchmarkGlobalData::current)
560 QBenchmarkGlobalData::current = &globalBenchmarkData;
561 QTest::qtest_qParseArgs(argc, argv, true);
564 void QuickTestResult::setProgramName(const char *name)
567 QTestResult::reset();
568 } else if (!name && loggingStarted) {
569 QTestResult::setCurrentTestObject(globalProgramName);
570 QTestLog::stopLogging();
571 QTestResult::setCurrentTestObject(0);
573 globalProgramName = name;
574 QTestResult::setCurrentTestObject(globalProgramName);
577 int QuickTestResult::exitCode()
579 #if defined(QTEST_NOEXITCODE)
582 // make sure our exit code is never going above 127
583 // since that could wrap and indicate 0 test fails
584 return qMin(QTestResult::failCount(), 127);