diff options
Diffstat (limited to 'tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp')
-rw-r--r-- | tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp | 199 |
1 files changed, 180 insertions, 19 deletions
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 17deeb4c5e..40190ca465 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -1,17 +1,27 @@ // Copyright (C) 2020 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +/* WARNING: this source-code is reused by another test. + + As Qt built with GUI support may use a different backend for its event loops + and other timer-related matters, it is important to test it in that form, as + well as in its GUI-less form. So this source file is reused by a build config + in the GUI module. Similarly, testing with and without glib is supported, + where relevant (see DISABLE_GLIB below). +*/ #ifdef QT_GUI_LIB +// When compiled as tests/auto/gui/kernel/qguitimer/'s source-code: # include <QtGui/QGuiApplication> -# define tst_QTimer tst_QGuiTimer #else +// When compiled as tests/auto/corelib/kernel/qtimer/'s source-code: # include <QtCore/QCoreApplication> #endif #include <QtCore/private/qglobal_p.h> #include <QTest> #include <QSignalSpy> +#include <QtTest/private/qpropertytesthelper_p.h> #include <qtimer.h> #include <qthread.h> @@ -23,18 +33,14 @@ #endif #ifdef DISABLE_GLIB -# ifdef tst_QTimer -# undef tst_QTimer -# define tst_QTimer tst_QGuiTimer_NoGlib -# else -# define tst_QTimer tst_QTimer_NoGlib -# endif static bool glibDisabled = []() { qputenv("QT_NO_GLIB", "1"); return true; }(); #endif +using namespace std::chrono_literals; + class tst_QTimer : public QObject { Q_OBJECT @@ -46,6 +52,8 @@ private slots: void zeroTimer(); void singleShotTimeout(); void timeout(); + void singleShotNormalizes_data(); + void singleShotNormalizes(); void sequentialTimers_data(); void sequentialTimers(); void singleShotSequentialTimers_data(); @@ -87,6 +95,10 @@ private slots: void bindToTimer(); void bindTimer(); + void automatedBindingTests(); + + void negativeInterval(); + void testTimerId(); }; void tst_QTimer::zeroTimer() @@ -138,6 +150,60 @@ void tst_QTimer::timeout() QTRY_VERIFY_WITH_TIMEOUT(timeoutSpy.size() > oldCount, TIMEOUT_TIMEOUT); } +void tst_QTimer::singleShotNormalizes_data() +{ + QTest::addColumn<QByteArray>("slotName"); + + QTest::newRow("normalized") << QByteArray(SLOT(exitLoop())); + + QTest::newRow("space-before") << QByteArray(SLOT( exitLoop())); + QTest::newRow("space-after") << QByteArray(SLOT(exitLoop ())); + QTest::newRow("space-around") << QByteArray(SLOT( exitLoop ())); + QTest::newRow("spaces-before") << QByteArray(SLOT( exitLoop())); + QTest::newRow("spaces-after") << QByteArray(SLOT(exitLoop ())); + QTest::newRow("spaces-around") << QByteArray(SLOT( exitLoop ())); + + QTest::newRow("space-in-parens") << QByteArray(SLOT(exitLoop( ))); + QTest::newRow("spaces-in-parens") << QByteArray(SLOT(exitLoop( ))); + QTest::newRow("space-after-parens") << QByteArray(SLOT(exitLoop() )); + QTest::newRow("spaces-after-parens") << QByteArray(SLOT(exitLoop() )); +} + +void tst_QTimer::singleShotNormalizes() +{ + static constexpr auto TestTimeout = 250ms; + QFETCH(QByteArray, slotName); + QEventLoop loop; + + // control test: regular connection + { + QTimer timer; + QVERIFY(QObject::connect(&timer, SIGNAL(timeout()), &QTestEventLoop::instance(), slotName)); + timer.setSingleShot(true); + timer.start(1); + QTestEventLoop::instance().enterLoop(TestTimeout); + QVERIFY(!QTestEventLoop::instance().timeout()); + } + + // non-zero time + QTimer::singleShot(1, &QTestEventLoop::instance(), slotName); + QTestEventLoop::instance().enterLoop(TestTimeout); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QTimer::singleShot(1ms, &QTestEventLoop::instance(), slotName); + QTestEventLoop::instance().enterLoop(TestTimeout); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // zero time + QTimer::singleShot(0, &QTestEventLoop::instance(), slotName); + QTestEventLoop::instance().enterLoop(TestTimeout); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QTimer::singleShot(0ms, &QTestEventLoop::instance(), slotName); + QTestEventLoop::instance().enterLoop(TestTimeout); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + void tst_QTimer::sequentialTimers_data() { #ifdef Q_OS_WIN @@ -751,12 +817,10 @@ void tst_QTimer::timerFiresOnlyOncePerProcessEvents() class TimerIdPersistsAfterThreadExitThread : public QThread { public: - QTimer *timer; - int timerId, returnValue; + QTimer *timer = nullptr; + Qt::TimerId timerId = Qt::TimerId::Invalid; + int returnValue = -1; - TimerIdPersistsAfterThreadExitThread() - : QThread(), timer(0), timerId(-1), returnValue(-1) - { } ~TimerIdPersistsAfterThreadExitThread() { delete timer; @@ -768,11 +832,15 @@ public: timer = new QTimer; connect(timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); timer->start(100); - timerId = timer->timerId(); + timerId = timer->id(); returnValue = eventLoop.exec(); } }; +namespace { +int operator&(Qt::TimerId id, int i) { return qToUnderlying(id) & i; } +} + void tst_QTimer::timerIdPersistsAfterThreadExit() { TimerIdPersistsAfterThreadExitThread thread; @@ -798,6 +866,19 @@ void tst_QTimer::cancelLongTimer() QVERIFY(!timer.isActive()); } +void tst_QTimer::testTimerId() +{ + QTimer timer; + timer.start(100ms); + QVERIFY(timer.isActive()); + QCOMPARE_GT(timer.timerId(), 0); + QCOMPARE_GT(timer.id(), Qt::TimerId::Invalid); + timer.stop(); + QVERIFY(!timer.isActive()); + QCOMPARE(timer.timerId(), -1); + QCOMPARE(timer.id(), Qt::TimerId::Invalid); +} + class TimeoutCounter : public QObject { Q_OBJECT @@ -972,7 +1053,7 @@ void tst_QTimer::singleShotToFunctors() thread.wait(); struct MoveOnly : CountedStruct { - Q_DISABLE_COPY(MoveOnly); + Q_DISABLE_COPY(MoveOnly) MoveOnly(MoveOnly &&o) : CountedStruct(std::move(o)) {}; MoveOnly(int *c) : CountedStruct(c) {} }; @@ -1225,6 +1306,23 @@ void tst_QTimer::bindToTimer() timer.stop(); QVERIFY(!active); + + auto ignoreMsg = [] { + QTest::ignoreMessage(QtWarningMsg, + "QObject::startTimer: Timers cannot have negative intervals"); + }; + + // also test that using negative interval updates the binding correctly + timer.start(100); + QVERIFY(active); + ignoreMsg(); + timer.setInterval(-100); + QVERIFY(!active); + timer.start(100); + QVERIFY(active); + ignoreMsg(); + timer.start(-100); + QVERIFY(!active); } void tst_QTimer::bindTimer() @@ -1269,6 +1367,73 @@ void tst_QTimer::bindTimer() QCOMPARE(timer.timerType(), Qt::VeryCoarseTimer); } +void tst_QTimer::automatedBindingTests() +{ + QTimer timer; + + QVERIFY(!timer.isSingleShot()); + QTestPrivate::testReadWritePropertyBasics(timer, true, false, "singleShot"); + if (QTest::currentTestFailed()) { + qDebug("Failed property test for QTimer::singleShot"); + return; + } + + QCOMPARE_NE(timer.interval(), 10); + QTestPrivate::testReadWritePropertyBasics(timer, 10, 20, "interval"); + if (QTest::currentTestFailed()) { + qDebug("Failed property test for QTimer::interval"); + return; + } + + QCOMPARE_NE(timer.timerType(), Qt::PreciseTimer); + QTestPrivate::testReadWritePropertyBasics(timer, Qt::PreciseTimer, Qt::CoarseTimer, + "timerType"); + if (QTest::currentTestFailed()) { + qDebug("Failed property test for QTimer::timerType"); + return; + } + + timer.start(1000); + QVERIFY(timer.isActive()); + QTestPrivate::testReadOnlyPropertyBasics(timer, true, false, "active", + [&timer]() { timer.stop(); }); + if (QTest::currentTestFailed()) { + qDebug("Failed property test for QTimer::active"); + return; + } +} + +void tst_QTimer::negativeInterval() +{ + auto ignoreMsg = [] { + QTest::ignoreMessage(QtWarningMsg, + "QObject::startTimer: Timers cannot have negative intervals"); + }; + + QTimer timer; + + // Starting with a negative interval does not change active state. + ignoreMsg(); + timer.start(-100ms); + QVERIFY(!timer.isActive()); + + // Updating the interval to a negative value stops the timer and changes + // the active state. + timer.start(100ms); + QVERIFY(timer.isActive()); + ignoreMsg(); + timer.setInterval(-100); + QVERIFY(!timer.isActive()); + + // Starting with a negative interval when already started leads to stop + // and inactive state. + timer.start(100); + QVERIFY(timer.isActive()); + ignoreMsg(); + timer.start(-100ms); + QVERIFY(!timer.isActive()); +} + class OrderHelper : public QObject { Q_OBJECT @@ -1342,14 +1507,10 @@ void tst_QTimer::timerOrder_data() void tst_QTimer::timerOrderBackgroundThread() { -#if !QT_CONFIG(cxx11_future) - QSKIP("This test requires QThread::create"); -#else auto *thread = QThread::create([this]() { timerOrder(); }); thread->start(); QVERIFY(thread->wait()); delete thread; -#endif } struct StaticSingleShotUser |