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/concurrent/qtconcurrentrun/.gitignore | 1 + .../concurrent/qtconcurrentrun/qtconcurrentrun.pro | 4 + .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 463 +++++++++++++++++++++ 3 files changed, 468 insertions(+) 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 (limited to 'tests/auto/concurrent/qtconcurrentrun') 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" -- cgit v1.2.3