summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/qbenchmarkmetric.cpp190
-rw-r--r--src/testlib/qtest.h29
-rw-r--r--src/testlib/qtest_gui.h29
-rw-r--r--src/testlib/qtestblacklist.cpp14
-rw-r--r--src/testlib/qtestcase.cpp106
-rw-r--r--src/testlib/qtestcase.h22
-rw-r--r--src/testlib/qtestcase.qdoc34
-rw-r--r--src/testlib/qtestkeyboard.h20
-rw-r--r--src/testlib/qtestutil_macos.mm27
-rw-r--r--src/testlib/qtestutil_macos_p.h11
10 files changed, 303 insertions, 179 deletions
diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp
index 0ba55dbeb7..0f4f915ed3 100644
--- a/src/testlib/qbenchmarkmetric.cpp
+++ b/src/testlib/qbenchmarkmetric.cpp
@@ -40,6 +40,53 @@
#include <QtTest/private/qbenchmarkmetric_p.h>
+QT_BEGIN_NAMESPACE
+
+namespace QTest {
+
+struct QBenchmarkMetricKey {
+ int metric;
+ const char * name;
+ const char * unit;
+};
+
+static const QBenchmarkMetricKey entries[] = {
+ { FramesPerSecond, "FramesPerSecond", "fps" },
+ { BitsPerSecond, "BitsPerSecond", "bits/s" },
+ { BytesPerSecond, "BytesPerSecond", "bytes/s" },
+ { WalltimeMilliseconds, "WalltimeMilliseconds", "msecs" },
+ { CPUTicks, "CPUTicks", "CPU ticks" },
+ { InstructionReads, "InstructionReads", "instruction reads" },
+ { Events, "Events", "events" },
+ { WalltimeNanoseconds, "WalltimeNanoseconds", "nsecs" },
+ { BytesAllocated, "BytesAllocated", "bytes" },
+ { CPUMigrations, "CPUMigrations", "CPU migrations" },
+ { CPUCycles, "CPUCycles", "CPU cycles" },
+ { BusCycles, "BusCycles", "bus cycles" },
+ { StalledCycles, "StalledCycles", "stalled cycles" },
+ { Instructions, "Instructions", "instructions" },
+ { BranchInstructions, "BranchInstructions", "branch instructions" },
+ { BranchMisses, "BranchMisses", "branch misses" },
+ { CacheReferences, "CacheReferences", "cache references" },
+ { CacheReads, "CacheReads", "cache loads" },
+ { CacheWrites, "CacheWrites", "cache stores" },
+ { CachePrefetches, "CachePrefetches", "cache prefetches" },
+ { CacheMisses, "CacheMisses", "cache misses" },
+ { CacheReadMisses, "CacheReadMisses", "cache load misses" },
+ { CacheWriteMisses, "CacheWriteMisses", "cache store misses" },
+ { CachePrefetchMisses, "CachePrefetchMisses", "cache prefetch misses" },
+ { ContextSwitches, "ContextSwitches", "context switches" },
+ { PageFaults, "PageFaults", "page faults" },
+ { MinorPageFaults, "MinorPageFaults", "minor page faults" },
+ { MajorPageFaults, "MajorPageFaults", "major page faults" },
+ { AlignmentFaults, "AlignmentFaults", "alignment faults" },
+ { EmulationFaults, "EmulationFaults", "emulation faults" },
+ { RefCPUCycles, "RefCPUCycles", "Reference CPU cycles" },
+};
+static const int NumEntries = sizeof(entries) / sizeof(entries[0]);
+
+}
+
/*!
\enum QTest::QBenchmarkMetric
\since 4.7
@@ -92,73 +139,11 @@
*/
const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
{
- switch (metric) {
- case FramesPerSecond:
- return "FramesPerSecond";
- case BitsPerSecond:
- return "BitsPerSecond";
- case BytesPerSecond:
- return "BytesPerSecond";
- case WalltimeMilliseconds:
- return "WalltimeMilliseconds";
- case Events:
- return "Events";
- case CPUTicks:
- return "CPUTicks";
- case CPUMigrations:
- return "CPUMigrations";
- case CPUCycles:
- return "CPUCycles";
- case RefCPUCycles:
- return "RefCPUCycles";
- case BusCycles:
- return "BusCycles";
- case StalledCycles:
- return "StalledCycles";
- case InstructionReads:
- return "InstructionReads";
- case Instructions:
- return "Instructions";
- case WalltimeNanoseconds:
- return "WalltimeNanoseconds";
- case BytesAllocated:
- return "BytesAllocated";
- case BranchInstructions:
- return "BranchInstructions";
- case BranchMisses:
- return "BranchMisses";
- case CacheReferences:
- return "CacheReferences";
- case CacheReads:
- return "CacheReads";
- case CacheWrites:
- return "CacheWrites";
- case CachePrefetches:
- return "CachePrefetches";
- case CacheMisses:
- return "CacheMisses";
- case CacheReadMisses:
- return "CacheReadMisses";
- case CacheWriteMisses:
- return "CacheWriteMisses";
- case CachePrefetchMisses:
- return "CachePrefetchMisses";
- case ContextSwitches:
- return "ContextSwitches";
- case PageFaults:
- return "PageFaults";
- case MinorPageFaults:
- return "MinorPageFaults";
- case MajorPageFaults:
- return "MajorPageFaults";
- case AlignmentFaults:
- return "AlignmentFaults";
- case EmulationFaults:
- return "EmulationFaults";
- default:
- return "";
- }
-};
+ if (metric >= 0 && metric < QTest::NumEntries)
+ return entries[metric].name;
+
+ return "";
+}
/*!
\since 4.7
@@ -166,71 +151,10 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
*/
const char * QTest::benchmarkMetricUnit(QBenchmarkMetric metric)
{
- switch (metric) {
- case FramesPerSecond:
- return "fps";
- case BitsPerSecond:
- return "bits/s";
- case BytesPerSecond:
- return "bytes/s";
- case WalltimeMilliseconds:
- return "msecs";
- case Events:
- return "events";
- case CPUTicks:
- return "CPU ticks";
- case CPUMigrations:
- return "CPU migrations";
- case CPUCycles:
- return "CPU cycles";
- case RefCPUCycles:
- return "Reference CPU cycles";
- case BusCycles:
- return "bus cycles";
- case StalledCycles:
- return "stalled cycles";
- case InstructionReads:
- return "instruction reads";
- case Instructions:
- return "instructions";
- case WalltimeNanoseconds:
- return "nsecs";
- case BytesAllocated:
- return "bytes";
- case BranchInstructions:
- return "branch instructions";
- case BranchMisses:
- return "branch misses";
- case CacheReferences:
- return "cache references";
- case CacheReads:
- return "cache loads";
- case CacheWrites:
- return "cache stores";
- case CachePrefetches:
- return "cache prefetches";
- case CacheMisses:
- return "cache misses";
- case CacheReadMisses:
- return "cache load misses";
- case CacheWriteMisses:
- return "cache store misses";
- case CachePrefetchMisses:
- return "cache prefetch misses";
- case ContextSwitches:
- return "context switches";
- case PageFaults:
- return "page faults";
- case MinorPageFaults:
- return "minor page faults";
- case MajorPageFaults:
- return "major page faults";
- case AlignmentFaults:
- return "alignment faults";
- case EmulationFaults:
- return "emulation faults";
- default:
- return "";
- }
+ if (metric >= 0 && metric < QTest::NumEntries)
+ return entries[metric].unit;
+
+ return "";
}
+QT_END_NAMESPACE
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index ba63df5f36..ca045120d5 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -65,9 +65,14 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
+template <> inline char *toString(const QStringView &str)
+{
+ return QTest::toPrettyUnicode(str);
+}
+
template<> inline char *toString(const QString &str)
{
- return QTest::toPrettyUnicode(reinterpret_cast<const ushort *>(str.constData()), str.length());
+ return toString(QStringView(str));
}
template<> inline char *toString(const QLatin1String &str)
@@ -84,21 +89,21 @@ template<> inline char *toString(const QByteArray &ba)
template<> inline char *toString(const QTime &time)
{
return time.isValid()
- ? qstrdup(qPrintable(time.toString(QLatin1String("hh:mm:ss.zzz"))))
+ ? qstrdup(qPrintable(time.toString(QStringViewLiteral("hh:mm:ss.zzz"))))
: qstrdup("Invalid QTime");
}
template<> inline char *toString(const QDate &date)
{
return date.isValid()
- ? qstrdup(qPrintable(date.toString(QLatin1String("yyyy/MM/dd"))))
+ ? qstrdup(qPrintable(date.toString(QStringViewLiteral("yyyy/MM/dd"))))
: qstrdup("Invalid QDate");
}
template<> inline char *toString(const QDateTime &dateTime)
{
return dateTime.isValid()
- ? qstrdup(qPrintable(dateTime.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
+ ? qstrdup(qPrintable(dateTime.toString(QStringViewLiteral("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
: qstrdup("Invalid QDateTime");
}
#endif // QT_NO_DATESTRING
@@ -194,6 +199,22 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+template <typename T1, typename T2>
+inline char *toString(const QPair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("QPair(%s,%s)", first.data(), second.data()));
+}
+
+template <typename T1, typename T2>
+inline char *toString(const std::pair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("std::pair(%s,%s)", first.data(), second.data()));
+}
+
inline char *toString(std::nullptr_t)
{
return toString(QLatin1String("nullptr"));
diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h
index d0d56e7bd0..d848f08d55 100644
--- a/src/testlib/qtest_gui.h
+++ b/src/testlib/qtest_gui.h
@@ -59,6 +59,9 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qregion.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
#ifdef QT_WIDGETS_LIB
#include <QtGui/qicon.h>
@@ -116,6 +119,32 @@ template<> inline char *toString(const QRegion &region)
return qstrdup(result.constData());
}
+#ifndef QT_NO_VECTOR2D
+template<> inline char *toString(const QVector2D &v)
+{
+ QByteArray result = "QVector2D(" + QByteArray::number(v.x()) + ", "
+ + QByteArray::number(v.y()) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR2D
+#ifndef QT_NO_VECTOR3D
+template<> inline char *toString(const QVector3D &v)
+{
+ QByteArray result = "QVector3D(" + QByteArray::number(v.x()) + ", "
+ + QByteArray::number(v.y()) + ", " + QByteArray::number(v.z()) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR3D
+#ifndef QT_NO_VECTOR4D
+template<> inline char *toString(const QVector4D &v)
+{
+ QByteArray result = "QVector4D(" + QByteArray::number(v.x()) + ", "
+ + QByteArray::number(v.y()) + ", " + QByteArray::number(v.z())
+ + ", " + QByteArray::number(v.w()) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR4D
+
inline bool qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected,
const char *file, int line)
{
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 57661bb389..b24ce0578e 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -58,9 +58,10 @@ QT_BEGIN_NAMESPACE
referring to this documentation is kind to readers. Comments can also be used
to indicate the reasons for ignoring particular cases.
- A key names a platform, O/S, distribution, tool-chain or architecture; a !
- prefix reverses what it checks. A version, joined to a key (at present, only
- for distributions and for msvc) with a hyphen, limits the key to the specific
+ The key "ci" applies only when run by COIN. Other keys name platforms,
+ operating systems, distributions, tool-chains or architectures; a ! prefix
+ reverses what it checks. A version, joined to a key (at present, only for
+ distributions and for msvc) with a hyphen, limits the key to the specific
version. A keyword line matches if every key on it applies to the present
run. Successive lines are alternate conditions for ignoring a test.
@@ -70,13 +71,18 @@ QT_BEGIN_NAMESPACE
Subsequent lines give conditions for ignoring this test.
# See qtbase/src/testlib/qtestblacklist.cpp for format
- osx
+ # Test doesn't work on QNX at all
+ qnx
# QTBUG-12345
[testFunction]
linux
windows 64bit
+ # Flaky in COIN on macOS, not reproducible by developers
+ [testSlowly]
+ ci osx
+
# Needs basic C++11 support
[testfunction2:testData]
msvc-2010
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 4c5c9e1eb8..3b5acb6b95 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -275,6 +275,11 @@ namespace QTest
static QObject *currentTestObject = 0;
static QString mainSourcePath;
+#if defined(Q_OS_MACOS)
+ bool macNeedsActivate = false;
+ IOPMAssertionID powerID;
+#endif
+
class TestMethods {
Q_DISABLE_COPY(TestMethods)
public:
@@ -1269,6 +1274,16 @@ char *toPrettyCString(const char *p, int length)
return buffer.take();
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+// this used to be the signature up to and including Qt 5.9
+// keep it for BC reasons:
+Q_TESTLIB_EXPORT
+char *toPrettyUnicode(const ushort *p, int length)
+{
+ return toPrettyUnicode(QStringView(p, length));
+}
+#endif
+
/*!
\internal
Returns the same QString but with only the ASCII characters still shown;
@@ -1276,8 +1291,10 @@ char *toPrettyCString(const char *p, int length)
Similar to QDebug::putString().
*/
-char *toPrettyUnicode(const ushort *p, int length)
+char *toPrettyUnicode(QStringView string)
{
+ auto p = reinterpret_cast<const ushort *>(string.utf16());
+ auto length = string.size();
// keep it simple for the vast majority of cases
bool trimmed = false;
QScopedArrayPointer<char> buffer(new char[256]);
@@ -1343,9 +1360,7 @@ void TestMethods::invokeTests(QObject *testObject) const
{
const QMetaObject *metaObject = testObject->metaObject();
QTEST_ASSERT(metaObject);
- QTestLog::startLogging();
QTestResult::setCurrentTestFunction("initTestCase");
- QTestTable::globalTestTable();
if (m_initTestCaseDataMethod.isValid())
m_initTestCaseDataMethod.invoke(testObject, Qt::DirectConnection);
@@ -1390,9 +1405,6 @@ void TestMethods::invokeTests(QObject *testObject) const
}
QTestResult::finishedCurrentTestFunction();
QTestResult::setCurrentTestFunction(0);
- QTestTable::clearGlobalTestTable();
-
- QTestLog::stopLogging();
}
#if defined(Q_OS_UNIX)
@@ -1702,23 +1714,27 @@ static void initEnvironment()
int QTest::qExec(QObject *testObject, int argc, char **argv)
{
- initEnvironment();
- QBenchmarkGlobalData benchmarkData;
- QBenchmarkGlobalData::current = &benchmarkData;
+ qInit(testObject, argc, argv);
+ int ret = qRun();
+ qCleanup();
+ return ret;
+}
-#ifdef QTESTLIB_USE_VALGRIND
- int callgrindChildExitCode = 0;
-#endif
+/*! \internal
+ */
+void QTest::qInit(QObject *testObject, int argc, char **argv)
+{
+ initEnvironment();
+ QBenchmarkGlobalData::current = new QBenchmarkGlobalData;
#if defined(Q_OS_MACX)
- bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
- IOPMAssertionID powerID;
+ macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
// Don't restore saved window state for auto tests.
QTestPrivate::disableWindowRestore();
-#endif
-#ifndef QT_NO_EXCEPTIONS
- try {
+
+ // Disable App Nap which may cause tests to stall.
+ QTestPrivate::AppNapDisabler appNapDisabler;
#endif
#if defined(Q_OS_MACX)
@@ -1749,6 +1765,24 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
qtest_qParseArgs(argc, argv, false);
+ QTestTable::globalTestTable();
+ QTestLog::startLogging();
+}
+
+/*! \internal
+ */
+int QTest::qRun()
+{
+ QTEST_ASSERT(currentTestObject);
+
+#ifdef QTESTLIB_USE_VALGRIND
+ int callgrindChildExitCode = 0;
+#endif
+
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+
#if defined(Q_OS_WIN)
if (!noCrashHandler) {
# ifndef Q_CC_MINGW
@@ -1784,17 +1818,17 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
for (const QString &tf : qAsConst(QTest::testFunctions)) {
const QByteArray tfB = tf.toLatin1();
const QByteArray signature = tfB + QByteArrayLiteral("()");
- QMetaMethod m = TestMethods::findMethod(testObject, signature.constData());
+ QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
if (!m.isValid() || !isValidSlot(m)) {
fprintf(stderr, "Unknown test function: '%s'. Possible matches:\n", tfB.constData());
qPrintTestSlots(stderr, tfB.constData());
- fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", argv[0]);
+ fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", QTestResult::currentAppName());
exit(1);
}
commandLineMethods.push_back(m);
}
- TestMethods test(testObject, commandLineMethods);
- test.invokeTests(testObject);
+ TestMethods test(currentTestObject, commandLineMethods);
+ test.invokeTests(currentTestObject);
}
#ifndef QT_NO_EXCEPTIONS
@@ -1819,16 +1853,6 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
#endif
- currentTestObject = 0;
-
- QSignalDumper::endDump();
-
-#if defined(Q_OS_MACX)
- if (macNeedsActivate) {
- IOPMAssertionRelease(powerID);
- }
-#endif
-
#ifdef QTESTLIB_USE_VALGRIND
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
return callgrindChildExitCode;
@@ -1838,6 +1862,26 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
return qMin(QTestLog::failCount(), 127);
}
+/*! \internal
+ */
+void QTest::qCleanup()
+{
+ currentTestObject = 0;
+
+ QTestTable::clearGlobalTestTable();
+ QTestLog::stopLogging();
+
+ delete QBenchmarkGlobalData::current;
+ QBenchmarkGlobalData::current = 0;
+
+ QSignalDumper::endDump();
+
+#if defined(Q_OS_MACOS)
+ if (macNeedsActivate)
+ IOPMAssertionRelease(powerID);
+#endif
+}
+
/*!
\overload
\since 4.4
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index a59eb4ecb3..b738043cb7 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -259,12 +259,22 @@ namespace QTest
return Internal::toString(t);
}
+ template <typename T1, typename T2>
+ inline char *toString(const QPair<T1, T2> &pair);
+
+ template <typename T1, typename T2>
+ inline char *toString(const std::pair<T1, T2> &pair);
+
Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length);
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
- Q_TESTLIB_EXPORT char *toPrettyUnicode(const ushort *unicode, int length);
+ Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
Q_TESTLIB_EXPORT char *toString(const char *);
Q_TESTLIB_EXPORT char *toString(const void *);
+ Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR);
+ Q_TESTLIB_EXPORT int qRun();
+ Q_TESTLIB_EXPORT void qCleanup();
+
Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR);
Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
@@ -319,6 +329,8 @@ namespace QTest
Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag);
Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // kept after adding implementation of <T1, T2> out of paranoia:
template <typename T>
inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected,
const char *file, int line)
@@ -326,6 +338,7 @@ namespace QTest
return compare_helper(t1 == t2, "Compared values are not the same",
toString(t1), toString(t2), actual, expected, file, line);
}
+#endif
Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
const char *actual, const char *expected, const char *file, int line);
@@ -376,7 +389,12 @@ namespace QTest
#endif
template <typename T1, typename T2>
- bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
+ inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected,
+ const char *file, int line)
+ {
+ return compare_helper(t1 == t2, "Compared values are not the same",
+ toString(t1), toString(t2), actual, expected, file, line);
+ }
inline bool qCompare(double const &t1, float const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index 8f3d140add..2d1e27ec40 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -82,11 +82,6 @@
QCOMPARE tries to output the contents of the values if the comparison fails,
so it is visible from the test log why the comparison failed.
- QCOMPARE is very strict on the data types. Both \a actual and \a expected
- have to be of the same type, otherwise the test won't compile. This prohibits
- unspecified behavior from being introduced; that is behavior that usually
- occurs when the compiler implicitly casts the argument.
-
For your own classes, you can use \l QTest::toString() to format values for
outputting into the test log.
@@ -575,6 +570,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWidget *widget, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a widget.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
\overload
\since 5.0
@@ -611,6 +615,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWindow *window, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a window.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
Sends a Qt key event to \a widget with the given \a key and an associated \a action.
@@ -1071,6 +1084,10 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
\sa QTest::qWaitForWindowActive(), QWindow::isExposed()
*/
@@ -1093,6 +1110,13 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
+ A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
+ The viewport widget gets the expose event, not the parent widget.
+
\sa QTest::qWaitForWindowActive()
*/
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index e750fdb5a9..a7cf78f25a 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -54,6 +54,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qwindow.h>
#include <QtGui/qevent.h>
+#include <QtGui/qkeysequence.h>
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qwidget.h>
@@ -165,6 +166,15 @@ namespace QTest
Q_DECL_UNUSED inline static void keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Press, window, key, modifier, delay); }
+ Q_DECL_UNUSED inline static void keySequence(QWindow *window, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(window, key, modifiers);
+ }
+ }
+
#ifdef QT_WIDGETS_LIB
static void simulateEvent(QWidget *widget, bool press, int code,
Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1)
@@ -294,6 +304,16 @@ namespace QTest
{ keyEvent(Release, widget, key, modifier, delay); }
inline static void keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Click, widget, key, modifier, delay); }
+
+ inline static void keySequence(QWidget *widget, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(widget, key, modifiers);
+ }
+ }
+
#endif // QT_WIDGETS_LIB
}
diff --git a/src/testlib/qtestutil_macos.mm b/src/testlib/qtestutil_macos.mm
index 70a7fb9f85..7579c3b164 100644
--- a/src/testlib/qtestutil_macos.mm
+++ b/src/testlib/qtestutil_macos.mm
@@ -54,6 +54,33 @@ namespace QTestPrivate {
void disableWindowRestore() {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"ApplePersistenceIgnoreState"];
}
+
+ /*! \internal
+ \class AppNapDisabler
+ \brief Disables App Nap by registereing a bacground activity.
+
+ App Nap remains disabled as long as the AppNapDisabler instance
+ exists.
+ */
+
+ /*! \internal
+ Creates an AppNapDisabler instance and starts a NSActivityBackground activity.
+ */
+ AppNapDisabler::AppNapDisabler()
+ {
+ m_activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityBackground
+ reason:@"Qt Auto Test"];
+ [m_activity retain];
+ }
+
+ /*! \internal
+ Destroys the AppNapDisabler instance and ends the NSActivityBackground activity.
+ */
+ AppNapDisabler::~AppNapDisabler()
+ {
+ [[NSProcessInfo processInfo] endActivity:m_activity];
+ [m_activity release];
+ }
}
QT_END_NAMESPACE
diff --git a/src/testlib/qtestutil_macos_p.h b/src/testlib/qtestutil_macos_p.h
index d7cc5bc251..36f27167c0 100644
--- a/src/testlib/qtestutil_macos_p.h
+++ b/src/testlib/qtestutil_macos_p.h
@@ -58,6 +58,17 @@ QT_BEGIN_NAMESPACE
namespace QTestPrivate {
void disableWindowRestore();
+
+ class AppNapDisabler
+ {
+ public:
+ AppNapDisabler();
+ ~AppNapDisabler();
+ AppNapDisabler(const AppNapDisabler&) = delete;
+ AppNapDisabler& operator=(const AppNapDisabler&) = delete;
+ private:
+ id m_activity;
+ };
}
QT_END_NAMESPACE