mirror of
https://github.com/simonbrunel/qtpromise.git
synced 2024-11-22 02:34:30 +08:00
Implement QPromise<Sequence<T>>::each(functor)
Call the given `functor` on each element in the promise value (i.e. `Sequence<T>`), then resolve to the original sequence unmodified. Also provide a static helper to directly filter values (`QtPromise::each(values, functor)`).
This commit is contained in:
parent
f610826ef0
commit
051fed5fbc
@ -5,6 +5,7 @@
|
|||||||
* [API Reference](qtpromise/api-reference.md)
|
* [API Reference](qtpromise/api-reference.md)
|
||||||
* [QPromise](qtpromise/qpromise/constructor.md)
|
* [QPromise](qtpromise/qpromise/constructor.md)
|
||||||
* [.delay](qtpromise/qpromise/delay.md)
|
* [.delay](qtpromise/qpromise/delay.md)
|
||||||
|
* [.each](qtpromise/qpromise/each.md)
|
||||||
* [.fail](qtpromise/qpromise/fail.md)
|
* [.fail](qtpromise/qpromise/fail.md)
|
||||||
* [.filter](qtpromise/qpromise/filter.md)
|
* [.filter](qtpromise/qpromise/filter.md)
|
||||||
* [.finally](qtpromise/qpromise/finally.md)
|
* [.finally](qtpromise/qpromise/finally.md)
|
||||||
@ -23,5 +24,6 @@
|
|||||||
* [qPromise](qtpromise/helpers/qpromise.md)
|
* [qPromise](qtpromise/helpers/qpromise.md)
|
||||||
* [qPromiseAll](qtpromise/helpers/qpromiseall.md)
|
* [qPromiseAll](qtpromise/helpers/qpromiseall.md)
|
||||||
* [QtPromise::attempt](qtpromise/helpers/attempt.md)
|
* [QtPromise::attempt](qtpromise/helpers/attempt.md)
|
||||||
|
* [QtPromise::each](qtpromise/helpers/each.md)
|
||||||
* [QtPromise::filter](qtpromise/helpers/filter.md)
|
* [QtPromise::filter](qtpromise/helpers/filter.md)
|
||||||
* [QtPromise::map](qtpromise/helpers/map.md)
|
* [QtPromise::map](qtpromise/helpers/map.md)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
* [`QPromise<T>::QPromise`](qpromise/constructor.md)
|
* [`QPromise<T>::QPromise`](qpromise/constructor.md)
|
||||||
* [`QPromise<T>::delay`](qpromise/delay.md)
|
* [`QPromise<T>::delay`](qpromise/delay.md)
|
||||||
|
* [`QPromise<T>::each`](qpromise/each.md)
|
||||||
* [`QPromise<T>::fail`](qpromise/fail.md)
|
* [`QPromise<T>::fail`](qpromise/fail.md)
|
||||||
* [`QPromise<T>::filter`](qpromise/filter.md)
|
* [`QPromise<T>::filter`](qpromise/filter.md)
|
||||||
* [`QPromise<T>::finally`](qpromise/finally.md)
|
* [`QPromise<T>::finally`](qpromise/finally.md)
|
||||||
@ -28,5 +29,6 @@
|
|||||||
* [`qPromise`](helpers/qpromise.md)
|
* [`qPromise`](helpers/qpromise.md)
|
||||||
* [`qPromiseAll`](helpers/qpromiseall.md)
|
* [`qPromiseAll`](helpers/qpromiseall.md)
|
||||||
* [`QtPromise::attempt`](helpers/attempt.md)
|
* [`QtPromise::attempt`](helpers/attempt.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)
|
||||||
|
39
docs/qtpromise/helpers/each.md
Normal file
39
docs/qtpromise/helpers/each.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
## `QtPromise::each`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QtPromise::each(Sequence<T> values, Functor functor) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Functor: Function(T value, int index) -> void | QPromise<void>
|
||||||
|
```
|
||||||
|
|
||||||
|
Calls the given `functor` on each element in `values` then resolves to the original sequence
|
||||||
|
unmodified. If `functor` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fail, `output` immediately rejects with the error
|
||||||
|
of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto output = QtPromise::each(QVector<QUrl>{
|
||||||
|
QUrl("http://a..."),
|
||||||
|
QUrl("http://b..."),
|
||||||
|
QUrl("http://c...")
|
||||||
|
}, [](const QUrl& url, ...) {
|
||||||
|
return QPromise<void>([&](auto resolve, auto reject) {
|
||||||
|
// process url asynchronously ...
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// `output` resolves as soon as all promises returned by
|
||||||
|
// `functor` are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// output type: QPromise<QVector<QUrl>>
|
||||||
|
output.then([](const QVector<QUrl>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [`QPromise<T>::each`](../qpromise/each.md)
|
48
docs/qtpromise/qpromise/each.md
Normal file
48
docs/qtpromise/qpromise/each.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
## `QPromise<Sequence<T>>::each`
|
||||||
|
|
||||||
|
> **Important:** applies only to promise with sequence value.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<Sequence<T>>::each(Functor functor) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container
|
||||||
|
// - Functor: Function(T value, int index) -> any
|
||||||
|
```
|
||||||
|
|
||||||
|
Calls the given `functor` on each element in the promise value (i.e. `Sequence<T>`), then resolves to the original sequence unmodified. If `functor` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QByteArray>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.each([](const QByteArray& value, int index) {
|
||||||
|
// process value ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// output type: QPromise<QList<QByteArray>>
|
||||||
|
output.then([](const QList<QByteArray>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QUrl>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.each([](const QUrl& url, ...) {
|
||||||
|
return QPromise<void>([&](auto resolve, auto reject) {
|
||||||
|
// process url asynchronously ...
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// `output` resolves as soon as all promises returned by
|
||||||
|
// `functor` are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// output type: QPromise<QList<QUrl>>
|
||||||
|
output.then([](const QList<QUrl>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [`QtPromise::each`](../helpers/each.md)
|
@ -88,6 +88,9 @@ public:
|
|||||||
template <typename F>
|
template <typename F>
|
||||||
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
||||||
|
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> each(Functor fn);
|
||||||
|
|
||||||
template <typename Functor>
|
template <typename Functor>
|
||||||
inline QPromise<T> filter(Functor fn);
|
inline QPromise<T> filter(Functor fn);
|
||||||
|
|
||||||
|
@ -155,6 +155,29 @@ inline QPromise<T> QPromiseBase<T>::reject(E&& error)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> QPromise<T>::each(Functor fn)
|
||||||
|
{
|
||||||
|
return this->tap([=](const T& values) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
std::vector<QPromise<void>> promises;
|
||||||
|
for (const auto& v : values) {
|
||||||
|
promises.push_back(
|
||||||
|
QtPromise::attempt(fn, v, i)
|
||||||
|
.then([]() {
|
||||||
|
// Cast to void in case fn returns a non promise value.
|
||||||
|
// TODO remove when implicit cast is implemented.
|
||||||
|
}));
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPromise<void>::all(promises);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename Functor>
|
template <typename Functor>
|
||||||
inline QPromise<T> QPromise<T>::filter(Functor fn)
|
inline QPromise<T> QPromise<T>::filter(Functor fn)
|
||||||
|
@ -64,6 +64,12 @@ attempt(Functor&& fn, Args&&... args)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Sequence, typename Functor>
|
||||||
|
static inline QPromise<Sequence> each(const Sequence& values, Functor&& fn)
|
||||||
|
{
|
||||||
|
return QPromise<Sequence>::resolve(values).each(std::forward<Functor>(fn));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Sequence, typename Functor>
|
template <typename Sequence, typename Functor>
|
||||||
static inline typename QtPromisePrivate::PromiseMapper<Sequence, Functor>::PromiseType
|
static inline typename QtPromisePrivate::PromiseMapper<Sequence, Functor>::PromiseType
|
||||||
map(const Sequence& values, Functor fn)
|
map(const Sequence& values, Functor fn)
|
||||||
|
4
tests/auto/qtpromise/helpers/each/each.pro
Normal file
4
tests/auto/qtpromise/helpers/each/each.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_each
|
||||||
|
SOURCES += $$PWD/tst_each.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
154
tests/auto/qtpromise/helpers/each/tst_each.cpp
Normal file
154
tests/auto/qtpromise/helpers/each/tst_each.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_each : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void preserveValues();
|
||||||
|
void ignoreResult();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_each)
|
||||||
|
#include "tst_each.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(Sequence{42, 43, 44}, [&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_helpers_each::emptySequence()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{}, [&](int v, ...) {
|
||||||
|
values << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>());
|
||||||
|
QCOMPARE(values, QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::preserveValues()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::ignoreResult()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
return "Foo";
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::delayedFulfilled()
|
||||||
|
{
|
||||||
|
QMap<int, int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, int index) {
|
||||||
|
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=, &values]() {
|
||||||
|
values[v] = index;
|
||||||
|
resolve(42);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 43) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
if (v == 44) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::functorArguments()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
@ -2,6 +2,7 @@ TEMPLATE = subdirs
|
|||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
all \
|
all \
|
||||||
attempt \
|
attempt \
|
||||||
|
each \
|
||||||
filter \
|
filter \
|
||||||
map \
|
map \
|
||||||
reject \
|
reject \
|
||||||
|
4
tests/auto/qtpromise/qpromise/each/each.pro
Normal file
4
tests/auto/qtpromise/qpromise/each/each.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_each
|
||||||
|
SOURCES += $$PWD/tst_each.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
170
tests/auto/qtpromise/qpromise/each/tst_each.cpp
Normal file
170
tests/auto/qtpromise/qpromise/each/tst_each.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_qpromise_each : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void preserveValues();
|
||||||
|
void ignoreResult();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qpromise_each)
|
||||||
|
#include "tst_each.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::qPromise(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([&](){
|
||||||
|
values << -1;
|
||||||
|
});
|
||||||
|
}).each([&](int v, ...) {
|
||||||
|
values << v + 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({42, 43, 44}));
|
||||||
|
|
||||||
|
QVector<int> expected{
|
||||||
|
0, 42, 1, 43, 2, 44,
|
||||||
|
42, 43, 44,
|
||||||
|
43, 44, 45,
|
||||||
|
-1, -1, -1,
|
||||||
|
44, 45, 46
|
||||||
|
};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_qpromise_each::emptySequence()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({}).each([&](int v, ...) {
|
||||||
|
values << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>());
|
||||||
|
QCOMPARE(values, QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::preserveValues()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::ignoreResult()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
return "Foo";
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::delayedFulfilled()
|
||||||
|
{
|
||||||
|
QMap<int, int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, int index) {
|
||||||
|
return QPromise<void>::resolve().delay(250).then([=, &values]() {
|
||||||
|
values[v] = index;
|
||||||
|
return 42;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 44) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([](int v, ...) {
|
||||||
|
if (v == 44) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::functorArguments()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
@ -2,6 +2,7 @@ TEMPLATE = subdirs
|
|||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
construct \
|
construct \
|
||||||
delay \
|
delay \
|
||||||
|
each \
|
||||||
fail \
|
fail \
|
||||||
filter \
|
filter \
|
||||||
finally \
|
finally \
|
||||||
|
Loading…
Reference in New Issue
Block a user