From 08c50599f149b7a8d448845dcb0b171e96342784 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 27 Aug 2012 23:15:40 +0200 Subject: Move QFutureWatcher back to QtCore This belongs with QFuture. Change-Id: I555cd01c1d3890fbbaca4fd8a9170292ea4eb0fb Reviewed-by: Qt Doc Bot Reviewed-by: Thiago Macieira --- tests/auto/concurrent/concurrent.pro | 1 - tests/auto/concurrent/qfuturewatcher/.gitignore | 1 - .../concurrent/qfuturewatcher/qfuturewatcher.pro | 5 - .../qfuturewatcher/tst_qfuturewatcher.cpp | 942 --------------------- 4 files changed, 949 deletions(-) delete mode 100644 tests/auto/concurrent/qfuturewatcher/.gitignore delete mode 100644 tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro delete mode 100644 tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp (limited to 'tests/auto/concurrent') diff --git a/tests/auto/concurrent/concurrent.pro b/tests/auto/concurrent/concurrent.pro index 80d19d30ec..14aff5d493 100644 --- a/tests/auto/concurrent/concurrent.pro +++ b/tests/auto/concurrent/concurrent.pro @@ -1,7 +1,6 @@ TEMPLATE=subdirs SUBDIRS=\ qfuturesynchronizer \ - qfuturewatcher \ qtconcurrentfilter \ qtconcurrentiteratekernel \ qtconcurrentmap \ diff --git a/tests/auto/concurrent/qfuturewatcher/.gitignore b/tests/auto/concurrent/qfuturewatcher/.gitignore deleted file mode 100644 index 1d778431c5..0000000000 --- a/tests/auto/concurrent/qfuturewatcher/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfuturewatcher diff --git a/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro b/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro deleted file mode 100644 index 17c0363ce4..0000000000 --- a/tests/auto/concurrent/qfuturewatcher/qfuturewatcher.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qfuturewatcher -QT = core core-private testlib concurrent -SOURCES = tst_qfuturewatcher.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp deleted file mode 100644 index c68a33279c..0000000000 --- a/tests/auto/concurrent/qfuturewatcher/tst_qfuturewatcher.cpp +++ /dev/null @@ -1,942 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, 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, Digia gives you certain additional -** rights. These rights are described in the Digia 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. -** -** -** $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" -- cgit v1.2.3