Detect double timer during single timeout in registerTimer test, and skip

We observe this happening on macOS in the CI system, and it might happen
if a VM doesn't get CPU cycles for long enough time so that two timers
time out. Then event processing will process two timer events, and we
overwrite the timerIdFromEvent with the second event.

Instead, skip the test when this happens.

This is an ammendment to 5c520f4b0a

Fixes: QTBUG-71751
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 67491e2df5)
Change-Id: I30eef8cfc94988e6cad500dd5e6722488c2985be
This commit is contained in:
Volker Hilsheimer 2020-02-12 17:50:44 +01:00
parent c3951470ca
commit 1ce3585305

View File

@ -45,8 +45,10 @@ class tst_QEventDispatcher : public QObject
Q_OBJECT Q_OBJECT
QAbstractEventDispatcher *eventDispatcher; QAbstractEventDispatcher *eventDispatcher;
int receivedEventType;
int timerIdFromEvent; int receivedEventType = -1;
int timerIdFromEvent = -1;
bool doubleTimer = false;
protected: protected:
bool event(QEvent *e); bool event(QEvent *e);
@ -54,9 +56,7 @@ protected:
public: public:
inline tst_QEventDispatcher() inline tst_QEventDispatcher()
: QObject(), : QObject(),
eventDispatcher(QAbstractEventDispatcher::instance(thread())), eventDispatcher(QAbstractEventDispatcher::instance(thread()))
receivedEventType(-1),
timerIdFromEvent(-1)
{ } { }
private slots: private slots:
@ -74,6 +74,9 @@ bool tst_QEventDispatcher::event(QEvent *e)
switch (receivedEventType = e->type()) { switch (receivedEventType = e->type()) {
case QEvent::Timer: case QEvent::Timer:
{ {
// sometimes, two timers fire during a single QTRY_xxx wait loop
if (timerIdFromEvent != -1)
doubleTimer = true;
timerIdFromEvent = static_cast<QTimerEvent *>(e)->timerId(); timerIdFromEvent = static_cast<QTimerEvent *>(e)->timerId();
return true; return true;
} }
@ -219,12 +222,17 @@ void tst_QEventDispatcher::registerTimer()
// process events, waiting for the next event... this should only fire the precise timer // process events, waiting for the next event... this should only fire the precise timer
receivedEventType = -1; receivedEventType = -1;
timerIdFromEvent = -1; timerIdFromEvent = -1;
doubleTimer = false;
QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), PreciseTimerInterval * 2); QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), PreciseTimerInterval * 2);
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
if (doubleTimer)
QSKIP("Double timer during a single timeout - aborting test as flaky on macOS");
if (timerIdFromEvent != timers.preciseTimerId() if (timerIdFromEvent != timers.preciseTimerId()
&& elapsedTimer.elapsed() > PreciseTimerInterval * 3) && elapsedTimer.elapsed() > PreciseTimerInterval * 3)
QSKIP("Ignore flaky test behavior due to VM scheduling on macOS"); QSKIP("Ignore flaky test behavior due to VM scheduling on macOS");
#endif #endif
QCOMPARE(timerIdFromEvent, timers.preciseTimerId()); QCOMPARE(timerIdFromEvent, timers.preciseTimerId());
// now unregister it and make sure it's gone // now unregister it and make sure it's gone
timers.unregister(timers.preciseTimerId()); timers.unregister(timers.preciseTimerId());
@ -238,8 +246,12 @@ void tst_QEventDispatcher::registerTimer()
// do the same again for the coarse timer // do the same again for the coarse timer
receivedEventType = -1; receivedEventType = -1;
timerIdFromEvent = -1; timerIdFromEvent = -1;
doubleTimer = false;
QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), CoarseTimerInterval * 2); QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), CoarseTimerInterval * 2);
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
if (doubleTimer)
QSKIP("Double timer during a single timeout - aborting test as flaky on macOS");
if (timerIdFromEvent != timers.coarseTimerId() if (timerIdFromEvent != timers.coarseTimerId()
&& elapsedTimer.elapsed() > CoarseTimerInterval * 3) && elapsedTimer.elapsed() > CoarseTimerInterval * 3)
QSKIP("Ignore flaky test behavior due to VM scheduling on macOS"); QSKIP("Ignore flaky test behavior due to VM scheduling on macOS");