From 96501b0a18f4f70048403dccc4cb42dd71db8f9d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 Feb 2012 14:17:26 +0100 Subject: Move QtConcurrent into its own module Task-number: QTBUG-20892 Change-Id: I614500aafb6428915509983608bbb0ade4e4f016 Reviewed-by: Thiago Macieira --- tests/auto/auto.pro | 4 + tests/auto/concurrent/concurrent.pro | 12 + tests/auto/concurrent/qfuture/.gitignore | 1 + tests/auto/concurrent/qfuture/qfuture.pro | 5 + tests/auto/concurrent/qfuture/tst_qfuture.cpp | 1438 ++++++++++++ .../qfuturesynchronizer/qfuturesynchronizer.pro | 4 + .../tst_qfuturesynchronizer.cpp | 158 ++ tests/auto/concurrent/qfuturewatcher/.gitignore | 1 + .../concurrent/qfuturewatcher/qfuturewatcher.pro | 4 + .../qfuturewatcher/tst_qfuturewatcher.cpp | 942 ++++++++ .../auto/concurrent/qtconcurrentfilter/.gitignore | 1 + .../qtconcurrentfilter/qtconcurrentfilter.pro | 7 + .../qtconcurrentfilter/tst_qtconcurrentfilter.cpp | 1543 +++++++++++++ .../qtconcurrentiteratekernel/.gitignore | 1 + .../qtconcurrentiteratekernel.pro | 4 + .../tst_qtconcurrentiteratekernel.cpp | 310 +++ tests/auto/concurrent/qtconcurrentmap/.gitignore | 1 + tests/auto/concurrent/qtconcurrentmap/functions.h | 130 ++ .../concurrent/qtconcurrentmap/qtconcurrentmap.pro | 5 + .../qtconcurrentmap/tst_qtconcurrentmap.cpp | 2426 ++++++++++++++++++++ .../qtconcurrentresultstore.pro | 5 + .../tst_qtconcurrentresultstore.cpp | 490 ++++ tests/auto/concurrent/qtconcurrentrun/.gitignore | 1 + .../concurrent/qtconcurrentrun/qtconcurrentrun.pro | 4 + .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 463 ++++ .../concurrent/qtconcurrentthreadengine/.gitignore | 1 + .../qtconcurrentthreadengine.pro | 4 + .../tst_qtconcurrentthreadengine.cpp | 520 +++++ .../corelib/codecs/qtextcodec/tst_qtextcodec.cpp | 82 +- tests/auto/corelib/concurrent/concurrent.pro | 13 - tests/auto/corelib/concurrent/qfuture/.gitignore | 1 - tests/auto/corelib/concurrent/qfuture/qfuture.pro | 5 - .../corelib/concurrent/qfuture/tst_qfuture.cpp | 1438 ------------ .../qfuturesynchronizer/qfuturesynchronizer.pro | 4 - .../tst_qfuturesynchronizer.cpp | 158 -- .../corelib/concurrent/qfuturewatcher/.gitignore | 1 - .../concurrent/qfuturewatcher/qfuturewatcher.pro | 4 - .../qfuturewatcher/tst_qfuturewatcher.cpp | 945 -------- .../concurrent/qtconcurrentfilter/.gitignore | 1 - .../qtconcurrentfilter/qtconcurrentfilter.pro | 7 - .../qtconcurrentfilter/tst_qtconcurrentfilter.cpp | 1543 ------------- .../qtconcurrentiteratekernel/.gitignore | 1 - .../qtconcurrentiteratekernel.pro | 4 - .../tst_qtconcurrentiteratekernel.cpp | 310 --- .../corelib/concurrent/qtconcurrentmap/.gitignore | 1 - .../corelib/concurrent/qtconcurrentmap/functions.h | 130 -- .../concurrent/qtconcurrentmap/qtconcurrentmap.pro | 5 - .../qtconcurrentmap/tst_qtconcurrentmap.cpp | 2426 -------------------- .../qtconcurrentresultstore.pro | 5 - .../tst_qtconcurrentresultstore.cpp | 490 ---- .../corelib/concurrent/qtconcurrentrun/.gitignore | 1 - .../concurrent/qtconcurrentrun/qtconcurrentrun.pro | 4 - .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 463 ---- .../concurrent/qtconcurrentthreadengine/.gitignore | 1 - .../qtconcurrentthreadengine.pro | 4 - .../tst_qtconcurrentthreadengine.cpp | 520 ----- .../auto/corelib/concurrent/qthreadpool/.gitignore | 1 - .../corelib/concurrent/qthreadpool/qthreadpool.pro | 4 - .../concurrent/qthreadpool/tst_qthreadpool.cpp | 849 ------- tests/auto/corelib/corelib.pro | 2 - tests/auto/corelib/thread/qthreadpool/.gitignore | 1 + .../corelib/thread/qthreadpool/qthreadpool.pro | 4 + .../corelib/thread/qthreadpool/tst_qthreadpool.cpp | 849 +++++++ tests/auto/corelib/thread/thread.pro | 1 + 64 files changed, 9393 insertions(+), 9370 deletions(-) create mode 100644 tests/auto/concurrent/concurrent.pro create mode 100644 tests/auto/concurrent/qfuture/.gitignore create mode 100644 tests/auto/concurrent/qfuture/qfuture.pro create mode 100644 tests/auto/concurrent/qfuture/tst_qfuture.cpp create mode 100644 tests/auto/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro create mode 100644 tests/auto/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp create mode 100644 tests/auto/concurrent/qfuturewatcher/.gitignore create mode 100644 tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro create mode 100644 tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp create mode 100644 tests/auto/concurrent/qtconcurrentfilter/.gitignore create mode 100644 tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro create mode 100644 tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp create mode 100644 tests/auto/concurrent/qtconcurrentiteratekernel/.gitignore create mode 100644 tests/auto/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro create mode 100644 tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp create mode 100644 tests/auto/concurrent/qtconcurrentmap/.gitignore create mode 100644 tests/auto/concurrent/qtconcurrentmap/functions.h create mode 100644 tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro create mode 100644 tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp create mode 100644 tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro create mode 100644 tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp create mode 100644 tests/auto/concurrent/qtconcurrentrun/.gitignore create mode 100644 tests/auto/concurrent/qtconcurrentrun/qtconcurrentrun.pro create mode 100644 tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp create mode 100644 tests/auto/concurrent/qtconcurrentthreadengine/.gitignore create mode 100644 tests/auto/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro create mode 100644 tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp delete mode 100644 tests/auto/corelib/concurrent/concurrent.pro delete mode 100644 tests/auto/corelib/concurrent/qfuture/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qfuture/qfuture.pro delete mode 100644 tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp delete mode 100644 tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro delete mode 100644 tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp delete mode 100644 tests/auto/corelib/concurrent/qfuturewatcher/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro delete mode 100644 tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentmap/functions.h delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro delete mode 100644 tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp delete mode 100644 tests/auto/corelib/concurrent/qthreadpool/.gitignore delete mode 100644 tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro delete mode 100644 tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp create mode 100644 tests/auto/corelib/thread/qthreadpool/.gitignore create mode 100644 tests/auto/corelib/thread/qthreadpool/qthreadpool.pro create mode 100644 tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp (limited to 'tests') diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 4f81c43553..1796fa2db9 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -10,6 +10,7 @@ SUBDIRS += \ testlib \ tools \ xml \ + concurrent \ other \ widgets \ @@ -21,3 +22,6 @@ cross_compile: SUBDIRS -= tools mac { network.CONFIG += no_check_target } + +!contains(QT_CONFIG, concurrent): SUBDIRS -= concurrent + diff --git a/tests/auto/concurrent/concurrent.pro b/tests/auto/concurrent/concurrent.pro new file mode 100644 index 0000000000..15368aef64 --- /dev/null +++ b/tests/auto/concurrent/concurrent.pro @@ -0,0 +1,12 @@ +TEMPLATE=subdirs +SUBDIRS=\ + qfuture \ + qfuturesynchronizer \ + qfuturewatcher \ + qtconcurrentfilter \ + qtconcurrentiteratekernel \ + qtconcurrentmap \ + qtconcurrentresultstore \ + qtconcurrentrun \ + qtconcurrentthreadengine + diff --git a/tests/auto/concurrent/qfuture/.gitignore b/tests/auto/concurrent/qfuture/.gitignore new file mode 100644 index 0000000000..77c055c874 --- /dev/null +++ b/tests/auto/concurrent/qfuture/.gitignore @@ -0,0 +1 @@ +tst_qfuture diff --git a/tests/auto/concurrent/qfuture/qfuture.pro b/tests/auto/concurrent/qfuture/qfuture.pro new file mode 100644 index 0000000000..a4c706129d --- /dev/null +++ b/tests/auto/concurrent/qfuture/qfuture.pro @@ -0,0 +1,5 @@ +CONFIG += testcase parallel_test +TARGET = tst_qfuture +QT = concurrent-private testlib concurrent +SOURCES = tst_qfuture.cpp +DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/concurrent/qfuture/tst_qfuture.cpp b/tests/auto/concurrent/qfuture/tst_qfuture.cpp new file mode 100644 index 0000000000..3610f8f2d4 --- /dev/null +++ b/tests/auto/concurrent/qfuture/tst_qfuture.cpp @@ -0,0 +1,1438 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +#define QFUTURE_TEST + +#include +#include +#include +#include +#include +#include + +using namespace QtConcurrent; + +// COM interface macro. +#if defined(Q_OS_WIN) && defined(interface) +# undef interface +#endif + +class tst_QFuture: public QObject +{ + Q_OBJECT +private slots: + void resultStore(); + void future(); + void futureInterface(); + void refcounting(); + void cancel(); + void statePropagation(); + void multipleResults(); + void indexedResults(); + void progress(); + void progressText(); + void resultsAfterFinished(); + void resultsAsList(); + void implicitConversions(); + void iterators(); + void pause(); + void throttling(); + void voidConversions(); +#ifndef QT_NO_EXCEPTIONS + void exceptions(); + void nestedExceptions(); +#endif +}; + +void tst_QFuture::resultStore() +{ + int int0 = 0; + int int1 = 1; + int int2 = 2; + + { + ResultStore store; + QVERIFY(store.begin() == store.end()); + QVERIFY(store.resultAt(0) == store.end()); + QVERIFY(store.resultAt(1) == store.end()); + } + + + { + ResultStoreBase store; + store.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since + store.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QVERIFY(it != store.begin()); + QVERIFY(it == store.end()); + } + + QVector vec0 = QVector() << 2 << 3; + QVector vec1 = QVector() << 4 << 5; + + { + ResultStoreBase store; + store.addResults(-1, &vec0, 2, 2); + store.addResults(-1, &vec1, 2, 2); + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + + ++it; + QCOMPARE(it.resultIndex(), 3); + + ++it; + QVERIFY(it == store.end()); + } + { + ResultStoreBase store; + store.addResult(-1, &int0); + store.addResults(-1, &vec1, 2, 2); + store.addResult(-1, &int1); + + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + QVERIFY(it != store.end()); + ++it; + QCOMPARE(it.resultIndex(), 3); + QVERIFY(it != store.end()); + ++it; + QVERIFY(it == store.end()); + + QCOMPARE(store.resultAt(0).resultIndex(), 0); + QCOMPARE(store.resultAt(1).resultIndex(), 1); + QCOMPARE(store.resultAt(2).resultIndex(), 2); + QCOMPARE(store.resultAt(3).resultIndex(), 3); + QCOMPARE(store.resultAt(4), store.end()); + } + { + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(-1, &int1); + + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + QVERIFY(it != store.end()); + ++it; + QCOMPARE(it.resultIndex(), 3); + QVERIFY(it != store.end()); + ++it; + QVERIFY(it == store.end()); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(3).value(), int1); + } + { + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(200, &int1); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(200).value(), int1); + } + + { + ResultStore store; + store.addResult(1, &int1); + store.addResult(0, &int0); + store.addResult(-1, &int2); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), int1); + QCOMPARE(store.resultAt(2).value(), int2); + } + + { + ResultStore store; + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(INT_MAX), false); + } + + { + // Test filter mode, where "gaps" in the result array aren't allowed. + ResultStore store; + store.setFilterMode(true); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int2); // add result at index 2 + QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. + + store.addResult(1, &int1); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); // 2 should be visible now. + + store.addResult(4, &int0); + store.addResult(5, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(7), false); + + store.addResult(3, &int0); // adding 3 makes 4 and 5 visible + QCOMPARE(store.contains(4), true); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.contains(7), false); + + store.addResult(6, &int0); // adding 6 makes 7 visible + + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + QCOMPARE(store.contains(8), false); + } + + { + // test canceled results + ResultStore store; + store.setFilterMode(true); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int0); + QCOMPARE(store.contains(2), false); + + store.addCanceledResult(1); // report no result at 1 + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 + QCOMPARE(store.contains(2), false); + + store.addResult(3, &int0); + QCOMPARE(store.contains(2), true); //3 gets renamed to 2 + + store.addResult(6, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(3), false); + + store.addCanceledResult(4); + store.addCanceledResult(5); + + QCOMPARE(store.contains(3), true); //6 gets renamed to 3 + QCOMPARE(store.contains(4), true); //7 gets renamed to 4 + + store.addResult(8, &int0); + QCOMPARE(store.contains(5), true); //8 gets renamed to 4 + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } + + { + // test addResult return value + ResultStore store; + store.setFilterMode(true); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 1); // result 0 becomes available + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int0); + QCOMPARE(store.count(), 1); + QCOMPARE(store.contains(2), false); + + store.addCanceledResult(1); + QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + + store.addResult(3, &int0); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(2), true); + + store.addResult(6, &int0); + QCOMPARE(store.count(), 3); + store.addResult(7, &int0); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(3), false); + + store.addCanceledResult(4); + store.addCanceledResult(5); + QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available + + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), true); + + store.addResult(8, &int0); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.count(), 6); + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } + + { + // test resultCount in non-filtered mode. It should always be possible + // to iterate through the results 0 to resultCount. + ResultStore store; + store.addResult(0, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(2, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResult(2, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 4); + } + { + ResultStore store; + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addResult(2, &int0); + QCOMPARE(store.count(), 5); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addCanceledResult(2); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 + + store.addResult(5, &int0); + QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 + } + + { + ResultStore store; + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), false); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + + store.addCanceledResult(0); + store.addCanceledResult(2); + store.addCanceledResults(4, 2); + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } + { + ResultStore store; + store.setFilterMode(true); + store.addCanceledResult(0); + QCOMPARE(store.contains(0), false); + + store.addResult(1, &int0); + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), false); + } +} + +void tst_QFuture::future() +{ + // default constructors + QFuture intFuture; + intFuture.waitForFinished(); + QFuture stringFuture; + stringFuture.waitForFinished(); + QFuture voidFuture; + voidFuture.waitForFinished(); + QFuture defaultVoidFuture; + defaultVoidFuture.waitForFinished(); + + // copy constructor + QFuture intFuture2(intFuture); + QFuture voidFuture2(defaultVoidFuture); + + // assigmnent operator + intFuture2 = QFuture(); + voidFuture2 = QFuture(); + + // state + QCOMPARE(intFuture2.isStarted(), true); + QCOMPARE(intFuture2.isFinished(), true); +} + +class IntResult : public QFutureInterface +{ +public: + QFuture run() + { + this->reportStarted(); + QFuture future = QFuture(this); + + int res = 10; + reportFinished(&res); + return future; + } +}; + +int value = 10; + +class VoidResult : public QFutureInterfaceBase +{ +public: + QFuture run() + { + this->reportStarted(); + QFuture future = QFuture(this); + reportFinished(); + return future; + } +}; + +void tst_QFuture::futureInterface() +{ + { + QFuture future; + { + QFutureInterface i; + i.reportStarted(); + future = i.future(); + i.reportFinished(); + } + } + { + QFuture future; + { + QFutureInterface i; + i.reportStarted(); + i.reportResult(10); + future = i.future(); + i.reportFinished(); + } + QCOMPARE(future.resultAt(0), 10); + } + + { + QFuture intFuture; + + QCOMPARE(intFuture.isStarted(), true); + QCOMPARE(intFuture.isFinished(), true); + + IntResult result; + + result.reportStarted(); + intFuture = result.future(); + + QCOMPARE(intFuture.isStarted(), true); + QCOMPARE(intFuture.isFinished(), false); + + result.reportFinished(&value); + + QCOMPARE(intFuture.isStarted(), true); + QCOMPARE(intFuture.isFinished(), true); + + int e = intFuture.result(); + + QCOMPARE(intFuture.isStarted(), true); + QCOMPARE(intFuture.isFinished(), true); + QCOMPARE(intFuture.isCanceled(), false); + + QCOMPARE(e, value); + intFuture.waitForFinished(); + + IntResult intAlgo; + intFuture = intAlgo.run(); + QFuture intFuture2(intFuture); + QCOMPARE(intFuture.result(), value); + QCOMPARE(intFuture2.result(), value); + intFuture.waitForFinished(); + + VoidResult a; + a.run().waitForFinished(); + } +} + +template +void testRefCounting() +{ + QFutureInterface interface; + QCOMPARE(interface.d->refCount.load(), 1); + + { + interface.reportStarted(); + + QFuture f = interface.future(); + QCOMPARE(interface.d->refCount.load(), 2); + + QFuture f2(f); + QCOMPARE(interface.d->refCount.load(), 3); + + QFuture f3; + f3 = f2; + QCOMPARE(interface.d->refCount.load(), 4); + + interface.reportFinished(0); + QCOMPARE(interface.d->refCount.load(), 4); + } + + QCOMPARE(interface.d->refCount.load(), 1); +} + +void tst_QFuture::refcounting() +{ + testRefCounting(); +} + +void tst_QFuture::cancel() +{ + { + QFuture f; + QFutureInterface result; + + result.reportStarted(); + f = result.future(); + QVERIFY(f.isCanceled() == false); + result.reportCanceled(); + QVERIFY(f.isCanceled()); + result.reportFinished(); + QVERIFY(f.isCanceled()); + f.waitForFinished(); + QVERIFY(f.isCanceled()); + } + + // Cancel from the QFuture side and test if the result + // interface detects it. + { + QFutureInterface result; + + QFuture f; + QVERIFY(f.isStarted() == true); + + result.reportStarted(); + f = result.future(); + + QVERIFY(f.isStarted() == true); + + QVERIFY(result.isCanceled() == false); + f.cancel(); + + QVERIFY(result.isCanceled()); + + result.reportFinished(); + } + + // Test that finished futures can be canceled. + { + QFutureInterface result; + + QFuture f; + QVERIFY(f.isStarted() == true); + + result.reportStarted(); + f = result.future(); + + QVERIFY(f.isStarted() == true); + + result.reportFinished(); + + f.cancel(); + + QVERIFY(result.isCanceled()); + QVERIFY(f.isCanceled()); + } + + // Results reported after canceled is called should not be propagated. + { + + QFutureInterface futureInterface; + futureInterface.reportStarted(); + QFuture f = futureInterface.future(); + + int result = 0; + futureInterface.reportResult(&result); + result = 1; + futureInterface.reportResult(&result); + f.cancel(); + result = 2; + futureInterface.reportResult(&result); + result = 3; + futureInterface.reportResult(&result); + futureInterface.reportFinished(); + QCOMPARE(f.results(), QList()); + } +} + +void tst_QFuture::statePropagation() +{ + QFuture f1; + QFuture f2; + + QCOMPARE(f1.isStarted(), true); + + QFutureInterface result; + result.reportStarted(); + f1 = result.future(); + + f2 = f1; + + QCOMPARE(f2.isStarted(), true); + + result.reportCanceled(); + + QCOMPARE(f2.isStarted(), true); + QCOMPARE(f2.isCanceled(), true); + + QFuture f3 = f2; + + QCOMPARE(f3.isStarted(), true); + QCOMPARE(f3.isCanceled(), true); + + result.reportFinished(); + + QCOMPARE(f2.isStarted(), true); + QCOMPARE(f2.isCanceled(), true); + + QCOMPARE(f3.isStarted(), true); + QCOMPARE(f3.isCanceled(), true); +} + +/* + Tests that a QFuture can return multiple results. +*/ +void tst_QFuture::multipleResults() +{ + IntResult a; + a.reportStarted(); + QFuture f = a.future(); + + QFuture copy = f; + int result; + + result = 1; + a.reportResult(&result); + QCOMPARE(f.resultAt(0), 1); + + result = 2; + a.reportResult(&result); + QCOMPARE(f.resultAt(1), 2); + + result = 3; + a.reportResult(&result); + + result = 4; + a.reportFinished(&result); + + QCOMPARE(f.results(), QList() << 1 << 2 << 3 << 4); + + // test foreach + QList fasit = QList() << 1 << 2 << 3 << 4; + { + QList results; + foreach(int result, f) + results.append(result); + QCOMPARE(results, fasit); + } + { + QList results; + foreach(int result, copy) + results.append(result); + QCOMPARE(results, fasit); + } +} + +/* + Test out-of-order result reporting using indexes +*/ +void tst_QFuture::indexedResults() +{ + { + QFutureInterface Interface; + QFuture f; + QVERIFY(f.isStarted() == true); + + Interface.reportStarted(); + f = Interface.future(); + + QVERIFY(f.isStarted() == true); + + QChar result; + + result = 'B'; + Interface.reportResult(&result, 1); + + QCOMPARE(f.resultAt(1), result); + + result = 'A'; + Interface.reportResult(&result, 0); + QCOMPARE(f.resultAt(0), result); + + result = 'C'; + Interface.reportResult(&result); // no index + QCOMPARE(f.resultAt(2), result); + + Interface.reportFinished(); + + QCOMPARE(f.results(), QList() << 'A' << 'B' << 'C'); + } + + { + // Test result reporting with a missing result in the middle + QFutureInterface Interface; + Interface.reportStarted(); + QFuture f = Interface.future(); + int result; + + result = 0; + Interface.reportResult(&result, 0); + QVERIFY(f.isResultReadyAt(0)); + QCOMPARE(f.resultAt(0), 0); + + result = 3; + Interface.reportResult(&result, 3); + QVERIFY(f.isResultReadyAt(3)); + QCOMPARE(f.resultAt(3), 3); + + result = 2; + Interface.reportResult(&result, 2); + QVERIFY(f.isResultReadyAt(2)); + QCOMPARE(f.resultAt(2), 2); + + result = 4; + Interface.reportResult(&result); // no index + QVERIFY(f.isResultReadyAt(4)); + QCOMPARE(f.resultAt(4), 4); + + Interface.reportFinished(); + + QCOMPARE(f.results(), QList() << 0 << 2 << 3 << 4); + } +} + +void tst_QFuture::progress() +{ + QFutureInterface result; + QFuture f; + + QCOMPARE (f.progressValue(), 0); + + result.reportStarted(); + f = result.future(); + + QCOMPARE (f.progressValue(), 0); + + result.setProgressValue(50); + + QCOMPARE (f.progressValue(), 50); + + result.reportFinished(); + + QCOMPARE (f.progressValue(), 50); +} + +void tst_QFuture::progressText() +{ + QFutureInterface i; + i.reportStarted(); + QFuture f = i.future(); + + QCOMPARE(f.progressText(), QLatin1String("")); + i.setProgressValueAndText(1, QLatin1String("foo")); + QCOMPARE(f.progressText(), QLatin1String("foo")); + i.reportFinished(); +} + +/* + Test that results reported after finished are ignored. +*/ +void tst_QFuture::resultsAfterFinished() +{ + { + IntResult a; + a.reportStarted(); + QFuture f = a.future(); + int result; + + QCOMPARE(f.resultCount(), 0); + + result = 1; + a.reportResult(&result); + QCOMPARE(f.resultAt(0), 1); + + a.reportFinished(); + + QCOMPARE(f.resultAt(0), 1); + QCOMPARE(f.resultCount(), 1); + result = 2; + a.reportResult(&result); + QCOMPARE(f.resultCount(), 1); + } + // cancel it + { + IntResult a; + a.reportStarted(); + QFuture f = a.future(); + int result; + + QCOMPARE(f.resultCount(), 0); + + result = 1; + a.reportResult(&result); + QCOMPARE(f.resultAt(0), 1); + QCOMPARE(f.resultCount(), 1); + + a.reportCanceled(); + + QCOMPARE(f.resultAt(0), 1); + QCOMPARE(f.resultCount(), 1); + + result = 2; + a.reportResult(&result); + a.reportFinished(); + } +} + +void tst_QFuture::resultsAsList() +{ + IntResult a; + a.reportStarted(); + QFuture f = a.future(); + + int result; + result = 1; + a.reportResult(&result); + result = 2; + a.reportResult(&result); + + a.reportFinished(); + + QList results = f.results(); + QCOMPARE(results, QList() << 1 << 2); +} + +/* + Test that QFuture can be implicitly converted to T +*/ +void tst_QFuture::implicitConversions() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture f(&iface); + + const QString input("FooBar 2000"); + iface.reportFinished(&input); + + const QString result = f; + QCOMPARE(result, input); + QCOMPARE(QString(f), input); + QCOMPARE(static_cast(f), input); +} + +void tst_QFuture::iterators() +{ + { + QFutureInterface e; + e.reportStarted(); + QFuture f = e.future(); + + int result; + result = 1; + e.reportResult(&result); + result = 2; + e.reportResult(&result); + result = 3; + e.reportResult(&result); + e.reportFinished(); + + QList results; + QFutureIterator i(f); + while (i.hasNext()) { + results.append(i.next()); + } + + QCOMPARE(results, f.results()); + + QFuture::const_iterator i1 = f.begin(), i2 = i1 + 1; + QFuture::const_iterator c1 = i1, c2 = c1 + 1; + + QVERIFY(i1 == i1); + QVERIFY(i1 == c1); + QVERIFY(c1 == i1); + QVERIFY(c1 == c1); + QVERIFY(i2 == i2); + QVERIFY(i2 == c2); + QVERIFY(c2 == i2); + QVERIFY(c2 == c2); + + QVERIFY(i1 != i2); + QVERIFY(i1 != c2); + QVERIFY(c1 != i2); + QVERIFY(c1 != c2); + QVERIFY(i2 != i1); + QVERIFY(i2 != c1); + QVERIFY(c2 != i1); + QVERIFY(c2 != c1); + + int x1 = *i1; + Q_UNUSED(x1); + int x2 = *i2; + Q_UNUSED(x2); + int y1 = *c1; + Q_UNUSED(y1); + int y2 = *c2; + Q_UNUSED(y2); + } + + { + QFutureInterface e; + e.reportStarted(); + QFuture f = e.future(); + + e.reportResult(QString("one")); + e.reportResult(QString("two")); + e.reportResult(QString("three")); + e.reportFinished(); + + QList results; + QFutureIterator i(f); + while (i.hasNext()) { + results.append(i.next()); + } + + QCOMPARE(results, f.results()); + + QFuture::const_iterator i1 = f.begin(), i2 = i1 + 1; + QFuture::const_iterator c1 = i1, c2 = c1 + 1; + + QVERIFY(i1 == i1); + QVERIFY(i1 == c1); + QVERIFY(c1 == i1); + QVERIFY(c1 == c1); + QVERIFY(i2 == i2); + QVERIFY(i2 == c2); + QVERIFY(c2 == i2); + QVERIFY(c2 == c2); + + QVERIFY(i1 != i2); + QVERIFY(i1 != c2); + QVERIFY(c1 != i2); + QVERIFY(c1 != c2); + QVERIFY(i2 != i1); + QVERIFY(i2 != c1); + QVERIFY(c2 != i1); + QVERIFY(c2 != c1); + + QString x1 = *i1; + QString x2 = *i2; + QString y1 = *c1; + QString y2 = *c2; + + QCOMPARE(x1, y1); + QCOMPARE(x2, y2); + + int i1Size = i1->size(); + int i2Size = i2->size(); + int c1Size = c1->size(); + int c2Size = c2->size(); + + QCOMPARE(i1Size, c1Size); + QCOMPARE(i2Size, c2Size); + } + + { + const int resultCount = 20; + + QFutureInterface e; + e.reportStarted(); + QFuture f = e.future(); + + for (int i = 0; i < resultCount; ++i) { + e.reportResult(i); + } + + e.reportFinished(); + + { + QFutureIterator it(f); + QFutureIterator it2(it); + } + + { + QFutureIterator it(f); + + for (int i = 0; i < resultCount - 1; ++i) { + QVERIFY(it.hasNext()); + QCOMPARE(it.peekNext(), i); + QCOMPARE(it.next(), i); + } + + QVERIFY(it.hasNext()); + QCOMPARE(it.peekNext(), resultCount - 1); + QCOMPARE(it.next(), resultCount - 1); + QVERIFY(it.hasNext() == false); + } + + { + QFutureIterator it(f); + QVERIFY(it.hasNext()); + it.toBack(); + QVERIFY(it.hasNext() == false); + it.toFront(); + QVERIFY(it.hasNext()); + } + } +} + +class SignalSlotObject : public QObject +{ +Q_OBJECT +public: + SignalSlotObject() + : finishedCalled(false), + canceledCalled(false), + rangeBegin(0), + rangeEnd(0) { } + +public slots: + void finished() + { + finishedCalled = true; + } + + void canceled() + { + canceledCalled = true; + } + + void resultReady(int index) + { + results.insert(index); + } + + void progressRange(int begin, int end) + { + rangeBegin = begin; + rangeEnd = end; + } + + void progress(int progress) + { + reportedProgress.insert(progress); + } +public: + bool finishedCalled; + bool canceledCalled; + QSet results; + int rangeBegin; + int rangeEnd; + QSet reportedProgress; +}; + +void tst_QFuture::pause() +{ + QFutureInterface Interface; + + Interface.reportStarted(); + QFuture f = Interface.future(); + + QVERIFY(Interface.isPaused() == false); + f.pause(); + QVERIFY(Interface.isPaused() == true); + f.resume(); + QVERIFY(Interface.isPaused() == false); + f.togglePaused(); + QVERIFY(Interface.isPaused() == true); + f.togglePaused(); + QVERIFY(Interface.isPaused() == false); + + Interface.reportFinished(); +} + +const int resultCount = 1000; + +class ResultObject : public QObject +{ +Q_OBJECT +public slots: + void resultReady(int) + { + + } +public: +}; + +// Test that that the isPaused() on future result interface returns true +// if we report a lot of results that are not handled. +void tst_QFuture::throttling() +{ + { + QFutureInterface i; + + i.reportStarted(); + QFuture f = i.future(); + + QVERIFY(i.isThrottled() == false); + + i.setThrottled(true); + QVERIFY(i.isThrottled()); + + i.setThrottled(false); + QVERIFY(i.isThrottled() == false); + + i.setThrottled(true); + QVERIFY(i.isThrottled()); + + i.reportFinished(); + } +} + +void tst_QFuture::voidConversions() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture intFuture(&iface); + + int value = 10; + iface.reportFinished(&value); + + QFuture voidFuture(intFuture); + voidFuture = intFuture; + + QVERIFY(voidFuture == intFuture); +} + + +#ifndef QT_NO_EXCEPTIONS + +QFuture createExceptionFuture() +{ + QFutureInterface i; + i.reportStarted(); + QFuture f = i.future(); + + Exception e; + i.reportException(e); + i.reportFinished(); + return f; +} + +QFuture createExceptionResultFuture() +{ + QFutureInterface i; + i.reportStarted(); + QFuture f = i.future(); + int r = 0; + i.reportResult(r); + + Exception e; + i.reportException(e); + i.reportFinished(); + return f; +} + +class DerivedException : public Exception +{ +public: + void raise() const { throw *this; } + Exception *clone() const { return new DerivedException(*this); } +}; + +QFuture createDerivedExceptionFuture() +{ + QFutureInterface i; + i.reportStarted(); + QFuture f = i.future(); + + DerivedException e; + i.reportException(e); + i.reportFinished(); + return f; +} + +void tst_QFuture::exceptions() +{ + // test throwing from waitForFinished + { + QFuture f = createExceptionFuture(); + bool caught = false; + try { + f.waitForFinished(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + // test result() + { + QFuture f = createExceptionResultFuture(); + bool caught = false; + try { + f.result(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + // test result() and destroy + { + bool caught = false; + try { + createExceptionResultFuture().result(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + // test results() + { + QFuture f = createExceptionResultFuture(); + bool caught = false; + try { + f.results(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + // test foreach + { + QFuture f = createExceptionResultFuture(); + bool caught = false; + try { + foreach (int e, f.results()) { + Q_UNUSED(e); + QFAIL("did not get exception"); + } + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + // catch derived exceptions + { + bool caught = false; + try { + createDerivedExceptionFuture().waitForFinished(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + + { + bool caught = false; + try { + createDerivedExceptionFuture().waitForFinished(); + } catch (DerivedException &) { + caught = true; + } + QVERIFY(caught); + } +} + +class MyClass +{ +public: + ~MyClass() + { + QFuture f = createExceptionFuture(); + try { + f.waitForFinished(); + } catch (Exception &) { + caught = true; + } + } + static bool caught; +}; + +bool MyClass::caught = false; + +// This is a regression test for QTBUG-18149. where QFuture did not throw +// exceptions if called from destructors when the stack was already unwinding +// due to an exception having been thrown. +void tst_QFuture::nestedExceptions() +{ + try { + MyClass m; + Q_UNUSED(m); + throw 0; + } catch (int) {} + + QVERIFY(MyClass::caught); +} + +#endif // QT_NO_EXCEPTIONS + +QTEST_MAIN(tst_QFuture) +#include "tst_qfuture.moc" diff --git a/tests/auto/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro b/tests/auto/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro new file mode 100644 index 0000000000..331a8e3c05 --- /dev/null +++ b/tests/auto/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qfuturesynchronizer +QT = core testlib concurrent +SOURCES = tst_qfuturesynchronizer.cpp diff --git a/tests/auto/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp new file mode 100644 index 0000000000..012c90de18 --- /dev/null +++ b/tests/auto/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +class tst_QFutureSynchronizer : public QObject +{ + Q_OBJECT + + +private Q_SLOTS: + void construction(); + void addFuture(); + void cancelOnWait(); + void clearFutures(); + void futures(); + void setFuture(); + void waitForFinished(); +}; + + +void tst_QFutureSynchronizer::construction() +{ + + QFuture future; + QFutureSynchronizer synchronizer; + QFutureSynchronizer synchronizerWithFuture(future); + + QCOMPARE(synchronizer.futures().size(), 0); + QCOMPARE(synchronizerWithFuture.futures().size(), 1); +} + +void tst_QFutureSynchronizer::addFuture() +{ + QFutureSynchronizer synchronizer; + + synchronizer.addFuture(QFuture()); + QFuture future; + synchronizer.addFuture(future); + synchronizer.addFuture(future); + + QCOMPARE(synchronizer.futures().size(), 3); +} + +void tst_QFutureSynchronizer::cancelOnWait() +{ + QFutureSynchronizer synchronizer; + QVERIFY(!synchronizer.cancelOnWait()); + synchronizer.setCancelOnWait(true); + QVERIFY(synchronizer.cancelOnWait()); + synchronizer.setCancelOnWait(false); + QVERIFY(!synchronizer.cancelOnWait()); + synchronizer.setCancelOnWait(true); + QVERIFY(synchronizer.cancelOnWait()); +} + +void tst_QFutureSynchronizer::clearFutures() +{ + QFutureSynchronizer synchronizer; + synchronizer.clearFutures(); + QVERIFY(synchronizer.futures().isEmpty()); + + synchronizer.addFuture(QFuture()); + QFuture future; + synchronizer.addFuture(future); + synchronizer.addFuture(future); + synchronizer.clearFutures(); + QVERIFY(synchronizer.futures().isEmpty()); +} + +void tst_QFutureSynchronizer::futures() +{ + QFutureSynchronizer synchronizer; + + QList > futures; + for (int i=0; i<100; i++) { + QFuture future; + futures.append(future); + synchronizer.addFuture(future); + } + + QCOMPARE(futures, synchronizer.futures()); +} + +void tst_QFutureSynchronizer::setFuture() +{ + QFutureSynchronizer synchronizer; + + for (int i=0; i<100; i++) { + synchronizer.addFuture(QFuture()); + } + QCOMPARE(synchronizer.futures().size(), 100); + + QFuture future; + synchronizer.setFuture(future); + QCOMPARE(synchronizer.futures().size(), 1); + QCOMPARE(synchronizer.futures().first(), future); +} + +void tst_QFutureSynchronizer::waitForFinished() +{ + QFutureSynchronizer synchronizer; + + for (int i=0; i<100; i++) { + synchronizer.addFuture(QFuture()); + } + synchronizer.waitForFinished(); + const QList > futures = synchronizer.futures(); + + for (int i=0; i<100; i++) { + QVERIFY(futures.at(i).isFinished()); + } +} + +QTEST_MAIN(tst_QFutureSynchronizer) + +#include "tst_qfuturesynchronizer.moc" diff --git a/tests/auto/concurrent/qfuturewatcher/.gitignore b/tests/auto/concurrent/qfuturewatcher/.gitignore new file mode 100644 index 0000000000..1d778431c5 --- /dev/null +++ b/tests/auto/concurrent/qfuturewatcher/.gitignore @@ -0,0 +1 @@ +tst_qfuturewatcher diff --git a/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro b/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro new file mode 100644 index 0000000000..3b8ebda4a4 --- /dev/null +++ b/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qfuturewatcher +QT = concurrent-private testlib concurrent +SOURCES = tst_qfuturewatcher.cpp diff --git a/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp new file mode 100644 index 0000000000..fe3eb378d5 --- /dev/null +++ b/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp @@ -0,0 +1,942 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include + +#include +#include + +using namespace QtConcurrent; + +#include + +//#define PRINT + +class tst_QFutureWatcher: public QObject +{ + Q_OBJECT +private slots: + void startFinish(); + void progressValueChanged(); + void canceled(); + void resultAt(); + void resultReadyAt(); + void futureSignals(); + void watchFinishedFuture(); + void watchCanceledFuture(); + void disconnectRunningFuture(); + void tooMuchProgress(); + void progressText(); + void sharedFutureInterface(); + void changeFuture(); + void cancelEvents(); + void pauseEvents(); + void finishedState(); + void throttling(); + void incrementalMapResults(); + void incrementalFilterResults(); + void qfutureSynchronizer(); + void warnRace(); +}; + +void sleeper() +{ + QTest::qSleep(100); +} + +void tst_QFutureWatcher::startFinish() +{ + QFutureWatcher futureWatcher; + + QSignalSpy startedSpy(&futureWatcher, SIGNAL(started())); + QSignalSpy finishedSpy(&futureWatcher, SIGNAL(finished())); + + QVERIFY(startedSpy.isValid()); + QVERIFY(finishedSpy.isValid()); + + futureWatcher.setFuture(QtConcurrent::run(sleeper)); + QTest::qWait(10); // spin the event loop to deliver queued signals. + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); + futureWatcher.future().waitForFinished(); + QTest::qWait(10); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); +} + +void mapSleeper(int &) +{ + QTest::qSleep(100); +} + +QSet progressValues; +QSet progressTexts; +QMutex mutex; +class ProgressObject : public QObject +{ +Q_OBJECT +public slots: + void printProgress(int); + void printText(const QString &text); + void registerProgress(int); + void registerText(const QString &text); +}; + +void ProgressObject::printProgress(int progress) +{ + qDebug() << "thread" << QThread::currentThread() << "reports progress" << progress; +} + +void ProgressObject::printText(const QString &text) +{ + qDebug() << "thread" << QThread::currentThread() << "reports progress text" << text; +} + +void ProgressObject::registerProgress(int progress) +{ + QTest::qSleep(1); + progressValues.insert(progress); +} + +void ProgressObject::registerText(const QString &text) +{ + QTest::qSleep(1); + progressTexts.insert(text); +} + + +QList createList(int listSize) +{ + QList list; + for (int i = 0; i < listSize; ++i) { + list.append(i); + } + return list; +} + +void tst_QFutureWatcher::progressValueChanged() +{ +#ifdef PRINT + qDebug() << "main thread" << QThread::currentThread(); +#endif + + progressValues.clear(); + const int listSize = 20; + QList list = createList(listSize); + + QFutureWatcher futureWatcher; + ProgressObject progressObject; + QObject::connect(&futureWatcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); +#ifdef PRINT + QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(printProgress(int)), Qt::DirectConnection ); +#endif + QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(registerProgress(int))); + + futureWatcher.setFuture(QtConcurrent::map(list, mapSleeper)); + + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + futureWatcher.disconnect(); + QVERIFY(progressValues.contains(0)); + QVERIFY(progressValues.contains(listSize)); +} + +class CancelObject : public QObject +{ +Q_OBJECT +public: + bool wasCanceled; + CancelObject() : wasCanceled(false) {}; +public slots: + void cancel(); +}; + +void CancelObject::cancel() +{ +#ifdef PRINT + qDebug() << "thread" << QThread::currentThread() << "reports canceled"; +#endif + wasCanceled = true; +} + +void tst_QFutureWatcher::canceled() +{ + const int listSize = 20; + QList list = createList(listSize); + + QFutureWatcher futureWatcher; + QFuture future; + CancelObject cancelObject; + + QObject::connect(&futureWatcher, SIGNAL(canceled()), &cancelObject, SLOT(cancel())); + QObject::connect(&futureWatcher, SIGNAL(canceled()), + &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + + future = QtConcurrent::map(list, mapSleeper); + futureWatcher.setFuture(future); + futureWatcher.cancel(); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(future.isCanceled()); + QVERIFY(cancelObject.wasCanceled); + futureWatcher.disconnect(); + future.waitForFinished(); +} + +class IntTask : public RunFunctionTask +{ +public: + void runFunctor() + { + result = 10; + } +}; + +void tst_QFutureWatcher::resultAt() +{ + QFutureWatcher futureWatcher; + futureWatcher.setFuture((new IntTask())->start()); + futureWatcher.waitForFinished(); + QCOMPARE(futureWatcher.result(), 10); + QCOMPARE(futureWatcher.resultAt(0), 10); +} + +void tst_QFutureWatcher::resultReadyAt() +{ + QFutureWatcher futureWatcher; + QObject::connect(&futureWatcher, SIGNAL(resultReadyAt(int)), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + + QFuture future = (new IntTask())->start(); + futureWatcher.setFuture(future); + + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // Setting the future again should give us another signal. + // (this is to prevent the race where the task associated + // with the future finishes before setFuture is called.) + futureWatcher.setFuture(QFuture()); + futureWatcher.setFuture(future); + + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + +class SignalSlotObject : public QObject +{ +Q_OBJECT + +signals: + void cancel(); + +public slots: + void started() + { + qDebug() << "started called"; + } + + void finished() + { + qDebug() << "finished called"; + } + + void canceled() + { + qDebug() << "canceled called"; + } + +#ifdef PRINT + void resultReadyAt(int index) + { + qDebug() << "result" << index << "ready"; + } +#else + void resultReadyAt(int) { } +#endif + void progressValueChanged(int progress) + { + qDebug() << "progress" << progress; + } + + void progressRangeChanged(int min, int max) + { + qDebug() << "progress range" << min << max; + } + +}; + +void tst_QFutureWatcher::futureSignals() +{ + { + QFutureInterface a; + QFutureWatcher f; + + SignalSlotObject object; +#ifdef PRINT + connect(&f, SIGNAL(finished()), &object, SLOT(finished())); + connect(&f, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); +#endif + // must connect to resultReadyAt so that the watcher can detect the connection + // (QSignalSpy does not trigger it.) + connect(&f, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + a.reportStarted(); + f.setFuture(a.future()); + + QSignalSpy progressSpy(&f, SIGNAL(progressValueChanged(int))); + QVERIFY(progressSpy.isValid()); + const int progress = 1; + a.setProgressValue(progress); + QTest::qWait(10); + QCOMPARE(progressSpy.count(), 2); + QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 0); + QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 1); + + QSignalSpy finishedSpy(&f, SIGNAL(finished())); + QSignalSpy resultReadySpy(&f, SIGNAL(resultReadyAt(int))); + + QVERIFY(finishedSpy.isValid()); + QVERIFY(resultReadySpy.isValid()); + + const int result = 10; + a.reportResult(&result); + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 1); + a.reportFinished(&result); + QTest::qWait(10); + + QCOMPARE(resultReadySpy.count(), 2); + QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 0); // check the index + QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 1); + + QCOMPARE(finishedSpy.count(), 1); + } +} + +void tst_QFutureWatcher::watchFinishedFuture() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture f = iface.future(); + + int value = 100; + iface.reportFinished(&value); + + QFutureWatcher watcher; + + SignalSlotObject object; +#ifdef PRINT + connect(&watcher, SIGNAL(started()), &object, SLOT(started())); + connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled())); + connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); + connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); + connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int))); +#endif + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + + QSignalSpy startedSpy(&watcher, SIGNAL(started())); + QSignalSpy finishedSpy(&watcher, SIGNAL(finished())); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QSignalSpy canceledSpy(&watcher, SIGNAL(canceled())); + + QVERIFY(startedSpy.isValid()); + QVERIFY(finishedSpy.isValid()); + QVERIFY(resultReadySpy.isValid()); + QVERIFY(canceledSpy.isValid()); + + watcher.setFuture(f); + QTest::qWait(10); + + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(resultReadySpy.count(), 1); + QCOMPARE(canceledSpy.count(), 0); +} + +void tst_QFutureWatcher::watchCanceledFuture() +{ + QFuture f; + QFutureWatcher watcher; + + SignalSlotObject object; +#ifdef PRINT + connect(&watcher, SIGNAL(started()), &object, SLOT(started())); + connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled())); + connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); + connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); + connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int))); +#endif + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + + QSignalSpy startedSpy(&watcher, SIGNAL(started())); + QSignalSpy finishedSpy(&watcher, SIGNAL(finished())); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QSignalSpy canceledSpy(&watcher, SIGNAL(canceled())); + + QVERIFY(startedSpy.isValid()); + QVERIFY(finishedSpy.isValid()); + QVERIFY(resultReadySpy.isValid()); + QVERIFY(canceledSpy.isValid()); + + watcher.setFuture(f); + QTest::qWait(10); + + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(resultReadySpy.count(), 0); + QCOMPARE(canceledSpy.count(), 1); +} + +void tst_QFutureWatcher::disconnectRunningFuture() +{ + QFutureInterface a; + a.reportStarted(); + + QFuture f = a.future(); + QFutureWatcher *watcher = new QFutureWatcher(); + watcher->setFuture(f); + + SignalSlotObject object; + connect(watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + + QSignalSpy finishedSpy(watcher, SIGNAL(finished())); + QSignalSpy resultReadySpy(watcher, SIGNAL(resultReadyAt(int))); + + QVERIFY(finishedSpy.isValid()); + QVERIFY(resultReadySpy.isValid()); + + const int result = 10; + a.reportResult(&result); + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 1); + + delete watcher; + + a.reportResult(&result); + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 1); + + a.reportFinished(&result); + QTest::qWait(10); + QCOMPARE(finishedSpy.count(), 0); +} + +const int maxProgress = 100000; +class ProgressEmitterTask : public RunFunctionTask +{ +public: + void runFunctor() + { + setProgressRange(0, maxProgress); + for (int p = 0; p <= maxProgress; ++p) + setProgressValue(p); + } +}; + +void tst_QFutureWatcher::tooMuchProgress() +{ + progressValues.clear(); + ProgressObject o; + + QFutureWatcher f; + QObject::connect(&f, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); +#ifdef PRINT + QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int))); +#endif + QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int))); + f.setFuture((new ProgressEmitterTask())->start()); + + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(progressValues.contains(maxProgress)); +} + +template +class ProgressTextTask : public RunFunctionTask +{ +public: + void runFunctor() + { + this->setProgressValueAndText(1, QLatin1String("Foo 1")); + + while (this->isProgressUpdateNeeded() == false) + QTest::qSleep(1); + this->setProgressValueAndText(2, QLatin1String("Foo 2")); + + while (this->isProgressUpdateNeeded() == false) + QTest::qSleep(1); + this->setProgressValueAndText(3, QLatin1String("Foo 3")); + + while (this->isProgressUpdateNeeded() == false) + QTest::qSleep(1); + this->setProgressValueAndText(4, QLatin1String("Foo 4")); + } +}; + +void tst_QFutureWatcher::progressText() +{ + { // instantiate API for T=int and T=void. + ProgressTextTask a; + ProgressTextTask b; + } + { + progressValues.clear(); + progressTexts.clear(); + QFuture f = ((new ProgressTextTask())->start()); + QFutureWatcher watcher; + ProgressObject o; + QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); +#ifdef PRINT + QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int))); + QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(printText(const QString &))); +#endif + QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int))); + QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(registerText(const QString &))); + + watcher.setFuture(f); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(f.progressText(), QLatin1String("Foo 4")); + QCOMPARE(f.progressValue(), 4); + QVERIFY(progressValues.contains(1)); + QVERIFY(progressValues.contains(2)); + QVERIFY(progressValues.contains(3)); + QVERIFY(progressValues.contains(4)); + QVERIFY(progressTexts.contains(QLatin1String("Foo 1"))); + QVERIFY(progressTexts.contains(QLatin1String("Foo 2"))); + QVERIFY(progressTexts.contains(QLatin1String("Foo 3"))); + QVERIFY(progressTexts.contains(QLatin1String("Foo 4"))); + } +} + +template +void callInterface(T &obj) +{ + obj.progressValue(); + obj.progressMinimum(); + obj.progressMaximum(); + obj.progressText(); + + obj.isStarted(); + obj.isFinished(); + obj.isRunning(); + obj.isCanceled(); + obj.isPaused(); + + obj.cancel(); + obj.pause(); + obj.resume(); + obj.togglePaused(); + obj.waitForFinished(); + + const T& objConst = obj; + objConst.progressValue(); + objConst.progressMinimum(); + objConst.progressMaximum(); + objConst.progressText(); + + objConst.isStarted(); + objConst.isFinished(); + objConst.isRunning(); + objConst.isCanceled(); + objConst.isPaused(); +} + +template +void callInterface(const T &obj) +{ + obj.result(); + obj.resultAt(0); +} + + +// QFutureWatcher and QFuture has a similar interface. Test +// that the functions we want ot have in both are actually +// there. +void tst_QFutureWatcher::sharedFutureInterface() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture intFuture = iface.future(); + + int value = 0; + iface.reportFinished(&value); + + QFuture voidFuture; + QFutureWatcher intWatcher; + intWatcher.setFuture(intFuture); + QFutureWatcher voidWatcher; + + callInterface(intFuture); + callInterface(voidFuture); + callInterface(intWatcher); + callInterface(voidWatcher); + + callInterface(intFuture); + callInterface(intWatcher); +} + +void tst_QFutureWatcher::changeFuture() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture a = iface.future(); + + int value = 0; + iface.reportFinished(&value); + + QFuture b; + + QFutureWatcher watcher; + + SignalSlotObject object; + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QVERIFY(resultReadySpy.isValid()); + + watcher.setFuture(a); // Watch 'a' which will genere a resultReady event. + watcher.setFuture(b); // But oh no! we're switching to another future + QTest::qWait(10); // before the event gets delivered. + + QCOMPARE(resultReadySpy.count(), 0); + + watcher.setFuture(a); + watcher.setFuture(b); + watcher.setFuture(a); // setting it back gets us one event, not two. + QTest::qWait(10); + + QCOMPARE(resultReadySpy.count(), 1); +} + +// Test that events aren't delivered from canceled futures +void tst_QFutureWatcher::cancelEvents() +{ + QFutureInterface iface; + iface.reportStarted(); + + QFuture a = iface.future(); + + int value = 0; + iface.reportFinished(&value); + + QFutureWatcher watcher; + + SignalSlotObject object; + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QVERIFY(resultReadySpy.isValid()); + + watcher.setFuture(a); + watcher.cancel(); + + QTest::qWait(10); + + QCOMPARE(resultReadySpy.count(), 0); +} + +// Tests that events from paused futures are saved and +// delivered on resume. +void tst_QFutureWatcher::pauseEvents() +{ + { + QFutureInterface iface; + iface.reportStarted(); + + QFuture a = iface.future(); + + int value = 0; + iface.reportFinished(&value); + + QFutureWatcher watcher; + + SignalSlotObject object; + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QVERIFY(resultReadySpy.isValid()); + + watcher.setFuture(a); + watcher.pause(); + + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 0); + + watcher.resume(); + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 1); + } + { + QFutureInterface iface; + iface.reportStarted(); + + QFuture a = iface.future(); + + int value = 0; + iface.reportFinished(&value); + + QFutureWatcher watcher; + + SignalSlotObject object; + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); + QVERIFY(resultReadySpy.isValid()); + + watcher.setFuture(a); + a.pause(); + + QFuture b; + watcher.setFuture(b); // If we watch b instead, resuming a + a.resume(); // should give us no results. + + QTest::qWait(10); + QCOMPARE(resultReadySpy.count(), 0); + } +} + +// Test that the finished state for the watcher gets +// set when the finished event is delivered. +// This means it will lag the finished state for the future, +// but makes it more useful. +void tst_QFutureWatcher::finishedState() +{ + QFutureInterface iface; + iface.reportStarted(); + QFuture future = iface.future(); + QFutureWatcher watcher; + + watcher.setFuture(future); + QTest::qWait(10); + + iface.reportFinished(); + QVERIFY(future.isFinished()); + QVERIFY(watcher.isFinished() == false); + + QTest::qWait(10); + QVERIFY(watcher.isFinished()); +} + +/* + Verify that throttling kicks in if you report a lot of results, + and that it clears when the result events are processed. +*/ +void tst_QFutureWatcher::throttling() +{ + QFutureInterface iface; + iface.reportStarted(); + QFuture future = iface.future(); + QFutureWatcher watcher; + watcher.setFuture(future); + + QVERIFY(iface.isThrottled() == false); + + for (int i = 0; i < 1000; ++i) { + int result = 0; + iface.reportResult(result); + } + + QVERIFY(iface.isThrottled() == true); + + QTest::qWait(100); // process events. + + QVERIFY(iface.isThrottled() == false); + + iface.reportFinished(); +} + +int mapper(const int &i) +{ + return i; +} + +class ResultReadyTester : public QObject +{ +Q_OBJECT +public: + ResultReadyTester(QFutureWatcher *watcher) + :m_watcher(watcher), filter(false), ok(true), count(0) + { + + } +public slots: + void resultReadyAt(int index) + { + ++count; + if (m_watcher->future().isResultReadyAt(index) == false) + ok = false; + if (!filter && m_watcher->future().resultAt(index) != index) + ok = false; + if (filter && m_watcher->future().resultAt(index) != index * 2 + 1) + ok = false; + } +public: + QFutureWatcher *m_watcher; + bool filter; + bool ok; + int count; +}; + +void tst_QFutureWatcher::incrementalMapResults() +{ + QFutureWatcher watcher; + + SignalSlotObject object; +#ifdef PRINT + connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); + connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); +#endif + + QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + ResultReadyTester resultReadyTester(&watcher); + connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int))); + + const int count = 10000; + QList ints; + for (int i = 0; i < count; ++i) + ints << i; + + QFuture future = QtConcurrent::mapped(ints, mapper); + watcher.setFuture(future); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(resultReadyTester.count, count); + QVERIFY(resultReadyTester.ok); + QVERIFY(watcher.isFinished()); + future.waitForFinished(); +} + +bool filterer(int i) +{ + return (i % 2); +} + +void tst_QFutureWatcher::incrementalFilterResults() +{ + QFutureWatcher watcher; + + SignalSlotObject object; +#ifdef PRINT + connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); + connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); + connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); +#endif + + QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + + ResultReadyTester resultReadyTester(&watcher); + resultReadyTester.filter = true; + connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int))); + + const int count = 10000; + QList ints; + for (int i = 0; i < count; ++i) + ints << i; + + QFuture future = QtConcurrent::filtered(ints, filterer); + watcher.setFuture(future); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(resultReadyTester.count, count / 2); + QVERIFY(resultReadyTester.ok); + QVERIFY(watcher.isFinished()); + future.waitForFinished(); +} + +void tst_QFutureWatcher::qfutureSynchronizer() +{ + int taskCount = 1000; + QTime t; + t.start(); + + { + QFutureSynchronizer sync; + + sync.setCancelOnWait(true); + for (int i = 0; i < taskCount; ++i) { + sync.addFuture(run(sleeper)); + } + } + + // Test that we're not running each task. + QVERIFY(t.elapsed() < taskCount * 10); +} + +class DummyObject : public QObject { + Q_OBJECT +public slots: + void dummySlot() {} +public: + static void function(QMutex *m) + { + QMutexLocker lock(m); + } +}; + +void tst_QFutureWatcher::warnRace() +{ +#ifndef Q_OS_MAC //I don't know why it is not working on mac +#ifndef QT_NO_DEBUG + QTest::ignoreMessage(QtWarningMsg, "QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); +#endif +#endif + QFutureWatcher watcher; + DummyObject object; + QMutex mutex; + mutex.lock(); + + QFuture future = QtConcurrent::run(DummyObject::function, &mutex); + watcher.setFuture(future); + QTRY_VERIFY(future.isStarted()); + connect(&watcher, SIGNAL(finished()), &object, SLOT(dummySlot())); + mutex.unlock(); + future.waitForFinished(); +} + +QTEST_MAIN(tst_QFutureWatcher) +#include "tst_qfuturewatcher.moc" diff --git a/tests/auto/concurrent/qtconcurrentfilter/.gitignore b/tests/auto/concurrent/qtconcurrentfilter/.gitignore new file mode 100644 index 0000000000..f93d27e009 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentfilter/.gitignore @@ -0,0 +1 @@ +tst_qtconcurrentfilter diff --git a/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro new file mode 100644 index 0000000000..eb0c054f6f --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro @@ -0,0 +1,7 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentfilter +QT = core testlib concurrent +SOURCES = tst_qtconcurrentfilter.cpp +DEFINES += QT_STRICT_ITERATORS + +CONFIG += insignificant_test # See QTBUG-20688 diff --git a/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp new file mode 100644 index 0000000000..971a6992ff --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp @@ -0,0 +1,1543 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include +#include + +#include "../qtconcurrentmap/functions.h" + +class tst_QtConcurrentFilter : public QObject +{ + Q_OBJECT + +private slots: +#ifdef QT_NO_CONCURRENT_FILTER + void initTestCase(); +#else + void filter(); + void filtered(); + void filteredReduced(); + void resultAt(); + void incrementalResults(); + void noDetach(); +#ifndef QT_NO_STL + void stlContainers(); +#endif +#endif +}; + +#ifdef QT_NO_CONCURRENT_FILTER +void tst_QtConcurrentFilter::initTestCase() +{ + QSKIP("This test is skipped for gcc 3.x"); +} + +#else + +void tst_QtConcurrentFilter::filter() +{ + // functor + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::filter(list, KeepEvenIntegers()).waitForFinished(); + QCOMPARE(list, QList() << 2 << 4); + } + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(list, KeepEvenIntegers()); + QCOMPARE(list, QList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::filter(linkedList, KeepEvenIntegers()).waitForFinished(); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(linkedList, KeepEvenIntegers()); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + { + QVector vector; + vector << 1 << 2 << 3 << 4; + QtConcurrent::filter(vector, KeepEvenIntegers()).waitForFinished(); + QCOMPARE(vector, QVector() << 2 << 4); + } + { + QVector vector; + vector << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(vector, KeepEvenIntegers()); + QCOMPARE(vector, QVector() << 2 << 4); + } + + + // function + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::filter(list, keepEvenIntegers).waitForFinished(); + QCOMPARE(list, QList() << 2 << 4); + } + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(list, keepEvenIntegers); + QCOMPARE(list, QList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished(); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(linkedList, keepEvenIntegers); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + + // bound function + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::filter(list, keepEvenIntegers).waitForFinished(); + QCOMPARE(list, QList() << 2 << 4); + } + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(list, keepEvenIntegers); + QCOMPARE(list, QList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished(); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(linkedList, keepEvenIntegers); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + + // member + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::filter(list, &Number::isEven).waitForFinished(); + QCOMPARE(list, QList() << 2 << 4); + } + { + QList list; + list << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(list, &Number::isEven); + QCOMPARE(list, QList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::filter(linkedList, &Number::isEven).waitForFinished(); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(linkedList, &Number::isEven); + QCOMPARE(linkedList, QLinkedList() << 2 << 4); + } +} + +void tst_QtConcurrentFilter::filtered() +{ + QList list; + list << 1 << 2 << 3 << 4; + + // functor + { + QFuture f = QtConcurrent::filtered(list, KeepEvenIntegers()); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.begin(), list.end(), KeepEvenIntegers()); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.constBegin(), + list.constEnd(), + KeepEvenIntegers()); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered(list, KeepEvenIntegers()); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.begin(), + list.end(), + KeepEvenIntegers()); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), + list.constEnd(), + KeepEvenIntegers()); + QCOMPARE(list2, QList() << 2 << 4); + } + + { + QVector vector; + vector << 1 << 2 << 3 << 4; + QVector vector2 = QtConcurrent::blockingFiltered(vector, KeepEvenIntegers()); + QCOMPARE(vector2, QVector() << 2 << 4); + } + { + QVector vector; + vector << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(vector, KeepEvenIntegers()); + QCOMPARE(f.results(), QList() << 2 << 4); + } + + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers()); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(linkedList, KeepEvenIntegers()); + QCOMPARE(f.results(), QList() << 2 << 4); + } + + // function + { + QFuture f = QtConcurrent::filtered(list, keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.constBegin(), + list.constEnd(), + keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.begin(), + list.end(), + keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), + list.constEnd(), + keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + + // bound function + { + QFuture f = QtConcurrent::filtered(list, keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(list.constBegin(), + list.constEnd(), + keepEvenIntegers); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.begin(), + list.end(), + keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), + list.constEnd(), + keepEvenIntegers); + QCOMPARE(list2, QList() << 2 << 4); + } + + // const member function + { + QList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers, &Number::isEven); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers.begin(), + integers.end(), + &Number::isEven); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers.constBegin(), + integers.constEnd(), + &Number::isEven); + QList list2 = f.results(); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList integers; + integers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::blockingFiltered(integers, &Number::isEven); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList integers; + integers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::blockingFiltered >(integers.begin(), + integers.end(), + &Number::isEven); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList integers; + integers << 1 << 2 << 3 << 4; + QList list2 = + QtConcurrent::blockingFiltered >(integers.constBegin(), + integers.constEnd(), + &Number::isEven); + QCOMPARE(list2, QList() << 2 << 4); + } + + // same thing on linked lists + + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + + // functor + { + QFuture f = QtConcurrent::filtered(linkedList, KeepEvenIntegers()); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers()); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers()); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers()); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers()); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers()); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // function + { + QFuture f = QtConcurrent::filtered(linkedList, keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.begin(), + linkedList.end(), + keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), + linkedList.end(), + keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // bound function + { + QFuture f = QtConcurrent::filtered(linkedList, keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.begin(), + linkedList.end(), + keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QFuture f = QtConcurrent::filtered(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), + linkedList.end(), + keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // const member function + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers, &Number::isEven); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers.begin(), + integers.end(), + &Number::isEven); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QFuture f = QtConcurrent::filtered(integers.constBegin(), + integers.constEnd(), + &Number::isEven); + QList linkedList2 = f.results(); + QCOMPARE(linkedList2, QList() << 2 << 4); + } + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFiltered(integers, &Number::isEven); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(integers.begin(), + integers.end(), + &Number::isEven); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList integers; + integers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = + QtConcurrent::blockingFiltered >(integers.constBegin(), + integers.constEnd(), + &Number::isEven); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } +} + +void tst_QtConcurrentFilter::filteredReduced() +{ + QList list; + list << 1 << 2 << 3 << 4; + QList numberList; + numberList << 1 << 2 << 3 << 4; + + // functor-functor + { + int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce); + QCOMPARE(sum2, 6); + } + { + QVector vector; + vector << 1 << 2 << 3 << 4; + int sum = QtConcurrent::filteredReduced(vector, KeepEvenIntegers(), IntSumReduce()); + QCOMPARE(sum, 6); + } + + { + int sum = QtConcurrent::filteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + + // function-functor + { + int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + + // functor-function + { + int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + + // function-function + { + int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + + // functor-member + { + QList list2 = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::filteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + KeepEvenIntegers(), + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + KeepEvenIntegers(), + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + + // member-functor + { + int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, NumberSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(QList(numberList), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberList.begin(), + numberList.end(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList, &Number::isEven, NumberSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(QList(numberList), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList.begin(), + numberList.end(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + + // member-member + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::filteredReduced(numbers, + &Number::isEven, + &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::filteredReduced(numbers.begin(), + numbers.end(), + &Number::isEven, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::filteredReduced(numbers.constBegin(), + numbers.constEnd(), + &Number::isEven, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::blockingFilteredReduced(numbers, + &Number::isEven, + &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::blockingFilteredReduced(numbers.begin(), + numbers.end(), + &Number::isEven, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList numbers; + numbers << 1 << 2 << 3 << 4; + QList list2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(), + numbers.constEnd(), + &Number::isEven, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + + // function-member + { + QList list2 = QtConcurrent::filteredReduced(list, keepEvenIntegers, &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::filteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::filteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, &QList::push_back, QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list.begin(), + list.end(), + keepEvenIntegers, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + { + QList list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), + list.constEnd(), + keepEvenIntegers, + &QList::push_back, + QtConcurrent::OrderedReduce); + QCOMPARE(list2, QList() << 2 << 4); + } + + // member-function + { + int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, numberSumReduce); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(QList(numberList), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberList.begin(), + numberList.end(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList, &Number::isEven, numberSumReduce); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(QList(numberList), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList.begin(), + numberList.end(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + + // same as above on linked lists + QLinkedList linkedList; + linkedList << 1 << 2 << 3 << 4; + QLinkedList numberLinkedList; + numberLinkedList << 1 << 2 << 3 << 4; + + // functor-functor + { + int sum = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + IntSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum2, 6); + } + + // function-functor + { + int sum = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + IntSumReduce()); + QCOMPARE(sum, 6); + } + + // functor-function + { + int sum = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + intSumReduce); + QCOMPARE(sum, 6); + } + + // function-function + { + int sum = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + intSumReduce); + QCOMPARE(sum, 6); + } + + // functor-member + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + KeepEvenIntegers(), + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + KeepEvenIntegers(), + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // member-functor + { + int sum = QtConcurrent::filteredReduced(numberLinkedList, &Number::isEven, NumberSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(QLinkedList(numberLinkedList), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberLinkedList.begin(), + numberLinkedList.end(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList, &Number::isEven, NumberSumReduce()); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(QLinkedList(numberLinkedList), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.begin(), + numberLinkedList.end(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::isEven, + NumberSumReduce()); + QCOMPARE(sum, 6); + } + + // member-member + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers, + &Number::isEven, + &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers.begin(), + numbers.end(), + &Number::isEven, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers.constBegin(), + numbers.constEnd(), + &Number::isEven, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers, + &Number::isEven, + &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.begin(), + numbers.end(), + &Number::isEven, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList numbers; + numbers << 1 << 2 << 3 << 4; + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(), + numbers.constEnd(), + &Number::isEven, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // function-member + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, &QLinkedList::append, QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), + linkedList.end(), + keepEvenIntegers, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), + linkedList.constEnd(), + keepEvenIntegers, + &QLinkedList::append, + QtConcurrent::OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4); + } + + // member-function + { + int sum = QtConcurrent::filteredReduced(numberLinkedList, &Number::isEven, numberSumReduce); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(QLinkedList(numberLinkedList), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberLinkedList.begin(), + numberLinkedList.end(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::filteredReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList, &Number::isEven, numberSumReduce); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced(QLinkedList(numberLinkedList), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum2, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.begin(), + numberLinkedList.end(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + { + int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::isEven, + numberSumReduce); + QCOMPARE(sum, 6); + } + + // ### the same as above, with an initial result value +} + +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() == false); + + QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::blockingFiltered(l, waitFilterfn); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::filter(l, waitFilterfn).waitForFinished(); + QVERIFY(l.isDetached() == true); + QVERIFY(ll.isDetached() == true); + } + { + const QList l = QList() << 1; + QVERIFY(l.isDetached()); + + const QList ll = l; + QVERIFY(l.isDetached() == false); + + QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + } +} + +#ifndef QT_NO_STL +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); +} +#endif + +#endif + +QTEST_MAIN(tst_QtConcurrentFilter) +#include "tst_qtconcurrentfilter.moc" diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/.gitignore b/tests/auto/concurrent/qtconcurrentiteratekernel/.gitignore new file mode 100644 index 0000000000..ac5dec4db6 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentiteratekernel/.gitignore @@ -0,0 +1 @@ +tst_qtconcurrentiteratekernel diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro b/tests/auto/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro new file mode 100644 index 0000000000..4cfebc0e3d --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentiteratekernel +QT = core testlib concurrent +SOURCES = tst_qtconcurrentiteratekernel.cpp diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp new file mode 100644 index 0000000000..46562b5eb0 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +struct TestIterator +{ + TestIterator(int i) + :i(i) { } + + int operator-(const TestIterator &other) + { + return i - other.i; + } + + TestIterator& operator++() + { + ++i; + return *this; + } + + bool operator!=(const TestIterator &other) const + { + return i != other.i; + } + + int i; +}; + +#include +#ifndef QT_NO_STL +namespace std { +template <> +struct iterator_traits +{ + typedef random_access_iterator_tag iterator_category; +}; + +int distance(TestIterator &a, TestIterator &b) +{ + return b - a; +} + +} +#endif + +#include +#include + +using namespace QtConcurrent; + +class tst_QtConcurrentIterateKernel: public QObject +{ + Q_OBJECT +private slots: + // "for" iteration tests: + void instantiate(); + void cancel(); + void stresstest(); + void noIterations(); + void throttling(); +#ifndef QT_NO_STL + void blockSize(); + void multipleResults(); +#endif +}; + +QAtomicInt iterations; +class PrintFor : public IterateKernel +{ +public: + PrintFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } + bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) + { + iterations.fetchAndAddRelaxed(end - begin); +#ifdef PRINT + qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)"; +#endif + return false; + } + bool runIteration(TestIterator it, int index , void *result) + { + return runIterations(it, index, index + 1, result); + } + +}; + +class SleepPrintFor : public IterateKernel +{ +public: + SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } + inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) + { + QTest::qSleep(200); + iterations.fetchAndAddRelaxed(end - begin); +#ifdef PRINT + qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)"; +#endif + return false; + } + bool runIteration(TestIterator it, int index , void *result) + { + return runIterations(it, index, index + 1, result); + } +}; + + +void tst_QtConcurrentIterateKernel::instantiate() +{ + startThreadEngine(new PrintFor(0, 40)).startBlocking(); + QCOMPARE(iterations.load(), 40); +} + +void tst_QtConcurrentIterateKernel::cancel() +{ + { + QFuture f = startThreadEngine(new SleepPrintFor(0, 40)).startAsynchronously(); + f.cancel(); + f.waitForFinished(); + QVERIFY(f.isCanceled()); + QVERIFY(iterations.load() <= QThread::idealThreadCount()); // the threads might run one iteration each before they are canceled. + } +} + +QAtomicInt counter; +class CountFor : public IterateKernel +{ +public: + CountFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } + inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) + { + counter.fetchAndAddRelaxed(end - begin); + return false; + } + bool runIteration(TestIterator it, int index , void *result) + { + return runIterations(it, index, index + 1, result); + } +}; + +void tst_QtConcurrentIterateKernel::stresstest() +{ + const int iterations = 1000; + const int times = 50; + for (int i = 0; i < times; ++i) { + counter.store(0); + CountFor f(0, iterations); + f.startBlocking(); + QCOMPARE(counter.load(), iterations); + } +} + +void tst_QtConcurrentIterateKernel::noIterations() +{ + const int times = 20000; + for (int i = 0; i < times; ++i) + startThreadEngine(new IterateKernel(0, 0)).startBlocking(); +} + +QMutex threadsMutex; +QSet threads; +class ThrottleFor : public IterateKernel +{ +public: + // this class throttles between iterations 100 and 200, + // and then records how many threads that run between + // iterations 140 and 160. + ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); throttling = false; } + inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) + { + if (200 >= begin && 200 < end) { + throttling = false; + } + + iterations.fetchAndAddRelaxed(end - begin); + + QThread *thread = QThread::currentThread(); + + if (begin > 140 && end < 160) { + QMutexLocker locker(&threadsMutex); + threads.insert(thread); + } + + if (100 >= begin && 100 < end) { + throttling = true; + } + + QTest::qWait(1); + + return false; + } + bool runIteration(TestIterator it, int index , void *result) + { + return runIterations(it, index, index + 1, result); + } + + bool shouldThrottleThread() + { + const int load = iterations.load(); + return (load > 100 && load < 200); + } + bool throttling; +}; + +void tst_QtConcurrentIterateKernel::throttling() +{ + const int totalIterations = 400; + iterations.store(0); + + threads.clear(); + + ThrottleFor f(0, totalIterations); + f.startBlocking(); + + QCOMPARE(iterations.load(), totalIterations); + + + QCOMPARE(threads.count(), 1); +} + + +int peakBlockSize = 0; +class BlockSizeRecorder : public IterateKernel +{ +public: + BlockSizeRecorder(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { } + inline bool runIterations(TestIterator, int begin, int end, void *) + { + peakBlockSize = qMax(peakBlockSize, end - begin); + return false; + } +}; + +// Missing stl iterators prevent correct block size calculation. +#ifndef QT_NO_STL +void tst_QtConcurrentIterateKernel::blockSize() +{ + const int expectedMinimumBlockSize = 1024 / QThread::idealThreadCount(); + BlockSizeRecorder(0, 10000).startBlocking(); + if (peakBlockSize < expectedMinimumBlockSize) + qDebug() << "block size" << peakBlockSize; + QVERIFY(peakBlockSize >= expectedMinimumBlockSize); +} +#endif + +class MultipleResultsFor : public IterateKernel +{ +public: + MultipleResultsFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { } + inline bool runIterations(TestIterator, int begin, int end, int *results) + { + for (int i = begin; i < end; ++i) + results[i - begin] = i; + return true; + } +}; + +// Missing stl iterators prevent correct summation. +#ifndef QT_NO_STL +void tst_QtConcurrentIterateKernel::multipleResults() +{ + QFuture f = startThreadEngine(new MultipleResultsFor(0, 10)).startAsynchronously(); + QCOMPARE(f.results().count() , 10); + QCOMPARE(f.resultAt(0), 0); + QCOMPARE(f.resultAt(5), 5); + QCOMPARE(f.resultAt(9), 9); + f.waitForFinished(); +} +#endif + +QTEST_MAIN(tst_QtConcurrentIterateKernel) + +#include "tst_qtconcurrentiteratekernel.moc" diff --git a/tests/auto/concurrent/qtconcurrentmap/.gitignore b/tests/auto/concurrent/qtconcurrentmap/.gitignore new file mode 100644 index 0000000000..f1c563e979 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentmap/.gitignore @@ -0,0 +1 @@ +tst_qtconcurrentmap diff --git a/tests/auto/concurrent/qtconcurrentmap/functions.h b/tests/auto/concurrent/qtconcurrentmap/functions.h new file mode 100644 index 0000000000..f5963db904 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentmap/functions.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +bool keepEvenIntegers(const int &x) +{ + return (x & 1) == 0; +} + +class KeepEvenIntegers +{ +public: + bool operator()(const int &x) + { + return (x & 1) == 0; + } +}; + +class Number +{ + int n; + +public: + Number() + : n(0) + { } + + Number(int n) + : n(n) + { } + + void multiplyBy2() + { + n *= 2; + } + + Number multipliedBy2() const + { + return n * 2; + } + + bool isEven() const + { + return (n & 1) == 0; + } + + int toInt() const + { + return n; + } + + QString toString() const + { + return QString::number(n); + } + + bool operator==(const Number &other) const + { + return n == other.n; + } +}; + +void intSumReduce(int &sum, int x) +{ + sum += x; +} + +class IntSumReduce +{ +public: + void operator()(int &sum, int x) + { + sum += x; + } +}; + +void numberSumReduce(int &sum, const Number &x) +{ + sum += x.toInt(); +} + +class NumberSumReduce +{ +public: + void operator()(int &sum, const Number &x) + { + sum += x.toInt(); + } +}; + +#endif diff --git a/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro new file mode 100644 index 0000000000..199e5ad4d6 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentmap/qtconcurrentmap.pro @@ -0,0 +1,5 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentmap +QT = core testlib concurrent +SOURCES = tst_qtconcurrentmap.cpp +DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp new file mode 100644 index 0000000000..960511d87b --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp @@ -0,0 +1,2426 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +#include +#include + +#include + +#include "functions.h" + +Q_DECLARE_METATYPE(QVector); +Q_DECLARE_METATYPE(QVector); +Q_DECLARE_METATYPE(QVector); +Q_DECLARE_METATYPE(QList); +Q_DECLARE_METATYPE(QList); +Q_DECLARE_METATYPE(QList); + +class tst_QtConcurrentMap: public QObject +{ + Q_OBJECT +private slots: +#ifdef QT_NO_CONCURRENT_MAP + void initTestCase() +#else + void map(); + void blocking_map(); + void mapped(); + void blocking_mapped(); + void mappedReduced(); + void blocking_mappedReduced(); + void assignResult(); + void functionOverloads(); +#ifndef QT_NO_EXCEPTIONS + void exceptions(); +#endif + void incrementalResults(); + void noDetach(); +#ifndef QT_NO_STL + void stlContainers(); +#endif + void qFutureAssignmentLeak(); + void stressTest(); +public slots: + void throttling(); +#endif +}; + +#ifdef QT_NO_CONCURRENT_FILTER +void tst_QtConcurrentFilter::initTestCase() +{ + QSKIP("This test is skipped for gcc 3.x"); +} + +#else + +using namespace QtConcurrent; + +void multiplyBy2Immutable(int x) +{ + x *= 2; +} + +class MultiplyBy2Immutable +{ +public: + void operator()(int x) + { + x *= 2; + } +}; + +void multiplyBy2InPlace(int &x) +{ + x *= 2; +} + +class MultiplyBy2InPlace +{ +public: + void operator()(int &x) + { + x *= 2; + } +}; + +Q_DECLARE_METATYPE(QList); + +void tst_QtConcurrentMap::map() +{ + // functors take arguments by reference, modifying the sequence in place + { + QList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished(); + QCOMPARE(list, QList() << 2 << 4 << 6); + QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished(); + QCOMPARE(list, QList() << 4 << 8 << 12); + + // function + QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QList() << 8 << 16 << 24); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QList() << 16 << 32 << 48); + + // bound function + QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QList() << 32 << 64 << 96); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QList() << 64 << 128 << 192); + + // member function + QList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished(); + QCOMPARE(numberList, QList() << 2 << 4 << 6); + QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished(); + QCOMPARE(numberList, QList() << 4 << 8 << 12); + +#ifdef Q_COMPILER_LAMBDA + // lambda + QtConcurrent::map(list, [](int &x){x *= 2;}).waitForFinished(); + QCOMPARE(list, QList() << 128 << 256 << 384); + QtConcurrent::map(list.begin(), list.end(), [](int &x){x *= 2;}).waitForFinished(); + QCOMPARE(list, QList() << 256 << 512 << 768); +#endif + + } + + // functors don't take arguments by reference, making these no-ops + { + QList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::map(list, MultiplyBy2Immutable()).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::map(list.begin(), list.end(), MultiplyBy2Immutable()).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + // function + QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + // bound function + QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + +#ifdef Q_COMPILER_LAMBDA + // lambda + QtConcurrent::map(list, [](int x){x *= 2;}).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::map(list.begin(), list.end(), [](int x){x *= 2;}).waitForFinished(); + QCOMPARE(list, QList() << 1 << 2 << 3); +#endif + } + + // Linked lists and forward iterators + { + QLinkedList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished(); + QCOMPARE(list, QLinkedList() << 2 << 4 << 6); + QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished(); + QCOMPARE(list, QLinkedList() << 4 << 8 << 12); + + // function + QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QLinkedList() << 8 << 16 << 24); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QLinkedList() << 16 << 32 << 48); + + // bound function + QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QLinkedList() << 32 << 64 << 96); + QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); + QCOMPARE(list, QLinkedList() << 64 << 128 << 192); + + // member function + QLinkedList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished(); + QCOMPARE(numberList, QLinkedList() << 2 << 4 << 6); + QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished(); + QCOMPARE(numberList, QLinkedList() << 4 << 8 << 12); + } + +#if 0 + // not allowed: map() with immutable sequences makes no sense + { + const QList list = QList() << 1 << 2 << 3; + + QtConcurrent::map(list, MultiplyBy2Immutable()); + QtConcurrent::map(list, multiplyBy2Immutable); + QtConcurrent::map(list, multiplyBy2Immutable); + } +#endif + +#if 0 + // not allowed: in place modification of a temp copy (since temp copy goes out of scope) + { + QList list; + list << 1 << 2 << 3; + + QtConcurrent::map(QList(list), MultiplyBy2InPlace()); + QtConcurrent::map(QList(list), multiplyBy2); + QtConcurrent::map(QList(list), multiplyBy2InPlace); + + QList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::map(QList(numberList), &Number::multiplyBy2); + } +#endif + +#if 0 + // not allowed: map() on a const list, where functors try to modify the items in the list + { + const QList list = QList() << 1 << 2 << 3;; + + QtConcurrent::map(list, MultiplyBy2InPlace()); + QtConcurrent::map(list, multiplyBy2InPlace); + QtConcurrent::map(list, multiplyBy2InPlace); + + const QList numberList = QList() << 1 << 2 << 3; + QtConcurrent::map(numberList, &Number::multiplyBy2); + } +#endif +} + +void tst_QtConcurrentMap::blocking_map() +{ + // functors take arguments by reference, modifying the sequence in place + { + QList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); + QCOMPARE(list, QList() << 2 << 4 << 6); + QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace()); + QCOMPARE(list, QList() << 4 << 8 << 12); + + // function + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + QCOMPARE(list, QList() << 8 << 16 << 24); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); + QCOMPARE(list, QList() << 16 << 32 << 48); + + // bound function + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + QCOMPARE(list, QList() << 32 << 64 << 96); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); + QCOMPARE(list, QList() << 64 << 128 << 192); + + // member function + QList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); + QCOMPARE(numberList, QList() << 2 << 4 << 6); + QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2); + QCOMPARE(numberList, QList() << 4 << 8 << 12); + } + + // functors don't take arguments by reference, making these no-ops + { + QList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::blockingMap(list, MultiplyBy2Immutable()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2Immutable()); + QCOMPARE(list, QList() << 1 << 2 << 3); + + // function + QtConcurrent::blockingMap(list, multiplyBy2Immutable); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable); + QCOMPARE(list, QList() << 1 << 2 << 3); + + // bound function + QtConcurrent::blockingMap(list, multiplyBy2Immutable); + QCOMPARE(list, QList() << 1 << 2 << 3); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable); + QCOMPARE(list, QList() << 1 << 2 << 3); + } + + // Linked lists and forward iterators + { + QLinkedList list; + list << 1 << 2 << 3; + + // functor + QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); + QCOMPARE(list, QLinkedList() << 2 << 4 << 6); + QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace()); + QCOMPARE(list, QLinkedList() << 4 << 8 << 12); + + // function + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + QCOMPARE(list, QLinkedList() << 8 << 16 << 24); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); + QCOMPARE(list, QLinkedList() << 16 << 32 << 48); + + // bound function + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + QCOMPARE(list, QLinkedList() << 32 << 64 << 96); + QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); + QCOMPARE(list, QLinkedList() << 64 << 128 << 192); + + // member function + QLinkedList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); + QCOMPARE(numberList, QLinkedList() << 2 << 4 << 6); + QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2); + QCOMPARE(numberList, QLinkedList() << 4 << 8 << 12); + } + +#if 0 + // not allowed: map() with immutable sequences makes no sense + { + const QList list = QList() << 1 << 2 << 3; + + QtConcurrent::blockingMap(list, MultiplyBy2Immutable()); + QtConcurrent::blockkng::map(list, multiplyBy2Immutable); + QtConcurrent::blockingMap(list, multiplyBy2Immutable); + } +#endif + +#if 0 + // not allowed: in place modification of a temp copy (since temp copy goes out of scope) + { + QList list; + list << 1 << 2 << 3; + + QtConcurrent::blockingMap(QList(list), MultiplyBy2InPlace()); + QtConcurrent::blockingMap(QList(list), multiplyBy2); + QtConcurrent::blockingMap(QList(list), multiplyBy2InPlace); + + QList numberList; + numberList << 1 << 2 << 3; + QtConcurrent::blockingMap(QList(numberList), &Number::multiplyBy2); + } +#endif + +#if 0 + // not allowed: map() on a const list, where functors try to modify the items in the list + { + const QList list = QList() << 1 << 2 << 3;; + + QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + QtConcurrent::blockingMap(list, multiplyBy2InPlace); + + const QList numberList = QList() << 1 << 2 << 3; + QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); + } +#endif +} + +int multiplyBy2(int x) +{ + int y = x * 2; + return y; +} + +class MultiplyBy2 +{ +public: + typedef int result_type; + + int operator()(int x) const + { + int y = x * 2; + return y; + } +}; + +double intToDouble(int x) +{ + return double(x); +} + +class IntToDouble +{ +public: + typedef double result_type; + + double operator()(int x) const + { + return double(x); + } +}; + +int stringToInt(const QString &string) +{ + return string.toInt(); +} + +class StringToInt +{ +public: + typedef int result_type; + + int operator()(const QString &string) const + { + return string.toInt(); + } +}; + +void tst_QtConcurrentMap::mapped() +{ + QList list; + list << 1 << 2 << 3; + QLinkedList linkedList; + linkedList << 1 << 2 << 3; + QList numberList; + numberList << 1 << 2 << 3; + QLinkedList numberLinkedList; + numberLinkedList << 1 << 2 << 3; + + // functor + { + QList list2 = QtConcurrent::mapped(list, MultiplyBy2()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + MultiplyBy2()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::mapped(QList(list), MultiplyBy2()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QList list2 = QtConcurrent::mapped(linkedList, MultiplyBy2()).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + MultiplyBy2()).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = + QtConcurrent::mapped(QLinkedList(linkedList), MultiplyBy2()).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + + // function + { + QList list2 = QtConcurrent::mapped(list, multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::mapped(QList(list), multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QList list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + multiplyBy2).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = + QtConcurrent::mapped(QLinkedList(linkedList), multiplyBy2).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + + // bound function + { + QList list2 = QtConcurrent::mapped(list, multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::mapped(QList(list), multiplyBy2).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QList list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + multiplyBy2) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), multiplyBy2) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + + // const member function + { + QList numberList2 = QtConcurrent::mapped(numberList, &Number::multipliedBy2) + .results(); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList2, QList() << 2 << 4 << 6); + + QList numberList3 = QtConcurrent::mapped(numberList.constBegin(), + numberList.constEnd(), + &Number::multipliedBy2) + .results(); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList3, QList() << 2 << 4 << 6); + + QList numberList4 = QtConcurrent::mapped(QList(numberList), + &Number::multipliedBy2) + .results(); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList4, QList() << 2 << 4 << 6); + } + { + QList numberList2 = QtConcurrent::mapped(numberLinkedList, &Number::multipliedBy2) + .results(); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberList2, QList() << 2 << 4 << 6); + + QList numberList3 = QtConcurrent::mapped(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::multipliedBy2) + .results(); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberList3, QList() << 2 << 4 << 6); + + QList numberList4 = QtConcurrent::mapped(QLinkedList(numberLinkedList), + &Number::multipliedBy2) + .results(); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberList4, QList() << 2 << 4 << 6); + } + + // change the value_type, same container + + // functor + { + QList list2 = QtConcurrent::mapped(list, IntToDouble()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + IntToDouble()) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::mapped(QList(list), + IntToDouble()) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QList list2 = QtConcurrent::mapped(linkedList, IntToDouble()).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + IntToDouble()) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), + IntToDouble()) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + + // function + { + QList list2 = QtConcurrent::mapped(list, intToDouble).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + intToDouble) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::mapped(QList(list), intToDouble).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QList list2 = QtConcurrent::mapped(linkedList, intToDouble).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + intToDouble) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), intToDouble) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + + // bound function + { + QList list2 = QtConcurrent::mapped(list, intToDouble).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(list.constBegin(), + list.constEnd(), + intToDouble) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + + QList list4 = QtConcurrent::mapped(QList(list), + intToDouble) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QList list2 = QtConcurrent::mapped(linkedList, intToDouble).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::mapped(linkedList.constBegin(), + linkedList.constEnd(), + intToDouble) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + + QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), + intToDouble) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + + // const member function + { + QList list2 = QtConcurrent::mapped(numberList, &Number::toString).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << "1" << "2" << "3"); + + QList list3 = QtConcurrent::mapped(numberList.constBegin(), + numberList.constEnd(), + &Number::toString) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << "1" << "2" << "3"); + + QList list4 = QtConcurrent::mapped(QList(numberList), &Number::toString) + .results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << "1" << "2" << "3"); + } + { + QList list2 = QtConcurrent::mapped(numberLinkedList, &Number::toString).results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << "1" << "2" << "3"); + + QList list3 = QtConcurrent::mapped(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toString) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << "1" << "2" << "3"); + + QList list4 = QtConcurrent::mapped(QLinkedList(numberLinkedList), + &Number::toString) + .results(); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << "1" << "2" << "3"); + } + + // change the value_type + { + QList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::mapped(strings, StringToInt()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::mapped(strings.constBegin(), + strings.constEnd(), + StringToInt()) + .results(); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + { + QList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::mapped(strings, stringToInt).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::mapped(strings.constBegin(), + strings.constEnd(), + stringToInt).results(); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + + { + QList numberList2 = QtConcurrent::mapped(numberList, &Number::toInt).results(); + QCOMPARE(numberList2, QList() << 1 << 2 << 3); + + QList numberList3 = QtConcurrent::mapped(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt) + .results(); + QCOMPARE(numberList3, QList() << 1 << 2 << 3); + } + + // change the value_type from QStringList + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::mapped(strings, StringToInt()).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::mapped(strings.constBegin(), + strings.constEnd(), + StringToInt()) + .results(); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::mapped(strings, stringToInt).results(); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::mapped(strings.constBegin(), + strings.constEnd(), + stringToInt) + .results(); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } +} + +void tst_QtConcurrentMap::blocking_mapped() +{ + QList list; + list << 1 << 2 << 3; + QLinkedList linkedList; + linkedList << 1 << 2 << 3; + QList numberList; + numberList << 1 << 2 << 3; + QLinkedList numberLinkedList; + numberLinkedList << 1 << 2 << 3; + + // functor + { + QList list2 = QtConcurrent::blockingMapped(list, MultiplyBy2()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + MultiplyBy2()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::blockingMapped(QList(list), MultiplyBy2()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, MultiplyBy2()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + MultiplyBy2()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), MultiplyBy2()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); + } + + // function + { + QList list2 = QtConcurrent::blockingMapped(list, multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::blockingMapped(QList(list), multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); + } + + // bound function + { + QList list2 = QtConcurrent::blockingMapped(list, multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 2 << 4 << 6); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 2 << 4 << 6); + + QList list4 = QtConcurrent::blockingMapped(QList(list), multiplyBy2); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 2 << 4 << 6); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); + + QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), multiplyBy2); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); + } + + // const member function + { + QList numberList2 = QtConcurrent::blockingMapped(numberList, &Number::multipliedBy2); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList2, QList() << 2 << 4 << 6); + + QList numberList3 = QtConcurrent::blockingMapped >(numberList.constBegin(), + numberList.constEnd(), + &Number::multipliedBy2); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList3, QList() << 2 << 4 << 6); + + QList numberList4 = QtConcurrent::blockingMapped(QList(numberList), + &Number::multipliedBy2); + QCOMPARE(numberList, QList() << 1 << 2 << 3); + QCOMPARE(numberList4, QList() << 2 << 4 << 6); + } + { + QLinkedList numberLinkedList2 = QtConcurrent::blockingMapped(numberLinkedList, &Number::multipliedBy2); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberLinkedList2, QLinkedList() << 2 << 4 << 6); + + QLinkedList numberLinkedList3 = QtConcurrent::blockingMapped >(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::multipliedBy2); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberLinkedList3, QLinkedList() << 2 << 4 << 6); + + QLinkedList numberLinkedList4 = QtConcurrent::blockingMapped(QLinkedList(numberLinkedList), + &Number::multipliedBy2); + QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(numberLinkedList4, QLinkedList() << 2 << 4 << 6); + } + + // change the value_type, same container + + // functor + { + QList list2 = QtConcurrent::blockingMapped >(list, IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::blockingMapped >(QList(list), + IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, IntToDouble()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + IntToDouble()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); + + QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), + IntToDouble()); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); + } + + // function + { + QList list2 = QtConcurrent::blockingMapped >(list, intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + QList list4 = QtConcurrent::blockingMapped >(QList(list), intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); + + QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); + } + + // bound function + { + QList list2 = QtConcurrent::blockingMapped >(list, intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); + + QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); + + + QList list4 = QtConcurrent::blockingMapped >(QList(list), + intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), + linkedList.constEnd(), + intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); + + + QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), + intToDouble); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); + } + + // const member function + { + QList list2 = + QtConcurrent::blockingMapped >(numberList, &Number::toString); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << "1" << "2" << "3"); + + QList list3 = QtConcurrent::blockingMapped >(numberList.constBegin(), + numberList.constEnd() + , &Number::toString); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << "1" << "2" << "3"); + + QList list4 = + QtConcurrent::blockingMapped >(QList(numberList), &Number::toString); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << "1" << "2" << "3"); + } + { + QLinkedList linkedList2 = + QtConcurrent::blockingMapped >(numberLinkedList, &Number::toString); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << "1" << "2" << "3"); + + QLinkedList linkedList3 = QtConcurrent::blockingMapped >(numberLinkedList.constBegin(), + numberLinkedList.constEnd() + , &Number::toString); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << "1" << "2" << "3"); + + QLinkedList linkedList4 = + QtConcurrent::blockingMapped >(QLinkedList(numberLinkedList), &Number::toString); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << "1" << "2" << "3"); + } + + // change the value_type + { + QList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::blockingMapped(strings, StringToInt()); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + StringToInt()); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + { + QList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::blockingMapped(strings, stringToInt); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + stringToInt); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + + { + QList numberList2 = QtConcurrent::blockingMapped(numberList, &Number::toInt); + QCOMPARE(numberList2, QList() << 1 << 2 << 3); + + QList numberList3 = QtConcurrent::blockingMapped >(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt); + QCOMPARE(numberList3, QList() << 1 << 2 << 3); + } + + // change the value_type from QStringList + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::blockingMapped(strings, StringToInt()); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + StringToInt()); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList list = QtConcurrent::blockingMapped(strings, stringToInt); + QCOMPARE(list, QList() << 1 << 2 << 3); + + QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + stringToInt); + QCOMPARE(list2, QList() << 1 << 2 << 3); + } + + // functor + { + QVector list2 = QtConcurrent::blockingMapped >(list, IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); + + QVector list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); + + QVector list4 = QtConcurrent::blockingMapped >(QList(list), + IntToDouble()); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QVector() << 1.0 << 2.0 << 3.0); + + QStringList strings = QStringList() << "1" << "2" << "3"; + QVector list5 = QtConcurrent::blockingMapped >(strings, StringToInt()); + QCOMPARE(list5, QVector() << 1 << 2 << 3); + + QVector list6 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + StringToInt()); + QCOMPARE(list6, QVector() << 1 << 2 << 3); + + QVector list7 = QtConcurrent::blockingMapped >(QStringList(strings), + StringToInt()); + QCOMPARE(list7, QVector() << 1 << 2 << 3); + } + + // function + { + QVector list2 = QtConcurrent::blockingMapped >(list, intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); + + QVector list3 = QtConcurrent::blockingMapped >(list.constBegin(), + list.constEnd(), + intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); + + QVector list4 = QtConcurrent::blockingMapped >(QList(list), + intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QVector() << 1.0 << 2.0 << 3.0); + + QStringList strings = QStringList() << "1" << "2" << "3"; + QVector list5 = QtConcurrent::blockingMapped >(strings, stringToInt); + QCOMPARE(list5, QVector() << 1 << 2 << 3); + + QVector list6 = QtConcurrent::blockingMapped >(strings.constBegin(), + strings.constEnd(), + stringToInt); + QCOMPARE(list6, QVector() << 1 << 2 << 3); + + QVector list7 = QtConcurrent::blockingMapped >(QStringList(strings), + stringToInt); + QCOMPARE(list7, QVector() << 1 << 2 << 3); + } + + // bound function + { + QVector list2 = QtConcurrent::blockingMapped >(list, intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); + + QVector list3 = QtConcurrent::blockingMapped >(QList(list), intToDouble); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); + + QStringList strings = QStringList() << "1" << "2" << "3"; + QVector list4 = QtConcurrent::blockingMapped >(strings, stringToInt); + QCOMPARE(list4, QVector() << 1 << 2 << 3); + + QVector list5 = QtConcurrent::blockingMapped >(QStringList(strings), stringToInt); + QCOMPARE(list5, QVector() << 1 << 2 << 3); + } + + // const member function + { + QVector list2 = QtConcurrent::blockingMapped >(numberList, &Number::toString); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QVector() << "1" << "2" << "3"); + + QVector list3 = + QtConcurrent::blockingMapped >(QList(numberList), &Number::toString); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QVector() << "1" << "2" << "3"); + + // not allowed: const member function where all arguments have default values +#if 0 + QStringList strings = QStringList() << "1" << "2" << "3"; + QVector list4 = QtConcurrent::blockingMapped >(strings, &QString::toInt); + QCOMPARE(list4, QVector() << 1 << 2 << 3); + + QVector list5 = QtConcurrent::blockingMapped >(QStringList(strings), &QString::toInt); + QCOMPARE(list5, QVector() << 1 << 2 << 3); +#endif + } +} + +int intSquare(int x) +{ + return x * x; +} + +class IntSquare +{ +public: + typedef int result_type; + + int operator()(int x) + { + return x * x; + } +}; + +void tst_QtConcurrentMap::mappedReduced() +{ + QList list; + list << 1 << 2 << 3; + QLinkedList linkedList; + linkedList << 1 << 2 << 3; + QList numberList; + numberList << 1 << 2 << 3; + QLinkedList numberLinkedList; + numberLinkedList << 1 << 2 << 3; + + // test Q_DECLARE_OPERATORS_FOR_FLAGS + QtConcurrent::ReduceOptions opt = (QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce); + QVERIFY(opt); + + // functor-functor + { + int sum = QtConcurrent::mappedReduced(list, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QList(list), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::mappedReduced(QList(list), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + { + int sum = QtConcurrent::mappedReduced(linkedList, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::mappedReduced(linkedList, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::mappedReduced(QLinkedList(linkedList), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + + // function-functor + { + int sum = QtConcurrent::mappedReduced(list, intSquare, IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QList(list), intSquare, IntSumReduce()); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::mappedReduced(linkedList, intSquare, IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), intSquare, IntSumReduce()); + QCOMPARE(sum3, 14); + } + + // functor-function + { + int sum = QtConcurrent::mappedReduced(list, IntSquare(), intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QList(list), IntSquare(), intSumReduce); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::mappedReduced(linkedList, IntSquare(), intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), IntSquare(), intSumReduce); + QCOMPARE(sum3, 14); + } + + // function-function + { + int sum = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QList(list), intSquare, intSumReduce); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::mappedReduced(linkedList, intSquare, intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), intSquare, intSumReduce); + QCOMPARE(sum3, 14); + } + + // functor-member + { + QList list2 = QtConcurrent::mappedReduced(list, + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1 << 4 << 9); + + QList list3 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1 << 4 << 9); + + QList list4 = QtConcurrent::mappedReduced(QList(list), + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1 << 4 << 9); + } + { + QLinkedList linkedList2 = QtConcurrent::mappedReduced(linkedList, + IntSquare(), + &QLinkedList::push_back, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + &QLinkedList::push_back, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(linkedList), + IntSquare(), + &QLinkedList::push_back, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); + } + + // member-functor + { + int sum = QtConcurrent::mappedReduced(numberList, &Number::toInt, IntSumReduce()); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::mappedReduced(QList(numberList), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum3, 6); + } + { + int sum = QtConcurrent::mappedReduced(numberLinkedList, &Number::toInt, IntSumReduce()); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum3, 6); + } + + // member-member + { + QList list2 = QtConcurrent::mappedReduced(numberList, + &Number::toInt, + &QList::push_back, + OrderedReduce); + QCOMPARE(list2, QList() << 1 << 2 << 3); + + QList list3 = QtConcurrent::mappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + &QList::push_back, + OrderedReduce); + QCOMPARE(list3, QList() << 1 << 2 << 3); + + QList list4 = QtConcurrent::mappedReduced(QList(numberList), + &Number::toInt, + &QList::push_back, OrderedReduce); + QCOMPARE(list4, QList() << 1 << 2 << 3); + } + { + QLinkedList linkedList2 = QtConcurrent::mappedReduced(numberLinkedList, + &Number::toInt, + &QLinkedList::push_back, + OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 1 << 2 << 3); + + QLinkedList linkedList3 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + &QLinkedList::push_back, + OrderedReduce); + QCOMPARE(linkedList3, QLinkedList() << 1 << 2 << 3); + + QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + &QLinkedList::push_back, OrderedReduce); + QCOMPARE(linkedList4, QLinkedList() << 1 << 2 << 3); + } + + // function-member + { + QList list2 = QtConcurrent::mappedReduced(list, + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1 << 4 << 9); + + QList list3 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1 << 4 << 9); + + QList list4 = QtConcurrent::mappedReduced(QList(list), + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1 << 4 << 9); + } + { + QLinkedList linkedList2 = QtConcurrent::mappedReduced(linkedList, + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(linkedList), + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); + } + + // member-function + { + int sum = QtConcurrent::mappedReduced(numberList, + &Number::toInt, + intSumReduce); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + intSumReduce); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::mappedReduced(QList(numberList), + &Number::toInt, + intSumReduce); + QCOMPARE(sum3, 6); + } + { + int sum = QtConcurrent::mappedReduced(numberLinkedList, + &Number::toInt, + intSumReduce); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + intSumReduce); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + intSumReduce); + QCOMPARE(sum3, 6); + } + + // linked lists + { + + QLinkedList list; + list << 1 << 2 << 3; + + QLinkedList numberList; + numberList << 1 << 2 << 3; + + int sum = QtConcurrent::mappedReduced(list, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced(QLinkedList(list), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::mappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::mappedReduced(QLinkedList(list), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + + // ### the same as above, with an initial result value +} + +void tst_QtConcurrentMap::blocking_mappedReduced() +{ + QList list; + list << 1 << 2 << 3; + QLinkedList linkedList; + linkedList << 1 << 2 << 3; + QList numberList; + numberList << 1 << 2 << 3; + QLinkedList numberLinkedList; + numberLinkedList << 1 << 2 << 3; + + // functor-functor + { + int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(list), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::blockingMappedReduced(QList(list), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + { + int sum = QtConcurrent::blockingMappedReduced(linkedList, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::blockingMappedReduced(linkedList, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + + // function-functor + { + int sum = QtConcurrent::blockingMappedReduced(list, intSquare, IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(list), intSquare, IntSumReduce()); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::blockingMappedReduced(linkedList, intSquare, IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), intSquare, IntSumReduce()); + QCOMPARE(sum3, 14); + } + + // functor-function + { + int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(list), IntSquare(), intSumReduce); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::blockingMappedReduced(linkedList, IntSquare(), intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), IntSquare(), intSumReduce); + QCOMPARE(sum3, 14); + } + + // function-function + { + int sum = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(list), intSquare, intSumReduce); + QCOMPARE(sum3, 14); + } + { + int sum = QtConcurrent::blockingMappedReduced(linkedList, intSquare, intSumReduce); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), intSquare, intSumReduce); + QCOMPARE(sum3, 14); + } + + // functor-member + { + QList list2 = QtConcurrent::blockingMappedReduced(list, + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1 << 4 << 9); + + QList list3 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1 << 4 << 9); + + QList list4 = QtConcurrent::blockingMappedReduced(QList(list), + IntSquare(), + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1 << 4 << 9); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(linkedList, + IntSquare(), + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + IntSquare(), + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), + IntSquare(), + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); + } + + // member-functor + { + int sum = QtConcurrent::blockingMappedReduced(numberList, &Number::toInt, + IntSumReduce()); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(numberList), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum3, 6); + } + { + int sum = QtConcurrent::blockingMappedReduced(numberLinkedList, &Number::toInt, IntSumReduce()); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + IntSumReduce()); + QCOMPARE(sum3, 6); + } + + // member-member + { + QList list2 = QtConcurrent::blockingMappedReduced(numberList, + &Number::toInt, + &QList::push_back, + OrderedReduce); + QCOMPARE(list2, QList() << 1 << 2 << 3); + + QList list3 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + &QList::push_back, + OrderedReduce); + QCOMPARE(list3, QList() << 1 << 2 << 3); + + QList list4 = QtConcurrent::blockingMappedReduced(QList(numberList), + &Number::toInt, + &QList::push_back, OrderedReduce); + QCOMPARE(list4, QList() << 1 << 2 << 3); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(numberLinkedList, + &Number::toInt, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList2, QLinkedList() << 1 << 2 << 3); + + QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList3, QLinkedList() << 1 << 2 << 3); + + QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + &QLinkedList::append, OrderedReduce); + QCOMPARE(linkedList4, QLinkedList() << 1 << 2 << 3); + } + + // function-member + { + QList list2 = QtConcurrent::blockingMappedReduced(list, + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list2, QList() << 1 << 4 << 9); + + QList list3 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list3, QList() << 1 << 4 << 9); + + QList list4 = QtConcurrent::blockingMappedReduced(QList(list), + intSquare, + &QList::push_back, + OrderedReduce); + QCOMPARE(list, QList() << 1 << 2 << 3); + QCOMPARE(list4, QList() << 1 << 4 << 9); + } + { + QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(linkedList, + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), + linkedList.constEnd(), + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); + + QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), + intSquare, + &QLinkedList::append, + OrderedReduce); + QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); + QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); + } + + // member-function + { + int sum = QtConcurrent::blockingMappedReduced(numberList, + &Number::toInt, + intSumReduce); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), + numberList.constEnd(), + &Number::toInt, + intSumReduce); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingMappedReduced(QList(numberList), + &Number::toInt, + intSumReduce); + QCOMPARE(sum3, 6); + } + { + int sum = QtConcurrent::blockingMappedReduced(numberLinkedList, + &Number::toInt, + intSumReduce); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), + numberLinkedList.constEnd(), + &Number::toInt, + intSumReduce); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), + &Number::toInt, + intSumReduce); + QCOMPARE(sum3, 6); + } + + // linked lists + { + + QLinkedList list; + list << 1 << 2 << 3; + + QLinkedList numberList; + numberList << 1 << 2 << 3; + + int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), IntSumReduce()); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + IntSquare(), + IntSumReduce()); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(list), IntSquare(), IntSumReduce()); + QCOMPARE(sum3, 14); + + int sum4 = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); + QCOMPARE(sum4, 14); + int sum5 = QtConcurrent::blockingMappedReduced(list.constBegin(), + list.constEnd(), + intSquare, + intSumReduce); + QCOMPARE(sum5, 14); + + int sum6 = QtConcurrent::blockingMappedReduced(QLinkedList(list), + intSquare, + intSumReduce); + QCOMPARE(sum6, 14); + } + + // ### the same as above, with an initial result value +} + +int sleeper(int val) +{ + QTest::qSleep(100); + return val; +} + +void tst_QtConcurrentMap::assignResult() +{ + const QList startList = QList() << 0 << 1 << 2; + QList list = QtConcurrent::blockingMapped(startList, sleeper); + QCOMPARE(list.at(0), 0); + QCOMPARE(list.at(1), 1); +} + +int fnConst(const int &i) +{ + return i; +} + +int fn(int &i) +{ + return i; +} + +QString changeTypeConst(const int &) +{ + return QString(); +} + +QString changeType(int &) +{ + return QString(); +} + +int changeTypeQStringListConst(const QStringList &) +{ + return 0; +} + +int changeTypeQStringList(QStringList &) +{ + return 0; +} + +class MemFnTester +{ +public: + MemFnTester() {} + + MemFnTester fn() + { + return MemFnTester(); + } + + MemFnTester fnConst() const + { + return MemFnTester(); + } + + QString changeType() + { + return QString(); + } + + QString changeTypeConst() const + { + return QString(); + } +}; + +Q_DECLARE_METATYPE(QVector); +Q_DECLARE_METATYPE(QList); + +void tst_QtConcurrentMap::functionOverloads() +{ + QList intList; + const QList constIntList; + QList classList; + const QList constMemFnTesterList; + + QtConcurrent::mapped(intList, fnConst); + QtConcurrent::mapped(constIntList, fnConst); + QtConcurrent::mapped(classList, &MemFnTester::fnConst); + QtConcurrent::mapped(constMemFnTesterList, &MemFnTester::fnConst); + + QtConcurrent::blockingMapped >(intList, fnConst); + QtConcurrent::blockingMapped >(constIntList, fnConst); + QtConcurrent::blockingMapped >(classList, &MemFnTester::fnConst); + QtConcurrent::blockingMapped >(constMemFnTesterList, &MemFnTester::fnConst); + + QtConcurrent::blockingMapped >(intList, changeTypeConst); + QtConcurrent::blockingMapped >(constIntList, changeTypeConst); + QtConcurrent::blockingMapped >(classList, &MemFnTester::changeTypeConst); + QtConcurrent::blockingMapped >(constMemFnTesterList, &MemFnTester::changeTypeConst); + + QStringList stringList; + const QStringList constStringList; + // QtConcurrent::map(stringList, changeTypeQStringListConst); + // QtConcurrent::map(intList, changeTypeNonConst); + // QList(QtConcurrent::map(constStringList, changeTypeQStringList)); + // QtConcurrent::map(classList, &MemFnTester::changeType); + // QtConcurrent::map(classList, &MemFnTester::changeTypeConst); + // QtConcurrent::map(constMemFnTesterList, &MemFnTester::changeTypeConst); +} + +QAtomicInt currentInstanceCount; +QAtomicInt peakInstanceCount; +class InstanceCounter +{ +public: + inline InstanceCounter() + { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); } + inline ~InstanceCounter() + { currentInstanceCount.fetchAndAddRelaxed(-1);} + inline InstanceCounter(const InstanceCounter &) + { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); } + + void updatePeak() + { + forever { + const int localPeak = peakInstanceCount.load(); + const int localCurrent = currentInstanceCount.load(); + if (localCurrent <= localPeak) + break; + if (peakInstanceCount.testAndSetOrdered(localPeak, localCurrent)) + break; + } + } +}; + +InstanceCounter slowMap(const InstanceCounter &in) +{ + QTest::qSleep(2); + return in; +} + +InstanceCounter fastMap(const InstanceCounter &in) +{ + QTest::qSleep(rand() % 2 + 1); + return in; +} + +void slowReduce(int &result, const InstanceCounter&) +{ + QTest::qSleep(rand() % 4 + 1); + ++result; +} + +void fastReduce(int &result, const InstanceCounter&) +{ + ++result; +} + +void tst_QtConcurrentMap::throttling() +{ + const int itemcount = 100; + const int allowedTemporaries = QThread::idealThreadCount() * 40; + + { + currentInstanceCount.store(0); + peakInstanceCount.store(0); + + QList instances; + for (int i = 0; i < itemcount; ++i) + instances.append(InstanceCounter()); + + QCOMPARE(currentInstanceCount.load(), itemcount); + + int results = QtConcurrent::blockingMappedReduced(instances, slowMap, fastReduce); + QCOMPARE(results, itemcount); + QCOMPARE(currentInstanceCount.load(), itemcount); + QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries); + } + + { + QCOMPARE(currentInstanceCount.load(), 0); + peakInstanceCount.store(0); + + QList instances; + for (int i = 0; i < itemcount; ++i) + instances.append(InstanceCounter()); + + QCOMPARE(currentInstanceCount.load(), itemcount); + int results = QtConcurrent::blockingMappedReduced(instances, fastMap, slowReduce); + + QCOMPARE(results, itemcount); + QCOMPARE(currentInstanceCount.load(), itemcount); + QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries); + } +} + +#ifndef QT_NO_EXCEPTIONS +void throwMapper(int &e) +{ + Q_UNUSED(e); + throw QtConcurrent::Exception(); +} + +void tst_QtConcurrentMap::exceptions() +{ + bool caught = false; + try { + QList list = QList() << 1 << 2 << 3; + QtConcurrent::map(list, throwMapper).waitForFinished(); + } catch (const Exception &) { + caught = true; + } + if (!caught) + QFAIL("did not get exception"); +} +#endif + +int mapper(const int &i) +{ + QTest::qWait(1); + return i; +} + +void tst_QtConcurrentMap::incrementalResults() +{ + const int count = 200; + QList ints; + for (int i=0; i < count; ++i) + ints << i; + + QFuture future = QtConcurrent::mapped(ints, mapper); + + 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); + QCOMPARE(future.results().count(), count); +} + +/* + Test that mapped does not cause deep copies when holding + references to Qt containers. +*/ +void tst_QtConcurrentMap::noDetach() +{ + { + QList l = QList() << 1; + QVERIFY(l.isDetached()); + + QList ll = l; + QVERIFY(l.isDetached() == false); + + QtConcurrent::mapped(l, mapper).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::map(l, multiplyBy2Immutable).waitForFinished(); + QVERIFY(l.isDetached() == true); + QVERIFY(ll.isDetached() == true); + } + { + const QList l = QList() << 1; + QVERIFY(l.isDetached()); + + const QList ll = l; + QVERIFY(l.isDetached() == false); + + QtConcurrent::mapped(l, mapper).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + + QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished(); + + QVERIFY(l.isDetached() == false); + QVERIFY(ll.isDetached() == false); + } + +} + +#ifndef QT_NO_STL +void tst_QtConcurrentMap::stlContainers() +{ + std::vector vector; + vector.push_back(1); + vector.push_back(2); + + std::vector vector2 = QtConcurrent::blockingMapped >(vector, mapper); + QCOMPARE(vector2.size(), (std::vector::size_type)(2)); + + std::list list; + list.push_back(1); + list.push_back(2); + + std::list list2 = QtConcurrent::blockingMapped >(list, mapper); + QCOMPARE(list2.size(), (std::vector::size_type)(2)); + + QtConcurrent::mapped(list, mapper).waitForFinished(); + + QtConcurrent::blockingMap(list, multiplyBy2Immutable); +} +#endif + +InstanceCounter ic_fn(const InstanceCounter & ic) +{ + return InstanceCounter(ic); +}; + +// Verify that held results are deleted when a future is +// assigned over with operator == +void tst_QtConcurrentMap::qFutureAssignmentLeak() +{ + currentInstanceCount.store(0); + peakInstanceCount.store(0); + QFuture future; + { + QList list; + for (int i=0;i<1000;++i) + list += InstanceCounter(); + future = QtConcurrent::mapped(list, ic_fn); + future.waitForFinished(); + + future = QtConcurrent::mapped(list, ic_fn); + future.waitForFinished(); + + future = QtConcurrent::mapped(list, ic_fn); + future.waitForFinished(); + } + + QCOMPARE(currentInstanceCount.load(), 1000); + future = QFuture(); + QCOMPARE(currentInstanceCount.load(), 0); +} + +inline void increment(int &num) +{ + ++num; +} + +inline int echo(const int &num) +{ + return num; +} + +void add(int &result, const int &sum) +{ + result += sum; +} + +void tst_QtConcurrentMap::stressTest() +{ + const int listSize = 1000; + const int sum = (listSize - 1) * (listSize / 2); + QList list; + + + for (int i = 0; i < listSize; ++i) { + list.append(i); + } + + for (int i =0 ; i < 100; ++i) { + QList result = QtConcurrent::blockingMapped(list, echo); + for (int j = 0; j < listSize; ++j) + QCOMPARE(result.at(j), j); + } + + for (int i = 0 ; i < 100; ++i) { + int result = QtConcurrent::blockingMappedReduced(list, echo, add); + QCOMPARE(result, sum); + } + + for (int i = 0 ; i < 100; ++i) { + QtConcurrent::map(list, increment).waitForFinished(); + for (int j = 0; j < listSize; ++j) + QCOMPARE(list.at(j), i + j + 1); + } +} + +#endif + +QTEST_MAIN(tst_QtConcurrentMap) +#include "tst_qtconcurrentmap.moc" diff --git a/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro b/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro new file mode 100644 index 0000000000..2c04f75025 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro @@ -0,0 +1,5 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentresultstore +QT = core-private testlib concurrent +SOURCES = tst_qtconcurrentresultstore.cpp +DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp b/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp new file mode 100644 index 0000000000..236d0b62e3 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +using namespace QtConcurrent; + +class tst_QtConcurrentResultStore : public QObject +{ + Q_OBJECT +public slots: + void init(); +private slots: + void construction(); + void iterators(); + void addResult(); + void addResults(); + void resultIndex(); + void resultAt(); + void contains(); + void filterMode(); + void addCanceledResult(); + void count(); +private: + int int0; + int int1; + int int2; + QVector vec0; + QVector vec1; +}; + +void tst_QtConcurrentResultStore::init() +{ + int0 = 0; + int1 = 1; + int2 = 2; + vec0 = QVector() << 2 << 3; + vec1 = QVector() << 4 << 5; +} + +void tst_QtConcurrentResultStore::construction() +{ + ResultStore store; + QCOMPARE(store.count(), 0); +} + +void tst_QtConcurrentResultStore::iterators() +{ + { + ResultStore store; + QVERIFY(store.begin() == store.end()); + QVERIFY(store.resultAt(0) == store.end()); + QVERIFY(store.resultAt(1) == store.end()); + } + { + ResultStoreBase storebase; + storebase.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since + storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. + ResultIteratorBase it = storebase.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == storebase.begin()); + QVERIFY(it != storebase.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != storebase.begin()); + QVERIFY(it != storebase.end()); + + ++it; + QVERIFY(it != storebase.begin()); + QVERIFY(it == storebase.end()); + } +} + +void tst_QtConcurrentResultStore::addResult() +{ + { + // test addResult return value + ResultStore store; + store.setFilterMode(true); + + QCOMPARE(store.addResult(0, &int0), 0); + QCOMPARE(store.count(), 1); // result 0 becomes available + QCOMPARE(store.contains(0), true); + + QCOMPARE(store.addResult(2, &int0), 2); + QCOMPARE(store.count(), 1); + QCOMPARE(store.contains(2), false); + + QCOMPARE(store.addCanceledResult(1), 1); + QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + + QCOMPARE(store.addResult(3, &int0), 3); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(2), true); + + QCOMPARE(store.addResult(6, &int0), 6); + QCOMPARE(store.count(), 3); + QCOMPARE(store.addResult(7, &int0), 7); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(3), false); + + QCOMPARE(store.addCanceledResult(4), 4); + QCOMPARE(store.addCanceledResult(5), 5); + QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available + + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), true); + + QCOMPARE(store.addResult(8, &int0), 8); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.count(), 6); + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } +} + +void tst_QtConcurrentResultStore::addResults() +{ + + ResultStoreBase store; + store.addResults(-1, &vec0, 2, 2); + store.addResults(-1, &vec1, 2, 2); + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + + ++it; + QCOMPARE(it.resultIndex(), 3); + + ++it; + QVERIFY(it == store.end()); +} + +void tst_QtConcurrentResultStore::resultIndex() +{ + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(-1, &int1); + + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + QVERIFY(it != store.end()); + ++it; + QCOMPARE(it.resultIndex(), 3); + QVERIFY(it != store.end()); + ++it; + QVERIFY(it == store.end()); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(3).value(), int1); +} + +void tst_QtConcurrentResultStore::resultAt() +{ + { + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(200, &int1); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(200).value(), int1); + } + { + ResultStore store; + store.addResult(1, &int1); + store.addResult(0, &int0); + store.addResult(-1, &int2); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), int1); + QCOMPARE(store.resultAt(2).value(), int2); + } +} + +void tst_QtConcurrentResultStore::contains() +{ + { + ResultStore store; + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(INT_MAX), false); + store.addResult(1, &int1); + QVERIFY(store.contains(int1)); + store.addResult(0, &int0); + QVERIFY(store.contains(int0)); + store.addResult(-1, &int2); + QVERIFY(store.contains(int2)); + } + { + ResultStore store; + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), false); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + + store.addCanceledResult(0); + store.addCanceledResult(2); + store.addCanceledResults(4, 2); + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } + { + ResultStore store; + store.setFilterMode(true); + store.addCanceledResult(0); + QCOMPARE(store.contains(0), false); + + store.addResult(1, &int0); + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), false); + } +} + +void tst_QtConcurrentResultStore::filterMode() +{ + // Test filter mode, where "gaps" in the result array aren't allowed. + ResultStore store; + QCOMPARE(store.filterMode(), false); + store.setFilterMode(true); + QVERIFY(store.filterMode()); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int2); // add result at index 2 + QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. + + store.addResult(1, &int1); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); // 2 should be visible now. + + store.addResult(4, &int0); + store.addResult(5, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(7), false); + + store.addResult(3, &int0); // adding 3 makes 4 and 5 visible + QCOMPARE(store.contains(4), true); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.contains(7), false); + + store.addResult(6, &int0); // adding 6 makes 7 visible + + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + QCOMPARE(store.contains(8), false); +} + +void tst_QtConcurrentResultStore::addCanceledResult() +{ + // test canceled results + ResultStore store; + store.setFilterMode(true); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int0); + QCOMPARE(store.contains(2), false); + + store.addCanceledResult(1); // report no result at 1 + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 + QCOMPARE(store.contains(2), false); + + store.addResult(3, &int0); + QCOMPARE(store.contains(2), true); //3 gets renamed to 2 + + store.addResult(6, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(3), false); + + store.addCanceledResult(4); + store.addCanceledResult(5); + + QCOMPARE(store.contains(3), true); //6 gets renamed to 3 + QCOMPARE(store.contains(4), true); //7 gets renamed to 4 + + store.addResult(8, &int0); + QCOMPARE(store.contains(5), true); //8 gets renamed to 4 + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); +} + +void tst_QtConcurrentResultStore::count() +{ + { + // test resultCount in non-filtered mode. It should always be possible + // to iterate through the results 0 to resultCount. + ResultStore store; + store.addResult(0, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(2, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResult(2, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 4); + } + { + ResultStore store; + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addResult(2, &int0); + QCOMPARE(store.count(), 5); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addCanceledResult(2); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 + + store.addResult(5, &int0); + QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 + } +} + +QTEST_MAIN(tst_QtConcurrentResultStore) +#include "tst_qtconcurrentresultstore.moc" diff --git a/tests/auto/concurrent/qtconcurrentrun/.gitignore b/tests/auto/concurrent/qtconcurrentrun/.gitignore new file mode 100644 index 0000000000..d7a8334ec4 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentrun/.gitignore @@ -0,0 +1 @@ +tst_qtconcurrentrun diff --git a/tests/auto/concurrent/qtconcurrentrun/qtconcurrentrun.pro b/tests/auto/concurrent/qtconcurrentrun/qtconcurrentrun.pro new file mode 100644 index 0000000000..03d77b33a2 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentrun/qtconcurrentrun.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentrun +QT = core testlib concurrent +SOURCES = tst_qtconcurrentrun.cpp diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp new file mode 100644 index 0000000000..86e3433c12 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -0,0 +1,463 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +using namespace QtConcurrent; + +class tst_QtConcurrentRun: public QObject +{ + Q_OBJECT +private slots: + void runLightFunction(); + void runHeavyFunction(); + void returnValue(); + void functionObject(); + void memberFunctions(); + void implicitConvertibleTypes(); + void runWaitLoop(); + void recursive(); +#ifndef QT_NO_EXCEPTIONS + void exceptions(); +#endif + void functor(); + void lambda(); +}; + +void light() +{ + qDebug("in function"); + qDebug("done function"); +} + +void heavy() +{ + qDebug("in function"); + QString str; + for (int i = 0; i < 1000000; ++i) + str.append("a"); + qDebug("done function"); +} + + +void tst_QtConcurrentRun::runLightFunction() +{ + qDebug("starting function"); + QFuture future = run(light); + qDebug("waiting"); + future.waitForFinished(); + qDebug("done"); +} + +void tst_QtConcurrentRun::runHeavyFunction() +{ + qDebug("starting function"); + QFuture future = run(heavy); + qDebug("waiting"); + future.waitForFinished(); + qDebug("done"); +} + +int returnInt0() +{ + return 10; +} + +int returnInt1(int i) +{ + return i; +} + +class A +{ +public: + int member0() { return 10; } + int member1(int in) { return in; } + + typedef int result_type; + int operator()() { return 10; } + int operator()(int in) { return in; } +}; + +class AConst +{ +public: + int member0() const { return 10; } + int member1(int in) const { return in; } + + typedef int result_type; + int operator()() const { return 10; } + int operator()(int in) const { return in; } +}; + +void tst_QtConcurrentRun::returnValue() +{ + QFuture f; + + f = run(returnInt0); + QCOMPARE(f.result(), 10); + + A a; + f = run(&a, &A::member0); + QCOMPARE(f.result(), 10); + + f = run(&a, &A::member1, 20); + QCOMPARE(f.result(), 20); + + f = run(a, &A::member0); + QCOMPARE(f.result(), 10); + + f = run(a, &A::member1, 20); + QCOMPARE(f.result(), 20); + + f = run(a); + QCOMPARE(f.result(), 10); + + f = run(&a); + QCOMPARE(f.result(), 10); + + f = run(a, 20); + QCOMPARE(f.result(), 20); + + f = run(&a, 20); + QCOMPARE(f.result(), 20); + + const AConst aConst = AConst(); + f = run(&aConst, &AConst::member0); + QCOMPARE(f.result(), 10); + + f = run(&aConst, &AConst::member1, 20); + QCOMPARE(f.result(), 20); + + f = run(aConst, &AConst::member0); + QCOMPARE(f.result(), 10); + + f = run(aConst, &AConst::member1, 20); + QCOMPARE(f.result(), 20); + + f = run(aConst); + QCOMPARE(f.result(), 10); + + f = run(&aConst); + QCOMPARE(f.result(), 10); + + f = run(aConst, 20); + QCOMPARE(f.result(), 20); + + f = run(&aConst, 20); + QCOMPARE(f.result(), 20); +} + +struct TestClass +{ + void foo() { } + typedef void result_type; + void operator()() { } + void operator()(int) { } + void fooInt(int){ }; +}; + +struct TestConstClass +{ + void foo() const { } + typedef void result_type; + void operator()() const { } + void operator()(int) const { } + void fooInt(int) const { }; +}; + +void tst_QtConcurrentRun::functionObject() +{ + QFuture f; + TestClass c; + + f = run(c); + f = run(&c); + f = run(c, 10); + f = run(&c, 10); + + const TestConstClass cc = TestConstClass(); + f = run(cc); + f = run(&cc); + f = run(cc, 10); + f = run(&cc, 10); +} + + +void tst_QtConcurrentRun::memberFunctions() +{ + TestClass c; + + run(c, &TestClass::foo).waitForFinished(); + run(&c, &TestClass::foo).waitForFinished(); + run(c, &TestClass::fooInt, 10).waitForFinished(); + run(&c, &TestClass::fooInt, 10).waitForFinished(); + + const TestConstClass cc = TestConstClass(); + run(cc, &TestConstClass::foo).waitForFinished(); + run(&cc, &TestConstClass::foo).waitForFinished(); + run(cc, &TestConstClass::fooInt, 10).waitForFinished(); + run(&cc, &TestConstClass::fooInt, 10).waitForFinished(); +} + + +void doubleFunction(double) +{ + +} + +void stringConstRefFunction(const QString &) +{ + +} + +void stringRefFunction(QString &) +{ + +} + +void stringFunction(QString) +{ + +} + +void stringIntFunction(QString) +{ + +} + + +void tst_QtConcurrentRun::implicitConvertibleTypes() +{ + double d; + run(doubleFunction, d).waitForFinished(); + int i; + run(doubleFunction, d).waitForFinished(); + run(doubleFunction, i).waitForFinished(); + run(doubleFunction, 10).waitForFinished(); + run(stringFunction, QLatin1String("Foo")).waitForFinished(); + run(stringConstRefFunction, QLatin1String("Foo")).waitForFinished(); + QString string; + run(stringRefFunction, string).waitForFinished(); +} + +void fn() { } + +void tst_QtConcurrentRun::runWaitLoop() +{ + for (int i = 0; i < 1000; ++i) + run(fn).waitForFinished(); +} + +QAtomicInt count; + +void recursiveRun(int level) +{ + count.ref(); + if (--level > 0) { + QFuture f1 = run(recursiveRun, level); + QFuture f2 = run(recursiveRun, level); + f1.waitForFinished(); + f2.waitForFinished(); + } +} + +int recursiveResult(int level) +{ + count.ref(); + if (--level > 0) { + QFuture f1 = run(recursiveResult, level); + QFuture f2 = run(recursiveResult, level); + return f1.result() + f2.result(); + } + return 1; +} + +void tst_QtConcurrentRun::recursive() +{ + int levels = 15; + + for (int i = 0; i < QThread::idealThreadCount(); ++i) { + count.store(0); + QThreadPool::globalInstance()->setMaxThreadCount(i); + recursiveRun(levels); + QCOMPARE(count.load(), (int)pow(2.0, levels) - 1); + } + + for (int i = 0; i < QThread::idealThreadCount(); ++i) { + count.store(0); + QThreadPool::globalInstance()->setMaxThreadCount(i); + recursiveResult(levels); + QCOMPARE(count.load(), (int)pow(2.0, levels) - 1); + } +} + +int e; +void vfn0() +{ + ++e; +} + +int fn0() +{ + return 1; +} + +void vfn1(double) +{ + ++e; +} + +int fn1(int) +{ + return 1; +} + +void vfn2(double, int *) +{ + ++e; +} + +int fn2(double, int *) +{ + return 1; +} + + +#ifndef QT_NO_EXCEPTIONS +void throwFunction() +{ + throw QtConcurrent::Exception(); +} + +int throwFunctionReturn() +{ + throw QtConcurrent::Exception(); + return 0; +} + +void tst_QtConcurrentRun::exceptions() +{ + bool caught = false; + try { + QtConcurrent::run(throwFunction).waitForFinished(); + } catch (Exception &e) { + caught = true; + } + if (!caught) + QFAIL("did not get exception"); + + caught = false; + try { + QtConcurrent::run(throwFunctionReturn).waitForFinished(); + } catch (Exception &e) { + caught = true; + } + if (!caught) + QFAIL("did not get exception"); +} +#endif + +struct Functor { + int operator()() { return 42; } + double operator()(double a, double b) { return a/b; } + int operator()(int a, int b) { return a/b; } + void operator()(int) { } + void operator()(int, int, int) { } + void operator()(int, int, int, int) { } + void operator()(int, int, int, int, int) { } + void operator()(int, int, int, int, int, int) { } +}; + +// This tests functor without result_type; decltype need to be supported by the compiler. +void tst_QtConcurrentRun::functor() +{ +#ifndef Q_COMPILER_DECLTYPE + QSKIP("Compiler does not support decltype"); +#else + Functor f; + { + QFuture fut = QtConcurrent::run(f); + QCOMPARE(fut.result(), 42); + } + { + QFuture fut = QtConcurrent::run(f, 8.5, 1.8); + QCOMPARE(fut.result(), (8.5/1.8)); + } + { + QFuture fut = QtConcurrent::run(f, 19, 3); + QCOMPARE(fut.result(), int(19/3)); + } + { + QtConcurrent::run(f, 1).waitForFinished(); + QtConcurrent::run(f, 1,2).waitForFinished(); + QtConcurrent::run(f, 1,2,3).waitForFinished(); + QtConcurrent::run(f, 1,2,3,4).waitForFinished(); + QtConcurrent::run(f, 1,2,3,4,5).waitForFinished(); + } +#endif +} + +void tst_QtConcurrentRun::lambda() +{ +#ifndef Q_COMPILER_LAMBDA + QSKIP("Compiler does not support lambda"); +#else + QCOMPARE(QtConcurrent::run([](){ return 45; }).result(), 45); + QCOMPARE(QtConcurrent::run([](int a){ return a+15; }, 12).result(), 12+15); + QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15)); + QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5); + +#ifdef Q_COMPILER_INITIALIZER_LISTS + { + QString str { "Hello World Foo" }; + QFuture f1 = QtConcurrent::run([&](){ return str.split(' '); }); + auto r = f1.result(); + QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); + } +#endif +#endif +} + +QTEST_MAIN(tst_QtConcurrentRun) +#include "tst_qtconcurrentrun.moc" diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/.gitignore b/tests/auto/concurrent/qtconcurrentthreadengine/.gitignore new file mode 100644 index 0000000000..a2e2896246 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentthreadengine/.gitignore @@ -0,0 +1 @@ +tst_qtconcurrentthreadengine diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro b/tests/auto/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro new file mode 100644 index 0000000000..f6ddd33504 --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qtconcurrentthreadengine +QT = core testlib concurrent +SOURCES = tst_qtconcurrentthreadengine.cpp diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp new file mode 100644 index 0000000000..9722887c7d --- /dev/null +++ b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp @@ -0,0 +1,520 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +using namespace QtConcurrent; + +class tst_QtConcurrentThreadEngine: public QObject +{ + Q_OBJECT +private slots: + void runDirectly(); + void result(); + void runThroughStarter(); + void cancel(); + void throttle(); + void threadCount(); + void multipleResults(); + void stresstest(); + void cancelQueuedSlowUser(); +#ifndef QT_NO_EXCEPTIONS + void exceptions(); +#endif +}; + + +class PrintUser : public ThreadEngine +{ +public: + ThreadFunctionResult threadFunction() + { + QTest::qSleep(50); + QTest::qSleep(100); + return ThreadFinished; + } +}; + +void tst_QtConcurrentThreadEngine::runDirectly() +{ + { + PrintUser engine; + engine.startSingleThreaded(); + engine.startBlocking(); + } + { + PrintUser *engine = new PrintUser(); + QFuture f = engine->startAsynchronously(); + f.waitForFinished(); + } +} + +class StringResultUser : public ThreadEngine +{ +public: + typedef QString ResultType; + StringResultUser() + : done(false) { } + + bool shouldStartThread() + { + return !done; + } + + ThreadFunctionResult threadFunction() + { + done = true; + return ThreadFinished; + } + + QString *result() + { + foo = "Foo"; + return &foo; + } + QString foo; + bool done; +}; + +void tst_QtConcurrentThreadEngine::result() +{ + StringResultUser engine; + QCOMPARE(*engine.startBlocking(), QString("Foo")); +} + +class VoidResultUser : public ThreadEngine +{ +public: + bool shouldStartThread() + { + return !done; + } + + ThreadFunctionResult threadFunction() + { + done = true; + return ThreadFinished; + } + + void *result() + { + return 0; + } + bool done; +}; + +void tst_QtConcurrentThreadEngine::runThroughStarter() +{ + { + ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); + QFuture f = starter.startAsynchronously(); + QCOMPARE(f.result(), QString("Foo")); + } + + { + ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); + QString str = starter.startBlocking(); + QCOMPARE(str, QString("Foo")); + } +} + +class CancelUser : public ThreadEngine +{ +public: + void *result() + { + return 0; + } + + ThreadFunctionResult threadFunction() + { + while (this->isCanceled() == false) + { + QTest::qSleep(10); + } + return ThreadFinished; + } +}; + +void tst_QtConcurrentThreadEngine::cancel() +{ + { + CancelUser *engine = new CancelUser(); + QFuture f = engine->startAsynchronously(); + f.cancel(); + f.waitForFinished(); + } + { + CancelUser *engine = new CancelUser(); + QFuture f = engine->startAsynchronously(); + QTest::qSleep(10); + f.cancel(); + f.waitForFinished(); + } +} + +QAtomicInt count; +class ThrottleAlwaysUser : public ThreadEngine +{ +public: + ThrottleAlwaysUser() + { + count.store(initialCount = 100); + finishing = false; + } + + bool shouldStartThread() + { + return !finishing; + } + + ThreadFunctionResult threadFunction() + { + forever { + const int local = count.load(); + if (local == 0) { + finishing = true; + return ThreadFinished; + } + + if (count.testAndSetOrdered(local, local - 1)) + break; + } + return ThrottleThread; + } + + bool finishing; + int initialCount; +}; + +// Test that a user task with a thread function that always +// want to be throttled still completes. The thread engine +// should make keep one thread running at all times. +void tst_QtConcurrentThreadEngine::throttle() +{ + const int repeats = 10; + for (int i = 0; i < repeats; ++i) { + QFuture f = (new ThrottleAlwaysUser())->startAsynchronously(); + f.waitForFinished(); + QCOMPARE(count.load(), 0); + } + + for (int i = 0; i < repeats; ++i) { + ThrottleAlwaysUser t; + t.startBlocking(); + QCOMPARE(count.load(), 0); + } +} + +QSet threads; +QMutex mutex; +class ThreadCountUser : public ThreadEngine +{ +public: + ThreadCountUser(bool finishImmediately = false) + { + threads.clear(); + finishing = finishImmediately; + } + + bool shouldStartThread() + { + return !finishing; + } + + ThreadFunctionResult threadFunction() + { + { + QMutexLocker lock(&mutex); + threads.insert(QThread::currentThread()); + } + QTest::qSleep(10); + finishing = true; + return ThreadFinished; + } + + bool finishing; +}; + +void tst_QtConcurrentThreadEngine::threadCount() +{ + QSKIP("QTBUG-23333: This test is unstable"); + + const int repeats = 10; + for (int i = 0; i < repeats; ++i) { + ThreadCountUser t; + t.startBlocking(); + QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount() + 1); // +1 for the main thread. + + (new ThreadCountUser())->startAsynchronously().waitForFinished(); + QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount()); + } + + // Set the finish flag immediately, this should give us one thread only. + for (int i = 0; i < repeats; ++i) { + ThreadCountUser t(true /*finishImmediately*/); + t.startBlocking(); + QCOMPARE(threads.count(), 1); + + (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished(); + QCOMPARE(threads.count(), 1); + } +} + +class MultipleResultsUser : public ThreadEngine +{ +public: + bool shouldStartThread() + { + return false; + } + + ThreadFunctionResult threadFunction() + { + for (int i = 0; i < 10; ++i) + this->reportResult(&i); + return ThreadFinished; + } +}; + + +void tst_QtConcurrentThreadEngine::multipleResults() +{ + MultipleResultsUser *engine = new MultipleResultsUser(); + QFuture f = engine->startAsynchronously(); + QCOMPARE(f.results().count() , 10); + QCOMPARE(f.resultAt(0), 0); + QCOMPARE(f.resultAt(5), 5); + QCOMPARE(f.resultAt(9), 9); + f.waitForFinished(); +} + + +class NoThreadsUser : public ThreadEngine +{ +public: + bool shouldStartThread() + { + return false; + } + + ThreadFunctionResult threadFunction() + { + return ThreadFinished; + } + + void *result() + { + return 0; + } +}; + +void tst_QtConcurrentThreadEngine::stresstest() +{ + const int times = 20000; + + for (int i = 0; i < times; ++i) { + VoidResultUser *engine = new VoidResultUser(); + engine->startAsynchronously().waitForFinished(); + } + + for (int i = 0; i < times; ++i) { + VoidResultUser *engine = new VoidResultUser(); + engine->startAsynchronously(); + } + + for (int i = 0; i < times; ++i) { + VoidResultUser *engine = new VoidResultUser(); + engine->startAsynchronously().waitForFinished(); + } +} + +const int sleepTime = 20; +class SlowUser : public ThreadEngine +{ +public: + bool shouldStartThread() { return false; } + ThreadFunctionResult threadFunction() { QTest::qSleep(sleepTime); return ThreadFinished; } +}; + +void tst_QtConcurrentThreadEngine::cancelQueuedSlowUser() +{ + const int times = 100; + + QTime t; + t.start(); + + { + QList > futures; + for (int i = 0; i < times; ++i) { + SlowUser *engine = new SlowUser(); + futures.append(engine->startAsynchronously()); + } + + foreach(QFuture future, futures) + future.cancel(); + } + + QVERIFY(t.elapsed() < (sleepTime * times) / 2); +} + +#ifndef QT_NO_EXCEPTIONS + +class QtConcurrentExceptionThrower : public ThreadEngine +{ +public: + QtConcurrentExceptionThrower(QThread *blockThread = 0) + { + this->blockThread = blockThread; + } + + ThreadFunctionResult threadFunction() + { + QTest::qSleep(50); + throw QtConcurrent::Exception(); + return ThreadFinished; + } + QThread *blockThread; +}; + +class UnrelatedExceptionThrower : public ThreadEngine +{ +public: + UnrelatedExceptionThrower(QThread *blockThread = 0) + { + this->blockThread = blockThread; + } + + ThreadFunctionResult threadFunction() + { + QTest::qSleep(50); + throw int(); + return ThreadFinished; + } + QThread *blockThread; +}; + +void tst_QtConcurrentThreadEngine::exceptions() +{ + // Asynchronous mode: + { + bool caught = false; + try { + QtConcurrentExceptionThrower *e = new QtConcurrentExceptionThrower(); + QFuture f = e->startAsynchronously(); + f.waitForFinished(); + } catch (const Exception &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } + + // Blocking mode: + // test throwing the exception from a worker thread. + { + bool caught = false; + try { + QtConcurrentExceptionThrower e(QThread::currentThread()); + e.startBlocking(); + } catch (const Exception &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } + + // test throwing the exception from the main thread (different code path) + { + bool caught = false; + try { + QtConcurrentExceptionThrower e(0); + e.startBlocking(); + } catch (const Exception &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } + + // Asynchronous mode: + { + bool caught = false; + try { + UnrelatedExceptionThrower *e = new UnrelatedExceptionThrower(); + QFuture f = e->startAsynchronously(); + f.waitForFinished(); + } catch (const QtConcurrent::UnhandledException &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } + + // Blocking mode: + // test throwing the exception from a worker thread. + { + bool caught = false; + try { + UnrelatedExceptionThrower e(QThread::currentThread()); + e.startBlocking(); + } catch (const QtConcurrent::UnhandledException &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } + + // test throwing the exception from the main thread (different code path) + { + bool caught = false; + try { + UnrelatedExceptionThrower e(0); + e.startBlocking(); + } catch (const QtConcurrent::UnhandledException &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + } +} + +#endif + +QTEST_MAIN(tst_QtConcurrentThreadEngine) + +#include "tst_qtconcurrentthreadengine.moc" diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp index ade17863d9..7daed397d5 100644 --- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include class tst_QTextCodec : public QObject @@ -55,9 +54,7 @@ class tst_QTextCodec : public QObject Q_OBJECT private slots: -#ifndef QT_NO_CONCURRENT void threadSafety(); -#endif void toUnicode_data(); void toUnicode(); @@ -1939,48 +1936,75 @@ void tst_QTextCodec::toLocal8Bit() } #endif -static QByteArray loadAndConvert(const QByteArray &codecName) +class LoadAndConvert: public QRunnable { - QTextCodec *c = QTextCodec::codecForName(codecName); - if (!c) { - qWarning() << "WARNING" << codecName << "not found?"; - return QByteArray(); +public: + LoadAndConvert(const QByteArray &source, QByteArray *destination) + : codecName(source), target(destination) + {} + QByteArray codecName; + QByteArray *target; + void run() + { + QTextCodec *c = QTextCodec::codecForName(codecName); + if (!c) { + qWarning() << "WARNING" << codecName << "not found?"; + return; + } + QString str = QString::fromLatin1(codecName); + QByteArray b = c->fromUnicode(str); + c->toUnicode(b); + *target = codecName; } - QString str = QString::fromLatin1(codecName); - QByteArray b = c->fromUnicode(str); - c->toUnicode(b); - return codecName; -} +}; -static int loadAndConvertMIB(int mib) +class LoadAndConvertMIB: public QRunnable { - QTextCodec *c = QTextCodec::codecForMib(mib); - if (!c) { - qWarning() << "WARNING" << mib << "not found?"; - return 0; +public: + LoadAndConvertMIB(int mib, int *target) + : mib(mib), target(target) + {} + int mib; + int *target; + void run() + { + QTextCodec *c = QTextCodec::codecForMib(mib); + if (!c) { + qWarning() << "WARNING" << mib << "not found?"; + return; + } + QString str = QString::number(mib); + QByteArray b = c->fromUnicode(str); + c->toUnicode(b); + *target = mib; } - QString str = QString::number(mib); - QByteArray b = c->fromUnicode(str); - c->toUnicode(b); - return mib; -} +}; -#ifndef QT_NO_CONCURRENT void tst_QTextCodec::threadSafety() { QList codecList = QTextCodec::availableCodecs(); QList mibList = QTextCodec::availableMibs(); QThreadPool::globalInstance()->setMaxThreadCount(12); - QFuture res = QtConcurrent::mapped(codecList, loadAndConvert); + QVector res; + res.resize(codecList.size()); + for (int i = 0; i < codecList.size(); ++i) { + QThreadPool::globalInstance()->start(new LoadAndConvert(codecList.at(i), &res[i])); + } - QFuture res2 = QtConcurrent::mapped(mibList, loadAndConvertMIB); + QVector res2; + res2.resize(mibList.size()); + for (int i = 0; i < mibList.size(); ++i) { + QThreadPool::globalInstance()->start(new LoadAndConvertMIB(mibList.at(i), &res2[i])); + } + + // wait for all threads to finish working + QThreadPool::globalInstance()->waitForDone(); - QCOMPARE(res.results(), codecList); - QCOMPARE(res2.results(), mibList); + QCOMPARE(res.toList(), codecList); + QCOMPARE(res2.toList(), mibList); } -#endif void tst_QTextCodec::invalidNames() { diff --git a/tests/auto/corelib/concurrent/concurrent.pro b/tests/auto/corelib/concurrent/concurrent.pro deleted file mode 100644 index 6541b0ce42..0000000000 --- a/tests/auto/corelib/concurrent/concurrent.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE=subdirs -SUBDIRS=\ - qfuture \ - qfuturesynchronizer \ - qfuturewatcher \ - qtconcurrentfilter \ - qtconcurrentiteratekernel \ - qtconcurrentmap \ - qtconcurrentresultstore \ - qtconcurrentrun \ - qtconcurrentthreadengine \ - qthreadpool - diff --git a/tests/auto/corelib/concurrent/qfuture/.gitignore b/tests/auto/corelib/concurrent/qfuture/.gitignore deleted file mode 100644 index 77c055c874..0000000000 --- a/tests/auto/corelib/concurrent/qfuture/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfuture diff --git a/tests/auto/corelib/concurrent/qfuture/qfuture.pro b/tests/auto/corelib/concurrent/qfuture/qfuture.pro deleted file mode 100644 index 517871ab5d..0000000000 --- a/tests/auto/corelib/concurrent/qfuture/qfuture.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qfuture -QT = core-private testlib -SOURCES = tst_qfuture.cpp -DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp b/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp deleted file mode 100644 index 3610f8f2d4..0000000000 --- a/tests/auto/corelib/concurrent/qfuture/tst_qfuture.cpp +++ /dev/null @@ -1,1438 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include - -#define QFUTURE_TEST - -#include -#include -#include -#include -#include -#include - -using namespace QtConcurrent; - -// COM interface macro. -#if defined(Q_OS_WIN) && defined(interface) -# undef interface -#endif - -class tst_QFuture: public QObject -{ - Q_OBJECT -private slots: - void resultStore(); - void future(); - void futureInterface(); - void refcounting(); - void cancel(); - void statePropagation(); - void multipleResults(); - void indexedResults(); - void progress(); - void progressText(); - void resultsAfterFinished(); - void resultsAsList(); - void implicitConversions(); - void iterators(); - void pause(); - void throttling(); - void voidConversions(); -#ifndef QT_NO_EXCEPTIONS - void exceptions(); - void nestedExceptions(); -#endif -}; - -void tst_QFuture::resultStore() -{ - int int0 = 0; - int int1 = 1; - int int2 = 2; - - { - ResultStore store; - QVERIFY(store.begin() == store.end()); - QVERIFY(store.resultAt(0) == store.end()); - QVERIFY(store.resultAt(1) == store.end()); - } - - - { - ResultStoreBase store; - store.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since - store.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QVERIFY(it != store.begin()); - QVERIFY(it == store.end()); - } - - QVector vec0 = QVector() << 2 << 3; - QVector vec1 = QVector() << 4 << 5; - - { - ResultStoreBase store; - store.addResults(-1, &vec0, 2, 2); - store.addResults(-1, &vec1, 2, 2); - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - - ++it; - QCOMPARE(it.resultIndex(), 3); - - ++it; - QVERIFY(it == store.end()); - } - { - ResultStoreBase store; - store.addResult(-1, &int0); - store.addResults(-1, &vec1, 2, 2); - store.addResult(-1, &int1); - - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - QVERIFY(it != store.end()); - ++it; - QCOMPARE(it.resultIndex(), 3); - QVERIFY(it != store.end()); - ++it; - QVERIFY(it == store.end()); - - QCOMPARE(store.resultAt(0).resultIndex(), 0); - QCOMPARE(store.resultAt(1).resultIndex(), 1); - QCOMPARE(store.resultAt(2).resultIndex(), 2); - QCOMPARE(store.resultAt(3).resultIndex(), 3); - QCOMPARE(store.resultAt(4), store.end()); - } - { - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(-1, &int1); - - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - QVERIFY(it != store.end()); - ++it; - QCOMPARE(it.resultIndex(), 3); - QVERIFY(it != store.end()); - ++it; - QVERIFY(it == store.end()); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(3).value(), int1); - } - { - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(200, &int1); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(200).value(), int1); - } - - { - ResultStore store; - store.addResult(1, &int1); - store.addResult(0, &int0); - store.addResult(-1, &int2); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), int1); - QCOMPARE(store.resultAt(2).value(), int2); - } - - { - ResultStore store; - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(INT_MAX), false); - } - - { - // Test filter mode, where "gaps" in the result array aren't allowed. - ResultStore store; - store.setFilterMode(true); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int2); // add result at index 2 - QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. - - store.addResult(1, &int1); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); // 2 should be visible now. - - store.addResult(4, &int0); - store.addResult(5, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(7), false); - - store.addResult(3, &int0); // adding 3 makes 4 and 5 visible - QCOMPARE(store.contains(4), true); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.contains(7), false); - - store.addResult(6, &int0); // adding 6 makes 7 visible - - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - QCOMPARE(store.contains(8), false); - } - - { - // test canceled results - ResultStore store; - store.setFilterMode(true); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int0); - QCOMPARE(store.contains(2), false); - - store.addCanceledResult(1); // report no result at 1 - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 - QCOMPARE(store.contains(2), false); - - store.addResult(3, &int0); - QCOMPARE(store.contains(2), true); //3 gets renamed to 2 - - store.addResult(6, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(3), false); - - store.addCanceledResult(4); - store.addCanceledResult(5); - - QCOMPARE(store.contains(3), true); //6 gets renamed to 3 - QCOMPARE(store.contains(4), true); //7 gets renamed to 4 - - store.addResult(8, &int0); - QCOMPARE(store.contains(5), true); //8 gets renamed to 4 - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } - - { - // test addResult return value - ResultStore store; - store.setFilterMode(true); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 1); // result 0 becomes available - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int0); - QCOMPARE(store.count(), 1); - QCOMPARE(store.contains(2), false); - - store.addCanceledResult(1); - QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - - store.addResult(3, &int0); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(2), true); - - store.addResult(6, &int0); - QCOMPARE(store.count(), 3); - store.addResult(7, &int0); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(3), false); - - store.addCanceledResult(4); - store.addCanceledResult(5); - QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available - - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), true); - - store.addResult(8, &int0); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.count(), 6); - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } - - { - // test resultCount in non-filtered mode. It should always be possible - // to iterate through the results 0 to resultCount. - ResultStore store; - store.addResult(0, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(2, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResult(2, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 4); - } - { - ResultStore store; - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addResult(2, &int0); - QCOMPARE(store.count(), 5); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addCanceledResult(2); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 - - store.addResult(5, &int0); - QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 - } - - { - ResultStore store; - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), false); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - - store.addCanceledResult(0); - store.addCanceledResult(2); - store.addCanceledResults(4, 2); - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } - { - ResultStore store; - store.setFilterMode(true); - store.addCanceledResult(0); - QCOMPARE(store.contains(0), false); - - store.addResult(1, &int0); - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), false); - } -} - -void tst_QFuture::future() -{ - // default constructors - QFuture intFuture; - intFuture.waitForFinished(); - QFuture stringFuture; - stringFuture.waitForFinished(); - QFuture voidFuture; - voidFuture.waitForFinished(); - QFuture defaultVoidFuture; - defaultVoidFuture.waitForFinished(); - - // copy constructor - QFuture intFuture2(intFuture); - QFuture voidFuture2(defaultVoidFuture); - - // assigmnent operator - intFuture2 = QFuture(); - voidFuture2 = QFuture(); - - // state - QCOMPARE(intFuture2.isStarted(), true); - QCOMPARE(intFuture2.isFinished(), true); -} - -class IntResult : public QFutureInterface -{ -public: - QFuture run() - { - this->reportStarted(); - QFuture future = QFuture(this); - - int res = 10; - reportFinished(&res); - return future; - } -}; - -int value = 10; - -class VoidResult : public QFutureInterfaceBase -{ -public: - QFuture run() - { - this->reportStarted(); - QFuture future = QFuture(this); - reportFinished(); - return future; - } -}; - -void tst_QFuture::futureInterface() -{ - { - QFuture future; - { - QFutureInterface i; - i.reportStarted(); - future = i.future(); - i.reportFinished(); - } - } - { - QFuture future; - { - QFutureInterface i; - i.reportStarted(); - i.reportResult(10); - future = i.future(); - i.reportFinished(); - } - QCOMPARE(future.resultAt(0), 10); - } - - { - QFuture intFuture; - - QCOMPARE(intFuture.isStarted(), true); - QCOMPARE(intFuture.isFinished(), true); - - IntResult result; - - result.reportStarted(); - intFuture = result.future(); - - QCOMPARE(intFuture.isStarted(), true); - QCOMPARE(intFuture.isFinished(), false); - - result.reportFinished(&value); - - QCOMPARE(intFuture.isStarted(), true); - QCOMPARE(intFuture.isFinished(), true); - - int e = intFuture.result(); - - QCOMPARE(intFuture.isStarted(), true); - QCOMPARE(intFuture.isFinished(), true); - QCOMPARE(intFuture.isCanceled(), false); - - QCOMPARE(e, value); - intFuture.waitForFinished(); - - IntResult intAlgo; - intFuture = intAlgo.run(); - QFuture intFuture2(intFuture); - QCOMPARE(intFuture.result(), value); - QCOMPARE(intFuture2.result(), value); - intFuture.waitForFinished(); - - VoidResult a; - a.run().waitForFinished(); - } -} - -template -void testRefCounting() -{ - QFutureInterface interface; - QCOMPARE(interface.d->refCount.load(), 1); - - { - interface.reportStarted(); - - QFuture f = interface.future(); - QCOMPARE(interface.d->refCount.load(), 2); - - QFuture f2(f); - QCOMPARE(interface.d->refCount.load(), 3); - - QFuture f3; - f3 = f2; - QCOMPARE(interface.d->refCount.load(), 4); - - interface.reportFinished(0); - QCOMPARE(interface.d->refCount.load(), 4); - } - - QCOMPARE(interface.d->refCount.load(), 1); -} - -void tst_QFuture::refcounting() -{ - testRefCounting(); -} - -void tst_QFuture::cancel() -{ - { - QFuture f; - QFutureInterface result; - - result.reportStarted(); - f = result.future(); - QVERIFY(f.isCanceled() == false); - result.reportCanceled(); - QVERIFY(f.isCanceled()); - result.reportFinished(); - QVERIFY(f.isCanceled()); - f.waitForFinished(); - QVERIFY(f.isCanceled()); - } - - // Cancel from the QFuture side and test if the result - // interface detects it. - { - QFutureInterface result; - - QFuture f; - QVERIFY(f.isStarted() == true); - - result.reportStarted(); - f = result.future(); - - QVERIFY(f.isStarted() == true); - - QVERIFY(result.isCanceled() == false); - f.cancel(); - - QVERIFY(result.isCanceled()); - - result.reportFinished(); - } - - // Test that finished futures can be canceled. - { - QFutureInterface result; - - QFuture f; - QVERIFY(f.isStarted() == true); - - result.reportStarted(); - f = result.future(); - - QVERIFY(f.isStarted() == true); - - result.reportFinished(); - - f.cancel(); - - QVERIFY(result.isCanceled()); - QVERIFY(f.isCanceled()); - } - - // Results reported after canceled is called should not be propagated. - { - - QFutureInterface futureInterface; - futureInterface.reportStarted(); - QFuture f = futureInterface.future(); - - int result = 0; - futureInterface.reportResult(&result); - result = 1; - futureInterface.reportResult(&result); - f.cancel(); - result = 2; - futureInterface.reportResult(&result); - result = 3; - futureInterface.reportResult(&result); - futureInterface.reportFinished(); - QCOMPARE(f.results(), QList()); - } -} - -void tst_QFuture::statePropagation() -{ - QFuture f1; - QFuture f2; - - QCOMPARE(f1.isStarted(), true); - - QFutureInterface result; - result.reportStarted(); - f1 = result.future(); - - f2 = f1; - - QCOMPARE(f2.isStarted(), true); - - result.reportCanceled(); - - QCOMPARE(f2.isStarted(), true); - QCOMPARE(f2.isCanceled(), true); - - QFuture f3 = f2; - - QCOMPARE(f3.isStarted(), true); - QCOMPARE(f3.isCanceled(), true); - - result.reportFinished(); - - QCOMPARE(f2.isStarted(), true); - QCOMPARE(f2.isCanceled(), true); - - QCOMPARE(f3.isStarted(), true); - QCOMPARE(f3.isCanceled(), true); -} - -/* - Tests that a QFuture can return multiple results. -*/ -void tst_QFuture::multipleResults() -{ - IntResult a; - a.reportStarted(); - QFuture f = a.future(); - - QFuture copy = f; - int result; - - result = 1; - a.reportResult(&result); - QCOMPARE(f.resultAt(0), 1); - - result = 2; - a.reportResult(&result); - QCOMPARE(f.resultAt(1), 2); - - result = 3; - a.reportResult(&result); - - result = 4; - a.reportFinished(&result); - - QCOMPARE(f.results(), QList() << 1 << 2 << 3 << 4); - - // test foreach - QList fasit = QList() << 1 << 2 << 3 << 4; - { - QList results; - foreach(int result, f) - results.append(result); - QCOMPARE(results, fasit); - } - { - QList results; - foreach(int result, copy) - results.append(result); - QCOMPARE(results, fasit); - } -} - -/* - Test out-of-order result reporting using indexes -*/ -void tst_QFuture::indexedResults() -{ - { - QFutureInterface Interface; - QFuture f; - QVERIFY(f.isStarted() == true); - - Interface.reportStarted(); - f = Interface.future(); - - QVERIFY(f.isStarted() == true); - - QChar result; - - result = 'B'; - Interface.reportResult(&result, 1); - - QCOMPARE(f.resultAt(1), result); - - result = 'A'; - Interface.reportResult(&result, 0); - QCOMPARE(f.resultAt(0), result); - - result = 'C'; - Interface.reportResult(&result); // no index - QCOMPARE(f.resultAt(2), result); - - Interface.reportFinished(); - - QCOMPARE(f.results(), QList() << 'A' << 'B' << 'C'); - } - - { - // Test result reporting with a missing result in the middle - QFutureInterface Interface; - Interface.reportStarted(); - QFuture f = Interface.future(); - int result; - - result = 0; - Interface.reportResult(&result, 0); - QVERIFY(f.isResultReadyAt(0)); - QCOMPARE(f.resultAt(0), 0); - - result = 3; - Interface.reportResult(&result, 3); - QVERIFY(f.isResultReadyAt(3)); - QCOMPARE(f.resultAt(3), 3); - - result = 2; - Interface.reportResult(&result, 2); - QVERIFY(f.isResultReadyAt(2)); - QCOMPARE(f.resultAt(2), 2); - - result = 4; - Interface.reportResult(&result); // no index - QVERIFY(f.isResultReadyAt(4)); - QCOMPARE(f.resultAt(4), 4); - - Interface.reportFinished(); - - QCOMPARE(f.results(), QList() << 0 << 2 << 3 << 4); - } -} - -void tst_QFuture::progress() -{ - QFutureInterface result; - QFuture f; - - QCOMPARE (f.progressValue(), 0); - - result.reportStarted(); - f = result.future(); - - QCOMPARE (f.progressValue(), 0); - - result.setProgressValue(50); - - QCOMPARE (f.progressValue(), 50); - - result.reportFinished(); - - QCOMPARE (f.progressValue(), 50); -} - -void tst_QFuture::progressText() -{ - QFutureInterface i; - i.reportStarted(); - QFuture f = i.future(); - - QCOMPARE(f.progressText(), QLatin1String("")); - i.setProgressValueAndText(1, QLatin1String("foo")); - QCOMPARE(f.progressText(), QLatin1String("foo")); - i.reportFinished(); -} - -/* - Test that results reported after finished are ignored. -*/ -void tst_QFuture::resultsAfterFinished() -{ - { - IntResult a; - a.reportStarted(); - QFuture f = a.future(); - int result; - - QCOMPARE(f.resultCount(), 0); - - result = 1; - a.reportResult(&result); - QCOMPARE(f.resultAt(0), 1); - - a.reportFinished(); - - QCOMPARE(f.resultAt(0), 1); - QCOMPARE(f.resultCount(), 1); - result = 2; - a.reportResult(&result); - QCOMPARE(f.resultCount(), 1); - } - // cancel it - { - IntResult a; - a.reportStarted(); - QFuture f = a.future(); - int result; - - QCOMPARE(f.resultCount(), 0); - - result = 1; - a.reportResult(&result); - QCOMPARE(f.resultAt(0), 1); - QCOMPARE(f.resultCount(), 1); - - a.reportCanceled(); - - QCOMPARE(f.resultAt(0), 1); - QCOMPARE(f.resultCount(), 1); - - result = 2; - a.reportResult(&result); - a.reportFinished(); - } -} - -void tst_QFuture::resultsAsList() -{ - IntResult a; - a.reportStarted(); - QFuture f = a.future(); - - int result; - result = 1; - a.reportResult(&result); - result = 2; - a.reportResult(&result); - - a.reportFinished(); - - QList results = f.results(); - QCOMPARE(results, QList() << 1 << 2); -} - -/* - Test that QFuture can be implicitly converted to T -*/ -void tst_QFuture::implicitConversions() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture f(&iface); - - const QString input("FooBar 2000"); - iface.reportFinished(&input); - - const QString result = f; - QCOMPARE(result, input); - QCOMPARE(QString(f), input); - QCOMPARE(static_cast(f), input); -} - -void tst_QFuture::iterators() -{ - { - QFutureInterface e; - e.reportStarted(); - QFuture f = e.future(); - - int result; - result = 1; - e.reportResult(&result); - result = 2; - e.reportResult(&result); - result = 3; - e.reportResult(&result); - e.reportFinished(); - - QList results; - QFutureIterator i(f); - while (i.hasNext()) { - results.append(i.next()); - } - - QCOMPARE(results, f.results()); - - QFuture::const_iterator i1 = f.begin(), i2 = i1 + 1; - QFuture::const_iterator c1 = i1, c2 = c1 + 1; - - QVERIFY(i1 == i1); - QVERIFY(i1 == c1); - QVERIFY(c1 == i1); - QVERIFY(c1 == c1); - QVERIFY(i2 == i2); - QVERIFY(i2 == c2); - QVERIFY(c2 == i2); - QVERIFY(c2 == c2); - - QVERIFY(i1 != i2); - QVERIFY(i1 != c2); - QVERIFY(c1 != i2); - QVERIFY(c1 != c2); - QVERIFY(i2 != i1); - QVERIFY(i2 != c1); - QVERIFY(c2 != i1); - QVERIFY(c2 != c1); - - int x1 = *i1; - Q_UNUSED(x1); - int x2 = *i2; - Q_UNUSED(x2); - int y1 = *c1; - Q_UNUSED(y1); - int y2 = *c2; - Q_UNUSED(y2); - } - - { - QFutureInterface e; - e.reportStarted(); - QFuture f = e.future(); - - e.reportResult(QString("one")); - e.reportResult(QString("two")); - e.reportResult(QString("three")); - e.reportFinished(); - - QList results; - QFutureIterator i(f); - while (i.hasNext()) { - results.append(i.next()); - } - - QCOMPARE(results, f.results()); - - QFuture::const_iterator i1 = f.begin(), i2 = i1 + 1; - QFuture::const_iterator c1 = i1, c2 = c1 + 1; - - QVERIFY(i1 == i1); - QVERIFY(i1 == c1); - QVERIFY(c1 == i1); - QVERIFY(c1 == c1); - QVERIFY(i2 == i2); - QVERIFY(i2 == c2); - QVERIFY(c2 == i2); - QVERIFY(c2 == c2); - - QVERIFY(i1 != i2); - QVERIFY(i1 != c2); - QVERIFY(c1 != i2); - QVERIFY(c1 != c2); - QVERIFY(i2 != i1); - QVERIFY(i2 != c1); - QVERIFY(c2 != i1); - QVERIFY(c2 != c1); - - QString x1 = *i1; - QString x2 = *i2; - QString y1 = *c1; - QString y2 = *c2; - - QCOMPARE(x1, y1); - QCOMPARE(x2, y2); - - int i1Size = i1->size(); - int i2Size = i2->size(); - int c1Size = c1->size(); - int c2Size = c2->size(); - - QCOMPARE(i1Size, c1Size); - QCOMPARE(i2Size, c2Size); - } - - { - const int resultCount = 20; - - QFutureInterface e; - e.reportStarted(); - QFuture f = e.future(); - - for (int i = 0; i < resultCount; ++i) { - e.reportResult(i); - } - - e.reportFinished(); - - { - QFutureIterator it(f); - QFutureIterator it2(it); - } - - { - QFutureIterator it(f); - - for (int i = 0; i < resultCount - 1; ++i) { - QVERIFY(it.hasNext()); - QCOMPARE(it.peekNext(), i); - QCOMPARE(it.next(), i); - } - - QVERIFY(it.hasNext()); - QCOMPARE(it.peekNext(), resultCount - 1); - QCOMPARE(it.next(), resultCount - 1); - QVERIFY(it.hasNext() == false); - } - - { - QFutureIterator it(f); - QVERIFY(it.hasNext()); - it.toBack(); - QVERIFY(it.hasNext() == false); - it.toFront(); - QVERIFY(it.hasNext()); - } - } -} - -class SignalSlotObject : public QObject -{ -Q_OBJECT -public: - SignalSlotObject() - : finishedCalled(false), - canceledCalled(false), - rangeBegin(0), - rangeEnd(0) { } - -public slots: - void finished() - { - finishedCalled = true; - } - - void canceled() - { - canceledCalled = true; - } - - void resultReady(int index) - { - results.insert(index); - } - - void progressRange(int begin, int end) - { - rangeBegin = begin; - rangeEnd = end; - } - - void progress(int progress) - { - reportedProgress.insert(progress); - } -public: - bool finishedCalled; - bool canceledCalled; - QSet results; - int rangeBegin; - int rangeEnd; - QSet reportedProgress; -}; - -void tst_QFuture::pause() -{ - QFutureInterface Interface; - - Interface.reportStarted(); - QFuture f = Interface.future(); - - QVERIFY(Interface.isPaused() == false); - f.pause(); - QVERIFY(Interface.isPaused() == true); - f.resume(); - QVERIFY(Interface.isPaused() == false); - f.togglePaused(); - QVERIFY(Interface.isPaused() == true); - f.togglePaused(); - QVERIFY(Interface.isPaused() == false); - - Interface.reportFinished(); -} - -const int resultCount = 1000; - -class ResultObject : public QObject -{ -Q_OBJECT -public slots: - void resultReady(int) - { - - } -public: -}; - -// Test that that the isPaused() on future result interface returns true -// if we report a lot of results that are not handled. -void tst_QFuture::throttling() -{ - { - QFutureInterface i; - - i.reportStarted(); - QFuture f = i.future(); - - QVERIFY(i.isThrottled() == false); - - i.setThrottled(true); - QVERIFY(i.isThrottled()); - - i.setThrottled(false); - QVERIFY(i.isThrottled() == false); - - i.setThrottled(true); - QVERIFY(i.isThrottled()); - - i.reportFinished(); - } -} - -void tst_QFuture::voidConversions() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture intFuture(&iface); - - int value = 10; - iface.reportFinished(&value); - - QFuture voidFuture(intFuture); - voidFuture = intFuture; - - QVERIFY(voidFuture == intFuture); -} - - -#ifndef QT_NO_EXCEPTIONS - -QFuture createExceptionFuture() -{ - QFutureInterface i; - i.reportStarted(); - QFuture f = i.future(); - - Exception e; - i.reportException(e); - i.reportFinished(); - return f; -} - -QFuture createExceptionResultFuture() -{ - QFutureInterface i; - i.reportStarted(); - QFuture f = i.future(); - int r = 0; - i.reportResult(r); - - Exception e; - i.reportException(e); - i.reportFinished(); - return f; -} - -class DerivedException : public Exception -{ -public: - void raise() const { throw *this; } - Exception *clone() const { return new DerivedException(*this); } -}; - -QFuture createDerivedExceptionFuture() -{ - QFutureInterface i; - i.reportStarted(); - QFuture f = i.future(); - - DerivedException e; - i.reportException(e); - i.reportFinished(); - return f; -} - -void tst_QFuture::exceptions() -{ - // test throwing from waitForFinished - { - QFuture f = createExceptionFuture(); - bool caught = false; - try { - f.waitForFinished(); - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - // test result() - { - QFuture f = createExceptionResultFuture(); - bool caught = false; - try { - f.result(); - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - // test result() and destroy - { - bool caught = false; - try { - createExceptionResultFuture().result(); - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - // test results() - { - QFuture f = createExceptionResultFuture(); - bool caught = false; - try { - f.results(); - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - // test foreach - { - QFuture f = createExceptionResultFuture(); - bool caught = false; - try { - foreach (int e, f.results()) { - Q_UNUSED(e); - QFAIL("did not get exception"); - } - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - // catch derived exceptions - { - bool caught = false; - try { - createDerivedExceptionFuture().waitForFinished(); - } catch (Exception &) { - caught = true; - } - QVERIFY(caught); - } - - { - bool caught = false; - try { - createDerivedExceptionFuture().waitForFinished(); - } catch (DerivedException &) { - caught = true; - } - QVERIFY(caught); - } -} - -class MyClass -{ -public: - ~MyClass() - { - QFuture f = createExceptionFuture(); - try { - f.waitForFinished(); - } catch (Exception &) { - caught = true; - } - } - static bool caught; -}; - -bool MyClass::caught = false; - -// This is a regression test for QTBUG-18149. where QFuture did not throw -// exceptions if called from destructors when the stack was already unwinding -// due to an exception having been thrown. -void tst_QFuture::nestedExceptions() -{ - try { - MyClass m; - Q_UNUSED(m); - throw 0; - } catch (int) {} - - QVERIFY(MyClass::caught); -} - -#endif // QT_NO_EXCEPTIONS - -QTEST_MAIN(tst_QFuture) -#include "tst_qfuture.moc" diff --git a/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro b/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro deleted file mode 100644 index b36560b4ba..0000000000 --- a/tests/auto/corelib/concurrent/qfuturesynchronizer/qfuturesynchronizer.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qfuturesynchronizer -QT = core testlib -SOURCES = tst_qfuturesynchronizer.cpp diff --git a/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp b/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp deleted file mode 100644 index 5bf6d1d1f3..0000000000 --- a/tests/auto/corelib/concurrent/qfuturesynchronizer/tst_qfuturesynchronizer.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include -#include - -class tst_QFutureSynchronizer : public QObject -{ - Q_OBJECT - - -private Q_SLOTS: - void construction(); - void addFuture(); - void cancelOnWait(); - void clearFutures(); - void futures(); - void setFuture(); - void waitForFinished(); -}; - - -void tst_QFutureSynchronizer::construction() -{ - - QFuture future; - QFutureSynchronizer synchronizer; - QFutureSynchronizer synchronizerWithFuture(future); - - QCOMPARE(synchronizer.futures().size(), 0); - QCOMPARE(synchronizerWithFuture.futures().size(), 1); -} - -void tst_QFutureSynchronizer::addFuture() -{ - QFutureSynchronizer synchronizer; - - synchronizer.addFuture(QFuture()); - QFuture future; - synchronizer.addFuture(future); - synchronizer.addFuture(future); - - QCOMPARE(synchronizer.futures().size(), 3); -} - -void tst_QFutureSynchronizer::cancelOnWait() -{ - QFutureSynchronizer synchronizer; - QVERIFY(!synchronizer.cancelOnWait()); - synchronizer.setCancelOnWait(true); - QVERIFY(synchronizer.cancelOnWait()); - synchronizer.setCancelOnWait(false); - QVERIFY(!synchronizer.cancelOnWait()); - synchronizer.setCancelOnWait(true); - QVERIFY(synchronizer.cancelOnWait()); -} - -void tst_QFutureSynchronizer::clearFutures() -{ - QFutureSynchronizer synchronizer; - synchronizer.clearFutures(); - QVERIFY(synchronizer.futures().isEmpty()); - - synchronizer.addFuture(QFuture()); - QFuture future; - synchronizer.addFuture(future); - synchronizer.addFuture(future); - synchronizer.clearFutures(); - QVERIFY(synchronizer.futures().isEmpty()); -} - -void tst_QFutureSynchronizer::futures() -{ - QFutureSynchronizer synchronizer; - - QList > futures; - for (int i=0; i<100; i++) { - QFuture future; - futures.append(future); - synchronizer.addFuture(future); - } - - QCOMPARE(futures, synchronizer.futures()); -} - -void tst_QFutureSynchronizer::setFuture() -{ - QFutureSynchronizer synchronizer; - - for (int i=0; i<100; i++) { - synchronizer.addFuture(QFuture()); - } - QCOMPARE(synchronizer.futures().size(), 100); - - QFuture future; - synchronizer.setFuture(future); - QCOMPARE(synchronizer.futures().size(), 1); - QCOMPARE(synchronizer.futures().first(), future); -} - -void tst_QFutureSynchronizer::waitForFinished() -{ - QFutureSynchronizer synchronizer; - - for (int i=0; i<100; i++) { - synchronizer.addFuture(QFuture()); - } - synchronizer.waitForFinished(); - const QList > futures = synchronizer.futures(); - - for (int i=0; i<100; i++) { - QVERIFY(futures.at(i).isFinished()); - } -} - -QTEST_MAIN(tst_QFutureSynchronizer) - -#include "tst_qfuturesynchronizer.moc" diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore b/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore deleted file mode 100644 index 1d778431c5..0000000000 --- a/tests/auto/corelib/concurrent/qfuturewatcher/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfuturewatcher diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro b/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro deleted file mode 100644 index ae98fed3d9..0000000000 --- a/tests/auto/corelib/concurrent/qfuturewatcher/qfuturewatcher.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qfuturewatcher -QT = core-private testlib -SOURCES = tst_qfuturewatcher.cpp diff --git a/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp deleted file mode 100644 index 5a86d97d4e..0000000000 --- a/tests/auto/corelib/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace QtConcurrent; - -#include - -//#define PRINT - -class tst_QFutureWatcher: public QObject -{ - Q_OBJECT -private slots: - void startFinish(); - void progressValueChanged(); - void canceled(); - void resultAt(); - void resultReadyAt(); - void futureSignals(); - void watchFinishedFuture(); - void watchCanceledFuture(); - void disconnectRunningFuture(); - void tooMuchProgress(); - void progressText(); - void sharedFutureInterface(); - void changeFuture(); - void cancelEvents(); - void pauseEvents(); - void finishedState(); - void throttling(); - void incrementalMapResults(); - void incrementalFilterResults(); - void qfutureSynchronizer(); - void warnRace(); -}; - -void sleeper() -{ - QTest::qSleep(100); -} - -void tst_QFutureWatcher::startFinish() -{ - QFutureWatcher futureWatcher; - - QSignalSpy startedSpy(&futureWatcher, SIGNAL(started())); - QSignalSpy finishedSpy(&futureWatcher, SIGNAL(finished())); - - QVERIFY(startedSpy.isValid()); - QVERIFY(finishedSpy.isValid()); - - futureWatcher.setFuture(QtConcurrent::run(sleeper)); - QTest::qWait(10); // spin the event loop to deliver queued signals. - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 0); - futureWatcher.future().waitForFinished(); - QTest::qWait(10); - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 1); -} - -void mapSleeper(int &) -{ - QTest::qSleep(100); -} - -QSet progressValues; -QSet progressTexts; -QMutex mutex; -class ProgressObject : public QObject -{ -Q_OBJECT -public slots: - void printProgress(int); - void printText(const QString &text); - void registerProgress(int); - void registerText(const QString &text); -}; - -void ProgressObject::printProgress(int progress) -{ - qDebug() << "thread" << QThread::currentThread() << "reports progress" << progress; -} - -void ProgressObject::printText(const QString &text) -{ - qDebug() << "thread" << QThread::currentThread() << "reports progress text" << text; -} - -void ProgressObject::registerProgress(int progress) -{ - QTest::qSleep(1); - progressValues.insert(progress); -} - -void ProgressObject::registerText(const QString &text) -{ - QTest::qSleep(1); - progressTexts.insert(text); -} - - -QList createList(int listSize) -{ - QList list; - for (int i = 0; i < listSize; ++i) { - list.append(i); - } - return list; -} - -void tst_QFutureWatcher::progressValueChanged() -{ -#ifdef PRINT - qDebug() << "main thread" << QThread::currentThread(); -#endif - - progressValues.clear(); - const int listSize = 20; - QList list = createList(listSize); - - QFutureWatcher futureWatcher; - ProgressObject progressObject; - QObject::connect(&futureWatcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); -#ifdef PRINT - QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(printProgress(int)), Qt::DirectConnection ); -#endif - QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &progressObject, SLOT(registerProgress(int))); - - futureWatcher.setFuture(QtConcurrent::map(list, mapSleeper)); - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - futureWatcher.disconnect(); - QVERIFY(progressValues.contains(0)); - QVERIFY(progressValues.contains(listSize)); -} - -class CancelObject : public QObject -{ -Q_OBJECT -public: - bool wasCanceled; - CancelObject() : wasCanceled(false) {}; -public slots: - void cancel(); -}; - -void CancelObject::cancel() -{ -#ifdef PRINT - qDebug() << "thread" << QThread::currentThread() << "reports canceled"; -#endif - wasCanceled = true; -} - -void tst_QFutureWatcher::canceled() -{ - const int listSize = 20; - QList list = createList(listSize); - - QFutureWatcher futureWatcher; - QFuture future; - CancelObject cancelObject; - - QObject::connect(&futureWatcher, SIGNAL(canceled()), &cancelObject, SLOT(cancel())); - QObject::connect(&futureWatcher, SIGNAL(canceled()), - &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); - - future = QtConcurrent::map(list, mapSleeper); - futureWatcher.setFuture(future); - futureWatcher.cancel(); - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - - QVERIFY(future.isCanceled()); - QVERIFY(cancelObject.wasCanceled); - futureWatcher.disconnect(); - future.waitForFinished(); -} - -class IntTask : public RunFunctionTask -{ -public: - void runFunctor() - { - result = 10; - } -}; - -void tst_QFutureWatcher::resultAt() -{ - QFutureWatcher futureWatcher; - futureWatcher.setFuture((new IntTask())->start()); - futureWatcher.waitForFinished(); - QCOMPARE(futureWatcher.result(), 10); - QCOMPARE(futureWatcher.resultAt(0), 10); -} - -void tst_QFutureWatcher::resultReadyAt() -{ - QFutureWatcher futureWatcher; - QObject::connect(&futureWatcher, SIGNAL(resultReadyAt(int)), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); - - QFuture future = (new IntTask())->start(); - futureWatcher.setFuture(future); - - QTestEventLoop::instance().enterLoop(1); - QVERIFY(!QTestEventLoop::instance().timeout()); - - // Setting the future again should give us another signal. - // (this is to prevent the race where the task associated - // with the future finishes before setFuture is called.) - futureWatcher.setFuture(QFuture()); - futureWatcher.setFuture(future); - - QTestEventLoop::instance().enterLoop(1); - QVERIFY(!QTestEventLoop::instance().timeout()); -} - -class SignalSlotObject : public QObject -{ -Q_OBJECT - -signals: - void cancel(); - -public slots: - void started() - { - qDebug() << "started called"; - } - - void finished() - { - qDebug() << "finished called"; - } - - void canceled() - { - qDebug() << "canceled called"; - } - -#ifdef PRINT - void resultReadyAt(int index) - { - qDebug() << "result" << index << "ready"; - } -#else - void resultReadyAt(int) { } -#endif - void progressValueChanged(int progress) - { - qDebug() << "progress" << progress; - } - - void progressRangeChanged(int min, int max) - { - qDebug() << "progress range" << min << max; - } - -}; - -void tst_QFutureWatcher::futureSignals() -{ - { - QFutureInterface a; - QFutureWatcher f; - - SignalSlotObject object; -#ifdef PRINT - connect(&f, SIGNAL(finished()), &object, SLOT(finished())); - connect(&f, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); -#endif - // must connect to resultReadyAt so that the watcher can detect the connection - // (QSignalSpy does not trigger it.) - connect(&f, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - a.reportStarted(); - f.setFuture(a.future()); - - QSignalSpy progressSpy(&f, SIGNAL(progressValueChanged(int))); - QVERIFY(progressSpy.isValid()); - const int progress = 1; - a.setProgressValue(progress); - QTest::qWait(10); - QCOMPARE(progressSpy.count(), 2); - QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 0); - QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 1); - - QSignalSpy finishedSpy(&f, SIGNAL(finished())); - QSignalSpy resultReadySpy(&f, SIGNAL(resultReadyAt(int))); - - QVERIFY(finishedSpy.isValid()); - QVERIFY(resultReadySpy.isValid()); - - const int result = 10; - a.reportResult(&result); - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 1); - a.reportFinished(&result); - QTest::qWait(10); - - QCOMPARE(resultReadySpy.count(), 2); - QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 0); // check the index - QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 1); - - QCOMPARE(finishedSpy.count(), 1); - } -} - -void tst_QFutureWatcher::watchFinishedFuture() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture f = iface.future(); - - int value = 100; - iface.reportFinished(&value); - - QFutureWatcher watcher; - - SignalSlotObject object; -#ifdef PRINT - connect(&watcher, SIGNAL(started()), &object, SLOT(started())); - connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled())); - connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); - connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); - connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int))); -#endif - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - - QSignalSpy startedSpy(&watcher, SIGNAL(started())); - QSignalSpy finishedSpy(&watcher, SIGNAL(finished())); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QSignalSpy canceledSpy(&watcher, SIGNAL(canceled())); - - QVERIFY(startedSpy.isValid()); - QVERIFY(finishedSpy.isValid()); - QVERIFY(resultReadySpy.isValid()); - QVERIFY(canceledSpy.isValid()); - - watcher.setFuture(f); - QTest::qWait(10); - - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(resultReadySpy.count(), 1); - QCOMPARE(canceledSpy.count(), 0); -} - -void tst_QFutureWatcher::watchCanceledFuture() -{ - QFuture f; - QFutureWatcher watcher; - - SignalSlotObject object; -#ifdef PRINT - connect(&watcher, SIGNAL(started()), &object, SLOT(started())); - connect(&watcher, SIGNAL(canceled()), &object, SLOT(canceled())); - connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); - connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); - connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &object, SLOT(progressRangeChanged(int, int))); -#endif - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - - QSignalSpy startedSpy(&watcher, SIGNAL(started())); - QSignalSpy finishedSpy(&watcher, SIGNAL(finished())); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QSignalSpy canceledSpy(&watcher, SIGNAL(canceled())); - - QVERIFY(startedSpy.isValid()); - QVERIFY(finishedSpy.isValid()); - QVERIFY(resultReadySpy.isValid()); - QVERIFY(canceledSpy.isValid()); - - watcher.setFuture(f); - QTest::qWait(10); - - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(resultReadySpy.count(), 0); - QCOMPARE(canceledSpy.count(), 1); -} - -void tst_QFutureWatcher::disconnectRunningFuture() -{ - QFutureInterface a; - a.reportStarted(); - - QFuture f = a.future(); - QFutureWatcher *watcher = new QFutureWatcher(); - watcher->setFuture(f); - - SignalSlotObject object; - connect(watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - - QSignalSpy finishedSpy(watcher, SIGNAL(finished())); - QSignalSpy resultReadySpy(watcher, SIGNAL(resultReadyAt(int))); - - QVERIFY(finishedSpy.isValid()); - QVERIFY(resultReadySpy.isValid()); - - const int result = 10; - a.reportResult(&result); - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 1); - - delete watcher; - - a.reportResult(&result); - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 1); - - a.reportFinished(&result); - QTest::qWait(10); - QCOMPARE(finishedSpy.count(), 0); -} - -const int maxProgress = 100000; -class ProgressEmitterTask : public RunFunctionTask -{ -public: - void runFunctor() - { - setProgressRange(0, maxProgress); - for (int p = 0; p <= maxProgress; ++p) - setProgressValue(p); - } -}; - -void tst_QFutureWatcher::tooMuchProgress() -{ - progressValues.clear(); - ProgressObject o; - - QFutureWatcher f; - QObject::connect(&f, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); -#ifdef PRINT - QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int))); -#endif - QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int))); - f.setFuture((new ProgressEmitterTask())->start()); - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(progressValues.contains(maxProgress)); -} - -template -class ProgressTextTask : public RunFunctionTask -{ -public: - void runFunctor() - { - this->setProgressValueAndText(1, QLatin1String("Foo 1")); - - while (this->isProgressUpdateNeeded() == false) - QTest::qSleep(1); - this->setProgressValueAndText(2, QLatin1String("Foo 2")); - - while (this->isProgressUpdateNeeded() == false) - QTest::qSleep(1); - this->setProgressValueAndText(3, QLatin1String("Foo 3")); - - while (this->isProgressUpdateNeeded() == false) - QTest::qSleep(1); - this->setProgressValueAndText(4, QLatin1String("Foo 4")); - } -}; - -void tst_QFutureWatcher::progressText() -{ - { // instantiate API for T=int and T=void. - ProgressTextTask a; - ProgressTextTask b; - } - { - progressValues.clear(); - progressTexts.clear(); - QFuture f = ((new ProgressTextTask())->start()); - QFutureWatcher watcher; - ProgressObject o; - QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); -#ifdef PRINT - QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int))); - QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(printText(const QString &))); -#endif - QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int))); - QObject::connect(&watcher, SIGNAL(progressTextChanged(const QString &)), &o, SLOT(registerText(const QString &))); - - watcher.setFuture(f); - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - - QCOMPARE(f.progressText(), QLatin1String("Foo 4")); - QCOMPARE(f.progressValue(), 4); - QVERIFY(progressValues.contains(1)); - QVERIFY(progressValues.contains(2)); - QVERIFY(progressValues.contains(3)); - QVERIFY(progressValues.contains(4)); - QVERIFY(progressTexts.contains(QLatin1String("Foo 1"))); - QVERIFY(progressTexts.contains(QLatin1String("Foo 2"))); - QVERIFY(progressTexts.contains(QLatin1String("Foo 3"))); - QVERIFY(progressTexts.contains(QLatin1String("Foo 4"))); - } -} - -template -void callInterface(T &obj) -{ - obj.progressValue(); - obj.progressMinimum(); - obj.progressMaximum(); - obj.progressText(); - - obj.isStarted(); - obj.isFinished(); - obj.isRunning(); - obj.isCanceled(); - obj.isPaused(); - - obj.cancel(); - obj.pause(); - obj.resume(); - obj.togglePaused(); - obj.waitForFinished(); - - const T& objConst = obj; - objConst.progressValue(); - objConst.progressMinimum(); - objConst.progressMaximum(); - objConst.progressText(); - - objConst.isStarted(); - objConst.isFinished(); - objConst.isRunning(); - objConst.isCanceled(); - objConst.isPaused(); -} - -template -void callInterface(const T &obj) -{ - obj.result(); - obj.resultAt(0); -} - - -// QFutureWatcher and QFuture has a similar interface. Test -// that the functions we want ot have in both are actually -// there. -void tst_QFutureWatcher::sharedFutureInterface() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture intFuture = iface.future(); - - int value = 0; - iface.reportFinished(&value); - - QFuture voidFuture; - QFutureWatcher intWatcher; - intWatcher.setFuture(intFuture); - QFutureWatcher voidWatcher; - - callInterface(intFuture); - callInterface(voidFuture); - callInterface(intWatcher); - callInterface(voidWatcher); - - callInterface(intFuture); - callInterface(intWatcher); -} - -void tst_QFutureWatcher::changeFuture() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture a = iface.future(); - - int value = 0; - iface.reportFinished(&value); - - QFuture b; - - QFutureWatcher watcher; - - SignalSlotObject object; - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QVERIFY(resultReadySpy.isValid()); - - watcher.setFuture(a); // Watch 'a' which will genere a resultReady event. - watcher.setFuture(b); // But oh no! we're switching to another future - QTest::qWait(10); // before the event gets delivered. - - QCOMPARE(resultReadySpy.count(), 0); - - watcher.setFuture(a); - watcher.setFuture(b); - watcher.setFuture(a); // setting it back gets us one event, not two. - QTest::qWait(10); - - QCOMPARE(resultReadySpy.count(), 1); -} - -// Test that events aren't delivered from canceled futures -void tst_QFutureWatcher::cancelEvents() -{ - QFutureInterface iface; - iface.reportStarted(); - - QFuture a = iface.future(); - - int value = 0; - iface.reportFinished(&value); - - QFutureWatcher watcher; - - SignalSlotObject object; - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QVERIFY(resultReadySpy.isValid()); - - watcher.setFuture(a); - watcher.cancel(); - - QTest::qWait(10); - - QCOMPARE(resultReadySpy.count(), 0); -} - -// Tests that events from paused futures are saved and -// delivered on resume. -void tst_QFutureWatcher::pauseEvents() -{ - { - QFutureInterface iface; - iface.reportStarted(); - - QFuture a = iface.future(); - - int value = 0; - iface.reportFinished(&value); - - QFutureWatcher watcher; - - SignalSlotObject object; - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QVERIFY(resultReadySpy.isValid()); - - watcher.setFuture(a); - watcher.pause(); - - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 0); - - watcher.resume(); - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 1); - } - { - QFutureInterface iface; - iface.reportStarted(); - - QFuture a = iface.future(); - - int value = 0; - iface.reportFinished(&value); - - QFutureWatcher watcher; - - SignalSlotObject object; - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); - QSignalSpy resultReadySpy(&watcher, SIGNAL(resultReadyAt(int))); - QVERIFY(resultReadySpy.isValid()); - - watcher.setFuture(a); - a.pause(); - - QFuture b; - watcher.setFuture(b); // If we watch b instead, resuming a - a.resume(); // should give us no results. - - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 0); - } -} - -// Test that the finished state for the watcher gets -// set when the finished event is delivered. -// This means it will lag the finished state for the future, -// but makes it more useful. -void tst_QFutureWatcher::finishedState() -{ - QFutureInterface iface; - iface.reportStarted(); - QFuture future = iface.future(); - QFutureWatcher watcher; - - watcher.setFuture(future); - QTest::qWait(10); - - iface.reportFinished(); - QVERIFY(future.isFinished()); - QVERIFY(watcher.isFinished() == false); - - QTest::qWait(10); - QVERIFY(watcher.isFinished()); -} - -/* - Verify that throttling kicks in if you report a lot of results, - and that it clears when the result events are processed. -*/ -void tst_QFutureWatcher::throttling() -{ - QFutureInterface iface; - iface.reportStarted(); - QFuture future = iface.future(); - QFutureWatcher watcher; - watcher.setFuture(future); - - QVERIFY(iface.isThrottled() == false); - - for (int i = 0; i < 1000; ++i) { - int result = 0; - iface.reportResult(result); - } - - QVERIFY(iface.isThrottled() == true); - - QTest::qWait(100); // process events. - - QVERIFY(iface.isThrottled() == false); - - iface.reportFinished(); -} - -int mapper(const int &i) -{ - return i; -} - -class ResultReadyTester : public QObject -{ -Q_OBJECT -public: - ResultReadyTester(QFutureWatcher *watcher) - :m_watcher(watcher), filter(false), ok(true), count(0) - { - - } -public slots: - void resultReadyAt(int index) - { - ++count; - if (m_watcher->future().isResultReadyAt(index) == false) - ok = false; - if (!filter && m_watcher->future().resultAt(index) != index) - ok = false; - if (filter && m_watcher->future().resultAt(index) != index * 2 + 1) - ok = false; - } -public: - QFutureWatcher *m_watcher; - bool filter; - bool ok; - int count; -}; - -void tst_QFutureWatcher::incrementalMapResults() -{ - QFutureWatcher watcher; - - SignalSlotObject object; -#ifdef PRINT - connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); - connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); -#endif - - QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - ResultReadyTester resultReadyTester(&watcher); - connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int))); - - const int count = 10000; - QList ints; - for (int i = 0; i < count; ++i) - ints << i; - - QFuture future = QtConcurrent::mapped(ints, mapper); - watcher.setFuture(future); - - QTestEventLoop::instance().enterLoop(10); - QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(resultReadyTester.count, count); - QVERIFY(resultReadyTester.ok); - QVERIFY(watcher.isFinished()); - future.waitForFinished(); -} - -bool filterer(int i) -{ - return (i % 2); -} - -void tst_QFutureWatcher::incrementalFilterResults() -{ - QFutureWatcher watcher; - - SignalSlotObject object; -#ifdef PRINT - connect(&watcher, SIGNAL(finished()), &object, SLOT(finished())); - connect(&watcher, SIGNAL(progressValueChanged(int)), &object, SLOT(progressValueChanged(int))); - connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); -#endif - - QObject::connect(&watcher, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - - ResultReadyTester resultReadyTester(&watcher); - resultReadyTester.filter = true; - connect(&watcher, SIGNAL(resultReadyAt(int)), &resultReadyTester, SLOT(resultReadyAt(int))); - - const int count = 10000; - QList ints; - for (int i = 0; i < count; ++i) - ints << i; - - QFuture future = QtConcurrent::filtered(ints, filterer); - watcher.setFuture(future); - - QTestEventLoop::instance().enterLoop(10); - QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(resultReadyTester.count, count / 2); - QVERIFY(resultReadyTester.ok); - QVERIFY(watcher.isFinished()); - future.waitForFinished(); -} - -void tst_QFutureWatcher::qfutureSynchronizer() -{ - int taskCount = 1000; - QTime t; - t.start(); - - { - QFutureSynchronizer sync; - - sync.setCancelOnWait(true); - for (int i = 0; i < taskCount; ++i) { - sync.addFuture(run(sleeper)); - } - } - - // Test that we're not running each task. - QVERIFY(t.elapsed() < taskCount * 10); -} - -class DummyObject : public QObject { - Q_OBJECT -public slots: - void dummySlot() {} -public: - static void function(QMutex *m) - { - QMutexLocker lock(m); - } -}; - -void tst_QFutureWatcher::warnRace() -{ -#ifndef Q_OS_MAC //I don't know why it is not working on mac -#ifndef QT_NO_DEBUG - QTest::ignoreMessage(QtWarningMsg, "QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); -#endif -#endif - QFutureWatcher watcher; - DummyObject object; - QMutex mutex; - mutex.lock(); - - QFuture future = QtConcurrent::run(DummyObject::function, &mutex); - watcher.setFuture(future); - QTRY_VERIFY(future.isStarted()); - connect(&watcher, SIGNAL(finished()), &object, SLOT(dummySlot())); - mutex.unlock(); - future.waitForFinished(); -} - -QTEST_MAIN(tst_QFutureWatcher) -#include "tst_qfuturewatcher.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore deleted file mode 100644 index f93d27e009..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentfilter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtconcurrentfilter diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro b/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro deleted file mode 100644 index f783455b2e..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentfilter/qtconcurrentfilter.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentfilter -QT = core testlib -SOURCES = tst_qtconcurrentfilter.cpp -DEFINES += QT_STRICT_ITERATORS - -CONFIG += insignificant_test # See QTBUG-20688 diff --git a/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp b/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp deleted file mode 100644 index 971a6992ff..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp +++ /dev/null @@ -1,1543 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include -#include - -#include "../qtconcurrentmap/functions.h" - -class tst_QtConcurrentFilter : public QObject -{ - Q_OBJECT - -private slots: -#ifdef QT_NO_CONCURRENT_FILTER - void initTestCase(); -#else - void filter(); - void filtered(); - void filteredReduced(); - void resultAt(); - void incrementalResults(); - void noDetach(); -#ifndef QT_NO_STL - void stlContainers(); -#endif -#endif -}; - -#ifdef QT_NO_CONCURRENT_FILTER -void tst_QtConcurrentFilter::initTestCase() -{ - QSKIP("This test is skipped for gcc 3.x"); -} - -#else - -void tst_QtConcurrentFilter::filter() -{ - // functor - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::filter(list, KeepEvenIntegers()).waitForFinished(); - QCOMPARE(list, QList() << 2 << 4); - } - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(list, KeepEvenIntegers()); - QCOMPARE(list, QList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::filter(linkedList, KeepEvenIntegers()).waitForFinished(); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(linkedList, KeepEvenIntegers()); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - { - QVector vector; - vector << 1 << 2 << 3 << 4; - QtConcurrent::filter(vector, KeepEvenIntegers()).waitForFinished(); - QCOMPARE(vector, QVector() << 2 << 4); - } - { - QVector vector; - vector << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(vector, KeepEvenIntegers()); - QCOMPARE(vector, QVector() << 2 << 4); - } - - - // function - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::filter(list, keepEvenIntegers).waitForFinished(); - QCOMPARE(list, QList() << 2 << 4); - } - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(list, keepEvenIntegers); - QCOMPARE(list, QList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished(); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(linkedList, keepEvenIntegers); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - - // bound function - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::filter(list, keepEvenIntegers).waitForFinished(); - QCOMPARE(list, QList() << 2 << 4); - } - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(list, keepEvenIntegers); - QCOMPARE(list, QList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::filter(linkedList, keepEvenIntegers).waitForFinished(); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(linkedList, keepEvenIntegers); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - - // member - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::filter(list, &Number::isEven).waitForFinished(); - QCOMPARE(list, QList() << 2 << 4); - } - { - QList list; - list << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(list, &Number::isEven); - QCOMPARE(list, QList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::filter(linkedList, &Number::isEven).waitForFinished(); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QtConcurrent::blockingFilter(linkedList, &Number::isEven); - QCOMPARE(linkedList, QLinkedList() << 2 << 4); - } -} - -void tst_QtConcurrentFilter::filtered() -{ - QList list; - list << 1 << 2 << 3 << 4; - - // functor - { - QFuture f = QtConcurrent::filtered(list, KeepEvenIntegers()); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.begin(), list.end(), KeepEvenIntegers()); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.constBegin(), - list.constEnd(), - KeepEvenIntegers()); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered(list, KeepEvenIntegers()); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.begin(), - list.end(), - KeepEvenIntegers()); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), - list.constEnd(), - KeepEvenIntegers()); - QCOMPARE(list2, QList() << 2 << 4); - } - - { - QVector vector; - vector << 1 << 2 << 3 << 4; - QVector vector2 = QtConcurrent::blockingFiltered(vector, KeepEvenIntegers()); - QCOMPARE(vector2, QVector() << 2 << 4); - } - { - QVector vector; - vector << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(vector, KeepEvenIntegers()); - QCOMPARE(f.results(), QList() << 2 << 4); - } - - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers()); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(linkedList, KeepEvenIntegers()); - QCOMPARE(f.results(), QList() << 2 << 4); - } - - // function - { - QFuture f = QtConcurrent::filtered(list, keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.constBegin(), - list.constEnd(), - keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.begin(), - list.end(), - keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), - list.constEnd(), - keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - - // bound function - { - QFuture f = QtConcurrent::filtered(list, keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.begin(), list.end(), keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(list.constBegin(), - list.constEnd(), - keepEvenIntegers); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered(list, keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.begin(), - list.end(), - keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFiltered >(list.constBegin(), - list.constEnd(), - keepEvenIntegers); - QCOMPARE(list2, QList() << 2 << 4); - } - - // const member function - { - QList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers, &Number::isEven); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers.begin(), - integers.end(), - &Number::isEven); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers.constBegin(), - integers.constEnd(), - &Number::isEven); - QList list2 = f.results(); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList integers; - integers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::blockingFiltered(integers, &Number::isEven); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList integers; - integers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::blockingFiltered >(integers.begin(), - integers.end(), - &Number::isEven); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList integers; - integers << 1 << 2 << 3 << 4; - QList list2 = - QtConcurrent::blockingFiltered >(integers.constBegin(), - integers.constEnd(), - &Number::isEven); - QCOMPARE(list2, QList() << 2 << 4); - } - - // same thing on linked lists - - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - - // functor - { - QFuture f = QtConcurrent::filtered(linkedList, KeepEvenIntegers()); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers()); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers()); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, KeepEvenIntegers()); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers()); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers()); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // function - { - QFuture f = QtConcurrent::filtered(linkedList, keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.begin(), - linkedList.end(), - keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), - linkedList.end(), - keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // bound function - { - QFuture f = QtConcurrent::filtered(linkedList, keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.begin(), - linkedList.end(), - keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QFuture f = QtConcurrent::filtered(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered(linkedList, keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.begin(), - linkedList.end(), - keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // const member function - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers, &Number::isEven); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers.begin(), - integers.end(), - &Number::isEven); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QFuture f = QtConcurrent::filtered(integers.constBegin(), - integers.constEnd(), - &Number::isEven); - QList linkedList2 = f.results(); - QCOMPARE(linkedList2, QList() << 2 << 4); - } - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFiltered(integers, &Number::isEven); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFiltered >(integers.begin(), - integers.end(), - &Number::isEven); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList integers; - integers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = - QtConcurrent::blockingFiltered >(integers.constBegin(), - integers.constEnd(), - &Number::isEven); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } -} - -void tst_QtConcurrentFilter::filteredReduced() -{ - QList list; - list << 1 << 2 << 3 << 4; - QList numberList; - numberList << 1 << 2 << 3 << 4; - - // functor-functor - { - int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce); - QCOMPARE(sum2, 6); - } - { - QVector vector; - vector << 1 << 2 << 3 << 4; - int sum = QtConcurrent::filteredReduced(vector, KeepEvenIntegers(), IntSumReduce()); - QCOMPARE(sum, 6); - } - - { - int sum = QtConcurrent::filteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - - // function-functor - { - int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - - // functor-function - { - int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - - // function-function - { - int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - - // functor-member - { - QList list2 = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::filteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - KeepEvenIntegers(), - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - KeepEvenIntegers(), - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - - // member-functor - { - int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, NumberSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(QList(numberList), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberList.begin(), - numberList.end(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList, &Number::isEven, NumberSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(QList(numberList), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList.begin(), - numberList.end(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - - // member-member - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::filteredReduced(numbers, - &Number::isEven, - &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::filteredReduced(numbers.begin(), - numbers.end(), - &Number::isEven, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::filteredReduced(numbers.constBegin(), - numbers.constEnd(), - &Number::isEven, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::blockingFilteredReduced(numbers, - &Number::isEven, - &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::blockingFilteredReduced(numbers.begin(), - numbers.end(), - &Number::isEven, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList numbers; - numbers << 1 << 2 << 3 << 4; - QList list2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(), - numbers.constEnd(), - &Number::isEven, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - - // function-member - { - QList list2 = QtConcurrent::filteredReduced(list, keepEvenIntegers, &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::filteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::filteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, &QList::push_back, QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list.begin(), - list.end(), - keepEvenIntegers, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - { - QList list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(), - list.constEnd(), - keepEvenIntegers, - &QList::push_back, - QtConcurrent::OrderedReduce); - QCOMPARE(list2, QList() << 2 << 4); - } - - // member-function - { - int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, numberSumReduce); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(QList(numberList), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberList.begin(), - numberList.end(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList, &Number::isEven, numberSumReduce); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(QList(numberList), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList.begin(), - numberList.end(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - - // same as above on linked lists - QLinkedList linkedList; - linkedList << 1 << 2 << 3 << 4; - QLinkedList numberLinkedList; - numberLinkedList << 1 << 2 << 3 << 4; - - // functor-functor - { - int sum = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - IntSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum2, 6); - } - - // function-functor - { - int sum = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - IntSumReduce()); - QCOMPARE(sum, 6); - } - - // functor-function - { - int sum = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - intSumReduce); - QCOMPARE(sum, 6); - } - - // function-function - { - int sum = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - intSumReduce); - QCOMPARE(sum, 6); - } - - // functor-member - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, KeepEvenIntegers(), &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - KeepEvenIntegers(), - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - KeepEvenIntegers(), - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // member-functor - { - int sum = QtConcurrent::filteredReduced(numberLinkedList, &Number::isEven, NumberSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(QLinkedList(numberLinkedList), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberLinkedList.begin(), - numberLinkedList.end(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList, &Number::isEven, NumberSumReduce()); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(QLinkedList(numberLinkedList), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.begin(), - numberLinkedList.end(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::isEven, - NumberSumReduce()); - QCOMPARE(sum, 6); - } - - // member-member - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers, - &Number::isEven, - &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers.begin(), - numbers.end(), - &Number::isEven, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::filteredReduced(numbers.constBegin(), - numbers.constEnd(), - &Number::isEven, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers, - &Number::isEven, - &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.begin(), - numbers.end(), - &Number::isEven, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList numbers; - numbers << 1 << 2 << 3 << 4; - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(), - numbers.constEnd(), - &Number::isEven, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // function-member - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList, keepEvenIntegers, &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::filteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList, keepEvenIntegers, &QLinkedList::append, QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.begin(), - linkedList.end(), - keepEvenIntegers, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingFilteredReduced(linkedList.constBegin(), - linkedList.constEnd(), - keepEvenIntegers, - &QLinkedList::append, - QtConcurrent::OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4); - } - - // member-function - { - int sum = QtConcurrent::filteredReduced(numberLinkedList, &Number::isEven, numberSumReduce); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::filteredReduced(QLinkedList(numberLinkedList), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberLinkedList.begin(), - numberLinkedList.end(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::filteredReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList, &Number::isEven, numberSumReduce); - QCOMPARE(sum, 6); - - int sum2 = QtConcurrent::blockingFilteredReduced(QLinkedList(numberLinkedList), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum2, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.begin(), - numberLinkedList.end(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - { - int sum = QtConcurrent::blockingFilteredReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::isEven, - numberSumReduce); - QCOMPARE(sum, 6); - } - - // ### the same as above, with an initial result value -} - -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() == false); - - QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::blockingFiltered(l, waitFilterfn); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::filter(l, waitFilterfn).waitForFinished(); - QVERIFY(l.isDetached() == true); - QVERIFY(ll.isDetached() == true); - } - { - const QList l = QList() << 1; - QVERIFY(l.isDetached()); - - const QList ll = l; - QVERIFY(l.isDetached() == false); - - QtConcurrent::filtered(l, waitFilterfn).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::filteredReduced(l, waitFilterfn, intSumReduce).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - } -} - -#ifndef QT_NO_STL -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); -} -#endif - -#endif - -QTEST_MAIN(tst_QtConcurrentFilter) -#include "tst_qtconcurrentfilter.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore deleted file mode 100644 index ac5dec4db6..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtconcurrentiteratekernel diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro deleted file mode 100644 index e876c86725..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/qtconcurrentiteratekernel.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentiteratekernel -QT = core testlib -SOURCES = tst_qtconcurrentiteratekernel.cpp diff --git a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp deleted file mode 100644 index 46562b5eb0..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include - -struct TestIterator -{ - TestIterator(int i) - :i(i) { } - - int operator-(const TestIterator &other) - { - return i - other.i; - } - - TestIterator& operator++() - { - ++i; - return *this; - } - - bool operator!=(const TestIterator &other) const - { - return i != other.i; - } - - int i; -}; - -#include -#ifndef QT_NO_STL -namespace std { -template <> -struct iterator_traits -{ - typedef random_access_iterator_tag iterator_category; -}; - -int distance(TestIterator &a, TestIterator &b) -{ - return b - a; -} - -} -#endif - -#include -#include - -using namespace QtConcurrent; - -class tst_QtConcurrentIterateKernel: public QObject -{ - Q_OBJECT -private slots: - // "for" iteration tests: - void instantiate(); - void cancel(); - void stresstest(); - void noIterations(); - void throttling(); -#ifndef QT_NO_STL - void blockSize(); - void multipleResults(); -#endif -}; - -QAtomicInt iterations; -class PrintFor : public IterateKernel -{ -public: - PrintFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } - bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) - { - iterations.fetchAndAddRelaxed(end - begin); -#ifdef PRINT - qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)"; -#endif - return false; - } - bool runIteration(TestIterator it, int index , void *result) - { - return runIterations(it, index, index + 1, result); - } - -}; - -class SleepPrintFor : public IterateKernel -{ -public: - SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } - inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) - { - QTest::qSleep(200); - iterations.fetchAndAddRelaxed(end - begin); -#ifdef PRINT - qDebug() << QThread::currentThread() << "iteration" << begin << "to" << end << "(exclusive)"; -#endif - return false; - } - bool runIteration(TestIterator it, int index , void *result) - { - return runIterations(it, index, index + 1, result); - } -}; - - -void tst_QtConcurrentIterateKernel::instantiate() -{ - startThreadEngine(new PrintFor(0, 40)).startBlocking(); - QCOMPARE(iterations.load(), 40); -} - -void tst_QtConcurrentIterateKernel::cancel() -{ - { - QFuture f = startThreadEngine(new SleepPrintFor(0, 40)).startAsynchronously(); - f.cancel(); - f.waitForFinished(); - QVERIFY(f.isCanceled()); - QVERIFY(iterations.load() <= QThread::idealThreadCount()); // the threads might run one iteration each before they are canceled. - } -} - -QAtomicInt counter; -class CountFor : public IterateKernel -{ -public: - CountFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); } - inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) - { - counter.fetchAndAddRelaxed(end - begin); - return false; - } - bool runIteration(TestIterator it, int index , void *result) - { - return runIterations(it, index, index + 1, result); - } -}; - -void tst_QtConcurrentIterateKernel::stresstest() -{ - const int iterations = 1000; - const int times = 50; - for (int i = 0; i < times; ++i) { - counter.store(0); - CountFor f(0, iterations); - f.startBlocking(); - QCOMPARE(counter.load(), iterations); - } -} - -void tst_QtConcurrentIterateKernel::noIterations() -{ - const int times = 20000; - for (int i = 0; i < times; ++i) - startThreadEngine(new IterateKernel(0, 0)).startBlocking(); -} - -QMutex threadsMutex; -QSet threads; -class ThrottleFor : public IterateKernel -{ -public: - // this class throttles between iterations 100 and 200, - // and then records how many threads that run between - // iterations 140 and 160. - ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { iterations.store(0); throttling = false; } - inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *) - { - if (200 >= begin && 200 < end) { - throttling = false; - } - - iterations.fetchAndAddRelaxed(end - begin); - - QThread *thread = QThread::currentThread(); - - if (begin > 140 && end < 160) { - QMutexLocker locker(&threadsMutex); - threads.insert(thread); - } - - if (100 >= begin && 100 < end) { - throttling = true; - } - - QTest::qWait(1); - - return false; - } - bool runIteration(TestIterator it, int index , void *result) - { - return runIterations(it, index, index + 1, result); - } - - bool shouldThrottleThread() - { - const int load = iterations.load(); - return (load > 100 && load < 200); - } - bool throttling; -}; - -void tst_QtConcurrentIterateKernel::throttling() -{ - const int totalIterations = 400; - iterations.store(0); - - threads.clear(); - - ThrottleFor f(0, totalIterations); - f.startBlocking(); - - QCOMPARE(iterations.load(), totalIterations); - - - QCOMPARE(threads.count(), 1); -} - - -int peakBlockSize = 0; -class BlockSizeRecorder : public IterateKernel -{ -public: - BlockSizeRecorder(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { } - inline bool runIterations(TestIterator, int begin, int end, void *) - { - peakBlockSize = qMax(peakBlockSize, end - begin); - return false; - } -}; - -// Missing stl iterators prevent correct block size calculation. -#ifndef QT_NO_STL -void tst_QtConcurrentIterateKernel::blockSize() -{ - const int expectedMinimumBlockSize = 1024 / QThread::idealThreadCount(); - BlockSizeRecorder(0, 10000).startBlocking(); - if (peakBlockSize < expectedMinimumBlockSize) - qDebug() << "block size" << peakBlockSize; - QVERIFY(peakBlockSize >= expectedMinimumBlockSize); -} -#endif - -class MultipleResultsFor : public IterateKernel -{ -public: - MultipleResultsFor(TestIterator begin, TestIterator end) : IterateKernel(begin, end) { } - inline bool runIterations(TestIterator, int begin, int end, int *results) - { - for (int i = begin; i < end; ++i) - results[i - begin] = i; - return true; - } -}; - -// Missing stl iterators prevent correct summation. -#ifndef QT_NO_STL -void tst_QtConcurrentIterateKernel::multipleResults() -{ - QFuture f = startThreadEngine(new MultipleResultsFor(0, 10)).startAsynchronously(); - QCOMPARE(f.results().count() , 10); - QCOMPARE(f.resultAt(0), 0); - QCOMPARE(f.resultAt(5), 5); - QCOMPARE(f.resultAt(9), 9); - f.waitForFinished(); -} -#endif - -QTEST_MAIN(tst_QtConcurrentIterateKernel) - -#include "tst_qtconcurrentiteratekernel.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore deleted file mode 100644 index f1c563e979..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentmap/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtconcurrentmap diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h b/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h deleted file mode 100644 index f5963db904..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentmap/functions.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef FUNCTIONS_H -#define FUNCTIONS_H - -bool keepEvenIntegers(const int &x) -{ - return (x & 1) == 0; -} - -class KeepEvenIntegers -{ -public: - bool operator()(const int &x) - { - return (x & 1) == 0; - } -}; - -class Number -{ - int n; - -public: - Number() - : n(0) - { } - - Number(int n) - : n(n) - { } - - void multiplyBy2() - { - n *= 2; - } - - Number multipliedBy2() const - { - return n * 2; - } - - bool isEven() const - { - return (n & 1) == 0; - } - - int toInt() const - { - return n; - } - - QString toString() const - { - return QString::number(n); - } - - bool operator==(const Number &other) const - { - return n == other.n; - } -}; - -void intSumReduce(int &sum, int x) -{ - sum += x; -} - -class IntSumReduce -{ -public: - void operator()(int &sum, int x) - { - sum += x; - } -}; - -void numberSumReduce(int &sum, const Number &x) -{ - sum += x.toInt(); -} - -class NumberSumReduce -{ -public: - void operator()(int &sum, const Number &x) - { - sum += x.toInt(); - } -}; - -#endif diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro b/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro deleted file mode 100644 index b4f5cbc565..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentmap/qtconcurrentmap.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentmap -QT = core testlib -SOURCES = tst_qtconcurrentmap.cpp -DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp deleted file mode 100644 index 960511d87b..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp +++ /dev/null @@ -1,2426 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include - -#include -#include - -#include - -#include "functions.h" - -Q_DECLARE_METATYPE(QVector); -Q_DECLARE_METATYPE(QVector); -Q_DECLARE_METATYPE(QVector); -Q_DECLARE_METATYPE(QList); -Q_DECLARE_METATYPE(QList); -Q_DECLARE_METATYPE(QList); - -class tst_QtConcurrentMap: public QObject -{ - Q_OBJECT -private slots: -#ifdef QT_NO_CONCURRENT_MAP - void initTestCase() -#else - void map(); - void blocking_map(); - void mapped(); - void blocking_mapped(); - void mappedReduced(); - void blocking_mappedReduced(); - void assignResult(); - void functionOverloads(); -#ifndef QT_NO_EXCEPTIONS - void exceptions(); -#endif - void incrementalResults(); - void noDetach(); -#ifndef QT_NO_STL - void stlContainers(); -#endif - void qFutureAssignmentLeak(); - void stressTest(); -public slots: - void throttling(); -#endif -}; - -#ifdef QT_NO_CONCURRENT_FILTER -void tst_QtConcurrentFilter::initTestCase() -{ - QSKIP("This test is skipped for gcc 3.x"); -} - -#else - -using namespace QtConcurrent; - -void multiplyBy2Immutable(int x) -{ - x *= 2; -} - -class MultiplyBy2Immutable -{ -public: - void operator()(int x) - { - x *= 2; - } -}; - -void multiplyBy2InPlace(int &x) -{ - x *= 2; -} - -class MultiplyBy2InPlace -{ -public: - void operator()(int &x) - { - x *= 2; - } -}; - -Q_DECLARE_METATYPE(QList); - -void tst_QtConcurrentMap::map() -{ - // functors take arguments by reference, modifying the sequence in place - { - QList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished(); - QCOMPARE(list, QList() << 2 << 4 << 6); - QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished(); - QCOMPARE(list, QList() << 4 << 8 << 12); - - // function - QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QList() << 8 << 16 << 24); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QList() << 16 << 32 << 48); - - // bound function - QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QList() << 32 << 64 << 96); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QList() << 64 << 128 << 192); - - // member function - QList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished(); - QCOMPARE(numberList, QList() << 2 << 4 << 6); - QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished(); - QCOMPARE(numberList, QList() << 4 << 8 << 12); - -#ifdef Q_COMPILER_LAMBDA - // lambda - QtConcurrent::map(list, [](int &x){x *= 2;}).waitForFinished(); - QCOMPARE(list, QList() << 128 << 256 << 384); - QtConcurrent::map(list.begin(), list.end(), [](int &x){x *= 2;}).waitForFinished(); - QCOMPARE(list, QList() << 256 << 512 << 768); -#endif - - } - - // functors don't take arguments by reference, making these no-ops - { - QList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::map(list, MultiplyBy2Immutable()).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::map(list.begin(), list.end(), MultiplyBy2Immutable()).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - // function - QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - // bound function - QtConcurrent::map(list, multiplyBy2Immutable).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - -#ifdef Q_COMPILER_LAMBDA - // lambda - QtConcurrent::map(list, [](int x){x *= 2;}).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::map(list.begin(), list.end(), [](int x){x *= 2;}).waitForFinished(); - QCOMPARE(list, QList() << 1 << 2 << 3); -#endif - } - - // Linked lists and forward iterators - { - QLinkedList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::map(list, MultiplyBy2InPlace()).waitForFinished(); - QCOMPARE(list, QLinkedList() << 2 << 4 << 6); - QtConcurrent::map(list.begin(), list.end(), MultiplyBy2InPlace()).waitForFinished(); - QCOMPARE(list, QLinkedList() << 4 << 8 << 12); - - // function - QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QLinkedList() << 8 << 16 << 24); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QLinkedList() << 16 << 32 << 48); - - // bound function - QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QLinkedList() << 32 << 64 << 96); - QtConcurrent::map(list.begin(), list.end(), multiplyBy2InPlace).waitForFinished(); - QCOMPARE(list, QLinkedList() << 64 << 128 << 192); - - // member function - QLinkedList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::map(numberList, &Number::multiplyBy2).waitForFinished(); - QCOMPARE(numberList, QLinkedList() << 2 << 4 << 6); - QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished(); - QCOMPARE(numberList, QLinkedList() << 4 << 8 << 12); - } - -#if 0 - // not allowed: map() with immutable sequences makes no sense - { - const QList list = QList() << 1 << 2 << 3; - - QtConcurrent::map(list, MultiplyBy2Immutable()); - QtConcurrent::map(list, multiplyBy2Immutable); - QtConcurrent::map(list, multiplyBy2Immutable); - } -#endif - -#if 0 - // not allowed: in place modification of a temp copy (since temp copy goes out of scope) - { - QList list; - list << 1 << 2 << 3; - - QtConcurrent::map(QList(list), MultiplyBy2InPlace()); - QtConcurrent::map(QList(list), multiplyBy2); - QtConcurrent::map(QList(list), multiplyBy2InPlace); - - QList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::map(QList(numberList), &Number::multiplyBy2); - } -#endif - -#if 0 - // not allowed: map() on a const list, where functors try to modify the items in the list - { - const QList list = QList() << 1 << 2 << 3;; - - QtConcurrent::map(list, MultiplyBy2InPlace()); - QtConcurrent::map(list, multiplyBy2InPlace); - QtConcurrent::map(list, multiplyBy2InPlace); - - const QList numberList = QList() << 1 << 2 << 3; - QtConcurrent::map(numberList, &Number::multiplyBy2); - } -#endif -} - -void tst_QtConcurrentMap::blocking_map() -{ - // functors take arguments by reference, modifying the sequence in place - { - QList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); - QCOMPARE(list, QList() << 2 << 4 << 6); - QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace()); - QCOMPARE(list, QList() << 4 << 8 << 12); - - // function - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - QCOMPARE(list, QList() << 8 << 16 << 24); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); - QCOMPARE(list, QList() << 16 << 32 << 48); - - // bound function - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - QCOMPARE(list, QList() << 32 << 64 << 96); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); - QCOMPARE(list, QList() << 64 << 128 << 192); - - // member function - QList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); - QCOMPARE(numberList, QList() << 2 << 4 << 6); - QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2); - QCOMPARE(numberList, QList() << 4 << 8 << 12); - } - - // functors don't take arguments by reference, making these no-ops - { - QList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::blockingMap(list, MultiplyBy2Immutable()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2Immutable()); - QCOMPARE(list, QList() << 1 << 2 << 3); - - // function - QtConcurrent::blockingMap(list, multiplyBy2Immutable); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable); - QCOMPARE(list, QList() << 1 << 2 << 3); - - // bound function - QtConcurrent::blockingMap(list, multiplyBy2Immutable); - QCOMPARE(list, QList() << 1 << 2 << 3); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable); - QCOMPARE(list, QList() << 1 << 2 << 3); - } - - // Linked lists and forward iterators - { - QLinkedList list; - list << 1 << 2 << 3; - - // functor - QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); - QCOMPARE(list, QLinkedList() << 2 << 4 << 6); - QtConcurrent::blockingMap(list.begin(), list.end(), MultiplyBy2InPlace()); - QCOMPARE(list, QLinkedList() << 4 << 8 << 12); - - // function - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - QCOMPARE(list, QLinkedList() << 8 << 16 << 24); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); - QCOMPARE(list, QLinkedList() << 16 << 32 << 48); - - // bound function - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - QCOMPARE(list, QLinkedList() << 32 << 64 << 96); - QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2InPlace); - QCOMPARE(list, QLinkedList() << 64 << 128 << 192); - - // member function - QLinkedList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); - QCOMPARE(numberList, QLinkedList() << 2 << 4 << 6); - QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2); - QCOMPARE(numberList, QLinkedList() << 4 << 8 << 12); - } - -#if 0 - // not allowed: map() with immutable sequences makes no sense - { - const QList list = QList() << 1 << 2 << 3; - - QtConcurrent::blockingMap(list, MultiplyBy2Immutable()); - QtConcurrent::blockkng::map(list, multiplyBy2Immutable); - QtConcurrent::blockingMap(list, multiplyBy2Immutable); - } -#endif - -#if 0 - // not allowed: in place modification of a temp copy (since temp copy goes out of scope) - { - QList list; - list << 1 << 2 << 3; - - QtConcurrent::blockingMap(QList(list), MultiplyBy2InPlace()); - QtConcurrent::blockingMap(QList(list), multiplyBy2); - QtConcurrent::blockingMap(QList(list), multiplyBy2InPlace); - - QList numberList; - numberList << 1 << 2 << 3; - QtConcurrent::blockingMap(QList(numberList), &Number::multiplyBy2); - } -#endif - -#if 0 - // not allowed: map() on a const list, where functors try to modify the items in the list - { - const QList list = QList() << 1 << 2 << 3;; - - QtConcurrent::blockingMap(list, MultiplyBy2InPlace()); - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - QtConcurrent::blockingMap(list, multiplyBy2InPlace); - - const QList numberList = QList() << 1 << 2 << 3; - QtConcurrent::blockingMap(numberList, &Number::multiplyBy2); - } -#endif -} - -int multiplyBy2(int x) -{ - int y = x * 2; - return y; -} - -class MultiplyBy2 -{ -public: - typedef int result_type; - - int operator()(int x) const - { - int y = x * 2; - return y; - } -}; - -double intToDouble(int x) -{ - return double(x); -} - -class IntToDouble -{ -public: - typedef double result_type; - - double operator()(int x) const - { - return double(x); - } -}; - -int stringToInt(const QString &string) -{ - return string.toInt(); -} - -class StringToInt -{ -public: - typedef int result_type; - - int operator()(const QString &string) const - { - return string.toInt(); - } -}; - -void tst_QtConcurrentMap::mapped() -{ - QList list; - list << 1 << 2 << 3; - QLinkedList linkedList; - linkedList << 1 << 2 << 3; - QList numberList; - numberList << 1 << 2 << 3; - QLinkedList numberLinkedList; - numberLinkedList << 1 << 2 << 3; - - // functor - { - QList list2 = QtConcurrent::mapped(list, MultiplyBy2()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - MultiplyBy2()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::mapped(QList(list), MultiplyBy2()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QList list2 = QtConcurrent::mapped(linkedList, MultiplyBy2()).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - MultiplyBy2()).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = - QtConcurrent::mapped(QLinkedList(linkedList), MultiplyBy2()).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - - // function - { - QList list2 = QtConcurrent::mapped(list, multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::mapped(QList(list), multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QList list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - multiplyBy2).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = - QtConcurrent::mapped(QLinkedList(linkedList), multiplyBy2).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - - // bound function - { - QList list2 = QtConcurrent::mapped(list, multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::mapped(QList(list), multiplyBy2).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QList list2 = QtConcurrent::mapped(linkedList, multiplyBy2).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - multiplyBy2) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), multiplyBy2) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - - // const member function - { - QList numberList2 = QtConcurrent::mapped(numberList, &Number::multipliedBy2) - .results(); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList2, QList() << 2 << 4 << 6); - - QList numberList3 = QtConcurrent::mapped(numberList.constBegin(), - numberList.constEnd(), - &Number::multipliedBy2) - .results(); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList3, QList() << 2 << 4 << 6); - - QList numberList4 = QtConcurrent::mapped(QList(numberList), - &Number::multipliedBy2) - .results(); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList4, QList() << 2 << 4 << 6); - } - { - QList numberList2 = QtConcurrent::mapped(numberLinkedList, &Number::multipliedBy2) - .results(); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberList2, QList() << 2 << 4 << 6); - - QList numberList3 = QtConcurrent::mapped(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::multipliedBy2) - .results(); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberList3, QList() << 2 << 4 << 6); - - QList numberList4 = QtConcurrent::mapped(QLinkedList(numberLinkedList), - &Number::multipliedBy2) - .results(); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberList4, QList() << 2 << 4 << 6); - } - - // change the value_type, same container - - // functor - { - QList list2 = QtConcurrent::mapped(list, IntToDouble()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - IntToDouble()) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::mapped(QList(list), - IntToDouble()) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QList list2 = QtConcurrent::mapped(linkedList, IntToDouble()).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - IntToDouble()) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), - IntToDouble()) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - - // function - { - QList list2 = QtConcurrent::mapped(list, intToDouble).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - intToDouble) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::mapped(QList(list), intToDouble).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QList list2 = QtConcurrent::mapped(linkedList, intToDouble).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - intToDouble) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), intToDouble) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - - // bound function - { - QList list2 = QtConcurrent::mapped(list, intToDouble).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(list.constBegin(), - list.constEnd(), - intToDouble) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - - QList list4 = QtConcurrent::mapped(QList(list), - intToDouble) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QList list2 = QtConcurrent::mapped(linkedList, intToDouble).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::mapped(linkedList.constBegin(), - linkedList.constEnd(), - intToDouble) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - - QList list4 = QtConcurrent::mapped(QLinkedList(linkedList), - intToDouble) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - - // const member function - { - QList list2 = QtConcurrent::mapped(numberList, &Number::toString).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << "1" << "2" << "3"); - - QList list3 = QtConcurrent::mapped(numberList.constBegin(), - numberList.constEnd(), - &Number::toString) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << "1" << "2" << "3"); - - QList list4 = QtConcurrent::mapped(QList(numberList), &Number::toString) - .results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << "1" << "2" << "3"); - } - { - QList list2 = QtConcurrent::mapped(numberLinkedList, &Number::toString).results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << "1" << "2" << "3"); - - QList list3 = QtConcurrent::mapped(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toString) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << "1" << "2" << "3"); - - QList list4 = QtConcurrent::mapped(QLinkedList(numberLinkedList), - &Number::toString) - .results(); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << "1" << "2" << "3"); - } - - // change the value_type - { - QList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::mapped(strings, StringToInt()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::mapped(strings.constBegin(), - strings.constEnd(), - StringToInt()) - .results(); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - { - QList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::mapped(strings, stringToInt).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::mapped(strings.constBegin(), - strings.constEnd(), - stringToInt).results(); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - - { - QList numberList2 = QtConcurrent::mapped(numberList, &Number::toInt).results(); - QCOMPARE(numberList2, QList() << 1 << 2 << 3); - - QList numberList3 = QtConcurrent::mapped(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt) - .results(); - QCOMPARE(numberList3, QList() << 1 << 2 << 3); - } - - // change the value_type from QStringList - { - QStringList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::mapped(strings, StringToInt()).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::mapped(strings.constBegin(), - strings.constEnd(), - StringToInt()) - .results(); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - { - QStringList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::mapped(strings, stringToInt).results(); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::mapped(strings.constBegin(), - strings.constEnd(), - stringToInt) - .results(); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } -} - -void tst_QtConcurrentMap::blocking_mapped() -{ - QList list; - list << 1 << 2 << 3; - QLinkedList linkedList; - linkedList << 1 << 2 << 3; - QList numberList; - numberList << 1 << 2 << 3; - QLinkedList numberLinkedList; - numberLinkedList << 1 << 2 << 3; - - // functor - { - QList list2 = QtConcurrent::blockingMapped(list, MultiplyBy2()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - MultiplyBy2()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::blockingMapped(QList(list), MultiplyBy2()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, MultiplyBy2()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - MultiplyBy2()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), MultiplyBy2()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); - } - - // function - { - QList list2 = QtConcurrent::blockingMapped(list, multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::blockingMapped(QList(list), multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); - } - - // bound function - { - QList list2 = QtConcurrent::blockingMapped(list, multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 2 << 4 << 6); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 2 << 4 << 6); - - QList list4 = QtConcurrent::blockingMapped(QList(list), multiplyBy2); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 2 << 4 << 6); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped(linkedList, multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 2 << 4 << 6); - - QLinkedList linkedList4 = QtConcurrent::blockingMapped(QLinkedList(linkedList), multiplyBy2); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 2 << 4 << 6); - } - - // const member function - { - QList numberList2 = QtConcurrent::blockingMapped(numberList, &Number::multipliedBy2); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList2, QList() << 2 << 4 << 6); - - QList numberList3 = QtConcurrent::blockingMapped >(numberList.constBegin(), - numberList.constEnd(), - &Number::multipliedBy2); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList3, QList() << 2 << 4 << 6); - - QList numberList4 = QtConcurrent::blockingMapped(QList(numberList), - &Number::multipliedBy2); - QCOMPARE(numberList, QList() << 1 << 2 << 3); - QCOMPARE(numberList4, QList() << 2 << 4 << 6); - } - { - QLinkedList numberLinkedList2 = QtConcurrent::blockingMapped(numberLinkedList, &Number::multipliedBy2); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberLinkedList2, QLinkedList() << 2 << 4 << 6); - - QLinkedList numberLinkedList3 = QtConcurrent::blockingMapped >(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::multipliedBy2); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberLinkedList3, QLinkedList() << 2 << 4 << 6); - - QLinkedList numberLinkedList4 = QtConcurrent::blockingMapped(QLinkedList(numberLinkedList), - &Number::multipliedBy2); - QCOMPARE(numberLinkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(numberLinkedList4, QLinkedList() << 2 << 4 << 6); - } - - // change the value_type, same container - - // functor - { - QList list2 = QtConcurrent::blockingMapped >(list, IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::blockingMapped >(QList(list), - IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, IntToDouble()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - IntToDouble()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); - - QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), - IntToDouble()); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); - } - - // function - { - QList list2 = QtConcurrent::blockingMapped >(list, intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - QList list4 = QtConcurrent::blockingMapped >(QList(list), intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); - - QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); - } - - // bound function - { - QList list2 = QtConcurrent::blockingMapped >(list, intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1.0 << 2.0 << 3.0); - - QList list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1.0 << 2.0 << 3.0); - - - QList list4 = QtConcurrent::blockingMapped >(QList(list), - intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1.0 << 2.0 << 3.0); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMapped >(linkedList, intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1.0 << 2.0 << 3.0); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(linkedList.constBegin(), - linkedList.constEnd(), - intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1.0 << 2.0 << 3.0); - - - QLinkedList linkedList4 = QtConcurrent::blockingMapped >(QLinkedList(linkedList), - intToDouble); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1.0 << 2.0 << 3.0); - } - - // const member function - { - QList list2 = - QtConcurrent::blockingMapped >(numberList, &Number::toString); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << "1" << "2" << "3"); - - QList list3 = QtConcurrent::blockingMapped >(numberList.constBegin(), - numberList.constEnd() - , &Number::toString); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << "1" << "2" << "3"); - - QList list4 = - QtConcurrent::blockingMapped >(QList(numberList), &Number::toString); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << "1" << "2" << "3"); - } - { - QLinkedList linkedList2 = - QtConcurrent::blockingMapped >(numberLinkedList, &Number::toString); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << "1" << "2" << "3"); - - QLinkedList linkedList3 = QtConcurrent::blockingMapped >(numberLinkedList.constBegin(), - numberLinkedList.constEnd() - , &Number::toString); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << "1" << "2" << "3"); - - QLinkedList linkedList4 = - QtConcurrent::blockingMapped >(QLinkedList(numberLinkedList), &Number::toString); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << "1" << "2" << "3"); - } - - // change the value_type - { - QList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::blockingMapped(strings, StringToInt()); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - StringToInt()); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - { - QList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::blockingMapped(strings, stringToInt); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - stringToInt); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - - { - QList numberList2 = QtConcurrent::blockingMapped(numberList, &Number::toInt); - QCOMPARE(numberList2, QList() << 1 << 2 << 3); - - QList numberList3 = QtConcurrent::blockingMapped >(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt); - QCOMPARE(numberList3, QList() << 1 << 2 << 3); - } - - // change the value_type from QStringList - { - QStringList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::blockingMapped(strings, StringToInt()); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - StringToInt()); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - { - QStringList strings = QStringList() << "1" << "2" << "3"; - QList list = QtConcurrent::blockingMapped(strings, stringToInt); - QCOMPARE(list, QList() << 1 << 2 << 3); - - QList list2 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - stringToInt); - QCOMPARE(list2, QList() << 1 << 2 << 3); - } - - // functor - { - QVector list2 = QtConcurrent::blockingMapped >(list, IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); - - QVector list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); - - QVector list4 = QtConcurrent::blockingMapped >(QList(list), - IntToDouble()); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QVector() << 1.0 << 2.0 << 3.0); - - QStringList strings = QStringList() << "1" << "2" << "3"; - QVector list5 = QtConcurrent::blockingMapped >(strings, StringToInt()); - QCOMPARE(list5, QVector() << 1 << 2 << 3); - - QVector list6 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - StringToInt()); - QCOMPARE(list6, QVector() << 1 << 2 << 3); - - QVector list7 = QtConcurrent::blockingMapped >(QStringList(strings), - StringToInt()); - QCOMPARE(list7, QVector() << 1 << 2 << 3); - } - - // function - { - QVector list2 = QtConcurrent::blockingMapped >(list, intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); - - QVector list3 = QtConcurrent::blockingMapped >(list.constBegin(), - list.constEnd(), - intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); - - QVector list4 = QtConcurrent::blockingMapped >(QList(list), - intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QVector() << 1.0 << 2.0 << 3.0); - - QStringList strings = QStringList() << "1" << "2" << "3"; - QVector list5 = QtConcurrent::blockingMapped >(strings, stringToInt); - QCOMPARE(list5, QVector() << 1 << 2 << 3); - - QVector list6 = QtConcurrent::blockingMapped >(strings.constBegin(), - strings.constEnd(), - stringToInt); - QCOMPARE(list6, QVector() << 1 << 2 << 3); - - QVector list7 = QtConcurrent::blockingMapped >(QStringList(strings), - stringToInt); - QCOMPARE(list7, QVector() << 1 << 2 << 3); - } - - // bound function - { - QVector list2 = QtConcurrent::blockingMapped >(list, intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QVector() << 1.0 << 2.0 << 3.0); - - QVector list3 = QtConcurrent::blockingMapped >(QList(list), intToDouble); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QVector() << 1.0 << 2.0 << 3.0); - - QStringList strings = QStringList() << "1" << "2" << "3"; - QVector list4 = QtConcurrent::blockingMapped >(strings, stringToInt); - QCOMPARE(list4, QVector() << 1 << 2 << 3); - - QVector list5 = QtConcurrent::blockingMapped >(QStringList(strings), stringToInt); - QCOMPARE(list5, QVector() << 1 << 2 << 3); - } - - // const member function - { - QVector list2 = QtConcurrent::blockingMapped >(numberList, &Number::toString); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QVector() << "1" << "2" << "3"); - - QVector list3 = - QtConcurrent::blockingMapped >(QList(numberList), &Number::toString); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QVector() << "1" << "2" << "3"); - - // not allowed: const member function where all arguments have default values -#if 0 - QStringList strings = QStringList() << "1" << "2" << "3"; - QVector list4 = QtConcurrent::blockingMapped >(strings, &QString::toInt); - QCOMPARE(list4, QVector() << 1 << 2 << 3); - - QVector list5 = QtConcurrent::blockingMapped >(QStringList(strings), &QString::toInt); - QCOMPARE(list5, QVector() << 1 << 2 << 3); -#endif - } -} - -int intSquare(int x) -{ - return x * x; -} - -class IntSquare -{ -public: - typedef int result_type; - - int operator()(int x) - { - return x * x; - } -}; - -void tst_QtConcurrentMap::mappedReduced() -{ - QList list; - list << 1 << 2 << 3; - QLinkedList linkedList; - linkedList << 1 << 2 << 3; - QList numberList; - numberList << 1 << 2 << 3; - QLinkedList numberLinkedList; - numberLinkedList << 1 << 2 << 3; - - // test Q_DECLARE_OPERATORS_FOR_FLAGS - QtConcurrent::ReduceOptions opt = (QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce); - QVERIFY(opt); - - // functor-functor - { - int sum = QtConcurrent::mappedReduced(list, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QList(list), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::mappedReduced(QList(list), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - { - int sum = QtConcurrent::mappedReduced(linkedList, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::mappedReduced(linkedList, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::mappedReduced(QLinkedList(linkedList), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - - // function-functor - { - int sum = QtConcurrent::mappedReduced(list, intSquare, IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QList(list), intSquare, IntSumReduce()); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::mappedReduced(linkedList, intSquare, IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), intSquare, IntSumReduce()); - QCOMPARE(sum3, 14); - } - - // functor-function - { - int sum = QtConcurrent::mappedReduced(list, IntSquare(), intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QList(list), IntSquare(), intSumReduce); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::mappedReduced(linkedList, IntSquare(), intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), IntSquare(), intSumReduce); - QCOMPARE(sum3, 14); - } - - // function-function - { - int sum = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QList(list), intSquare, intSumReduce); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::mappedReduced(linkedList, intSquare, intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(linkedList), intSquare, intSumReduce); - QCOMPARE(sum3, 14); - } - - // functor-member - { - QList list2 = QtConcurrent::mappedReduced(list, - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1 << 4 << 9); - - QList list3 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1 << 4 << 9); - - QList list4 = QtConcurrent::mappedReduced(QList(list), - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1 << 4 << 9); - } - { - QLinkedList linkedList2 = QtConcurrent::mappedReduced(linkedList, - IntSquare(), - &QLinkedList::push_back, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - &QLinkedList::push_back, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(linkedList), - IntSquare(), - &QLinkedList::push_back, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); - } - - // member-functor - { - int sum = QtConcurrent::mappedReduced(numberList, &Number::toInt, IntSumReduce()); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::mappedReduced(QList(numberList), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum3, 6); - } - { - int sum = QtConcurrent::mappedReduced(numberLinkedList, &Number::toInt, IntSumReduce()); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum3, 6); - } - - // member-member - { - QList list2 = QtConcurrent::mappedReduced(numberList, - &Number::toInt, - &QList::push_back, - OrderedReduce); - QCOMPARE(list2, QList() << 1 << 2 << 3); - - QList list3 = QtConcurrent::mappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - &QList::push_back, - OrderedReduce); - QCOMPARE(list3, QList() << 1 << 2 << 3); - - QList list4 = QtConcurrent::mappedReduced(QList(numberList), - &Number::toInt, - &QList::push_back, OrderedReduce); - QCOMPARE(list4, QList() << 1 << 2 << 3); - } - { - QLinkedList linkedList2 = QtConcurrent::mappedReduced(numberLinkedList, - &Number::toInt, - &QLinkedList::push_back, - OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 1 << 2 << 3); - - QLinkedList linkedList3 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - &QLinkedList::push_back, - OrderedReduce); - QCOMPARE(linkedList3, QLinkedList() << 1 << 2 << 3); - - QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - &QLinkedList::push_back, OrderedReduce); - QCOMPARE(linkedList4, QLinkedList() << 1 << 2 << 3); - } - - // function-member - { - QList list2 = QtConcurrent::mappedReduced(list, - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1 << 4 << 9); - - QList list3 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1 << 4 << 9); - - QList list4 = QtConcurrent::mappedReduced(QList(list), - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1 << 4 << 9); - } - { - QLinkedList linkedList2 = QtConcurrent::mappedReduced(linkedList, - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList3 = QtConcurrent::mappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList4 = QtConcurrent::mappedReduced(QLinkedList(linkedList), - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); - } - - // member-function - { - int sum = QtConcurrent::mappedReduced(numberList, - &Number::toInt, - intSumReduce); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - intSumReduce); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::mappedReduced(QList(numberList), - &Number::toInt, - intSumReduce); - QCOMPARE(sum3, 6); - } - { - int sum = QtConcurrent::mappedReduced(numberLinkedList, - &Number::toInt, - intSumReduce); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::mappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - intSumReduce); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - intSumReduce); - QCOMPARE(sum3, 6); - } - - // linked lists - { - - QLinkedList list; - list << 1 << 2 << 3; - - QLinkedList numberList; - numberList << 1 << 2 << 3; - - int sum = QtConcurrent::mappedReduced(list, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::mappedReduced(QLinkedList(list), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::mappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::mappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::mappedReduced(QLinkedList(list), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - - // ### the same as above, with an initial result value -} - -void tst_QtConcurrentMap::blocking_mappedReduced() -{ - QList list; - list << 1 << 2 << 3; - QLinkedList linkedList; - linkedList << 1 << 2 << 3; - QList numberList; - numberList << 1 << 2 << 3; - QLinkedList numberLinkedList; - numberLinkedList << 1 << 2 << 3; - - // functor-functor - { - int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(list), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::blockingMappedReduced(QList(list), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - { - int sum = QtConcurrent::blockingMappedReduced(linkedList, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::blockingMappedReduced(linkedList, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - - // function-functor - { - int sum = QtConcurrent::blockingMappedReduced(list, intSquare, IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(list), intSquare, IntSumReduce()); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::blockingMappedReduced(linkedList, intSquare, IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), intSquare, IntSumReduce()); - QCOMPARE(sum3, 14); - } - - // functor-function - { - int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(list), IntSquare(), intSumReduce); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::blockingMappedReduced(linkedList, IntSquare(), intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), IntSquare(), intSumReduce); - QCOMPARE(sum3, 14); - } - - // function-function - { - int sum = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(list), intSquare, intSumReduce); - QCOMPARE(sum3, 14); - } - { - int sum = QtConcurrent::blockingMappedReduced(linkedList, intSquare, intSumReduce); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), intSquare, intSumReduce); - QCOMPARE(sum3, 14); - } - - // functor-member - { - QList list2 = QtConcurrent::blockingMappedReduced(list, - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1 << 4 << 9); - - QList list3 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1 << 4 << 9); - - QList list4 = QtConcurrent::blockingMappedReduced(QList(list), - IntSquare(), - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1 << 4 << 9); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(linkedList, - IntSquare(), - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - IntSquare(), - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), - IntSquare(), - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); - } - - // member-functor - { - int sum = QtConcurrent::blockingMappedReduced(numberList, &Number::toInt, - IntSumReduce()); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(numberList), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum3, 6); - } - { - int sum = QtConcurrent::blockingMappedReduced(numberLinkedList, &Number::toInt, IntSumReduce()); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - IntSumReduce()); - QCOMPARE(sum3, 6); - } - - // member-member - { - QList list2 = QtConcurrent::blockingMappedReduced(numberList, - &Number::toInt, - &QList::push_back, - OrderedReduce); - QCOMPARE(list2, QList() << 1 << 2 << 3); - - QList list3 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - &QList::push_back, - OrderedReduce); - QCOMPARE(list3, QList() << 1 << 2 << 3); - - QList list4 = QtConcurrent::blockingMappedReduced(QList(numberList), - &Number::toInt, - &QList::push_back, OrderedReduce); - QCOMPARE(list4, QList() << 1 << 2 << 3); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(numberLinkedList, - &Number::toInt, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList2, QLinkedList() << 1 << 2 << 3); - - QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList3, QLinkedList() << 1 << 2 << 3); - - QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - &QLinkedList::append, OrderedReduce); - QCOMPARE(linkedList4, QLinkedList() << 1 << 2 << 3); - } - - // function-member - { - QList list2 = QtConcurrent::blockingMappedReduced(list, - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list2, QList() << 1 << 4 << 9); - - QList list3 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list3, QList() << 1 << 4 << 9); - - QList list4 = QtConcurrent::blockingMappedReduced(QList(list), - intSquare, - &QList::push_back, - OrderedReduce); - QCOMPARE(list, QList() << 1 << 2 << 3); - QCOMPARE(list4, QList() << 1 << 4 << 9); - } - { - QLinkedList linkedList2 = QtConcurrent::blockingMappedReduced(linkedList, - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList2, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList3 = QtConcurrent::blockingMappedReduced(linkedList.constBegin(), - linkedList.constEnd(), - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList3, QLinkedList() << 1 << 4 << 9); - - QLinkedList linkedList4 = QtConcurrent::blockingMappedReduced(QLinkedList(linkedList), - intSquare, - &QLinkedList::append, - OrderedReduce); - QCOMPARE(linkedList, QLinkedList() << 1 << 2 << 3); - QCOMPARE(linkedList4, QLinkedList() << 1 << 4 << 9); - } - - // member-function - { - int sum = QtConcurrent::blockingMappedReduced(numberList, - &Number::toInt, - intSumReduce); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(), - numberList.constEnd(), - &Number::toInt, - intSumReduce); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::blockingMappedReduced(QList(numberList), - &Number::toInt, - intSumReduce); - QCOMPARE(sum3, 6); - } - { - int sum = QtConcurrent::blockingMappedReduced(numberLinkedList, - &Number::toInt, - intSumReduce); - QCOMPARE(sum, 6); - int sum2 = QtConcurrent::blockingMappedReduced(numberLinkedList.constBegin(), - numberLinkedList.constEnd(), - &Number::toInt, - intSumReduce); - QCOMPARE(sum2, 6); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(numberLinkedList), - &Number::toInt, - intSumReduce); - QCOMPARE(sum3, 6); - } - - // linked lists - { - - QLinkedList list; - list << 1 << 2 << 3; - - QLinkedList numberList; - numberList << 1 << 2 << 3; - - int sum = QtConcurrent::blockingMappedReduced(list, IntSquare(), IntSumReduce()); - QCOMPARE(sum, 14); - int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - IntSquare(), - IntSumReduce()); - QCOMPARE(sum2, 14); - - int sum3 = QtConcurrent::blockingMappedReduced(QLinkedList(list), IntSquare(), IntSumReduce()); - QCOMPARE(sum3, 14); - - int sum4 = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce); - QCOMPARE(sum4, 14); - int sum5 = QtConcurrent::blockingMappedReduced(list.constBegin(), - list.constEnd(), - intSquare, - intSumReduce); - QCOMPARE(sum5, 14); - - int sum6 = QtConcurrent::blockingMappedReduced(QLinkedList(list), - intSquare, - intSumReduce); - QCOMPARE(sum6, 14); - } - - // ### the same as above, with an initial result value -} - -int sleeper(int val) -{ - QTest::qSleep(100); - return val; -} - -void tst_QtConcurrentMap::assignResult() -{ - const QList startList = QList() << 0 << 1 << 2; - QList list = QtConcurrent::blockingMapped(startList, sleeper); - QCOMPARE(list.at(0), 0); - QCOMPARE(list.at(1), 1); -} - -int fnConst(const int &i) -{ - return i; -} - -int fn(int &i) -{ - return i; -} - -QString changeTypeConst(const int &) -{ - return QString(); -} - -QString changeType(int &) -{ - return QString(); -} - -int changeTypeQStringListConst(const QStringList &) -{ - return 0; -} - -int changeTypeQStringList(QStringList &) -{ - return 0; -} - -class MemFnTester -{ -public: - MemFnTester() {} - - MemFnTester fn() - { - return MemFnTester(); - } - - MemFnTester fnConst() const - { - return MemFnTester(); - } - - QString changeType() - { - return QString(); - } - - QString changeTypeConst() const - { - return QString(); - } -}; - -Q_DECLARE_METATYPE(QVector); -Q_DECLARE_METATYPE(QList); - -void tst_QtConcurrentMap::functionOverloads() -{ - QList intList; - const QList constIntList; - QList classList; - const QList constMemFnTesterList; - - QtConcurrent::mapped(intList, fnConst); - QtConcurrent::mapped(constIntList, fnConst); - QtConcurrent::mapped(classList, &MemFnTester::fnConst); - QtConcurrent::mapped(constMemFnTesterList, &MemFnTester::fnConst); - - QtConcurrent::blockingMapped >(intList, fnConst); - QtConcurrent::blockingMapped >(constIntList, fnConst); - QtConcurrent::blockingMapped >(classList, &MemFnTester::fnConst); - QtConcurrent::blockingMapped >(constMemFnTesterList, &MemFnTester::fnConst); - - QtConcurrent::blockingMapped >(intList, changeTypeConst); - QtConcurrent::blockingMapped >(constIntList, changeTypeConst); - QtConcurrent::blockingMapped >(classList, &MemFnTester::changeTypeConst); - QtConcurrent::blockingMapped >(constMemFnTesterList, &MemFnTester::changeTypeConst); - - QStringList stringList; - const QStringList constStringList; - // QtConcurrent::map(stringList, changeTypeQStringListConst); - // QtConcurrent::map(intList, changeTypeNonConst); - // QList(QtConcurrent::map(constStringList, changeTypeQStringList)); - // QtConcurrent::map(classList, &MemFnTester::changeType); - // QtConcurrent::map(classList, &MemFnTester::changeTypeConst); - // QtConcurrent::map(constMemFnTesterList, &MemFnTester::changeTypeConst); -} - -QAtomicInt currentInstanceCount; -QAtomicInt peakInstanceCount; -class InstanceCounter -{ -public: - inline InstanceCounter() - { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); } - inline ~InstanceCounter() - { currentInstanceCount.fetchAndAddRelaxed(-1);} - inline InstanceCounter(const InstanceCounter &) - { currentInstanceCount.fetchAndAddRelaxed(1); updatePeak(); } - - void updatePeak() - { - forever { - const int localPeak = peakInstanceCount.load(); - const int localCurrent = currentInstanceCount.load(); - if (localCurrent <= localPeak) - break; - if (peakInstanceCount.testAndSetOrdered(localPeak, localCurrent)) - break; - } - } -}; - -InstanceCounter slowMap(const InstanceCounter &in) -{ - QTest::qSleep(2); - return in; -} - -InstanceCounter fastMap(const InstanceCounter &in) -{ - QTest::qSleep(rand() % 2 + 1); - return in; -} - -void slowReduce(int &result, const InstanceCounter&) -{ - QTest::qSleep(rand() % 4 + 1); - ++result; -} - -void fastReduce(int &result, const InstanceCounter&) -{ - ++result; -} - -void tst_QtConcurrentMap::throttling() -{ - const int itemcount = 100; - const int allowedTemporaries = QThread::idealThreadCount() * 40; - - { - currentInstanceCount.store(0); - peakInstanceCount.store(0); - - QList instances; - for (int i = 0; i < itemcount; ++i) - instances.append(InstanceCounter()); - - QCOMPARE(currentInstanceCount.load(), itemcount); - - int results = QtConcurrent::blockingMappedReduced(instances, slowMap, fastReduce); - QCOMPARE(results, itemcount); - QCOMPARE(currentInstanceCount.load(), itemcount); - QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries); - } - - { - QCOMPARE(currentInstanceCount.load(), 0); - peakInstanceCount.store(0); - - QList instances; - for (int i = 0; i < itemcount; ++i) - instances.append(InstanceCounter()); - - QCOMPARE(currentInstanceCount.load(), itemcount); - int results = QtConcurrent::blockingMappedReduced(instances, fastMap, slowReduce); - - QCOMPARE(results, itemcount); - QCOMPARE(currentInstanceCount.load(), itemcount); - QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries); - } -} - -#ifndef QT_NO_EXCEPTIONS -void throwMapper(int &e) -{ - Q_UNUSED(e); - throw QtConcurrent::Exception(); -} - -void tst_QtConcurrentMap::exceptions() -{ - bool caught = false; - try { - QList list = QList() << 1 << 2 << 3; - QtConcurrent::map(list, throwMapper).waitForFinished(); - } catch (const Exception &) { - caught = true; - } - if (!caught) - QFAIL("did not get exception"); -} -#endif - -int mapper(const int &i) -{ - QTest::qWait(1); - return i; -} - -void tst_QtConcurrentMap::incrementalResults() -{ - const int count = 200; - QList ints; - for (int i=0; i < count; ++i) - ints << i; - - QFuture future = QtConcurrent::mapped(ints, mapper); - - 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); - QCOMPARE(future.results().count(), count); -} - -/* - Test that mapped does not cause deep copies when holding - references to Qt containers. -*/ -void tst_QtConcurrentMap::noDetach() -{ - { - QList l = QList() << 1; - QVERIFY(l.isDetached()); - - QList ll = l; - QVERIFY(l.isDetached() == false); - - QtConcurrent::mapped(l, mapper).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::map(l, multiplyBy2Immutable).waitForFinished(); - QVERIFY(l.isDetached() == true); - QVERIFY(ll.isDetached() == true); - } - { - const QList l = QList() << 1; - QVERIFY(l.isDetached()); - - const QList ll = l; - QVERIFY(l.isDetached() == false); - - QtConcurrent::mapped(l, mapper).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - - QtConcurrent::mappedReduced(l, mapper, intSumReduce).waitForFinished(); - - QVERIFY(l.isDetached() == false); - QVERIFY(ll.isDetached() == false); - } - -} - -#ifndef QT_NO_STL -void tst_QtConcurrentMap::stlContainers() -{ - std::vector vector; - vector.push_back(1); - vector.push_back(2); - - std::vector vector2 = QtConcurrent::blockingMapped >(vector, mapper); - QCOMPARE(vector2.size(), (std::vector::size_type)(2)); - - std::list list; - list.push_back(1); - list.push_back(2); - - std::list list2 = QtConcurrent::blockingMapped >(list, mapper); - QCOMPARE(list2.size(), (std::vector::size_type)(2)); - - QtConcurrent::mapped(list, mapper).waitForFinished(); - - QtConcurrent::blockingMap(list, multiplyBy2Immutable); -} -#endif - -InstanceCounter ic_fn(const InstanceCounter & ic) -{ - return InstanceCounter(ic); -}; - -// Verify that held results are deleted when a future is -// assigned over with operator == -void tst_QtConcurrentMap::qFutureAssignmentLeak() -{ - currentInstanceCount.store(0); - peakInstanceCount.store(0); - QFuture future; - { - QList list; - for (int i=0;i<1000;++i) - list += InstanceCounter(); - future = QtConcurrent::mapped(list, ic_fn); - future.waitForFinished(); - - future = QtConcurrent::mapped(list, ic_fn); - future.waitForFinished(); - - future = QtConcurrent::mapped(list, ic_fn); - future.waitForFinished(); - } - - QCOMPARE(currentInstanceCount.load(), 1000); - future = QFuture(); - QCOMPARE(currentInstanceCount.load(), 0); -} - -inline void increment(int &num) -{ - ++num; -} - -inline int echo(const int &num) -{ - return num; -} - -void add(int &result, const int &sum) -{ - result += sum; -} - -void tst_QtConcurrentMap::stressTest() -{ - const int listSize = 1000; - const int sum = (listSize - 1) * (listSize / 2); - QList list; - - - for (int i = 0; i < listSize; ++i) { - list.append(i); - } - - for (int i =0 ; i < 100; ++i) { - QList result = QtConcurrent::blockingMapped(list, echo); - for (int j = 0; j < listSize; ++j) - QCOMPARE(result.at(j), j); - } - - for (int i = 0 ; i < 100; ++i) { - int result = QtConcurrent::blockingMappedReduced(list, echo, add); - QCOMPARE(result, sum); - } - - for (int i = 0 ; i < 100; ++i) { - QtConcurrent::map(list, increment).waitForFinished(); - for (int j = 0; j < listSize; ++j) - QCOMPARE(list.at(j), i + j + 1); - } -} - -#endif - -QTEST_MAIN(tst_QtConcurrentMap) -#include "tst_qtconcurrentmap.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro b/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro deleted file mode 100644 index e93fc587a7..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentresultstore -QT = core-private testlib -SOURCES = tst_qtconcurrentresultstore.cpp -DEFINES += QT_STRICT_ITERATORS diff --git a/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp b/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp deleted file mode 100644 index 236d0b62e3..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include - -using namespace QtConcurrent; - -class tst_QtConcurrentResultStore : public QObject -{ - Q_OBJECT -public slots: - void init(); -private slots: - void construction(); - void iterators(); - void addResult(); - void addResults(); - void resultIndex(); - void resultAt(); - void contains(); - void filterMode(); - void addCanceledResult(); - void count(); -private: - int int0; - int int1; - int int2; - QVector vec0; - QVector vec1; -}; - -void tst_QtConcurrentResultStore::init() -{ - int0 = 0; - int1 = 1; - int2 = 2; - vec0 = QVector() << 2 << 3; - vec1 = QVector() << 4 << 5; -} - -void tst_QtConcurrentResultStore::construction() -{ - ResultStore store; - QCOMPARE(store.count(), 0); -} - -void tst_QtConcurrentResultStore::iterators() -{ - { - ResultStore store; - QVERIFY(store.begin() == store.end()); - QVERIFY(store.resultAt(0) == store.end()); - QVERIFY(store.resultAt(1) == store.end()); - } - { - ResultStoreBase storebase; - storebase.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since - storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. - ResultIteratorBase it = storebase.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == storebase.begin()); - QVERIFY(it != storebase.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != storebase.begin()); - QVERIFY(it != storebase.end()); - - ++it; - QVERIFY(it != storebase.begin()); - QVERIFY(it == storebase.end()); - } -} - -void tst_QtConcurrentResultStore::addResult() -{ - { - // test addResult return value - ResultStore store; - store.setFilterMode(true); - - QCOMPARE(store.addResult(0, &int0), 0); - QCOMPARE(store.count(), 1); // result 0 becomes available - QCOMPARE(store.contains(0), true); - - QCOMPARE(store.addResult(2, &int0), 2); - QCOMPARE(store.count(), 1); - QCOMPARE(store.contains(2), false); - - QCOMPARE(store.addCanceledResult(1), 1); - QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - - QCOMPARE(store.addResult(3, &int0), 3); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(2), true); - - QCOMPARE(store.addResult(6, &int0), 6); - QCOMPARE(store.count(), 3); - QCOMPARE(store.addResult(7, &int0), 7); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(3), false); - - QCOMPARE(store.addCanceledResult(4), 4); - QCOMPARE(store.addCanceledResult(5), 5); - QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available - - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), true); - - QCOMPARE(store.addResult(8, &int0), 8); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.count(), 6); - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } -} - -void tst_QtConcurrentResultStore::addResults() -{ - - ResultStoreBase store; - store.addResults(-1, &vec0, 2, 2); - store.addResults(-1, &vec1, 2, 2); - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - - ++it; - QCOMPARE(it.resultIndex(), 3); - - ++it; - QVERIFY(it == store.end()); -} - -void tst_QtConcurrentResultStore::resultIndex() -{ - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(-1, &int1); - - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - QVERIFY(it != store.end()); - ++it; - QCOMPARE(it.resultIndex(), 3); - QVERIFY(it != store.end()); - ++it; - QVERIFY(it == store.end()); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(3).value(), int1); -} - -void tst_QtConcurrentResultStore::resultAt() -{ - { - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(200, &int1); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(200).value(), int1); - } - { - ResultStore store; - store.addResult(1, &int1); - store.addResult(0, &int0); - store.addResult(-1, &int2); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), int1); - QCOMPARE(store.resultAt(2).value(), int2); - } -} - -void tst_QtConcurrentResultStore::contains() -{ - { - ResultStore store; - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(INT_MAX), false); - store.addResult(1, &int1); - QVERIFY(store.contains(int1)); - store.addResult(0, &int0); - QVERIFY(store.contains(int0)); - store.addResult(-1, &int2); - QVERIFY(store.contains(int2)); - } - { - ResultStore store; - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), false); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - - store.addCanceledResult(0); - store.addCanceledResult(2); - store.addCanceledResults(4, 2); - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } - { - ResultStore store; - store.setFilterMode(true); - store.addCanceledResult(0); - QCOMPARE(store.contains(0), false); - - store.addResult(1, &int0); - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), false); - } -} - -void tst_QtConcurrentResultStore::filterMode() -{ - // Test filter mode, where "gaps" in the result array aren't allowed. - ResultStore store; - QCOMPARE(store.filterMode(), false); - store.setFilterMode(true); - QVERIFY(store.filterMode()); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int2); // add result at index 2 - QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. - - store.addResult(1, &int1); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); // 2 should be visible now. - - store.addResult(4, &int0); - store.addResult(5, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(7), false); - - store.addResult(3, &int0); // adding 3 makes 4 and 5 visible - QCOMPARE(store.contains(4), true); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.contains(7), false); - - store.addResult(6, &int0); // adding 6 makes 7 visible - - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - QCOMPARE(store.contains(8), false); -} - -void tst_QtConcurrentResultStore::addCanceledResult() -{ - // test canceled results - ResultStore store; - store.setFilterMode(true); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int0); - QCOMPARE(store.contains(2), false); - - store.addCanceledResult(1); // report no result at 1 - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 - QCOMPARE(store.contains(2), false); - - store.addResult(3, &int0); - QCOMPARE(store.contains(2), true); //3 gets renamed to 2 - - store.addResult(6, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(3), false); - - store.addCanceledResult(4); - store.addCanceledResult(5); - - QCOMPARE(store.contains(3), true); //6 gets renamed to 3 - QCOMPARE(store.contains(4), true); //7 gets renamed to 4 - - store.addResult(8, &int0); - QCOMPARE(store.contains(5), true); //8 gets renamed to 4 - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); -} - -void tst_QtConcurrentResultStore::count() -{ - { - // test resultCount in non-filtered mode. It should always be possible - // to iterate through the results 0 to resultCount. - ResultStore store; - store.addResult(0, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(2, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResult(2, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 4); - } - { - ResultStore store; - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addResult(2, &int0); - QCOMPARE(store.count(), 5); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addCanceledResult(2); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 - - store.addResult(5, &int0); - QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 - } -} - -QTEST_MAIN(tst_QtConcurrentResultStore) -#include "tst_qtconcurrentresultstore.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore deleted file mode 100644 index d7a8334ec4..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentrun/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtconcurrentrun diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro b/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro deleted file mode 100644 index d4f130fecd..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentrun/qtconcurrentrun.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentrun -QT = core testlib -SOURCES = tst_qtconcurrentrun.cpp diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp deleted file mode 100644 index 86e3433c12..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include - -using namespace QtConcurrent; - -class tst_QtConcurrentRun: public QObject -{ - Q_OBJECT -private slots: - void runLightFunction(); - void runHeavyFunction(); - void returnValue(); - void functionObject(); - void memberFunctions(); - void implicitConvertibleTypes(); - void runWaitLoop(); - void recursive(); -#ifndef QT_NO_EXCEPTIONS - void exceptions(); -#endif - void functor(); - void lambda(); -}; - -void light() -{ - qDebug("in function"); - qDebug("done function"); -} - -void heavy() -{ - qDebug("in function"); - QString str; - for (int i = 0; i < 1000000; ++i) - str.append("a"); - qDebug("done function"); -} - - -void tst_QtConcurrentRun::runLightFunction() -{ - qDebug("starting function"); - QFuture future = run(light); - qDebug("waiting"); - future.waitForFinished(); - qDebug("done"); -} - -void tst_QtConcurrentRun::runHeavyFunction() -{ - qDebug("starting function"); - QFuture future = run(heavy); - qDebug("waiting"); - future.waitForFinished(); - qDebug("done"); -} - -int returnInt0() -{ - return 10; -} - -int returnInt1(int i) -{ - return i; -} - -class A -{ -public: - int member0() { return 10; } - int member1(int in) { return in; } - - typedef int result_type; - int operator()() { return 10; } - int operator()(int in) { return in; } -}; - -class AConst -{ -public: - int member0() const { return 10; } - int member1(int in) const { return in; } - - typedef int result_type; - int operator()() const { return 10; } - int operator()(int in) const { return in; } -}; - -void tst_QtConcurrentRun::returnValue() -{ - QFuture f; - - f = run(returnInt0); - QCOMPARE(f.result(), 10); - - A a; - f = run(&a, &A::member0); - QCOMPARE(f.result(), 10); - - f = run(&a, &A::member1, 20); - QCOMPARE(f.result(), 20); - - f = run(a, &A::member0); - QCOMPARE(f.result(), 10); - - f = run(a, &A::member1, 20); - QCOMPARE(f.result(), 20); - - f = run(a); - QCOMPARE(f.result(), 10); - - f = run(&a); - QCOMPARE(f.result(), 10); - - f = run(a, 20); - QCOMPARE(f.result(), 20); - - f = run(&a, 20); - QCOMPARE(f.result(), 20); - - const AConst aConst = AConst(); - f = run(&aConst, &AConst::member0); - QCOMPARE(f.result(), 10); - - f = run(&aConst, &AConst::member1, 20); - QCOMPARE(f.result(), 20); - - f = run(aConst, &AConst::member0); - QCOMPARE(f.result(), 10); - - f = run(aConst, &AConst::member1, 20); - QCOMPARE(f.result(), 20); - - f = run(aConst); - QCOMPARE(f.result(), 10); - - f = run(&aConst); - QCOMPARE(f.result(), 10); - - f = run(aConst, 20); - QCOMPARE(f.result(), 20); - - f = run(&aConst, 20); - QCOMPARE(f.result(), 20); -} - -struct TestClass -{ - void foo() { } - typedef void result_type; - void operator()() { } - void operator()(int) { } - void fooInt(int){ }; -}; - -struct TestConstClass -{ - void foo() const { } - typedef void result_type; - void operator()() const { } - void operator()(int) const { } - void fooInt(int) const { }; -}; - -void tst_QtConcurrentRun::functionObject() -{ - QFuture f; - TestClass c; - - f = run(c); - f = run(&c); - f = run(c, 10); - f = run(&c, 10); - - const TestConstClass cc = TestConstClass(); - f = run(cc); - f = run(&cc); - f = run(cc, 10); - f = run(&cc, 10); -} - - -void tst_QtConcurrentRun::memberFunctions() -{ - TestClass c; - - run(c, &TestClass::foo).waitForFinished(); - run(&c, &TestClass::foo).waitForFinished(); - run(c, &TestClass::fooInt, 10).waitForFinished(); - run(&c, &TestClass::fooInt, 10).waitForFinished(); - - const TestConstClass cc = TestConstClass(); - run(cc, &TestConstClass::foo).waitForFinished(); - run(&cc, &TestConstClass::foo).waitForFinished(); - run(cc, &TestConstClass::fooInt, 10).waitForFinished(); - run(&cc, &TestConstClass::fooInt, 10).waitForFinished(); -} - - -void doubleFunction(double) -{ - -} - -void stringConstRefFunction(const QString &) -{ - -} - -void stringRefFunction(QString &) -{ - -} - -void stringFunction(QString) -{ - -} - -void stringIntFunction(QString) -{ - -} - - -void tst_QtConcurrentRun::implicitConvertibleTypes() -{ - double d; - run(doubleFunction, d).waitForFinished(); - int i; - run(doubleFunction, d).waitForFinished(); - run(doubleFunction, i).waitForFinished(); - run(doubleFunction, 10).waitForFinished(); - run(stringFunction, QLatin1String("Foo")).waitForFinished(); - run(stringConstRefFunction, QLatin1String("Foo")).waitForFinished(); - QString string; - run(stringRefFunction, string).waitForFinished(); -} - -void fn() { } - -void tst_QtConcurrentRun::runWaitLoop() -{ - for (int i = 0; i < 1000; ++i) - run(fn).waitForFinished(); -} - -QAtomicInt count; - -void recursiveRun(int level) -{ - count.ref(); - if (--level > 0) { - QFuture f1 = run(recursiveRun, level); - QFuture f2 = run(recursiveRun, level); - f1.waitForFinished(); - f2.waitForFinished(); - } -} - -int recursiveResult(int level) -{ - count.ref(); - if (--level > 0) { - QFuture f1 = run(recursiveResult, level); - QFuture f2 = run(recursiveResult, level); - return f1.result() + f2.result(); - } - return 1; -} - -void tst_QtConcurrentRun::recursive() -{ - int levels = 15; - - for (int i = 0; i < QThread::idealThreadCount(); ++i) { - count.store(0); - QThreadPool::globalInstance()->setMaxThreadCount(i); - recursiveRun(levels); - QCOMPARE(count.load(), (int)pow(2.0, levels) - 1); - } - - for (int i = 0; i < QThread::idealThreadCount(); ++i) { - count.store(0); - QThreadPool::globalInstance()->setMaxThreadCount(i); - recursiveResult(levels); - QCOMPARE(count.load(), (int)pow(2.0, levels) - 1); - } -} - -int e; -void vfn0() -{ - ++e; -} - -int fn0() -{ - return 1; -} - -void vfn1(double) -{ - ++e; -} - -int fn1(int) -{ - return 1; -} - -void vfn2(double, int *) -{ - ++e; -} - -int fn2(double, int *) -{ - return 1; -} - - -#ifndef QT_NO_EXCEPTIONS -void throwFunction() -{ - throw QtConcurrent::Exception(); -} - -int throwFunctionReturn() -{ - throw QtConcurrent::Exception(); - return 0; -} - -void tst_QtConcurrentRun::exceptions() -{ - bool caught = false; - try { - QtConcurrent::run(throwFunction).waitForFinished(); - } catch (Exception &e) { - caught = true; - } - if (!caught) - QFAIL("did not get exception"); - - caught = false; - try { - QtConcurrent::run(throwFunctionReturn).waitForFinished(); - } catch (Exception &e) { - caught = true; - } - if (!caught) - QFAIL("did not get exception"); -} -#endif - -struct Functor { - int operator()() { return 42; } - double operator()(double a, double b) { return a/b; } - int operator()(int a, int b) { return a/b; } - void operator()(int) { } - void operator()(int, int, int) { } - void operator()(int, int, int, int) { } - void operator()(int, int, int, int, int) { } - void operator()(int, int, int, int, int, int) { } -}; - -// This tests functor without result_type; decltype need to be supported by the compiler. -void tst_QtConcurrentRun::functor() -{ -#ifndef Q_COMPILER_DECLTYPE - QSKIP("Compiler does not support decltype"); -#else - Functor f; - { - QFuture fut = QtConcurrent::run(f); - QCOMPARE(fut.result(), 42); - } - { - QFuture fut = QtConcurrent::run(f, 8.5, 1.8); - QCOMPARE(fut.result(), (8.5/1.8)); - } - { - QFuture fut = QtConcurrent::run(f, 19, 3); - QCOMPARE(fut.result(), int(19/3)); - } - { - QtConcurrent::run(f, 1).waitForFinished(); - QtConcurrent::run(f, 1,2).waitForFinished(); - QtConcurrent::run(f, 1,2,3).waitForFinished(); - QtConcurrent::run(f, 1,2,3,4).waitForFinished(); - QtConcurrent::run(f, 1,2,3,4,5).waitForFinished(); - } -#endif -} - -void tst_QtConcurrentRun::lambda() -{ -#ifndef Q_COMPILER_LAMBDA - QSKIP("Compiler does not support lambda"); -#else - QCOMPARE(QtConcurrent::run([](){ return 45; }).result(), 45); - QCOMPARE(QtConcurrent::run([](int a){ return a+15; }, 12).result(), 12+15); - QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15)); - QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5); - -#ifdef Q_COMPILER_INITIALIZER_LISTS - { - QString str { "Hello World Foo" }; - QFuture f1 = QtConcurrent::run([&](){ return str.split(' '); }); - auto r = f1.result(); - QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); - } -#endif -#endif -} - -QTEST_MAIN(tst_QtConcurrentRun) -#include "tst_qtconcurrentrun.moc" diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore deleted file mode 100644 index a2e2896246..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qtconcurrentthreadengine diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro deleted file mode 100644 index 536ccc3ea5..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/qtconcurrentthreadengine.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentthreadengine -QT = core testlib -SOURCES = tst_qtconcurrentthreadengine.cpp diff --git a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp deleted file mode 100644 index 9722887c7d..0000000000 --- a/tests/auto/corelib/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include - -using namespace QtConcurrent; - -class tst_QtConcurrentThreadEngine: public QObject -{ - Q_OBJECT -private slots: - void runDirectly(); - void result(); - void runThroughStarter(); - void cancel(); - void throttle(); - void threadCount(); - void multipleResults(); - void stresstest(); - void cancelQueuedSlowUser(); -#ifndef QT_NO_EXCEPTIONS - void exceptions(); -#endif -}; - - -class PrintUser : public ThreadEngine -{ -public: - ThreadFunctionResult threadFunction() - { - QTest::qSleep(50); - QTest::qSleep(100); - return ThreadFinished; - } -}; - -void tst_QtConcurrentThreadEngine::runDirectly() -{ - { - PrintUser engine; - engine.startSingleThreaded(); - engine.startBlocking(); - } - { - PrintUser *engine = new PrintUser(); - QFuture f = engine->startAsynchronously(); - f.waitForFinished(); - } -} - -class StringResultUser : public ThreadEngine -{ -public: - typedef QString ResultType; - StringResultUser() - : done(false) { } - - bool shouldStartThread() - { - return !done; - } - - ThreadFunctionResult threadFunction() - { - done = true; - return ThreadFinished; - } - - QString *result() - { - foo = "Foo"; - return &foo; - } - QString foo; - bool done; -}; - -void tst_QtConcurrentThreadEngine::result() -{ - StringResultUser engine; - QCOMPARE(*engine.startBlocking(), QString("Foo")); -} - -class VoidResultUser : public ThreadEngine -{ -public: - bool shouldStartThread() - { - return !done; - } - - ThreadFunctionResult threadFunction() - { - done = true; - return ThreadFinished; - } - - void *result() - { - return 0; - } - bool done; -}; - -void tst_QtConcurrentThreadEngine::runThroughStarter() -{ - { - ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); - QFuture f = starter.startAsynchronously(); - QCOMPARE(f.result(), QString("Foo")); - } - - { - ThreadEngineStarter starter = startThreadEngine(new StringResultUser()); - QString str = starter.startBlocking(); - QCOMPARE(str, QString("Foo")); - } -} - -class CancelUser : public ThreadEngine -{ -public: - void *result() - { - return 0; - } - - ThreadFunctionResult threadFunction() - { - while (this->isCanceled() == false) - { - QTest::qSleep(10); - } - return ThreadFinished; - } -}; - -void tst_QtConcurrentThreadEngine::cancel() -{ - { - CancelUser *engine = new CancelUser(); - QFuture f = engine->startAsynchronously(); - f.cancel(); - f.waitForFinished(); - } - { - CancelUser *engine = new CancelUser(); - QFuture f = engine->startAsynchronously(); - QTest::qSleep(10); - f.cancel(); - f.waitForFinished(); - } -} - -QAtomicInt count; -class ThrottleAlwaysUser : public ThreadEngine -{ -public: - ThrottleAlwaysUser() - { - count.store(initialCount = 100); - finishing = false; - } - - bool shouldStartThread() - { - return !finishing; - } - - ThreadFunctionResult threadFunction() - { - forever { - const int local = count.load(); - if (local == 0) { - finishing = true; - return ThreadFinished; - } - - if (count.testAndSetOrdered(local, local - 1)) - break; - } - return ThrottleThread; - } - - bool finishing; - int initialCount; -}; - -// Test that a user task with a thread function that always -// want to be throttled still completes. The thread engine -// should make keep one thread running at all times. -void tst_QtConcurrentThreadEngine::throttle() -{ - const int repeats = 10; - for (int i = 0; i < repeats; ++i) { - QFuture f = (new ThrottleAlwaysUser())->startAsynchronously(); - f.waitForFinished(); - QCOMPARE(count.load(), 0); - } - - for (int i = 0; i < repeats; ++i) { - ThrottleAlwaysUser t; - t.startBlocking(); - QCOMPARE(count.load(), 0); - } -} - -QSet threads; -QMutex mutex; -class ThreadCountUser : public ThreadEngine -{ -public: - ThreadCountUser(bool finishImmediately = false) - { - threads.clear(); - finishing = finishImmediately; - } - - bool shouldStartThread() - { - return !finishing; - } - - ThreadFunctionResult threadFunction() - { - { - QMutexLocker lock(&mutex); - threads.insert(QThread::currentThread()); - } - QTest::qSleep(10); - finishing = true; - return ThreadFinished; - } - - bool finishing; -}; - -void tst_QtConcurrentThreadEngine::threadCount() -{ - QSKIP("QTBUG-23333: This test is unstable"); - - const int repeats = 10; - for (int i = 0; i < repeats; ++i) { - ThreadCountUser t; - t.startBlocking(); - QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount() + 1); // +1 for the main thread. - - (new ThreadCountUser())->startAsynchronously().waitForFinished(); - QCOMPARE(threads.count(), QThreadPool::globalInstance()->maxThreadCount()); - } - - // Set the finish flag immediately, this should give us one thread only. - for (int i = 0; i < repeats; ++i) { - ThreadCountUser t(true /*finishImmediately*/); - t.startBlocking(); - QCOMPARE(threads.count(), 1); - - (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished(); - QCOMPARE(threads.count(), 1); - } -} - -class MultipleResultsUser : public ThreadEngine -{ -public: - bool shouldStartThread() - { - return false; - } - - ThreadFunctionResult threadFunction() - { - for (int i = 0; i < 10; ++i) - this->reportResult(&i); - return ThreadFinished; - } -}; - - -void tst_QtConcurrentThreadEngine::multipleResults() -{ - MultipleResultsUser *engine = new MultipleResultsUser(); - QFuture f = engine->startAsynchronously(); - QCOMPARE(f.results().count() , 10); - QCOMPARE(f.resultAt(0), 0); - QCOMPARE(f.resultAt(5), 5); - QCOMPARE(f.resultAt(9), 9); - f.waitForFinished(); -} - - -class NoThreadsUser : public ThreadEngine -{ -public: - bool shouldStartThread() - { - return false; - } - - ThreadFunctionResult threadFunction() - { - return ThreadFinished; - } - - void *result() - { - return 0; - } -}; - -void tst_QtConcurrentThreadEngine::stresstest() -{ - const int times = 20000; - - for (int i = 0; i < times; ++i) { - VoidResultUser *engine = new VoidResultUser(); - engine->startAsynchronously().waitForFinished(); - } - - for (int i = 0; i < times; ++i) { - VoidResultUser *engine = new VoidResultUser(); - engine->startAsynchronously(); - } - - for (int i = 0; i < times; ++i) { - VoidResultUser *engine = new VoidResultUser(); - engine->startAsynchronously().waitForFinished(); - } -} - -const int sleepTime = 20; -class SlowUser : public ThreadEngine -{ -public: - bool shouldStartThread() { return false; } - ThreadFunctionResult threadFunction() { QTest::qSleep(sleepTime); return ThreadFinished; } -}; - -void tst_QtConcurrentThreadEngine::cancelQueuedSlowUser() -{ - const int times = 100; - - QTime t; - t.start(); - - { - QList > futures; - for (int i = 0; i < times; ++i) { - SlowUser *engine = new SlowUser(); - futures.append(engine->startAsynchronously()); - } - - foreach(QFuture future, futures) - future.cancel(); - } - - QVERIFY(t.elapsed() < (sleepTime * times) / 2); -} - -#ifndef QT_NO_EXCEPTIONS - -class QtConcurrentExceptionThrower : public ThreadEngine -{ -public: - QtConcurrentExceptionThrower(QThread *blockThread = 0) - { - this->blockThread = blockThread; - } - - ThreadFunctionResult threadFunction() - { - QTest::qSleep(50); - throw QtConcurrent::Exception(); - return ThreadFinished; - } - QThread *blockThread; -}; - -class UnrelatedExceptionThrower : public ThreadEngine -{ -public: - UnrelatedExceptionThrower(QThread *blockThread = 0) - { - this->blockThread = blockThread; - } - - ThreadFunctionResult threadFunction() - { - QTest::qSleep(50); - throw int(); - return ThreadFinished; - } - QThread *blockThread; -}; - -void tst_QtConcurrentThreadEngine::exceptions() -{ - // Asynchronous mode: - { - bool caught = false; - try { - QtConcurrentExceptionThrower *e = new QtConcurrentExceptionThrower(); - QFuture f = e->startAsynchronously(); - f.waitForFinished(); - } catch (const Exception &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // Blocking mode: - // test throwing the exception from a worker thread. - { - bool caught = false; - try { - QtConcurrentExceptionThrower e(QThread::currentThread()); - e.startBlocking(); - } catch (const Exception &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // test throwing the exception from the main thread (different code path) - { - bool caught = false; - try { - QtConcurrentExceptionThrower e(0); - e.startBlocking(); - } catch (const Exception &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // Asynchronous mode: - { - bool caught = false; - try { - UnrelatedExceptionThrower *e = new UnrelatedExceptionThrower(); - QFuture f = e->startAsynchronously(); - f.waitForFinished(); - } catch (const QtConcurrent::UnhandledException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // Blocking mode: - // test throwing the exception from a worker thread. - { - bool caught = false; - try { - UnrelatedExceptionThrower e(QThread::currentThread()); - e.startBlocking(); - } catch (const QtConcurrent::UnhandledException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // test throwing the exception from the main thread (different code path) - { - bool caught = false; - try { - UnrelatedExceptionThrower e(0); - e.startBlocking(); - } catch (const QtConcurrent::UnhandledException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } -} - -#endif - -QTEST_MAIN(tst_QtConcurrentThreadEngine) - -#include "tst_qtconcurrentthreadengine.moc" diff --git a/tests/auto/corelib/concurrent/qthreadpool/.gitignore b/tests/auto/corelib/concurrent/qthreadpool/.gitignore deleted file mode 100644 index 16105821a2..0000000000 --- a/tests/auto/corelib/concurrent/qthreadpool/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qthreadpool diff --git a/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro b/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro deleted file mode 100644 index 4d81218f24..0000000000 --- a/tests/auto/corelib/concurrent/qthreadpool/qthreadpool.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qthreadpool -QT = core testlib -SOURCES = tst_qthreadpool.cpp diff --git a/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp deleted file mode 100644 index 1dd0410f41..0000000000 --- a/tests/auto/corelib/concurrent/qthreadpool/tst_qthreadpool.cpp +++ /dev/null @@ -1,849 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include -#include -#include -#include - -typedef void (*FunctionPointer)(); - -class FunctionPointerTask : public QRunnable -{ -public: - FunctionPointerTask(FunctionPointer function) - :function(function) {} - void run() { function(); } -private: - FunctionPointer function; -}; - -QRunnable *createTask(FunctionPointer pointer) -{ - return new FunctionPointerTask(pointer); -} - -class tst_QThreadPool : public QObject -{ - Q_OBJECT -private slots: - void runFunction(); - void createThreadRunFunction(); - void runMultiple(); - void waitcomplete(); - void runTask(); - void singleton(); - void destruction(); - void threadRecycling(); - void expiryTimeout(); -#ifndef QT_NO_EXCEPTIONS - void exceptions(); -#endif - void setMaxThreadCount_data(); - void setMaxThreadCount(); - void setMaxThreadCountStartsAndStopsThreads(); - void reserveThread_data(); - void reserveThread(); - void releaseThread_data(); - void releaseThread(); - void start(); - void tryStart(); - void tryStartPeakThreadCount(); - void tryStartCount(); - void waitForDone(); - void waitForDoneTimeout(); - void destroyingWaitsForTasksToFinish(); - void stressTest(); -}; - -int testFunctionCount; - -void sleepTestFunction() -{ - QTest::qSleep(1000); - ++testFunctionCount; -} - -void emptyFunct() -{ - -} - -void noSleepTestFunction() -{ - ++testFunctionCount; -} - -void sleepTestFunctionMutex() -{ - static QMutex testMutex; - QTest::qSleep(1000); - testMutex.lock(); - ++testFunctionCount; - testMutex.unlock(); -} - -void noSleepTestFunctionMutex() -{ - static QMutex testMutex; - testMutex.lock(); - ++testFunctionCount; - testMutex.unlock(); -} - -void tst_QThreadPool::runFunction() -{ - { - QThreadPool manager; - testFunctionCount = 0; - manager.start(createTask(noSleepTestFunction)); - } - QCOMPARE(testFunctionCount, 1); -} - -void tst_QThreadPool::createThreadRunFunction() -{ - { - QThreadPool manager; - testFunctionCount = 0; - manager.start(createTask(noSleepTestFunction)); - } - - QCOMPARE(testFunctionCount, 1); -} - -void tst_QThreadPool::runMultiple() -{ - const int runs = 10; - - { - QThreadPool manager; - testFunctionCount = 0; - for (int i = 0; i < runs; ++i) { - manager.start(createTask(sleepTestFunctionMutex)); - } - } - QCOMPARE(testFunctionCount, runs); - - { - QThreadPool manager; - testFunctionCount = 0; - for (int i = 0; i < runs; ++i) { - manager.start(createTask(noSleepTestFunctionMutex)); - } - } - QCOMPARE(testFunctionCount, runs); - - { - QThreadPool manager; - for (int i = 0; i < 500; ++i) - manager.start(createTask(emptyFunct)); - } -} - -void tst_QThreadPool::waitcomplete() -{ - testFunctionCount = 0; - const int runs = 500; - for (int i = 0; i < 500; ++i) { - QThreadPool pool; - pool.start(createTask(noSleepTestFunction)); - } - QCOMPARE(testFunctionCount, runs); -} - -volatile bool ran; -class TestTask : public QRunnable -{ -public: - void run() - { - ran = true; - } -}; - -void tst_QThreadPool::runTask() -{ - QThreadPool manager; - ran = false; - manager.start(new TestTask()); - QTRY_VERIFY(ran); -} - -/* - Test running via QThreadPool::globalInstance() -*/ -void tst_QThreadPool::singleton() -{ - ran = false; - QThreadPool::globalInstance()->start(new TestTask()); - QTRY_VERIFY(ran); -} - -int *value = 0; -class IntAccessor : public QRunnable -{ -public: - void run() - { - for (int i = 0; i < 100; ++i) { - ++(*value); - QTest::qSleep(1); - } - } -}; - -/* - Test that the ThreadManager destructor waits until - all threads have completed. -*/ -void tst_QThreadPool::destruction() -{ - value = new int; - QThreadPool *threadManager = new QThreadPool(); - threadManager->start(new IntAccessor()); - threadManager->start(new IntAccessor()); - delete threadManager; - delete value; - value = 0; -} - -QSemaphore threadRecyclingSemaphore; -QThread *recycledThread = 0; - -class ThreadRecorderTask : public QRunnable -{ -public: - void run() - { - recycledThread = QThread::currentThread(); - threadRecyclingSemaphore.release(); - } -}; - -/* - Test that the thread pool really reuses threads. -*/ -void tst_QThreadPool::threadRecycling() -{ - QThreadPool threadPool; - - threadPool.start(new ThreadRecorderTask()); - threadRecyclingSemaphore.acquire(); - QThread *thread1 = recycledThread; - - QTest::qSleep(100); - - threadPool.start(new ThreadRecorderTask()); - threadRecyclingSemaphore.acquire(); - QThread *thread2 = recycledThread; - QCOMPARE(thread1, thread2); - - QTest::qSleep(100); - - threadPool.start(new ThreadRecorderTask()); - threadRecyclingSemaphore.acquire(); - QThread *thread3 = recycledThread; - QCOMPARE(thread2, thread3); -} - -class ExpiryTimeoutTask : public QRunnable -{ -public: - QThread *thread; - int runCount; - QSemaphore semaphore; - - ExpiryTimeoutTask() - : thread(0), runCount(0) - { - setAutoDelete(false); - } - - void run() - { - thread = QThread::currentThread(); - ++runCount; - semaphore.release(); - } -}; - -void tst_QThreadPool::expiryTimeout() -{ - ExpiryTimeoutTask task; - - QThreadPool threadPool; - threadPool.setMaxThreadCount(1); - - int expiryTimeout = threadPool.expiryTimeout(); - threadPool.setExpiryTimeout(1000); - QCOMPARE(threadPool.expiryTimeout(), 1000); - - // run the task - threadPool.start(&task); - QVERIFY(task.semaphore.tryAcquire(1, 10000)); - QCOMPARE(task.runCount, 1); - QVERIFY(!task.thread->wait(100)); - // thread should expire - QThread *firstThread = task.thread; - QVERIFY(task.thread->wait(10000)); - - // run task again, thread should be restarted - threadPool.start(&task); - QVERIFY(task.semaphore.tryAcquire(1, 10000)); - QCOMPARE(task.runCount, 2); - QVERIFY(!task.thread->wait(100)); - // thread should expire again - QVERIFY(task.thread->wait(10000)); - - // thread pool should have reused the expired thread (instead of - // starting a new one) - QCOMPARE(firstThread, task.thread); - - threadPool.setExpiryTimeout(expiryTimeout); - QCOMPARE(threadPool.expiryTimeout(), expiryTimeout); -} - -#ifndef QT_NO_EXCEPTIONS -class ExceptionTask : public QRunnable -{ -public: - void run() - { - throw new int; - } -}; - -void tst_QThreadPool::exceptions() -{ - ExceptionTask task; - { - QThreadPool threadPool; -// Uncomment this for a nice crash. -// threadPool.start(&task); - } -} -#endif - -void tst_QThreadPool::setMaxThreadCount_data() -{ - QTest::addColumn("limit"); - - QTest::newRow("") << 1; - QTest::newRow("") << -1; - QTest::newRow("") << 2; - QTest::newRow("") << -2; - QTest::newRow("") << 4; - QTest::newRow("") << -4; - QTest::newRow("") << 0; - QTest::newRow("") << 12345; - QTest::newRow("") << -6789; - QTest::newRow("") << 42; - QTest::newRow("") << -666; -} - -void tst_QThreadPool::setMaxThreadCount() -{ - QFETCH(int, limit); - QThreadPool *threadPool = QThreadPool::globalInstance(); - int savedLimit = threadPool->maxThreadCount(); - - // maxThreadCount() should always return the previous argument to - // setMaxThreadCount(), regardless of input - threadPool->setMaxThreadCount(limit); - QCOMPARE(threadPool->maxThreadCount(), limit); - - // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount() - threadPool->setMaxThreadCount(savedLimit); - QCOMPARE(threadPool->maxThreadCount(), savedLimit); - - // setting the limit on children should have no effect on the parent - { - QThreadPool threadPool2(threadPool); - savedLimit = threadPool2.maxThreadCount(); - - // maxThreadCount() should always return the previous argument to - // setMaxThreadCount(), regardless of input - threadPool2.setMaxThreadCount(limit); - QCOMPARE(threadPool2.maxThreadCount(), limit); - - // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount() - threadPool2.setMaxThreadCount(savedLimit); - QCOMPARE(threadPool2.maxThreadCount(), savedLimit); - } -} - -void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads() -{ - class WaitingTask : public QRunnable - { - public: - QSemaphore waitForStarted, waitToFinish; - - WaitingTask() { setAutoDelete(false); } - - void run() - { - waitForStarted.release(); - waitToFinish.acquire(); - } - }; - - QThreadPool threadPool; - threadPool.setMaxThreadCount(1); - - WaitingTask *task = new WaitingTask; - threadPool.start(task); - QVERIFY(task->waitForStarted.tryAcquire(1, 1000)); - - // thread limit is 1, cannot start more tasks - threadPool.start(task); - QVERIFY(!task->waitForStarted.tryAcquire(1, 1000)); - - // increasing the limit by 1 should start the task immediately - threadPool.setMaxThreadCount(2); - QVERIFY(task->waitForStarted.tryAcquire(1, 1000)); - - // ... but we still cannot start more tasks - threadPool.start(task); - QVERIFY(!task->waitForStarted.tryAcquire(1, 1000)); - - // increasing the limit should be able to start more than one at a time - threadPool.start(task); - threadPool.setMaxThreadCount(4); - QVERIFY(task->waitForStarted.tryAcquire(2, 1000)); - - // ... but we still cannot start more tasks - threadPool.start(task); - threadPool.start(task); - QVERIFY(!task->waitForStarted.tryAcquire(2, 1000)); - - // decreasing the thread limit should cause the active thread count to go down - threadPool.setMaxThreadCount(2); - QCOMPARE(threadPool.activeThreadCount(), 4); - task->waitToFinish.release(2); - QTest::qWait(1000); - QCOMPARE(threadPool.activeThreadCount(), 2); - - // ... and we still cannot start more tasks - threadPool.start(task); - threadPool.start(task); - QVERIFY(!task->waitForStarted.tryAcquire(2, 1000)); - - // start all remaining tasks - threadPool.start(task); - threadPool.start(task); - threadPool.start(task); - threadPool.start(task); - threadPool.setMaxThreadCount(8); - QVERIFY(task->waitForStarted.tryAcquire(6, 1000)); - - task->waitToFinish.release(10); -// delete task; -} - -void tst_QThreadPool::reserveThread_data() -{ - setMaxThreadCount_data(); -} - -void tst_QThreadPool::reserveThread() -{ - QFETCH(int, limit); - QThreadPool *threadpool = QThreadPool::globalInstance(); - int savedLimit = threadpool->maxThreadCount(); - threadpool->setMaxThreadCount(limit); - - // reserve up to the limit - for (int i = 0; i < limit; ++i) - threadpool->reserveThread(); - - // reserveThread() should always reserve a thread, regardless of - // how many have been previously reserved - threadpool->reserveThread(); - QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 1); - threadpool->reserveThread(); - QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 2); - - // cleanup - threadpool->releaseThread(); - threadpool->releaseThread(); - for (int i = 0; i < limit; ++i) - threadpool->releaseThread(); - - // reserving threads in children should not effect the parent - { - QThreadPool threadpool2(threadpool); - threadpool2.setMaxThreadCount(limit); - - // reserve up to the limit - for (int i = 0; i < limit; ++i) - threadpool2.reserveThread(); - - // reserveThread() should always reserve a thread, regardless - // of how many have been previously reserved - threadpool2.reserveThread(); - QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 1); - threadpool2.reserveThread(); - QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 2); - - threadpool->reserveThread(); - QCOMPARE(threadpool->activeThreadCount(), 1); - threadpool->reserveThread(); - QCOMPARE(threadpool->activeThreadCount(), 2); - - // cleanup - threadpool2.releaseThread(); - threadpool2.releaseThread(); - threadpool->releaseThread(); - threadpool->releaseThread(); - while (threadpool2.activeThreadCount() > 0) - threadpool2.releaseThread(); - } - - // reset limit on global QThreadPool - threadpool->setMaxThreadCount(savedLimit); -} - -void tst_QThreadPool::releaseThread_data() -{ - setMaxThreadCount_data(); -} - -void tst_QThreadPool::releaseThread() -{ - QFETCH(int, limit); - QThreadPool *threadpool = QThreadPool::globalInstance(); - int savedLimit = threadpool->maxThreadCount(); - threadpool->setMaxThreadCount(limit); - - // reserve up to the limit - for (int i = 0; i < limit; ++i) - threadpool->reserveThread(); - - // release should decrease the number of reserved threads - int reserved = threadpool->activeThreadCount(); - while (reserved-- > 0) { - threadpool->releaseThread(); - QCOMPARE(threadpool->activeThreadCount(), reserved); - } - QCOMPARE(threadpool->activeThreadCount(), 0); - - // releaseThread() can release more than have been reserved - threadpool->releaseThread(); - QCOMPARE(threadpool->activeThreadCount(), -1); - threadpool->reserveThread(); - QCOMPARE(threadpool->activeThreadCount(), 0); - - // releasing threads in children should not effect the parent - { - QThreadPool threadpool2(threadpool); - threadpool2.setMaxThreadCount(limit); - - // reserve up to the limit - for (int i = 0; i < limit; ++i) - threadpool2.reserveThread(); - - // release should decrease the number of reserved threads - int reserved = threadpool2.activeThreadCount(); - while (reserved-- > 0) { - threadpool2.releaseThread(); - QCOMPARE(threadpool2.activeThreadCount(), reserved); - QCOMPARE(threadpool->activeThreadCount(), 0); - } - QCOMPARE(threadpool2.activeThreadCount(), 0); - QCOMPARE(threadpool->activeThreadCount(), 0); - - // releaseThread() can release more than have been reserved - threadpool2.releaseThread(); - QCOMPARE(threadpool2.activeThreadCount(), -1); - QCOMPARE(threadpool->activeThreadCount(), 0); - threadpool2.reserveThread(); - QCOMPARE(threadpool2.activeThreadCount(), 0); - QCOMPARE(threadpool->activeThreadCount(), 0); - } - - // reset limit on global QThreadPool - threadpool->setMaxThreadCount(savedLimit); -} - -QAtomicInt count; -class CountingRunnable : public QRunnable -{ - public: void run() - { - count.ref(); - } -}; - -void tst_QThreadPool::start() -{ - const int runs = 1000; - count.store(0); - { - QThreadPool threadPool; - for (int i = 0; i< runs; ++i) { - threadPool.start(new CountingRunnable()); - } - } - QCOMPARE(count.load(), runs); -} - -void tst_QThreadPool::tryStart() -{ - class WaitingTask : public QRunnable - { - public: - QSemaphore semaphore; - - WaitingTask() { setAutoDelete(false); } - - void run() - { - semaphore.acquire(); - count.ref(); - } - }; - - count.store(0); - - WaitingTask task; - QThreadPool threadPool; - for (int i = 0; i < threadPool.maxThreadCount(); ++i) { - threadPool.start(&task); - } - QVERIFY(!threadPool.tryStart(&task)); - task.semaphore.release(threadPool.maxThreadCount()); - threadPool.waitForDone(); - QCOMPARE(count.load(), threadPool.maxThreadCount()); -} - -QMutex mutex; -int activeThreads = 0; -int peakActiveThreads = 0; -void tst_QThreadPool::tryStartPeakThreadCount() -{ - class CounterTask : public QRunnable - { - public: - CounterTask() { setAutoDelete(false); } - - void run() - { - { - QMutexLocker lock(&mutex); - ++activeThreads; - peakActiveThreads = qMax(peakActiveThreads, activeThreads); - } - - QTest::qWait(100); - { - QMutexLocker lock(&mutex); - --activeThreads; - } - } - }; - - CounterTask task; - QThreadPool threadPool; - - for (int i = 0; i < 20; ++i) { - if (threadPool.tryStart(&task) == false) - QTest::qWait(10); - } - QCOMPARE(peakActiveThreads, QThread::idealThreadCount()); - - for (int i = 0; i < 20; ++i) { - if (threadPool.tryStart(&task) == false) - QTest::qWait(10); - } - QCOMPARE(peakActiveThreads, QThread::idealThreadCount()); -} - -void tst_QThreadPool::tryStartCount() -{ - class SleeperTask : public QRunnable - { - public: - SleeperTask() { setAutoDelete(false); } - - void run() - { - QTest::qWait(50); - } - }; - - SleeperTask task; - QThreadPool threadPool; - const int runs = 5; - - for (int i = 0; i < runs; ++i) { - int count = 0; - while (threadPool.tryStart(&task)) - ++count; - QCOMPARE(count, QThread::idealThreadCount()); - - QTest::qWait(100); - } -} - -void tst_QThreadPool::waitForDone() -{ - QTime total, pass; - total.start(); - - QThreadPool threadPool; - while (total.elapsed() < 10000) { - int runs; - count.store(runs = 0); - pass.restart(); - while (pass.elapsed() < 100) { - threadPool.start(new CountingRunnable()); - ++runs; - } - threadPool.waitForDone(); - QCOMPARE(count.load(), runs); - - count.store(runs = 0); - pass.restart(); - while (pass.elapsed() < 100) { - threadPool.start(new CountingRunnable()); - threadPool.start(new CountingRunnable()); - runs += 2; - } - threadPool.waitForDone(); - QCOMPARE(count.load(), runs); - } -} - -void tst_QThreadPool::waitForDoneTimeout() -{ - class BlockedTask : public QRunnable - { - public: - QMutex mutex; - BlockedTask() { setAutoDelete(false); } - - void run() - { - mutex.lock(); - mutex.unlock(); - QTest::qSleep(50); - } - }; - - QThreadPool threadPool; - - BlockedTask *task = new BlockedTask; - task->mutex.lock(); - threadPool.start(task); - QVERIFY(!threadPool.waitForDone(100)); - task->mutex.unlock(); - QVERIFY(threadPool.waitForDone(400)); -} - -void tst_QThreadPool::destroyingWaitsForTasksToFinish() -{ - QTime total, pass; - total.start(); - - while (total.elapsed() < 10000) { - int runs; - count.store(runs = 0); - { - QThreadPool threadPool; - pass.restart(); - while (pass.elapsed() < 100) { - threadPool.start(new CountingRunnable()); - ++runs; - } - } - QCOMPARE(count.load(), runs); - - count.store(runs = 0); - { - QThreadPool threadPool; - pass.restart(); - while (pass.elapsed() < 100) { - threadPool.start(new CountingRunnable()); - threadPool.start(new CountingRunnable()); - runs += 2; - } - } - QCOMPARE(count.load(), runs); - } -} - -void tst_QThreadPool::stressTest() -{ - class Task : public QRunnable - { - QSemaphore semaphore; - public: - Task() { setAutoDelete(false); } - - void start() - { - QThreadPool::globalInstance()->start(this); - } - - void wait() - { - semaphore.acquire(); - } - - void run() - { - semaphore.release(); - } - }; - - QTime total; - total.start(); - while (total.elapsed() < 30000) { - Task t; - t.start(); - t.wait(); - } -} - -QTEST_MAIN(tst_QThreadPool); -#include "tst_qthreadpool.moc" diff --git a/tests/auto/corelib/corelib.pro b/tests/auto/corelib/corelib.pro index be12fdab62..4f284ac21e 100644 --- a/tests/auto/corelib/corelib.pro +++ b/tests/auto/corelib/corelib.pro @@ -2,7 +2,6 @@ TEMPLATE=subdirs SUBDIRS=\ animation \ codecs \ - concurrent \ global \ io \ itemmodels \ @@ -14,4 +13,3 @@ SUBDIRS=\ tools \ xml -!contains(QT_CONFIG, concurrent): SUBDIRS -= concurrent diff --git a/tests/auto/corelib/thread/qthreadpool/.gitignore b/tests/auto/corelib/thread/qthreadpool/.gitignore new file mode 100644 index 0000000000..16105821a2 --- /dev/null +++ b/tests/auto/corelib/thread/qthreadpool/.gitignore @@ -0,0 +1 @@ +tst_qthreadpool diff --git a/tests/auto/corelib/thread/qthreadpool/qthreadpool.pro b/tests/auto/corelib/thread/qthreadpool/qthreadpool.pro new file mode 100644 index 0000000000..4d81218f24 --- /dev/null +++ b/tests/auto/corelib/thread/qthreadpool/qthreadpool.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qthreadpool +QT = core testlib +SOURCES = tst_qthreadpool.cpp diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp new file mode 100644 index 0000000000..1dd0410f41 --- /dev/null +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -0,0 +1,849 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include +#include + +typedef void (*FunctionPointer)(); + +class FunctionPointerTask : public QRunnable +{ +public: + FunctionPointerTask(FunctionPointer function) + :function(function) {} + void run() { function(); } +private: + FunctionPointer function; +}; + +QRunnable *createTask(FunctionPointer pointer) +{ + return new FunctionPointerTask(pointer); +} + +class tst_QThreadPool : public QObject +{ + Q_OBJECT +private slots: + void runFunction(); + void createThreadRunFunction(); + void runMultiple(); + void waitcomplete(); + void runTask(); + void singleton(); + void destruction(); + void threadRecycling(); + void expiryTimeout(); +#ifndef QT_NO_EXCEPTIONS + void exceptions(); +#endif + void setMaxThreadCount_data(); + void setMaxThreadCount(); + void setMaxThreadCountStartsAndStopsThreads(); + void reserveThread_data(); + void reserveThread(); + void releaseThread_data(); + void releaseThread(); + void start(); + void tryStart(); + void tryStartPeakThreadCount(); + void tryStartCount(); + void waitForDone(); + void waitForDoneTimeout(); + void destroyingWaitsForTasksToFinish(); + void stressTest(); +}; + +int testFunctionCount; + +void sleepTestFunction() +{ + QTest::qSleep(1000); + ++testFunctionCount; +} + +void emptyFunct() +{ + +} + +void noSleepTestFunction() +{ + ++testFunctionCount; +} + +void sleepTestFunctionMutex() +{ + static QMutex testMutex; + QTest::qSleep(1000); + testMutex.lock(); + ++testFunctionCount; + testMutex.unlock(); +} + +void noSleepTestFunctionMutex() +{ + static QMutex testMutex; + testMutex.lock(); + ++testFunctionCount; + testMutex.unlock(); +} + +void tst_QThreadPool::runFunction() +{ + { + QThreadPool manager; + testFunctionCount = 0; + manager.start(createTask(noSleepTestFunction)); + } + QCOMPARE(testFunctionCount, 1); +} + +void tst_QThreadPool::createThreadRunFunction() +{ + { + QThreadPool manager; + testFunctionCount = 0; + manager.start(createTask(noSleepTestFunction)); + } + + QCOMPARE(testFunctionCount, 1); +} + +void tst_QThreadPool::runMultiple() +{ + const int runs = 10; + + { + QThreadPool manager; + testFunctionCount = 0; + for (int i = 0; i < runs; ++i) { + manager.start(createTask(sleepTestFunctionMutex)); + } + } + QCOMPARE(testFunctionCount, runs); + + { + QThreadPool manager; + testFunctionCount = 0; + for (int i = 0; i < runs; ++i) { + manager.start(createTask(noSleepTestFunctionMutex)); + } + } + QCOMPARE(testFunctionCount, runs); + + { + QThreadPool manager; + for (int i = 0; i < 500; ++i) + manager.start(createTask(emptyFunct)); + } +} + +void tst_QThreadPool::waitcomplete() +{ + testFunctionCount = 0; + const int runs = 500; + for (int i = 0; i < 500; ++i) { + QThreadPool pool; + pool.start(createTask(noSleepTestFunction)); + } + QCOMPARE(testFunctionCount, runs); +} + +volatile bool ran; +class TestTask : public QRunnable +{ +public: + void run() + { + ran = true; + } +}; + +void tst_QThreadPool::runTask() +{ + QThreadPool manager; + ran = false; + manager.start(new TestTask()); + QTRY_VERIFY(ran); +} + +/* + Test running via QThreadPool::globalInstance() +*/ +void tst_QThreadPool::singleton() +{ + ran = false; + QThreadPool::globalInstance()->start(new TestTask()); + QTRY_VERIFY(ran); +} + +int *value = 0; +class IntAccessor : public QRunnable +{ +public: + void run() + { + for (int i = 0; i < 100; ++i) { + ++(*value); + QTest::qSleep(1); + } + } +}; + +/* + Test that the ThreadManager destructor waits until + all threads have completed. +*/ +void tst_QThreadPool::destruction() +{ + value = new int; + QThreadPool *threadManager = new QThreadPool(); + threadManager->start(new IntAccessor()); + threadManager->start(new IntAccessor()); + delete threadManager; + delete value; + value = 0; +} + +QSemaphore threadRecyclingSemaphore; +QThread *recycledThread = 0; + +class ThreadRecorderTask : public QRunnable +{ +public: + void run() + { + recycledThread = QThread::currentThread(); + threadRecyclingSemaphore.release(); + } +}; + +/* + Test that the thread pool really reuses threads. +*/ +void tst_QThreadPool::threadRecycling() +{ + QThreadPool threadPool; + + threadPool.start(new ThreadRecorderTask()); + threadRecyclingSemaphore.acquire(); + QThread *thread1 = recycledThread; + + QTest::qSleep(100); + + threadPool.start(new ThreadRecorderTask()); + threadRecyclingSemaphore.acquire(); + QThread *thread2 = recycledThread; + QCOMPARE(thread1, thread2); + + QTest::qSleep(100); + + threadPool.start(new ThreadRecorderTask()); + threadRecyclingSemaphore.acquire(); + QThread *thread3 = recycledThread; + QCOMPARE(thread2, thread3); +} + +class ExpiryTimeoutTask : public QRunnable +{ +public: + QThread *thread; + int runCount; + QSemaphore semaphore; + + ExpiryTimeoutTask() + : thread(0), runCount(0) + { + setAutoDelete(false); + } + + void run() + { + thread = QThread::currentThread(); + ++runCount; + semaphore.release(); + } +}; + +void tst_QThreadPool::expiryTimeout() +{ + ExpiryTimeoutTask task; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(1); + + int expiryTimeout = threadPool.expiryTimeout(); + threadPool.setExpiryTimeout(1000); + QCOMPARE(threadPool.expiryTimeout(), 1000); + + // run the task + threadPool.start(&task); + QVERIFY(task.semaphore.tryAcquire(1, 10000)); + QCOMPARE(task.runCount, 1); + QVERIFY(!task.thread->wait(100)); + // thread should expire + QThread *firstThread = task.thread; + QVERIFY(task.thread->wait(10000)); + + // run task again, thread should be restarted + threadPool.start(&task); + QVERIFY(task.semaphore.tryAcquire(1, 10000)); + QCOMPARE(task.runCount, 2); + QVERIFY(!task.thread->wait(100)); + // thread should expire again + QVERIFY(task.thread->wait(10000)); + + // thread pool should have reused the expired thread (instead of + // starting a new one) + QCOMPARE(firstThread, task.thread); + + threadPool.setExpiryTimeout(expiryTimeout); + QCOMPARE(threadPool.expiryTimeout(), expiryTimeout); +} + +#ifndef QT_NO_EXCEPTIONS +class ExceptionTask : public QRunnable +{ +public: + void run() + { + throw new int; + } +}; + +void tst_QThreadPool::exceptions() +{ + ExceptionTask task; + { + QThreadPool threadPool; +// Uncomment this for a nice crash. +// threadPool.start(&task); + } +} +#endif + +void tst_QThreadPool::setMaxThreadCount_data() +{ + QTest::addColumn("limit"); + + QTest::newRow("") << 1; + QTest::newRow("") << -1; + QTest::newRow("") << 2; + QTest::newRow("") << -2; + QTest::newRow("") << 4; + QTest::newRow("") << -4; + QTest::newRow("") << 0; + QTest::newRow("") << 12345; + QTest::newRow("") << -6789; + QTest::newRow("") << 42; + QTest::newRow("") << -666; +} + +void tst_QThreadPool::setMaxThreadCount() +{ + QFETCH(int, limit); + QThreadPool *threadPool = QThreadPool::globalInstance(); + int savedLimit = threadPool->maxThreadCount(); + + // maxThreadCount() should always return the previous argument to + // setMaxThreadCount(), regardless of input + threadPool->setMaxThreadCount(limit); + QCOMPARE(threadPool->maxThreadCount(), limit); + + // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount() + threadPool->setMaxThreadCount(savedLimit); + QCOMPARE(threadPool->maxThreadCount(), savedLimit); + + // setting the limit on children should have no effect on the parent + { + QThreadPool threadPool2(threadPool); + savedLimit = threadPool2.maxThreadCount(); + + // maxThreadCount() should always return the previous argument to + // setMaxThreadCount(), regardless of input + threadPool2.setMaxThreadCount(limit); + QCOMPARE(threadPool2.maxThreadCount(), limit); + + // the value returned from maxThreadCount() should always be valid input for setMaxThreadCount() + threadPool2.setMaxThreadCount(savedLimit); + QCOMPARE(threadPool2.maxThreadCount(), savedLimit); + } +} + +void tst_QThreadPool::setMaxThreadCountStartsAndStopsThreads() +{ + class WaitingTask : public QRunnable + { + public: + QSemaphore waitForStarted, waitToFinish; + + WaitingTask() { setAutoDelete(false); } + + void run() + { + waitForStarted.release(); + waitToFinish.acquire(); + } + }; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(1); + + WaitingTask *task = new WaitingTask; + threadPool.start(task); + QVERIFY(task->waitForStarted.tryAcquire(1, 1000)); + + // thread limit is 1, cannot start more tasks + threadPool.start(task); + QVERIFY(!task->waitForStarted.tryAcquire(1, 1000)); + + // increasing the limit by 1 should start the task immediately + threadPool.setMaxThreadCount(2); + QVERIFY(task->waitForStarted.tryAcquire(1, 1000)); + + // ... but we still cannot start more tasks + threadPool.start(task); + QVERIFY(!task->waitForStarted.tryAcquire(1, 1000)); + + // increasing the limit should be able to start more than one at a time + threadPool.start(task); + threadPool.setMaxThreadCount(4); + QVERIFY(task->waitForStarted.tryAcquire(2, 1000)); + + // ... but we still cannot start more tasks + threadPool.start(task); + threadPool.start(task); + QVERIFY(!task->waitForStarted.tryAcquire(2, 1000)); + + // decreasing the thread limit should cause the active thread count to go down + threadPool.setMaxThreadCount(2); + QCOMPARE(threadPool.activeThreadCount(), 4); + task->waitToFinish.release(2); + QTest::qWait(1000); + QCOMPARE(threadPool.activeThreadCount(), 2); + + // ... and we still cannot start more tasks + threadPool.start(task); + threadPool.start(task); + QVERIFY(!task->waitForStarted.tryAcquire(2, 1000)); + + // start all remaining tasks + threadPool.start(task); + threadPool.start(task); + threadPool.start(task); + threadPool.start(task); + threadPool.setMaxThreadCount(8); + QVERIFY(task->waitForStarted.tryAcquire(6, 1000)); + + task->waitToFinish.release(10); +// delete task; +} + +void tst_QThreadPool::reserveThread_data() +{ + setMaxThreadCount_data(); +} + +void tst_QThreadPool::reserveThread() +{ + QFETCH(int, limit); + QThreadPool *threadpool = QThreadPool::globalInstance(); + int savedLimit = threadpool->maxThreadCount(); + threadpool->setMaxThreadCount(limit); + + // reserve up to the limit + for (int i = 0; i < limit; ++i) + threadpool->reserveThread(); + + // reserveThread() should always reserve a thread, regardless of + // how many have been previously reserved + threadpool->reserveThread(); + QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 1); + threadpool->reserveThread(); + QCOMPARE(threadpool->activeThreadCount(), (limit > 0 ? limit : 0) + 2); + + // cleanup + threadpool->releaseThread(); + threadpool->releaseThread(); + for (int i = 0; i < limit; ++i) + threadpool->releaseThread(); + + // reserving threads in children should not effect the parent + { + QThreadPool threadpool2(threadpool); + threadpool2.setMaxThreadCount(limit); + + // reserve up to the limit + for (int i = 0; i < limit; ++i) + threadpool2.reserveThread(); + + // reserveThread() should always reserve a thread, regardless + // of how many have been previously reserved + threadpool2.reserveThread(); + QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 1); + threadpool2.reserveThread(); + QCOMPARE(threadpool2.activeThreadCount(), (limit > 0 ? limit : 0) + 2); + + threadpool->reserveThread(); + QCOMPARE(threadpool->activeThreadCount(), 1); + threadpool->reserveThread(); + QCOMPARE(threadpool->activeThreadCount(), 2); + + // cleanup + threadpool2.releaseThread(); + threadpool2.releaseThread(); + threadpool->releaseThread(); + threadpool->releaseThread(); + while (threadpool2.activeThreadCount() > 0) + threadpool2.releaseThread(); + } + + // reset limit on global QThreadPool + threadpool->setMaxThreadCount(savedLimit); +} + +void tst_QThreadPool::releaseThread_data() +{ + setMaxThreadCount_data(); +} + +void tst_QThreadPool::releaseThread() +{ + QFETCH(int, limit); + QThreadPool *threadpool = QThreadPool::globalInstance(); + int savedLimit = threadpool->maxThreadCount(); + threadpool->setMaxThreadCount(limit); + + // reserve up to the limit + for (int i = 0; i < limit; ++i) + threadpool->reserveThread(); + + // release should decrease the number of reserved threads + int reserved = threadpool->activeThreadCount(); + while (reserved-- > 0) { + threadpool->releaseThread(); + QCOMPARE(threadpool->activeThreadCount(), reserved); + } + QCOMPARE(threadpool->activeThreadCount(), 0); + + // releaseThread() can release more than have been reserved + threadpool->releaseThread(); + QCOMPARE(threadpool->activeThreadCount(), -1); + threadpool->reserveThread(); + QCOMPARE(threadpool->activeThreadCount(), 0); + + // releasing threads in children should not effect the parent + { + QThreadPool threadpool2(threadpool); + threadpool2.setMaxThreadCount(limit); + + // reserve up to the limit + for (int i = 0; i < limit; ++i) + threadpool2.reserveThread(); + + // release should decrease the number of reserved threads + int reserved = threadpool2.activeThreadCount(); + while (reserved-- > 0) { + threadpool2.releaseThread(); + QCOMPARE(threadpool2.activeThreadCount(), reserved); + QCOMPARE(threadpool->activeThreadCount(), 0); + } + QCOMPARE(threadpool2.activeThreadCount(), 0); + QCOMPARE(threadpool->activeThreadCount(), 0); + + // releaseThread() can release more than have been reserved + threadpool2.releaseThread(); + QCOMPARE(threadpool2.activeThreadCount(), -1); + QCOMPARE(threadpool->activeThreadCount(), 0); + threadpool2.reserveThread(); + QCOMPARE(threadpool2.activeThreadCount(), 0); + QCOMPARE(threadpool->activeThreadCount(), 0); + } + + // reset limit on global QThreadPool + threadpool->setMaxThreadCount(savedLimit); +} + +QAtomicInt count; +class CountingRunnable : public QRunnable +{ + public: void run() + { + count.ref(); + } +}; + +void tst_QThreadPool::start() +{ + const int runs = 1000; + count.store(0); + { + QThreadPool threadPool; + for (int i = 0; i< runs; ++i) { + threadPool.start(new CountingRunnable()); + } + } + QCOMPARE(count.load(), runs); +} + +void tst_QThreadPool::tryStart() +{ + class WaitingTask : public QRunnable + { + public: + QSemaphore semaphore; + + WaitingTask() { setAutoDelete(false); } + + void run() + { + semaphore.acquire(); + count.ref(); + } + }; + + count.store(0); + + WaitingTask task; + QThreadPool threadPool; + for (int i = 0; i < threadPool.maxThreadCount(); ++i) { + threadPool.start(&task); + } + QVERIFY(!threadPool.tryStart(&task)); + task.semaphore.release(threadPool.maxThreadCount()); + threadPool.waitForDone(); + QCOMPARE(count.load(), threadPool.maxThreadCount()); +} + +QMutex mutex; +int activeThreads = 0; +int peakActiveThreads = 0; +void tst_QThreadPool::tryStartPeakThreadCount() +{ + class CounterTask : public QRunnable + { + public: + CounterTask() { setAutoDelete(false); } + + void run() + { + { + QMutexLocker lock(&mutex); + ++activeThreads; + peakActiveThreads = qMax(peakActiveThreads, activeThreads); + } + + QTest::qWait(100); + { + QMutexLocker lock(&mutex); + --activeThreads; + } + } + }; + + CounterTask task; + QThreadPool threadPool; + + for (int i = 0; i < 20; ++i) { + if (threadPool.tryStart(&task) == false) + QTest::qWait(10); + } + QCOMPARE(peakActiveThreads, QThread::idealThreadCount()); + + for (int i = 0; i < 20; ++i) { + if (threadPool.tryStart(&task) == false) + QTest::qWait(10); + } + QCOMPARE(peakActiveThreads, QThread::idealThreadCount()); +} + +void tst_QThreadPool::tryStartCount() +{ + class SleeperTask : public QRunnable + { + public: + SleeperTask() { setAutoDelete(false); } + + void run() + { + QTest::qWait(50); + } + }; + + SleeperTask task; + QThreadPool threadPool; + const int runs = 5; + + for (int i = 0; i < runs; ++i) { + int count = 0; + while (threadPool.tryStart(&task)) + ++count; + QCOMPARE(count, QThread::idealThreadCount()); + + QTest::qWait(100); + } +} + +void tst_QThreadPool::waitForDone() +{ + QTime total, pass; + total.start(); + + QThreadPool threadPool; + while (total.elapsed() < 10000) { + int runs; + count.store(runs = 0); + pass.restart(); + while (pass.elapsed() < 100) { + threadPool.start(new CountingRunnable()); + ++runs; + } + threadPool.waitForDone(); + QCOMPARE(count.load(), runs); + + count.store(runs = 0); + pass.restart(); + while (pass.elapsed() < 100) { + threadPool.start(new CountingRunnable()); + threadPool.start(new CountingRunnable()); + runs += 2; + } + threadPool.waitForDone(); + QCOMPARE(count.load(), runs); + } +} + +void tst_QThreadPool::waitForDoneTimeout() +{ + class BlockedTask : public QRunnable + { + public: + QMutex mutex; + BlockedTask() { setAutoDelete(false); } + + void run() + { + mutex.lock(); + mutex.unlock(); + QTest::qSleep(50); + } + }; + + QThreadPool threadPool; + + BlockedTask *task = new BlockedTask; + task->mutex.lock(); + threadPool.start(task); + QVERIFY(!threadPool.waitForDone(100)); + task->mutex.unlock(); + QVERIFY(threadPool.waitForDone(400)); +} + +void tst_QThreadPool::destroyingWaitsForTasksToFinish() +{ + QTime total, pass; + total.start(); + + while (total.elapsed() < 10000) { + int runs; + count.store(runs = 0); + { + QThreadPool threadPool; + pass.restart(); + while (pass.elapsed() < 100) { + threadPool.start(new CountingRunnable()); + ++runs; + } + } + QCOMPARE(count.load(), runs); + + count.store(runs = 0); + { + QThreadPool threadPool; + pass.restart(); + while (pass.elapsed() < 100) { + threadPool.start(new CountingRunnable()); + threadPool.start(new CountingRunnable()); + runs += 2; + } + } + QCOMPARE(count.load(), runs); + } +} + +void tst_QThreadPool::stressTest() +{ + class Task : public QRunnable + { + QSemaphore semaphore; + public: + Task() { setAutoDelete(false); } + + void start() + { + QThreadPool::globalInstance()->start(this); + } + + void wait() + { + semaphore.acquire(); + } + + void run() + { + semaphore.release(); + } + }; + + QTime total; + total.start(); + while (total.elapsed() < 30000) { + Task t; + t.start(); + t.wait(); + } +} + +QTEST_MAIN(tst_QThreadPool); +#include "tst_qthreadpool.moc" diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro index a137748b75..12a284c7c7 100644 --- a/tests/auto/corelib/thread/thread.pro +++ b/tests/auto/corelib/thread/thread.pro @@ -9,6 +9,7 @@ SUBDIRS=\ qsemaphore \ qthread \ qthreadonce \ + qthreadpool \ qthreadstorage \ qwaitcondition \ qwritelocker -- cgit v1.2.3