summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/doc/qttestlib.qdocconf2
-rw-r--r--src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp2
-rw-r--r--src/testlib/qbenchmark_p.h2
-rw-r--r--src/testlib/qbenchmarkmetric.cpp2
-rw-r--r--src/testlib/qsignalspy.h9
-rw-r--r--src/testlib/qtest.h22
-rw-r--r--src/testlib/qtest_gui.h14
-rw-r--r--src/testlib/qtestaccessible.h17
-rw-r--r--src/testlib/qtestblacklist.cpp98
-rw-r--r--src/testlib/qtestblacklist_p.h7
-rw-r--r--src/testlib/qtestcase.cpp350
-rw-r--r--src/testlib/qtestcase.h52
-rw-r--r--src/testlib/qtestevent.h10
-rw-r--r--src/testlib/qtesteventloop.h6
-rw-r--r--src/testlib/qtestkeyboard.h16
-rw-r--r--src/testlib/qtestlog.cpp17
-rw-r--r--src/testlib/qtestlog_p.h5
-rw-r--r--src/testlib/qtestmouse.cpp47
-rw-r--r--src/testlib/qtestmouse.h110
-rw-r--r--src/testlib/qtestresult.cpp20
-rw-r--r--src/testlib/qtestsystem.h6
-rw-r--r--src/testlib/qtesttable.cpp164
-rw-r--r--src/testlib/qtesttouch.h16
-rw-r--r--src/testlib/qxmltestlogger.cpp9
-rw-r--r--src/testlib/qxmltestlogger_p.h3
-rw-r--r--src/testlib/testlib.pro3
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(&quotedFunction, 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
}
}