summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/doc/qttestlib.qdocconf3
-rw-r--r--src/testlib/qtest.h31
-rw-r--r--src/testlib/qtestblacklist.cpp27
-rw-r--r--src/testlib/qtestblacklist_p.h6
-rw-r--r--src/testlib/qtestcase.cpp24
-rw-r--r--src/testlib/qtestcase.h2
-rw-r--r--src/testlib/qtestmouse.cpp47
-rw-r--r--src/testlib/qtestmouse.h80
-rw-r--r--src/testlib/testlib.pro1
9 files changed, 180 insertions, 41 deletions
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 35b4fbcb7b..0fafc733b1 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -40,5 +40,8 @@ excludedirs += ../../../examples/widgets/doc
imagedirs += images
+# Add a thumbnail for examples that do not have images
+manifestmeta.thumbnail.names = "QtTestLib/Chapter *"
+
navigation.landingpage = "Qt Test"
navigation.cppclassespage = "Qt Test C++ Classes"
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 81cc07c410..994179958b 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -274,14 +274,33 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
}
QT_END_NAMESPACE
+#ifdef QT_TESTCASE_BUILDDIR
+# define QTEST_SET_MAIN_SOURCE_PATH QTest::setMainSourcePath(__FILE__, QT_TESTCASE_BUILDDIR);
+#else
+# define QTEST_SET_MAIN_SOURCE_PATH QTest::setMainSourcePath(__FILE__);
+#endif
+
#define QTEST_APPLESS_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
#include <QtTest/qtestsystem.h>
+#include <set>
+
+#ifndef QT_NO_OPENGL
+# define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+ extern Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &); \
+ extern Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &);
+# define QTEST_ADD_GPU_BLACKLIST_SUPPORT \
+ qgpu_features_ptr = qgpu_features;
+#else
+# define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+# define QTEST_ADD_GPU_BLACKLIST_SUPPORT
+#endif
#if defined(QT_WIDGETS_LIB)
@@ -294,12 +313,17 @@ int main(int argc, char *argv[]) \
#endif
#define QTEST_MAIN(TestObject) \
+QT_BEGIN_NAMESPACE \
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+QT_END_NAMESPACE \
int main(int argc, char *argv[]) \
{ \
QApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
QTEST_DISABLE_KEYPAD_NAVIGATION \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
@@ -308,11 +332,16 @@ int main(int argc, char *argv[]) \
#include <QtTest/qtest_gui.h>
#define QTEST_MAIN(TestObject) \
+QT_BEGIN_NAMESPACE \
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+QT_END_NAMESPACE \
int main(int argc, char *argv[]) \
{ \
QGuiApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
@@ -324,6 +353,7 @@ int main(int argc, char *argv[]) \
QCoreApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
@@ -335,6 +365,7 @@ int main(int argc, char *argv[]) \
QCoreApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index bfeca08617..f9ce908a00 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -34,6 +34,7 @@
#include "qtestresult_p.h"
#include <QtTest/qtestcase.h>
+#include <QtTest/qtest.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
#include <QtCore/qset.h>
@@ -161,6 +162,9 @@ static bool checkCondition(const QByteArray &condition)
static bool ignoreAll = false;
static std::set<QByteArray> *ignoredTests = 0;
+static std::set<QByteArray> *gpuFeatures = 0;
+
+Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &) = 0;
namespace QTestPrivate {
@@ -196,7 +200,18 @@ void parseBlackList()
}
}
-void checkBlackList(const char *slot, const char *data)
+void parseGpuBlackList()
+{
+ if (!qgpu_features_ptr)
+ return;
+ QString filename = QTest::qFindTestData(QStringLiteral("GPU_BLACKLIST"));
+ if (filename.isEmpty())
+ return;
+ if (!gpuFeatures)
+ gpuFeatures = qgpu_features_ptr(filename);
+}
+
+void checkBlackLists(const char *slot, const char *data)
{
bool ignore = ignoreAll;
@@ -211,6 +226,16 @@ void checkBlackList(const char *slot, const char *data)
}
QTestResult::setBlacklistCurrentTest(ignore);
+
+ // 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__);
+ }
+ }
}
}
diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h
index 158d99593e..87f4dfdb5e 100644
--- a/src/testlib/qtestblacklist_p.h
+++ b/src/testlib/qtestblacklist_p.h
@@ -50,8 +50,10 @@
QT_BEGIN_NAMESPACE
namespace QTestPrivate {
- void parseBlackList();
- void checkBlackList(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 e1e6805a0f..858475f396 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1374,6 +1374,7 @@ static bool installCoverageTool(const char * appname, const char * testname)
namespace QTest
{
static QObject *currentTestObject = 0;
+ static QString mainSourcePath;
class TestFunction {
public:
@@ -2167,7 +2168,7 @@ static bool qInvokeTestMethod(const char *slotName, const char *data, WatchDog *
if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
foundFunction = true;
- QTestPrivate::checkBlackList(slot, dataCount ? table.testData(curDataIndex)->dataTag() : 0);
+ QTestPrivate::checkBlackLists(slot, dataCount ? table.testData(curDataIndex)->dataTag() : 0);
QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
: table.testData(curDataIndex));
@@ -2682,6 +2683,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
#endif
QTestPrivate::parseBlackList();
+ QTestPrivate::parseGpuBlackList();
QTestResult::reset();
@@ -3032,6 +3034,13 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co
found = candidate;
}
+ // 6. Try main source directory
+ if (found.isEmpty()) {
+ QString candidate = QTest::mainSourcePath % QLatin1Char('/') % base;
+ if (QFileInfo(candidate).exists())
+ found = candidate;
+ }
+
if (found.isEmpty()) {
QTest::qWarn(qPrintable(
QString::fromLatin1("testdata %1 could not be located!").arg(base)),
@@ -3219,6 +3228,19 @@ QObject *QTest::testObject()
}
/*! \internal
+ */
+void QTest::setMainSourcePath(const char *file, const char *builddir)
+{
+ QString mainSourceFile = QFile::decodeName(file);
+ QFileInfo fi;
+ if (builddir)
+ fi.setFile(QDir(QFile::decodeName(builddir)), mainSourceFile);
+ else
+ fi.setFile(mainSourceFile);
+ QTest::mainSourcePath = fi.absolutePath();
+}
+
+/*! \internal
This function is called by various specializations of QTest::qCompare
to decide whether to report a failure and to produce verbose test output.
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index 45290de6de..2c6a94faa1 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -236,6 +236,8 @@ namespace QTest
Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = 0);
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 bool qVerify(bool statement, const char *statementStr, const char *description,
const char *file, int line);
Q_TESTLIB_EXPORT void qFail(const char *statementStr, const char *file, int line);
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 2cf84a7ea0..cd3901ae6f 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,52 +87,48 @@ 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();
- 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();
}
@@ -153,6 +153,15 @@ namespace QTest
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 +169,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);
@@ -198,12 +204,12 @@ namespace QTest
}
QSpontaneKeyEvent::setSpontaneous(&me);
if (!qApp->notify(widget, &me)) {
- static const char *mouseActionNames[] =
+ static const char *const mouseActionNames[] =
{ "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" };
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,
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 52bcdd097b..2d9bae5f31 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