diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 38 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp | 91 |
2 files changed, 129 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index a7f308de59..d647ce6eba 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -113,6 +113,7 @@ private slots: void iterators(); void iteratorsThread(); void pause(); + void suspend(); void throttling(); void voidConversions(); #ifndef QT_NO_EXCEPTIONS @@ -1334,6 +1335,43 @@ void tst_QFuture::pause() Interface.reportFinished(); } +void tst_QFuture::suspend() +{ + QFutureInterface<void> interface; + + interface.reportStarted(); + QFuture<void> f = interface.future(); + QVERIFY(!interface.isSuspended()); + + interface.reportSuspended(); + QVERIFY(!interface.isSuspended()); + + // pause + interface.togglePaused(); + QVERIFY(!interface.isSuspended()); + QVERIFY(interface.isPaused()); + + interface.reportSuspended(); + QVERIFY(interface.isSuspended()); + QVERIFY(interface.isPaused()); + + // resume + interface.togglePaused(); + QVERIFY(!interface.isSuspended()); + QVERIFY(!interface.isPaused()); + + // pause again + interface.togglePaused(); + interface.reportSuspended(); + + interface.reportCanceled(); + QVERIFY(!interface.isSuspended()); + QVERIFY(!interface.isPaused()); + QVERIFY(interface.isCanceled()); + + interface.reportFinished(); +} + class ResultObject : public QObject { Q_OBJECT diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp index 8b332e67fe..13fb587607 100644 --- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp @@ -58,6 +58,8 @@ private slots: void changeFuture(); void cancelEvents(); void pauseEvents(); + void suspended(); + void suspendedEvents(); void finishedState(); void throttling(); void incrementalMapResults(); @@ -723,6 +725,95 @@ void tst_QFutureWatcher::pauseEvents() } } +void tst_QFutureWatcher::suspended() +{ + QFutureWatcher<void> watcher; + QSignalSpy resultReadySpy(&watcher, &QFutureWatcher<int>::resultReadyAt); + QSignalSpy pausedSpy(&watcher, &QFutureWatcher<int>::paused); + QSignalSpy suspendedSpy(&watcher, &QFutureWatcher<int>::suspended); + QSignalSpy finishedSpy(&watcher, &QFutureWatcher<int>::finished); + + const int numValues = 25; + std::vector<int> values(numValues, 0); + std::atomic_int count = 0; + + QThreadPool pool; + pool.setMaxThreadCount(3); + + QFuture<int> future = QtConcurrent::mapped(&pool, values, [&](int value) { + ++count; + // Sleep, to make sure not all threads will start at once. + QThread::msleep(50); + return value; + }); + watcher.setFuture(future); + + // Allow some threads to start before pausing. + QThread::msleep(200); + + watcher.pause(); + watcher.pause(); + QTRY_COMPARE(suspendedSpy.count(), 1); // suspended() should be emitted only once + QCOMPARE(pausedSpy.count(), 2); // paused() is emitted as many times as requested + + // Make sure QFutureWatcher::resultReadyAt() is emitted only for already started threads. + const auto resultReadyAfterPaused = resultReadySpy.count(); + QCOMPARE(resultReadyAfterPaused, count); + + // Make sure no more results are reported before resuming. + QThread::msleep(200); + QCOMPARE(resultReadyAfterPaused, resultReadySpy.count()); + resultReadySpy.clear(); + + watcher.resume(); + QTRY_COMPARE(finishedSpy.count(), 1); + + // Make sure that no more suspended() signals have been emitted. + QCOMPARE(suspendedSpy.count(), 1); + + // Make sure the rest of results were reported after resume. + QCOMPARE(resultReadySpy.count(), numValues - resultReadyAfterPaused); +} + +void tst_QFutureWatcher::suspendedEvents() +{ + QFutureInterface<void> iface; + iface.reportStarted(); + + QFutureWatcher<void> watcher; + + QSignalSpy pausedSpy(&watcher, &QFutureWatcher<void>::paused); + QVERIFY(pausedSpy.isValid()); + + QSignalSpy suspendedSpy(&watcher, &QFutureWatcher<void>::suspended); + QVERIFY(suspendedSpy.isValid()); + + bool pausedBeforeSuspended = false; + bool notSuspendedBeforePasused = false; + connect(&watcher, &QFutureWatcher<void>::paused, + [&] { notSuspendedBeforePasused = (suspendedSpy.count() == 0); }); + connect(&watcher, &QFutureWatcher<void>::suspended, + [&] { pausedBeforeSuspended = (pausedSpy.count() == 1); }); + + watcher.setFuture(iface.future()); + iface.reportSuspended(); + + // Make sure reportPaused() is ignored if the state is not paused + pausedSpy.wait(100); + QCOMPARE(pausedSpy.count(), 0); + QCOMPARE(suspendedSpy.count(), 0); + + iface.setPaused(true); + iface.reportSuspended(); + + QTRY_COMPARE(suspendedSpy.count(), 1); + QCOMPARE(pausedSpy.count(), 1); + QVERIFY(notSuspendedBeforePasused); + QVERIFY(pausedBeforeSuspended); + + iface.reportFinished(); +} + // Test that the finished state for the watcher gets // set when the finished event is delivered. // This means it will lag the finished state for the future, |