mirror of
https://github.com/simonbrunel/qtpromise.git
synced 2024-11-24 19:50:41 +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:
parent
1f30224578
commit
963ec621e1
@ -51,7 +51,7 @@ module.exports = {
|
|||||||
'qtpromise/helpers/each',
|
'qtpromise/helpers/each',
|
||||||
'qtpromise/helpers/filter',
|
'qtpromise/helpers/filter',
|
||||||
'qtpromise/helpers/map',
|
'qtpromise/helpers/map',
|
||||||
'qtpromise/helpers/qpromise',
|
'qtpromise/helpers/resolve',
|
||||||
'qtpromise/helpers/qpromiseall'
|
'qtpromise/helpers/qpromiseall'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
* [`QtPromise::each`](helpers/each.md)
|
* [`QtPromise::each`](helpers/each.md)
|
||||||
* [`QtPromise::filter`](helpers/filter.md)
|
* [`QtPromise::filter`](helpers/filter.md)
|
||||||
* [`QtPromise::map`](helpers/map.md)
|
* [`QtPromise::map`](helpers/map.md)
|
||||||
* [`qPromise`](helpers/qpromise.md)
|
* [`QtPromise::resolve`](helpers/resolve.md)
|
||||||
* [`qPromiseAll`](helpers/qpromiseall.md)
|
* [`qPromiseAll`](helpers/qpromiseall.md)
|
||||||
|
|
||||||
## Exceptions
|
## Exceptions
|
||||||
@ -39,3 +39,7 @@
|
|||||||
* [`QPromiseCanceledException`](exceptions/canceled.md)
|
* [`QPromiseCanceledException`](exceptions/canceled.md)
|
||||||
* [`QPromiseTimeoutException`](exceptions/timeout.md)
|
* [`QPromiseTimeoutException`](exceptions/timeout.md)
|
||||||
* [`QPromiseUndefinedException`](exceptions/undefined.md)
|
* [`QPromiseUndefinedException`](exceptions/undefined.md)
|
||||||
|
|
||||||
|
## Deprecations
|
||||||
|
|
||||||
|
* `QtPromise::qPromise`: use [`QtPromise::resolve`](helpers/resolve.md) instead (since 0.5.0)
|
||||||
|
@ -9,7 +9,7 @@ title: QPromiseCanceledException
|
|||||||
This exception is thrown for promise created from a [`QFuture`](../qtconcurrent.md) which has been canceled (e.g. using [`QFuture::cancel()`](http://doc.qt.io/qt-5/qfuture.html#cancel)), for example:
|
This exception is thrown for promise created from a [`QFuture`](../qtconcurrent.md) which has been canceled (e.g. using [`QFuture::cancel()`](http://doc.qt.io/qt-5/qfuture.html#cancel)), for example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
auto output = qPromise(future)
|
auto output = QtPromise::resolve(future)
|
||||||
.fail([](const QPromiseCanceledException&) {
|
.fail([](const QPromiseCanceledException&) {
|
||||||
// `future` has been canceled!
|
// `future` has been canceled!
|
||||||
});
|
});
|
||||||
|
@ -56,7 +56,7 @@ The following method `uncompress` data in a separate thread and returns a [promi
|
|||||||
```cpp
|
```cpp
|
||||||
QPromise<Entries> uncompress(const QByteArray& data)
|
QPromise<Entries> uncompress(const QByteArray& data)
|
||||||
{
|
{
|
||||||
return qPromise(QtConcurrent::run([](const QByteArray& data) {
|
return QtPromise::resolve(QtConcurrent::run([](const QByteArray& data) {
|
||||||
Entries entries;
|
Entries entries;
|
||||||
|
|
||||||
// {...} uncompress data and parse content.
|
// {...} uncompress data and parse content.
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
title: qPromise
|
|
||||||
---
|
|
||||||
|
|
||||||
# qPromise
|
|
||||||
|
|
||||||
*Since: 0.1.0*
|
|
||||||
|
|
||||||
```
|
|
||||||
qPromise(T value) -> QPromise<R>
|
|
||||||
```
|
|
||||||
|
|
||||||
Similar to the [`QPromise<T>::resolve`](../qpromise/resolve.md) static method, creates a promise resolved from a given `value` without the extra typing:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
auto promise = qPromise(); // QPromise<void>
|
|
||||||
auto promise = qPromise(42); // QPromise<int>
|
|
||||||
auto promise = qPromise(QString("foo")); // QPromise<QString>
|
|
||||||
```
|
|
||||||
|
|
||||||
This method also allows to convert `QFuture<T>` to `QPromise<T>` delayed until the `QFuture` is finished ([read more](../qtconcurrent.md#convert)).
|
|
21
docs/qtpromise/helpers/resolve.md
Normal file
21
docs/qtpromise/helpers/resolve.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: resolve
|
||||||
|
---
|
||||||
|
|
||||||
|
# QtPromise::resolve
|
||||||
|
|
||||||
|
*Since: 0.5.0*
|
||||||
|
|
||||||
|
```
|
||||||
|
QtPromise::resolve(T value) -> QPromise<R>
|
||||||
|
```
|
||||||
|
|
||||||
|
Similar to the [`QPromise<T>::resolve`](../qpromise/resolve.md) static method, creates a promise resolved from a given `value` but without the extra typing:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto promise = QtPromise::resolve(); // QPromise<void>
|
||||||
|
auto promise = QtPromise::resolve(42); // QPromise<int>
|
||||||
|
auto promise = QtPromise::resolve(QString("foo")); // QPromise<QString>
|
||||||
|
```
|
||||||
|
|
||||||
|
This method also allows to convert `QFuture<T>` to `QPromise<T>`, delayed until the `QFuture` is finished ([read more](../qtconcurrent.md#convert)).
|
@ -25,4 +25,4 @@ QPromise<int> compute(const QString& type)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See also: [`qPromise`](../helpers/qpromise.md)
|
See also: [`QtPromise::resolve`](../helpers/resolve.md)
|
||||||
|
@ -15,7 +15,7 @@ This method holds the execution of the remaining code until the `input` promise
|
|||||||
```cpp
|
```cpp
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
QPromise<int> input = qPromise(QtConcurrent::run([]() {
|
QPromise<int> input = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
return 42;
|
return 42;
|
||||||
})).tap([&](int res) {
|
})).tap([&](int res) {
|
||||||
result = res;
|
result = res;
|
||||||
|
@ -4,7 +4,7 @@ QtPromise integrates with [QtConcurrent](https://doc.qt.io/qt-5/qtconcurrent-ind
|
|||||||
|
|
||||||
## <a name="qtconcurrent-convert"></a> Convert
|
## <a name="qtconcurrent-convert"></a> Convert
|
||||||
|
|
||||||
Converting `QFuture<T>` to `QPromise<T>` is done using the [`qPromise`](helpers/qpromise.md) helper:
|
Converting `QFuture<T>` to `QPromise<T>` is done using the [`QtPromise::resolve`](helpers/resolve.md) helper:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
QFuture<int> future = QtConcurrent::run([]() {
|
QFuture<int> future = QtConcurrent::run([]() {
|
||||||
@ -12,13 +12,13 @@ QFuture<int> future = QtConcurrent::run([]() {
|
|||||||
return 42;
|
return 42;
|
||||||
});
|
});
|
||||||
|
|
||||||
QPromise<int> promise = qPromise(future);
|
QPromise<int> promise = QtPromise::resolve(future);
|
||||||
```
|
```
|
||||||
|
|
||||||
or simply:
|
or simply:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
auto promise = qPromise(QtConcurrent::run([]() {
|
auto promise = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
// {...}
|
// {...}
|
||||||
}));
|
}));
|
||||||
```
|
```
|
||||||
|
@ -279,9 +279,7 @@ inline QPromise<void> QPromise<void>::all(const Sequence<QPromise<void>, Args...
|
|||||||
|
|
||||||
inline QPromise<void> QPromise<void>::resolve()
|
inline QPromise<void> QPromise<void>::resolve()
|
||||||
{
|
{
|
||||||
return QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
return QtPromise::resolve();
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QtPromise
|
} // namespace QtPromise
|
||||||
|
@ -110,9 +110,24 @@ private:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct PromiseDeduce
|
struct PromiseDeduce
|
||||||
{
|
{
|
||||||
using Type = QtPromise::QPromise<Unqualified<T>>;
|
using Type = QtPromise::QPromise<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct PromiseDeduce<T&>
|
||||||
|
: public PromiseDeduce<T>
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct PromiseDeduce<const T>
|
||||||
|
: public PromiseDeduce<T>
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct PromiseDeduce<const volatile T>
|
||||||
|
: public PromiseDeduce<T>
|
||||||
|
{ };
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct PromiseDeduce<QtPromise::QPromise<T>>
|
struct PromiseDeduce<QtPromise::QPromise<T>>
|
||||||
: public PromiseDeduce<T>
|
: public PromiseDeduce<T>
|
||||||
@ -128,22 +143,21 @@ struct PromiseFunctor
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct PromiseFulfill
|
struct PromiseFulfill
|
||||||
{
|
{
|
||||||
static void call(
|
template <typename V, typename TResolve, typename TReject>
|
||||||
T&& value,
|
static void call(V&& value, const TResolve& resolve, const TReject&)
|
||||||
const QtPromise::QPromiseResolve<T>& resolve,
|
|
||||||
const QtPromise::QPromiseReject<T>&)
|
|
||||||
{
|
{
|
||||||
resolve(std::move(value));
|
resolve(std::forward<V>(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct PromiseFulfill<QtPromise::QPromise<T>>
|
struct PromiseFulfill<QtPromise::QPromise<T>>
|
||||||
{
|
{
|
||||||
|
template <typename TResolve, typename TReject>
|
||||||
static void call(
|
static void call(
|
||||||
const QtPromise::QPromise<T>& promise,
|
const QtPromise::QPromise<T>& promise,
|
||||||
const QtPromise::QPromiseResolve<T>& resolve,
|
const TResolve& resolve,
|
||||||
const QtPromise::QPromiseReject<T>& reject)
|
const TReject& reject)
|
||||||
{
|
{
|
||||||
if (promise.isFulfilled()) {
|
if (promise.isFulfilled()) {
|
||||||
resolve(promise.m_d->value());
|
resolve(promise.m_d->value());
|
||||||
|
@ -7,21 +7,34 @@
|
|||||||
namespace QtPromise {
|
namespace QtPromise {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline typename QtPromisePrivate::PromiseDeduce<T>::Type qPromise(T&& value)
|
static inline typename QtPromisePrivate::PromiseDeduce<T>::Type
|
||||||
|
resolve(T&& value)
|
||||||
{
|
{
|
||||||
using namespace QtPromisePrivate;
|
using namespace QtPromisePrivate;
|
||||||
using Promise = typename PromiseDeduce<T>::Type;
|
using PromiseType = typename PromiseDeduce<T>::Type;
|
||||||
return Promise([&](
|
using ValueType = typename PromiseType::Type;
|
||||||
const QPromiseResolve<typename Promise::Type>& resolve,
|
using ResolveType = QPromiseResolve<ValueType>;
|
||||||
const QPromiseReject<typename Promise::Type>& reject) {
|
using RejectType = QPromiseReject<ValueType>;
|
||||||
PromiseFulfill<T>::call(std::forward<T>(value), resolve, reject);
|
|
||||||
|
return PromiseType([&](ResolveType&& resolve, RejectType&& reject) {
|
||||||
|
PromiseFulfill<Unqualified<T>>::call(
|
||||||
|
std::forward<T>(value),
|
||||||
|
std::forward<ResolveType>(resolve),
|
||||||
|
std::forward<RejectType>(reject));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QPromise<void> qPromise()
|
template <typename T>
|
||||||
|
static inline QPromise<T>
|
||||||
|
resolve(QPromise<T> value)
|
||||||
{
|
{
|
||||||
return QPromise<void>([](
|
return std::move(value);
|
||||||
const QPromiseResolve<void>& resolve) {
|
}
|
||||||
|
|
||||||
|
static inline QPromise<void>
|
||||||
|
resolve()
|
||||||
|
{
|
||||||
|
return QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -153,6 +166,17 @@ static inline QPromise<Sequence> filter(const Sequence& values, Functor fn)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATIONS (remove at version 1)
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
Q_DECL_DEPRECATED_X("Use QtPromise::resolve instead")
|
||||||
|
static inline auto
|
||||||
|
qPromise(Args&&... args)
|
||||||
|
-> decltype(QtPromise::resolve(std::forward<Args>(args)...))
|
||||||
|
{
|
||||||
|
return QtPromise::resolve(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QtPromise
|
} // namespace QtPromise
|
||||||
|
|
||||||
#endif // QTPROMISE_QPROMISEHELPERS_H
|
#endif // QTPROMISE_QPROMISEHELPERS_H
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include "../shared/data.h"
|
||||||
|
|
||||||
// QtPromise
|
// QtPromise
|
||||||
#include <QtPromise>
|
#include <QtPromise>
|
||||||
|
|
||||||
@ -20,7 +22,6 @@ class tst_benchmark : public QObject
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void valueResolve();
|
void valueResolve();
|
||||||
void valueResolveStatic();
|
|
||||||
void valueReject();
|
void valueReject();
|
||||||
void valueThen();
|
void valueThen();
|
||||||
void valueFinally();
|
void valueFinally();
|
||||||
@ -34,72 +35,6 @@ private Q_SLOTS:
|
|||||||
QTEST_MAIN(tst_benchmark)
|
QTEST_MAIN(tst_benchmark)
|
||||||
#include "tst_benchmark.moc"
|
#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()
|
void tst_benchmark::valueResolve()
|
||||||
{
|
{
|
||||||
{ // should move the value when resolved by rvalue
|
{ // 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()
|
void tst_benchmark::valueReject()
|
||||||
{
|
{
|
||||||
{ // should not create any data if rejected
|
{ // 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>
|
template <class E>
|
||||||
void verify()
|
void verify()
|
||||||
{
|
{
|
||||||
auto p = qPromise(QtConcurrent::run([]() { throw E(); }));
|
auto p = QtPromise::resolve(QtConcurrent::run([]() { throw E(); }));
|
||||||
QCOMPARE(p.isPending(), true);
|
QCOMPARE(p.isPending(), true);
|
||||||
QCOMPARE(waitForRejected<E>(p), true);
|
QCOMPARE(waitForRejected<E>(p), true);
|
||||||
QCOMPARE(p.isRejected(), true);
|
QCOMPARE(p.isRejected(), true);
|
||||||
|
@ -52,7 +52,7 @@ QTEST_MAIN(tst_future)
|
|||||||
void tst_future::fulfilled()
|
void tst_future::fulfilled()
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
return 42;
|
return 42;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ void tst_future::fulfilled()
|
|||||||
void tst_future::fulfilled_void()
|
void tst_future::fulfilled_void()
|
||||||
{
|
{
|
||||||
int result = -1;
|
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));
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
QCOMPARE(p.isPending(), true);
|
QCOMPARE(p.isPending(), true);
|
||||||
@ -86,7 +86,7 @@ void tst_future::fulfilled_void()
|
|||||||
void tst_future::rejected()
|
void tst_future::rejected()
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
throw MyException("foo");
|
throw MyException("foo");
|
||||||
return 42;
|
return 42;
|
||||||
}));
|
}));
|
||||||
@ -106,7 +106,7 @@ void tst_future::rejected()
|
|||||||
void tst_future::rejected_void()
|
void tst_future::rejected_void()
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
throw MyException("foo");
|
throw MyException("foo");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ void tst_future::rejected_void()
|
|||||||
void tst_future::unhandled()
|
void tst_future::unhandled()
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
throw QString("foo");
|
throw QString("foo");
|
||||||
return 42;
|
return 42;
|
||||||
}));
|
}));
|
||||||
@ -149,7 +149,7 @@ void tst_future::unhandled()
|
|||||||
void tst_future::unhandled_void()
|
void tst_future::unhandled_void()
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
throw QString("foo");
|
throw QString("foo");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ void tst_future::unhandled_void()
|
|||||||
void tst_future::canceled()
|
void tst_future::canceled()
|
||||||
{
|
{
|
||||||
QString error;
|
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);
|
QCOMPARE(p.isPending(), true);
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ void tst_future::canceled()
|
|||||||
void tst_future::canceled_void()
|
void tst_future::canceled_void()
|
||||||
{
|
{
|
||||||
QString error;
|
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);
|
QCOMPARE(p.isPending(), true);
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ void tst_future::canceled_void()
|
|||||||
void tst_future::canceledFromThread()
|
void tst_future::canceledFromThread()
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
auto p = qPromise(QtConcurrent::run([]() {
|
auto p = QtPromise::resolve(QtConcurrent::run([]() {
|
||||||
throw QPromiseCanceledException();
|
throw QPromiseCanceledException();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ void tst_future::canceledFromThread()
|
|||||||
void tst_future::then()
|
void tst_future::then()
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
auto input = qPromise(42);
|
auto input = QtPromise::resolve(42);
|
||||||
auto output = input.then([](int res) {
|
auto output = input.then([](int res) {
|
||||||
return QtConcurrent::run([=]() {
|
return QtConcurrent::run([=]() {
|
||||||
return QString("foo%1").arg(res);
|
return QString("foo%1").arg(res);
|
||||||
@ -238,7 +238,7 @@ void tst_future::then()
|
|||||||
void tst_future::then_void()
|
void tst_future::then_void()
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
auto input = qPromise();
|
auto input = QtPromise::resolve();
|
||||||
auto output = input.then([&]() {
|
auto output = input.then([&]() {
|
||||||
return QtConcurrent::run([&]() {
|
return QtConcurrent::run([&]() {
|
||||||
result = "foo";
|
result = "foo";
|
||||||
@ -300,7 +300,7 @@ void tst_future::fail_void()
|
|||||||
|
|
||||||
void tst_future::finally()
|
void tst_future::finally()
|
||||||
{
|
{
|
||||||
auto input = qPromise(42);
|
auto input = QtPromise::resolve(42);
|
||||||
auto output = input.finally([]() {
|
auto output = input.finally([]() {
|
||||||
return QtConcurrent::run([]() {
|
return QtConcurrent::run([]() {
|
||||||
return QString("foo");
|
return QString("foo");
|
||||||
@ -323,7 +323,7 @@ void tst_future::finally()
|
|||||||
|
|
||||||
void tst_future::finallyRejected()
|
void tst_future::finallyRejected()
|
||||||
{
|
{
|
||||||
auto input = qPromise(42);
|
auto input = QtPromise::resolve(42);
|
||||||
auto output = input.finally([]() {
|
auto output = input.finally([]() {
|
||||||
return QtConcurrent::run([]() {
|
return QtConcurrent::run([]() {
|
||||||
throw MyException("foo");
|
throw MyException("foo");
|
||||||
|
@ -37,13 +37,13 @@ struct SequenceTester
|
|||||||
static void exec()
|
static void exec()
|
||||||
{
|
{
|
||||||
Sequence promises{
|
Sequence promises{
|
||||||
QtPromise::qPromise(42),
|
QtPromise::resolve(42),
|
||||||
QtPromise::qPromise(43),
|
QtPromise::resolve(43),
|
||||||
QtPromise::qPromise(44)
|
QtPromise::resolve(44)
|
||||||
};
|
};
|
||||||
|
|
||||||
promises.push_back(QtPromise::qPromise(45));
|
promises.push_back(QtPromise::resolve(45));
|
||||||
promises.insert(++promises.begin(), QtPromise::qPromise(46));
|
promises.insert(++promises.begin(), QtPromise::resolve(46));
|
||||||
promises.pop_back();
|
promises.pop_back();
|
||||||
|
|
||||||
auto p = QtPromise::qPromiseAll(promises);
|
auto p = QtPromise::qPromiseAll(promises);
|
||||||
@ -60,13 +60,13 @@ struct SequenceTester<Sequence<QPromise<void>, Args...>>
|
|||||||
static void exec()
|
static void exec()
|
||||||
{
|
{
|
||||||
Sequence<QPromise<void>, Args...> promises{
|
Sequence<QPromise<void>, Args...> promises{
|
||||||
QtPromise::qPromise(),
|
QtPromise::resolve(),
|
||||||
QtPromise::qPromise(),
|
QtPromise::resolve(),
|
||||||
QtPromise::qPromise()
|
QtPromise::resolve()
|
||||||
};
|
};
|
||||||
|
|
||||||
promises.push_back(QtPromise::qPromise());
|
promises.push_back(QtPromise::resolve());
|
||||||
promises.insert(++promises.begin(), QtPromise::qPromise());
|
promises.insert(++promises.begin(), QtPromise::resolve());
|
||||||
promises.pop_back();
|
promises.pop_back();
|
||||||
|
|
||||||
auto p = QtPromise::qPromiseAll(promises);
|
auto p = QtPromise::qPromiseAll(promises);
|
||||||
@ -99,8 +99,8 @@ void tst_helpers_all::emptySequence_void()
|
|||||||
|
|
||||||
void tst_helpers_all::allPromisesSucceed()
|
void tst_helpers_all::allPromisesSucceed()
|
||||||
{
|
{
|
||||||
auto p0 = QtPromise::qPromise(42);
|
auto p0 = QtPromise::resolve(42);
|
||||||
auto p1 = QtPromise::qPromise(44);
|
auto p1 = QtPromise::resolve(44);
|
||||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>& resolve) {
|
auto p2 = QPromise<int>([](const QPromiseResolve<int>& resolve) {
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
resolve(43);
|
resolve(43);
|
||||||
@ -120,8 +120,8 @@ void tst_helpers_all::allPromisesSucceed()
|
|||||||
|
|
||||||
void tst_helpers_all::allPromisesSucceed_void()
|
void tst_helpers_all::allPromisesSucceed_void()
|
||||||
{
|
{
|
||||||
auto p0 = QtPromise::qPromise();
|
auto p0 = QtPromise::resolve();
|
||||||
auto p1 = QtPromise::qPromise();
|
auto p1 = QtPromise::resolve();
|
||||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
auto p2 = QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
resolve();
|
resolve();
|
||||||
@ -141,8 +141,8 @@ void tst_helpers_all::allPromisesSucceed_void()
|
|||||||
|
|
||||||
void tst_helpers_all::atLeastOnePromiseReject()
|
void tst_helpers_all::atLeastOnePromiseReject()
|
||||||
{
|
{
|
||||||
auto p0 = QtPromise::qPromise(42);
|
auto p0 = QtPromise::resolve(42);
|
||||||
auto p1 = QtPromise::qPromise(44);
|
auto p1 = QtPromise::resolve(44);
|
||||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
|
auto p2 = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
reject(QString("foo"));
|
reject(QString("foo"));
|
||||||
@ -162,8 +162,8 @@ void tst_helpers_all::atLeastOnePromiseReject()
|
|||||||
|
|
||||||
void tst_helpers_all::atLeastOnePromiseReject_void()
|
void tst_helpers_all::atLeastOnePromiseReject_void()
|
||||||
{
|
{
|
||||||
auto p0 = QtPromise::qPromise();
|
auto p0 = QtPromise::resolve();
|
||||||
auto p1 = QtPromise::qPromise();
|
auto p1 = QtPromise::resolve();
|
||||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
|
auto p2 = QPromise<void>([](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
reject(QString("foo"));
|
reject(QString("foo"));
|
||||||
@ -183,9 +183,9 @@ void tst_helpers_all::atLeastOnePromiseReject_void()
|
|||||||
|
|
||||||
void tst_helpers_all::preserveOrder()
|
void tst_helpers_all::preserveOrder()
|
||||||
{
|
{
|
||||||
auto p0 = QtPromise::qPromise(42).delay(500);
|
auto p0 = QtPromise::resolve(42).delay(500);
|
||||||
auto p1 = QtPromise::qPromise(43).delay(100);
|
auto p1 = QtPromise::resolve(43).delay(100);
|
||||||
auto p2 = QtPromise::qPromise(44).delay(250);
|
auto p2 = QtPromise::resolve(44).delay(250);
|
||||||
|
|
||||||
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p1, p2});
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p1, p2});
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ void tst_helpers_attempt::futureResult()
|
|||||||
void tst_helpers_attempt::promiseResult()
|
void tst_helpers_attempt::promiseResult()
|
||||||
{
|
{
|
||||||
auto p = QtPromise::attempt([]() {
|
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));
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
QT += concurrent
|
||||||
TARGET = tst_helpers_resolve
|
TARGET = tst_helpers_resolve
|
||||||
SOURCES += $$PWD/tst_resolve.cpp
|
SOURCES += $$PWD/tst_resolve.cpp
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
#include "../../shared/data.h"
|
||||||
#include "../../shared/utils.h"
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
// QtPromise
|
// QtPromise
|
||||||
#include <QtPromise>
|
#include <QtPromise>
|
||||||
|
|
||||||
// Qt
|
// Qt
|
||||||
|
#include <QtConcurrent>
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
|
|
||||||
// STL
|
// STL
|
||||||
@ -16,109 +18,251 @@ class tst_helpers_resolve : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void resolveWithValue();
|
void value();
|
||||||
void resolveWithNoValue();
|
void noValue();
|
||||||
void resolveWithTypedPromise();
|
void moveRValue();
|
||||||
void resolveWithVoidPromise();
|
void copyLValue();
|
||||||
void resolveWithQSharedPtr();
|
void qtSharedPtr();
|
||||||
void resolveWithStdSharedPtr();
|
void stdSharedPtr();
|
||||||
|
void typedPromise();
|
||||||
|
void voidPromise();
|
||||||
|
void typedFuture();
|
||||||
|
void voidFuture();
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_MAIN(tst_helpers_resolve)
|
QTEST_MAIN(tst_helpers_resolve)
|
||||||
#include "tst_resolve.moc"
|
#include "tst_resolve.moc"
|
||||||
|
|
||||||
void tst_helpers_resolve::resolveWithValue()
|
void tst_helpers_resolve::value()
|
||||||
{
|
{
|
||||||
const int value = 42;
|
int v0 = 42;
|
||||||
auto p0 = QPromise<int>::resolve(value);
|
const int v1 = 42;
|
||||||
auto p1 = QPromise<int>::resolve(43);
|
|
||||||
|
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(p0), QPromise<int>>::value));
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
Q_STATIC_ASSERT((std::is_same<decltype(p2), QPromise<int>>::value));
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
|
||||||
QCOMPARE(waitForValue(p0, -1), 42);
|
for (const auto& p : {p0, p1, p2}) {
|
||||||
QCOMPARE(waitForValue(p1, -1), 43);
|
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));
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_helpers_resolve::resolveWithTypedPromise()
|
void tst_helpers_resolve::moveRValue()
|
||||||
{
|
{
|
||||||
auto p = QtPromise::qPromise(
|
Data::logs().reset();
|
||||||
QPromise<QString>([](const QPromiseResolve<QString>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
resolve("foo");
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
{
|
||||||
|
auto p = QtPromise::resolve(Data(42)).wait();
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||||
QCOMPARE(waitForValue(p, QString()), QString("foo"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_helpers_resolve::resolveWithVoidPromise()
|
QCOMPARE(Data::logs().ctor, 1);
|
||||||
|
QCOMPARE(Data::logs().copy, 0);
|
||||||
|
QCOMPARE(Data::logs().move, 1);
|
||||||
|
QCOMPARE(Data::logs().refs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_resolve::copyLValue()
|
||||||
{
|
{
|
||||||
int check;
|
Data::logs().reset();
|
||||||
auto p = QtPromise::qPromise(
|
|
||||||
QPromise<void>([&](const QPromiseResolve<void>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=, &check](){
|
|
||||||
check = 8;
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
{
|
||||||
|
Data value(42);
|
||||||
|
auto p = QtPromise::resolve(value).wait();
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Data>>::value));
|
||||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
}
|
||||||
QCOMPARE(check, 8);
|
|
||||||
|
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
|
// 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));
|
QSharedPointer<Data> sptr0(new Data(42));
|
||||||
auto p = QPromise<QSharedPointer<int>>::resolve(sptr);
|
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;
|
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<QSharedPointer<Data>>>::value));
|
||||||
sptr.reset();
|
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(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
|
// 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));
|
std::shared_ptr<Data> sptr0(new Data(42));
|
||||||
auto p = QPromise<std::shared_ptr<int>>::resolve(sptr);
|
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;
|
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<std::shared_ptr<Data>>>::value));
|
||||||
sptr.reset();
|
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(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()
|
static void exec()
|
||||||
{
|
{
|
||||||
QVector<int> values;
|
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;
|
values << i << v;
|
||||||
}).each([&](int v, ...) {
|
}).each([&](int v, ...) {
|
||||||
values << v;
|
values << v;
|
||||||
return QString("foo");
|
return QString("foo");
|
||||||
}).each([&](int v, ...) {
|
}).each([&](int v, ...) {
|
||||||
values << v + 1;
|
values << v + 1;
|
||||||
return QPromise<QString>::resolve(QString("foo")).then([&](){
|
return QtPromise::resolve(QString("foo")).then([&](){
|
||||||
values << -1;
|
values << -1;
|
||||||
});
|
});
|
||||||
}).each([&](int v, ...) {
|
}).each([&](int v, ...) {
|
||||||
|
@ -33,7 +33,7 @@ struct SequenceTester
|
|||||||
{
|
{
|
||||||
static void exec()
|
static void exec()
|
||||||
{
|
{
|
||||||
auto p = QtPromise::qPromise(Sequence{
|
auto p = QtPromise::resolve(Sequence{
|
||||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||||
}).filter([](int v, ...) {
|
}).filter([](int v, ...) {
|
||||||
return v > 42 && v < 51;
|
return v > 42 && v < 51;
|
||||||
|
@ -34,12 +34,12 @@ struct SequenceTester
|
|||||||
{
|
{
|
||||||
static void exec()
|
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);
|
return QString::number(v + 1);
|
||||||
}).map([](const QString& v, int i) {
|
}).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, ...) {
|
}).map([](const QString& v, ...) {
|
||||||
return QtPromise::qPromise((v + "!").toUtf8());
|
return QtPromise::resolve((v + "!").toUtf8());
|
||||||
}).map([](const QByteArray& v, ...) {
|
}).map([](const QByteArray& v, ...) {
|
||||||
return QString::fromUtf8(v);
|
return QString::fromUtf8(v);
|
||||||
});
|
});
|
||||||
@ -53,7 +53,7 @@ struct SequenceTester
|
|||||||
|
|
||||||
void tst_qpromise_map::emptySequence()
|
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;
|
return v + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ void tst_qpromise_map::emptySequence()
|
|||||||
|
|
||||||
void tst_qpromise_map::modifyValues()
|
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;
|
return v + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ void tst_qpromise_map::modifyValues()
|
|||||||
|
|
||||||
void tst_qpromise_map::convertValues()
|
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);
|
return QString::number(v + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ void tst_qpromise_map::convertValues()
|
|||||||
|
|
||||||
void tst_qpromise_map::delayedFulfilled()
|
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) {
|
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
|
||||||
QtPromisePrivate::qtpromise_defer([=]() {
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
resolve(v + 1);
|
resolve(v + 1);
|
||||||
@ -97,7 +97,7 @@ void tst_qpromise_map::delayedFulfilled()
|
|||||||
|
|
||||||
void tst_qpromise_map::delayedRejected()
|
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>([&](
|
return QPromise<int>([&](
|
||||||
const QPromiseResolve<int>& resolve,
|
const QPromiseResolve<int>& resolve,
|
||||||
const QPromiseReject<int>& reject) {
|
const QPromiseReject<int>& reject) {
|
||||||
@ -116,7 +116,7 @@ void tst_qpromise_map::delayedRejected()
|
|||||||
|
|
||||||
void tst_qpromise_map::functorThrows()
|
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) {
|
if (v == 43) {
|
||||||
throw QString("foo");
|
throw QString("foo");
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ void tst_qpromise_map::functorThrows()
|
|||||||
|
|
||||||
void tst_qpromise_map::functorArguments()
|
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;
|
return v * i;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ void tst_qpromise_map::functorArguments()
|
|||||||
|
|
||||||
void tst_qpromise_map::preserveOrder()
|
void tst_qpromise_map::preserveOrder()
|
||||||
{
|
{
|
||||||
auto p = QtPromise::qPromise(QVector<int>{250, 500, 100}).map([](int v, ...) {
|
auto p = QtPromise::resolve(QVector<int>{250, 500, 100}).map([](int v, ...) {
|
||||||
return QtPromise::qPromise(v + 1).delay(v);
|
return QtPromise::resolve(v + 1).delay(v);
|
||||||
});
|
});
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
@ -8,6 +8,7 @@ SUBDIRS += \
|
|||||||
finally \
|
finally \
|
||||||
map \
|
map \
|
||||||
operators \
|
operators \
|
||||||
|
resolve \
|
||||||
tap \
|
tap \
|
||||||
tapfail \
|
tapfail \
|
||||||
then \
|
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
|
# Additional warnings and make all warnings into errors
|
||||||
# https://github.com/simonbrunel/qtpromise/issues/10
|
# https://github.com/simonbrunel/qtpromise/issues/10
|
||||||
gcc:QMAKE_CXXFLAGS += -Werror -Wold-style-cast
|
gcc:QMAKE_CXXFLAGS += -Werror -Wold-style-cast
|
||||||
msvc:QMAKE_CXXFLAGS -= -WX
|
msvc:QMAKE_CXXFLAGS += -WX
|
||||||
|
|
||||||
coverage {
|
coverage {
|
||||||
gcc {
|
gcc {
|
||||||
@ -21,6 +21,7 @@ coverage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$PWD/shared/data.h \
|
||||||
$$PWD/shared/object.h \
|
$$PWD/shared/object.h \
|
||||||
$$PWD/shared/utils.h
|
$$PWD/shared/utils.h
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
benchmark \
|
benchmark \
|
||||||
|
deprecations \
|
||||||
exceptions \
|
exceptions \
|
||||||
future \
|
future \
|
||||||
helpers \
|
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;
|
int value = -1;
|
||||||
QThread* target = nullptr;
|
QThread* target = nullptr;
|
||||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||||
p.then([&](int res) {
|
p.then([&](int res) {
|
||||||
target = QThread::currentThread();
|
target = QThread::currentThread();
|
||||||
value = res;
|
value = res;
|
||||||
@ -125,7 +125,7 @@ void tst_thread::then_void()
|
|||||||
|
|
||||||
int value = -1;
|
int value = -1;
|
||||||
QThread* target = nullptr;
|
QThread* target = nullptr;
|
||||||
qPromise(QtConcurrent::run([&](const QPromise<void>& p) {
|
QtPromise::resolve(QtConcurrent::run([&](const QPromise<void>& p) {
|
||||||
p.then([&]() {
|
p.then([&]() {
|
||||||
target = QThread::currentThread();
|
target = QThread::currentThread();
|
||||||
value = 43;
|
value = 43;
|
||||||
@ -148,7 +148,7 @@ void tst_thread::fail()
|
|||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
QThread* target = nullptr;
|
QThread* target = nullptr;
|
||||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||||
p.fail([&](const QString& err) {
|
p.fail([&](const QString& err) {
|
||||||
target = QThread::currentThread();
|
target = QThread::currentThread();
|
||||||
error = err;
|
error = err;
|
||||||
@ -172,7 +172,7 @@ void tst_thread::finally()
|
|||||||
|
|
||||||
int value = -1;
|
int value = -1;
|
||||||
QThread* target = nullptr;
|
QThread* target = nullptr;
|
||||||
qPromise(QtConcurrent::run([&](const QPromise<int>& p) {
|
QtPromise::resolve(QtConcurrent::run([&](const QPromise<int>& p) {
|
||||||
p.finally([&]() {
|
p.finally([&]() {
|
||||||
target = QThread::currentThread();
|
target = QThread::currentThread();
|
||||||
value = 43;
|
value = 43;
|
||||||
|
Loading…
Reference in New Issue
Block a user