diff options
Diffstat (limited to 'src/testlib')
-rw-r--r-- | src/testlib/qtest.h | 13 | ||||
-rw-r--r-- | src/testlib/qtestblacklist.cpp | 14 | ||||
-rw-r--r-- | src/testlib/qtestcase.cpp | 103 | ||||
-rw-r--r-- | src/testlib/qtestcase.h | 32 | ||||
-rw-r--r-- | src/testlib/qtestcase.qdoc | 23 | ||||
-rw-r--r-- | src/testlib/qtestkeyboard.h | 20 |
6 files changed, 159 insertions, 46 deletions
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index ba63df5f36..4abba93721 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 diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 0ebc800fe1..dbf79575a8 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 8b0820b941..a4099c3cd8 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: @@ -1271,6 +1276,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; @@ -1278,8 +1293,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]); @@ -1345,9 +1362,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); @@ -1392,9 +1407,6 @@ void TestMethods::invokeTests(QObject *testObject) const } QTestResult::finishedCurrentTestFunction(); QTestResult::setCurrentTestFunction(0); - QTestTable::clearGlobalTestTable(); - - QTestLog::stopLogging(); } #if defined(Q_OS_UNIX) @@ -1698,24 +1710,25 @@ 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 { -#endif #if defined(Q_OS_MACX) if (macNeedsActivate) { @@ -1745,6 +1758,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 @@ -1780,17 +1811,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 @@ -1815,16 +1846,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; @@ -1834,6 +1855,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 a7e825396a..b70bacbd17 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -259,12 +259,32 @@ namespace QTest return Internal::toString(t); } + 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())); + } + 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 +339,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 +348,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 +399,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..1b1a8b6007 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. 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 } |