Implement QPromise<Sequence<T>>::map(mapper) (#15)

Iterate over all the promise value (i.e. `Sequence<T>`) and map the sequence to another using the given `mapper` function. Also provide a static helper to directly map values (`QtPromise::map(values, mapper)`).
This commit is contained in:
Simon Brunel
2018-05-26 11:40:51 +02:00
committed by GitHub
parent 4cfe2e54f4
commit 69c07855f4
14 changed files with 474 additions and 0 deletions

View File

@ -1,5 +1,6 @@
TEMPLATE = subdirs
SUBDIRS += \
all \
map \
reject \
resolve

View File

@ -0,0 +1,4 @@
TARGET = tst_helpers_map
SOURCES += $$PWD/tst_map.cpp
include(../../qtpromise.pri)

View File

@ -0,0 +1,151 @@
// Tests
#include "../../shared/utils.h"
// QtPromise
#include <QtPromise>
// Qt
#include <QtTest>
using namespace QtPromise;
class tst_helpers_map : public QObject
{
Q_OBJECT
private Q_SLOTS:
void emptySequence();
void modifyValues();
void convertValues();
void delayedFulfilled();
void delayedRejected();
void functorThrows();
void functorArguments();
void preserveOrder();
void sequenceTypes();
};
QTEST_MAIN(tst_helpers_map)
#include "tst_map.moc"
namespace {
template <class Sequence>
struct SequenceTester
{
static void exec()
{
auto p = QtPromise::map(Sequence{42, 43, 44}, [](int v, ...) {
return QString::number(v + 1);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
}
};
} // anonymous namespace
void tst_helpers_map::emptySequence()
{
auto p = QtPromise::map(QVector<int>{}, [](int v, ...) {
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({}));
}
void tst_helpers_map::modifyValues()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
}
void tst_helpers_map::convertValues()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return QString::number(v + 1);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
}
void tst_helpers_map::delayedFulfilled()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
});
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
}
void tst_helpers_map::delayedRejected()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
return QPromise<int>([&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
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_map::functorThrows()
{
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
if (v == 43) {
throw QString("foo");
}
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForError(p, QString()), QString("foo"));
}
void tst_helpers_map::functorArguments()
{
auto p = QtPromise::map(QVector<int>{42, 42, 42}, [](int v, int i) {
return v * i;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({0, 42, 84}));
}
void tst_helpers_map::preserveOrder()
{
auto p = QtPromise::map(QVector<int>{500, 100, 250}, [](int v, ...) {
return QPromise<int>::resolve(v + 1).delay(v);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({501, 101, 251}));
}
void tst_helpers_map::sequenceTypes()
{
SequenceTester<QList<int>>::exec();
SequenceTester<QVector<int>>::exec();
SequenceTester<std::list<int>>::exec();
SequenceTester<std::vector<int>>::exec();
}

View File

@ -0,0 +1,4 @@
TARGET = tst_qpromise_map
SOURCES += $$PWD/tst_map.cpp
include(../../qtpromise.pri)

View File

@ -0,0 +1,157 @@
// Tests
#include "../../shared/utils.h"
// QtPromise
#include <QtPromise>
// Qt
#include <QtTest>
using namespace QtPromise;
class tst_qpromise_map : public QObject
{
Q_OBJECT
private Q_SLOTS:
void emptySequence();
void modifyValues();
void convertValues();
void delayedFulfilled();
void delayedRejected();
void functorThrows();
void functorArguments();
void preserveOrder();
void sequenceTypes();
};
QTEST_MAIN(tst_qpromise_map)
#include "tst_map.moc"
namespace {
template <class Sequence>
struct SequenceTester
{
static void exec()
{
auto p = QtPromise::qPromise(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));
}).map([](const QString& v, ...) {
return QtPromise::qPromise((v + "!").toUtf8());
}).map([](const QByteArray& v, ...) {
return QString::fromUtf8(v);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"0:43!", "1:44!", "2:45!"}));
}
};
} // anonymous namespace
void tst_qpromise_map::emptySequence()
{
auto p = QtPromise::qPromise(QVector<int>{}).map([](int v, ...) {
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({}));
}
void tst_qpromise_map::modifyValues()
{
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
}
void tst_qpromise_map::convertValues()
{
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
return QString::number(v + 1);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
}
void tst_qpromise_map::delayedFulfilled()
{
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
QtPromisePrivate::qtpromise_defer([=]() {
resolve(v + 1);
});
});
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
}
void tst_qpromise_map::delayedRejected()
{
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](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_qpromise_map::functorThrows()
{
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
if (v == 43) {
throw QString("foo");
}
return v + 1;
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForError(p, QString()), QString("foo"));
}
void tst_qpromise_map::functorArguments()
{
auto p1 = QtPromise::qPromise(QVector<int>{42, 42, 42}).map([](int v, int i) {
return v * i;
});
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p1, QVector<int>()), QVector<int>({0, 42, 84}));
}
void tst_qpromise_map::preserveOrder()
{
auto p = QtPromise::qPromise(QVector<int>{250, 500, 100}).map([](int v, ...) {
return QtPromise::qPromise(v + 1).delay(v);
});
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({251, 501, 101}));
}
void tst_qpromise_map::sequenceTypes()
{
SequenceTester<QList<int>>::exec();
SequenceTester<QVector<int>>::exec();
SequenceTester<std::list<int>>::exec();
SequenceTester<std::vector<int>>::exec();
}

View File

@ -4,6 +4,7 @@ SUBDIRS += \
delay \
fail \
finally \
map \
operators \
tap \
tapfail \