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 <kde@privat.broulik.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
David Edmundson 2018-04-06 01:27:32 +01:00 committed by David Faure
parent fc88dd52a4
commit d761c62783
4 changed files with 194 additions and 63 deletions

View File

@ -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<int> 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 *);

View File

@ -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 &param = hook.argumentMatch.at(i);
for (int i = 0; i < hook.argumentMatch.args.size(); ++i) {
const QString &param = 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);
}

View File

@ -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
*/

View File

@ -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<QString>("watchedName");
QTest::addColumn<QString>("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<QString>("serviceName");
QTest::newRow("normal") << generateServiceName();
}
void tst_QDBusServiceWatcher::setConnection()
{
QFETCH(QString, serviceName);
// begin with a disconnected connection
QDBusConnection con("");
QVERIFY(!con.isConnected());