From bf5e8a646071abae8bd2111ff75b1eae52874fed Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Feb 2010 20:04:23 +0100 Subject: Autotest: add a test for QDBusPendingCallWatcher use in threads I'm satisfied that the finished() signal won't be emitted until the event loop is run, or waitForFinished() is called. However, I'm not fully convinced that there isn't a race condition if you try to waitForFinished() right away. Needs more investigation. --- .../auto/qdbuspendingcall/tst_qdbuspendingcall.cpp | 57 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/auto/qdbuspendingcall/tst_qdbuspendingcall.cpp b/tests/auto/qdbuspendingcall/tst_qdbuspendingcall.cpp index 7208383..54426ce 100644 --- a/tests/auto/qdbuspendingcall/tst_qdbuspendingcall.cpp +++ b/tests/auto/qdbuspendingcall/tst_qdbuspendingcall.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #ifndef QT_NO_DBUS @@ -90,6 +91,7 @@ private Q_SLOTS: void watcher(); void watcher_error(); void watcher_waitForFinished(); + void watcher_waitForFinished_threaded(); void watcher_waitForFinished_alreadyFinished(); void watcher_waitForFinished_alreadyFinished_eventLoop(); void watcher_waitForFinished_error(); @@ -124,7 +126,10 @@ void tst_QDBusPendingCall::finished(QDBusPendingCallWatcher *call) slotCalled = FinishCalled; ++callCount; watchArgument = call; - QTestEventLoop::instance().exitLoop(); + if (QThread::currentThread() == thread()) + QTestEventLoop::instance().exitLoop(); + else + QMetaObject::invokeMethod(&QTestEventLoop::instance(), "exitLoop", Qt::QueuedConnection); } void tst_QDBusPendingCall::callback(const QStringList &list) @@ -377,6 +382,56 @@ void tst_QDBusPendingCall::watcher_waitForFinished() QVERIFY(args2.at(0).toStringList().contains(conn.baseService())); } +void tst_QDBusPendingCall::watcher_waitForFinished_threaded() +{ + callCount = 0; + watchArgument = 0; + slotCalled = 0; + + class WorkerThread: public QThread { + public: + tst_QDBusPendingCall *tst; + WorkerThread(tst_QDBusPendingCall *tst) : tst(tst) {} + void run() + { + QDBusPendingCall ac = tst->sendMessage(); +// QVERIFY(!ac.isFinished()); +// QVERIFY(!ac.isError()); +// QVERIFY(ac.reply().type() == QDBusMessage::InvalidMessage); + + QDBusPendingCallWatcher watch(ac); + tst->connect(&watch, SIGNAL(finished(QDBusPendingCallWatcher*)), + SLOT(finished(QDBusPendingCallWatcher*)), Qt::DirectConnection); + + QTest::qSleep(100); // don't process events in this thread + +// QVERIFY(!ac.isFinished()); +// QVERIFY(!ac.isError()); +// QVERIFY(ac.reply().type() == QDBusMessage::InvalidMessage); + QCOMPARE(tst->callCount, 0); + QCOMPARE(tst->slotCalled, 0); + + watch.waitForFinished(); + QVERIFY(ac.isFinished()); + QVERIFY(!ac.isError()); + + QCOMPARE(tst->callCount, 1); + QCOMPARE(tst->slotCalled, (int)FinishCalled); + QCOMPARE(tst->watchArgument, &watch); + QVERIFY(!watch.isError()); + + const QVariantList args2 = ac.reply().arguments(); + QVERIFY(!args2.isEmpty()); + QVERIFY(args2.at(0).toStringList().contains(tst->conn.baseService())); + } + } thread(this); + QTestEventLoop::instance().connect(&thread, SIGNAL(finished()), SLOT(exitLoop())); + thread.start(); + QTestEventLoop::instance().enterLoop(1000); + QVERIFY(!thread.isRunning()); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + void tst_QDBusPendingCall::watcher_waitForFinished_alreadyFinished() { QDBusPendingCall ac = sendMessage(); -- cgit v0.12