mirror of
https://github.com/simonbrunel/qtpromise.git
synced 2025-07-02 07:15:25 +08:00
Rename qPromise() helper to QtPromise::resolve()
For consistency with other helpers, deprecate `qPromise()` in favor of `QtPromise::resolve()` but also add support for calling this helper with lvalue. Add extra unit tests to make sure that rvalue is not copied.
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
#include "../shared/data.h"
|
||||
|
||||
// QtPromise
|
||||
#include <QtPromise>
|
||||
|
||||
@ -20,7 +22,6 @@ class tst_benchmark : public QObject
|
||||
|
||||
private Q_SLOTS:
|
||||
void valueResolve();
|
||||
void valueResolveStatic();
|
||||
void valueReject();
|
||||
void valueThen();
|
||||
void valueFinally();
|
||||
@ -34,72 +35,6 @@ private Q_SLOTS:
|
||||
QTEST_MAIN(tst_benchmark)
|
||||
#include "tst_benchmark.moc"
|
||||
|
||||
struct Logs {
|
||||
int ctor = 0;
|
||||
int copy = 0;
|
||||
int move = 0;
|
||||
int refs = 0;
|
||||
|
||||
void reset() {
|
||||
ctor = 0;
|
||||
copy = 0;
|
||||
move = 0;
|
||||
refs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Logger
|
||||
{
|
||||
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; }
|
||||
|
||||
public: // STATICS
|
||||
static Logs& logs() { static Logs logs; return logs; }
|
||||
};
|
||||
|
||||
struct Data : public Logger
|
||||
{
|
||||
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
|
||||
// operator, so we need to explicitly define these methods and thus the copy
|
||||
// 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(Data&& other) : Logger(std::forward<Data>(other))
|
||||
{
|
||||
qSwap(m_value, other.m_value);
|
||||
}
|
||||
|
||||
Data& operator=(const Data& other)
|
||||
{
|
||||
Logger::operator=(other);
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Data& operator=(Data&& other)
|
||||
{
|
||||
Logger::operator=(std::forward<Data>(other));
|
||||
qSwap(m_value, other.m_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
};
|
||||
|
||||
void tst_benchmark::valueResolve()
|
||||
{
|
||||
{ // should move the value when resolved by rvalue
|
||||
@ -127,31 +62,6 @@ void tst_benchmark::valueResolve()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_benchmark::valueResolveStatic()
|
||||
{
|
||||
{ // should move the value when resolved by rvalue
|
||||
Data::logs().reset();
|
||||
QPromise<Data>::resolve(Data(42)).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().refs, 0);
|
||||
}
|
||||
{ // should create one copy of the value when resolved by lvalue
|
||||
{
|
||||
Data::logs().reset();
|
||||
Data value(42);
|
||||
QPromise<Data>::resolve(value).wait();
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 1); // copy value to the promise data
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_benchmark::valueReject()
|
||||
{
|
||||
{ // should not create any data if rejected
|
||||
|
5
tests/auto/qtpromise/deprecations/deprecations.pri
Normal file
5
tests/auto/qtpromise/deprecations/deprecations.pri
Normal file
@ -0,0 +1,5 @@
|
||||
include(../qtpromise.pri)
|
||||
|
||||
DEFINES -= QT_DEPRECATED_WARNINGS
|
||||
gcc:QMAKE_CXXFLAGS += -Wno-deprecated-declarations
|
||||
msvc:QMAKE_CXXFLAGS -= -wd4996
|
3
tests/auto/qtpromise/deprecations/deprecations.pro
Normal file
3
tests/auto/qtpromise/deprecations/deprecations.pro
Normal file
@ -0,0 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
helpers
|
3
tests/auto/qtpromise/deprecations/helpers/helpers.pro
Normal file
3
tests/auto/qtpromise/deprecations/helpers/helpers.pro
Normal file
@ -0,0 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
qpromise
|
@ -0,0 +1,5 @@
|
||||
QT += concurrent
|
||||
TARGET = tst_deprecations_helpers_qpromise
|
||||
SOURCES += $$PWD/tst_qpromise.cpp
|
||||
|
||||
include(../../deprecations.pri)
|
@ -0,0 +1,268 @@
|
||||
#include "../../../shared/data.h"
|
||||
#include "../../../shared/utils.h"
|
||||
|
||||
// QtPromise
|
||||
#include <QtPromise>
|
||||
|
||||
// Qt
|
||||
#include <QtConcurrent>
|
||||
#include <QtTest>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
|
||||
using namespace QtPromise;
|
||||
|
||||
class tst_deprecations_helpers_qpromise : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void value();
|
||||
void noValue();
|
||||
void moveRValue();
|
||||
void copyLValue();
|
||||
void qtSharedPtr();
|
||||
void stdSharedPtr();
|
||||
void typedPromise();
|
||||
void voidPromise();
|
||||
void typedFuture();
|
||||
void voidFuture();
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_deprecations_helpers_qpromise)
|
||||
#include "tst_qpromise.moc"
|
||||
|
||||
void tst_deprecations_helpers_qpromise::value()
|
||||
{
|
||||
int v0 = 42;
|
||||
const int v1 = 42;
|
||||
|
||||
auto p0 = qPromise(42);
|
||||
auto p1 = qPromise(v0);
|
||||
auto p2 = qPromise(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
}
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(p, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::noValue()
|
||||
{
|
||||
auto p = qPromise();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::moveRValue()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
{
|
||||
auto p = qPromise(Data(42)).wait();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 1);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::copyLValue()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
{
|
||||
Data value(42);
|
||||
auto p = qPromise(value).wait();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 1);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_deprecations_helpers_qpromise::qtSharedPtr()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
QWeakPointer<Data> wptr;
|
||||
|
||||
{
|
||||
QSharedPointer<Data> sptr0(new Data(42));
|
||||
const QSharedPointer<Data> sptr1 = sptr0;
|
||||
|
||||
auto p0 = qPromise(QSharedPointer<Data>(new Data(42)));
|
||||
auto p1 = qPromise(sptr0);
|
||||
auto p2 = qPromise(sptr1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<QSharedPointer<Data>>>::value));
|
||||
|
||||
QCOMPARE(waitForValue(p1, QSharedPointer<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, QSharedPointer<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.isNull(), false);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.isNull(), true);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_deprecations_helpers_qpromise::stdSharedPtr()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
std::weak_ptr<Data> wptr;
|
||||
|
||||
{
|
||||
std::shared_ptr<Data> sptr0(new Data(42));
|
||||
const std::shared_ptr<Data> sptr1 = sptr0;
|
||||
|
||||
auto p0 = qPromise(std::shared_ptr<Data>(new Data(42)));
|
||||
auto p1 = qPromise(sptr0);
|
||||
auto p2 = qPromise(sptr1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<std::shared_ptr<Data>>>::value));
|
||||
|
||||
QCOMPARE(waitForValue(p1, std::shared_ptr<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, std::shared_ptr<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.use_count(), 4l);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.use_count(), 0l);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::typedPromise()
|
||||
{
|
||||
auto resolver = [](const QPromiseResolve<int>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve(42);
|
||||
});
|
||||
};
|
||||
|
||||
QPromise<int> v0(resolver);
|
||||
const QPromise<int> v1 = v0;
|
||||
|
||||
auto p0 = qPromise(QPromise<int>(resolver));
|
||||
auto p1 = qPromise(v0);
|
||||
auto p2 = qPromise(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::voidPromise()
|
||||
{
|
||||
auto resolver = [](const QPromiseResolve<void>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
QPromise<void> v0(resolver);
|
||||
const QPromise<void> v1 = v0;
|
||||
|
||||
auto p0 = qPromise(QPromise<void>(resolver));
|
||||
auto p1 = qPromise(v0);
|
||||
auto p2 = qPromise(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<void>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1, 42), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::typedFuture()
|
||||
{
|
||||
auto fn = [](){ return 42; };
|
||||
QFuture<int> v0 = QtConcurrent::run(fn);
|
||||
const QFuture<int> v1 = v0;
|
||||
|
||||
auto p0 = qPromise(QtConcurrent::run(fn));
|
||||
auto p1 = qPromise(v0);
|
||||
auto p2 = qPromise(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_deprecations_helpers_qpromise::voidFuture()
|
||||
{
|
||||
auto fn = [](){ };
|
||||
QFuture<void> v0 = QtConcurrent::run(fn);
|
||||
const QFuture<void> v1 = v0;
|
||||
|
||||
auto p0 = qPromise(QtConcurrent::run(fn));
|
||||
auto p1 = qPromise(v0);
|
||||
auto p2 = qPromise(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<void>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1, 42), 42);
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ namespace {
|
||||
template <class E>
|
||||
void verify()
|
||||
{
|
||||
auto p = qPromise(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);
|
||||
|
@ -52,7 +52,7 @@ QTEST_MAIN(tst_future)
|
||||
void tst_future::fulfilled()
|
||||
{
|
||||
int result = -1;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
return 42;
|
||||
}));
|
||||
|
||||
@ -70,7 +70,7 @@ void tst_future::fulfilled()
|
||||
void tst_future::fulfilled_void()
|
||||
{
|
||||
int result = -1;
|
||||
auto p = qPromise(QtConcurrent::run([]() { }));
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() { }));
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||
QCOMPARE(p.isPending(), true);
|
||||
@ -86,7 +86,7 @@ void tst_future::fulfilled_void()
|
||||
void tst_future::rejected()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
throw MyException("foo");
|
||||
return 42;
|
||||
}));
|
||||
@ -106,7 +106,7 @@ void tst_future::rejected()
|
||||
void tst_future::rejected_void()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
throw MyException("foo");
|
||||
}));
|
||||
|
||||
@ -125,7 +125,7 @@ void tst_future::rejected_void()
|
||||
void tst_future::unhandled()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
throw QString("foo");
|
||||
return 42;
|
||||
}));
|
||||
@ -149,7 +149,7 @@ void tst_future::unhandled()
|
||||
void tst_future::unhandled_void()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
throw QString("foo");
|
||||
}));
|
||||
|
||||
@ -169,7 +169,7 @@ void tst_future::unhandled_void()
|
||||
void tst_future::canceled()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QFuture<int>()); // Constructs an empty, canceled future.
|
||||
auto p = QtPromise::resolve(QFuture<int>()); // Constructs an empty, canceled future.
|
||||
|
||||
QCOMPARE(p.isPending(), true);
|
||||
|
||||
@ -185,7 +185,7 @@ void tst_future::canceled()
|
||||
void tst_future::canceled_void()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QFuture<void>()); // Constructs an empty, canceled future.
|
||||
auto p = QtPromise::resolve(QFuture<void>()); // Constructs an empty, canceled future.
|
||||
|
||||
QCOMPARE(p.isPending(), true);
|
||||
|
||||
@ -200,7 +200,7 @@ void tst_future::canceled_void()
|
||||
void tst_future::canceledFromThread()
|
||||
{
|
||||
QString error;
|
||||
auto p = qPromise(QtConcurrent::run([]() {
|
||||
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||
throw QPromiseCanceledException();
|
||||
}));
|
||||
|
||||
@ -217,7 +217,7 @@ void tst_future::canceledFromThread()
|
||||
void tst_future::then()
|
||||
{
|
||||
QString result;
|
||||
auto input = qPromise(42);
|
||||
auto input = QtPromise::resolve(42);
|
||||
auto output = input.then([](int res) {
|
||||
return QtConcurrent::run([=]() {
|
||||
return QString("foo%1").arg(res);
|
||||
@ -238,7 +238,7 @@ void tst_future::then()
|
||||
void tst_future::then_void()
|
||||
{
|
||||
QString result;
|
||||
auto input = qPromise();
|
||||
auto input = QtPromise::resolve();
|
||||
auto output = input.then([&]() {
|
||||
return QtConcurrent::run([&]() {
|
||||
result = "foo";
|
||||
@ -300,7 +300,7 @@ void tst_future::fail_void()
|
||||
|
||||
void tst_future::finally()
|
||||
{
|
||||
auto input = qPromise(42);
|
||||
auto input = QtPromise::resolve(42);
|
||||
auto output = input.finally([]() {
|
||||
return QtConcurrent::run([]() {
|
||||
return QString("foo");
|
||||
@ -323,7 +323,7 @@ void tst_future::finally()
|
||||
|
||||
void tst_future::finallyRejected()
|
||||
{
|
||||
auto input = qPromise(42);
|
||||
auto input = QtPromise::resolve(42);
|
||||
auto output = input.finally([]() {
|
||||
return QtConcurrent::run([]() {
|
||||
throw MyException("foo");
|
||||
|
@ -37,13 +37,13 @@ struct SequenceTester
|
||||
static void exec()
|
||||
{
|
||||
Sequence promises{
|
||||
QtPromise::qPromise(42),
|
||||
QtPromise::qPromise(43),
|
||||
QtPromise::qPromise(44)
|
||||
QtPromise::resolve(42),
|
||||
QtPromise::resolve(43),
|
||||
QtPromise::resolve(44)
|
||||
};
|
||||
|
||||
promises.push_back(QtPromise::qPromise(45));
|
||||
promises.insert(++promises.begin(), QtPromise::qPromise(46));
|
||||
promises.push_back(QtPromise::resolve(45));
|
||||
promises.insert(++promises.begin(), QtPromise::resolve(46));
|
||||
promises.pop_back();
|
||||
|
||||
auto p = QtPromise::qPromiseAll(promises);
|
||||
@ -60,13 +60,13 @@ struct SequenceTester<Sequence<QPromise<void>, Args...>>
|
||||
static void exec()
|
||||
{
|
||||
Sequence<QPromise<void>, Args...> promises{
|
||||
QtPromise::qPromise(),
|
||||
QtPromise::qPromise(),
|
||||
QtPromise::qPromise()
|
||||
QtPromise::resolve(),
|
||||
QtPromise::resolve(),
|
||||
QtPromise::resolve()
|
||||
};
|
||||
|
||||
promises.push_back(QtPromise::qPromise());
|
||||
promises.insert(++promises.begin(), QtPromise::qPromise());
|
||||
promises.push_back(QtPromise::resolve());
|
||||
promises.insert(++promises.begin(), QtPromise::resolve());
|
||||
promises.pop_back();
|
||||
|
||||
auto p = QtPromise::qPromiseAll(promises);
|
||||
@ -99,8 +99,8 @@ void tst_helpers_all::emptySequence_void()
|
||||
|
||||
void tst_helpers_all::allPromisesSucceed()
|
||||
{
|
||||
auto p0 = QtPromise::qPromise(42);
|
||||
auto p1 = QtPromise::qPromise(44);
|
||||
auto p0 = QtPromise::resolve(42);
|
||||
auto p1 = QtPromise::resolve(44);
|
||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve(43);
|
||||
@ -120,8 +120,8 @@ void tst_helpers_all::allPromisesSucceed()
|
||||
|
||||
void tst_helpers_all::allPromisesSucceed_void()
|
||||
{
|
||||
auto p0 = QtPromise::qPromise();
|
||||
auto p1 = QtPromise::qPromise();
|
||||
auto p0 = QtPromise::resolve();
|
||||
auto p1 = QtPromise::resolve();
|
||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve();
|
||||
@ -141,8 +141,8 @@ void tst_helpers_all::allPromisesSucceed_void()
|
||||
|
||||
void tst_helpers_all::atLeastOnePromiseReject()
|
||||
{
|
||||
auto p0 = QtPromise::qPromise(42);
|
||||
auto p1 = QtPromise::qPromise(44);
|
||||
auto p0 = QtPromise::resolve(42);
|
||||
auto p1 = QtPromise::resolve(44);
|
||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
reject(QString("foo"));
|
||||
@ -162,8 +162,8 @@ void tst_helpers_all::atLeastOnePromiseReject()
|
||||
|
||||
void tst_helpers_all::atLeastOnePromiseReject_void()
|
||||
{
|
||||
auto p0 = QtPromise::qPromise();
|
||||
auto p1 = QtPromise::qPromise();
|
||||
auto p0 = QtPromise::resolve();
|
||||
auto p1 = QtPromise::resolve();
|
||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
reject(QString("foo"));
|
||||
@ -183,9 +183,9 @@ void tst_helpers_all::atLeastOnePromiseReject_void()
|
||||
|
||||
void tst_helpers_all::preserveOrder()
|
||||
{
|
||||
auto p0 = QtPromise::qPromise(42).delay(500);
|
||||
auto p1 = QtPromise::qPromise(43).delay(100);
|
||||
auto p2 = QtPromise::qPromise(44).delay(250);
|
||||
auto p0 = QtPromise::resolve(42).delay(500);
|
||||
auto p1 = QtPromise::resolve(43).delay(100);
|
||||
auto p2 = QtPromise::resolve(44).delay(250);
|
||||
|
||||
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p1, p2});
|
||||
|
||||
|
@ -64,7 +64,7 @@ void tst_helpers_attempt::futureResult()
|
||||
void tst_helpers_attempt::promiseResult()
|
||||
{
|
||||
auto p = QtPromise::attempt([]() {
|
||||
return QtPromise::qPromise(42).delay(200);
|
||||
return QtPromise::resolve(42).delay(200);
|
||||
});
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
|
||||
|
@ -1,3 +1,4 @@
|
||||
QT += concurrent
|
||||
TARGET = tst_helpers_resolve
|
||||
SOURCES += $$PWD/tst_resolve.cpp
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include "../../shared/data.h"
|
||||
#include "../../shared/utils.h"
|
||||
|
||||
// QtPromise
|
||||
#include <QtPromise>
|
||||
|
||||
// Qt
|
||||
#include <QtConcurrent>
|
||||
#include <QtTest>
|
||||
|
||||
// STL
|
||||
@ -16,109 +18,251 @@ class tst_helpers_resolve : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void resolveWithValue();
|
||||
void resolveWithNoValue();
|
||||
void resolveWithTypedPromise();
|
||||
void resolveWithVoidPromise();
|
||||
void resolveWithQSharedPtr();
|
||||
void resolveWithStdSharedPtr();
|
||||
void value();
|
||||
void noValue();
|
||||
void moveRValue();
|
||||
void copyLValue();
|
||||
void qtSharedPtr();
|
||||
void stdSharedPtr();
|
||||
void typedPromise();
|
||||
void voidPromise();
|
||||
void typedFuture();
|
||||
void voidFuture();
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_helpers_resolve)
|
||||
#include "tst_resolve.moc"
|
||||
|
||||
void tst_helpers_resolve::resolveWithValue()
|
||||
void tst_helpers_resolve::value()
|
||||
{
|
||||
const int value = 42;
|
||||
auto p0 = QPromise<int>::resolve(value);
|
||||
auto p1 = QPromise<int>::resolve(43);
|
||||
int v0 = 42;
|
||||
const int v1 = 42;
|
||||
|
||||
auto p0 = QtPromise::resolve(42);
|
||||
auto p1 = QtPromise::resolve(v0);
|
||||
auto p2 = QtPromise::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
QCOMPARE(p0.isFulfilled(), true);
|
||||
QCOMPARE(p1.isFulfilled(), true);
|
||||
QCOMPARE(waitForValue(p0, -1), 42);
|
||||
QCOMPARE(waitForValue(p1, -1), 43);
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
}
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(p, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::resolveWithNoValue()
|
||||
void tst_helpers_resolve::noValue()
|
||||
{
|
||||
auto p = QPromise<void>::resolve();
|
||||
auto p = QtPromise::resolve();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::resolveWithTypedPromise()
|
||||
void tst_helpers_resolve::moveRValue()
|
||||
{
|
||||
auto p = QtPromise::qPromise(
|
||||
QPromise<QString>([](const QPromiseResolve<QString>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve("foo");
|
||||
});
|
||||
}));
|
||||
Data::logs().reset();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
||||
{
|
||||
auto p = QtPromise::resolve(Data(42)).wait();
|
||||
|
||||
QCOMPARE(p.isPending(), true);
|
||||
QCOMPARE(waitForValue(p, QString()), QString("foo"));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 1);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::resolveWithVoidPromise()
|
||||
void tst_helpers_resolve::copyLValue()
|
||||
{
|
||||
int check;
|
||||
auto p = QtPromise::qPromise(
|
||||
QPromise<void>([&](const QPromiseResolve<void>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=, &check](){
|
||||
check = 8;
|
||||
resolve();
|
||||
});
|
||||
}));
|
||||
Data::logs().reset();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||
{
|
||||
Data value(42);
|
||||
auto p = QtPromise::resolve(value).wait();
|
||||
|
||||
QCOMPARE(p.isPending(), true);
|
||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||
QCOMPARE(check, 8);
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 1);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_helpers_resolve::resolveWithQSharedPtr()
|
||||
void tst_helpers_resolve::qtSharedPtr()
|
||||
{
|
||||
QWeakPointer<int> wptr;
|
||||
Data::logs().reset();
|
||||
|
||||
QWeakPointer<Data> wptr;
|
||||
|
||||
{
|
||||
QSharedPointer<int> sptr(new int(42));
|
||||
auto p = QPromise<QSharedPointer<int>>::resolve(sptr);
|
||||
QSharedPointer<Data> sptr0(new Data(42));
|
||||
const QSharedPointer<Data> sptr1 = sptr0;
|
||||
|
||||
QCOMPARE(waitForValue(p, QSharedPointer<int>()), sptr);
|
||||
auto p0 = QtPromise::resolve(QSharedPointer<Data>(new Data(42)));
|
||||
auto p1 = QtPromise::resolve(sptr0);
|
||||
auto p2 = QtPromise::resolve(sptr1);
|
||||
|
||||
wptr = sptr;
|
||||
sptr.reset();
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<QSharedPointer<Data>>>::value));
|
||||
|
||||
QCOMPARE(wptr.isNull(), false); // "p" still holds a reference
|
||||
QCOMPARE(waitForValue(p1, QSharedPointer<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, QSharedPointer<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.isNull(), false);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.isNull(), true);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_helpers_resolve::resolveWithStdSharedPtr()
|
||||
void tst_helpers_resolve::stdSharedPtr()
|
||||
{
|
||||
std::weak_ptr<int> wptr;
|
||||
Data::logs().reset();
|
||||
|
||||
std::weak_ptr<Data> wptr;
|
||||
|
||||
{
|
||||
std::shared_ptr<int> sptr(new int(42));
|
||||
auto p = QPromise<std::shared_ptr<int>>::resolve(sptr);
|
||||
std::shared_ptr<Data> sptr0(new Data(42));
|
||||
const std::shared_ptr<Data> sptr1 = sptr0;
|
||||
|
||||
QCOMPARE(waitForValue(p, std::shared_ptr<int>()), sptr);
|
||||
auto p0 = QtPromise::resolve(std::shared_ptr<Data>(new Data(42)));
|
||||
auto p1 = QtPromise::resolve(sptr0);
|
||||
auto p2 = QtPromise::resolve(sptr1);
|
||||
|
||||
wptr = sptr;
|
||||
sptr.reset();
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<std::shared_ptr<Data>>>::value));
|
||||
|
||||
QCOMPARE(wptr.use_count(), 1l); // "p" still holds a reference
|
||||
QCOMPARE(waitForValue(p1, std::shared_ptr<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, std::shared_ptr<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.use_count(), 4l);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.use_count(), 0l);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::typedPromise()
|
||||
{
|
||||
auto resolver = [](const QPromiseResolve<int>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve(42);
|
||||
});
|
||||
};
|
||||
|
||||
QPromise<int> v0(resolver);
|
||||
const QPromise<int> v1 = v0;
|
||||
|
||||
auto p0 = QtPromise::resolve(QPromise<int>(resolver));
|
||||
auto p1 = QtPromise::resolve(v0);
|
||||
auto p2 = QtPromise::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::voidPromise()
|
||||
{
|
||||
auto resolver = [](const QPromiseResolve<void>& resolve) {
|
||||
QtPromisePrivate::qtpromise_defer([=](){
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
QPromise<void> v0(resolver);
|
||||
const QPromise<void> v1 = v0;
|
||||
|
||||
auto p0 = QtPromise::resolve(QPromise<void>(resolver));
|
||||
auto p1 = QtPromise::resolve(v0);
|
||||
auto p2 = QtPromise::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<void>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1, 42), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::typedFuture()
|
||||
{
|
||||
auto fn = [](){ return 42; };
|
||||
QFuture<int> v0 = QtConcurrent::run(fn);
|
||||
const QFuture<int> v1 = v0;
|
||||
|
||||
auto p0 = QtPromise::resolve(QtConcurrent::run(fn));
|
||||
auto p1 = QtPromise::resolve(v0);
|
||||
auto p2 = QtPromise::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_helpers_resolve::voidFuture()
|
||||
{
|
||||
auto fn = [](){ };
|
||||
QFuture<void> v0 = QtConcurrent::run(fn);
|
||||
const QFuture<void> v1 = v0;
|
||||
|
||||
auto p0 = QtPromise::resolve(QtConcurrent::run(fn));
|
||||
auto p1 = QtPromise::resolve(v0);
|
||||
auto p2 = QtPromise::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<void>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<void>>::value));
|
||||
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(promise.isPending(), true);
|
||||
}
|
||||
for (const auto& promise : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(promise, -1, 42), 42);
|
||||
}
|
||||
}
|
||||
|
@ -34,14 +34,14 @@ struct SequenceTester
|
||||
static void exec()
|
||||
{
|
||||
QVector<int> values;
|
||||
auto p = QtPromise::qPromise(Sequence{42, 43, 44}).each([&](int v, int i) {
|
||||
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 QPromise<QString>::resolve(QString("foo")).then([&](){
|
||||
return QtPromise::resolve(QString("foo")).then([&](){
|
||||
values << -1;
|
||||
});
|
||||
}).each([&](int v, ...) {
|
||||
|
@ -33,7 +33,7 @@ struct SequenceTester
|
||||
{
|
||||
static void exec()
|
||||
{
|
||||
auto p = QtPromise::qPromise(Sequence{
|
||||
auto p = QtPromise::resolve(Sequence{
|
||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||
}).filter([](int v, ...) {
|
||||
return v > 42 && v < 51;
|
||||
|
@ -34,12 +34,12 @@ struct SequenceTester
|
||||
{
|
||||
static void exec()
|
||||
{
|
||||
auto p = QtPromise::qPromise(Sequence{42, 43, 44}).map([](int 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::qPromise(QString("%1:%2").arg(i).arg(v));
|
||||
return QtPromise::resolve(QString("%1:%2").arg(i).arg(v));
|
||||
}).map([](const QString& v, ...) {
|
||||
return QtPromise::qPromise((v + "!").toUtf8());
|
||||
return QtPromise::resolve((v + "!").toUtf8());
|
||||
}).map([](const QByteArray& v, ...) {
|
||||
return QString::fromUtf8(v);
|
||||
});
|
||||
@ -53,7 +53,7 @@ struct SequenceTester
|
||||
|
||||
void tst_qpromise_map::emptySequence()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{}).map([](int v, ...) {
|
||||
auto p = QtPromise::resolve(QVector<int>{}).map([](int v, ...) {
|
||||
return v + 1;
|
||||
});
|
||||
|
||||
@ -63,7 +63,7 @@ void tst_qpromise_map::emptySequence()
|
||||
|
||||
void tst_qpromise_map::modifyValues()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
return v + 1;
|
||||
});
|
||||
|
||||
@ -73,7 +73,7 @@ void tst_qpromise_map::modifyValues()
|
||||
|
||||
void tst_qpromise_map::convertValues()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
return QString::number(v + 1);
|
||||
});
|
||||
|
||||
@ -83,7 +83,7 @@ void tst_qpromise_map::convertValues()
|
||||
|
||||
void tst_qpromise_map::delayedFulfilled()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
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);
|
||||
@ -97,7 +97,7 @@ void tst_qpromise_map::delayedFulfilled()
|
||||
|
||||
void tst_qpromise_map::delayedRejected()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
return QPromise<int>([&](
|
||||
const QPromiseResolve<int>& resolve,
|
||||
const QPromiseReject<int>& reject) {
|
||||
@ -116,7 +116,7 @@ void tst_qpromise_map::delayedRejected()
|
||||
|
||||
void tst_qpromise_map::functorThrows()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
auto p = QtPromise::resolve(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||
if (v == 43) {
|
||||
throw QString("foo");
|
||||
}
|
||||
@ -129,7 +129,7 @@ void tst_qpromise_map::functorThrows()
|
||||
|
||||
void tst_qpromise_map::functorArguments()
|
||||
{
|
||||
auto p1 = QtPromise::qPromise(QVector<int>{42, 42, 42}).map([](int v, int i) {
|
||||
auto p1 = QtPromise::resolve(QVector<int>{42, 42, 42}).map([](int v, int i) {
|
||||
return v * i;
|
||||
});
|
||||
|
||||
@ -139,8 +139,8 @@ void tst_qpromise_map::functorArguments()
|
||||
|
||||
void tst_qpromise_map::preserveOrder()
|
||||
{
|
||||
auto p = QtPromise::qPromise(QVector<int>{250, 500, 100}).map([](int v, ...) {
|
||||
return QtPromise::qPromise(v + 1).delay(v);
|
||||
auto p = QtPromise::resolve(QVector<int>{250, 500, 100}).map([](int v, ...) {
|
||||
return QtPromise::resolve(v + 1).delay(v);
|
||||
});
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||
|
@ -8,6 +8,7 @@ SUBDIRS += \
|
||||
finally \
|
||||
map \
|
||||
operators \
|
||||
resolve \
|
||||
tap \
|
||||
tapfail \
|
||||
then \
|
||||
|
4
tests/auto/qtpromise/qpromise/resolve/resolve.pro
Normal file
4
tests/auto/qtpromise/qpromise/resolve/resolve.pro
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = tst_qpromise_resolve
|
||||
SOURCES += $$PWD/tst_resolve.cpp
|
||||
|
||||
include(../../qtpromise.pri)
|
165
tests/auto/qtpromise/qpromise/resolve/tst_resolve.cpp
Normal file
165
tests/auto/qtpromise/qpromise/resolve/tst_resolve.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "../../shared/data.h"
|
||||
#include "../../shared/utils.h"
|
||||
|
||||
// QtPromise
|
||||
#include <QtPromise>
|
||||
|
||||
// Qt
|
||||
#include <QtTest>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
|
||||
using namespace QtPromise;
|
||||
|
||||
class tst_qpromise_resolve : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void value();
|
||||
void noValue();
|
||||
void moveRValue();
|
||||
void copyLValue();
|
||||
void qtSharedPtr();
|
||||
void stdSharedPtr();
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_qpromise_resolve)
|
||||
#include "tst_resolve.moc"
|
||||
|
||||
void tst_qpromise_resolve::value()
|
||||
{
|
||||
int v0 = 42;
|
||||
const int v1 = 42;
|
||||
|
||||
auto p0 = QPromise<int>::resolve(42);
|
||||
auto p1 = QPromise<int>::resolve(v0);
|
||||
auto p2 = QPromise<int>::resolve(v1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
}
|
||||
for (const auto& p : {p0, p1, p2}) {
|
||||
QCOMPARE(waitForValue(p, -1), 42);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_qpromise_resolve::noValue()
|
||||
{
|
||||
auto p = QPromise<void>::resolve();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||
|
||||
QCOMPARE(p.isFulfilled(), true);
|
||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||
}
|
||||
|
||||
void tst_qpromise_resolve::moveRValue()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
{
|
||||
auto p = QtPromise::resolve(Data(42)).wait();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 1);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
void tst_qpromise_resolve::copyLValue()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
{
|
||||
Data value(42);
|
||||
auto p = QtPromise::resolve(value).wait();
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||
}
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 1);
|
||||
QCOMPARE(Data::logs().copy, 1);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_qpromise_resolve::qtSharedPtr()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
QWeakPointer<Data> wptr;
|
||||
|
||||
{
|
||||
QSharedPointer<Data> sptr0(new Data(42));
|
||||
const QSharedPointer<Data> sptr1 = sptr0;
|
||||
|
||||
auto p0 = QPromise<QSharedPointer<Data>>::resolve(QSharedPointer<Data>(new Data(42)));
|
||||
auto p1 = QPromise<QSharedPointer<Data>>::resolve(sptr0);
|
||||
auto p2 = QPromise<QSharedPointer<Data>>::resolve(sptr1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<QSharedPointer<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<QSharedPointer<Data>>>::value));
|
||||
|
||||
QCOMPARE(waitForValue(p1, QSharedPointer<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, QSharedPointer<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.isNull(), false);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.isNull(), true);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
||||
|
||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||
void tst_qpromise_resolve::stdSharedPtr()
|
||||
{
|
||||
Data::logs().reset();
|
||||
|
||||
std::weak_ptr<Data> wptr;
|
||||
|
||||
{
|
||||
std::shared_ptr<Data> sptr0(new Data(42));
|
||||
const std::shared_ptr<Data> sptr1 = sptr0;
|
||||
|
||||
auto p0 = QPromise<std::shared_ptr<Data>>::resolve(std::shared_ptr<Data>(new Data(42)));
|
||||
auto p1 = QPromise<std::shared_ptr<Data>>::resolve(sptr0);
|
||||
auto p2 = QPromise<std::shared_ptr<Data>>::resolve(sptr1);
|
||||
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<std::shared_ptr<Data>>>::value));
|
||||
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<std::shared_ptr<Data>>>::value));
|
||||
|
||||
QCOMPARE(waitForValue(p1, std::shared_ptr<Data>()), sptr0);
|
||||
QCOMPARE(waitForValue(p2, std::shared_ptr<Data>()), sptr1);
|
||||
|
||||
wptr = sptr0;
|
||||
|
||||
QCOMPARE(wptr.use_count(), 4l);
|
||||
QCOMPARE(Data::logs().refs, 2);
|
||||
}
|
||||
|
||||
QCOMPARE(wptr.use_count(), 0l);
|
||||
|
||||
QCOMPARE(Data::logs().ctor, 2);
|
||||
QCOMPARE(Data::logs().copy, 0);
|
||||
QCOMPARE(Data::logs().move, 0);
|
||||
QCOMPARE(Data::logs().refs, 0);
|
||||
}
|
@ -8,7 +8,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||
# Additional warnings and make all warnings into errors
|
||||
# https://github.com/simonbrunel/qtpromise/issues/10
|
||||
gcc:QMAKE_CXXFLAGS += -Werror -Wold-style-cast
|
||||
msvc:QMAKE_CXXFLAGS -= -WX
|
||||
msvc:QMAKE_CXXFLAGS += -WX
|
||||
|
||||
coverage {
|
||||
gcc {
|
||||
@ -21,6 +21,7 @@ coverage {
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/shared/data.h \
|
||||
$$PWD/shared/object.h \
|
||||
$$PWD/shared/utils.h
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
benchmark \
|
||||
deprecations \
|
||||
exceptions \
|
||||
future \
|
||||
helpers \
|
||||
|
76
tests/auto/qtpromise/shared/data.h
Normal file
76
tests/auto/qtpromise/shared/data.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef QTPROMISE_TESTS_AUTO_SHARED_DATA_H
|
||||
#define QTPROMISE_TESTS_AUTO_SHARED_DATA_H
|
||||
|
||||
// STL
|
||||
#include <utility>
|
||||
|
||||
struct Logs {
|
||||
int ctor = 0;
|
||||
int copy = 0;
|
||||
int move = 0;
|
||||
int refs = 0;
|
||||
|
||||
void reset() {
|
||||
ctor = 0;
|
||||
copy = 0;
|
||||
move = 0;
|
||||
refs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Logger
|
||||
{
|
||||
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; }
|
||||
|
||||
public: // STATICS
|
||||
static Logs& logs() { static Logs logs; return logs; }
|
||||
};
|
||||
|
||||
struct Data : public Logger
|
||||
{
|
||||
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
|
||||
// operator, so we need to explicitly define these methods and thus the copy
|
||||
// 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(Data&& other) : Logger(std::forward<Data>(other))
|
||||
{
|
||||
std::swap(m_value, other.m_value);
|
||||
}
|
||||
|
||||
Data& operator=(const Data& other)
|
||||
{
|
||||
Logger::operator=(other);
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Data& operator=(Data&& other)
|
||||
{
|
||||
Logger::operator=(std::forward<Data>(other));
|
||||
std::swap(m_value, other.m_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Data& other) const { return (m_value == other.m_value); }
|
||||
bool operator!=(const Data& other) const { return (m_value != other.m_value); }
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
};
|
||||
|
||||
#endif // QTPROMISE_TESTS_AUTO_SHARED_DATA_H
|
@ -102,7 +102,7 @@ void tst_thread::then()
|
||||
|
||||
int value = -1;
|
||||
QThread* target = nullptr;
|
||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
p.then([&](int res) {
|
||||
target = QThread::currentThread();
|
||||
value = res;
|
||||
@ -125,7 +125,7 @@ void tst_thread::then_void()
|
||||
|
||||
int value = -1;
|
||||
QThread* target = nullptr;
|
||||
qPromise(QtConcurrent::run([&](const QPromise<void>& p) {
|
||||
QtPromise::resolve(QtConcurrent::run([&](const QPromise<void>& p) {
|
||||
p.then([&]() {
|
||||
target = QThread::currentThread();
|
||||
value = 43;
|
||||
@ -148,7 +148,7 @@ void tst_thread::fail()
|
||||
|
||||
QString error;
|
||||
QThread* target = nullptr;
|
||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
p.fail([&](const QString& err) {
|
||||
target = QThread::currentThread();
|
||||
error = err;
|
||||
@ -172,7 +172,7 @@ void tst_thread::finally()
|
||||
|
||||
int value = -1;
|
||||
QThread* target = nullptr;
|
||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||
p.finally([&]() {
|
||||
target = QThread::currentThread();
|
||||
value = 43;
|
||||
|
Reference in New Issue
Block a user