Add unit tests to assure QtConcurrent works on move-only sequences

Unit tests are added to make sure QtConcurrent works on
move-only sequences.

Change-Id: I1d066f75ceab9cef98832e96c5827103cbfd72a8
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
This commit is contained in:
Andreas Buhr 2020-09-29 10:30:59 +02:00
parent b7f1915bd2
commit b5fc1e4e26
3 changed files with 291 additions and 78 deletions

View File

@ -222,12 +222,28 @@ void tst_QtConcurrentFilter::filtered()
testFiltered(intList, intListEven, lambdaIsEven);
CHECK_FAIL("lambda");
// rvalue sequences
auto future = QtConcurrent::filtered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
{
// rvalue sequences
auto future = QtConcurrent::filtered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
auto result = QtConcurrent::blockingFiltered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
auto result = QtConcurrent::blockingFiltered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
}
#if 0
// does not work yet
{
// move only types sequences
auto future = QtConcurrent::filtered(
MoveOnlyVector({ 1, 2, 3, 4 }), keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
auto result = QtConcurrent::blockingFiltered(
MoveOnlyVector({ 1, 2, 3, 4 }), keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
}
#endif
}
template <typename SourceObject,
@ -282,13 +298,30 @@ void tst_QtConcurrentFilter::filteredThreadPool()
testFilteredThreadPool(&pool, intList, intListEven, lambdaIsOdd);
CHECK_FAIL("lambda");
// rvalue sequences
auto future = QtConcurrent::filtered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
{
// rvalue sequences
auto future = QtConcurrent::filtered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
auto result =
QtConcurrent::blockingFiltered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
auto result =
QtConcurrent::blockingFiltered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
}
#if 0
// does not work yet
{
// move-only sequences
auto future = QtConcurrent::filtered(
&pool, MoveOnlyVector({ 1, 2, 3, 4 }), keepEvenIntegers);
QCOMPARE(future.results(), QList<int>({ 2, 4 }));
auto result =
QtConcurrent::blockingFiltered(
&pool, MoveOnlyVector({ 1, 2, 3, 4 }), keepEvenIntegers);
QCOMPARE(result, std::vector<int>({ 2, 4 }));
}
#endif
}
template <typename SourceObject,
@ -425,14 +458,27 @@ void tst_QtConcurrentFilter::filteredReduced()
testFilteredReduced(intList, intSum, lambdaIsEven, lambdaIntSumReduce);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
intSumReduce);
QCOMPARE(future, intSum);
{
// rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
intSumReduce);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(std::vector { 1, 2, 3, 4 },
keepEvenIntegers, intSumReduce);
QCOMPARE(result, intSum);
auto result = QtConcurrent::blockingFilteredReduced(std::vector { 1, 2, 3, 4 },
keepEvenIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
{
// move only sequences
auto future = QtConcurrent::filteredReduced(MoveOnlyVector({ 1, 2, 3, 4 }),
keepEvenIntegers, intSumReduce);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(MoveOnlyVector({ 1, 2, 3, 4 }),
keepEvenIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
}
template <typename SourceObject,
@ -510,14 +556,27 @@ void tst_QtConcurrentFilter::filteredReducedThreadPool()
testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, lambdaSumReduce);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 }, keepOddIntegers,
intSumReduce);
QCOMPARE(future, intSum);
{
// rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 },
keepOddIntegers, intSumReduce);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(&pool, std::vector { 1, 2, 3, 4 },
keepOddIntegers, intSumReduce);
QCOMPARE(result, intSum);
auto result = QtConcurrent::blockingFilteredReduced(&pool, std::vector { 1, 2, 3, 4 },
keepOddIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
{
// move only sequences
auto future = QtConcurrent::filteredReduced(&pool, MoveOnlyVector({ 1, 2, 3, 4 }),
keepOddIntegers, intSumReduce);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(&pool, MoveOnlyVector({ 1, 2, 3, 4 }),
keepOddIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
}
void tst_QtConcurrentFilter::filteredReducedDifferentType()
@ -714,14 +773,27 @@ void tst_QtConcurrentFilter::filteredReducedInitialValue()
lambdaIntSumReduce, intInitial);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
intSumReduce, intInitial);
QCOMPARE(future, intSum);
{
// rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
intSumReduce, intInitial);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(std::vector { 1, 2, 3, 4 },
keepEvenIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
auto result = QtConcurrent::blockingFilteredReduced(
std::vector { 1, 2, 3, 4 }, keepEvenIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
}
{
// move only sequences
auto future = QtConcurrent::filteredReduced(MoveOnlyVector({ 1, 2, 3, 4 }),
keepEvenIntegers, intSumReduce, intInitial);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(
MoveOnlyVector({ 1, 2, 3, 4 }), keepEvenIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
}
}
template <typename SourceObject,
@ -811,14 +883,27 @@ void tst_QtConcurrentFilter::filteredReducedInitialValueThreadPool()
lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 }, keepOddIntegers,
intSumReduce, intInitial);
QCOMPARE(future, intSum);
{
// rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 },
keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(&pool, std::vector { 1, 2, 3, 4 },
keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
auto result = QtConcurrent::blockingFilteredReduced(
&pool, std::vector { 1, 2, 3, 4 }, keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
}
{
// move only sequences
auto future = QtConcurrent::filteredReduced(&pool, MoveOnlyVector({ 1, 2, 3, 4 }),
keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(future, intSum);
auto result = QtConcurrent::blockingFilteredReduced(
&pool, MoveOnlyVector({ 1, 2, 3, 4 }), keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(result, intSum);
}
}
void tst_QtConcurrentFilter::filteredReducedDifferentTypeInitialValue()

View File

@ -28,6 +28,8 @@
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <vector>
bool keepEvenIntegers(const int &x)
{
return (x & 1) == 0;
@ -133,4 +135,34 @@ public:
}
};
class MoveOnlyVector
{
public:
// rule of six
MoveOnlyVector() = default;
~MoveOnlyVector() = default;
MoveOnlyVector(MoveOnlyVector &&other) = default;
MoveOnlyVector &operator=(MoveOnlyVector &&other) = default;
MoveOnlyVector(const MoveOnlyVector &) = delete;
MoveOnlyVector &operator=(const MoveOnlyVector &) = delete;
// convenience for creation
explicit MoveOnlyVector(const std::vector<int> &v) : data(v) { }
// minimal interface to be usable as a Sequence in QtConcurrent
typedef std::vector<int>::const_iterator const_iterator;
typedef std::vector<int>::iterator iterator;
const_iterator cbegin() const { return data.cbegin(); }
const_iterator cend() const { return data.cend(); }
iterator begin() { return data.begin(); }
iterator end() { return data.end(); }
const_iterator begin() const { return data.cbegin(); }
const_iterator end() const { return data.cend(); }
bool operator==(const MoveOnlyVector &other) const { return data == other.data; }
private:
std::vector<int> data;
};
#endif

View File

@ -170,6 +170,15 @@ void tst_QtConcurrentMap::map()
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
}
// functors take arguments by reference, modifying the move-only sequence in place
{
MoveOnlyVector moveOnlyVector({ 1, 2, 3 });
// functor
QtConcurrent::map(moveOnlyVector, MultiplyBy2InPlace()).waitForFinished();
QCOMPARE(moveOnlyVector, MoveOnlyVector({ 2, 4, 6 }));
}
#if 0
// not allowed: map() with immutable sequences makes no sense
{
@ -252,6 +261,18 @@ void tst_QtConcurrentMap::blockingMap()
QCOMPARE(list, QList<int>() << 256 << 512 << 768);
}
// functors take arguments by reference, modifying the move-only sequence in place
{
MoveOnlyVector moveOnlyVector({ 1, 2, 3 });
// functor
QtConcurrent::blockingMap(moveOnlyVector, MultiplyBy2InPlace());
QCOMPARE(moveOnlyVector, MoveOnlyVector({ 2, 4, 6 }));
QtConcurrent::blockingMap(moveOnlyVector.begin(), moveOnlyVector.end(),
MultiplyBy2InPlace());
QCOMPARE(moveOnlyVector, MoveOnlyVector({ 4, 8, 12 }));
}
// functors don't take arguments by reference, making these no-ops
{
QList<int> list;
@ -497,13 +518,25 @@ void tst_QtConcurrentMap::mapped()
CHECK_FAIL("member");
#endif
// rvalue sequences
auto future = QtConcurrent::mapped(std::vector { 1, 2, 3 }, multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
{
// rvalue sequences
auto future = QtConcurrent::mapped(std::vector { 1, 2, 3 }, multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
auto result =
QtConcurrent::blockingMapped<std::vector<int>>(std::vector { 1, 2, 3 }, multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped<std::vector<int>>(std::vector { 1, 2, 3 },
multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
}
{
// move only sequences
auto future = QtConcurrent::mapped(MoveOnlyVector({ 1, 2, 3 }), multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped<std::vector<int>>(MoveOnlyVector({ 1, 2, 3 }),
multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
}
}
static QSemaphore semaphore(1);
@ -589,13 +622,24 @@ void tst_QtConcurrentMap::mappedThreadPool()
testMappedThreadPool(&pool, intList, intListMultipiedBy3, lambdaMultiplyBy3);
CHECK_FAIL("lambda");
// rvalue sequences
auto future = QtConcurrent::mapped(&pool, std::vector { 1, 2, 3 }, multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
{
// rvalue sequences
auto future = QtConcurrent::mapped(&pool, std::vector { 1, 2, 3 }, multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped<std::vector<int>>(&pool, std::vector { 1, 2, 3 },
multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped<std::vector<int>>(&pool, std::vector { 1, 2, 3 },
multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
}
{
// move only sequences
auto future = QtConcurrent::mapped(&pool, MoveOnlyVector({ 1, 2, 3 }), multiplyBy2);
QCOMPARE(future.results(), QList<int>({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped<std::vector<int>>(
&pool, MoveOnlyVector({ 1, 2, 3 }), multiplyBy2);
QCOMPARE(result, std::vector<int>({ 2, 4, 6 }));
}
}
int intSquare(int x)
@ -723,13 +767,26 @@ void tst_QtConcurrentMap::mappedReduced()
testMappedReduced(intList, sumOfSquares, lambdaSquare, lambdaSumReduce);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce);
QCOMPARE(future, sumOfSquares);
{
// rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce);
QCOMPARE(future, sumOfSquares);
auto result =
QtConcurrent::blockingMappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce);
QCOMPARE(result, sumOfSquares);
auto result = QtConcurrent::blockingMappedReduced(std::vector { 1, 2, 3 }, intSquare,
intSumReduce);
QCOMPARE(result, sumOfSquares);
}
{
// move only sequences
auto future =
QtConcurrent::mappedReduced(MoveOnlyVector({ 1, 2, 3 }), intSquare, intSumReduce);
QCOMPARE(future, sumOfSquares);
auto result = QtConcurrent::blockingMappedReduced(MoveOnlyVector({ 1, 2, 3 }), intSquare,
intSumReduce);
QCOMPARE(result, sumOfSquares);
}
}
template <typename SourceObject, typename ResultObject, typename MapObject, typename ReduceObject>
@ -817,14 +874,27 @@ void tst_QtConcurrentMap::mappedReducedThreadPool()
testMappedReducedThreadPool(&pool, intList, sumOfCubes, lambdaCube, lambdaSumReduce);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future =
QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube, intSumReduce);
QCOMPARE(future, sumOfCubes);
{
// rvalue sequences
auto future =
QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube, intSumReduce);
QCOMPARE(future, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,
intSumReduce);
QCOMPARE(result, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,
intSumReduce);
QCOMPARE(result, sumOfCubes);
}
{
// move only sequences
auto future = QtConcurrent::mappedReduced(&pool, MoveOnlyVector({ 1, 2, 3 }), intCube,
intSumReduce);
QCOMPARE(future, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, MoveOnlyVector({ 1, 2, 3 }),
intCube, intSumReduce);
QCOMPARE(result, sumOfCubes);
}
}
void tst_QtConcurrentMap::mappedReducedDifferentType()
@ -988,14 +1058,27 @@ void tst_QtConcurrentMap::mappedReducedInitialValue()
testMappedReducedInitialValue(intList, sumOfSquares, lambdaSquare, lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce,
intInitial);
QCOMPARE(future, sumOfSquares);
{
// rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce,
intInitial);
QCOMPARE(future, sumOfSquares);
auto result = QtConcurrent::blockingMappedReduced(std::vector { 1, 2, 3 }, intSquare,
intSumReduce, intInitial);
QCOMPARE(result, sumOfSquares);
auto result = QtConcurrent::blockingMappedReduced(std::vector { 1, 2, 3 }, intSquare,
intSumReduce, intInitial);
QCOMPARE(result, sumOfSquares);
}
{
// move only sequences
auto future = QtConcurrent::mappedReduced(MoveOnlyVector({ 1, 2, 3 }), intSquare,
intSumReduce, intInitial);
QCOMPARE(future, sumOfSquares);
auto result = QtConcurrent::blockingMappedReduced(MoveOnlyVector({ 1, 2, 3 }), intSquare,
intSumReduce, intInitial);
QCOMPARE(result, sumOfSquares);
}
}
template <typename SourceObject, typename ResultObject, typename InitialObject, typename MapObject, typename ReduceObject>
@ -1082,14 +1165,27 @@ void tst_QtConcurrentMap::mappedReducedInitialValueThreadPool()
lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda");
// rvalue sequences
auto future = QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube, intSumReduce,
intInitial);
QCOMPARE(future, sumOfCubes);
{
// rvalue sequences
auto future = QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,
intSumReduce, intInitial);
QCOMPARE(future, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,
intSumReduce, intInitial);
QCOMPARE(result, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,
intSumReduce, intInitial);
QCOMPARE(result, sumOfCubes);
}
{
// move only sequences
auto future = QtConcurrent::mappedReduced(&pool, MoveOnlyVector({ 1, 2, 3 }), intCube,
intSumReduce, intInitial);
QCOMPARE(future, sumOfCubes);
auto result = QtConcurrent::blockingMappedReduced(&pool, MoveOnlyVector({ 1, 2, 3 }),
intCube, intSumReduce, intInitial);
QCOMPARE(result, sumOfCubes);
}
}
void tst_QtConcurrentMap::mappedReducedDifferentTypeInitialValue()