diff --git a/README.md b/README.md index 935e4c9..b3cbda7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Promises/A+ # QtPromise -[![qpm](https://img.shields.io/github/release/simonbrunel/qtpromise.svg?style=flat-square&label=qpm&colorB=4CAF50)](http://www.qpm.io/packages/com.github.simonbrunel.qtpromise/index.html) [![Travis](https://img.shields.io/travis/simonbrunel/qtpromise.svg?style=flat-square)](https://travis-ci.org/simonbrunel/qtpromise) [![coverage](https://img.shields.io/codecov/c/github/simonbrunel/qtpromise.svg?style=flat-square)](https://codecov.io/gh/simonbrunel/qtpromise) +[![qpm](https://img.shields.io/github/release/simonbrunel/qtpromise.svg?style=flat-square&label=qpm&colorB=4CAF50)](http://www.qpm.io/packages/com.github.simonbrunel.qtpromise/index.html) [![Travis](https://img.shields.io/travis/simonbrunel/qtpromise/master.svg?style=flat-square)](https://travis-ci.org/simonbrunel/qtpromise) [![coverage](https://img.shields.io/codecov/c/github/simonbrunel/qtpromise.svg?style=flat-square)](https://codecov.io/gh/simonbrunel/qtpromise) [Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/). diff --git a/tests/auto/qtpromise/qpromise/construct/construct.pro b/tests/auto/qtpromise/qpromise/construct/construct.pro new file mode 100644 index 0000000..83b8095 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/construct/construct.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_construct +SOURCES += $$PWD/tst_construct.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/construct/tst_construct.cpp b/tests/auto/qtpromise/qpromise/construct/tst_construct.cpp new file mode 100644 index 0000000..c4ffc80 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/construct/tst_construct.cpp @@ -0,0 +1,230 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_construct : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void resolveSyncOneArg(); + void resolveSyncOneArg_void(); + void resolveSyncTwoArgs(); + void resolveSyncTwoArgs_void(); + void resolveAsyncOneArg(); + void resolveAsyncOneArg_void(); + void resolveAsyncTwoArgs(); + void resolveAsyncTwoArgs_void(); + void rejectThrowOneArg(); + void rejectThrowOneArg_void(); + void rejectThrowTwoArgs(); + void rejectThrowTwoArgs_void(); + void rejectSync(); + void rejectSync_void(); + void rejectAsync(); + void rejectAsync_void(); +}; + +QTEST_MAIN(tst_qpromise_construct) +#include "tst_construct.moc" + +void tst_qpromise_construct::resolveSyncOneArg() +{ + QPromise p([](const QPromiseResolve& resolve) { + resolve(42); + }); + + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1), 42); +} + +void tst_qpromise_construct::resolveSyncOneArg_void() +{ + QPromise p([](const QPromiseResolve& resolve) { + resolve(); + }); + + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1, 42), 42); +} + +void tst_qpromise_construct::resolveSyncTwoArgs() +{ + QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { + resolve(42); + }); + + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1), 42); +} + +void tst_qpromise_construct::resolveSyncTwoArgs_void() +{ + QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { + resolve(); + }); + + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1, 42), 42); +} + +void tst_qpromise_construct::resolveAsyncOneArg() +{ + QPromise p([](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=]() { + resolve(42); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); +} + +void tst_qpromise_construct::resolveAsyncOneArg_void() +{ + QPromise p([](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=]() { + resolve(); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1, 42), 42); + QCOMPARE(p.isFulfilled(), true); +} + +void tst_qpromise_construct::resolveAsyncTwoArgs() +{ + QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { + QtPromisePrivate::qtpromise_defer([=]() { + resolve(42); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); +} + +void tst_qpromise_construct::resolveAsyncTwoArgs_void() +{ + QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { + QtPromisePrivate::qtpromise_defer([=]() { + resolve(); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForError(p, QString()), QString()); + QCOMPARE(waitForValue(p, -1, 42), 42); + QCOMPARE(p.isFulfilled(), true); +} + +void tst_qpromise_construct::rejectSync() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { + reject(QString("foo")); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} + +void tst_qpromise_construct::rejectSync_void() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { + reject(QString("foo")); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1, 42), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} + +void tst_qpromise_construct::rejectAsync() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=]() { + reject(QString("foo")); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForValue(p, -1), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_construct::rejectAsync_void() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=]() { + reject(QString("foo")); + }); + }); + + QCOMPARE(p.isPending(), true); + QCOMPARE(waitForValue(p, -1, 42), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_construct::rejectThrowOneArg() +{ + QPromise p([](const QPromiseResolve&) { + throw QString("foo"); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} + +void tst_qpromise_construct::rejectThrowOneArg_void() +{ + QPromise p([](const QPromiseResolve&) { + throw QString("foo"); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1, 42), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} + +void tst_qpromise_construct::rejectThrowTwoArgs() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject&) { + throw QString("foo"); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} + +void tst_qpromise_construct::rejectThrowTwoArgs_void() +{ + QPromise p([](const QPromiseResolve&, const QPromiseReject&) { + throw QString("foo"); + }); + + QCOMPARE(p.isRejected(), true); + QCOMPARE(waitForValue(p, -1, 42), -1); + QCOMPARE(waitForError(p, QString()), QString("foo")); +} diff --git a/tests/auto/qtpromise/qpromise/delay/delay.pro b/tests/auto/qtpromise/qpromise/delay/delay.pro new file mode 100644 index 0000000..bc905c8 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/delay/delay.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_delay +SOURCES += $$PWD/tst_delay.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/delay/tst_delay.cpp b/tests/auto/qtpromise/qpromise/delay/tst_delay.cpp new file mode 100644 index 0000000..5a35aec --- /dev/null +++ b/tests/auto/qtpromise/qpromise/delay/tst_delay.cpp @@ -0,0 +1,55 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_delay : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void fulfilled(); + void rejected(); +}; + +QTEST_MAIN(tst_qpromise_delay) +#include "tst_delay.moc" + +void tst_qpromise_delay::fulfilled() +{ + QElapsedTimer timer; + qint64 elapsed = -1; + + timer.start(); + + auto p = QPromise::resolve(42).delay(1000).finally([&]() { + elapsed = timer.elapsed(); + }); + + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + QVERIFY(elapsed >= 1000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to + QVERIFY(elapsed <= 1000 * 1.05); // keep accuracy within 5% of the desired interval. +} + +void tst_qpromise_delay::rejected() +{ + QElapsedTimer timer; + qint64 elapsed = -1; + + timer.start(); + + auto p = QPromise::reject(QString("foo")).delay(1000).finally([&]() { + elapsed = timer.elapsed(); + }); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QVERIFY(elapsed < 5); +} diff --git a/tests/auto/qtpromise/qpromise/fail/fail.pro b/tests/auto/qtpromise/qpromise/fail/fail.pro new file mode 100644 index 0000000..db8fea3 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/fail/fail.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_fail +SOURCES += $$PWD/tst_fail.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/fail/tst_fail.cpp b/tests/auto/qtpromise/qpromise/fail/tst_fail.cpp new file mode 100644 index 0000000..3477c2c --- /dev/null +++ b/tests/auto/qtpromise/qpromise/fail/tst_fail.cpp @@ -0,0 +1,83 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_fail : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void sameType(); + void baseClass(); + void catchAll(); + // TODO: sync / async +}; + +QTEST_MAIN(tst_qpromise_fail) +#include "tst_fail.moc" + +void tst_qpromise_fail::sameType() +{ + // http://en.cppreference.com/w/cpp/error/exception + auto p = QPromise::reject(std::out_of_range("foo")); + + QString error; + p.fail([&](const std::domain_error& e) { + error += QString(e.what()) + "0"; + return -1; + }).fail([&](const std::out_of_range& e) { + error += QString(e.what()) + "1"; + return -1; + }).fail([&](const std::exception& e) { + error += QString(e.what()) + "2"; + return -1; + }).wait(); + + QCOMPARE(error, QString("foo1")); +} + +void tst_qpromise_fail::baseClass() +{ + // http://en.cppreference.com/w/cpp/error/exception + auto p = QPromise::reject(std::out_of_range("foo")); + + QString error; + p.fail([&](const std::runtime_error& e) { + error += QString(e.what()) + "0"; + return -1; + }).fail([&](const std::logic_error& e) { + error += QString(e.what()) + "1"; + return -1; + }).fail([&](const std::exception& e) { + error += QString(e.what()) + "2"; + return -1; + }).wait(); + + QCOMPARE(error, QString("foo1")); +} + +void tst_qpromise_fail::catchAll() +{ + auto p = QPromise::reject(std::out_of_range("foo")); + + QString error; + p.fail([&](const std::runtime_error& e) { + error += QString(e.what()) + "0"; + return -1; + }).fail([&]() { + error += "bar"; + return -1; + }).fail([&](const std::exception& e) { + error += QString(e.what()) + "2"; + return -1; + }).wait(); + + QCOMPARE(error, QString("bar")); +} diff --git a/tests/auto/qtpromise/qpromise/finally/finally.pro b/tests/auto/qtpromise/qpromise/finally/finally.pro new file mode 100644 index 0000000..6cd4893 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/finally/finally.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_finally +SOURCES += $$PWD/tst_finally.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/finally/tst_finally.cpp b/tests/auto/qtpromise/qpromise/finally/tst_finally.cpp new file mode 100644 index 0000000..024a509 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/finally/tst_finally.cpp @@ -0,0 +1,204 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_finally : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void fulfilledSync(); + void fulfilledSync_void(); + void fulfilledThrows(); + void fulfilledThrows_void(); + void fulfilledAsyncResolve(); + void fulfilledAsyncReject(); + void rejectedSync(); + void rejectedSync_void(); + void rejectedThrows(); + void rejectedThrows_void(); + void rejectedAsyncResolve(); + void rejectedAsyncReject(); +}; + +QTEST_MAIN(tst_qpromise_finally) +#include "tst_finally.moc" + +void tst_qpromise_finally::fulfilledSync() +{ + int value = -1; + auto p = QPromise::resolve(42).finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 8); +} + +void tst_qpromise_finally::fulfilledSync_void() +{ + int value = -1; + auto p = QPromise::resolve().finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForValue(p, -1, 42), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 8); +} + +void tst_qpromise_finally::fulfilledThrows() +{ + auto p = QPromise::resolve(42).finally([&]() { + throw QString("bar"); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_finally::fulfilledThrows_void() +{ + auto p = QPromise::resolve().finally([&]() { + throw QString("bar"); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_finally::fulfilledAsyncResolve() +{ + QVector values; + auto p = QPromise::resolve(42).finally([&]() { + QPromise p([&](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=, &values]() { + values << 64; + resolve(16); // ignored! + }); + }); + + values << 8; + return p; + }); + + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(values, QVector({8, 64})); +} + +void tst_qpromise_finally::fulfilledAsyncReject() +{ + auto p = QPromise::resolve(42).finally([]() { + return QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=]() { + reject(QString("bar")); + }); + }); + }); + + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_finally::rejectedSync() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, 8); +} + +void tst_qpromise_finally::rejectedSync_void() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, 8); +} + +void tst_qpromise_finally::rejectedThrows() +{ + auto p = QPromise::reject(QString("foo")).finally([&]() { + throw QString("bar"); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_finally::rejectedThrows_void() +{ + auto p = QPromise::reject(QString("foo")).finally([&]() { + throw QString("bar"); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_finally::rejectedAsyncResolve() +{ + QVector values; + auto p = QPromise::reject(QString("foo")).finally([&]() { + QPromise p([&](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=, &values]() { + values << 64; + resolve(16); // ignored! + }); + }); + + values << 8; + return p; + }); + + p.then([&](int r) { + values << r; + }).wait(); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(values, QVector({8, 64})); +} + +void tst_qpromise_finally::rejectedAsyncReject() +{ + auto p = QPromise::reject(QString("foo")).finally([]() { + return QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=]() { + reject(QString("bar")); + }); + }); + }); + + QCOMPARE(waitForError(p, QString()), QString("bar")); + QCOMPARE(p.isRejected(), true); +} diff --git a/tests/auto/qtpromise/qpromise/qpromise.pro b/tests/auto/qtpromise/qpromise/qpromise.pro index 0fb2a2f..7eb2f1f 100644 --- a/tests/auto/qtpromise/qpromise/qpromise.pro +++ b/tests/auto/qtpromise/qpromise/qpromise.pro @@ -1,4 +1,9 @@ -TARGET = tst_qpromise -SOURCES += $$PWD/tst_qpromise.cpp - -include(../qtpromise.pri) +TEMPLATE = subdirs +SUBDIRS += \ + construct \ + delay \ + fail \ + finally \ + tap \ + then \ + timeout diff --git a/tests/auto/qtpromise/qpromise/tap/tap.pro b/tests/auto/qtpromise/qpromise/tap/tap.pro new file mode 100644 index 0000000..71958f8 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/tap/tap.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_tap +SOURCES += $$PWD/tst_tap.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/tap/tst_tap.cpp b/tests/auto/qtpromise/qpromise/tap/tst_tap.cpp new file mode 100644 index 0000000..6061f9f --- /dev/null +++ b/tests/auto/qtpromise/qpromise/tap/tst_tap.cpp @@ -0,0 +1,145 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_tap : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void fulfilledSync(); + void fulfilledSync_void(); + void fulfilledThrows(); + void fulfilledThrows_void(); + void fulfilledAsyncResolve(); + void fulfilledAsyncReject(); + void rejectedSync(); + void rejectedSync_void(); +}; + +QTEST_MAIN(tst_qpromise_tap) +#include "tst_tap.moc" + +void tst_qpromise_tap::fulfilledSync() +{ + int value = -1; + auto p = QPromise::resolve(42).tap([&](int res) { + value = res + 1; + return 8; + }); + + QCOMPARE(waitForValue(p, 42), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 43); +} + +void tst_qpromise_tap::fulfilledSync_void() +{ + int value = -1; + auto p = QPromise::resolve().tap([&]() { + value = 43; + return 8; + }); + + QCOMPARE(waitForValue(p, -1, 42), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 43); +} + +void tst_qpromise_tap::fulfilledThrows() +{ + auto p = QPromise::resolve(42).tap([&](int) { + throw QString("foo"); + }); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_tap::fulfilledThrows_void() +{ + auto p = QPromise::resolve().tap([&]() { + throw QString("foo"); + }); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_tap::fulfilledAsyncResolve() +{ + QVector values; + auto p = QPromise::resolve(1).tap([&](int) { + QPromise p([&](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=, &values]() { + values << 3; + resolve(4); // ignored! + }); + }); + + values << 2; + return p; + }); + + p.then([&](int r) { + values << r; + }).wait(); + + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(values, QVector({2, 3, 1})); +} + +void tst_qpromise_tap::fulfilledAsyncReject() +{ + QVector values; + auto p = QPromise::resolve(1).tap([&](int) { + QPromise p([&](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=, &values]() { + values << 3; + reject(QString("foo")); + }); + }); + + values << 2; + return p; + }); + + p.then([&](int r) { + values << r; + }).wait(); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(values, QVector({2, 3})); +} + +void tst_qpromise_tap::rejectedSync() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).tap([&](int res) { + value = res + 1; + }); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, -1); +} + +void tst_qpromise_tap::rejectedSync_void() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).tap([&]() { + value = 43; + }); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, -1); +} diff --git a/tests/auto/qtpromise/qpromise/then/then.pro b/tests/auto/qtpromise/qpromise/then/then.pro new file mode 100644 index 0000000..b82d33e --- /dev/null +++ b/tests/auto/qtpromise/qpromise/then/then.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_then +SOURCES += $$PWD/tst_then.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/then/tst_then.cpp b/tests/auto/qtpromise/qpromise/then/tst_then.cpp new file mode 100644 index 0000000..3d5bf03 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/then/tst_then.cpp @@ -0,0 +1,126 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_then : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void resolveSync(); + void resolveAsync(); + void rejectSync(); + void rejectAsync(); + void skipResult(); + void noHandler(); +}; + +QTEST_MAIN(tst_qpromise_then) +#include "tst_then.moc" + +void tst_qpromise_then::resolveSync() +{ + QVariantList values; + + auto input = QPromise::resolve(42); + auto output = input.then([&](int res) { + values << res; + return QString::number(res+1); + }); + + output.then([&](const QString& res) { + values << res; + }).then([&]() { + values << 44; + }).wait(); + + QCOMPARE(values, QVariantList({42, QString("43"), 44})); + QCOMPARE(input.isFulfilled(), true); + QCOMPARE(output.isFulfilled(), true); +} + +void tst_qpromise_then::resolveAsync() +{ + auto p = QPromise::resolve(42).then([](int res) { + return QPromise([=](const QPromiseResolve& resolve) { + QtPromisePrivate::qtpromise_defer([=]() { + resolve(QString("foo%1").arg(res)); + }); + }); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForValue(p, QString()), QString("foo42")); + QCOMPARE(p.isFulfilled(), true); +} + +void tst_qpromise_then::rejectSync() +{ + auto input = QPromise::resolve(42); + auto output = input.then([](int res) { + throw QString("foo%1").arg(res); + return 42; + }); + + QString error; + output.then([&](int res) { + error += "bar" + QString::number(res); + }).fail([&](const QString& err) { + error += err; + }).wait(); + + QCOMPARE(error, QString("foo42")); + QCOMPARE(input.isFulfilled(), true); + QCOMPARE(output.isRejected(), true); +} + +void tst_qpromise_then::rejectAsync() +{ + auto p = QPromise::resolve(42).then([](int res) { + return QPromise([=](const QPromiseResolve&, const QPromiseReject& reject) { + QtPromisePrivate::qtpromise_defer([=]() { + reject(QString("foo%1").arg(res)); + }); + }); + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("foo42")); + QCOMPARE(p.isRejected(), true); +} + +void tst_qpromise_then::skipResult() +{ + auto p = QPromise::resolve(42); + + int value = -1; + p.then([&]() { + value = 43; + }).wait(); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(value, 43); +} + +void tst_qpromise_then::noHandler() +{ + { // resolved + auto p = QPromise::resolve(42).then(nullptr); + + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + } + { // rejected + auto p = QPromise::reject(QString("foo")).then(nullptr); + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + } +} diff --git a/tests/auto/qtpromise/qpromise/timeout/timeout.pro b/tests/auto/qtpromise/qpromise/timeout/timeout.pro new file mode 100644 index 0000000..c3ce03a --- /dev/null +++ b/tests/auto/qtpromise/qpromise/timeout/timeout.pro @@ -0,0 +1,4 @@ +TARGET = tst_qpromise_timeout +SOURCES += $$PWD/tst_timeout.cpp + +include(../../qtpromise.pri) diff --git a/tests/auto/qtpromise/qpromise/timeout/tst_timeout.cpp b/tests/auto/qtpromise/qpromise/timeout/tst_timeout.cpp new file mode 100644 index 0000000..bf43c61 --- /dev/null +++ b/tests/auto/qtpromise/qpromise/timeout/tst_timeout.cpp @@ -0,0 +1,92 @@ +// Tests +#include "../../shared/utils.h" + +// QtPromise +#include + +// Qt +#include + +using namespace QtPromise; + +class tst_qpromise_timeout : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void fulfilled(); + void rejected(); + void timeout(); +}; + +QTEST_MAIN(tst_qpromise_timeout) +#include "tst_timeout.moc" + +void tst_qpromise_timeout::fulfilled() +{ + QElapsedTimer timer; + qint64 elapsed = -1; + + timer.start(); + + auto p = QPromise([](const QPromiseResolve& resolve) { + QTimer::singleShot(1000, [=]() { + resolve(42); + }); + }).timeout(2000).finally([&]() { + elapsed = timer.elapsed(); + }); + + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + QVERIFY(elapsed < 2000); +} + +void tst_qpromise_timeout::rejected() +{ + QElapsedTimer timer; + qint64 elapsed = -1; + + timer.start(); + + auto p = QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { + QTimer::singleShot(1000, [=]() { + reject(QString("foo")); + }); + }).timeout(2000).finally([&]() { + elapsed = timer.elapsed(); + }); + + + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QVERIFY(elapsed < 2000); +} + +void tst_qpromise_timeout::timeout() +{ + QElapsedTimer timer; + qint64 elapsed = -1; + bool failed = false; + + timer.start(); + + auto p = QPromise([](const QPromiseResolve& resolve) { + QTimer::singleShot(4000, [=]() { + resolve(42); + }); + }).timeout(2000).finally([&]() { + elapsed = timer.elapsed(); + }); + + p.fail([&](const QPromiseTimeoutException&) { + failed = true; + return -1; + }).wait(); + + QCOMPARE(waitForValue(p, -1), -1); + QCOMPARE(p.isRejected(), true); + QCOMPARE(failed, true); + QVERIFY(elapsed >= 2000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to + QVERIFY(elapsed <= 2000 * 1.05); // keep accuracy within 5% of the desired interval. +} diff --git a/tests/auto/qtpromise/qpromise/tst_qpromise.cpp b/tests/auto/qtpromise/qpromise/tst_qpromise.cpp deleted file mode 100644 index f20b989..0000000 --- a/tests/auto/qtpromise/qpromise/tst_qpromise.cpp +++ /dev/null @@ -1,766 +0,0 @@ -// QtPromise -#include - -// Qt -#include -#include - -using namespace QtPromise; -using namespace QtPromisePrivate; - -class tst_qpromise : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void resolveSync(); - void resolveSync_void(); - void resolveDelayed(); - void rejectSync(); - void rejectDelayed(); - void rejectThrows(); - - void thenReturns(); - void thenThrows(); - void thenNullPtr(); - void thenSkipResult(); - void thenDelayedResolved(); - void thenDelayedRejected(); - - void failSameType(); - void failBaseClass(); - void failCatchAll(); - - void finallyFulfilled(); - void finallyFulfilled_void(); - void finallyRejected(); - void finallyRejected_void(); - void finallyThrows(); - void finallyThrows_void(); - void finallyDelayedResolved(); - void finallyDelayedRejected(); - - void tapFulfilled(); - void tapFulfilled_void(); - void tapRejected(); - void tapRejected_void(); - void tapThrows(); - void tapThrows_void(); - void tapDelayedResolved(); - void tapDelayedRejected(); - - void timeoutFulfilled(); - void timeoutRejected(); - void timeoutReject(); - - void delayFulfilled(); - void delayRejected(); - -}; // class tst_qpromise - -QTEST_MAIN(tst_qpromise) -#include "tst_qpromise.moc" - -template -T waitForValue(const QPromise& promise, const T& initial) -{ - T value(initial); - promise.then([&](const T& res) { - value = res; - }).wait(); - return value; -} - -template -T waitForValue(const QPromise& promise, const T& initial, const T& expected) -{ - T value(initial); - promise.then([&]() { - value = expected; - }).wait(); - return value; -} - -template -E waitForError(const QPromise& promise, const E& initial) -{ - E error(initial); - promise.fail([&](const E& err) { - error = err; - return T(); - }).wait(); - return error; -} - -template -E waitForError(const QPromise& promise, const E& initial) -{ - E error(initial); - promise.fail([&](const E& err) { - error = err; - }).wait(); - return error; -} - -void tst_qpromise::resolveSync() -{ - { // resolver(resolve) - QPromise p([](const QPromiseResolve& resolve) { - resolve(42); - }); - - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1), 42); - } - { // resolver(resolve, reject) - QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { - resolve(42); - }); - - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1), 42); - } -} - -void tst_qpromise::resolveSync_void() -{ - { // resolver(resolve) - QPromise p([](const QPromiseResolve& resolve) { - resolve(); - }); - - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1, 42), 42); - } - { // resolver(resolve, reject) - QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { - resolve(); - }); - - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1, 42), 42); - } -} - -void tst_qpromise::resolveDelayed() -{ - { // resolver(resolve) - QPromise p([](const QPromiseResolve& resolve) { - QtPromisePrivate::qtpromise_defer([=]() { - resolve(42); - }); - }); - - QCOMPARE(p.isPending(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - } - { // resolver(resolve, reject) - QPromise p([](const QPromiseResolve& resolve, const QPromiseReject&) { - QtPromisePrivate::qtpromise_defer([=]() { - resolve(42); - }); - }); - - QCOMPARE(p.isPending(), true); - QCOMPARE(waitForError(p, QString()), QString()); - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - } -} - -void tst_qpromise::rejectSync() -{ - QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { - reject(QString("foo")); - }); - - QCOMPARE(p.isRejected(), true); - QCOMPARE(waitForValue(p, -1), -1); - QCOMPARE(waitForError(p, QString()), QString("foo")); -} - -void tst_qpromise::rejectDelayed() -{ - QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { - QtPromisePrivate::qtpromise_defer([=]() { - reject(QString("foo")); - }); - }); - - QCOMPARE(p.isPending(), true); - QCOMPARE(waitForValue(p, -1), -1); - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); -} - -void tst_qpromise::rejectThrows() -{ - { // resolver(resolve) - QPromise p([](const QPromiseResolve&) { - throw QString("foo"); - }); - - QCOMPARE(p.isRejected(), true); - QCOMPARE(waitForValue(p, -1), -1); - QCOMPARE(waitForError(p, QString()), QString("foo")); - } - { // resolver(resolve, reject) - QPromise p([](const QPromiseResolve&, const QPromiseReject&) { - throw QString("foo"); - }); - - QCOMPARE(p.isRejected(), true); - QCOMPARE(waitForValue(p, -1), -1); - QCOMPARE(waitForError(p, QString()), QString("foo")); - } -} - -void tst_qpromise::thenReturns() -{ - auto p = QPromise::resolve(42); - - QVariantList values; - p.then([&](int res) { - values << res; - return QString::number(res+1); - }).then([&](const QString& res) { - values << res; - }).then([&]() { - values << 44; - }).wait(); - - QCOMPARE(values, QVariantList({42, QString("43"), 44})); -} - -void tst_qpromise::thenThrows() -{ - auto input = QPromise::resolve(42); - auto output = input.then([](int res) { - throw QString("foo%1").arg(res); - return 42; - }); - - QString error; - output.then([&](int res) { - error += "bar" + QString::number(res); - }).fail([&](const QString& err) { - error += err; - }).wait(); - - QCOMPARE(input.isFulfilled(), true); - QCOMPARE(output.isRejected(), true); - QCOMPARE(error, QString("foo42")); -} - -void tst_qpromise::thenNullPtr() -{ - { // resolved - auto p = QPromise::resolve(42).then(nullptr); - - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - } - { // rejected - auto p = QPromise::reject(QString("foo")).then(nullptr); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - } -} - -void tst_qpromise::thenSkipResult() -{ - auto p = QPromise::resolve(42); - - int value = -1; - p.then([&]() { - value = 43; - }).wait(); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(value, 43); -} - -void tst_qpromise::thenDelayedResolved() -{ - auto p = QPromise::resolve(42).then([](int res) { - return QPromise([=](const QPromiseResolve& resolve) { - QtPromisePrivate::qtpromise_defer([=]() { - resolve(QString("foo%1").arg(res)); - }); - }); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForValue(p, QString()), QString("foo42")); -} - -void tst_qpromise::thenDelayedRejected() -{ - auto p = QPromise::resolve(42).then([](int res) { - return QPromise([=](const QPromiseResolve&, const QPromiseReject& reject) { - QtPromisePrivate::qtpromise_defer([=]() { - reject(QString("foo%1").arg(res)); - }); - }); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("foo42")); -} - -void tst_qpromise::failSameType() -{ - // http://en.cppreference.com/w/cpp/error/exception - auto p = QPromise::reject(std::out_of_range("foo")); - - QString error; - p.fail([&](const std::domain_error& e) { - error += QString(e.what()) + "0"; - return -1; - }).fail([&](const std::out_of_range& e) { - error += QString(e.what()) + "1"; - return -1; - }).fail([&](const std::exception& e) { - error += QString(e.what()) + "2"; - return -1; - }).wait(); - - QCOMPARE(error, QString("foo1")); -} - -void tst_qpromise::failBaseClass() -{ - // http://en.cppreference.com/w/cpp/error/exception - auto p = QPromise::reject(std::out_of_range("foo")); - - QString error; - p.fail([&](const std::runtime_error& e) { - error += QString(e.what()) + "0"; - return -1; - }).fail([&](const std::logic_error& e) { - error += QString(e.what()) + "1"; - return -1; - }).fail([&](const std::exception& e) { - error += QString(e.what()) + "2"; - return -1; - }).wait(); - - QCOMPARE(error, QString("foo1")); -} - -void tst_qpromise::failCatchAll() -{ - auto p = QPromise::reject(std::out_of_range("foo")); - - QString error; - p.fail([&](const std::runtime_error& e) { - error += QString(e.what()) + "0"; - return -1; - }).fail([&]() { - error += "bar"; - return -1; - }).fail([&](const std::exception& e) { - error += QString(e.what()) + "2"; - return -1; - }).wait(); - - QCOMPARE(error, QString("bar")); -} - -void tst_qpromise::finallyFulfilled() -{ - int value = -1; - auto p = QPromise::resolve(42).finally([&]() { - value = 8; - return 16; // ignored! - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 8); -} - -void tst_qpromise::finallyFulfilled_void() -{ - int value = -1; - auto p = QPromise::resolve().finally([&]() { - value = 8; - return 16; // ignored! - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForValue(p, -1, 42), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 8); -} - -void tst_qpromise::finallyRejected() -{ - int value = -1; - auto p = QPromise::reject(QString("foo")).finally([&]() { - value = 8; - return 16; // ignored! - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, 8); -} - -void tst_qpromise::finallyRejected_void() -{ - int value = -1; - auto p = QPromise::reject(QString("foo")).finally([&]() { - value = 8; - return 16; // ignored! - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, 8); -} - -void tst_qpromise::finallyThrows() -{ - { // fulfilled - auto p = QPromise::resolve(42).finally([&]() { - throw QString("bar"); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } - { // rejected - auto p = QPromise::reject(QString("foo")).finally([&]() { - throw QString("bar"); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } -} - -void tst_qpromise::finallyThrows_void() -{ - { // fulfilled - auto p = QPromise::resolve().finally([&]() { - throw QString("bar"); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } - { // rejected - auto p = QPromise::reject(QString("foo")).finally([&]() { - throw QString("bar"); - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } -} - -void tst_qpromise::finallyDelayedResolved() -{ - { // fulfilled - QVector values; - auto p = QPromise::resolve(42).finally([&]() { - QPromise p([&](const QPromiseResolve& resolve) { - qtpromise_defer([=, &values]() { - values << 64; - resolve(16); // ignored! - }); - }); - - values << 8; - return p; - }); - - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(values, QVector({8, 64})); - } - { // rejected - QVector values; - auto p = QPromise::reject(QString("foo")).finally([&]() { - QPromise p([&](const QPromiseResolve& resolve) { - qtpromise_defer([=, &values]() { - values << 64; - resolve(16); // ignored! - }); - }); - - values << 8; - return p; - }); - - p.then([&](int r) { - values << r; - }).wait(); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(values, QVector({8, 64})); - } -} - -void tst_qpromise::finallyDelayedRejected() -{ - { // fulfilled - auto p = QPromise::resolve(42).finally([]() { - return QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=]() { - reject(QString("bar")); - }); - }); - }); - - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } - { // rejected - auto p = QPromise::reject(QString("foo")).finally([]() { - return QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=]() { - reject(QString("bar")); - }); - }); - }); - - QCOMPARE(waitForError(p, QString()), QString("bar")); - QCOMPARE(p.isRejected(), true); - } -} - -void tst_qpromise::tapFulfilled() -{ - int value = -1; - auto p = QPromise::resolve(42).tap([&](int res) { - value = res + 1; - return 8; - }); - - QCOMPARE(waitForValue(p, 42), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 43); -} - -void tst_qpromise::tapFulfilled_void() -{ - int value = -1; - auto p = QPromise::resolve().tap([&]() { - value = 43; - return 8; - }); - - QCOMPARE(waitForValue(p, -1, 42), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 43); -} - -void tst_qpromise::tapRejected() -{ - int value = -1; - auto p = QPromise::reject(QString("foo")).tap([&](int res) { - value = res + 1; - }); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, -1); -} - -void tst_qpromise::tapRejected_void() -{ - int value = -1; - auto p = QPromise::reject(QString("foo")).tap([&]() { - value = 43; - }); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, -1); -} - -void tst_qpromise::tapThrows() -{ - auto p = QPromise::resolve(42).tap([&](int) { - throw QString("foo"); - }); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); -} - -void tst_qpromise::tapThrows_void() -{ - auto p = QPromise::resolve().tap([&]() { - throw QString("foo"); - }); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); -} - -void tst_qpromise::tapDelayedResolved() -{ - QVector values; - auto p = QPromise::resolve(1).tap([&](int) { - QPromise p([&](const QPromiseResolve& resolve) { - qtpromise_defer([=, &values]() { - values << 3; - resolve(4); // ignored! - }); - }); - - values << 2; - return p; - }); - - p.then([&](int r) { - values << r; - }).wait(); - - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(values, QVector({2, 3, 1})); -} - -void tst_qpromise::tapDelayedRejected() -{ - QVector values; - auto p = QPromise::resolve(1).tap([&](int) { - QPromise p([&](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=, &values]() { - values << 3; - reject(QString("foo")); - }); - }); - - values << 2; - return p; - }); - - p.then([&](int r) { - values << r; - }).wait(); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(values, QVector({2, 3})); -} - -void tst_qpromise::timeoutFulfilled() -{ - QElapsedTimer timer; - qint64 elapsed = -1; - - timer.start(); - - auto p = QPromise([](const QPromiseResolve& resolve) { - QTimer::singleShot(1000, [=]() { - resolve(42); - }); - }).timeout(2000).finally([&]() { - elapsed = timer.elapsed(); - }); - - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - QVERIFY(elapsed < 2000); -} - -void tst_qpromise::timeoutRejected() -{ - QElapsedTimer timer; - qint64 elapsed = -1; - - timer.start(); - - auto p = QPromise([](const QPromiseResolve&, const QPromiseReject& reject) { - QTimer::singleShot(1000, [=]() { - reject(QString("foo")); - }); - }).timeout(2000).finally([&]() { - elapsed = timer.elapsed(); - }); - - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QVERIFY(elapsed < 2000); -} - -void tst_qpromise::timeoutReject() -{ - QElapsedTimer timer; - qint64 elapsed = -1; - bool failed = false; - - timer.start(); - - auto p = QPromise([](const QPromiseResolve& resolve) { - QTimer::singleShot(4000, [=]() { - resolve(42); - }); - }).timeout(2000).finally([&]() { - elapsed = timer.elapsed(); - }); - - p.fail([&](const QPromiseTimeoutException&) { - failed = true; - return -1; - }).wait(); - - QCOMPARE(waitForValue(p, -1), -1); - QCOMPARE(p.isRejected(), true); - QCOMPARE(failed, true); - QVERIFY(elapsed >= 2000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to - QVERIFY(elapsed <= 2000 * 1.05); // keep accuracy within 5% of the desired interval. -} - -void tst_qpromise::delayFulfilled() -{ - QElapsedTimer timer; - qint64 elapsed = -1; - - timer.start(); - - auto p = QPromise::resolve(42).delay(1000).finally([&]() { - elapsed = timer.elapsed(); - }); - - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - QVERIFY(elapsed >= 1000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to - QVERIFY(elapsed <= 1000 * 1.05); // keep accuracy within 5% of the desired interval. -} - -void tst_qpromise::delayRejected() -{ - QElapsedTimer timer; - qint64 elapsed = -1; - - timer.start(); - - auto p = QPromise::reject(QString("foo")).delay(1000).finally([&]() { - elapsed = timer.elapsed(); - }); - - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QVERIFY(elapsed < 5); -} diff --git a/tests/auto/qtpromise/qtpromise.pri b/tests/auto/qtpromise/qtpromise.pri index ad49341..b39b4ca 100644 --- a/tests/auto/qtpromise/qtpromise.pri +++ b/tests/auto/qtpromise/qtpromise.pri @@ -15,4 +15,7 @@ coverage { } } +HEADERS += \ + $$PWD/shared/utils.h + include(../../../qtpromise.pri) diff --git a/tests/auto/qtpromise/requirements/tst_requirements.cpp b/tests/auto/qtpromise/requirements/tst_requirements.cpp index 5253865..0e8a5a4 100644 --- a/tests/auto/qtpromise/requirements/tst_requirements.cpp +++ b/tests/auto/qtpromise/requirements/tst_requirements.cpp @@ -5,7 +5,6 @@ #include using namespace QtPromise; -using namespace QtPromisePrivate; // https://promisesaplus.com/#requirements class tst_requirements : public QObject @@ -41,7 +40,7 @@ void tst_requirements::statePending() // 2.1.1.1. may transition to either the fulfilled state { QPromise p([&](const QPromiseResolve& resolve) { - qtpromise_defer([=]() { resolve(42); }); + QtPromisePrivate::qtpromise_defer([=]() { resolve(42); }); }); QVERIFY(p.isPending()); @@ -58,7 +57,7 @@ void tst_requirements::statePending() // 2.1.1.1. ... or the rejected state { QPromise p([&](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=]() { reject(QString("foo")); }); + QtPromisePrivate::qtpromise_defer([=]() { reject(QString("foo")); }); }); QVERIFY(p.isPending()); @@ -82,7 +81,7 @@ void tst_requirements::stateFulfilled() QPromise p([]( const QPromiseResolve& resolve, const QPromiseReject& reject) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { // 2.1.2.2. must have a value, which must not change. resolve(42); resolve(43); @@ -115,7 +114,7 @@ void tst_requirements::stateRejected() QPromise p([]( const QPromiseResolve& resolve, const QPromiseReject& reject) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { // 2.1.3.2. must have a reason, which must not change. reject(QString("foo")); reject(QString("bar")); @@ -196,7 +195,7 @@ void tst_requirements::thenOnFulfilled() // 2.2.2. If onFulfilled is a function: QVector values; QPromise p0([](const QPromiseResolve& resolve) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { // 2.2.2.3. it must not be called more than once resolve(42); resolve(43); @@ -224,7 +223,7 @@ void tst_requirements::thenOnRejected() // 2.2.3. If onRejected is a function: QStringList errors; QPromise p0([](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { // 2.2.3.3. it must not be called more than once. reject(QString("foo")); reject(QString("bar")); @@ -275,7 +274,7 @@ void tst_requirements::thenMultipleCalls() { QVector values; QPromise p([](const QPromiseResolve& resolve) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { resolve(42); }); }); @@ -294,7 +293,7 @@ void tst_requirements::thenMultipleCalls() { QVector values; QPromise p([](const QPromiseResolve&, const QPromiseReject& reject) { - qtpromise_defer([=]() { + QtPromisePrivate::qtpromise_defer([=]() { reject(8); }); }); diff --git a/tests/auto/qtpromise/shared/utils.h b/tests/auto/qtpromise/shared/utils.h new file mode 100644 index 0000000..56efc34 --- /dev/null +++ b/tests/auto/qtpromise/shared/utils.h @@ -0,0 +1,47 @@ +#ifndef QTPROMISE_TESTS_AUTO_SHARED_UTILS_H +#define QTPROMISE_TESTS_AUTO_SHARED_UTILS_H + +#include + +template +static inline T waitForValue(const QtPromise::QPromise& promise, const T& initial) +{ + T value(initial); + promise.then([&](const T& res) { + value = res; + }).wait(); + return value; +} + +template +static inline T waitForValue(const QtPromise::QPromise& promise, const T& initial, const T& expected) +{ + T value(initial); + promise.then([&]() { + value = expected; + }).wait(); + return value; +} + +template +static inline E waitForError(const QtPromise::QPromise& promise, const E& initial) +{ + E error(initial); + promise.fail([&](const E& err) { + error = err; + return T(); + }).wait(); + return error; +} + +template +static inline E waitForError(const QtPromise::QPromise& promise, const E& initial) +{ + E error(initial); + promise.fail([&](const E& err) { + error = err; + }).wait(); + return error; +} + +#endif // QTPROMISE_TESTS_AUTO_SHARED_UTILS_H