/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "../qtconcurrentmap/functions.h" class tst_QtConcurrentFilter : public QObject { Q_OBJECT private slots: void filter(); void filterThreadPool(); void filtered(); void filteredThreadPool(); void filteredReduced(); void filteredReducedThreadPool(); void filteredReducedDifferentType(); void filteredReducedInitialValue(); void filteredReducedInitialValueThreadPool(); void filteredReducedDifferentTypeInitialValue(); void resultAt(); void incrementalResults(); void noDetach(); void stlContainers(); void stlContainersLambda(); }; using namespace QtConcurrent; #define CHECK_FAIL(message) \ do {\ if (QTest::currentTestFailed())\ QFAIL("failed one line above on " message);\ } while (false) template void testFilter(const QList &sourceObjectList, const QList &expectedResult, FilterObject filterObject) { QList copy1 = sourceObjectList; QList copy2 = sourceObjectList; QtConcurrent::filter(copy1, filterObject).waitForFinished(); QCOMPARE(copy1, expectedResult); QtConcurrent::blockingFilter(copy2, filterObject); QCOMPARE(copy2, expectedResult); } void tst_QtConcurrentFilter::filter() { const QList intList {1, 2, 3, 4}; const QList intListEven {2, 4}; const QList numberList {1, 2, 3, 4}; const QList numberListEven {2, 4}; auto lambdaIsEven = [](const int &x) { return (x & 1) == 0; }; testFilter(intList, intListEven, KeepEvenIntegers()); CHECK_FAIL("functor"); testFilter(intList, intListEven, keepEvenIntegers); CHECK_FAIL("function"); testFilter(numberList, numberListEven, &Number::isEven); CHECK_FAIL("member"); testFilter(intList, intListEven, lambdaIsEven); CHECK_FAIL("lambda"); } static QSemaphore semaphore(1); static QSet workingThreads; void storeCurrentThread() { semaphore.acquire(); workingThreads.insert(QThread::currentThread()); semaphore.release(); } int threadCount() { semaphore.acquire(); const int count = workingThreads.size(); semaphore.release(); return count; } template void testFilterThreadPool(QThreadPool *pool, const QList &sourceObjectList, const QList &expectedResult, FilterObject filterObject) { QList copy1 = sourceObjectList; QList copy2 = sourceObjectList; QtConcurrent::filter(pool, copy1, filterObject).waitForFinished(); QCOMPARE(copy1, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working QtConcurrent::blockingFilter(pool, copy2, filterObject); QCOMPARE(copy2, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working } class KeepOddIntegers { public: bool operator()(const int &x) { storeCurrentThread(); return x & 1; } }; bool keepOddIntegers(const int &x) { storeCurrentThread(); return x & 1; } void tst_QtConcurrentFilter::filterThreadPool() { const QList intList {1, 2, 3, 4}; const QList intListEven {1, 3}; auto lambdaIsOdd = [](const int &x) { storeCurrentThread(); return x & 1; }; QThreadPool pool; pool.setMaxThreadCount(1); QCOMPARE(semaphore.available(), 1); workingThreads.clear(); testFilterThreadPool(&pool, intList, intListEven, KeepOddIntegers()); CHECK_FAIL("functor"); testFilterThreadPool(&pool, intList, intListEven, keepOddIntegers); CHECK_FAIL("function"); testFilterThreadPool(&pool, intList, intListEven, lambdaIsOdd); CHECK_FAIL("lambda"); } template void testFiltered(const QList &sourceObjectList, const QList &expectedResult, FilterObject filterObject) { const QList result1 = QtConcurrent::filtered( sourceObjectList, filterObject).results(); QCOMPARE(result1, expectedResult); const QList result2 = QtConcurrent::filtered( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject).results(); QCOMPARE(result2, expectedResult); const QList result3 = QtConcurrent::blockingFiltered( sourceObjectList, filterObject); QCOMPARE(result3, expectedResult); const QList result4 = QtConcurrent::blockingFiltered>( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject); QCOMPARE(result4, expectedResult); } void tst_QtConcurrentFilter::filtered() { const QList intList {1, 2, 3, 4}; const QList intListEven {2, 4}; const QList numberList {1, 2, 3, 4}; const QList numberListEven {2, 4}; auto lambdaIsEven = [](const int &x) { return (x & 1) == 0; }; testFiltered(intList, intListEven, KeepEvenIntegers()); CHECK_FAIL("functor"); testFiltered(intList, intListEven, keepEvenIntegers); CHECK_FAIL("function"); testFiltered(numberList, numberListEven, &Number::isEven); CHECK_FAIL("member"); testFiltered(intList, intListEven, lambdaIsEven); CHECK_FAIL("lambda"); } template void testFilteredThreadPool(QThreadPool *pool, const QList &sourceObjectList, const QList &expectedResult, FilterObject filterObject) { const QList result1 = QtConcurrent::filtered( pool, sourceObjectList, filterObject).results(); QCOMPARE(result1, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const QList result2 = QtConcurrent::filtered( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject).results(); QCOMPARE(result2, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const QList result3 = QtConcurrent::blockingFiltered( pool, sourceObjectList, filterObject); QCOMPARE(result3, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const QList result4 = QtConcurrent::blockingFiltered>( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject); QCOMPARE(result4, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working } void tst_QtConcurrentFilter::filteredThreadPool() { const QList intList {1, 2, 3, 4}; const QList intListEven {1, 3}; auto lambdaIsOdd = [](const int &x) { storeCurrentThread(); return x & 1; }; QThreadPool pool; pool.setMaxThreadCount(1); QCOMPARE(semaphore.available(), 1); workingThreads.clear(); testFilteredThreadPool(&pool, intList, intListEven, KeepOddIntegers()); CHECK_FAIL("functor"); testFilteredThreadPool(&pool, intList, intListEven, keepOddIntegers); CHECK_FAIL("function"); testFilteredThreadPool(&pool, intList, intListEven, lambdaIsOdd); CHECK_FAIL("lambda"); } template void testFilteredReduced(const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject) { const ResultObject result1 = QtConcurrent::filteredReduced( sourceObjectList, filterObject, reduceObject); QCOMPARE(result1, expectedResult); const ResultObject result2 = QtConcurrent::filteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject); QCOMPARE(result2, expectedResult); const ResultObject result3 = QtConcurrent::blockingFilteredReduced( sourceObjectList, filterObject, reduceObject); QCOMPARE(result3, expectedResult); const ResultObject result4 = QtConcurrent::blockingFilteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject); QCOMPARE(result4, expectedResult); } template void testFilteredReduced(const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject, QtConcurrent::ReduceOptions options) { const ResultObject result1 = QtConcurrent::filteredReduced( sourceObjectList, filterObject, reduceObject, options); QCOMPARE(result1, expectedResult); const ResultObject result2 = QtConcurrent::filteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, options); QCOMPARE(result2, expectedResult); const ResultObject result3 = QtConcurrent::blockingFilteredReduced( sourceObjectList, filterObject, reduceObject, options); QCOMPARE(result3, expectedResult); const ResultObject result4 = QtConcurrent::blockingFilteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, options); QCOMPARE(result4, expectedResult); } void numberSumReduceToNumber(Number &sum, const Number &x) { sum = Number(sum.toInt() + x.toInt()); } class NumberSumReduceToNumber { public: void operator()(Number &sum, const Number &x) { sum = Number(sum.toInt() + x.toInt()); } }; void tst_QtConcurrentFilter::filteredReduced() { const QList intList {1, 2, 3, 4}; const QList intListEven {2, 4}; const QList numberList {1, 2, 3, 4}; const QList numberListEven {2, 4}; const int intSum = 6; // sum of even values const Number numberSum = 6; // sum of even values void (QVector::*pushBackInt)(const int &) = &QVector::push_back; void (QVector::*pushBackNumber)(const Number &) = &QVector::push_back; auto lambdaIsEven = [](const int &x) { return (x & 1) == 0; }; auto lambdaIntSumReduce = [](int &sum, const int &x) { sum += x; }; auto lambdaNumberSumReduce = [](Number &sum, const Number &x) { sum = Number(sum.toInt() + x.toInt()); }; // FUNCTOR-other testFilteredReduced(intList, intSum, KeepEvenIntegers(), IntSumReduce()); CHECK_FAIL("functor-functor"); testFilteredReduced(intList, intSum, KeepEvenIntegers(), intSumReduce); CHECK_FAIL("functor-function"); testFilteredReduced(intList, intListEven, KeepEvenIntegers(), pushBackInt, OrderedReduce); CHECK_FAIL("functor-member"); testFilteredReduced(intList, intSum, KeepEvenIntegers(), lambdaIntSumReduce); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReduced(intList, intSum, keepEvenIntegers, IntSumReduce()); CHECK_FAIL("function-functor"); testFilteredReduced(intList, intSum, keepEvenIntegers, intSumReduce); CHECK_FAIL("function-function"); testFilteredReduced(intList, intListEven, keepEvenIntegers, pushBackInt, OrderedReduce); CHECK_FAIL("function-member"); testFilteredReduced(intList, intSum, keepEvenIntegers, lambdaIntSumReduce); CHECK_FAIL("function-lambda"); // MEMBER-other testFilteredReduced(numberList, numberSum, &Number::isEven, NumberSumReduceToNumber()); CHECK_FAIL("member-functor"); testFilteredReduced(numberList, numberSum, &Number::isEven, numberSumReduceToNumber); CHECK_FAIL("member-function"); testFilteredReduced(numberList, numberListEven, &Number::isEven, pushBackNumber, OrderedReduce); CHECK_FAIL("member-member"); testFilteredReduced(numberList, numberSum, &Number::isEven, lambdaNumberSumReduce); CHECK_FAIL("member-lambda"); // LAMBDA-other testFilteredReduced(intList, intSum, lambdaIsEven, IntSumReduce()); CHECK_FAIL("lambda-functor"); testFilteredReduced(intList, intSum, lambdaIsEven, intSumReduce); CHECK_FAIL("lambda-function"); testFilteredReduced(intList, intListEven, lambdaIsEven, pushBackInt, OrderedReduce); CHECK_FAIL("lambda-member"); testFilteredReduced(intList, intSum, lambdaIsEven, lambdaIntSumReduce); CHECK_FAIL("lambda-lambda"); } template void testFilteredReducedThreadPool(QThreadPool *pool, const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject) { const ResultObject result1 = QtConcurrent::filteredReduced( pool, sourceObjectList, filterObject, reduceObject); QCOMPARE(result1, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result2 = QtConcurrent::filteredReduced( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject); QCOMPARE(result2, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result3 = QtConcurrent::blockingFilteredReduced( pool, sourceObjectList, filterObject, reduceObject); QCOMPARE(result3, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result4 = QtConcurrent::blockingFilteredReduced( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject); QCOMPARE(result4, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working } void tst_QtConcurrentFilter::filteredReducedThreadPool() { const QList intList {1, 2, 3, 4}; const int intSum = 4; // sum of even values auto lambdaIsOdd = [](const int &x) { storeCurrentThread(); return x & 1; }; auto lambdaSumReduce = [](int &sum, const int &x) { sum += x; }; QThreadPool pool; pool.setMaxThreadCount(1); QCOMPARE(semaphore.available(), 1); workingThreads.clear(); // FUNCTOR-other testFilteredReducedThreadPool(&pool, intList, intSum, KeepOddIntegers(), IntSumReduce()); CHECK_FAIL("functor-functor"); testFilteredReducedThreadPool(&pool, intList, intSum, KeepOddIntegers(), intSumReduce); CHECK_FAIL("functor-function"); testFilteredReducedThreadPool(&pool, intList, intSum, KeepOddIntegers(), lambdaSumReduce); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReducedThreadPool(&pool, intList, intSum, keepOddIntegers, IntSumReduce()); CHECK_FAIL("function-functor"); testFilteredReducedThreadPool(&pool, intList, intSum, keepOddIntegers, intSumReduce); CHECK_FAIL("function-function"); testFilteredReducedThreadPool(&pool, intList, intSum, keepOddIntegers, lambdaSumReduce); CHECK_FAIL("function-lambda"); // LAMBDA-other testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, IntSumReduce()); CHECK_FAIL("lambda-functor"); testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, intSumReduce); CHECK_FAIL("lambda-function"); testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, lambdaSumReduce); CHECK_FAIL("lambda-lambda"); } void tst_QtConcurrentFilter::filteredReducedDifferentType() { const QList numberList {1, 2, 3, 4}; const int sum = 6; // sum of even values auto lambdaIsEven = [](const Number &x) { return (x.toInt() & 1) == 0; }; auto lambdaSumReduce = [](int &sum, const Number &x) { sum += x.toInt(); }; // Test the case where reduce function of the form: // V function(T &result, const U &intermediate) // has T and U types different. // FUNCTOR-other testFilteredReduced(numberList, sum, KeepEvenNumbers(), NumberSumReduce()); CHECK_FAIL("functor-functor"); testFilteredReduced(numberList, sum, KeepEvenNumbers(), numberSumReduce); CHECK_FAIL("functor-function"); testFilteredReduced(numberList, sum, KeepEvenNumbers(), lambdaSumReduce); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReduced(numberList, sum, keepEvenNumbers, NumberSumReduce()); CHECK_FAIL("function-functor"); testFilteredReduced(numberList, sum, keepEvenNumbers, numberSumReduce); CHECK_FAIL("function-function"); testFilteredReduced(numberList, sum, keepEvenNumbers, lambdaSumReduce); CHECK_FAIL("function-lambda"); // MEMBER-other testFilteredReduced(numberList, sum, &Number::isEven, NumberSumReduce()); CHECK_FAIL("member-functor"); testFilteredReduced(numberList, sum, &Number::isEven, numberSumReduce); CHECK_FAIL("member-function"); testFilteredReduced(numberList, sum, &Number::isEven, lambdaSumReduce); CHECK_FAIL("member-lambda"); // LAMBDA-other testFilteredReduced(numberList, sum, lambdaIsEven, NumberSumReduce()); CHECK_FAIL("lambda-functor"); testFilteredReduced(numberList, sum, lambdaIsEven, numberSumReduce); CHECK_FAIL("lambda-function"); testFilteredReduced(numberList, sum, lambdaIsEven, lambdaSumReduce); CHECK_FAIL("lambda-lambda"); } template void testFilteredReducedInitialValue(const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject, InitialObject &&initialObject) { const ResultObject result1 = QtConcurrent::filteredReduced( sourceObjectList, filterObject, reduceObject, initialObject); QCOMPARE(result1, expectedResult); const ResultObject result2 = QtConcurrent::filteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject); QCOMPARE(result2, expectedResult); const ResultObject result3 = QtConcurrent::blockingFilteredReduced( sourceObjectList, filterObject, reduceObject, initialObject); QCOMPARE(result3, expectedResult); const ResultObject result4 = QtConcurrent::blockingFilteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject); QCOMPARE(result4, expectedResult); } template void testFilteredReducedInitialValue(const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject, InitialObject &&initialObject, QtConcurrent::ReduceOptions options) { const ResultObject result1 = QtConcurrent::filteredReduced( sourceObjectList, filterObject, reduceObject, initialObject, options); QCOMPARE(result1, expectedResult); const ResultObject result2 = QtConcurrent::filteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject, options); QCOMPARE(result2, expectedResult); const ResultObject result3 = QtConcurrent::blockingFilteredReduced( sourceObjectList, filterObject, reduceObject, initialObject, options); QCOMPARE(result3, expectedResult); const ResultObject result4 = QtConcurrent::blockingFilteredReduced( sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject, options); QCOMPARE(result4, expectedResult); } void tst_QtConcurrentFilter::filteredReducedInitialValue() { // This is a copy of tst_QtConcurrentFilter::filteredReduced // with the initial value parameter added const QList intList {1, 2, 3, 4}; const QList intListInitial {10}; const QList intListAppended {10, 2, 4}; const QList numberList {1, 2, 3, 4}; const QList numberListInitial {10}; const QList numberListAppended {10, 2, 4}; const int intInitial = 10; const int intSum = 16; // sum of even values and initial value const Number numberSum = 16; // sum of even values and initial value void (QVector::*pushBackInt)(const int &) = &QVector::push_back; void (QVector::*pushBackNumber)(const Number &) = &QVector::push_back; auto lambdaIsEven = [](const int &x) { return (x & 1) == 0; }; auto lambdaIntSumReduce = [](int &sum, const int &x) { sum += x; }; auto lambdaNumberSumReduce = [](Number &sum, const Number &x) { sum = Number(sum.toInt() + x.toInt()); }; // FUNCTOR-other testFilteredReducedInitialValue(intList, intSum, KeepEvenIntegers(), IntSumReduce(), intInitial); CHECK_FAIL("functor-functor"); testFilteredReducedInitialValue(intList, intSum, KeepEvenIntegers(), intSumReduce, intInitial); CHECK_FAIL("functor-function"); testFilteredReducedInitialValue(intList, intListAppended, KeepEvenIntegers(), pushBackInt, intListInitial, OrderedReduce); CHECK_FAIL("functor-member"); testFilteredReducedInitialValue(intList, intSum, KeepEvenIntegers(), lambdaIntSumReduce, intInitial); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReducedInitialValue(intList, intSum, keepEvenIntegers, IntSumReduce(), intInitial); CHECK_FAIL("function-functor"); testFilteredReducedInitialValue(intList, intSum, keepEvenIntegers, intSumReduce, intInitial); CHECK_FAIL("function-function"); testFilteredReducedInitialValue(intList, intListAppended, keepEvenIntegers, pushBackInt, intListInitial, OrderedReduce); CHECK_FAIL("function-member"); testFilteredReducedInitialValue(intList, intSum, keepEvenIntegers, lambdaIntSumReduce, intInitial); CHECK_FAIL("function-lambda"); // MEMBER-other testFilteredReducedInitialValue(numberList, numberSum, &Number::isEven, NumberSumReduceToNumber(), intInitial); CHECK_FAIL("member-functor"); testFilteredReducedInitialValue(numberList, numberSum, &Number::isEven, numberSumReduceToNumber, intInitial); CHECK_FAIL("member-function"); testFilteredReducedInitialValue(numberList, numberListAppended, &Number::isEven, pushBackNumber, numberListInitial, OrderedReduce); CHECK_FAIL("member-member"); testFilteredReducedInitialValue(numberList, numberSum, &Number::isEven, lambdaNumberSumReduce, intInitial); CHECK_FAIL("member-lambda"); // LAMBDA-other testFilteredReducedInitialValue(intList, intSum, lambdaIsEven, IntSumReduce(), intInitial); CHECK_FAIL("lambda-functor"); testFilteredReducedInitialValue(intList, intSum, lambdaIsEven, intSumReduce, intInitial); CHECK_FAIL("lambda-function"); testFilteredReducedInitialValue(intList, intListAppended, lambdaIsEven, pushBackInt, intListInitial, OrderedReduce); CHECK_FAIL("lambda-member"); testFilteredReducedInitialValue(intList, intSum, lambdaIsEven, lambdaIntSumReduce, intInitial); CHECK_FAIL("lambda-lambda"); } template void testFilteredReducedInitialValueThreadPool(QThreadPool *pool, const QList &sourceObjectList, const ResultObject &expectedResult, FilterObject filterObject, ReduceObject reduceObject, InitialObject &&initialObject) { const ResultObject result1 = QtConcurrent::filteredReduced( pool, sourceObjectList, filterObject, reduceObject, initialObject); QCOMPARE(result1, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result2 = QtConcurrent::filteredReduced( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject); QCOMPARE(result2, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result3 = QtConcurrent::blockingFilteredReduced( pool, sourceObjectList, filterObject, reduceObject, initialObject); QCOMPARE(result3, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working const ResultObject result4 = QtConcurrent::blockingFilteredReduced( pool, sourceObjectList.constBegin(), sourceObjectList.constEnd(), filterObject, reduceObject, initialObject); QCOMPARE(result4, expectedResult); QCOMPARE(threadCount(), 1); // ensure the only one thread was working } void tst_QtConcurrentFilter::filteredReducedInitialValueThreadPool() { const QList intList {1, 2, 3, 4}; const int intInitial = 10; const int intSum = 14; // sum of even values and initial value auto lambdaIsOdd = [](const int &x) { storeCurrentThread(); return x & 1; }; auto lambdaSumReduce = [](int &sum, const int &x) { sum += x; }; QThreadPool pool; pool.setMaxThreadCount(1); QCOMPARE(semaphore.available(), 1); workingThreads.clear(); // FUNCTOR-other testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, KeepOddIntegers(), IntSumReduce(), intInitial); CHECK_FAIL("functor-functor"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, KeepOddIntegers(), intSumReduce, intInitial); CHECK_FAIL("functor-function"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, KeepOddIntegers(), lambdaSumReduce, intInitial); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, keepOddIntegers, IntSumReduce(), intInitial); CHECK_FAIL("function-functor"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, keepOddIntegers, intSumReduce, intInitial); CHECK_FAIL("function-function"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, keepOddIntegers, lambdaSumReduce, intInitial); CHECK_FAIL("function-lambda"); // LAMBDA-other testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, lambdaIsOdd, IntSumReduce(), intInitial); CHECK_FAIL("lambda-functor"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, lambdaIsOdd, intSumReduce, intInitial); CHECK_FAIL("lambda-function"); testFilteredReducedInitialValueThreadPool(&pool, intList, intSum, lambdaIsOdd, lambdaSumReduce, intInitial); CHECK_FAIL("lambda-lambda"); } void tst_QtConcurrentFilter::filteredReducedDifferentTypeInitialValue() { const QList numberList {1, 2, 3, 4}; const int initial = 10; const int sum = 16; // sum of even values and initial value auto lambdaIsEven = [](const Number &x) { return (x.toInt() & 1) == 0; }; auto lambdaSumReduce = [](int &sum, const Number &x) { sum += x.toInt(); }; // Test the case where reduce function of the form: // V function(T &result, const U &intermediate) // has T and U types different. // FUNCTOR-other testFilteredReducedInitialValue(numberList, sum, KeepEvenNumbers(), NumberSumReduce(), initial); CHECK_FAIL("functor-functor"); testFilteredReducedInitialValue(numberList, sum, KeepEvenNumbers(), numberSumReduce, initial); CHECK_FAIL("functor-function"); testFilteredReducedInitialValue(numberList, sum, KeepEvenNumbers(), lambdaSumReduce, initial); CHECK_FAIL("functor-lambda"); // FUNCTION-other testFilteredReducedInitialValue(numberList, sum, keepEvenNumbers, NumberSumReduce(), initial); CHECK_FAIL("function-functor"); testFilteredReducedInitialValue(numberList, sum, keepEvenNumbers, numberSumReduce, initial); CHECK_FAIL("function-function"); testFilteredReducedInitialValue(numberList, sum, keepEvenNumbers, lambdaSumReduce, initial); CHECK_FAIL("function-lambda"); // MEMBER-other testFilteredReducedInitialValue(numberList, sum, &Number::isEven, NumberSumReduce(), initial); CHECK_FAIL("member-functor"); testFilteredReducedInitialValue(numberList, sum, &Number::isEven, numberSumReduce, initial); CHECK_FAIL("member-function"); testFilteredReducedInitialValue(numberList, sum, &Number::isEven, lambdaSumReduce, initial); CHECK_FAIL("member-lambda"); // LAMBDA-other testFilteredReducedInitialValue(numberList, sum, lambdaIsEven, NumberSumReduce(), initial); CHECK_FAIL("lambda-functor"); testFilteredReducedInitialValue(numberList, sum, lambdaIsEven, numberSumReduce, initial); CHECK_FAIL("lambda-function"); testFilteredReducedInitialValue(numberList, sum, lambdaIsEven, lambdaSumReduce, initial); CHECK_FAIL("lambda-lambda"); } bool filterfn(int i) { return (i % 2); } void tst_QtConcurrentFilter::resultAt() { QList ints; for (int i = 0; i < 1000; ++i) ints << i; QFuture future = QtConcurrent::filtered(ints, filterfn); future.waitForFinished(); for (int i = 0; i < future.resultCount(); ++i) { QCOMPARE(future.resultAt(i), ints.at(i * 2 + 1)); } } bool waitFilterfn(const int &i) { QTest::qWait(1); return (i % 2); } void tst_QtConcurrentFilter::incrementalResults() { const int count = 200; QList ints; for (int i = 0; i < count; ++i) ints << i; QFuture future = QtConcurrent::filtered(ints, waitFilterfn); QList results; while (future.isFinished() == false) { for (int i = 0; i < future.resultCount(); ++i) { results += future.resultAt(i); } QTest::qWait(1); } QCOMPARE(future.isFinished(), true); QCOMPARE(future.resultCount(), count / 2); QCOMPARE(future.results().count(), count / 2); } void tst_QtConcurrentFilter::noDetach() { { QList l = QList() << 1; QVERIFY(l.isDetached()); QList ll = l; QVERIFY(!l.isDetached()); QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); QVERIFY(!l.isDetached()); QVERIFY(!ll.isDetached()); QtConcurrent::blockingFiltered(l, waitFilterfn); QVERIFY(!l.isDetached()); QVERIFY(!ll.isDetached()); QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); QVERIFY(!l.isDetached()); QVERIFY(!ll.isDetached()); QtConcurrent::filter(l, waitFilterfn).waitForFinished(); if (!l.isDetached()) QEXPECT_FAIL("", "QTBUG-20688: Known unstable failure", Abort); QVERIFY(l.isDetached()); QVERIFY(ll.isDetached()); } { const QList l = QList() << 1; QVERIFY(l.isDetached()); const QList ll = l; QVERIFY(!l.isDetached()); QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); QVERIFY(!l.isDetached()); QVERIFY(!ll.isDetached()); QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); QVERIFY(!l.isDetached()); QVERIFY(!ll.isDetached()); } } void tst_QtConcurrentFilter::stlContainers() { std::vector vector; vector.push_back(1); vector.push_back(2); std::vector vector2 = QtConcurrent::blockingFiltered(vector, waitFilterfn); QCOMPARE(vector2.size(), (std::vector::size_type)(1)); QCOMPARE(vector2[0], 1); std::list list; list.push_back(1); list.push_back(2); std::list list2 = QtConcurrent::blockingFiltered(list, waitFilterfn); QCOMPARE(list2.size(), (std::list::size_type)(1)); QCOMPARE(*list2.begin(), 1); QtConcurrent::filtered(list, waitFilterfn).waitForFinished(); QtConcurrent::filtered(vector, waitFilterfn).waitForFinished(); QtConcurrent::filtered(vector.begin(), vector.end(), waitFilterfn).waitForFinished(); QtConcurrent::blockingFilter(list, waitFilterfn); QCOMPARE(list2.size(), (std::list::size_type)(1)); QCOMPARE(*list2.begin(), 1); } void tst_QtConcurrentFilter::stlContainersLambda() { auto waitFilterLambda = [](const int &i) { return waitFilterfn(i); }; std::vector vector; vector.push_back(1); vector.push_back(2); std::vector vector2 = QtConcurrent::blockingFiltered(vector, waitFilterLambda); QCOMPARE(vector2.size(), (std::vector::size_type)(1)); QCOMPARE(vector2[0], 1); std::list list; list.push_back(1); list.push_back(2); std::list list2 = QtConcurrent::blockingFiltered(list, waitFilterLambda); QCOMPARE(list2.size(), (std::list::size_type)(1)); QCOMPARE(*list2.begin(), 1); QtConcurrent::filtered(list, waitFilterLambda).waitForFinished(); QtConcurrent::filtered(vector, waitFilterLambda).waitForFinished(); QtConcurrent::filtered(vector.begin(), vector.end(), waitFilterLambda).waitForFinished(); QtConcurrent::blockingFilter(list, waitFilterLambda); QCOMPARE(list.size(), (std::list::size_type)(1)); QCOMPARE(*list.begin(), 1); } QTEST_MAIN(tst_QtConcurrentFilter) #include "tst_qtconcurrentfilter.moc"