QObject: fix installEventFilterOrder() test flakiness
Don't rely on timer precision and use int counter instead. Amends 1fe88bf4cd919d4b5cadb4be2cf0193525c54673 Pick-to: 6.6 6.5 6.2 5.15 Change-Id: I057b4dd51014784ec9b244301b43583f3de6ddd1 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> (cherry picked from commit 0d0810e2dcc8a9ee28935af5daadc2ef36ed25a2) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
f48faee770
commit
c160f3340e
@ -3142,6 +3142,8 @@ void tst_QObject::blockingQueuedConnection()
|
||||
}
|
||||
}
|
||||
|
||||
static int s_eventSpyCounter = -1;
|
||||
|
||||
class EventSpy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -3161,16 +3163,17 @@ public:
|
||||
void clear()
|
||||
{
|
||||
events.clear();
|
||||
thisCounter = -1;
|
||||
}
|
||||
|
||||
bool eventFilter(QObject *object, QEvent *event) override
|
||||
{
|
||||
events.append(qMakePair(object, event->type()));
|
||||
timeStamp = std::chrono::steady_clock::now();
|
||||
thisCounter = ++s_eventSpyCounter;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::chrono::steady_clock::time_point timeStamp;
|
||||
int thisCounter = -1;
|
||||
private:
|
||||
EventList events;
|
||||
};
|
||||
@ -3372,76 +3375,68 @@ void tst_QObject::installEventFilter()
|
||||
QVERIFY(spy.eventList().isEmpty());
|
||||
}
|
||||
|
||||
#define CHECK_FAIL(message) \
|
||||
do {\
|
||||
if (QTest::currentTestFailed())\
|
||||
QFAIL("failed one line above on " message);\
|
||||
} while (false)
|
||||
|
||||
void tst_QObject::installEventFilterOrder()
|
||||
{
|
||||
// installEventFilter() adds new objects to d_func()->extraData->eventFilters, which
|
||||
// affects the order of calling each object's eventFilter() when processing the events.
|
||||
|
||||
QObject object;
|
||||
EventSpy spy1;
|
||||
object.installEventFilter(&spy1);
|
||||
EventSpy spy2;
|
||||
object.installEventFilter(&spy2);
|
||||
EventSpy spy3;
|
||||
object.installEventFilter(&spy3);
|
||||
|
||||
const EventSpy::EventList expected = { {&object, QEvent::Type(QEvent::User + 1)} };
|
||||
auto checkExpected = [&] {
|
||||
QCOMPARE(spy1.eventList(), expected);
|
||||
QCOMPARE(spy2.eventList(), expected);
|
||||
QCOMPARE(spy3.eventList(), expected);
|
||||
};
|
||||
EventSpy spy1, spy2, spy3;
|
||||
|
||||
auto clearSignalSpies = [&] {
|
||||
for (auto *s : {&spy1, &spy2, &spy3})
|
||||
s->clear();
|
||||
s_eventSpyCounter = -1;
|
||||
};
|
||||
|
||||
auto checkCallOrder = [](EventSpy &a, EventSpy &b, EventSpy &c) {
|
||||
QVERIFY(a.timeStamp > b.timeStamp);
|
||||
QVERIFY(b.timeStamp > c.timeStamp);
|
||||
const EventSpy::EventList expected = { { &object, QEvent::Type(QEvent::User + 1) } };
|
||||
|
||||
// Call Order: from first to last
|
||||
auto checkCallOrder = [&expected](const QList<EventSpy *> &spies) {
|
||||
for (int i = 0; i < spies.size(); ++i) {
|
||||
EventSpy *spy = spies.at(i);
|
||||
QVERIFY2(spy->eventList() == expected,
|
||||
QString("The spy %1 wasn't triggered exactly once.").arg(i).toLatin1());
|
||||
QCOMPARE(spy->thisCounter, i);
|
||||
}
|
||||
};
|
||||
|
||||
// Install event filters and check the order of invocations:
|
||||
// The last installed = the first called.
|
||||
object.installEventFilter(&spy1);
|
||||
object.installEventFilter(&spy2);
|
||||
object.installEventFilter(&spy3);
|
||||
clearSignalSpies();
|
||||
QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
checkExpected();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
checkCallOrder(spy1, spy2, spy3);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
clearSignalSpies();
|
||||
checkCallOrder({ &spy3, &spy2, &spy1 });
|
||||
CHECK_FAIL("checkCallOrder() - 1st round");
|
||||
|
||||
// Install event filter for `spy1` again, which reorders spy1 in `eventFilters`
|
||||
// (the list doesn't have duplicates).
|
||||
object.installEventFilter(&spy1);
|
||||
|
||||
QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
checkExpected();
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
checkCallOrder(spy2, spy3, spy1);
|
||||
if (QTest::currentTestFailed())
|
||||
return;
|
||||
|
||||
clearSignalSpies();
|
||||
|
||||
object.removeEventFilter(&spy3);
|
||||
|
||||
QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
QCoreApplication::processEvents();
|
||||
checkCallOrder({ &spy1, &spy3, &spy2 });
|
||||
CHECK_FAIL("checkCallOrder() - 2nd round");
|
||||
|
||||
// Remove event filter for `spy3`, ensure it's not called anymore and the
|
||||
// existing filters order is preserved.
|
||||
object.removeEventFilter(&spy3);
|
||||
clearSignalSpies();
|
||||
QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
QCoreApplication::processEvents();
|
||||
checkCallOrder({ &spy1, &spy2 });
|
||||
CHECK_FAIL("checkCallOrder() - 3rd round");
|
||||
QVERIFY(spy3.eventList().isEmpty());
|
||||
QCOMPARE(spy1.eventList(), expected);
|
||||
QCOMPARE(spy2.eventList(), expected);
|
||||
|
||||
QVERIFY(spy2.timeStamp > spy1.timeStamp);
|
||||
QCOMPARE(spy3.thisCounter, -1);
|
||||
}
|
||||
|
||||
class EmitThread : public QThread
|
||||
|
Loading…
x
Reference in New Issue
Block a user