Fix QTimer::crossThreadSingleShotToFunctor test

Amends 4d90c4e74a, 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 <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Volker Hilsheimer 2023-03-29 20:25:45 +02:00
parent 816ca43b88
commit fc319a8f8b
1 changed files with 20 additions and 8 deletions

View File

@ -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<int>("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<QObject> 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);
}