summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
diff options
context:
space:
mode:
authorHolger Ihrig <holger.ihrig@nokia.com>2011-08-24 10:51:34 +0200
committerHolger Ihrig <holger.ihrig@nokia.com>2011-08-30 13:17:07 +0200
commit0547598a28c3c1dd5c5f4c3ec9888b0de499199b (patch)
tree036c2f68f61cdef119cc74088ac8d4d60d608162 /tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
parentd610fbc13e589b36ce8f1e1af7166d215f0ccc90 (diff)
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 <qt_sanity_bot@ovi.com> Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com> Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
Diffstat (limited to 'tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp')
-rw-r--r--tests/auto/corelib/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp518
1 files changed, 518 insertions, 0 deletions
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 <qtconcurrentrun.h>
+// #include <qtconcurrentcreatefunctor.h>
+#include <qfuture.h>
+#include <QString>
+#include <QtTest/QtTest>
+#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<void> future = run(F(light));
+ qDebug("waiting");
+ future.waitForFinished();
+ qDebug("done");
+}
+
+void tst_QtConcurrentRun::runHeavyFunction()
+{
+ qDebug("starting function");
+ QFuture<void> 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<int> 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<void> 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<void> f1 = run(recursiveRun, level);
+ QFuture<void> f2 = run(recursiveRun, level);
+ f1.waitForFinished();
+ f2.waitForFinished();
+ }
+}
+
+int recursiveResult(int level)
+{
+ count.ref();
+ if (--level > 0) {
+ QFuture<int> f1 = run(recursiveResult, level);
+ QFuture<int> 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<int> fut = QtConcurrent::run(f);
+ QCOMPARE(fut.result(), 42);
+ }
+ {
+ QFuture<double> fut = QtConcurrent::run(f, 8.5, 1.8);
+ QCOMPARE(fut.result(), (8.5/1.8));
+ }
+ {
+ QFuture<int> 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<QStringList> 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