diff options
Diffstat (limited to 'async/autotests/asynctest.cpp')
-rw-r--r-- | async/autotests/asynctest.cpp | 205 |
1 files changed, 186 insertions, 19 deletions
diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index c507721..d709567 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <QtTest/QTest> | 27 | #include <QtTest/QTest> |
28 | #include <QDebug> | 28 | #include <QDebug> |
29 | 29 | ||
30 | #include <functional> | ||
31 | |||
30 | class AsyncTest : public QObject | 32 | class AsyncTest : public QObject |
31 | { | 33 | { |
32 | Q_OBJECT | 34 | Q_OBJECT |
@@ -60,7 +62,11 @@ private Q_SLOTS: | |||
60 | void testJoinedReduce(); | 62 | void testJoinedReduce(); |
61 | void testVoidReduce(); | 63 | void testVoidReduce(); |
62 | 64 | ||
65 | void testProgressReporting(); | ||
63 | void testErrorHandler(); | 66 | void testErrorHandler(); |
67 | void testErrorPropagation(); | ||
68 | void testErrorHandlerAsync(); | ||
69 | void testErrorPropagationAsync(); | ||
64 | 70 | ||
65 | void testChainingRunningJob(); | 71 | void testChainingRunningJob(); |
66 | void testChainingFinishedJob(); | 72 | void testChainingFinishedJob(); |
@@ -91,8 +97,25 @@ private: | |||
91 | mTimer.start(200); | 97 | mTimer.start(200); |
92 | } | 98 | } |
93 | 99 | ||
100 | AsyncSimulator(Async::Future<T> &future, std::function<void(Async::Future<T>&)> callback) | ||
101 | : mFuture(future) | ||
102 | , mCallback(callback) | ||
103 | { | ||
104 | QObject::connect(&mTimer, &QTimer::timeout, | ||
105 | [this]() { | ||
106 | mCallback(mFuture); | ||
107 | }); | ||
108 | QObject::connect(&mTimer, &QTimer::timeout, | ||
109 | [this]() { | ||
110 | delete this; | ||
111 | }); | ||
112 | mTimer.setSingleShot(true); | ||
113 | mTimer.start(200); | ||
114 | } | ||
115 | |||
94 | private: | 116 | private: |
95 | Async::Future<T> mFuture; | 117 | Async::Future<T> mFuture; |
118 | std::function<void(Async::Future<T>&)> mCallback; | ||
96 | T mResult; | 119 | T mResult; |
97 | QTimer mTimer; | 120 | QTimer mTimer; |
98 | }; | 121 | }; |
@@ -340,8 +363,6 @@ void AsyncTest::testSyncEach() | |||
340 | 363 | ||
341 | void AsyncTest::testJoinedEach() | 364 | void AsyncTest::testJoinedEach() |
342 | { | 365 | { |
343 | QFAIL("Crashes due to bad lifetime of Future"); | ||
344 | |||
345 | auto job1 = Async::start<QList<int>, int>( | 366 | auto job1 = Async::start<QList<int>, int>( |
346 | [](int v, Async::Future<QList<int>> &future) { | 367 | [](int v, Async::Future<QList<int>> &future) { |
347 | new AsyncSimulator<QList<int>>(future, { v * 2 }); | 368 | new AsyncSimulator<QList<int>>(future, { v * 2 }); |
@@ -391,18 +412,14 @@ void AsyncTest::testAsyncReduce() | |||
391 | }) | 412 | }) |
392 | .reduce<int, QList<int>>( | 413 | .reduce<int, QList<int>>( |
393 | [](const QList<int> &list, Async::Future<int> &future) { | 414 | [](const QList<int> &list, Async::Future<int> &future) { |
394 | QTimer *timer = new QTimer(); | 415 | new AsyncSimulator<int>(future, |
395 | QObject::connect(timer, &QTimer::timeout, | 416 | [list](Async::Future<int> &future) { |
396 | [list, &future]() { | 417 | int sum = 0; |
397 | int sum = 0; | 418 | for (int i : list) sum += i; |
398 | for (int i : list) sum += i; | 419 | future.setValue(sum); |
399 | future.setValue(sum); | 420 | future.setFinished(); |
400 | future.setFinished(); | 421 | } |
401 | }); | 422 | ); |
402 | QObject::connect(timer, &QTimer::timeout, | ||
403 | timer, &QObject::deleteLater); | ||
404 | timer->setSingleShot(true); | ||
405 | timer->start(0); | ||
406 | }); | 423 | }); |
407 | 424 | ||
408 | Async::Future<int> future = job.exec(); | 425 | Async::Future<int> future = job.exec(); |
@@ -473,30 +490,182 @@ void AsyncTest::testVoidReduce() | |||
473 | } | 490 | } |
474 | 491 | ||
475 | 492 | ||
493 | void AsyncTest::testProgressReporting() | ||
494 | { | ||
495 | static int progress; | ||
496 | progress = 0; | ||
497 | |||
498 | auto job = Async::start<void>( | ||
499 | [](Async::Future<void> &f) { | ||
500 | QTimer *timer = new QTimer(); | ||
501 | connect(timer, &QTimer::timeout, | ||
502 | [&f, timer]() { | ||
503 | f.setProgress(++progress); | ||
504 | if (progress == 100) { | ||
505 | timer->stop(); | ||
506 | timer->deleteLater(); | ||
507 | f.setFinished(); | ||
508 | } | ||
509 | }); | ||
510 | timer->start(1); | ||
511 | }); | ||
512 | |||
513 | int progressCheck = 0; | ||
514 | Async::FutureWatcher<void> watcher; | ||
515 | connect(&watcher, &Async::FutureWatcher<void>::futureProgress, | ||
516 | [&progressCheck](qreal progress) { | ||
517 | progressCheck++; | ||
518 | // FIXME: Don't use Q_ASSERT in unit tests | ||
519 | Q_ASSERT((int) progress == progressCheck); | ||
520 | }); | ||
521 | watcher.setFuture(job.exec()); | ||
522 | watcher.future().waitForFinished(); | ||
523 | |||
524 | QVERIFY(watcher.future().isFinished()); | ||
525 | QCOMPARE(progressCheck, 100); | ||
526 | } | ||
476 | 527 | ||
477 | void AsyncTest::testErrorHandler() | 528 | void AsyncTest::testErrorHandler() |
478 | { | 529 | { |
530 | |||
531 | { | ||
532 | auto job = Async::start<int>( | ||
533 | [](Async::Future<int> &f) { | ||
534 | f.setError(1, "error"); | ||
535 | }); | ||
536 | |||
537 | auto future = job.exec(); | ||
538 | QVERIFY(future.isFinished()); | ||
539 | QCOMPARE(future.errorCode(), 1); | ||
540 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
541 | } | ||
542 | |||
543 | { | ||
544 | int error = 0; | ||
545 | auto job = Async::start<int>( | ||
546 | [](Async::Future<int> &f) { | ||
547 | f.setError(1, "error"); | ||
548 | }, | ||
549 | [&error](int errorCode, const QString &errorMessage) { | ||
550 | error += errorCode; | ||
551 | } | ||
552 | ); | ||
553 | |||
554 | auto future = job.exec(); | ||
555 | QVERIFY(future.isFinished()); | ||
556 | QCOMPARE(error, 1); | ||
557 | QCOMPARE(future.errorCode(), 1); | ||
558 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | void AsyncTest::testErrorPropagation() | ||
563 | { | ||
479 | int error = 0; | 564 | int error = 0; |
565 | bool called = false; | ||
480 | auto job = Async::start<int>( | 566 | auto job = Async::start<int>( |
481 | [](Async::Future<int> &f) { | 567 | [](Async::Future<int> &f) { |
482 | f.setError(1, "error"); | 568 | f.setError(1, "error"); |
483 | }) | 569 | }) |
484 | .then<int, int>( | 570 | .then<int, int>( |
485 | [](int v, Async::Future<int> &f) { | 571 | [&called](int v, Async::Future<int> &f) { |
572 | called = true; | ||
486 | f.setFinished(); | 573 | f.setFinished(); |
487 | }, | 574 | }, |
488 | [&error](int errorCode, const QString &errorMessage) { | 575 | [&error](int errorCode, const QString &errorMessage) { |
489 | error = errorCode; | 576 | error += errorCode; |
490 | } | 577 | } |
491 | ); | 578 | ); |
492 | auto future = job.exec(); | 579 | auto future = job.exec(); |
493 | future.waitForFinished(); | 580 | QVERIFY(future.isFinished()); |
581 | QCOMPARE(future.errorCode(), 1); | ||
582 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
583 | QCOMPARE(called, false); | ||
494 | QCOMPARE(error, 1); | 584 | QCOMPARE(error, 1); |
585 | } | ||
586 | |||
587 | void AsyncTest::testErrorHandlerAsync() | ||
588 | { | ||
589 | { | ||
590 | auto job = Async::start<int>( | ||
591 | [](Async::Future<int> &f) { | ||
592 | new AsyncSimulator<int>(f, | ||
593 | [](Async::Future<int> &f) { | ||
594 | f.setError(1, "error"); | ||
595 | } | ||
596 | ); | ||
597 | } | ||
598 | ); | ||
599 | |||
600 | auto future = job.exec(); | ||
601 | future.waitForFinished(); | ||
602 | |||
603 | QVERIFY(future.isFinished()); | ||
604 | QCOMPARE(future.errorCode(), 1); | ||
605 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
606 | } | ||
607 | |||
608 | { | ||
609 | int error = 0; | ||
610 | auto job = Async::start<int>( | ||
611 | [](Async::Future<int> &f) { | ||
612 | new AsyncSimulator<int>(f, | ||
613 | [](Async::Future<int> &f) { | ||
614 | f.setError(1, "error"); | ||
615 | } | ||
616 | ); | ||
617 | }, | ||
618 | [&error](int errorCode, const QString &errorMessage) { | ||
619 | error += errorCode; | ||
620 | } | ||
621 | ); | ||
622 | |||
623 | auto future = job.exec(); | ||
624 | future.waitForFinished(); | ||
625 | |||
626 | QVERIFY(future.isFinished()); | ||
627 | QCOMPARE(error, 1); | ||
628 | QCOMPARE(future.errorCode(), 1); | ||
629 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
630 | } | ||
631 | } | ||
632 | |||
633 | void AsyncTest::testErrorPropagationAsync() | ||
634 | { | ||
635 | int error = 0; | ||
636 | bool called = false; | ||
637 | auto job = Async::start<int>( | ||
638 | [](Async::Future<int> &f) { | ||
639 | new AsyncSimulator<int>(f, | ||
640 | [](Async::Future<int> &f) { | ||
641 | f.setError(1, "error"); | ||
642 | } | ||
643 | ); | ||
644 | }) | ||
645 | .then<int, int>( | ||
646 | [&called](int v, Async::Future<int> &f) { | ||
647 | called = true; | ||
648 | f.setFinished(); | ||
649 | }, | ||
650 | [&error](int errorCode, const QString &errorMessage) { | ||
651 | error += errorCode; | ||
652 | } | ||
653 | ); | ||
654 | |||
655 | auto future = job.exec(); | ||
656 | future.waitForFinished(); | ||
657 | |||
495 | QVERIFY(future.isFinished()); | 658 | QVERIFY(future.isFinished()); |
659 | QCOMPARE(future.errorCode(), 1); | ||
660 | QCOMPARE(future.errorMessage(), QString::fromLatin1("error")); | ||
661 | QCOMPARE(called, false); | ||
662 | QCOMPARE(error, 1); | ||
496 | } | 663 | } |
497 | 664 | ||
498 | 665 | ||
499 | 666 | ||
667 | |||
668 | |||
500 | void AsyncTest::testChainingRunningJob() | 669 | void AsyncTest::testChainingRunningJob() |
501 | { | 670 | { |
502 | int check = 0; | 671 | int check = 0; |
@@ -636,8 +805,6 @@ void AsyncTest::benchmarkSyncThenExecutor() | |||
636 | } | 805 | } |
637 | } | 806 | } |
638 | 807 | ||
639 | |||
640 | |||
641 | QTEST_MAIN(AsyncTest); | 808 | QTEST_MAIN(AsyncTest); |
642 | 809 | ||
643 | #include "asynctest.moc" | 810 | #include "asynctest.moc" |