From d761c6278305ef8737daca4bc3e61a119b40e107 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 6 Apr 2018 01:27:32 +0100 Subject: [PATCH] QDBusServiceWatcher namespace prefix support This allows a user to efficiently watch for services with a common domain prefix. This is exposed in the API via a wildcard character in the service name. For example creating a watcher on "org.mpris*" will match "org.mpris.foo" "org.mpris.bar" and "org.mpris" itself. It will not match org.mprisasdf. Internally the argument match rules have been expanded from a single QStringList to a struct containing args and arg0namespace. This was done so that we can easily use argpath in match rules in the future. Change-Id: I55882ab603cc6ba478e8c0ea9a6800f6e483a50c Reviewed-by: Kai Uwe Broulik Reviewed-by: Thiago Macieira Reviewed-by: David Faure --- src/dbus/qdbusconnection_p.h | 20 ++- src/dbus/qdbusintegrator.cpp | 89 +++++++++--- src/dbus/qdbusservicewatcher.cpp | 11 ++ .../tst_qdbusservicewatcher.cpp | 137 +++++++++++++----- 4 files changed, 194 insertions(+), 63 deletions(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 444d4727fd9..84ce21092af 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -121,6 +121,15 @@ public: QSocketNotifier *write; }; + struct ArgMatchRules { + QStringList args; + QString arg0namespace; + bool operator==(const ArgMatchRules &other) const { + return args == other.args && + arg0namespace == other.arg0namespace; + } + }; + struct SignalHook { inline SignalHook() : obj(0), midx(-1) { } @@ -128,7 +137,7 @@ public: QObject* obj; int midx; QVector params; - QStringList argumentMatch; + ArgMatchRules argumentMatch; QByteArray matchRule; }; @@ -207,12 +216,19 @@ public: QDBusMessage sendWithReplyLocal(const QDBusMessage &message); QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, const char *returnMethod, const char *errorMethod,int timeout = -1); + bool connectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); bool disconnectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); + bool connectSignal(const QString &service, const QString &path, const QString& interface, + const QString &name, const ArgMatchRules &argumentMatch, const QString &signature, + QObject *receiver, const char *slot); + bool disconnectSignal(const QString &service, const QString &path, const QString& interface, + const QString &name, const ArgMatchRules &argumentMatch, const QString &signature, + QObject *receiver, const char *slot); void registerObject(const ObjectTreeNode *node); void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode); void connectRelay(const QString &service, @@ -332,7 +348,7 @@ public: static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, const QString &service, const QString &path, const QString &interface, const QString &name, - const QStringList &argMatch, + const ArgMatchRules &argMatch, QObject *receiver, const char *signal, int minMIdx, bool buildSignature); static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 03de5b00915..cee5c821c8b 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -338,7 +338,7 @@ void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnect static QByteArray buildMatchRule(const QString &service, const QString &objectPath, const QString &interface, - const QString &member, const QStringList &argMatch, const QString & /*signature*/) + const QString &member, const QDBusConnectionPrivate::ArgMatchRules &argMatch, const QString & /*signature*/) { QString result = QLatin1String("type='signal',"); QString keyValue = QLatin1String("%1='%2',"); @@ -353,11 +353,14 @@ static QByteArray buildMatchRule(const QString &service, result += keyValue.arg(QLatin1String("member"), member); // add the argument string-matching now - if (!argMatch.isEmpty()) { + if (!argMatch.args.isEmpty()) { keyValue = QLatin1String("arg%1='%2',"); - for (int i = 0; i < argMatch.count(); ++i) - if (!argMatch.at(i).isNull()) - result += keyValue.arg(i).arg(argMatch.at(i)); + for (int i = 0; i < argMatch.args.count(); ++i) + if (!argMatch.args.at(i).isNull()) + result += keyValue.arg(i).arg(argMatch.args.at(i)); + } + if (!argMatch.arg0namespace.isEmpty()) { + result += QStringLiteral("arg0namespace='%1',").arg(argMatch.arg0namespace); } result.chop(1); // remove ending comma @@ -456,21 +459,26 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro return 0; } -static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode) +static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode) { - QStringList matchArgs; - matchArgs << service; + QDBusConnectionPrivate::ArgMatchRules matchArgs; + if (service.endsWith(QLatin1Char('*'))) { + matchArgs.arg0namespace = service.chopped(1); + matchArgs.args << QString(); + } + else + matchArgs.args << service; switch (mode) { case QDBusServiceWatcher::WatchForOwnerChange: break; case QDBusServiceWatcher::WatchForRegistration: - matchArgs << QString::fromLatin1("", 0); + matchArgs.args << QString::fromLatin1("", 0); break; case QDBusServiceWatcher::WatchForUnregistration: - matchArgs << QString() << QString::fromLatin1("", 0); + matchArgs.args << QString() << QString::fromLatin1("", 0); break; } return matchArgs; @@ -1310,7 +1318,7 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, const QString &service, const QString &path, const QString &interface, const QString &name, - const QStringList &argMatch, + const ArgMatchRules &argMatch, QObject *receiver, const char *signal, int minMIdx, bool buildSignature) { @@ -1620,14 +1628,14 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage continue; if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty()) continue; - if (!hook.argumentMatch.isEmpty()) { + if (!hook.argumentMatch.args.isEmpty()) { const QVariantList arguments = msg.arguments(); - if (hook.argumentMatch.size() > arguments.size()) + if (hook.argumentMatch.args.size() > arguments.size()) continue; bool matched = true; - for (int i = 0; i < hook.argumentMatch.size(); ++i) { - const QString ¶m = hook.argumentMatch.at(i); + for (int i = 0; i < hook.argumentMatch.args.size(); ++i) { + const QString ¶m = hook.argumentMatch.args.at(i); if (param.isNull()) continue; // don't try to match against this if (param == arguments.at(i).toString()) @@ -1638,7 +1646,15 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage if (!matched) continue; } - + if (!hook.argumentMatch.arg0namespace.isEmpty()) { + const QVariantList arguments = msg.arguments(); + if (arguments.size() < 1) + continue; + const QString param = arguments.at(0).toString(); + if (param != hook.argumentMatch.arg0namespace + && !param.startsWith(hook.argumentMatch.arg0namespace + QLatin1Char('.'))) + continue; + } activateSignal(hook, msg); } } @@ -2180,10 +2196,21 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void * } } + bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot) +{ + ArgMatchRules rules; + rules.args = argumentMatch; + return connectSignal(service, path, interface, name, rules, signature, receiver, slot); +} + +bool QDBusConnectionPrivate::connectSignal(const QString &service, + const QString &path, const QString &interface, const QString &name, + const ArgMatchRules &argumentMatch, const QString &signature, + QObject *receiver, const char *slot) { // check the slot QDBusConnectionPrivate::SignalHook hook; @@ -2241,9 +2268,11 @@ bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; if (++data.refcount == 1) { // we need to watch for this service changing + ArgMatchRules rules; + rules.args << hook.service; q_dbus_bus_add_match(connection, buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + QDBusUtil::nameOwnerChanged(), rules, QString()), NULL); data.owner = getNameOwnerNoCache(hook.service); qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" @@ -2255,9 +2284,19 @@ bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook return true; } +bool QDBusConnectionPrivate::disconnectSignal(const QString &service, + const QString &path, const QString &interface, const QString &name, + const QStringList &argumentMatch, const QString &signature, + QObject *receiver, const char *slot) +{ + ArgMatchRules rules; + rules.args = argumentMatch; + return disconnectSignal(service, path, interface, name, rules, signature, receiver, slot); +} + bool QDBusConnectionPrivate::disconnectSignal(const QString &service, const QString &path, const QString &interface, const QString &name, - const QStringList &argumentMatch, const QString &signature, + const ArgMatchRules &argumentMatch, const QString &signature, QObject *receiver, const char *slot) { // check the slot @@ -2288,7 +2327,7 @@ bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHo entry.signature == hook.signature && entry.obj == hook.obj && entry.midx == hook.midx && - entry.argumentMatch == hook.argumentMatch) { + entry.argumentMatch.args == hook.argumentMatch.args) { // no need to compare the parameters if it's the same slot removeSignalHookNoLock(it); return true; // it was there @@ -2330,9 +2369,11 @@ QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it) if (sit != watchedServices.end()) { if (--sit.value().refcount == 0) { watchedServices.erase(sit); + ArgMatchRules rules; + rules.args << hook.service; q_dbus_bus_remove_match(connection, buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + QDBusUtil::nameOwnerChanged(), rules, QString()), NULL); } } @@ -2393,7 +2434,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, QByteArray sig; sig.append(QSIGNAL_CODE + '0'); sig.append(signal.methodSignature()); - if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig, + if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect @@ -2414,7 +2455,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, QByteArray sig; sig.append(QSIGNAL_CODE + '0'); sig.append(signal.methodSignature()); - if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig, + if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't disconnect @@ -2447,7 +2488,7 @@ bool QDBusConnectionPrivate::shouldWatchService(const QString &service) */ void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member) { - QStringList matchArgs = matchArgsForService(service, mode); + ArgMatchRules matchArgs = matchArgsForService(service, mode); connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), matchArgs, QString(), obj, member); } @@ -2462,7 +2503,7 @@ void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWa */ void QDBusConnectionPrivate::unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member) { - QStringList matchArgs = matchArgsForService(service, mode); + ArgMatchRules matchArgs = matchArgsForService(service, mode); disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), matchArgs, QString(), obj, member); } diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp index 0c2fb9118f9..b0bfe7254d4 100644 --- a/src/dbus/qdbusservicewatcher.cpp +++ b/src/dbus/qdbusservicewatcher.cpp @@ -139,6 +139,17 @@ void QDBusServiceWatcherPrivate::removeService(const QString &service) QDBusConnectionInterface::serviceOwnerChanged() signal because it allows one to receive only the signals for which the class is interested in. + Ending a service name with the character '*' will match all service names + within the specified namespace. + + For example "com.example.backend1*" will match + \list + \li com.example.backend1 + \li com.example.backend1.foo + \li com.example.backend1.foo.bar + \endlist + Substrings in the same domain will not be matched, i.e "com.example.backend12". + \sa QDBusConnection */ diff --git a/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp b/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp index b79f3ea5e34..1ba7ee51b11 100644 --- a/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp +++ b/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp @@ -34,22 +34,27 @@ class tst_QDBusServiceWatcher: public QObject { Q_OBJECT - QString serviceName; int testCounter; public: tst_QDBusServiceWatcher(); private slots: void initTestCase(); - void init(); - + void watchForCreation_data(); void watchForCreation(); + void watchForDisappearance_data(); void watchForDisappearance(); void watchForDisappearanceUniqueConnection(); + void watchForOwnerChange_data(); void watchForOwnerChange(); + void modeChange_data(); void modeChange(); void disconnectedConnection(); + void setConnection_data(); void setConnection(); + +private: + QString generateServiceName(); }; tst_QDBusServiceWatcher::tst_QDBusServiceWatcher() @@ -63,18 +68,45 @@ void tst_QDBusServiceWatcher::initTestCase() QVERIFY(con.isConnected()); } -void tst_QDBusServiceWatcher::init() +QString tst_QDBusServiceWatcher::generateServiceName() { + return "com.example.TestService" + QString::number(testCounter++); +} + +void tst_QDBusServiceWatcher::watchForCreation_data() { - // change the service name from test to test - serviceName = "com.example.TestService" + QString::number(testCounter++); + QTest::addColumn("watchedName"); + QTest::addColumn("registeredName"); + + //com.example.TestService5 matches com.example.TestService5 + QString name = generateServiceName(); + QTest::newRow("normal") << name << name; + + //com.example* matches com.example.TestService5 + name = generateServiceName(); + QTest::newRow("wildcard") << "com.example*" << name; + + //com.example.TestService5* matches com.example.TestService5 + name = generateServiceName(); + QTest::newRow("wildcard_exact") << name+"*" << name; + + //com.example.TestService5* matches com.example.TestService5.Foo + name = generateServiceName(); + QTest::newRow("wildcard_subdomain") << name+"*" << name + ".Foo"; + + //com.example.TestService5* matches com.example.TestService5.Foo.Bar + name = generateServiceName(); + QTest::newRow("wildcard_subsubdomain") << name+"*" << name + ".Foo.Bar"; } void tst_QDBusServiceWatcher::watchForCreation() { + QFETCH(QString, watchedName); + QFETCH(QString, registeredName); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); - QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration); + QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration); QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); @@ -82,18 +114,18 @@ void tst_QDBusServiceWatcher::watchForCreation() QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); // register a name - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spyR.count(), 1); - QCOMPARE(spyR.at(0).at(0).toString(), serviceName); + QCOMPARE(spyR.at(0).at(0).toString(), registeredName); QCOMPARE(spyU.count(), 0); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QVERIFY(spyO.at(0).at(1).toString().isEmpty()); QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); @@ -102,31 +134,39 @@ void tst_QDBusServiceWatcher::watchForCreation() spyO.clear(); // unregister it: - con.unregisterService(serviceName); + con.unregisterService(registeredName); // and register again - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spyR.count(), 1); - QCOMPARE(spyR.at(0).at(0).toString(), serviceName); + QCOMPARE(spyR.at(0).at(0).toString(), registeredName); QCOMPARE(spyU.count(), 0); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QVERIFY(spyO.at(0).at(1).toString().isEmpty()); QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); } +void tst_QDBusServiceWatcher::watchForDisappearance_data() +{ + tst_QDBusServiceWatcher::watchForCreation_data(); +} + void tst_QDBusServiceWatcher::watchForDisappearance() { + QFETCH(QString, watchedName); + QFETCH(QString, registeredName); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); - QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForUnregistration); + QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration); watcher.setObjectName("watcher for disappearance"); QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); @@ -135,10 +175,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance() QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop())); // register a name - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); // unregister it: - con.unregisterService(serviceName); + con.unregisterService(registeredName); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); @@ -146,10 +186,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance() QCOMPARE(spyR.count(), 0); QCOMPARE(spyU.count(), 1); - QCOMPARE(spyU.at(0).at(0).toString(), serviceName); + QCOMPARE(spyU.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); QVERIFY(spyO.at(0).at(2).toString().isEmpty()); } @@ -188,12 +228,20 @@ void tst_QDBusServiceWatcher::watchForDisappearanceUniqueConnection() QVERIFY(spyO.at(0).at(2).toString().isEmpty()); } +void tst_QDBusServiceWatcher::watchForOwnerChange_data() +{ + watchForCreation_data(); +} + void tst_QDBusServiceWatcher::watchForOwnerChange() { + QFETCH(QString, watchedName); + QFETCH(QString, registeredName); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); - QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForOwnerChange); + QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForOwnerChange); QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); @@ -201,18 +249,18 @@ void tst_QDBusServiceWatcher::watchForOwnerChange() QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); // register a name - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spyR.count(), 1); - QCOMPARE(spyR.at(0).at(0).toString(), serviceName); + QCOMPARE(spyR.at(0).at(0).toString(), registeredName); QCOMPARE(spyU.count(), 0); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QVERIFY(spyO.at(0).at(1).toString().isEmpty()); QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); @@ -221,35 +269,43 @@ void tst_QDBusServiceWatcher::watchForOwnerChange() spyO.clear(); // unregister it: - con.unregisterService(serviceName); + con.unregisterService(registeredName); // and register again - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spyR.count(), 1); - QCOMPARE(spyR.at(0).at(0).toString(), serviceName); + QCOMPARE(spyR.at(0).at(0).toString(), registeredName); QCOMPARE(spyU.count(), 1); - QCOMPARE(spyU.at(0).at(0).toString(), serviceName); + QCOMPARE(spyU.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.count(), 2); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); QVERIFY(spyO.at(0).at(2).toString().isEmpty()); - QCOMPARE(spyO.at(1).at(0).toString(), serviceName); + QCOMPARE(spyO.at(1).at(0).toString(), registeredName); QVERIFY(spyO.at(1).at(1).toString().isEmpty()); QCOMPARE(spyO.at(1).at(2).toString(), con.baseService()); } +void tst_QDBusServiceWatcher::modeChange_data() +{ + watchForCreation_data(); +} + void tst_QDBusServiceWatcher::modeChange() { + QFETCH(QString, watchedName); + QFETCH(QString, registeredName); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); - QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration); + QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration); QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); @@ -257,18 +313,18 @@ void tst_QDBusServiceWatcher::modeChange() QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); // register a name - QVERIFY(con.registerService(serviceName)); + QVERIFY(con.registerService(registeredName)); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(spyR.count(), 1); - QCOMPARE(spyR.at(0).at(0).toString(), serviceName); + QCOMPARE(spyR.at(0).at(0).toString(), registeredName); QCOMPARE(spyU.count(), 0); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QVERIFY(spyO.at(0).at(1).toString().isEmpty()); QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); @@ -279,7 +335,7 @@ void tst_QDBusServiceWatcher::modeChange() watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); // unregister it: - con.unregisterService(serviceName); + con.unregisterService(registeredName); QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(1); @@ -288,10 +344,10 @@ void tst_QDBusServiceWatcher::modeChange() QCOMPARE(spyR.count(), 0); QCOMPARE(spyU.count(), 1); - QCOMPARE(spyU.at(0).at(0).toString(), serviceName); + QCOMPARE(spyU.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.count(), 1); - QCOMPARE(spyO.at(0).at(0).toString(), serviceName); + QCOMPARE(spyO.at(0).at(0).toString(), registeredName); QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); QVERIFY(spyO.at(0).at(2).toString().isEmpty()); } @@ -301,7 +357,7 @@ void tst_QDBusServiceWatcher::disconnectedConnection() QDBusConnection con(""); QVERIFY(!con.isConnected()); - QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration); + QDBusServiceWatcher watcher(generateServiceName(), con, QDBusServiceWatcher::WatchForRegistration); watcher.addWatchedService("com.example.somethingelse"); watcher.addWatchedService("org.freedesktop.DBus"); @@ -311,8 +367,15 @@ void tst_QDBusServiceWatcher::disconnectedConnection() watcher.setWatchedServices(QStringList()); } +void tst_QDBusServiceWatcher::setConnection_data() +{ + QTest::addColumn("serviceName"); + QTest::newRow("normal") << generateServiceName(); +} + void tst_QDBusServiceWatcher::setConnection() { + QFETCH(QString, serviceName); // begin with a disconnected connection QDBusConnection con(""); QVERIFY(!con.isConnected());