From fc319a8f8b030af82613a79959d95ae800d1b2c9 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 29 Mar 2023 20:25:45 +0200 Subject: Fix QTimer::crossThreadSingleShotToFunctor test Amends 4d90c4e74a6aa34d5aabfb91ec304da1f02df3e3, after which the test became flaky. We need to wait for the functor to be called before quitting the thread, otherwise we have no guarnatee that any of the queued metacall events have been processed by the thread. Since QThread::quit is thread-safe, we can just call it from within the functor. This guarantees that at least one of the single-shot timers is processed before we quit. And since QTimer::singleShot has special code paths for 0-ms timers (going through an explicitly queued QMetaObject::invokeMethod call rather than through an actual QSingleShotTimer object), we need to run the test logic with different timeouts to cover both code paths. Task-number: QTBUG-112162 Pick-to: 6.5 6.2 5.15 Change-Id: Ide1e7b4b74dcbda72144a0d73ef5f64b0694ddbc Reviewed-by: Fabian Kosmale Reviewed-by: Thiago Macieira --- tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp | 28 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'tests/auto/corelib/kernel/qtimer') diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 5c39fc5d91..2e86d89923 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -56,6 +56,7 @@ private slots: void singleShotToFunctors(); void singleShot_chrono(); void singleShot_static(); + void crossThreadSingleShotToFunctor_data(); void crossThreadSingleShotToFunctor(); void timerOrder(); void timerOrder_data(); @@ -1007,28 +1008,39 @@ void tst_QTimer::postedEventsShouldNotStarveTimers() struct DummyFunctor { static QThread *callThread; - void operator()() { callThread = QThread::currentThread(); } + void operator()() { + callThread = QThread::currentThread(); + callThread->quit(); + } }; QThread *DummyFunctor::callThread = nullptr; +void tst_QTimer::crossThreadSingleShotToFunctor_data() +{ + QTest::addColumn("timeout"); + + QTest::addRow("zero-timer") << 0; + QTest::addRow("1ms") << 1; +} + void tst_QTimer::crossThreadSingleShotToFunctor() { + QFETCH(int, timeout); // We're also testing for crashes here, so the test simply running to // completion is part of the success + DummyFunctor::callThread = nullptr; + QThread t; t.start(); - QObject* o = new QObject(); + std::unique_ptr o(new QObject()); o->moveToThread(&t); - DummyFunctor::callThread = nullptr; - for (int i = 0; i < 10000; i++) { - QTimer::singleShot(0, o, DummyFunctor()); - } + for (int i = 0; i < 10000; i++) + QTimer::singleShot(timeout, o.get(), DummyFunctor()); - t.quit(); t.wait(); - delete o; + o.reset(); QCOMPARE(DummyFunctor::callThread, &t); } -- cgit v1.2.3