summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index a6be2e9727..9c8bd232d5 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -143,6 +143,7 @@ private slots:
void onFailedForMoveOnlyTypes();
#endif
void onCanceled();
+ void cancelContinuations();
void continuationsWithContext();
#if 0
// TODO: enable when QFuture::takeResults() is enabled
@@ -2882,6 +2883,131 @@ void tst_QFuture::onCanceled()
#endif // QT_NO_EXCEPTIONS
}
+void tst_QFuture::cancelContinuations()
+{
+ // The chain is cancelled in the middle of execution of continuations
+ {
+ QPromise<int> promise;
+
+ int checkpoint = 0;
+ auto future = promise.future().then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ promise.future().cancel();
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).onCanceled([] {
+ return -1;
+ });
+
+ promise.start();
+ promise.addResult(42);
+ promise.finish();
+
+ QCOMPARE(future.result(), -1);
+ QCOMPARE(checkpoint, 2);
+ }
+
+ // The chain is cancelled before the execution of continuations
+ {
+ auto f = QtFuture::makeReadyFuture(42);
+ f.cancel();
+
+ int checkpoint = 0;
+ auto future = f.then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).onCanceled([] {
+ return -1;
+ });
+
+ QCOMPARE(future.result(), -1);
+ QCOMPARE(checkpoint, 0);
+ }
+
+ // The chain is canceled partially, through an intermediate future
+ {
+ QPromise<int> promise;
+
+ int checkpoint = 0;
+ auto intermediate = promise.future().then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ });
+
+ auto future = intermediate.then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).onCanceled([] {
+ return -1;
+ });
+
+ promise.start();
+ promise.addResult(42);
+
+ // This should cancel only the chain starting from intermediate
+ intermediate.cancel();
+
+ promise.finish();
+
+ QCOMPARE(future.result(), -1);
+ QCOMPARE(checkpoint, 1);
+ }
+
+#ifndef QT_NO_EXCEPTIONS
+ // The chain is cancelled in the middle of execution of continuations,
+ // while there's an exception in the chain, which is handeled inside
+ // the continuations.
+ {
+ QPromise<int> promise;
+
+ int checkpoint = 0;
+ auto future = promise.future().then([&](int value) {
+ ++checkpoint;
+ throw QException();
+ return value + 1;
+ }).then([&](QFuture<int> future) {
+ try {
+ auto res = future.result();
+ Q_UNUSED(res);
+ } catch (const QException &) {
+ ++checkpoint;
+ }
+ return 2;
+ }).then([&](int value) {
+ ++checkpoint;
+ promise.future().cancel();
+ return value + 1;
+ }).then([&](int value) {
+ ++checkpoint;
+ return value + 1;
+ }).onCanceled([] {
+ return -1;
+ });
+
+ promise.start();
+ promise.addResult(42);
+ promise.finish();
+
+ QCOMPARE(future.result(), -1);
+ QCOMPARE(checkpoint, 3);
+ }
+#endif // QT_NO_EXCEPTIONS
+}
+
void tst_QFuture::continuationsWithContext()
{
QThread thread;