summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2024-01-17 21:41:51 +0200
committerAhmad Samir <a.samirh78@gmail.com>2024-02-01 23:42:56 +0200
commit1fe88bf4cd919d4b5cadb4be2cf0193525c54673 (patch)
tree2a83ef92077cde884a177cfb2e915b1b7977aad4
parent28db390ce686ec8af70334e80ceae5ee2ebf87df (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.cpp75
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: