summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2019-12-04 14:58:27 +0100
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2019-12-10 11:33:26 +0100
commit30e32870a052fda1a23099e46864242e52d94a17 (patch)
tree3114b7167b40cd4500c633d52e0b4b48452d16cc /tests/auto/corelib/kernel
parent95689c645fb42260d920091658b2d39c920abf00 (diff)
QCocoaEventDispatcher: make 'interrupt' work
even if we are currently inside processEvents (apparently called manually and not from QEventLoop::exec()). A carefully crafted application (see, for example, the linked QTBUG or even updated auto-test) can trigger itself into failing to exit the current (potentially nested) event loop. We can harden our Cocoa event dispatcher to detect such condition and properly propagate 'interrupt' to where it'll do its job, indeed, interrupting the real event loop (aka [NSApp run]). This mainly means we have to undo what bool blocker would erroneously do. Also, long live (as people love to say these days) to another tricky (somewhat) auto-test (surely, it's not flaky!). Fixes: QTBUG-79477 Change-Id: I794f0cda23e24d36be67f2bb63d52b74be057c31 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'tests/auto/corelib/kernel')
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
index 49c10c6a24..365508024b 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
+++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
@@ -67,6 +67,7 @@ private slots:
void sendPostedEvents_data();
void sendPostedEvents();
void processEventsOnlySendsQueuedEvents();
+ void eventLoopExit();
};
bool tst_QEventDispatcher::event(QEvent *e)
@@ -314,5 +315,49 @@ void tst_QEventDispatcher::processEventsOnlySendsQueuedEvents()
QCOMPARE(object.eventsReceived, 4);
}
+void tst_QEventDispatcher::eventLoopExit()
+{
+ // This test was inspired by QTBUG-79477. A particular
+ // implementation detail in QCocoaEventDispatcher allowed
+ // QEventLoop::exit() to fail to really exit the event loop.
+ // Thus this test is a part of the dispatcher auto-test.
+
+ // Imitates QApplication::exec():
+ QEventLoop mainLoop;
+ // The test itself is a lambda:
+ QTimer::singleShot(0, [&mainLoop]() {
+ // Two more single shots, both will be posted as events
+ // (zero timeout) and supposed to be processes by the
+ // mainLoop:
+
+ QTimer::singleShot(0, [&mainLoop]() {
+ // wakeUp triggers QCocoaEventDispatcher into incrementing
+ // its 'serialNumber':
+ mainLoop.wakeUp();
+ // QCocoaEventDispatcher::processEvents() will process
+ // posted events and execute the second lambda defined below:
+ QCoreApplication::processEvents();
+ });
+
+ QTimer::singleShot(0, [&mainLoop]() {
+ // With QCocoaEventDispatcher this is executed while in the
+ // processEvents (see above) and would fail to actually
+ // interrupt the loop.
+ mainLoop.exit();
+ });
+ });
+
+ bool timeoutObserved = false;
+ QTimer::singleShot(500, [&timeoutObserved, &mainLoop]() {
+ // In case the QEventLoop::exit above failed, we have to bail out
+ // early, not wasting time:
+ mainLoop.exit();
+ timeoutObserved = true;
+ });
+
+ mainLoop.exec();
+ QVERIFY(!timeoutObserved);
+}
+
QTEST_MAIN(tst_QEventDispatcher)
#include "tst_qeventdispatcher.moc"