diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2021-07-28 11:22:13 +0200 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2021-08-05 11:27:40 +0200 |
commit | 7e61b18d325c5b0022eedadf9e65b1d34d6c635f (patch) | |
tree | ade688a41f29f5038d0819c6a07022998d3f0e96 /tests | |
parent | 21c67c35caa89a10babd3d712e14aaf5b61e8691 (diff) |
QFuture: fix result reporting in the filter mode
After inserting a result into the result store, a wrong index for end
is used for reporting the range of ready results. This has been fixed
in Qt 6 in scope of 44ceb56455c82df3e6b1c9a2fa373cac14a039f8 already.
The problem was noticed also for Qt 5 long time ago (see the comments
of QTBUG-6799), so port the fix to 5.15. The relevant part for testing
the fix is taken from the same patch.
Fixes: QTBUG-83182
Change-Id: I99121732576befa9ec32f758746d9a22a30e4261
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index c09301ee75..49c8ec2113 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -94,6 +94,7 @@ private slots: void nestedExceptions(); #endif void nonGlobalThreadPool(); + void resultsReadyAt(); }; void tst_QFuture::resultStore() @@ -1577,5 +1578,63 @@ void tst_QFuture::nonGlobalThreadPool() } } +void tst_QFuture::resultsReadyAt() +{ + QFutureInterface<int> iface; + QFutureWatcher<int> watcher; + watcher.setFuture(iface.future()); + + QTestEventLoop eventProcessor; + connect(&watcher, &QFutureWatcher<int>::finished, &eventProcessor, &QTestEventLoop::exitLoop); + + const int nExpectedResults = 4; + int reported = 0; + int taken = 0; + connect(&watcher, &QFutureWatcher<int>::resultsReadyAt, + [&iface, &reported, &taken](int begin, int end) + { + auto future = iface.future(); + QVERIFY(end - begin > 0); + for (int i = begin; i < end; ++i, ++reported) { + QVERIFY(future.isResultReadyAt(i)); + taken |= 1 << i; + } + }); + + auto report = [&iface](int index) + { + int dummyResult = 0b101010; + iface.reportResult(&dummyResult, index); + }; + + const QSignalSpy readyCounter(&watcher, &QFutureWatcher<int>::resultsReadyAt); + QTimer::singleShot(0, [&iface, &report]{ + // With filter mode == true, the result may go into the pending results. + // Reporting it as ready will allow an application to try and access the + // result, crashing on invalid (store.end()) iterator dereferenced. + iface.setFilterMode(true); + iface.reportStarted(); + report(0); + report(1); + // This one - should not be reported (it goes into pending): + report(3); + // Let's close the 'gap' and make them all ready: + report(-1); + iface.reportFinished(); + }); + + // Run event loop, QCoreApplication::postEvent is in use + // in QFutureInterface: + eventProcessor.enterLoopMSecs(2000); + QVERIFY(!eventProcessor.timeout()); + if (QTest::currentTestFailed()) // Failed in our lambda observing 'ready at' + return; + + QCOMPARE(reported, nExpectedResults); + QCOMPARE(nExpectedResults, iface.future().resultCount()); + QCOMPARE(readyCounter.count(), 3); + QCOMPARE(taken, 0b1111); +} + QTEST_MAIN(tst_QFuture) #include "tst_qfuture.moc" |