diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2024-01-17 21:41:51 +0200 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2024-02-01 23:42:56 +0200 |
commit | 1fe88bf4cd919d4b5cadb4be2cf0193525c54673 (patch) | |
tree | 2a83ef92077cde884a177cfb2e915b1b7977aad4 | |
parent | 28db390ce686ec8af70334e80ceae5ee2ebf87df (diff) |
QObject: add unittest to check the order of eventFilter() calls
installEventFilter() prepends new objects to the eventList, so that
events that are posted while processing events are left to the next
round of event processing.
This is a baseline test to check that subsequent commits preserve the
current behavior.
QCOMPARE_GT is available since Qt6.4, so make the check backportable to
older releases too.
Pick-to: 6.7 6.6 6.5 6.2 5.15
Task-number: QTBUG-120779
Change-Id: I5ed5e9c2917a9be62de4af19c3b72889399b4fe6
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 0532841ac8..24eb0812eb 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -84,6 +84,7 @@ private slots: void childEvents(); void parentEvents(); void installEventFilter(); + void installEventFilterOrder(); void deleteSelfInSlot(); void disconnectSelfInSlotAndDeleteAfterEmit(); void dumpObjectInfo(); @@ -3165,9 +3166,11 @@ public: bool eventFilter(QObject *object, QEvent *event) override { events.append(qMakePair(object, event->type())); + timeStamp = std::chrono::steady_clock::now(); return false; } + std::chrono::steady_clock::time_point timeStamp; private: EventList events; }; @@ -3369,6 +3372,78 @@ void tst_QObject::installEventFilter() QVERIFY(spy.eventList().isEmpty()); } +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); + }; + + auto clearSignalSpies = [&] { + for (auto *s : {&spy1, &spy2, &spy3}) + s->clear(); + }; + + auto checkCallOrder = [](EventSpy &a, EventSpy &b, EventSpy &c) { + QVERIFY(a.timeStamp > b.timeStamp); + QVERIFY(b.timeStamp > c.timeStamp); + }; + + 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(); + + // 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(); + + QVERIFY(spy3.eventList().isEmpty()); + QCOMPARE(spy1.eventList(), expected); + QCOMPARE(spy2.eventList(), expected); + + QVERIFY(spy2.timeStamp > spy1.timeStamp); +} + class EmitThread : public QThread { Q_OBJECT public: |