diff options
Diffstat (limited to 'src/testlib')
26 files changed, 695 insertions, 314 deletions
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf index 0fafc733b1..72db51b925 100644 --- a/src/testlib/doc/qttestlib.qdocconf +++ b/src/testlib/doc/qttestlib.qdocconf @@ -4,7 +4,7 @@ project = QtTestLib description = Qt Test Reference Documentation version = $QT_VERSION -examplesinstallpath = testlib +examplesinstallpath = qtbase/testlib qhp.projects = QtTestLib diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index 29cbefdc04..8c32787b42 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -147,7 +147,7 @@ namespace QTest { { QByteArray ba = "MyPoint("; ba += QByteArray::number(point.x()) + ", " + QByteArray::number(point.y()); - ba += ")"; + ba += ')'; return qstrdup(ba.data()); } } diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index d785f3d4b7..6312a34cb8 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -91,6 +91,7 @@ struct QBenchmarkContext QBenchmarkContext() : checkpointIndex(-1) {} }; +Q_DECLARE_TYPEINFO(QBenchmarkContext, Q_MOVABLE_TYPE); class QBenchmarkResult { @@ -126,6 +127,7 @@ public: return (value / iterations) < (other.value / other.iterations); } }; +Q_DECLARE_TYPEINFO(QBenchmarkResult, Q_MOVABLE_TYPE); /* The QBenchmarkGlobalData class stores global benchmark-related data. diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp index ee212a49d0..f6d2c20a4a 100644 --- a/src/testlib/qbenchmarkmetric.cpp +++ b/src/testlib/qbenchmarkmetric.cpp @@ -79,7 +79,6 @@ */ /*! - \relates QTest \since 4.7 Returns the enum value \a metric as a character string. */ @@ -152,7 +151,6 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric) }; /*! - \relates QTest \since 4.7 Retuns the units of measure for the specified \a metric. */ diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h index cfde89aec8..e9744d0b07 100644 --- a/src/testlib/qsignalspy.h +++ b/src/testlib/qsignalspy.h @@ -82,7 +82,7 @@ public: } if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, - Qt::DirectConnection, 0)) { + Qt::DirectConnection, Q_NULLPTR)) { qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect."); return; } @@ -175,8 +175,11 @@ private: tp = QMetaType::UnknownType; } if (tp == QMetaType::UnknownType) { - qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.", - member.parameterNames().at(i).constData()); + qWarning("QSignalSpy: Unable to handle parameter '%s' of type '%s' of method '%s'," + " use qRegisterMetaType to register it.", + member.parameterNames().at(i).constData(), + member.parameterTypes().at(i).constData(), + member.name().constData()); } args << tp; } diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 994179958b..8da16af91e 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -51,6 +51,9 @@ #include <QtCore/qsize.h> #include <QtCore/qrect.h> +#ifdef QT_NETWORK_LIB +# include <QtNetwork/qhostaddress.h> +#endif QT_BEGIN_NAMESPACE @@ -162,6 +165,23 @@ template<> inline char *toString(const QVariant &v) return qstrdup(vstring.constData()); } +#ifdef QT_NETWORK_LIB +template<> inline char *toString(const QHostAddress &addr) +{ + switch (addr.protocol()) { + case QAbstractSocket::UnknownNetworkLayerProtocol: + return qstrdup("<unknown address (parse error)>"); + case QAbstractSocket::AnyIPProtocol: + return qstrdup("QHostAddress::Any"); + case QAbstractSocket::IPv4Protocol: + case QAbstractSocket::IPv6Protocol: + break; + } + + return qstrdup(addr.toString().toLatin1().constData()); +} +#endif + template<> inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line) @@ -205,7 +225,7 @@ inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, delete [] val2; } } - return compare_helper(isOk, msg, 0, 0, actual, expected, file, line); + return compare_helper(isOk, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } template <> diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index a474758de6..beae9ec065 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -86,24 +86,24 @@ inline bool qCompare(QImage const &t1, QImage const &t2, qsnprintf(msg, 1024, "Compared QImages differ.\n" " Actual (%s).isNull(): %d\n" " Expected (%s).isNull(): %d", actual, t1Null, expected, t2Null); - return compare_helper(false, msg, 0, 0, actual, expected, file, line); + return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } if (t1Null && t2Null) - return compare_helper(true, 0, 0, 0, actual, expected, file, line); + return compare_helper(true, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); if (t1.width() != t2.width() || t1.height() != t2.height()) { qsnprintf(msg, 1024, "Compared QImages differ in size.\n" " Actual (%s): %dx%d\n" " Expected (%s): %dx%d", actual, t1.width(), t1.height(), expected, t2.width(), t2.height()); - return compare_helper(false, msg, 0, 0, actual, expected, file, line); + return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } if (t1.format() != t2.format()) { qsnprintf(msg, 1024, "Compared QImages differ in format.\n" " Actual (%s): %d\n" " Expected (%s): %d", actual, t1.format(), expected, t2.format()); - return compare_helper(false, msg, 0, 0, actual, expected, file, line); + return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } return compare_helper(t1 == t2, "Compared values are not the same", toString(t1), toString(t2), actual, expected, file, line); @@ -120,17 +120,17 @@ inline bool qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, c qsnprintf(msg, 1024, "Compared QPixmaps differ.\n" " Actual (%s).isNull(): %d\n" " Expected (%s).isNull(): %d", actual, t1Null, expected, t2Null); - return compare_helper(false, msg, 0, 0, actual, expected, file, line); + return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } if (t1Null && t2Null) - return compare_helper(true, 0, 0, 0, actual, expected, file, line); + return compare_helper(true, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); if (t1.width() != t2.width() || t1.height() != t2.height()) { qsnprintf(msg, 1024, "Compared QPixmaps differ in size.\n" " Actual (%s): %dx%d\n" " Expected (%s): %dx%d", actual, t1.width(), t1.height(), expected, t2.width(), t2.height()); - return compare_helper(false, msg, 0, 0, actual, expected, file, line); + return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line); } return qCompare(t1.toImage(), t2.toImage(), actual, expected, file, line); } diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index f1ac625dbd..a397a09908 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -126,7 +126,7 @@ public: static void cleanup() { delete instance(); - instance() = 0; + instance() = Q_NULLPTR; } static void clearEvents() { eventList().clear(); } static EventList events() { return eventList(); } @@ -135,13 +135,12 @@ public: for (int i = 0; eventList().isEmpty() && i < 5; ++i) QTest::qWait(50); if (eventList().isEmpty()) { - qWarning("%s: Timeout waiting for accessibility event.", Q_FUNC_INFO); + qWarning("Timeout waiting for accessibility event."); return false; } const bool res = *eventList().first() == *ev; if (!res) - qWarning("%s: %s", Q_FUNC_INFO, - qPrintable(msgAccessibilityEventListMismatch(eventList(), ev))); + qWarning("%s", qPrintable(msgAccessibilityEventListMismatch(eventList(), ev))); delete eventList().takeFirst(); return res; } @@ -162,8 +161,8 @@ private: ~QTestAccessibility() { - QAccessible::installUpdateHandler(0); - QAccessible::installRootObjectHandler(0); + QAccessible::installUpdateHandler(Q_NULLPTR); + QAccessible::installRootObjectHandler(Q_NULLPTR); } static void rootObjectHandler(QObject *object) @@ -172,9 +171,9 @@ private: if (object) { QGuiApplication* app = qobject_cast<QGuiApplication*>(object); if ( !app ) - qWarning("%s: root Object is not a QGuiApplication!", Q_FUNC_INFO); + qWarning("root Object is not a QGuiApplication!"); } else { - qWarning("%s: root Object called with 0 pointer", Q_FUNC_INFO); + qWarning("root Object called with 0 pointer"); } } @@ -268,7 +267,7 @@ private: static QTestAccessibility *&instance() { - static QTestAccessibility *ta = 0; + static QTestAccessibility *ta = Q_NULLPTR; return ta; } diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 28a2878b32..c2643a2304 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -37,6 +37,9 @@ #include <QtTest/qtest.h> #include <QtCore/qbytearray.h> #include <QtCore/qfile.h> +#include <QtCore/qset.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qvariant.h> #include <QtCore/QSysInfo> #include <set> @@ -61,83 +64,89 @@ QT_BEGIN_NAMESPACE The known keys are listed below: */ -// this table can be extended with new keywords as required -const char *matchedConditions[] = +static QSet<QByteArray> keywords() { - "*", + // this list can be extended with new keywords as required + QSet<QByteArray> set = QSet<QByteArray>() + << "*" #ifdef Q_OS_LINUX - "linux", + << "linux" #endif #ifdef Q_OS_OSX - "osx", + << "osx" #endif #ifdef Q_OS_WIN - "windows", + << "windows" #endif #ifdef Q_OS_IOS - "ios", + << "ios" #endif #ifdef Q_OS_ANDROID - "android", + << "android" #endif #ifdef Q_OS_QNX - "qnx", + << "qnx" #endif #ifdef Q_OS_WINRT - "winrt", + << "winrt" #endif #ifdef Q_OS_WINCE - "wince", + << "wince" #endif #if QT_POINTER_SIZE == 8 - "64bit", + << "64bit" #else - "32bit", + << "32bit" #endif #ifdef Q_CC_GNU - "gcc", + << "gcc" #endif #ifdef Q_CC_CLANG - "clang", + << "clang" #endif #ifdef Q_CC_MSVC - "msvc", + << "msvc" #ifdef _MSC_VER - #if _MSC_VER == 1800 - "msvc-2013", + #if _MSC_VER == 1900 + << "msvc-2015" + #elif _MSC_VER == 1800 + << "msvc-2013" #elif _MSC_VER == 1700 - "msvc-2012", + << "msvc-2012" #elif _MSC_VER == 1600 - "msvc-2010", + << "msvc-2010" #endif #endif #endif #ifdef Q_AUTOTEST_EXPORT - "developer-build", + << "developer-build" #endif - 0 -}; + ; + QCoreApplication *app = QCoreApplication::instance(); + if (app) { + const QVariant platformName = app->property("platformName"); + if (platformName.isValid()) + set << platformName.toByteArray(); + } + + return set; +} static bool checkCondition(const QByteArray &condition) { + static QSet<QByteArray> matchedConditions = keywords(); QList<QByteArray> conds = condition.split(' '); - std::set<QByteArray> matches; - const char **m = matchedConditions; - while (*m) { - matches.insert(*m); - ++m; - } QByteArray distributionName = QSysInfo::productType().toLower().toUtf8(); QByteArray distributionRelease = QSysInfo::productVersion().toLower().toUtf8(); if (!distributionName.isEmpty()) { - if (matches.find(distributionName) == matches.end()) - matches.insert(distributionName); - matches.insert(distributionName + "-" + distributionRelease); + if (matchedConditions.find(distributionName) == matchedConditions.end()) + matchedConditions.insert(distributionName); + matchedConditions.insert(distributionName + "-" + distributionRelease); } for (int i = 0; i < conds.size(); ++i) { @@ -146,7 +155,7 @@ static bool checkCondition(const QByteArray &condition) if (result) c = c.mid(1); - result ^= (matches.find(c) != matches.end()); + result ^= matchedConditions.contains(c); if (!result) return false; } @@ -159,6 +168,19 @@ static std::set<QByteArray> *gpuFeatures = 0; Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &) = 0; +static bool isGPUTestBlacklisted(const char *slot, const char *data = 0) +{ + const QByteArray disableKey = QByteArrayLiteral("disable_") + QByteArray(slot); + if (gpuFeatures->find(disableKey) != gpuFeatures->end()) { + QByteArray msg = QByteArrayLiteral("Skipped due to GPU blacklist: ") + disableKey; + if (data) + msg += ':' + QByteArray(data); + QTest::qSkip(msg.constData(), __FILE__, __LINE__); + return true; + } + return false; +} + namespace QTestPrivate { void parseBlackList() @@ -223,10 +245,12 @@ void checkBlackLists(const char *slot, const char *data) // Tests blacklisted in GPU_BLACKLIST are to be skipped. Just ignoring the result is // not sufficient since these are expected to crash or behave in undefined ways. if (!ignore && gpuFeatures) { - const QByteArray disableKey = QByteArrayLiteral("disable_") + QByteArray(slot); - if (gpuFeatures->find(disableKey) != gpuFeatures->end()) { - const QByteArray msg = QByteArrayLiteral("Skipped due to GPU blacklist: ") + disableKey; - QTest::qSkip(msg.constData(), __FILE__, __LINE__); + QByteArray s_gpu = slot; + ignore = isGPUTestBlacklisted(s_gpu, data); + if (!ignore && data) { + s_gpu += ':'; + s_gpu += data; + isGPUTestBlacklisted(s_gpu); } } } diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h index 0107e5d282..87f4dfdb5e 100644 --- a/src/testlib/qtestblacklist_p.h +++ b/src/testlib/qtestblacklist_p.h @@ -50,9 +50,10 @@ QT_BEGIN_NAMESPACE namespace QTestPrivate { - void parseBlackList(); - void parseGpuBlackList(); - void checkBlackLists(const char *slot, const char *data); + // Export functions so they can also be used by QQuickTest + Q_TESTLIB_EXPORT void parseBlackList(); + Q_TESTLIB_EXPORT void parseGpuBlackList(); + Q_TESTLIB_EXPORT void checkBlackLists(const char *slot, const char *data); } QT_END_NAMESPACE diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index efc18180db..36eff6ac98 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -50,6 +50,9 @@ #include <QtCore/private/qtools_p.h> #include <QtCore/qdiriterator.h> #include <QtCore/qtemporarydir.h> +#include <QtCore/qthread.h> +#include <QtCore/qwaitcondition.h> +#include <QtCore/qmutex.h> #include <QtTest/private/qtestlog_p.h> #include <QtTest/private/qtesttable_p.h> @@ -70,6 +73,12 @@ #include <stdio.h> #include <stdlib.h> +#if defined(Q_OS_LINUX) +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#endif + #ifdef Q_OS_WIN #ifndef Q_OS_WINCE # if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR)) @@ -93,6 +102,40 @@ QT_BEGIN_NAMESPACE using QtMiscUtils::toHexUpper; using QtMiscUtils::fromHex; + +static void stackTrace() +{ + bool ok = false; + const int disableStackDump = qEnvironmentVariableIntValue("QTEST_DISABLE_STACK_DUMP", &ok); + if (ok && disableStackDump == 1) + return; +#ifdef Q_OS_LINUX + fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); + char cmd[512]; + qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n" + "set prompt\n" + "thread apply all where full\n" + "detach\n" + "quit\n" + "EOF\n", + (int)getpid()); + if (system(cmd) == -1) + fprintf(stderr, "calling gdb failed\n"); + fprintf(stderr, "========= End of stack trace ==============\n"); +#elif defined(Q_OS_OSX) + fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); + char cmd[512]; + qsnprintf(cmd, 512, "lldb -p %d 2>/dev/null <<EOF\n" + "bt all\n" + "quit\n" + "EOF\n", + (int)getpid()); + if (system(cmd) == -1) + fprintf(stderr, "calling lldb failed\n"); + fprintf(stderr, "========= End of stack trace ==============\n"); +#endif +} + /*! \namespace QTest \inmodule QtTest @@ -205,7 +248,7 @@ using QtMiscUtils::fromHex; \note This macro can only be used in a test function that is invoked by the test framework. - \sa QTRY_VERIFY(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() + \sa QTRY_VERIFY(), QTRY_VERIFY2_WITH_TIMEOUT(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() */ @@ -219,7 +262,47 @@ using QtMiscUtils::fromHex; \note This macro can only be used in a test function that is invoked by the test framework. - \sa QTRY_VERIFY_WITH_TIMEOUT(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() + \sa QTRY_VERIFY_WITH_TIMEOUT(), QTRY_VERIFY2(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() +*/ + +/*! \macro QTRY_VERIFY2_WITH_TIMEOUT(condition, message, timeout) + \since 5.6 + + \relates QTest + + The QTRY_VERIFY2_WITH_TIMEOUT macro is similar to QTRY_VERIFY_WITH_TIMEOUT() + except that it outputs a verbose \a message when \a condition is still false + after the specified \a timeout. The \a message is a plain C string. + + Example: + \code + QTRY_VERIFY2_WITH_TIMEOUT(list.size() > 2, QByteArray::number(list.size()).constData(), 10000); + \endcode + + \note This macro can only be used in a test function that is invoked + by the test framework. + + \sa QTRY_VERIFY(), QTRY_VERIFY_WITH_TIMEOUT(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() +*/ + +/*! \macro QTRY_VERIFY2(condition, message) + \since 5.6 + + \relates QTest + + Checks the \a condition by invoking QTRY_VERIFY2_WITH_TIMEOUT() with a timeout + of five seconds. If \a condition is then still false, \a message is output. + The \a message is a plain C string. + + Example: + \code + QTRY_VERIFY2_WITH_TIMEOUT(list.size() > 2, QByteArray::number(list.size()).constData()); + \endcode + + \note This macro can only be used in a test function that is invoked + by the test framework. + + \sa QTRY_VERIFY2_WITH_TIMEOUT(), QTRY_VERIFY2(), QVERIFY(), QCOMPARE(), QTRY_COMPARE() */ /*! \macro QTRY_COMPARE_WITH_TIMEOUT(actual, expected, timeout) @@ -1276,7 +1359,7 @@ using QtMiscUtils::fromHex; */ /*! - \fn QTouchEventSequence QTest::touchEvent(QWindow *window, QTouchDevice *device, bool autoCommit = true) + \fn QTouchEventSequence QTest::touchEvent(QWindow *window, QTouchDevice *device, bool autoCommit) \since 5.0 Creates and returns a QTouchEventSequence for the \a device to @@ -1293,7 +1376,7 @@ using QtMiscUtils::fromHex; */ /*! - \fn QTouchEventSequence QTest::touchEvent(QWidget *widget, QTouchDevice *device, bool autoCommit = true) + \fn QTouchEventSequence QTest::touchEvent(QWidget *widget, QTouchDevice *device, bool autoCommit) Creates and returns a QTouchEventSequence for the \a device to simulate events for \a widget. @@ -1883,7 +1966,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) QTestLog::addLogger(logFormat, logFilename); } -QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) +QBenchmarkResult qMedian(const QVector<QBenchmarkResult> &container) { const int count = container.count(); if (count == 0) @@ -1892,7 +1975,7 @@ QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) if (count == 1) return container.front(); - QList<QBenchmarkResult> containerCopy = container; + QVector<QBenchmarkResult> containerCopy = container; std::sort(containerCopy.begin(), containerCopy.end()); const int middle = count / 2; @@ -1929,7 +2012,7 @@ static void qInvokeTestMethodDataEntry(char *slot) bool isBenchmark = false; int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0; - QList<QBenchmarkResult> results; + QVector<QBenchmarkResult> results; bool minimumTotalReached = false; do { QBenchmarkTestMethodData::current->beginDataRun(); @@ -2011,6 +2094,58 @@ static void qInvokeTestMethodDataEntry(char *slot) } } +class WatchDog : public QThread +{ +public: + WatchDog() + { + QMutexLocker locker(&mutex); + timeout.store(-1); + start(); + waitCondition.wait(&mutex); + } + ~WatchDog() { + { + QMutexLocker locker(&mutex); + timeout.store(0); + waitCondition.wakeAll(); + } + wait(); + } + + void beginTest() { + QMutexLocker locker(&mutex); + timeout.store(5*60*1000); + waitCondition.wakeAll(); + } + + void testFinished() { + QMutexLocker locker(&mutex); + timeout.store(-1); + waitCondition.wakeAll(); + } + + void run() { + QMutexLocker locker(&mutex); + waitCondition.wakeAll(); + while (1) { + int t = timeout.load(); + if (!t) + break; + if (!waitCondition.wait(&mutex, t)) { + stackTrace(); + qFatal("Test function timed out"); + } + } + } + +private: + QBasicAtomicInt timeout; + QMutex mutex; + QWaitCondition waitCondition; +}; + + /*! \internal @@ -2020,7 +2155,7 @@ static void qInvokeTestMethodDataEntry(char *slot) If the function was successfully called, true is returned, otherwise false. */ -static bool qInvokeTestMethod(const char *slotName, const char *data=0) +static bool qInvokeTestMethod(const char *slotName, const char *data, WatchDog *watchDog) { QTEST_ASSERT(slotName); @@ -2079,7 +2214,11 @@ static bool qInvokeTestMethod(const char *slotName, const char *data=0) QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0) : table.testData(curDataIndex)); + if (watchDog) + watchDog->beginTest(); qInvokeTestMethodDataEntry(slot); + if (watchDog) + watchDog->testFinished(); if (data) break; @@ -2351,6 +2490,37 @@ char *toPrettyUnicode(const ushort *p, int length) return buffer.take(); } +static bool debuggerPresent() +{ +#if defined(Q_OS_LINUX) + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) + return false; + char buffer[2048]; + ssize_t size = read(fd, buffer, sizeof(buffer)); + if (size == -1) { + close(fd); + return false; + } + buffer[size] = 0; + const char tracerPidToken[] = "\nTracerPid:"; + char *tracerPid = strstr(buffer, tracerPidToken); + if (!tracerPid) { + close(fd); + return false; + } + tracerPid += sizeof(tracerPidToken); + long int pid = strtol(tracerPid, &tracerPid, 10); + close(fd); + return pid != 0; +#elif defined(Q_OS_WIN) + return IsDebuggerPresent(); +#else + // TODO + return false; +#endif +} + static void qInvokeTestMethods(QObject *testObject) { const QMetaObject *metaObject = testObject->metaObject(); @@ -2360,6 +2530,10 @@ static void qInvokeTestMethods(QObject *testObject) QTestTable::globalTestTable(); invokeMethod(testObject, "initTestCase_data()"); + QScopedPointer<WatchDog> watchDog; + if (!debuggerPresent()) + watchDog.reset(new WatchDog); + if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { invokeMethod(testObject, "initTestCase()"); @@ -2374,7 +2548,7 @@ static void qInvokeTestMethods(QObject *testObject) if (QTest::testFuncs) { for (int i = 0; i != QTest::testFuncCount; i++) { if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).methodSignature().constData(), - QTest::testFuncs[i].data())) { + QTest::testFuncs[i].data(), watchDog.data())) { break; } } @@ -2387,7 +2561,7 @@ static void qInvokeTestMethods(QObject *testObject) for (int i = 0; i != methodCount; i++) { if (!isValidSlot(testMethods[i])) continue; - if (!qInvokeTestMethod(testMethods[i].methodSignature().constData())) + if (!qInvokeTestMethod(testMethods[i].methodSignature().constData(), 0, watchDog.data())) break; } delete[] testMethods; @@ -2423,7 +2597,13 @@ private: void FatalSignalHandler::signal(int signum) { - qFatal("Received signal %d", signum); + const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); + const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); + if (signum != SIGINT) + stackTrace(); + qFatal("Received signal %d\n" + " Function time: %dms Total time: %dms", + signum, msecsFunctionTime, msecsTotalTime); #if defined(Q_OS_INTEGRITY) { struct sigaction act; @@ -2517,13 +2697,141 @@ FatalSignalHandler::~FatalSignalHandler() } // namespace #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) + +// Helper class for resolving symbol names by dynamically loading "dbghelp.dll". +class DebugSymbolResolver +{ + Q_DISABLE_COPY(DebugSymbolResolver) +public: + struct Symbol { + Symbol() : name(Q_NULLPTR), address(0) {} + + const char *name; // Must be freed by caller. + DWORD64 address; + }; + + explicit DebugSymbolResolver(HANDLE process); + ~DebugSymbolResolver() { cleanup(); } + + bool isValid() const { return m_symFromAddr; } + + Symbol resolveSymbol(DWORD64 address) const; + +private: + // typedefs from DbgHelp.h/.dll + struct DBGHELP_SYMBOL_INFO { // SYMBOL_INFO + ULONG SizeOfStruct; + ULONG TypeIndex; // Type Index of symbol + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; // Base Address of module comtaining this symbol + ULONG Flags; + ULONG64 Value; // Value of symbol, ValuePresent should be 1 + ULONG64 Address; // Address of symbol including base address of module + ULONG Register; // register holding value or pointer to value + ULONG Scope; // scope of the symbol + ULONG Tag; // pdb classification + ULONG NameLen; // Actual length of name + ULONG MaxNameLen; + CHAR Name[1]; // Name of symbol + }; + + typedef BOOL (__stdcall *SymInitializeType)(HANDLE, PCSTR, BOOL); + typedef BOOL (__stdcall *SymFromAddrType)(HANDLE, DWORD64, PDWORD64, DBGHELP_SYMBOL_INFO *); + + void cleanup(); + + const HANDLE m_process; + HMODULE m_dbgHelpLib; + SymFromAddrType m_symFromAddr; +}; + +void DebugSymbolResolver::cleanup() +{ + if (m_dbgHelpLib) + FreeLibrary(m_dbgHelpLib); + m_dbgHelpLib = 0; + m_symFromAddr = Q_NULLPTR; +} + +DebugSymbolResolver::DebugSymbolResolver(HANDLE process) + : m_process(process), m_dbgHelpLib(0), m_symFromAddr(Q_NULLPTR) +{ + bool success = false; + m_dbgHelpLib = LoadLibraryW(L"dbghelp.dll"); + if (m_dbgHelpLib) { + SymInitializeType symInitialize = (SymInitializeType)(GetProcAddress(m_dbgHelpLib, "SymInitialize")); + m_symFromAddr = (SymFromAddrType)(GetProcAddress(m_dbgHelpLib, "SymFromAddr")); + success = symInitialize && m_symFromAddr && symInitialize(process, NULL, TRUE); + } + if (!success) + cleanup(); +} + +DebugSymbolResolver::Symbol DebugSymbolResolver::resolveSymbol(DWORD64 address) const +{ + // reserve additional buffer where SymFromAddr() will store the name + struct NamedSymbolInfo : public DBGHELP_SYMBOL_INFO { + enum { symbolNameLength = 255 }; + + char name[symbolNameLength + 1]; + }; + + Symbol result; + if (!isValid()) + return result; + NamedSymbolInfo symbolBuffer; + memset(&symbolBuffer, 0, sizeof(NamedSymbolInfo)); + symbolBuffer.MaxNameLen = NamedSymbolInfo::symbolNameLength; + symbolBuffer.SizeOfStruct = sizeof(DBGHELP_SYMBOL_INFO); + if (!m_symFromAddr(m_process, address, 0, &symbolBuffer)) + return result; + result.name = qstrdup(symbolBuffer.Name); + result.address = symbolBuffer.Address; + return result; +} + static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo) { + enum { maxStackFrames = 100 }; char appName[MAX_PATH]; if (!GetModuleFileNameA(NULL, appName, MAX_PATH)) appName[0] = 0; - fprintf(stderr, "A crash occurred in %s (exception code 0x%lx).", - appName, exInfo->ExceptionRecord->ExceptionCode); + const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); + const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); + const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress; + printf("A crash occurred in %s.\n" + "Function time: %dms Total time: %dms\n\n" + "Exception address: 0x%p\n" + "Exception code : 0x%lx\n", + appName, msecsFunctionTime, msecsTotalTime, + exceptionAddress, exInfo->ExceptionRecord->ExceptionCode); + + DebugSymbolResolver resolver(GetCurrentProcess()); + if (resolver.isValid()) { + DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress)); + if (exceptionSymbol.name) { + printf("Nearby symbol : %s\n", exceptionSymbol.name); + delete [] exceptionSymbol.name; + } + void *stack[maxStackFrames]; + fputs("\nStack:\n", stdout); + const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL); + for (unsigned f = 0; f < frameCount; ++f) { + DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[f])); + if (symbol.name) { + printf("#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address); + delete [] symbol.name; + } else { + printf("#%3u: Unable to obtain symbol\n", f + 1); + } + } + } + + fputc('\n', stdout); + fflush(stdout); + return EXCEPTION_EXECUTE_HANDLER; } #endif // Q_OS_WIN) && !Q_OS_WINCE && !Q_OS_WINRT @@ -2911,7 +3219,7 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co QString testsPath = QLibraryInfo::location(QLibraryInfo::TestsPath); QString candidate = QString::fromLatin1("%1/%2/%3") .arg(testsPath, QFile::decodeName(testObjectName).toLower(), base); - if (QFileInfo(candidate).exists()) { + if (QFileInfo::exists(candidate)) { found = candidate; } else if (QTestLog::verboseLevel() >= 2) { @@ -2936,7 +3244,7 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co } QString candidate = QString::fromLatin1("%1/%2").arg(srcdir.canonicalFilePath(), base); - if (QFileInfo(candidate).exists()) { + if (QFileInfo::exists(candidate)) { found = candidate; } else if (QTestLog::verboseLevel() >= 2) { @@ -2950,21 +3258,21 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co // 4. Try resources if (found.isEmpty()) { QString candidate = QString::fromLatin1(":/%1").arg(base); - if (QFileInfo(candidate).exists()) + if (QFileInfo::exists(candidate)) found = candidate; } // 5. Try current directory if (found.isEmpty()) { QString candidate = QString::fromLatin1("%1/%2").arg(QDir::currentPath()).arg(base); - if (QFileInfo(candidate).exists()) + if (QFileInfo::exists(candidate)) found = candidate; } // 6. Try main source directory if (found.isEmpty()) { QString candidate = QTest::mainSourcePath % QLatin1Char('/') % base; - if (QFileInfo(candidate).exists()) + if (QFileInfo::exists(candidate)) found = candidate; } @@ -3237,6 +3545,8 @@ TO_STRING_IMPL(quint64, %llu) #endif TO_STRING_IMPL(bool, %d) TO_STRING_IMPL(char, %c) +TO_STRING_IMPL(signed char, %hhd) +TO_STRING_IMPL(unsigned char, %hhu) TO_STRING_IMPL(float, %g) TO_STRING_IMPL(double, %lg) @@ -3372,10 +3682,6 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac \internal */ -/*! \fn bool QTest::qCompare(bool const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line) - \internal - */ - /*! \fn bool QTest::qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line) \internal */ diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index f24283b65e..9d79439e04 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -39,6 +39,7 @@ #include <QtCore/qstring.h> #include <QtCore/qnamespace.h> #include <QtCore/qmetatype.h> +#include <QtCore/qmetaobject.h> #include <QtCore/qtypetraits.h> #include <QtCore/qsharedpointer.h> #include <QtCore/qtemporarydir.h> @@ -157,6 +158,15 @@ do { \ #define QTRY_VERIFY(__expr) QTRY_VERIFY_WITH_TIMEOUT((__expr), 5000) +// Will try to wait for the expression to become true while allowing event processing +#define QTRY_VERIFY2_WITH_TIMEOUT(__expr, __messageExpression, __timeout) \ +do { \ + QTRY_IMPL((__expr), __timeout);\ + QVERIFY2(__expr, __messageExpression); \ +} while (0) + +#define QTRY_VERIFY2(__expr, __messageExpression) QTRY_VERIFY2_WITH_TIMEOUT((__expr), (__messageExpression), 5000) + // Will try to wait for the comparison to become successful while allowing event processing #define QTRY_COMPARE_WITH_TIMEOUT(__expr, __expected, __timeout) \ do { \ @@ -222,12 +232,28 @@ class QTestData; namespace QTest { - template <typename T> - inline char *toString(const T &) + namespace Internal { + + template<typename T> // Output registered enums + inline typename QtPrivate::QEnableIf<QtPrivate::IsQEnumHelper<T>::Value, char*>::Type toString(T e) + { + QMetaEnum me = QMetaEnum::fromType<T>(); + return qstrdup(me.key(int(e))); // int cast is necessary to support enum classes + } + + template <typename T> // Fallback + inline typename QtPrivate::QEnableIf<!QtPrivate::IsQEnumHelper<T>::Value, char*>::Type toString(const T &) { - return 0; + return Q_NULLPTR; } + } // namespace Internal + + template<typename T> + inline char *toString(const T &t) + { + return Internal::toString(t); + } Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length); Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length); @@ -235,10 +261,10 @@ namespace QTest Q_TESTLIB_EXPORT char *toString(const char *); Q_TESTLIB_EXPORT char *toString(const void *); - Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = 0); + Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR); Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments); - Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = 0); + Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = Q_NULLPTR); Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description, const char *file, int line); @@ -246,15 +272,15 @@ namespace QTest Q_TESTLIB_EXPORT void qSkip(const char *message, const char *file, int line); Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, const char *file, int line); - Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = 0, int line = 0); + Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = Q_NULLPTR, int line = 0); Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message); #ifndef QT_NO_REGULAREXPRESSION Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern); #endif Q_TESTLIB_EXPORT QSharedPointer<QTemporaryDir> qExtractTestData(const QString &dirName); - Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = 0, int line = 0, const char* builddir = 0); - Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = 0, int line = 0, const char* builddir = 0); + Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = Q_NULLPTR, int line = 0, const char* builddir = Q_NULLPTR); + Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = Q_NULLPTR, int line = 0, const char* builddir = Q_NULLPTR); Q_TESTLIB_EXPORT void *qData(const char *tagName, int typeId); Q_TESTLIB_EXPORT void *qGlobalData(const char *tagName, int typeId); @@ -323,6 +349,8 @@ namespace QTest QTEST_COMPARE_DECL(float) QTEST_COMPARE_DECL(double) QTEST_COMPARE_DECL(char) + QTEST_COMPARE_DECL(signed char) + QTEST_COMPARE_DECL(unsigned char) QTEST_COMPARE_DECL(bool) #endif @@ -392,14 +420,6 @@ namespace QTest return compare_string_helper(t1, t2, actual, expected, file, line); } - // NokiaX86 and RVCT do not like implicitly comparing bool with int - inline bool qCompare(bool const &t1, int const &t2, - const char *actual, const char *expected, const char *file, int line) - { - return qCompare(int(t1), t2, actual, expected, file, line); - } - - template <class T> inline bool qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line) diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h index a3e5f02ec1..9794b15f4a 100644 --- a/src/testlib/qtestevent.h +++ b/src/testlib/qtestevent.h @@ -185,20 +185,20 @@ public: inline void addKeyEvent(QTest::KeyAction action, char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1) { append(new QTestKeyEvent(action, ascii, modifiers, msecs)); } - inline void addMousePress(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void addMousePress(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { append(new QTestMouseEvent(QTest::MousePress, button, stateKey, pos, delay)); } - inline void addMouseRelease(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void addMouseRelease(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { append(new QTestMouseEvent(QTest::MouseRelease, button, stateKey, pos, delay)); } - inline void addMouseClick(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void addMouseClick(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { append(new QTestMouseEvent(QTest::MouseClick, button, stateKey, pos, delay)); } - inline void addMouseDClick(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void addMouseDClick(Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { append(new QTestMouseEvent(QTest::MouseDClick, button, stateKey, pos, delay)); } inline void addMouseMove(QPoint pos = QPoint(), int delay=-1) - { append(new QTestMouseEvent(QTest::MouseMove, Qt::NoButton, 0, pos, delay)); } + { append(new QTestMouseEvent(QTest::MouseMove, Qt::NoButton, Qt::KeyboardModifiers(), pos, delay)); } #endif //QT_GUI_LIB inline void addDelay(int msecs) diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h index a9f611f306..a8ce619d4e 100644 --- a/src/testlib/qtesteventloop.h +++ b/src/testlib/qtesteventloop.h @@ -50,8 +50,8 @@ class Q_TESTLIB_EXPORT QTestEventLoop : public QObject Q_OBJECT public: - inline QTestEventLoop(QObject *aParent = 0) - : QObject(aParent), inLoop(false), _timeout(false), timerId(-1), loop(0) {} + inline QTestEventLoop(QObject *aParent = Q_NULLPTR) + : QObject(aParent), inLoop(false), _timeout(false), timerId(-1), loop(Q_NULLPTR) {} inline void enterLoopMSecs(int ms); inline void enterLoop(int secs) { enterLoopMSecs(secs * 1000); } @@ -97,7 +97,7 @@ inline void QTestEventLoop::enterLoopMSecs(int ms) loop = &l; l.exec(); - loop = 0; + loop = Q_NULLPTR; } inline void QTestEventLoop::exitLoop() diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 39520d621f..d2b3ef240b 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -57,11 +57,11 @@ QT_BEGIN_NAMESPACE Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); -Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); +Q_GUI_EXPORT bool qt_handleShortcutEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); namespace QTest { - enum KeyAction { Press, Release, Click }; + enum KeyAction { Press, Release, Click, Shortcut }; static void simulateEvent(QWindow *window, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) @@ -95,9 +95,15 @@ namespace QTest bool repeat = false; + if (action == Shortcut) { + int timestamp = 0; + qt_handleShortcutEvent(window, timestamp, code, modifier, text, repeat); + return; + } + if (action == Press) { if (modifier & Qt::ShiftModifier) - simulateEvent(window, true, Qt::Key_Shift, 0, QString(), false, delay); + simulateEvent(window, true, Qt::Key_Shift, Qt::KeyboardModifiers(), QString(), false, delay); if (modifier & Qt::ControlModifier) simulateEvent(window, true, Qt::Key_Control, modifier & Qt::ShiftModifier, QString(), false, delay); @@ -172,7 +178,7 @@ namespace QTest QKeyEvent a(press ? QEvent::KeyPress : QEvent::KeyRelease, code, modifier, text, repeat); QSpontaneKeyEvent::setSpontaneous(&a); - if (press && qt_sendShortcutOverrideEvent(widget, a.timestamp(), code, modifier, text, repeat)) + if (press && qt_handleShortcutEvent(widget, a.timestamp(), code, modifier, text, repeat)) return; if (!qApp->notify(widget, &a)) QTest::qWarn("Keyboard event not accepted by receiving widget"); @@ -220,7 +226,7 @@ namespace QTest if (action == Press) { if (modifier & Qt::ShiftModifier) - simulateEvent(widget, true, Qt::Key_Shift, 0, QString(), false, delay); + simulateEvent(widget, true, Qt::Key_Shift, Qt::KeyboardModifiers(), QString(), false, delay); if (modifier & Qt::ControlModifier) simulateEvent(widget, true, Qt::Key_Control, modifier & Qt::ShiftModifier, QString(), false, delay); diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 59aeb27ffe..3513e10eec 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -46,6 +46,7 @@ #include <QtCore/qatomic.h> #include <QtCore/qbytearray.h> +#include <QtCore/QElapsedTimer> #include <QtCore/QVariant> #include <QtCore/QRegularExpression> @@ -75,6 +76,9 @@ static void saveCoverageTool(const char * appname, bool testfailed, bool install #endif } +static QElapsedTimer elapsedFunctionTime; +static QElapsedTimer elapsedTotalTime; + namespace QTest { int fails = 0; @@ -325,6 +329,7 @@ namespace QTest { void QTestLog::enterTestFunction(const char* function) { + elapsedFunctionTime.restart(); if (printAvailableTags) return; @@ -450,6 +455,8 @@ void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) void QTestLog::startLogging() { + elapsedTotalTime.start(); + elapsedFunctionTime.start(); QTest::TestLoggers::startLogging(); QTest::oldMessageHandler = qInstallMessageHandler(QTest::messageHandler); } @@ -597,4 +604,14 @@ bool QTestLog::installedTestCoverage() return QTest::installedTestCoverage; } +qint64 QTestLog::nsecsTotalTime() +{ + return elapsedTotalTime.nsecsElapsed(); +} + +qint64 QTestLog::nsecsFunctionTime() +{ + return elapsedFunctionTime.nsecsElapsed(); +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index b4786b4904..b7e9d16ec3 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -110,6 +110,11 @@ public: static void setInstalledTestCoverage(bool installed); static bool installedTestCoverage(); + static qint64 nsecsTotalTime(); + static qreal msecsTotalTime() { return QTestLog::nsecsTotalTime() / 1000000.; } + static qint64 nsecsFunctionTime(); + static qreal msecsFunctionTime() { return QTestLog::nsecsFunctionTime() / 1000000.; } + private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qtestmouse.cpp b/src/testlib/qtestmouse.cpp new file mode 100644 index 0000000000..99a75744fa --- /dev/null +++ b/src/testlib/qtestmouse.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtTest module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QtGlobal> +#include <QtCore/qnamespace.h> +#include <QtTest/qtest_global.h> + +QT_BEGIN_NAMESPACE + +namespace QTest { + +Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton = Qt::NoButton; +Q_TESTLIB_EXPORT int lastMouseTimestamp = 0; + +} // namespace QTest + +QT_END_NAMESPACE diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h index ad6671af02..c5969a1603 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -45,6 +45,7 @@ #include <QtTest/qtestspontaneevent.h> #include <QtCore/qpoint.h> #include <QtCore/qstring.h> +#include <QtCore/qpointer.h> #include <QtGui/qevent.h> #include <QtGui/qwindow.h> @@ -57,12 +58,15 @@ QT_BEGIN_NAMESPACE -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); +Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp); namespace QTest { enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove }; + extern Q_TESTLIB_EXPORT Qt::MouseButton lastMouseButton; + extern Q_TESTLIB_EXPORT int lastMouseTimestamp; + static void waitForEvents() { #ifdef Q_OS_MAC @@ -83,76 +87,85 @@ namespace QTest QTest::qWarn("Mouse event occurs outside of target window."); } - static Qt::MouseButton lastButton = Qt::NoButton; - if (delay == -1 || delay < defaultMouseDelay()) delay = defaultMouseDelay(); - if (delay > 0) + if (delay > 0) { QTest::qWait(delay); + lastMouseTimestamp += delay; + } if (pos.isNull()) - pos = window->geometry().center(); + pos = QPoint(window->width() / 2, window->height() / 2); - if (action == MouseClick) { - mouseEvent(MousePress, window, button, stateKey, pos); - mouseEvent(MouseRelease, window, button, stateKey, pos); - return; - } QTEST_ASSERT(uint(stateKey) == 0 || stateKey & Qt::KeyboardModifierMask); stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask); + QPointF global = window->mapToGlobal(pos); + QPointer<QWindow> w(window); switch (action) { - case MousePress: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - lastButton = button; - break; - case MouseRelease: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - lastButton = Qt::NoButton; - break; - case MouseDClick: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - qWait(10); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - qWait(20); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),button,stateKey); - qWait(10); - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),Qt::NoButton,stateKey); - break; - case MouseMove: - qt_handleMouseEvent(window,pos,window->mapToGlobal(pos),lastButton,stateKey); - // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system - // which is highly undesired here. Tests must avoid relying on QCursor. + case MouseDClick: + qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp); + qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp); + // fall through + case MousePress: + case MouseClick: + qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp); + lastMouseButton = button; + if (action == MousePress) break; - default: - QTEST_ASSERT(false); + // fall through + case MouseRelease: + qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp); + lastMouseTimestamp += 500; // avoid double clicks being generated + lastMouseButton = Qt::NoButton; + break; + case MouseMove: + qt_handleMouseEvent(w, pos, global, lastMouseButton, stateKey, ++lastMouseTimestamp); + // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system + // which is highly undesired here. Tests must avoid relying on QCursor. + break; + default: + QTEST_ASSERT(false); } waitForEvents(); } - inline void mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mousePress(QWindow *window, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MousePress, window, button, stateKey, pos, delay); } - inline void mouseRelease(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseRelease(QWindow *window, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseRelease, window, button, stateKey, pos, delay); } - inline void mouseClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseClick(QWindow *window, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseClick, window, button, stateKey, pos, delay); } - inline void mouseDClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseDClick(QWindow *window, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseDClick, window, button, stateKey, pos, delay); } inline void mouseMove(QWindow *window, QPoint pos = QPoint(), int delay=-1) - { mouseEvent(MouseMove, window, Qt::NoButton, 0, pos, delay); } + { mouseEvent(MouseMove, window, Qt::NoButton, Qt::KeyboardModifiers(), pos, delay); } #ifdef QT_WIDGETS_LIB static void mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) { QTEST_ASSERT(widget); + + if (pos.isNull()) + pos = widget->rect().center(); + +#ifdef QTEST_QPA_MOUSE_HANDLING + QWindow *w = widget->window()->windowHandle(); + QTEST_ASSERT(w); + mouseEvent(action, w, button, stateKey, w->mapFromGlobal(widget->mapToGlobal(pos)), delay); +#else extern int Q_TESTLIB_EXPORT defaultMouseDelay(); if (delay == -1 || delay < defaultMouseDelay()) @@ -160,9 +173,6 @@ namespace QTest if (delay > 0) QTest::qWait(delay); - if (pos.isNull()) - pos = widget->rect().center(); - if (action == MouseClick) { mouseEvent(MousePress, widget, button, stateKey, pos); mouseEvent(MouseRelease, widget, button, stateKey, pos); @@ -180,7 +190,7 @@ namespace QTest me = QMouseEvent(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, button, stateKey); break; case MouseRelease: - me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, 0, stateKey); + me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, Qt::MouseButton(), stateKey); break; case MouseDClick: me = QMouseEvent(QEvent::MouseButtonDblClick, pos, widget->mapToGlobal(pos), button, button, stateKey); @@ -203,23 +213,27 @@ namespace QTest QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget"); QTest::qWarn(warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])).toLatin1().data()); } - +#endif } - inline void mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mousePress(QWidget *widget, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MousePress, widget, button, stateKey, pos, delay); } - inline void mouseRelease(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseRelease(QWidget *widget, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseRelease, widget, button, stateKey, pos, delay); } - inline void mouseClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseClick(QWidget *widget, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseClick, widget, button, stateKey, pos, delay); } - inline void mouseDClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, + inline void mouseDClick(QWidget *widget, Qt::MouseButton button, + Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers(), QPoint pos = QPoint(), int delay=-1) { mouseEvent(MouseDClick, widget, button, stateKey, pos, delay); } inline void mouseMove(QWidget *widget, QPoint pos = QPoint(), int delay=-1) - { mouseEvent(MouseMove, widget, Qt::NoButton, 0, pos, delay); } + { mouseEvent(MouseMove, widget, Qt::NoButton, Qt::KeyboardModifiers(), pos, delay); } #endif // QT_WIDGETS_LIB } diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index c65927ba7c..24689c6e87 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -235,17 +235,17 @@ bool QTestResult::verify(bool statement, const char *statementStr, { QTEST_ASSERT(statementStr); - char msg[1024]; + char msg[1024] = {'\0'}; if (QTestLog::verboseLevel() >= 2) { qsnprintf(msg, 1024, "QVERIFY(%s)", statementStr); QTestLog::info(msg, file, line); } - const char * format = QTest::expectFailMode - ? "'%s' returned TRUE unexpectedly. (%s)" - : "'%s' returned FALSE. (%s)"; - qsnprintf(msg, 1024, format, statementStr, description ? description : ""); + if (!statement && !QTest::expectFailMode) + qsnprintf(msg, 1024, "'%s' returned FALSE. (%s)", statementStr, description ? description : ""); + else if (statement && QTest::expectFailMode) + qsnprintf(msg, 1024, "'%s' returned TRUE unexpectedly. (%s)", statementStr, description ? description : ""); return checkStatement(statement, msg, file, line); } @@ -259,7 +259,7 @@ bool QTestResult::compare(bool success, const char *failureMsg, QTEST_ASSERT(actual); const size_t maxMsgLen = 1024; - char msg[maxMsgLen]; + char msg[maxMsgLen] = {'\0'}; if (QTestLog::verboseLevel() >= 2) { qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); @@ -269,9 +269,11 @@ bool QTestResult::compare(bool success, const char *failureMsg, if (!failureMsg) failureMsg = "Compared values are not the same"; - if (success && QTest::expectFailMode) { - qsnprintf(msg, maxMsgLen, - "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); + if (success) { + if (QTest::expectFailMode) { + qsnprintf(msg, maxMsgLen, + "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); + } } else if (val1 || val2) { size_t len1 = mbstowcs(NULL, actual, maxMsgLen); // Last parameter is not ignored on QNX size_t len2 = mbstowcs(NULL, expected, maxMsgLen); // (result is never larger than this). diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h index 50acc6136d..f81ede519c 100644 --- a/src/testlib/qtestsystem.h +++ b/src/testlib/qtestsystem.h @@ -56,7 +56,7 @@ namespace QTest timer.start(); do { QCoreApplication::processEvents(QEventLoop::AllEvents, ms); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete); QTest::qSleep(10); } while (timer.elapsed() < ms); } @@ -71,7 +71,7 @@ namespace QTest if (remaining <= 0) break; QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete); QTest::qSleep(10); } // Try ensuring the platform window receives the real position. @@ -100,7 +100,7 @@ namespace QTest if (remaining <= 0) break; QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete); QTest::qSleep(10); } return window->isExposed(); diff --git a/src/testlib/qtesttable.cpp b/src/testlib/qtesttable.cpp index 497b2649c5..05cce37a47 100644 --- a/src/testlib/qtesttable.cpp +++ b/src/testlib/qtesttable.cpp @@ -38,37 +38,35 @@ #include <QtCore/qmetaobject.h> #include <string.h> +#include <vector> +#include <algorithm> QT_BEGIN_NAMESPACE class QTestTablePrivate { public: - struct ElementList + ~QTestTablePrivate() { - ElementList(): elementName(0), elementType(0), next(0) {} - const char *elementName; - int elementType; - ElementList *next; - }; + qDeleteAll(dataList.begin(), dataList.end()); + } - struct DataList - { - DataList(): data(0), next(0) {} - QTestData *data; - DataList *next; + struct Element { + Element() : name(Q_NULLPTR), type(0) {} + Element(const char *n, int t) : name(n), type(t) {} + + const char *name; + int type; }; - QTestTablePrivate(): list(0), dataList(0) {} - ~QTestTablePrivate(); + typedef std::vector<Element> ElementList; + ElementList elementList; - ElementList *list; - DataList *dataList; + typedef std::vector<QTestData *> DataList; + DataList dataList; - void addColumn(int elemType, const char *elemName); - void addRow(QTestData *data); - ElementList *elementAt(int index); - QTestData *dataAt(int index); + void addColumn(int elemType, const char *elemName) { elementList.push_back(Element(elemName, elemType)); } + void addRow(QTestData *data) { dataList.push_back(data); } static QTestTable *currentTestTable; static QTestTable *gTable; @@ -77,74 +75,6 @@ public: QTestTable *QTestTablePrivate::currentTestTable = 0; QTestTable *QTestTablePrivate::gTable = 0; -QTestTablePrivate::ElementList *QTestTablePrivate::elementAt(int index) -{ - ElementList *iter = list; - for (int i = 0; i < index; ++i) { - if (!iter) - return 0; - iter = iter->next; - } - return iter; -} - -QTestData *QTestTablePrivate::dataAt(int index) -{ - DataList *iter = dataList; - for (int i = 0; i < index; ++i) { - if (!iter) - return 0; - iter = iter->next; - } - return iter ? iter->data : 0; -} - -QTestTablePrivate::~QTestTablePrivate() -{ - DataList *dit = dataList; - while (dit) { - DataList *next = dit->next; - delete dit->data; - delete dit; - dit = next; - } - ElementList *iter = list; - while (iter) { - ElementList *next = iter->next; - delete iter; - iter = next; - } -} - -void QTestTablePrivate::addColumn(int elemType, const char *elemName) -{ - ElementList *item = new ElementList; - item->elementName = elemName; - item->elementType = elemType; - if (!list) { - list = item; - return; - } - ElementList *last = list; - while (last->next != 0) - last = last->next; - last->next = item; -} - -void QTestTablePrivate::addRow(QTestData *data) -{ - DataList *item = new DataList; - item->data = data; - if (!dataList) { - dataList = item; - return; - } - DataList *last = dataList; - while (last->next != 0) - last = last->next; - last->next = item; -} - void QTestTable::addColumn(int type, const char *name) { QTEST_ASSERT(type); @@ -155,30 +85,17 @@ void QTestTable::addColumn(int type, const char *name) int QTestTable::elementCount() const { - QTestTablePrivate::ElementList *item = d->list; - int count = 0; - while (item) { - ++count; - item = item->next; - } - return count; + return int(d->elementList.size()); } - int QTestTable::dataCount() const { - QTestTablePrivate::DataList *item = d->dataList; - int count = 0; - while (item) { - ++count; - item = item->next; - } - return count; + return int(d->dataList.size()); } bool QTestTable::isEmpty() const { - return !d->list; + return d->elementList.empty(); } QTestData *QTestTable::newData(const char *tag) @@ -202,38 +119,43 @@ QTestTable::~QTestTable() int QTestTable::elementTypeId(int index) const { - QTestTablePrivate::ElementList *item = d->elementAt(index); - if (!item) - return -1; - return item->elementType; + return size_t(index) < d->elementList.size() ? d->elementList[index].type : -1; } const char *QTestTable::dataTag(int index) const { - QTestTablePrivate::ElementList *item = d->elementAt(index); - if (!item) - return 0; - return item->elementName; + return size_t(index) < d->elementList.size() ? d->elementList[index].name : Q_NULLPTR; } QTestData *QTestTable::testData(int index) const { - return d->dataAt(index); + return size_t(index) < d->dataList.size() ? d->dataList[index] : Q_NULLPTR; } +class NamePredicate : public std::unary_function<QTestTablePrivate::Element, bool> +{ +public: + explicit NamePredicate(const char *needle) : m_needle(needle) {} + + bool operator()(const QTestTablePrivate::Element &e) const + { return !strcmp(e.name, m_needle); } + +private: + const char *m_needle; +}; + int QTestTable::indexOf(const char *elementName) const { + typedef QTestTablePrivate::ElementList::const_iterator It; + QTEST_ASSERT(elementName); - QTestTablePrivate::ElementList *item = d->list; - int i = 0; - while (item) { - if (strcmp(elementName, item->elementName) == 0) - return i; - item = item->next; - ++i; - } - return -1; + const QTestTablePrivate::ElementList &elementList = d->elementList; + + const It it = std::find_if(elementList.begin(), elementList.end(), + NamePredicate(elementName)); + return it != elementList.end() ? + int(it - elementList.begin()) : -1; } QTestTable *QTestTable::globalTestTable() diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h index 5dcdca808b..8e782d17d7 100644 --- a/src/testlib/qtesttouch.h +++ b/src/testlib/qtesttouch.h @@ -68,21 +68,21 @@ namespace QTest if (commitWhenDestroyed) commit(); } - QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = 0) + QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(window, pt)); p.setState(Qt::TouchPointPressed); return *this; } - QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = 0) + QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(window, pt)); p.setState(Qt::TouchPointMoved); return *this; } - QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = 0) + QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(window, pt)); @@ -97,21 +97,21 @@ namespace QTest } #ifdef QT_WIDGETS_LIB - QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = 0) + QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(widget, pt)); p.setState(Qt::TouchPointPressed); return *this; } - QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = 0) + QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(widget, pt)); p.setState(Qt::TouchPointMoved); return *this; } - QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = 0) + QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR) { QTouchEvent::TouchPoint &p = point(touchId); p.setScreenPos(mapToScreen(widget, pt)); @@ -143,14 +143,14 @@ namespace QTest private: #ifdef QT_WIDGETS_LIB QTouchEventSequence(QWidget *widget, QTouchDevice *aDevice, bool autoCommit) - : targetWidget(widget), targetWindow(0), device(aDevice), commitWhenDestroyed(autoCommit) + : targetWidget(widget), targetWindow(Q_NULLPTR), device(aDevice), commitWhenDestroyed(autoCommit) { } #endif QTouchEventSequence(QWindow *window, QTouchDevice *aDevice, bool autoCommit) : #ifdef QT_WIDGETS_LIB - targetWidget(0), + targetWidget(Q_NULLPTR), #endif targetWindow(window), device(aDevice), commitWhenDestroyed(autoCommit) { diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index bf607b4702..f96b5647e4 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -36,6 +36,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qlibraryinfo.h> +#include <QtTest/private/qtestlog_p.h> #include <QtTest/private/qxmltestlogger_p.h> #include <QtTest/private/qtestresult_p.h> #include <QtTest/private/qbenchmark_p.h> @@ -124,15 +125,13 @@ void QXmlTestLogger::startLogging() " <QTestVersion>" QTEST_VERSION_STR "</QTestVersion>\n" "</Environment>\n", qVersion(), quotedBuild.constData()); outputString(buf.constData()); - m_totalTime.start(); } void QXmlTestLogger::stopLogging() { QTestCharBuffer buf; QTest::qt_asprintf(&buf, - "<Duration msecs=\"%f\"/>\n", - m_totalTime.nsecsElapsed() / 1000000.); + "<Duration msecs=\"%f\"/>\n", QTestLog::msecsTotalTime()); outputString(buf.constData()); if (xmlmode == QXmlTestLogger::Complete) { outputString("</TestCase>\n"); @@ -148,8 +147,6 @@ void QXmlTestLogger::enterTestFunction(const char *function) xmlQuote("edFunction, function); QTest::qt_asprintf(&buf, "<TestFunction name=\"%s\">\n", quotedFunction.constData()); outputString(buf.constData()); - - m_functionTime.start(); } void QXmlTestLogger::leaveTestFunction() @@ -158,7 +155,7 @@ void QXmlTestLogger::leaveTestFunction() QTest::qt_asprintf(&buf, " <Duration msecs=\"%f\"/>\n" "</TestFunction>\n", - m_functionTime.nsecsElapsed() / 1000000.); + QTestLog::msecsFunctionTime()); outputString(buf.constData()); } diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index 5cf8b4596c..49a21d9ca1 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -47,7 +47,6 @@ #include <QtTest/private/qabstracttestlogger_p.h> -#include <QtCore/qelapsedtimer.h> QT_BEGIN_NAMESPACE @@ -79,8 +78,6 @@ public: private: XmlMode xmlmode; - QElapsedTimer m_functionTime; - QElapsedTimer m_totalTime; }; QT_END_NAMESPACE diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 79fd342cca..ff4379f85d 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -56,6 +56,7 @@ SOURCES = qtestcase.cpp \ qcsvbenchmarklogger.cpp \ qtestelement.cpp \ qtestelementattribute.cpp \ + qtestmouse.cpp \ qtestxunitstreamer.cpp \ qxunittestlogger.cpp \ qtestblacklist.cpp @@ -91,7 +92,7 @@ mac { # don't know yet if the target that links to testlib will build under Xcode or not. # The corresponding flags for the target lives in xctest.prf, where we do know. QMAKE_LFLAGS += -F$${platform_dev_frameworks_path} -weak_framework XCTest - QMAKE_OBJECTIVE_CFLAGS += -F$${platform_dev_frameworks_path} + QMAKE_CXXFLAGS += -F$${platform_dev_frameworks_path} MODULE_CONFIG += xctest } } |