Files
qt-creator/tests/auto/runextensions/tst_runextensions.cpp

541 lines
18 KiB
C++
Raw Normal View History

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <utils/runextensions.h>
#include <QtTest>
#if !defined(Q_CC_MSVC) || _MSC_VER >= 1900 // MSVC2015
#define SUPPORTS_MOVE
#endif
class tst_RunExtensions : public QObject
{
Q_OBJECT
private slots:
void runAsync();
void runInThreadPool();
#ifdef SUPPORTS_MOVE
void moveOnlyType();
#endif
void threadPriority();
void runAsyncNoFutureInterface();
void crefFunction();
};
void report3(QFutureInterface<int> &fi)
{
fi.reportResults({0, 2, 1});
}
void reportN(QFutureInterface<double> &fi, int n)
{
fi.reportResults(QVector<double>(n, 0));
}
void reportString1(QFutureInterface<QString> &fi, const QString &s)
{
fi.reportResult(s);
}
void reportString2(QFutureInterface<QString> &fi, QString s)
{
fi.reportResult(s);
}
class Callable {
public:
void operator()(QFutureInterface<double> &fi, int n) const
{
fi.reportResults(QVector<double>(n, 0));
}
};
class MyObject {
public:
static void staticMember0(QFutureInterface<double> &fi)
{
fi.reportResults({0, 2, 1});
}
static void staticMember1(QFutureInterface<double> &fi, int n)
{
fi.reportResults(QVector<double>(n, 0));
}
void member0(QFutureInterface<double> &fi) const
{
fi.reportResults({0, 2, 1});
}
void member1(QFutureInterface<double> &fi, int n) const
{
fi.reportResults(QVector<double>(n, 0));
}
void memberString1(QFutureInterface<QString> &fi, const QString &s) const
{
fi.reportResult(s);
}
void memberString2(QFutureInterface<QString> &fi, QString s) const
{
fi.reportResult(s);
}
void nonConstMember(QFutureInterface<double> &fi)
{
fi.reportResults({0, 2, 1});
}
};
void voidFunction(bool *value) // can be useful to get QFuture for watching when it is finished
{
*value = true;
}
int one()
{
return 1;
}
int identity(int input)
{
return input;
}
QString stringIdentity1(const QString &s)
{
return s;
}
QString stringIdentity2(QString s)
{
return s;
}
class CallableWithoutQFutureInterface {
public:
void operator()(bool *value) const
{
*value = true;
}
};
class MyObjectWithoutQFutureInterface {
public:
static void staticMember0(bool *value)
{
*value = true;
}
static double staticMember1(int n)
{
return n;
}
void member0(bool *value) const
{
*value = true;
}
double member1(int n) const
{
return n;
}
QString memberString1(const QString &s) const
{
return s;
}
QString memberString2(QString s) const
{
return s;
}
double nonConstMember(int n)
{
return n;
}
};
void tst_RunExtensions::runAsync()
{
// free function pointer
QCOMPARE(Utils::runAsync(&report3).results(),
QList<int>({0, 2, 1}));
QCOMPARE(Utils::runAsync(report3).results(),
QList<int>({0, 2, 1}));
QCOMPARE(Utils::runAsync(reportN, 4).results(),
QList<double>({0, 0, 0, 0}));
QCOMPARE(Utils::runAsync(reportN, 2).results(),
QList<double>({0, 0}));
QString s = QLatin1String("string");
const QString &crs = QLatin1String("cr string");
const QString cs = QLatin1String("c string");
QCOMPARE(Utils::runAsync(reportString1, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(reportString1, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(reportString1, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(reportString1, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(reportString2, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(reportString2, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(reportString2, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(reportString2, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
// lambda
QCOMPARE(Utils::runAsync([](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
}, 3).results(),
QList<double>({0, 0, 0}));
// std::function
const std::function<void(QFutureInterface<double>&,int)> fun = [](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
};
QCOMPARE(Utils::runAsync(fun, 2).results(),
QList<double>({0, 0}));
// operator()
QCOMPARE(Utils::runAsync(Callable(), 3).results(),
QList<double>({0, 0, 0}));
const Callable c{};
QCOMPARE(Utils::runAsync(c, 2).results(),
QList<double>({0, 0}));
// static member functions
QCOMPARE(Utils::runAsync(&MyObject::staticMember0).results(),
QList<double>({0, 2, 1}));
QCOMPARE(Utils::runAsync(&MyObject::staticMember1, 2).results(),
QList<double>({0, 0}));
// member functions
const MyObject obj{};
QCOMPARE(Utils::runAsync(&MyObject::member0, &obj).results(),
QList<double>({0, 2, 1}));
QCOMPARE(Utils::runAsync(&MyObject::member1, &obj, 4).results(),
QList<double>({0, 0, 0, 0}));
QCOMPARE(Utils::runAsync(&MyObject::memberString1, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(&MyObject::memberString1, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(&MyObject::memberString1, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(&MyObject::memberString1, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(&MyObject::memberString2, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(&MyObject::memberString2, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(&MyObject::memberString2, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(&MyObject::memberString2, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
MyObject nonConstObj{};
QCOMPARE(Utils::runAsync(&MyObject::nonConstMember, &nonConstObj).results(),
QList<double>({0, 2, 1}));
}
void tst_RunExtensions::runInThreadPool()
{
QScopedPointer<QThreadPool> pool(new QThreadPool);
// free function pointer
QCOMPARE(Utils::runAsync(pool.data(), &report3).results(),
QList<int>({0, 2, 1}));
QCOMPARE(Utils::runAsync(pool.data(), report3).results(),
QList<int>({0, 2, 1}));
QCOMPARE(Utils::runAsync(pool.data(), reportN, 4).results(),
QList<double>({0, 0, 0, 0}));
QCOMPARE(Utils::runAsync(pool.data(), reportN, 2).results(),
QList<double>({0, 0}));
QString s = QLatin1String("string");
const QString &crs = QLatin1String("cr string");
const QString cs = QLatin1String("c string");
QCOMPARE(Utils::runAsync(pool.data(), reportString1, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(pool.data(), reportString1, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(pool.data(), reportString1, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(pool.data(), reportString1, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(pool.data(), reportString2, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(pool.data(), reportString2, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(pool.data(), reportString2, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(pool.data(), reportString2, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
// lambda
QCOMPARE(Utils::runAsync(pool.data(), [](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
}, 3).results(),
QList<double>({0, 0, 0}));
// std::function
const std::function<void(QFutureInterface<double>&,int)> fun = [](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
};
QCOMPARE(Utils::runAsync(pool.data(), fun, 2).results(),
QList<double>({0, 0}));
// operator()
QCOMPARE(Utils::runAsync(pool.data(), Callable(), 3).results(),
QList<double>({0, 0, 0}));
const Callable c{};
QCOMPARE(Utils::runAsync(pool.data(), c, 2).results(),
QList<double>({0, 0}));
// static member functions
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::staticMember0).results(),
QList<double>({0, 2, 1}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::staticMember1, 2).results(),
QList<double>({0, 0}));
// member functions
const MyObject obj{};
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::member0, &obj).results(),
QList<double>({0, 2, 1}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::member1, &obj, 4).results(),
QList<double>({0, 0, 0, 0}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString1, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString1, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString1, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString1, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString2, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString2, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString2, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(pool.data(), &MyObject::memberString2, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
}
#ifdef SUPPORTS_MOVE
class MoveOnlyType
{
public:
MoveOnlyType() = default;
MoveOnlyType(const MoveOnlyType &) = delete;
MoveOnlyType(MoveOnlyType &&) = default;
MoveOnlyType &operator=(const MoveOnlyType &) = delete;
MoveOnlyType &operator=(MoveOnlyType &&) = default;
};
class MoveOnlyCallable : public MoveOnlyType
{
public:
void operator()(QFutureInterface<int> &fi, const MoveOnlyType &)
{
fi.reportResult(1);
}
};
void tst_RunExtensions::moveOnlyType()
{
QCOMPARE(Utils::runAsync(MoveOnlyCallable(), MoveOnlyType()).results(),
QList<int>({1}));
}
#endif
void tst_RunExtensions::threadPriority()
{
QScopedPointer<QThreadPool> pool(new QThreadPool);
// with pool
QCOMPARE(Utils::runAsync(pool.data(), QThread::LowestPriority, &report3).results(),
QList<int>({0, 2, 1}));
// without pool
QCOMPARE(Utils::runAsync(QThread::LowestPriority, report3).results(),
QList<int>({0, 2, 1}));
}
void tst_RunExtensions::runAsyncNoFutureInterface()
{
// free function pointer
bool value = false;
Utils::runAsync(voidFunction, &value).waitForFinished();
QCOMPARE(value, true);
QCOMPARE(Utils::runAsync(one).results(),
QList<int>({1}));
QCOMPARE(Utils::runAsync(identity, 5).results(),
QList<int>({5}));
QString s = QLatin1String("string");
const QString &crs = QLatin1String("cr string");
const QString cs = QLatin1String("c string");
QCOMPARE(Utils::runAsync(stringIdentity1, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(stringIdentity1, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(stringIdentity1, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(stringIdentity1, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(stringIdentity2, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(stringIdentity2, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(stringIdentity2, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(stringIdentity2, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
// lambda
QCOMPARE(Utils::runAsync([](int n) -> double {
return n + 1;
}, 3).results(),
QList<double>({4}));
// std::function
const std::function<double(int)> fun = [](int n) {
return n + 1;
};
QCOMPARE(Utils::runAsync(fun, 2).results(),
QList<double>({3}));
// operator()
value = false;
Utils::runAsync(CallableWithoutQFutureInterface(), &value).waitForFinished();
QCOMPARE(value, true);
value = false;
const CallableWithoutQFutureInterface c{};
Utils::runAsync(c, &value).waitForFinished();
QCOMPARE(value, true);
// static member functions
value = false;
Utils::runAsync(&MyObjectWithoutQFutureInterface::staticMember0, &value).waitForFinished();
QCOMPARE(value, true);
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::staticMember1, 2).results(),
QList<double>({2}));
// member functions
const MyObjectWithoutQFutureInterface obj{};
value = false;
Utils::runAsync(&MyObjectWithoutQFutureInterface::member0, &obj, &value).waitForFinished();
QCOMPARE(value, true);
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::member1, &obj, 4).results(),
QList<double>({4}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString1, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString1, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString1, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString1, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString2, &obj, s).results(),
QList<QString>({s}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString2, &obj, crs).results(),
QList<QString>({crs}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString2, &obj, cs).results(),
QList<QString>({cs}));
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::memberString2, &obj, QString(QLatin1String("rvalue"))).results(),
QList<QString>({QString(QLatin1String("rvalue"))}));
MyObjectWithoutQFutureInterface nonConstObj{};
QCOMPARE(Utils::runAsync(&MyObjectWithoutQFutureInterface::nonConstMember, &nonConstObj, 4).results(),
QList<double>({4}));
}
void tst_RunExtensions::crefFunction()
{
// free function pointer with future interface
auto fun = &report3;
QCOMPARE(Utils::runAsync(std::cref(fun)).results(),
QList<int>({0, 2, 1}));
// lambda with future interface
auto lambda = [](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
};
QCOMPARE(Utils::runAsync(std::cref(lambda), 3).results(),
QList<double>({0, 0, 0}));
// std::function with future interface
const std::function<void(QFutureInterface<double>&,int)> funObj = [](QFutureInterface<double> &fi, int n) {
fi.reportResults(QVector<double>(n, 0));
};
QCOMPARE(Utils::runAsync(std::cref(funObj), 2).results(),
QList<double>({0, 0}));
// callable with future interface
const Callable c{};
QCOMPARE(Utils::runAsync(std::cref(c), 2).results(),
QList<double>({0, 0}));
// member functions with future interface
auto member = &MyObject::member0;
const MyObject obj{};
QCOMPARE(Utils::runAsync(std::cref(member), &obj).results(),
QList<double>({0, 2, 1}));
// free function pointer without future interface
bool value = false;
auto voidFun = &voidFunction;
Utils::runAsync(std::cref(voidFun), &value).waitForFinished();
QCOMPARE(value, true);
auto oneFun = &one;
QCOMPARE(Utils::runAsync(std::cref(oneFun)).results(),
QList<int>({1}));
// lambda without future interface
auto lambda2 = [](int n) -> double {
return n + 1;
};
QCOMPARE(Utils::runAsync(std::cref(lambda2), 3).results(),
QList<double>({4}));
// std::function
const std::function<double(int)> funObj2 = [](int n) {
return n + 1;
};
QCOMPARE(Utils::runAsync(std::cref(funObj2), 2).results(),
QList<double>({3}));
// callable without future interface
const CallableWithoutQFutureInterface c2{};
Utils::runAsync(std::cref(c2), &value).waitForFinished();
QCOMPARE(value, true);
// member functions without future interface
const MyObjectWithoutQFutureInterface obj2{};
auto member2 = &MyObjectWithoutQFutureInterface::member0;
value = false;
Utils::runAsync(std::cref(member2), &obj2, &value).waitForFinished();
QCOMPARE(value, true);
}
QTEST_GUILESS_MAIN(tst_RunExtensions)
#include "tst_runextensions.moc"