diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2013-03-13 11:56:08 -0700 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-03-19 07:03:17 +0100 |
commit | d2a98df9bcb113d9ef8ea0e7c1472875372706c7 (patch) | |
tree | a3c89ef0227a25bff5775ccbdad681f39274fd4c /tests/auto/dbus | |
parent | d1b4857d1718ef50dba64c8700253fed5d187ab2 (diff) |
Make sure that signal disconnects don't disconnect too much
There has been a latent bug forever in QtDBus that would make a signal
disconnect actually disconnect too much. The reason is that
disconnectNotify() is called every time a signal is disconnected from
a receiver, but that doesn't mean it was the last connection.
This test checks whether disconnecting from voidSignal() to our test
receiver will also disconnect from exitLoop(). If it does, we'll get a
timeout. I could have implemented it with two receivers, but in the
buggy case, it would always fail first in the timeout verification.
Change-Id: I5766d8a38594eb25e65b304913251303660fad41
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
Diffstat (limited to 'tests/auto/dbus')
-rw-r--r-- | tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp index 89b91558ff..786592d018 100644 --- a/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp +++ b/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp @@ -159,6 +159,11 @@ private slots: void followSignal(); + void connectDisconnect_data(); + void connectDisconnect(); + void connectDisconnectPeer_data(); + void connectDisconnectPeer(); + void createErrors_data(); void createErrors(); @@ -196,6 +201,15 @@ private: QProcess proc; }; +class SignalReceiver : public QObject +{ + Q_OBJECT +public: + int callCount; + SignalReceiver() : callCount(0) {} +public slots: + void receive() { ++callCount; } +}; tst_QDBusAbstractInterface::tst_QDBusAbstractInterface() { @@ -1022,6 +1036,82 @@ void tst_QDBusAbstractInterface::followSignal() con.interface()->unregisterService(serviceToFollow); } +void tst_QDBusAbstractInterface::connectDisconnect_data() +{ + QTest::addColumn<int>("connectCount"); + QTest::addColumn<int>("disconnectCount"); + + // we don't actually need multiple disconnects + // QObject::disconnect() disconnects all matching rules + // we'd have to use QMetaObject::disconnectOne if we wanted just one + QTest::newRow("null") << 0 << 0; + QTest::newRow("connect-disconnect") << 1 << 1; + QTest::newRow("connect-twice") << 2 << 0; + QTest::newRow("connect-twice-disconnect") << 2 << 1; +} + +void tst_QDBusAbstractInterface::connectDisconnect() +{ + QFETCH(int, connectCount); + QFETCH(int, disconnectCount); + + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + // connect the exitLoop slot first + // if the disconnect() below does something weird, we'll get a timeout + QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); + + SignalReceiver sr; + for (int i = 0; i < connectCount; ++i) + sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive())); + if (disconnectCount) + QObject::disconnect(p.data(), SIGNAL(voidSignal()), &sr, SLOT(receive())); + + emit targetObj.voidSignal(); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + if (disconnectCount != 0) + QCOMPARE(sr.callCount, 0); + else + QCOMPARE(sr.callCount, connectCount); +} + +void tst_QDBusAbstractInterface::connectDisconnectPeer_data() +{ + connectDisconnect_data(); +} + +void tst_QDBusAbstractInterface::connectDisconnectPeer() +{ + QFETCH(int, connectCount); + QFETCH(int, disconnectCount); + + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + // connect the exitLoop slot first + // if the disconnect() below does something weird, we'll get a timeout + QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); + + SignalReceiver sr; + for (int i = 0; i < connectCount; ++i) + sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive())); + if (disconnectCount) + QObject::disconnect(p.data(), SIGNAL(voidSignal()), &sr, SLOT(receive())); + + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "voidSignal"); + QVERIFY(QDBusConnection::sessionBus().send(req)); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + if (disconnectCount != 0) + QCOMPARE(sr.callCount, 0); + else + QCOMPARE(sr.callCount, connectCount); +} + void tst_QDBusAbstractInterface::createErrors_data() { QTest::addColumn<QString>("service"); |