summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp38
-rw-r--r--tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp91
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,