Use clang-format for code style consistency

Based on the WebKit preset and following 'most' of the Qt guidelines, except a few rules that work better for promise continuation lambdas. Requires clang-format 11.
This commit is contained in:
Simon Brunel
2020-03-21 14:23:40 +01:00
parent b99e468c84
commit d43657fbd5
40 changed files with 1534 additions and 1223 deletions

View File

@ -11,11 +11,11 @@
#include <QtTest>
#ifdef Q_CC_MSVC
// MSVC calls the copy constructor on std::current_exception AND std::rethrow_exception
// https://stackoverflow.com/a/31820854
#define EXCEPT_CALL_COPY_CTOR 1
// MSVC calls the copy constructor on std::current_exception AND std::rethrow_exception
// https://stackoverflow.com/a/31820854
# define EXCEPT_CALL_COPY_CTOR 1
#else
#define EXCEPT_CALL_COPY_CTOR 0
# define EXCEPT_CALL_COPY_CTOR 0
#endif
using namespace QtPromise;
@ -41,7 +41,7 @@ QTEST_MAIN(tst_benchmark)
void tst_benchmark::valueResolve()
{
{ // should move the value when resolved by rvalue
{ // should move the value when resolved by rvalue
Data::logs().reset();
QPromise<Data>{[&](const QPromiseResolve<Data>& resolve) {
resolve(Data{42});
@ -49,10 +49,10 @@ void tst_benchmark::valueResolve()
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move value to the promise data
QCOMPARE(Data::logs().move, 1); // move value to the promise data
QCOMPARE(Data::logs().refs, 0);
}
{ // should create one copy of the value when resolved by lvalue
{ // should create one copy of the value when resolved by lvalue
Data::logs().reset();
QPromise<Data>{[&](const QPromiseResolve<Data>& resolve) {
Data value{42};
@ -60,7 +60,7 @@ void tst_benchmark::valueResolve()
}}.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 1); // copy value to the promise data
QCOMPARE(Data::logs().copy, 1); // copy value to the promise data
QCOMPARE(Data::logs().move, 0);
QCOMPARE(Data::logs().refs, 0);
}
@ -68,7 +68,7 @@ void tst_benchmark::valueResolve()
void tst_benchmark::valueReject()
{
{ // should not create any data if rejected
{ // should not create any data if rejected
Data::logs().reset();
QPromise<Data>{[&](const QPromiseResolve<Data>&, const QPromiseReject<Data>& reject) {
reject(QString{"foo"});
@ -83,28 +83,34 @@ void tst_benchmark::valueReject()
void tst_benchmark::valueThen()
{
{ // should not copy value on continutation if fulfilled
{ // should not copy value on continutation if fulfilled
int value = -1;
Data::logs().reset();
QPromise<Data>::resolve(Data{42}).then([&](const Data& res) {
value = res.value();
}).wait();
QPromise<Data>::resolve(Data{42})
.then([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move value to the promise data
QCOMPARE(Data::logs().move, 1); // move value to the promise data
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42);
}
{ // should not create value on continutation if rejected
{ // should not create value on continutation if rejected
int value = -1;
QString error;
Data::logs().reset();
QPromise<Data>::reject(QString{"foo"}).then([&](const Data& res) {
value = res.value();
}, [&](const QString& err) {
error = err;
}).wait();
QPromise<Data>::reject(QString{"foo"})
.then(
[&](const Data& res) {
value = res.value();
},
[&](const QString& err) {
error = err;
})
.wait();
QCOMPARE(Data::logs().ctor, 0);
QCOMPARE(Data::logs().copy, 0);
@ -113,27 +119,32 @@ void tst_benchmark::valueThen()
QCOMPARE(error, QString{"foo"});
QCOMPARE(value, -1);
}
{ // should move the returned value when fulfilled
{ // should move the returned value when fulfilled
int value = -1;
Data::logs().reset();
QPromise<int>::resolve(42).then([&](int res) {
return Data{res+2};
}).then([&](const Data& res) {
value = res.value();
}).wait();
QPromise<int>::resolve(42)
.then([&](int res) {
return Data{res + 2};
})
.then([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move values to the next promise data
QCOMPARE(Data::logs().move, 1); // move values to the next promise data
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 44);
}
{ // should not create any data if handler throws
{ // should not create any data if handler throws
Data::logs().reset();
QPromise<int>::resolve(42).then([&](int res) {
throw QString{"foo"};
return Data{res+2};
}).wait();
QPromise<int>::resolve(42)
.then([&](int res) {
throw QString{"foo"};
return Data{res + 2};
})
.wait();
QCOMPARE(Data::logs().ctor, 0);
QCOMPARE(Data::logs().copy, 0);
@ -144,26 +155,31 @@ void tst_benchmark::valueThen()
void tst_benchmark::valueDelayed()
{
{ // should not copy the value on continutation if fulfilled
{ // should not copy the value on continutation if fulfilled
int value = -1;
Data::logs().reset();
QPromise<int>::resolve(42).then([&](int res) {
return QPromise<Data>::resolve(Data{res + 1});
}).then([&](const Data& res) {
value = res.value();
}).wait();
QPromise<int>::resolve(42)
.then([&](int res) {
return QPromise<Data>::resolve(Data{res + 1});
})
.then([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move value to the input promise data
QCOMPARE(Data::logs().move, 1); // move value to the input promise data
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 43);
}
{ // should not create value on continutation if rejected
{ // should not create value on continutation if rejected
Data::logs().reset();
QPromise<int>::resolve(42).then([&]() {
return QPromise<Data>::reject(QString{"foo"});
}).wait();
QPromise<int>::resolve(42)
.then([&]() {
return QPromise<Data>::reject(QString{"foo"});
})
.wait();
QCOMPARE(Data::logs().ctor, 0);
QCOMPARE(Data::logs().copy, 0);
@ -174,25 +190,29 @@ void tst_benchmark::valueDelayed()
void tst_benchmark::valueFinally()
{
{ // should not copy the value on continutation if fulfilled
{ // should not copy the value on continutation if fulfilled
int value = -1;
Data::logs().reset();
QPromise<Data>::resolve(Data{42}).finally([&]() {
value = 42;
}).wait();
QPromise<Data>::resolve(Data{42})
.finally([&]() {
value = 42;
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move value to the input and output promise data
QCOMPARE(Data::logs().move, 1); // move value to the input and output promise data
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42);
}
{ // should not create value on continutation if rejected
{ // should not create value on continutation if rejected
int value = -1;
Data::logs().reset();
QPromise<Data>::reject(QString{"foo"}).finally([&]() {
value = 42;
}).wait();
QPromise<Data>::reject(QString{"foo"})
.finally([&]() {
value = 42;
})
.wait();
QCOMPARE(Data::logs().ctor, 0);
QCOMPARE(Data::logs().copy, 0);
@ -204,25 +224,29 @@ void tst_benchmark::valueFinally()
void tst_benchmark::valueTap()
{
{ // should not copy the value on continutation if fulfilled
{ // should not copy the value on continutation if fulfilled
int value = -1;
Data::logs().reset();
QPromise<Data>::resolve(Data{42}).tap([&](const Data& res) {
value = res.value();
}).wait();
QPromise<Data>::resolve(Data{42})
.tap([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 0);
QCOMPARE(Data::logs().move, 1); // move value to the input and output promise data
QCOMPARE(Data::logs().move, 1); // move value to the input and output promise data
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42);
}
{ // should not create value on continutation if rejected
{ // should not create value on continutation if rejected
int value = -1;
Data::logs().reset();
QPromise<Data>::reject(QString{"foo"}).tap([&](const Data& res) {
value = res.value();
}).wait();
QPromise<Data>::reject(QString{"foo"})
.tap([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 0);
QCOMPARE(Data::logs().copy, 0);
@ -234,18 +258,18 @@ void tst_benchmark::valueTap()
void tst_benchmark::errorReject()
{
{ // should create one copy of the error when rejected by rvalue
{ // should create one copy of the error when rejected by rvalue
Data::logs().reset();
QPromise<int>{[&](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
reject(Data{42});
}}.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value in std::exception_ptr
QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value in std::exception_ptr
QCOMPARE(Data::logs().move, 0);
QCOMPARE(Data::logs().refs, 0);
}
{ // should create one copy of the error when rejected by lvalue (no extra copy)
{ // should create one copy of the error when rejected by lvalue (no extra copy)
Data::logs().reset();
QPromise<int>{[&](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
Data error{42};
@ -253,7 +277,7 @@ void tst_benchmark::errorReject()
}}.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value to the promise data
QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value to the promise data
QCOMPARE(Data::logs().move, 0);
QCOMPARE(Data::logs().refs, 0);
}
@ -261,30 +285,37 @@ void tst_benchmark::errorReject()
void tst_benchmark::errorThen()
{
{ // should not copy error on continutation if rejected
{ // should not copy error on continutation if rejected
int value = -1;
Data::logs().reset();
QPromise<void>::reject(Data{42}).fail([&](const Data& res) {
value = res.value();
}).wait();
QPromise<void>::reject(Data{42})
.fail([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 1 + 2 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr
QCOMPARE(Data::logs().copy,
1 + 2 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr
QCOMPARE(Data::logs().move, 0);
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42);
}
{ // should not copy error on continutation if rethrown
{ // should not copy error on continutation if rethrown
int value = -1;
Data::logs().reset();
QPromise<void>::reject(Data{42}).fail([](const Data&) {
throw;
}).fail([&](const Data& res) {
value = res.value();
}).wait();
QPromise<void>::reject(Data{42})
.fail([](const Data&) {
throw;
})
.fail([&](const Data& res) {
value = res.value();
})
.wait();
QCOMPARE(Data::logs().ctor, 1);
QCOMPARE(Data::logs().copy, 1 + 4 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr
QCOMPARE(Data::logs().copy,
1 + 4 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr
QCOMPARE(Data::logs().move, 0);
QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42);

View File

@ -175,7 +175,7 @@ void tst_deprecations_helpers_qpromise::stdSharedPtr()
void tst_deprecations_helpers_qpromise::typedPromise()
{
auto resolver = [](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve(42);
});
};
@ -202,7 +202,7 @@ void tst_deprecations_helpers_qpromise::typedPromise()
void tst_deprecations_helpers_qpromise::voidPromise()
{
auto resolver = [](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve();
});
};
@ -228,7 +228,9 @@ void tst_deprecations_helpers_qpromise::voidPromise()
void tst_deprecations_helpers_qpromise::typedFuture()
{
auto fn = [](){ return 42; };
auto fn = []() {
return 42;
};
QFuture<int> v0 = QtConcurrent::run(fn);
const QFuture<int> v1 = v0;
@ -250,7 +252,7 @@ void tst_deprecations_helpers_qpromise::typedFuture()
void tst_deprecations_helpers_qpromise::voidFuture()
{
auto fn = [](){ };
auto fn = []() {};
QFuture<void> v0 = QtConcurrent::run(fn);
const QFuture<void> v1 = v0;

View File

@ -33,18 +33,14 @@ QTEST_MAIN(tst_deprecations_helpers_qpromiseall)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
Q_STATIC_ASSERT((std::is_same<typename Sequence::value_type, QPromise<int>>::value));
static void exec()
{
Sequence promises{
QtPromise::resolve(42),
QtPromise::resolve(43),
QtPromise::resolve(44)
};
Sequence promises{QtPromise::resolve(42), QtPromise::resolve(43), QtPromise::resolve(44)};
promises.push_back(QtPromise::resolve(45));
promises.insert(++promises.begin(), QtPromise::resolve(46));
@ -58,16 +54,14 @@ struct SequenceTester
}
};
template <template <typename, typename...> class Sequence, typename ...Args>
template<template<typename, typename...> class Sequence, typename... Args>
struct SequenceTester<Sequence<QPromise<void>, Args...>>
{
static void exec()
{
Sequence<QPromise<void>, Args...> promises{
QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()
};
Sequence<QPromise<void>, Args...> promises{QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()};
promises.push_back(QtPromise::resolve());
promises.insert(++promises.begin(), QtPromise::resolve());
@ -106,7 +100,7 @@ void tst_deprecations_helpers_qpromiseall::allPromisesSucceed()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve(43);
});
}};
@ -127,7 +121,7 @@ void tst_deprecations_helpers_qpromiseall::allPromisesSucceed_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve();
});
}};
@ -148,7 +142,7 @@ void tst_deprecations_helpers_qpromiseall::atLeastOnePromiseReject()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -169,7 +163,7 @@ void tst_deprecations_helpers_qpromiseall::atLeastOnePromiseReject_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -210,7 +204,7 @@ void tst_deprecations_helpers_qpromiseall::preserveOrder()
void tst_deprecations_helpers_qpromiseall::sequenceTypes()
{
SequenceTester<QList<QPromise<int>>>::exec();
//SequenceTester<QVector<QPromise<int>>>::exec();
// SequenceTester<QVector<QPromise<int>>>::exec();
SequenceTester<std::list<QPromise<int>>>::exec();
SequenceTester<std::vector<QPromise<int>>>::exec();
}
@ -218,7 +212,7 @@ void tst_deprecations_helpers_qpromiseall::sequenceTypes()
void tst_deprecations_helpers_qpromiseall::sequenceTypes_void()
{
SequenceTester<QList<QPromise<void>>>::exec();
//SequenceTester<QVector<QPromise<void>>>::exec();
// SequenceTester<QVector<QPromise<void>>>::exec();
SequenceTester<std::list<QPromise<void>>>::exec();
SequenceTester<std::vector<QPromise<void>>>::exec();
}

View File

@ -33,18 +33,14 @@ QTEST_MAIN(tst_deprecations_qpromise_all)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
Q_STATIC_ASSERT((std::is_same<typename Sequence::value_type, QPromise<int>>::value));
static void exec()
{
Sequence promises{
QtPromise::resolve(42),
QtPromise::resolve(43),
QtPromise::resolve(44)
};
Sequence promises{QtPromise::resolve(42), QtPromise::resolve(43), QtPromise::resolve(44)};
promises.push_back(QtPromise::resolve(45));
promises.insert(++promises.begin(), QtPromise::resolve(46));
@ -59,16 +55,14 @@ struct SequenceTester
}
};
template <template <typename, typename...> class Sequence, typename ...Args>
template<template<typename, typename...> class Sequence, typename... Args>
struct SequenceTester<Sequence<QPromise<void>, Args...>>
{
static void exec()
{
Sequence<QPromise<void>, Args...> promises{
QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()
};
Sequence<QPromise<void>, Args...> promises{QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()};
promises.push_back(QtPromise::resolve());
promises.insert(++promises.begin(), QtPromise::resolve());
@ -110,7 +104,7 @@ void tst_deprecations_qpromise_all::allPromisesSucceed()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve(43);
});
}};
@ -132,7 +126,7 @@ void tst_deprecations_qpromise_all::allPromisesSucceed_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve();
});
}};
@ -154,7 +148,7 @@ void tst_deprecations_qpromise_all::atLeastOnePromiseReject()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -176,7 +170,7 @@ void tst_deprecations_qpromise_all::atLeastOnePromiseReject_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -219,7 +213,7 @@ void tst_deprecations_qpromise_all::preserveOrder()
void tst_deprecations_qpromise_all::sequenceTypes()
{
SequenceTester<QList<QPromise<int>>>::exec();
//SequenceTester<QVector<QPromise<int>>>::exec();
// SequenceTester<QVector<QPromise<int>>>::exec();
SequenceTester<std::list<QPromise<int>>>::exec();
SequenceTester<std::vector<QPromise<int>>>::exec();
}
@ -227,7 +221,7 @@ void tst_deprecations_qpromise_all::sequenceTypes()
void tst_deprecations_qpromise_all::sequenceTypes_void()
{
SequenceTester<QList<QPromise<void>>>::exec();
//SequenceTester<QVector<QPromise<void>>>::exec();
// SequenceTester<QVector<QPromise<void>>>::exec();
SequenceTester<std::list<QPromise<void>>>::exec();
SequenceTester<std::vector<QPromise<void>>>::exec();
}

View File

@ -30,10 +30,12 @@ QTEST_MAIN(tst_exceptions)
namespace {
template <class E>
template<class E>
void verify()
{
auto p = QtPromise::resolve(QtConcurrent::run([]() { throw E(); }));
auto p = QtPromise::resolve(QtConcurrent::run([]() {
throw E();
}));
QCOMPARE(p.isPending(), true);
QCOMPARE(waitForRejected<E>(p), true);
QCOMPARE(p.isRejected(), true);

View File

@ -37,9 +37,7 @@ private Q_SLOTS:
class MyException : public QException
{
public:
MyException(const QString& error)
: m_error{error}
{ }
MyException(const QString& error) : m_error{error} { }
const QString& error() const { return m_error; }
@ -64,8 +62,8 @@ void tst_future::fulfilled()
QCOMPARE(p.isPending(), true);
p.then([&](int res) {
result = res;
}).wait();
result = res;
}).wait();
QCOMPARE(p.isFulfilled(), true);
QCOMPARE(result, 42);
@ -74,14 +72,14 @@ void tst_future::fulfilled()
void tst_future::fulfilled_void()
{
int result = -1;
auto p = QtPromise::resolve(QtConcurrent::run([]() { }));
auto p = QtPromise::resolve(QtConcurrent::run([]() {}));
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
QCOMPARE(p.isPending(), true);
p.then([&]() {
result = 42;
}).wait();
result = 42;
}).wait();
QCOMPARE(p.isFulfilled(), true);
QCOMPARE(result, 42);
@ -99,9 +97,9 @@ void tst_future::rejected()
QCOMPARE(p.isPending(), true);
p.fail([&](const MyException& e) {
error = e.error();
return -1;
}).wait();
error = e.error();
return -1;
}).wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"foo"});
@ -119,8 +117,8 @@ void tst_future::rejected_void()
QCOMPARE(p.isPending(), true);
p.fail([&](const MyException& e) {
error = e.error();
}).wait();
error = e.error();
}).wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"foo"});
@ -139,12 +137,14 @@ void tst_future::unhandled()
QCOMPARE(p.isPending(), true);
p.fail([&](const QString& err) {
error += err;
return -1;
}).fail([&](const QUnhandledException&) {
error += "bar";
return -1;
}).wait();
error += err;
return -1;
})
.fail([&](const QUnhandledException&) {
error += "bar";
return -1;
})
.wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"bar"});
@ -161,10 +161,12 @@ void tst_future::unhandled_void()
QCOMPARE(p.isPending(), true);
p.fail([&](const QString& err) {
error += err;
}).fail([&](const QUnhandledException&) {
error += "bar";
}).wait();
error += err;
})
.fail([&](const QUnhandledException&) {
error += "bar";
})
.wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"bar"});
@ -173,14 +175,14 @@ void tst_future::unhandled_void()
void tst_future::canceled()
{
QString error;
auto p = QtPromise::resolve(QFuture<int>()); // Constructs an empty, canceled future.
auto p = QtPromise::resolve(QFuture<int>()); // Constructs an empty, canceled future.
QCOMPARE(p.isPending(), true);
p.fail([&](const QPromiseCanceledException&) {
error = "canceled";
return -1;
}).wait();
error = "canceled";
return -1;
}).wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"canceled"});
@ -189,13 +191,13 @@ void tst_future::canceled()
void tst_future::canceled_void()
{
QString error;
auto p = QtPromise::resolve(QFuture<void>()); // Constructs an empty, canceled future.
auto p = QtPromise::resolve(QFuture<void>()); // Constructs an empty, canceled future.
QCOMPARE(p.isPending(), true);
p.fail([&](const QPromiseCanceledException&) {
error = "canceled";
}).wait();
error = "canceled";
}).wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"canceled"});
@ -211,8 +213,8 @@ void tst_future::canceledFromThread()
QCOMPARE(p.isPending(), true);
p.fail([&](const QPromiseCanceledException&) {
error = "bar";
}).wait();
error = "bar";
}).wait();
QCOMPARE(p.isRejected(), true);
QCOMPARE(error, QString{"bar"});
@ -231,9 +233,11 @@ void tst_future::then()
QCOMPARE(input.isFulfilled(), true);
QCOMPARE(output.isPending(), true);
output.then([&](const QString& res) {
result = res;
}).wait();
output
.then([&](const QString& res) {
result = res;
})
.wait();
QCOMPARE(output.isFulfilled(), true);
QCOMPARE(result, QString{"foo42"});
@ -252,9 +256,11 @@ void tst_future::then_void()
QCOMPARE(input.isFulfilled(), true);
QCOMPARE(output.isPending(), true);
output.then([&]() {
result += "bar";
}).wait();
output
.then([&]() {
result += "bar";
})
.wait();
QCOMPARE(input.isFulfilled(), true);
QCOMPARE(result, QString{"foobar"});
@ -265,17 +271,21 @@ void tst_future::fail()
QString result;
auto input = QPromise<QString>::reject(MyException{"bar"});
auto output = input.fail([](const MyException& e) {
return QtConcurrent::run([](const QString& error) {
return QString{"foo%1"}.arg(error);
}, e.error());
return QtConcurrent::run(
[](const QString& error) {
return QString{"foo%1"}.arg(error);
},
e.error());
});
QCOMPARE(input.isRejected(), true);
QCOMPARE(output.isPending(), true);
output.then([&](const QString& res) {
result = res;
}).wait();
output
.then([&](const QString& res) {
result = res;
})
.wait();
QCOMPARE(output.isFulfilled(), true);
QCOMPARE(result, QString{"foobar"});
@ -286,17 +296,21 @@ void tst_future::fail_void()
QString result;
auto input = QPromise<void>::reject(MyException{"bar"});
auto output = input.fail([&](const MyException& e) {
return QtConcurrent::run([&](const QString& error) {
result = error;
}, e.error());
return QtConcurrent::run(
[&](const QString& error) {
result = error;
},
e.error());
});
QCOMPARE(input.isRejected(), true);
QCOMPARE(output.isPending(), true);
output.then([&]() {
result = result.prepend("foo");
}).wait();
output
.then([&]() {
result = result.prepend("foo");
})
.wait();
QCOMPARE(output.isFulfilled(), true);
QCOMPARE(result, QString{"foobar"});
@ -317,9 +331,11 @@ void tst_future::finally()
QCOMPARE(output.isPending(), true);
int value = -1;
output.then([&](int res) {
value = res;
}).wait();
output
.then([&](int res) {
value = res;
})
.wait();
QCOMPARE(output.isFulfilled(), true);
QCOMPARE(value, 42);
@ -340,10 +356,12 @@ void tst_future::finallyRejected()
QCOMPARE(output.isPending(), true);
QString error;
output.fail([&](const MyException& e) {
error = e.error();
return -1;
}).wait();
output
.fail([&](const MyException& e) {
error = e.error();
return -1;
})
.wait();
QCOMPARE(output.isRejected(), true);
QCOMPARE(error, QString{"foo"});

View File

@ -33,18 +33,14 @@ QTEST_MAIN(tst_helpers_all)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
Q_STATIC_ASSERT((std::is_same<typename Sequence::value_type, QPromise<int>>::value));
static void exec()
{
Sequence promises{
QtPromise::resolve(42),
QtPromise::resolve(43),
QtPromise::resolve(44)
};
Sequence promises{QtPromise::resolve(42), QtPromise::resolve(43), QtPromise::resolve(44)};
promises.push_back(QtPromise::resolve(45));
promises.insert(++promises.begin(), QtPromise::resolve(46));
@ -58,16 +54,14 @@ struct SequenceTester
}
};
template <template <typename, typename...> class Sequence, typename ...Args>
template<template<typename, typename...> class Sequence, typename... Args>
struct SequenceTester<Sequence<QPromise<void>, Args...>>
{
static void exec()
{
Sequence<QPromise<void>, Args...> promises{
QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()
};
Sequence<QPromise<void>, Args...> promises{QtPromise::resolve(),
QtPromise::resolve(),
QtPromise::resolve()};
promises.push_back(QtPromise::resolve());
promises.insert(++promises.begin(), QtPromise::resolve());
@ -106,7 +100,7 @@ void tst_helpers_all::allPromisesSucceed()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve(43);
});
}};
@ -127,7 +121,7 @@ void tst_helpers_all::allPromisesSucceed_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve();
});
}};
@ -148,7 +142,7 @@ void tst_helpers_all::atLeastOnePromiseReject()
auto p0 = QtPromise::resolve(42);
auto p1 = QtPromise::resolve(44);
auto p2 = QPromise<int>{[](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -169,7 +163,7 @@ void tst_helpers_all::atLeastOnePromiseReject_void()
auto p0 = QtPromise::resolve();
auto p1 = QtPromise::resolve();
auto p2 = QPromise<void>{[](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
@ -210,7 +204,7 @@ void tst_helpers_all::preserveOrder()
void tst_helpers_all::sequenceTypes()
{
SequenceTester<QList<QPromise<int>>>::exec();
//SequenceTester<QVector<QPromise<int>>>::exec();
// SequenceTester<QVector<QPromise<int>>>::exec();
SequenceTester<std::list<QPromise<int>>>::exec();
SequenceTester<std::vector<QPromise<int>>>::exec();
}
@ -218,7 +212,7 @@ void tst_helpers_all::sequenceTypes()
void tst_helpers_all::sequenceTypes_void()
{
SequenceTester<QList<QPromise<void>>>::exec();
//SequenceTester<QVector<QPromise<void>>>::exec();
// SequenceTester<QVector<QPromise<void>>>::exec();
SequenceTester<std::list<QPromise<void>>>::exec();
SequenceTester<std::vector<QPromise<void>>>::exec();
}

View File

@ -91,9 +91,12 @@ void tst_helpers_attempt::functorThrows()
void tst_helpers_attempt::callWithParams()
{
auto p = QtPromise::attempt([&](int i, const QString& s) {
return QString{"%1:%2"}.arg(i).arg(s);
}, 42, "foo");
auto p = QtPromise::attempt(
[&](int i, const QString& s) {
return QString{"%1:%2"}.arg(i).arg(s);
},
42,
"foo");
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
QCOMPARE(p.isFulfilled(), true);

View File

@ -32,7 +32,7 @@ QTEST_MAIN(tst_helpers_each)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
@ -92,11 +92,11 @@ void tst_helpers_each::delayedFulfilled()
QMap<int, int> values;
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, int index) {
return QPromise<int>{[&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=, &values]() {
values[v] = index;
resolve(42);
});
}};
QtPromisePrivate::qtpromise_defer([=, &values]() {
values[v] = index;
resolve(42);
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
@ -108,9 +108,8 @@ void tst_helpers_each::delayedFulfilled()
void tst_helpers_each::delayedRejected()
{
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<int>{[&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
return QPromise<int>{
[&](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 43) {
reject(QString{"foo"});

View File

@ -33,7 +33,7 @@ QTEST_MAIN(tst_helpers_filter)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
@ -74,10 +74,10 @@ void tst_helpers_filter::delayedFulfilled()
{
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<bool>{[&](const QPromiseResolve<bool>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v % 2 == 0);
});
}};
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v % 2 == 0);
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
@ -87,9 +87,8 @@ void tst_helpers_filter::delayedFulfilled()
void tst_helpers_filter::delayedRejected()
{
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<bool>{[&](
const QPromiseResolve<bool>& resolve,
const QPromiseReject<bool>& reject) {
return QPromise<bool>{
[&](const QPromiseResolve<bool>& resolve, const QPromiseReject<bool>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 44) {
reject(QString{"foo"});
@ -119,7 +118,7 @@ void tst_helpers_filter::functorThrows()
void tst_helpers_filter::functorArguments()
{
QMap<int, int> args;
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [&](int v, int i) {
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [&](int v, int i) {
args[v] = i;
return i % 2 == 0;
});

View File

@ -33,7 +33,7 @@ QTEST_MAIN(tst_helpers_map)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
@ -83,10 +83,10 @@ void tst_helpers_map::delayedFulfilled()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<int>{[&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
}};
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
@ -96,9 +96,8 @@ void tst_helpers_map::delayedFulfilled()
void tst_helpers_map::delayedRejected()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<int>{[&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
return QPromise<int>{
[&](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 43) {
reject(QString{"foo"});

View File

@ -34,16 +34,14 @@ QTEST_MAIN(tst_helpers_reduce)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
{
Sequence inputs{
QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)
};
Sequence inputs{QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)};
QVector<int> v0;
QVector<int> v1;
@ -51,10 +49,13 @@ struct SequenceTester
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, QtPromise::resolve(2).delay(100));
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
QtPromise::resolve(2).delay(100));
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -74,10 +75,13 @@ void tst_helpers_reduce::emptySequence()
{
bool called = false;
auto p = QtPromise::reduce(QVector<int>{}, [&](...) {
called = true;
return 43;
}, 42);
auto p = QtPromise::reduce(
QVector<int>{},
[&](...) {
called = true;
return 43;
},
42);
// NOTE(SB): reduce() on an empty sequence without an initial value is an error!
@ -97,10 +101,13 @@ void tst_helpers_reduce::regularValues()
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -115,11 +122,9 @@ void tst_helpers_reduce::regularValues()
void tst_helpers_reduce::promiseValues()
{
QVector<QPromise<int>> inputs{
QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)
};
QVector<QPromise<int>> inputs{QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)};
QVector<int> v0;
QVector<int> v1;
@ -127,10 +132,13 @@ void tst_helpers_reduce::promiseValues()
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -147,9 +155,12 @@ void tst_helpers_reduce::convertResultType()
{
QVector<int> inputs{4, 6, 8};
auto p = QtPromise::reduce(inputs, [&](const QString& acc, int cur, int idx) {
return QString{"%1:%2:%3"}.arg(acc).arg(cur).arg(idx);
}, QString{"foo"});
auto p = QtPromise::reduce(
inputs,
[&](const QString& acc, int cur, int idx) {
return QString{"%1:%2:%3"}.arg(acc).arg(cur).arg(idx);
},
QString{"foo"});
// NOTE(SB): when no initial value is given, the result type is the sequence type.
@ -163,10 +174,13 @@ void tst_helpers_reduce::delayedInitialValue()
{
QVector<int> values;
auto p = QtPromise::reduce(QVector<int>{4, 6, 8}, [&](int acc, int cur, int idx) {
values << acc << cur << idx;
return acc + cur + idx;
}, QtPromise::resolve(2).delay(100));
auto p = QtPromise::reduce(
QVector<int>{4, 6, 8},
[&](int acc, int cur, int idx) {
values << acc << cur << idx;
return acc + cur + idx;
},
QtPromise::resolve(2).delay(100));
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
@ -185,10 +199,13 @@ void tst_helpers_reduce::delayedFulfilled()
v0 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
}, 2);
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -214,13 +231,16 @@ void tst_helpers_reduce::delayedRejected()
}
return QtPromise::resolve(acc + cur + idx);
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
return QPromise<int>::reject(QString{"bar"});
}
return QtPromise::resolve(acc + cur + idx);
}, 2);
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
return QPromise<int>::reject(QString{"bar"});
}
return QtPromise::resolve(acc + cur + idx);
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -246,13 +266,16 @@ void tst_helpers_reduce::functorThrows()
}
return acc + cur + idx;
});
auto p1 = QtPromise::reduce(inputs, [&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
throw QString{"bar"};
}
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::reduce(
inputs,
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
throw QString{"bar"};
}
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));

View File

@ -8,8 +8,8 @@
#include "../shared/data.h"
#include "../shared/utils.h"
#include <QtPromise>
#include <QtConcurrent>
#include <QtPromise>
#include <QtTest>
#include <memory>
@ -175,7 +175,7 @@ void tst_helpers_resolve::stdSharedPtr()
void tst_helpers_resolve::typedPromise()
{
auto resolver = [](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve(42);
});
};
@ -202,7 +202,7 @@ void tst_helpers_resolve::typedPromise()
void tst_helpers_resolve::voidPromise()
{
auto resolver = [](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=](){
QtPromisePrivate::qtpromise_defer([=]() {
resolve();
});
};
@ -228,7 +228,9 @@ void tst_helpers_resolve::voidPromise()
void tst_helpers_resolve::typedFuture()
{
auto fn = [](){ return 42; };
auto fn = []() {
return 42;
};
QFuture<int> v0 = QtConcurrent::run(fn);
const QFuture<int> v1 = v0;
@ -250,7 +252,7 @@ void tst_helpers_resolve::typedFuture()
void tst_helpers_resolve::voidFuture()
{
auto fn = [](){ };
auto fn = []() {};
QFuture<void> v0 = QtConcurrent::run(fn);
const QFuture<void> v1 = v0;

View File

@ -27,43 +27,88 @@ private Q_SLOTS:
QTEST_MAIN(tst_internals_argsof)
#include "tst_argsof.moc"
#define TEST_ARGS_FOR_TYPE(T, E) \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const volatile T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const volatile T&>::first, E>::value)); \
#define TEST_ARGS_FOR_TYPE(T, E) \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<volatile T&&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const volatile T>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const volatile T&>::first, E>::value)); \
Q_STATIC_ASSERT((std::is_same<typename ArgsOf<const volatile T&&>::first, E>::value));
namespace {
const float kRes = 0.42f;
float fnNoArg() { return kRes; }
float fnOneArg(float v) { return v; }
float fnManyArgs(const float& v0, int, char*) { return v0; }
float fnNoArg()
{
return kRes;
}
float fnOneArg(float v)
{
return v;
}
float fnManyArgs(const float& v0, int, char*)
{
return v0;
}
struct OpNoArg { float operator()() { return kRes; } };
struct OpOneArg { float operator()(float v) { return v; } };
struct OpManyArgs { float operator()(const float& v, int, char*) { return v; } };
struct OpNoArg
{
float operator()() { return kRes; }
};
struct OpOneArg
{
float operator()(float v) { return v; }
};
struct OpManyArgs
{
float operator()(const float& v, int, char*) { return v; }
};
struct OpCNoArg { float operator()() const { return kRes; } };
struct OpCOneArg { float operator()(float v) const { return v; } };
struct OpCManyArgs { float operator()(const float& v, int, char*) const { return v; } };
struct OpCNoArg
{
float operator()() const { return kRes; }
};
struct OpCOneArg
{
float operator()(float v) const { return v; }
};
struct OpCManyArgs
{
float operator()(const float& v, int, char*) const { return v; }
};
struct OpVNoArg { float operator()() volatile { return kRes; } };
struct OpVOneArg { float operator()(float v) volatile { return v; } };
struct OpVManyArgs { float operator()(const float& v, int, char*) volatile { return v; } };
struct OpVNoArg
{
float operator()() volatile { return kRes; }
};
struct OpVOneArg
{
float operator()(float v) volatile { return v; }
};
struct OpVManyArgs
{
float operator()(const float& v, int, char*) volatile { return v; }
};
struct OpCVNoArg { float operator()() const volatile { return kRes; } };
struct OpCVOneArg { float operator()(float v) const volatile { return v; } };
struct OpCVManyArgs { float operator()(const float& v, int, char*) const volatile { return v; } };
struct OpCVNoArg
{
float operator()() const volatile { return kRes; }
};
struct OpCVOneArg
{
float operator()(float v) const volatile { return v; }
};
struct OpCVManyArgs
{
float operator()(const float& v, int, char*) const volatile { return v; }
};
} // namespace

View File

@ -270,23 +270,23 @@ void tst_qpromise_construct::connectAndResolve()
std::weak_ptr<int> wptr;
{
auto p = QPromise<std::shared_ptr<int>>{[&](
const QPromiseResolve<std::shared_ptr<int>>& resolve,
const QPromiseReject<std::shared_ptr<int>>& reject) {
auto p =
QPromise<std::shared_ptr<int>>{[&](const QPromiseResolve<std::shared_ptr<int>>& resolve,
const QPromiseReject<std::shared_ptr<int>>& reject) {
connect(object.data(),
&QObject::objectNameChanged,
[=, &wptr](const QString& name) {
auto sptr = std::make_shared<int>(42);
connect(object.data(), &QObject::objectNameChanged,
[=, &wptr](const QString& name) {
auto sptr = std::make_shared<int>(42);
wptr = sptr;
wptr = sptr;
if (name == "foobar") {
resolve(sptr);
} else {
reject(42);
}
});
}};
if (name == "foobar") {
resolve(sptr);
} else {
reject(42);
}
});
}};
QCOMPARE(p.isPending(), true);
@ -307,22 +307,19 @@ void tst_qpromise_construct::connectAndReject()
std::weak_ptr<int> wptr;
{
auto p = QPromise<int>{[&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
auto p = QPromise<int>{[&](const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
connect(object.data(), &QObject::objectNameChanged, [=, &wptr](const QString& name) {
auto sptr = std::make_shared<int>(42);
connect(object.data(), &QObject::objectNameChanged,
[=, &wptr](const QString& name) {
auto sptr = std::make_shared<int>(42);
wptr = sptr;
wptr = sptr;
if (name == "foobar") {
reject(sptr);
} else {
resolve(42);
}
});
if (name == "foobar") {
reject(sptr);
} else {
resolve(42);
}
});
}};
QCOMPARE(p.isPending(), true);

View File

@ -32,36 +32,34 @@ QTEST_MAIN(tst_qpromise_each)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
{
QVector<int> values;
auto p = QtPromise::resolve(Sequence{42, 43, 44}).each([&](int v, int i) {
values << i << v;
}).each([&](int v, ...) {
values << v;
return QString{"foo"};
}).each([&](int v, ...) {
values << v + 1;
return QtPromise::resolve(QString{"foo"}).then([&](){
values << -1;
});
}).each([&](int v, ...) {
values << v + 2;
});
auto p = QtPromise::resolve(Sequence{42, 43, 44})
.each([&](int v, int i) {
values << i << v;
})
.each([&](int v, ...) {
values << v;
return QString{"foo"};
})
.each([&](int v, ...) {
values << v + 1;
return QtPromise::resolve(QString{"foo"}).then([&]() {
values << -1;
});
})
.each([&](int v, ...) {
values << v + 2;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
QCOMPARE(waitForValue(p, Sequence{}), (Sequence{42, 43, 44}));
QVector<int> expected{
0, 42, 1, 43, 2, 44,
42, 43, 44,
43, 44, 45,
-1, -1, -1,
44, 45, 46
};
QVector<int> expected{0, 42, 1, 43, 2, 44, 42, 43, 44, 43, 44, 45, -1, -1, -1, 44, 45, 46};
QCOMPARE(values, expected);
}
};
@ -124,9 +122,8 @@ void tst_qpromise_each::delayedFulfilled()
void tst_qpromise_each::delayedRejected()
{
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([](int v, ...) {
return QPromise<int>{[&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
return QPromise<int>{
[&](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 44) {
reject(QString{"foo"});

View File

@ -36,18 +36,28 @@ const QString kErr{"0.42"};
const float kRes = 0.42f;
const float kFail = -1.f;
float fnNoArg() { return kErr.toFloat(); }
float fnArgByVal(QString e) { return e.toFloat(); }
float fnArgByRef(const QString& e) { return e.toFloat(); }
float fnNoArg()
{
return kErr.toFloat();
}
float fnArgByVal(QString e)
{
return e.toFloat();
}
float fnArgByRef(const QString& e)
{
return e.toFloat();
}
class Klass {
class Klass
{
public: // STATICS
static float kFnNoArg() { return kErr.toFloat(); }
static float kFnArgByVal(QString e) { return e.toFloat(); }
static float kFnArgByRef(const QString& e) { return e.toFloat(); }
public:
Klass(float v) : m_v{v} {}
Klass(float v) : m_v{v} { }
float fnNoArg() const { return m_v; }
float fnArgByVal(QString v) const { return v.toFloat() + m_v; }
@ -66,15 +76,18 @@ void tst_qpromise_fail::sameType()
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();
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"});
}
@ -86,15 +99,18 @@ void tst_qpromise_fail::baseClass()
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();
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"});
}
@ -105,22 +121,25 @@ void tst_qpromise_fail::catchAll()
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();
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_fail::functionPtrHandlers()
{
{ // Global functions.
{ // Global functions.
auto p0 = QPromise<float>::reject(kErr).fail(&fnNoArg);
auto p1 = QPromise<float>::reject(kErr).fail(&fnArgByVal);
auto p2 = QPromise<float>::reject(kErr).fail(&fnArgByRef);
@ -129,7 +148,7 @@ void tst_qpromise_fail::functionPtrHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // Static member functions.
{ // Static member functions.
auto p0 = QPromise<float>::reject(kErr).fail(&Klass::kFnNoArg);
auto p1 = QPromise<float>::reject(kErr).fail(&Klass::kFnArgByVal);
auto p2 = QPromise<float>::reject(kErr).fail(&Klass::kFnArgByRef);
@ -143,7 +162,7 @@ void tst_qpromise_fail::functionPtrHandlers()
// https://github.com/simonbrunel/qtpromise/issues/29
void tst_qpromise_fail::stdFunctionHandlers()
{
{ // lvalue.
{ // lvalue.
std::function<float()> stdFnNoArg = fnNoArg;
std::function<float(QString)> stdFnArgByVal = fnArgByVal;
std::function<float(const QString&)> stdFnArgByRef = fnArgByRef;
@ -156,7 +175,7 @@ void tst_qpromise_fail::stdFunctionHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // const lvalue.
{ // const lvalue.
const std::function<float()> stdFnNoArg = fnNoArg;
const std::function<float(QString)> stdFnArgByVal = fnArgByVal;
const std::function<float(const QString&)> stdFnArgByRef = fnArgByRef;
@ -169,10 +188,11 @@ void tst_qpromise_fail::stdFunctionHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // rvalue.
{ // rvalue.
auto p0 = QPromise<float>::reject(kErr).fail(std::function<float()>{fnNoArg});
auto p1 = QPromise<float>::reject(kErr).fail(std::function<float(QString)>{fnArgByVal});
auto p2 = QPromise<float>::reject(kErr).fail(std::function<float(const QString&)>{fnArgByRef});
auto p2 =
QPromise<float>::reject(kErr).fail(std::function<float(const QString&)>{fnArgByRef});
QCOMPARE(waitForValue(p0, kFail), kRes);
QCOMPARE(waitForValue(p1, kFail), kRes);
@ -190,7 +210,8 @@ void tst_qpromise_fail::stdBindHandlers()
const std::function<float()> bindNoArg = std::bind(&Klass::fnNoArg, &obj);
const std::function<float(QString)> bindArgByVal = std::bind(&Klass::fnArgByVal, &obj, _1);
const std::function<float(const QString&)> bindArgByRef = std::bind(&Klass::fnArgByRef, &obj, _1);
const std::function<float(const QString&)> bindArgByRef =
std::bind(&Klass::fnArgByRef, &obj, _1);
auto p0 = QPromise<float>::reject(kErr).fail(bindNoArg);
auto p1 = QPromise<float>::reject(kErr).fail(bindArgByVal);
@ -203,10 +224,16 @@ void tst_qpromise_fail::stdBindHandlers()
void tst_qpromise_fail::lambdaHandlers()
{
{ // lvalue.
auto lambdaNoArg = []() { return kRes; };
auto lambdaArgByVal = [](QString v) { return v.toFloat(); };
auto lambdaArgByRef = [](const QString& v) { return v.toFloat(); };
{ // lvalue.
auto lambdaNoArg = []() {
return kRes;
};
auto lambdaArgByVal = [](QString v) {
return v.toFloat();
};
auto lambdaArgByRef = [](const QString& v) {
return v.toFloat();
};
auto p0 = QPromise<float>::reject(kErr).fail(lambdaNoArg);
auto p1 = QPromise<float>::reject(kErr).fail(lambdaArgByVal);
@ -216,10 +243,16 @@ void tst_qpromise_fail::lambdaHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // const lvalue.
const auto lambdaNoArg = []() { return kRes; };
const auto lambdaArgByVal = [](QString v) { return v.toFloat(); };
const auto lambdaArgByRef = [](const QString& v) { return v.toFloat(); };
{ // const lvalue.
const auto lambdaNoArg = []() {
return kRes;
};
const auto lambdaArgByVal = [](QString v) {
return v.toFloat();
};
const auto lambdaArgByRef = [](const QString& v) {
return v.toFloat();
};
auto p0 = QPromise<float>::reject(kErr).fail(lambdaNoArg);
auto p1 = QPromise<float>::reject(kErr).fail(lambdaArgByVal);
@ -229,10 +262,16 @@ void tst_qpromise_fail::lambdaHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // rvalue.
auto p0 = QPromise<float>::reject(kErr).fail([]() { return kRes; });
auto p1 = QPromise<float>::reject(kErr).fail([](QString v) { return v.toFloat(); });
auto p2 = QPromise<float>::reject(kErr).fail([](const QString& v) { return v.toFloat(); });
{ // rvalue.
auto p0 = QPromise<float>::reject(kErr).fail([]() {
return kRes;
});
auto p1 = QPromise<float>::reject(kErr).fail([](QString v) {
return v.toFloat();
});
auto p2 = QPromise<float>::reject(kErr).fail([](const QString& v) {
return v.toFloat();
});
QCOMPARE(waitForValue(p0, kFail), kRes);
QCOMPARE(waitForValue(p1, kFail), kRes);

View File

@ -33,20 +33,21 @@ QTEST_MAIN(tst_qpromise_filter)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
{
auto p = QtPromise::resolve(Sequence{
42, 43, 44, 45, 46, 47, 48, 49, 50, 51
}).filter([](int v, ...) {
return v > 42 && v < 51;
}).filter([](int, int i) {
return QPromise<bool>::resolve(i % 2 == 0);
}).filter([](int v, ...) {
return v != 45;
});
auto p = QtPromise::resolve(Sequence{42, 43, 44, 45, 46, 47, 48, 49, 50, 51})
.filter([](int v, ...) {
return v > 42 && v < 51;
})
.filter([](int, int i) {
return QPromise<bool>::resolve(i % 2 == 0);
})
.filter([](int v, ...) {
return v != 45;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
QCOMPARE(waitForValue(p, Sequence{}), (Sequence{43, 47, 49}));
@ -79,10 +80,10 @@ void tst_qpromise_filter::delayedFulfilled()
{
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
return QPromise<bool>{[&](const QPromiseResolve<bool>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v % 2 == 0);
});
}};
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v % 2 == 0);
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
@ -92,9 +93,8 @@ void tst_qpromise_filter::delayedFulfilled()
void tst_qpromise_filter::delayedRejected()
{
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
return QPromise<bool>{[&](
const QPromiseResolve<bool>& resolve,
const QPromiseReject<bool>& reject) {
return QPromise<bool>{
[&](const QPromiseResolve<bool>& resolve, const QPromiseReject<bool>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 43) {
reject(QString{"foo"});

View File

@ -184,8 +184,8 @@ void tst_qpromise_finally::rejectedAsyncResolve()
});
p.then([&](int r) {
values << r;
}).wait();
values << r;
}).wait();
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
QCOMPARE(p.isRejected(), true);

View File

@ -33,23 +33,28 @@ QTEST_MAIN(tst_qpromise_map)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
{
auto p = QtPromise::resolve(Sequence{42, 43, 44}).map([](int v, ...) {
return QString::number(v + 1);
}).map([](const QString& v, int i) {
return QtPromise::resolve(QString{"%1:%2"}.arg(i).arg(v));
}).map([](const QString& v, ...) {
return QtPromise::resolve((v + "!").toUtf8());
}).map([](const QByteArray& v, ...) {
return QString::fromUtf8(v);
});
auto p = QtPromise::resolve(Sequence{42, 43, 44})
.map([](int v, ...) {
return QString::number(v + 1);
})
.map([](const QString& v, int i) {
return QtPromise::resolve(QString{"%1:%2"}.arg(i).arg(v));
})
.map([](const QString& v, ...) {
return QtPromise::resolve((v + "!").toUtf8());
})
.map([](const QByteArray& v, ...) {
return QString::fromUtf8(v);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
QCOMPARE(waitForValue(p, QVector<QString>{}), (QVector<QString>{"0:43!", "1:44!", "2:45!"}));
QCOMPARE(waitForValue(p, QVector<QString>{}),
(QVector<QString>{"0:43!", "1:44!", "2:45!"}));
}
};
@ -89,10 +94,10 @@ void tst_qpromise_map::delayedFulfilled()
{
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
return QPromise<int>{[&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
}};
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
@ -102,9 +107,8 @@ void tst_qpromise_map::delayedFulfilled()
void tst_qpromise_map::delayedRejected()
{
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
return QPromise<int>{[&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
return QPromise<int>{
[&](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
if (v == 43) {
reject(QString{"foo"});

View File

@ -204,7 +204,7 @@ void tst_qpromise_operators::notEqualTo_void()
void tst_qpromise_operators::chaining()
{
auto p = QPromise<int>::resolve(1);
for (int i=0; i<4; ++i) {
for (int i = 0; i < 4; ++i) {
p = p.then([](int res) {
return QPromise<int>::resolve(res * 2);
});
@ -220,7 +220,7 @@ void tst_qpromise_operators::chaining_void()
auto p = QPromise<void>::resolve();
for (int i=0; i<4; ++i) {
for (int i = 0; i < 4; ++i) {
p = p.then([i, &values]() {
values.append(i * 2);
return QPromise<void>::resolve();

View File

@ -34,16 +34,14 @@ QTEST_MAIN(tst_qpromise_reduce)
namespace {
template <class Sequence>
template<class Sequence>
struct SequenceTester
{
static void exec()
{
Sequence inputs{
QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)
};
Sequence inputs{QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)};
QVector<int> v0;
QVector<int> v1;
@ -51,10 +49,12 @@ struct SequenceTester
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, QtPromise::resolve(2).delay(100));
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
QtPromise::resolve(2).delay(100));
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -74,10 +74,13 @@ void tst_qpromise_reduce::emptySequence()
{
bool called = false;
auto p = QtPromise::resolve(QVector<int>{}).reduce([&](...) {
called = true;
return 43;
}, 42);
auto p = QtPromise::resolve(QVector<int>{})
.reduce(
[&](...) {
called = true;
return 43;
},
42);
// NOTE(SB): reduce() on an empty sequence without an initial value is an error!
@ -97,10 +100,12 @@ void tst_qpromise_reduce::regularValues()
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -115,11 +120,9 @@ void tst_qpromise_reduce::regularValues()
void tst_qpromise_reduce::promiseValues()
{
QVector<QPromise<int>> inputs{
QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)
};
QVector<QPromise<int>> inputs{QtPromise::resolve(4).delay(400),
QtPromise::resolve(6).delay(300),
QtPromise::resolve(8).delay(200)};
QVector<int> v0;
QVector<int> v1;
@ -127,10 +130,12 @@ void tst_qpromise_reduce::promiseValues()
v0 << acc << cur << idx;
return acc + cur + idx;
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -147,9 +152,11 @@ void tst_qpromise_reduce::convertResultType()
{
QVector<int> inputs{4, 6, 8};
auto p = QtPromise::resolve(inputs).reduce([&](const QString& acc, int cur, int idx) {
return QString{"%1:%2:%3"}.arg(acc).arg(cur).arg(idx);
}, QString{"foo"});
auto p = QtPromise::resolve(inputs).reduce(
[&](const QString& acc, int cur, int idx) {
return QString{"%1:%2:%3"}.arg(acc).arg(cur).arg(idx);
},
QString{"foo"});
// NOTE(SB): when no initial value is given, the result type is the sequence type.
@ -163,10 +170,13 @@ void tst_qpromise_reduce::delayedInitialValue()
{
QVector<int> values;
auto p = QtPromise::resolve(QVector<int>{4, 6, 8}).reduce([&](int acc, int cur, int idx) {
values << acc << cur << idx;
return acc + cur + idx;
}, QtPromise::resolve(2).delay(100));
auto p = QtPromise::resolve(QVector<int>{4, 6, 8})
.reduce(
[&](int acc, int cur, int idx) {
values << acc << cur << idx;
return acc + cur + idx;
},
QtPromise::resolve(2).delay(100));
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
@ -185,10 +195,12 @@ void tst_qpromise_reduce::delayedFulfilled()
v0 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
}, 2);
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
return QtPromise::resolve(acc + cur + idx).delay(100);
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -214,13 +226,15 @@ void tst_qpromise_reduce::delayedRejected()
}
return QtPromise::resolve(acc + cur + idx);
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
return QPromise<int>::reject(QString{"bar"});
}
return QtPromise::resolve(acc + cur + idx);
}, 2);
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
return QPromise<int>::reject(QString{"bar"});
}
return QtPromise::resolve(acc + cur + idx);
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
@ -246,13 +260,15 @@ void tst_qpromise_reduce::functorThrows()
}
return acc + cur + idx;
});
auto p1 = QtPromise::resolve(inputs).reduce([&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
throw QString{"bar"};
}
return acc + cur + idx;
}, 2);
auto p1 = QtPromise::resolve(inputs).reduce(
[&](int acc, int cur, int idx) {
v1 << acc << cur << idx;
if (cur == 6) {
throw QString{"bar"};
}
return acc + cur + idx;
},
2);
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));

View File

@ -92,8 +92,8 @@ void tst_qpromise_tap::fulfilledAsyncResolve()
});
p.then([&](int r) {
values << r;
}).wait();
values << r;
}).wait();
QCOMPARE(p.isFulfilled(), true);
QCOMPARE(values, (QVector<int>{2, 3, 1}));
@ -115,8 +115,8 @@ void tst_qpromise_tap::fulfilledAsyncReject()
});
p.then([&](int r) {
values << r;
}).wait();
values << r;
}).wait();
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
QCOMPARE(p.isRejected(), true);

View File

@ -58,16 +58,14 @@ void tst_qpromise_tapfail::rejected()
{
QStringList errors;
auto p0 = QPromise<int>::reject(QString{"foo"})
.tapFail([&](const QString& err) {
errors << "1:" + err;
});
auto p0 = QPromise<int>::reject(QString{"foo"}).tapFail([&](const QString& err) {
errors << "1:" + err;
});
auto p1 = p0
.fail([&](const QString& err) {
errors << "2:" + err;
return 43;
});
auto p1 = p0.fail([&](const QString& err) {
errors << "2:" + err;
return 43;
});
QCOMPARE(waitForError(p0, QString{}), QString{"foo"});
QCOMPARE(waitForValue(p1, -1), 43);
@ -80,15 +78,13 @@ void tst_qpromise_tapfail::rejected_void()
{
QStringList errors;
auto p0 = QPromise<void>::reject(QString{"foo"})
.tapFail([&](const QString& err) {
errors << "1:" + err;
});
auto p0 = QPromise<void>::reject(QString{"foo"}).tapFail([&](const QString& err) {
errors << "1:" + err;
});
auto p1 = p0
.fail([&](const QString& err) {
errors << "2:" + err;
});
auto p1 = p0.fail([&](const QString& err) {
errors << "2:" + err;
});
QCOMPARE(waitForError(p0, QString{}), QString{"foo"});
QCOMPARE(waitForValue(p1, -1, 43), 43);
@ -99,10 +95,9 @@ void tst_qpromise_tapfail::rejected_void()
void tst_qpromise_tapfail::throws()
{
auto p = QPromise<int>::reject(QString{"foo"})
.tapFail([&]() {
throw QString{"bar"};
});
auto p = QPromise<int>::reject(QString{"foo"}).tapFail([&]() {
throw QString{"bar"};
});
QCOMPARE(waitForError(p, QString{}), QString{"bar"});
QCOMPARE(p.isRejected(), true);
@ -110,10 +105,9 @@ void tst_qpromise_tapfail::throws()
void tst_qpromise_tapfail::throws_void()
{
auto p = QPromise<void>::reject(QString{"foo"})
.tapFail([&]() {
throw QString{"bar"};
});
auto p = QPromise<void>::reject(QString{"foo"}).tapFail([&]() {
throw QString{"bar"};
});
QCOMPARE(waitForError(p, QString{}), QString{"bar"});
QCOMPARE(p.isRejected(), true);
@ -122,18 +116,17 @@ void tst_qpromise_tapfail::throws_void()
void tst_qpromise_tapfail::delayedResolved()
{
QVector<int> values;
auto p = QPromise<int>::reject(QString{"foo"})
.tapFail([&]() {
QPromise<void> p{[&](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=, &values]() {
values << 3;
resolve(); // ignored!
});
}};
auto p = QPromise<int>::reject(QString{"foo"}).tapFail([&]() {
QPromise<void> p{[&](const QPromiseResolve<void>& resolve) {
QtPromisePrivate::qtpromise_defer([=, &values]() {
values << 3;
resolve(); // ignored!
});
}};
values << 2;
return p;
});
values << 2;
return p;
});
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
QCOMPARE(values, (QVector<int>{2, 3}));
@ -142,20 +135,17 @@ void tst_qpromise_tapfail::delayedResolved()
void tst_qpromise_tapfail::delayedRejected()
{
QVector<int> values;
auto p = QPromise<int>::reject(QString{"foo"})
.tapFail([&]() {
QPromise<void> p{[&](
const QPromiseResolve<void>&,
const QPromiseReject<void>& reject){
QtPromisePrivate::qtpromise_defer([=, &values]() {
values << 3;
reject(QString{"bar"});
});
}};
auto p = QPromise<int>::reject(QString{"foo"}).tapFail([&]() {
QPromise<void> p{[&](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=, &values]() {
values << 3;
reject(QString{"bar"});
});
}};
values << 2;
return p;
});
values << 2;
return p;
});
QCOMPARE(waitForError(p, QString{}), QString{"bar"});
QCOMPARE(values, (QVector<int>{2, 3}));

View File

@ -39,18 +39,28 @@ namespace {
const float kRes = 0.42f;
const float kFail = -1.f;
float fnNoArg() { return kRes; }
float fnArgByVal(float v) { return v; }
float fnArgByRef(const float& v) { return v; }
float fnNoArg()
{
return kRes;
}
float fnArgByVal(float v)
{
return v;
}
float fnArgByRef(const float& v)
{
return v;
}
class Klass {
class Klass
{
public: // STATICS
static float kFnNoArg() { return kRes; }
static float kFnArgByVal(float v) { return v; }
static float kFnArgByRef(const float& v) { return v; }
public:
Klass(float v) : m_v{v} {}
Klass(float v) : m_v{v} { }
float fnNoArg() const { return m_v; }
float fnArgByVal(float v) const { return v + m_v; }
@ -69,14 +79,17 @@ void tst_qpromise_then::resolveSync()
auto input = QPromise<int>::resolve(42);
auto output = input.then([&](int res) {
values << res;
return QString::number(res+1);
return QString::number(res + 1);
});
output.then([&](const QString& res) {
values << res;
}).then([&]() {
values << 44;
}).wait();
output
.then([&](const QString& res) {
values << res;
})
.then([&]() {
values << 44;
})
.wait();
QCOMPARE(values, (QVariantList{42, QString{"43"}, 44}));
QCOMPARE(input.isFulfilled(), true);
@ -107,11 +120,14 @@ void tst_qpromise_then::rejectSync()
});
QString error;
output.then([&](int res) {
error += "bar" + QString::number(res);
}).fail([&](const QString& err) {
error += err;
}).wait();
output
.then([&](int res) {
error += "bar" + QString::number(res);
})
.fail([&](const QString& err) {
error += err;
})
.wait();
QCOMPARE(error, QString{"foo42"});
QCOMPARE(input.isFulfilled(), true);
@ -121,11 +137,12 @@ void tst_qpromise_then::rejectSync()
void tst_qpromise_then::rejectAsync()
{
auto p = QPromise<int>::resolve(42).then([](int res) {
return QPromise<void>{[=](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo%1"}.arg(res));
});
}};
return QPromise<void>{
[=](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo%1"}.arg(res));
});
}};
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
@ -139,8 +156,8 @@ void tst_qpromise_then::skipResult()
int value = -1;
p.then([&]() {
value = 43;
}).wait();
value = 43;
}).wait();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
QCOMPARE(value, 43);
@ -148,13 +165,13 @@ void tst_qpromise_then::skipResult()
void tst_qpromise_then::nullHandler()
{
{ // resolved
{ // resolved
auto p = QPromise<int>::resolve(42).then(nullptr);
QCOMPARE(waitForValue(p, -1), 42);
QCOMPARE(p.isFulfilled(), true);
}
{ // rejected
{ // rejected
auto p = QPromise<int>::reject(QString{"foo"}).then(nullptr);
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
@ -164,7 +181,7 @@ void tst_qpromise_then::nullHandler()
void tst_qpromise_then::functionPtrHandlers()
{
{ // Global functions.
{ // Global functions.
auto p0 = QtPromise::resolve().then(&fnNoArg);
auto p1 = QtPromise::resolve(kRes).then(&fnArgByVal);
auto p2 = QtPromise::resolve(kRes).then(&fnArgByRef);
@ -173,7 +190,7 @@ void tst_qpromise_then::functionPtrHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // Static member functions.
{ // Static member functions.
auto p0 = QtPromise::resolve().then(&Klass::kFnNoArg);
auto p1 = QtPromise::resolve(kRes).then(&Klass::kFnArgByVal);
auto p2 = QtPromise::resolve(kRes).then(&Klass::kFnArgByRef);
@ -187,7 +204,7 @@ void tst_qpromise_then::functionPtrHandlers()
// https://github.com/simonbrunel/qtpromise/issues/29
void tst_qpromise_then::stdFunctionHandlers()
{
{ // lvalue.
{ // lvalue.
std::function<float()> stdFnNoArg = fnNoArg;
std::function<float(float)> stdFnArgByVal = fnArgByVal;
std::function<float(const float&)> stdFnArgByRef = fnArgByRef;
@ -200,7 +217,7 @@ void tst_qpromise_then::stdFunctionHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // const lvalue.
{ // const lvalue.
const std::function<float()> stdFnNoArg = fnNoArg;
const std::function<float(float)> stdFnArgByVal = fnArgByVal;
const std::function<float(const float&)> stdFnArgByRef = fnArgByRef;
@ -213,7 +230,7 @@ void tst_qpromise_then::stdFunctionHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // rvalue.
{ // rvalue.
auto p0 = QtPromise::resolve().then(std::function<float()>{fnNoArg});
auto p1 = QtPromise::resolve(kRes).then(std::function<float(float)>{fnArgByVal});
auto p2 = QtPromise::resolve(kRes).then(std::function<float(const float&)>{fnArgByRef});
@ -247,10 +264,16 @@ void tst_qpromise_then::stdBindHandlers()
void tst_qpromise_then::lambdaHandlers()
{
{ // lvalue.
auto lambdaNoArg = []() { return kRes; };
auto lambdaArgByVal = [](float v) { return v; };
auto lambdaArgByRef = [](const float& v) { return v; };
{ // lvalue.
auto lambdaNoArg = []() {
return kRes;
};
auto lambdaArgByVal = [](float v) {
return v;
};
auto lambdaArgByRef = [](const float& v) {
return v;
};
auto p0 = QtPromise::resolve().then(lambdaNoArg);
auto p1 = QtPromise::resolve(kRes).then(lambdaArgByVal);
@ -260,10 +283,16 @@ void tst_qpromise_then::lambdaHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // const lvalue.
const auto lambdaNoArg = []() { return kRes; };
const auto lambdaArgByVal = [](float v) { return v; };
const auto lambdaArgByRef = [](const float& v) { return v; };
{ // const lvalue.
const auto lambdaNoArg = []() {
return kRes;
};
const auto lambdaArgByVal = [](float v) {
return v;
};
const auto lambdaArgByRef = [](const float& v) {
return v;
};
auto p0 = QtPromise::resolve().then(lambdaNoArg);
auto p1 = QtPromise::resolve(kRes).then(lambdaArgByVal);
@ -273,10 +302,16 @@ void tst_qpromise_then::lambdaHandlers()
QCOMPARE(waitForValue(p1, kFail), kRes);
QCOMPARE(waitForValue(p2, kFail), kRes);
}
{ // rvalue.
auto p0 = QtPromise::resolve().then([]() { return kRes; });
auto p1 = QtPromise::resolve(kRes).then([](float v) { return v; });
auto p2 = QtPromise::resolve(kRes).then([](const float& v) { return v; });
{ // rvalue.
auto p0 = QtPromise::resolve().then([]() {
return kRes;
});
auto p1 = QtPromise::resolve(kRes).then([](float v) {
return v;
});
auto p2 = QtPromise::resolve(kRes).then([](const float& v) {
return v;
});
QCOMPARE(waitForValue(p0, kFail), kRes);
QCOMPARE(waitForValue(p1, kFail), kRes);

View File

@ -39,12 +39,13 @@ void tst_qpromise_timeout::fulfilled()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(1000, [=]() {
resolve(42);
});
}}.timeout(2000).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(1000, [=]() {
resolve(42);
});
}}.timeout(2000)
.finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForValue(p, -1), 42);
QCOMPARE(p.isFulfilled(), true);
@ -59,13 +60,13 @@ void tst_qpromise_timeout::rejected()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QTimer::singleShot(1000, [=]() {
reject(QString{"foo"});
});
}}.timeout(2000).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(1000, [=]() {
reject(QString{"foo"});
});
}}.timeout(2000)
.finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
QCOMPARE(p.isRejected(), true);
@ -81,17 +82,18 @@ void tst_qpromise_timeout::timeout()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(4000, [=]() {
resolve(42);
});
}}.timeout(2000).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(4000, [=]() {
resolve(42);
});
}}.timeout(2000)
.finally([&]() {
elapsed = timer.elapsed();
});
p.fail([&](const QPromiseTimeoutException&) {
failed = true;
return -1;
}).wait();
failed = true;
return -1;
}).wait();
QCOMPARE(waitForValue(p, -1), -1);
QCOMPARE(p.isRejected(), true);
@ -112,12 +114,13 @@ void tst_qpromise_timeout::fulfilledStdChrono()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(1000, [=]() {
resolve(42);
});
}}.timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(1000, [=]() {
resolve(42);
});
}}.timeout(std::chrono::seconds{2})
.finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForValue(p, -1), 42);
QCOMPARE(p.isFulfilled(), true);
@ -132,13 +135,13 @@ void tst_qpromise_timeout::rejectedStdChrono()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QTimer::singleShot(1000, [=]() {
reject(QString{"foo"});
});
}}.timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(1000, [=]() {
reject(QString{"foo"});
});
}}.timeout(std::chrono::seconds{2})
.finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForError(p, QString{}), QString{"foo"});
QCOMPARE(p.isRejected(), true);
@ -154,17 +157,18 @@ void tst_qpromise_timeout::timeoutStdChrono()
timer.start();
auto p = QPromise<int>{[](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(4000, [=]() {
resolve(42);
});
}}.timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
QTimer::singleShot(4000, [=]() {
resolve(42);
});
}}.timeout(std::chrono::seconds{2})
.finally([&]() {
elapsed = timer.elapsed();
});
p.fail([&](const QPromiseTimeoutException&) {
failed = true;
return -1;
}).wait();
failed = true;
return -1;
}).wait();
QCOMPARE(waitForValue(p, -1), -1);
QCOMPARE(p.isRejected(), true);

View File

@ -18,18 +18,18 @@ class tst_requirements : public QObject
private Q_SLOTS:
// 2.1. Promise States
void statePending(); // 2.1.1.
void stateFulfilled(); // 2.1.2.
void stateRejected(); // 2.1.3.
void statePending(); // 2.1.1.
void stateFulfilled(); // 2.1.2.
void stateRejected(); // 2.1.3.
// 2.2. The then Method
void thenArguments(); // 2.2.1.
void thenOnFulfilled(); // 2.2.2.
void thenOnRejected(); // 2.2.3.
void thenAsynchronous(); // 2.2.4.
// 2.2.5. NOT APPLICABLE
void thenMultipleCalls(); // 2.2.6.
void thenHandlers(); // 2.2.7.
void thenArguments(); // 2.2.1.
void thenOnFulfilled(); // 2.2.2.
void thenOnRejected(); // 2.2.3.
void thenAsynchronous(); // 2.2.4.
// 2.2.5. NOT APPLICABLE
void thenMultipleCalls(); // 2.2.6.
void thenHandlers(); // 2.2.7.
// 2.3. The Promise Resolution Procedure
@ -44,7 +44,9 @@ void tst_requirements::statePending()
// 2.1.1.1. may transition to either the fulfilled state
{
QPromise<int> p{[&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() { resolve(42); });
QtPromisePrivate::qtpromise_defer([=]() {
resolve(42);
});
}};
QVERIFY(p.isPending());
@ -59,9 +61,11 @@ void tst_requirements::statePending()
}
// 2.1.1.1. ... or the rejected state
{
{
QPromise<int> p{[&](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() { reject(QString{"foo"}); });
QtPromisePrivate::qtpromise_defer([=]() {
reject(QString{"foo"});
});
}};
QVERIFY(p.isPending());
@ -82,9 +86,7 @@ void tst_requirements::stateFulfilled()
int value = -1;
// 2.1.2. When fulfilled, a promise:
QPromise<int> p{[](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
QPromise<int> p{[](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
// 2.1.2.2. must have a value, which must not change.
resolve(42);
@ -97,11 +99,14 @@ void tst_requirements::stateFulfilled()
QVERIFY(p.isPending());
p.then([&](int res) {
value = res;
}, [&](const QString& err) {
error = err;
}).wait();
p.then(
[&](int res) {
value = res;
},
[&](const QString& err) {
error = err;
})
.wait();
QVERIFY(p.isFulfilled());
QVERIFY(!p.isRejected());
@ -115,9 +120,7 @@ void tst_requirements::stateRejected()
int value = -1;
// 2.1.3 When rejected, a promise:
QPromise<int> p{[](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
QPromise<int> p{[](const QPromiseResolve<int>& resolve, const QPromiseReject<int>& reject) {
QtPromisePrivate::qtpromise_defer([=]() {
// 2.1.3.2. must have a reason, which must not change.
reject(QString{"foo"});
@ -130,11 +133,14 @@ void tst_requirements::stateRejected()
QVERIFY(p.isPending());
p.then([&](int res) {
value = res;
}, [&](const QString& err) {
error = err;
}).wait();
p.then(
[&](int res) {
value = res;
},
[&](const QString& err) {
error = err;
})
.wait();
QVERIFY(!p.isFulfilled());
QVERIFY(p.isRejected());
@ -148,10 +154,15 @@ void tst_requirements::thenArguments()
{
QString error;
int value = -1;
QPromise<int>::resolve(42).then(
[&](int res) { value = res; },
[&](const QString& err) { error = err; }
).wait();
QPromise<int>::resolve(42)
.then(
[&](int res) {
value = res;
},
[&](const QString& err) {
error = err;
})
.wait();
QVERIFY(error.isEmpty());
QCOMPARE(value, 42);
@ -159,10 +170,15 @@ void tst_requirements::thenArguments()
{
QString error;
int value = -1;
QPromise<int>::reject(QString{"foo"}).then(
[&](int res) { value = res; },
[&](const QString& err){ error = err; }
).wait();
QPromise<int>::reject(QString{"foo"})
.then(
[&](int res) {
value = res;
},
[&](const QString& err) {
error = err;
})
.wait();
QCOMPARE(error, QString{"foo"});
QCOMPARE(value, -1);
@ -171,10 +187,13 @@ void tst_requirements::thenArguments()
// 2.2.1. onFulfilled is an optional arguments:
{
QString error;
QPromise<int>::reject(QString{"foo"}).then(
nullptr,
[&](const QString& err){ error = err; return 42; }
).wait();
QPromise<int>::reject(QString{"foo"})
.then(nullptr,
[&](const QString& err) {
error = err;
return 42;
})
.wait();
QCOMPARE(error, QString{"foo"});
}
@ -182,9 +201,11 @@ void tst_requirements::thenArguments()
// 2.2.1. onRejected is an optional arguments:
{
int value = -1;
QPromise<int>::resolve(42).then(
[&value](int res) { value = res; }
).wait();
QPromise<int>::resolve(42)
.then([&value](int res) {
value = res;
})
.wait();
QCOMPARE(value, 42);
}
@ -206,7 +227,9 @@ void tst_requirements::thenOnFulfilled()
});
}};
auto p1 = p0.then([&](int res) { values << res; });
auto p1 = p0.then([&](int res) {
values << res;
});
// 2.2.2.2. it must not be called before promise is fulfilled.
QVERIFY(p0.isPending());
@ -234,7 +257,9 @@ void tst_requirements::thenOnRejected()
});
}};
auto p1 = p0.then(nullptr, [&](const QString& err) { errors << err; });
auto p1 = p0.then(nullptr, [&](const QString& err) {
errors << err;
});
// 2.2.3.2. it must not be called before promise is rejected.
QVERIFY(p0.isPending());
@ -260,7 +285,9 @@ void tst_requirements::thenAsynchronous()
auto p0 = QPromise<int>::resolve(42);
QVERIFY(p0.isFulfilled());
auto p1 = p0.then([&](int res){ value = res; });
auto p1 = p0.then([&](int res) {
value = res;
});
QVERIFY(p1.isPending());
QCOMPARE(value, -1);
@ -283,11 +310,16 @@ void tst_requirements::thenMultipleCalls()
});
}};
QtPromise::all(QVector<QPromise<void>>{
p.then([&](int r) { values << r + 1; }),
p.then([&](int r) { values << r + 2; }),
p.then([&](int r) { values << r + 3; })
}).wait();
QtPromise::all(QVector<QPromise<void>>{p.then([&](int r) {
values << r + 1;
}),
p.then([&](int r) {
values << r + 2;
}),
p.then([&](int r) {
values << r + 3;
})})
.wait();
QCOMPARE(values, (QVector<int>{43, 44, 45}));
}
@ -302,11 +334,22 @@ void tst_requirements::thenMultipleCalls()
});
}};
QtPromise::all(QVector<QPromise<int>>{
p.then(nullptr, [&](int r) { values << r + 1; return r + 1; }),
p.then(nullptr, [&](int r) { values << r + 2; return r + 2; }),
p.then(nullptr, [&](int r) { values << r + 3; return r + 3; })
}).wait();
QtPromise::all(QVector<QPromise<int>>{p.then(nullptr,
[&](int r) {
values << r + 1;
return r + 1;
}),
p.then(nullptr,
[&](int r) {
values << r + 2;
return r + 2;
}),
p.then(nullptr,
[&](int r) {
values << r + 3;
return r + 3;
})})
.wait();
QCOMPARE(values, (QVector<int>{9, 10, 11}));
}
@ -316,7 +359,9 @@ void tst_requirements::thenHandlers()
{
// 2.2.7. then must return a promise: p2 = p1.then(onFulfilled, onRejected);
{
auto handler = [](){ return 42; };
auto handler = []() {
return 42;
};
auto p1 = QPromise<int>::resolve(42);
Q_STATIC_ASSERT((std::is_same<decltype(p1.then(handler, nullptr)), QPromise<int>>::value));
Q_STATIC_ASSERT((std::is_same<decltype(p1.then(nullptr, handler)), QPromise<int>>::value));
@ -331,8 +376,12 @@ void tst_requirements::thenHandlers()
{
QString reason;
auto p1 = QPromise<int>::resolve(42);
auto p2 = p1.then([](){ throw QString{"foo"}; });
p2.then(nullptr, [&](const QString& e) { reason = e; }).wait();
auto p2 = p1.then([]() {
throw QString{"foo"};
});
p2.then(nullptr, [&](const QString& e) {
reason = e;
}).wait();
QVERIFY(p1.isFulfilled());
QVERIFY(p2.isRejected());
@ -341,8 +390,14 @@ void tst_requirements::thenHandlers()
{
QString reason;
auto p1 = QPromise<int>::reject(QString{"foo"});
auto p2 = p1.then(nullptr, [](){ throw QString{"bar"}; return 42; });
p2.then(nullptr, [&](const QString& e) { reason = e; return 0; }).wait();
auto p2 = p1.then(nullptr, []() {
throw QString{"bar"};
return 42;
});
p2.then(nullptr, [&](const QString& e) {
reason = e;
return 0;
}).wait();
QVERIFY(p1.isRejected());
QVERIFY(p2.isRejected());
@ -354,9 +409,13 @@ void tst_requirements::thenHandlers()
{
QString value;
auto p1 = QPromise<QString>::resolve("42");
auto p2 = p1.then(nullptr, [](){ return QString{}; });
auto p2 = p1.then(nullptr, []() {
return QString{};
});
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<QString>>::value));
p2.then([&](const QString& e) { value = e; }).wait();
p2.then([&](const QString& e) {
value = e;
}).wait();
QVERIFY(p1.isFulfilled());
QVERIFY(p2.isFulfilled());

View File

@ -10,13 +10,15 @@
#include <utility>
struct Logs {
struct Logs
{
int ctor = 0;
int copy = 0;
int move = 0;
int refs = 0;
void reset() {
void reset()
{
ctor = 0;
copy = 0;
move = 0;
@ -26,21 +28,45 @@ struct Logs {
struct Logger
{
Logger() { logs().ctor++; logs().refs++; }
Logger(const Logger&) { logs().copy++; logs().refs++; }
Logger(Logger&&) { logs().move++; logs().refs++; }
Logger()
{
logs().ctor++;
logs().refs++;
}
Logger(const Logger&)
{
logs().copy++;
logs().refs++;
}
Logger(Logger&&)
{
logs().move++;
logs().refs++;
}
~Logger() { logs().refs--; }
Logger& operator=(const Logger&) { logs().copy++; return *this; }
Logger& operator=(Logger&&) { logs().move++; return *this; }
Logger& operator=(const Logger&)
{
logs().copy++;
return *this;
}
Logger& operator=(Logger&&)
{
logs().move++;
return *this;
}
public: // STATICS
static Logs& logs() { static Logs logs; return logs; }
static Logs& logs()
{
static Logs logs;
return logs;
}
};
struct Data : public Logger
{
Data(int v) : Logger{}, m_value{v} {}
Data(int v) : Logger{}, m_value{v} { }
int value() const { return m_value; }
// MSVC 2013 doesn't support implicit generation of the move constructor and
@ -48,15 +74,9 @@ struct Data : public Logger
// constructor and operator also need to be explicitly defined (error C2280).
// https://stackoverflow.com/a/26581337
Data(const Data& other)
: Logger{other}
, m_value{other.m_value}
{ }
Data(const Data& other) : Logger{other}, m_value{other.m_value} { }
Data(Data&& other) : Logger{std::forward<Data>(other)}
{
std::swap(m_value, other.m_value);
}
Data(Data&& other) : Logger{std::forward<Data>(other)} { std::swap(m_value, other.m_value); }
Data& operator=(const Data& other)
{

View File

@ -10,54 +10,65 @@
#include <QtPromise>
template <typename T>
template<typename T>
static inline T waitForValue(const QtPromise::QPromise<T>& promise, const T& initial)
{
T value(initial);
promise.then([&](const T& res) {
value = res;
}).wait();
promise
.then([&](const T& res) {
value = res;
})
.wait();
return value;
}
template <typename T>
static inline T waitForValue(const QtPromise::QPromise<void>& promise, const T& initial, const T& expected)
template<typename T>
static inline T
waitForValue(const QtPromise::QPromise<void>& promise, const T& initial, const T& expected)
{
T value(initial);
promise.then([&]() {
value = expected;
}).wait();
promise
.then([&]() {
value = expected;
})
.wait();
return value;
}
template <typename T, typename E>
template<typename T, typename E>
static inline E waitForError(const QtPromise::QPromise<T>& promise, const E& initial)
{
E error(initial);
promise.fail([&](const E& err) {
error = err;
return T();
}).wait();
promise
.fail([&](const E& err) {
error = err;
return T();
})
.wait();
return error;
}
template <typename E>
template<typename E>
static inline E waitForError(const QtPromise::QPromise<void>& promise, const E& initial)
{
E error(initial);
promise.fail([&](const E& err) {
error = err;
}).wait();
promise
.fail([&](const E& err) {
error = err;
})
.wait();
return error;
}
template <typename E, typename T>
template<typename E, typename T>
static inline bool waitForRejected(const T& promise)
{
bool result = false;
promise.tapFail([&](const E&) {
result = true;
}).wait();
promise
.tapFail([&](const E&) {
result = true;
})
.wait();
return result;
}

View File

@ -40,10 +40,12 @@ void tst_thread::resolve()
source = QThread::currentThread();
resolve(42);
});
}}.then([&](int res) {
target = QThread::currentThread();
value = res;
}).wait();
}}
.then([&](int res) {
target = QThread::currentThread();
value = res;
})
.wait();
QVERIFY(source != nullptr);
QVERIFY(source != target);
@ -62,10 +64,12 @@ void tst_thread::resolve_void()
source = QThread::currentThread();
resolve();
});
}}.then([&]() {
target = QThread::currentThread();
value = 43;
}).wait();
}}
.then([&]() {
target = QThread::currentThread();
value = 43;
})
.wait();
QVERIFY(source != nullptr);
QVERIFY(source != target);
@ -84,11 +88,13 @@ void tst_thread::reject()
source = QThread::currentThread();
reject(QString{"foo"});
});
}}.fail([&](const QString& err) {
target = QThread::currentThread();
error = err;
return -1;
}).wait();
}}
.fail([&](const QString& err) {
target = QThread::currentThread();
error = err;
return -1;
})
.wait();
QVERIFY(source != nullptr);
QVERIFY(source != target);
@ -106,12 +112,15 @@ void tst_thread::then()
int value = -1;
QThread* target = nullptr;
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
p.then([&](int res) {
target = QThread::currentThread();
value = res;
}).wait();
}, p)).wait();
QtPromise::resolve(QtConcurrent::run(
[&](const QPromise<int>& p) {
p.then([&](int res) {
target = QThread::currentThread();
value = res;
}).wait();
},
p))
.wait();
QVERIFY(target != nullptr);
QVERIFY(source != target);
@ -129,12 +138,15 @@ void tst_thread::then_void()
int value = -1;
QThread* target = nullptr;
QtPromise::resolve(QtConcurrent::run([&](const QPromise<void>& p) {
p.then([&]() {
target = QThread::currentThread();
value = 43;
}).wait();
}, p)).wait();
QtPromise::resolve(QtConcurrent::run(
[&](const QPromise<void>& p) {
p.then([&]() {
target = QThread::currentThread();
value = 43;
}).wait();
},
p))
.wait();
QVERIFY(target != nullptr);
QVERIFY(source != target);
@ -152,13 +164,16 @@ void tst_thread::fail()
QString error;
QThread* target = nullptr;
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
p.fail([&](const QString& err) {
target = QThread::currentThread();
error = err;
return -1;
}).wait();
}, p)).wait();
QtPromise::resolve(QtConcurrent::run(
[&](const QPromise<int>& p) {
p.fail([&](const QString& err) {
target = QThread::currentThread();
error = err;
return -1;
}).wait();
},
p))
.wait();
QVERIFY(target != nullptr);
QVERIFY(source != target);
@ -176,12 +191,15 @@ void tst_thread::finally()
int value = -1;
QThread* target = nullptr;
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
p.finally([&]() {
target = QThread::currentThread();
value = 43;
}).wait();
}, p)).wait();
QtPromise::resolve(QtConcurrent::run(
[&](const QPromise<int>& p) {
p.finally([&]() {
target = QThread::currentThread();
value = 43;
}).wait();
},
p))
.wait();
QVERIFY(target != nullptr);
QVERIFY(source != target);