From 0547598a28c3c1dd5c5f4c3ec9888b0de499199b Mon Sep 17 00:00:00 2001 From: Holger Ihrig Date: Wed, 24 Aug 2011 10:51:34 +0200 Subject: Moving relevant tests to corelib/concurrent Adding tests for QFutureSynchronizer and QtConcurrentResultStore Added minor things in QFutureSynchronizer and QtConcurrentResultStore and removed tests for destruction Task-number: QTBUG-21066 Change-Id: I9f088b89463340f339c914bcb37fb2f9d3b62057 Reviewed-on: http://codereview.qt.nokia.com/3477 Reviewed-by: Qt Sanity Bot Reviewed-by: Rohan McGovern Reviewed-by: Jason McDonald --- .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 518 +++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp (limited to 'tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp') diff --git a/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp new file mode 100644 index 0000000000..cacb09aae1 --- /dev/null +++ b/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -0,0 +1,518 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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 "../qfuture/versioncheck.h" + +#ifndef QT_NO_CONCURRENT_TEST + +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 +#if 0 + void createFunctor(); +#endif + void functor(); + void lambda(); +}; + +#if 0 +# define F(X) createFunctor(X) +#else +# define F(X) X +#endif + + +QTEST_MAIN(tst_QtConcurrentRun) + +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(F(light)); + qDebug("waiting"); + future.waitForFinished(); + qDebug("done"); +} + +void tst_QtConcurrentRun::runHeavyFunction() +{ + qDebug("starting function"); + QFuture future = run(F(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(F(returnInt0)); + QCOMPARE(f.result(), 10); + + A a; + f = run(&a, F(&A::member0)); + QCOMPARE(f.result(), 10); + + f = run(&a, F(&A::member1), 20); + QCOMPARE(f.result(), 20); + + f = run(a, F(&A::member0)); + QCOMPARE(f.result(), 10); + + f = run(a, F(&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, F(&AConst::member1), 20); + QCOMPARE(f.result(), 20); + + f = run(aConst, F(&AConst::member0)); + QCOMPARE(f.result(), 10); + + f = run(aConst, F(&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(F(&c)); + f = run(c, 10); + f = run(F(&c), 10); + + const TestConstClass cc = TestConstClass(); + f = run(cc); + f = run(F(&cc)); + f = run(cc, 10); + f = run(F(&cc), 10); +} + + +void tst_QtConcurrentRun::memberFunctions() +{ + TestClass c; + + run(c, F(&TestClass::foo)).waitForFinished(); + run(&c, F(&TestClass::foo)).waitForFinished(); + run(c, F(&TestClass::fooInt), 10).waitForFinished(); + run(&c, F(&TestClass::fooInt), 10).waitForFinished(); + + const TestConstClass cc = TestConstClass(); + run(cc, F(&TestConstClass::foo)).waitForFinished(); + run(&cc, F(&TestConstClass::foo)).waitForFinished(); + run(cc, F(&TestConstClass::fooInt), 10).waitForFinished(); + run(&cc, F(&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(F(doubleFunction), d).waitForFinished(); + int i; + run(F(doubleFunction), d).waitForFinished(); + run(F(doubleFunction), i).waitForFinished(); + run(F(doubleFunction), 10).waitForFinished(); + run(F(stringFunction), QLatin1String("Foo")).waitForFinished(); + run(F(stringConstRefFunction), QLatin1String("Foo")).waitForFinished(); + QString string; + run(F(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 = 0; + QThreadPool::globalInstance()->setMaxThreadCount(i); + recursiveRun(levels); + QCOMPARE((int)count, (int)pow(2.0, levels) - 1); + } + + for (int i = 0; i < QThread::idealThreadCount(); ++i) { + count = 0; + QThreadPool::globalInstance()->setMaxThreadCount(i); + recursiveResult(levels); + QCOMPARE((int)count, (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 + +#if 0 +void tst_QtConcurrentRun::createFunctor() +{ + e = 0; + ::QtConcurrent::createFunctor(vfn0)(); + e += QtConcurrent::createFunctor(fn0)(); + ::QtConcurrent::createFunctor(vfn1)(1); // implicit conversions should work + e += QtConcurrent::createFunctor(fn1)(2); + ::QtConcurrent::createFunctor(vfn2)(1.0, &e); + e += QtConcurrent::createFunctor(fn2)(2, &e); + QCOMPARE(e, 6); + + + e = 0; + TestClass c; + +// ::QtConcurrent::createFunctor(c, &TestClass::foo)(); + ::QtConcurrent::createFunctor(&c, &TestClass::foo)(); +// ::QtConcurrent::createFunctor(c, &TestClass::fooInt)(10); + ::QtConcurrent::createFunctor(&c, &TestClass::fooInt)(10); + + const TestConstClass cc = TestConstClass(); +/* + ::QtConcurrent::createFunctor(cc, &TestConstClass::foo)(); + ::QtConcurrent::createFunctor(&cc, &TestConstClass::foo)(); + ::QtConcurrent::createFunctor(cc, &TestConstClass::fooInt(10); + ::QtConcurrent::createFunctor(&cc, &TestConstClass::fooInt)(10); +*/ + qDebug() << e; +} +#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) { } +}; + +void tst_QtConcurrentRun::functor() +{ + //this test functor without result_type, decltype need to be supported by the compiler +#ifndef Q_COMPILER_DECLTYPE + QSKIP("Compiler do not suport decltype", SkipAll); +#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 do not suport lambda", SkipAll); +#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 +} + + +#include "tst_qtconcurrentrun.moc" + +#else +QTEST_NOOP_MAIN +#endif -- cgit v1.2.3