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:
parent
fc88dd52a4
commit
d761c62783
@ -121,6 +121,15 @@ public:
|
|||||||
QSocketNotifier *write;
|
QSocketNotifier *write;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ArgMatchRules {
|
||||||
|
QStringList args;
|
||||||
|
QString arg0namespace;
|
||||||
|
bool operator==(const ArgMatchRules &other) const {
|
||||||
|
return args == other.args &&
|
||||||
|
arg0namespace == other.arg0namespace;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SignalHook
|
struct SignalHook
|
||||||
{
|
{
|
||||||
inline SignalHook() : obj(0), midx(-1) { }
|
inline SignalHook() : obj(0), midx(-1) { }
|
||||||
@ -128,7 +137,7 @@ public:
|
|||||||
QObject* obj;
|
QObject* obj;
|
||||||
int midx;
|
int midx;
|
||||||
QVector<int> params;
|
QVector<int> params;
|
||||||
QStringList argumentMatch;
|
ArgMatchRules argumentMatch;
|
||||||
QByteArray matchRule;
|
QByteArray matchRule;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -207,12 +216,19 @@ public:
|
|||||||
QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
|
QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
|
||||||
QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
|
QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
|
||||||
const char *returnMethod, const char *errorMethod,int timeout = -1);
|
const char *returnMethod, const char *errorMethod,int timeout = -1);
|
||||||
|
|
||||||
bool connectSignal(const QString &service, const QString &path, const QString& interface,
|
bool connectSignal(const QString &service, const QString &path, const QString& interface,
|
||||||
const QString &name, const QStringList &argumentMatch, const QString &signature,
|
const QString &name, const QStringList &argumentMatch, const QString &signature,
|
||||||
QObject *receiver, const char *slot);
|
QObject *receiver, const char *slot);
|
||||||
bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
|
bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
|
||||||
const QString &name, const QStringList &argumentMatch, const QString &signature,
|
const QString &name, const QStringList &argumentMatch, const QString &signature,
|
||||||
QObject *receiver, const char *slot);
|
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 registerObject(const ObjectTreeNode *node);
|
||||||
void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode);
|
void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode);
|
||||||
void connectRelay(const QString &service,
|
void connectRelay(const QString &service,
|
||||||
@ -332,7 +348,7 @@ public:
|
|||||||
static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
|
static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
|
||||||
const QString &service,
|
const QString &service,
|
||||||
const QString &path, const QString &interface, const QString &name,
|
const QString &path, const QString &interface, const QString &name,
|
||||||
const QStringList &argMatch,
|
const ArgMatchRules &argMatch,
|
||||||
QObject *receiver, const char *signal, int minMIdx,
|
QObject *receiver, const char *signal, int minMIdx,
|
||||||
bool buildSignature);
|
bool buildSignature);
|
||||||
static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
|
static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
|
||||||
|
@ -338,7 +338,7 @@ void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnect
|
|||||||
|
|
||||||
static QByteArray buildMatchRule(const QString &service,
|
static QByteArray buildMatchRule(const QString &service,
|
||||||
const QString &objectPath, const QString &interface,
|
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 result = QLatin1String("type='signal',");
|
||||||
QString keyValue = QLatin1String("%1='%2',");
|
QString keyValue = QLatin1String("%1='%2',");
|
||||||
@ -353,11 +353,14 @@ static QByteArray buildMatchRule(const QString &service,
|
|||||||
result += keyValue.arg(QLatin1String("member"), member);
|
result += keyValue.arg(QLatin1String("member"), member);
|
||||||
|
|
||||||
// add the argument string-matching now
|
// add the argument string-matching now
|
||||||
if (!argMatch.isEmpty()) {
|
if (!argMatch.args.isEmpty()) {
|
||||||
keyValue = QLatin1String("arg%1='%2',");
|
keyValue = QLatin1String("arg%1='%2',");
|
||||||
for (int i = 0; i < argMatch.count(); ++i)
|
for (int i = 0; i < argMatch.args.count(); ++i)
|
||||||
if (!argMatch.at(i).isNull())
|
if (!argMatch.args.at(i).isNull())
|
||||||
result += keyValue.arg(i).arg(argMatch.at(i));
|
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
|
result.chop(1); // remove ending comma
|
||||||
@ -456,21 +459,26 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
|
static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
|
||||||
{
|
{
|
||||||
QStringList matchArgs;
|
QDBusConnectionPrivate::ArgMatchRules matchArgs;
|
||||||
matchArgs << service;
|
if (service.endsWith(QLatin1Char('*'))) {
|
||||||
|
matchArgs.arg0namespace = service.chopped(1);
|
||||||
|
matchArgs.args << QString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
matchArgs.args << service;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case QDBusServiceWatcher::WatchForOwnerChange:
|
case QDBusServiceWatcher::WatchForOwnerChange:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QDBusServiceWatcher::WatchForRegistration:
|
case QDBusServiceWatcher::WatchForRegistration:
|
||||||
matchArgs << QString::fromLatin1("", 0);
|
matchArgs.args << QString::fromLatin1("", 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QDBusServiceWatcher::WatchForUnregistration:
|
case QDBusServiceWatcher::WatchForUnregistration:
|
||||||
matchArgs << QString() << QString::fromLatin1("", 0);
|
matchArgs.args << QString() << QString::fromLatin1("", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return matchArgs;
|
return matchArgs;
|
||||||
@ -1310,7 +1318,7 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN
|
|||||||
bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
|
bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
|
||||||
const QString &service,
|
const QString &service,
|
||||||
const QString &path, const QString &interface, const QString &name,
|
const QString &path, const QString &interface, const QString &name,
|
||||||
const QStringList &argMatch,
|
const ArgMatchRules &argMatch,
|
||||||
QObject *receiver, const char *signal, int minMIdx,
|
QObject *receiver, const char *signal, int minMIdx,
|
||||||
bool buildSignature)
|
bool buildSignature)
|
||||||
{
|
{
|
||||||
@ -1620,14 +1628,14 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
|
|||||||
continue;
|
continue;
|
||||||
if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
|
if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
|
||||||
continue;
|
continue;
|
||||||
if (!hook.argumentMatch.isEmpty()) {
|
if (!hook.argumentMatch.args.isEmpty()) {
|
||||||
const QVariantList arguments = msg.arguments();
|
const QVariantList arguments = msg.arguments();
|
||||||
if (hook.argumentMatch.size() > arguments.size())
|
if (hook.argumentMatch.args.size() > arguments.size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool matched = true;
|
bool matched = true;
|
||||||
for (int i = 0; i < hook.argumentMatch.size(); ++i) {
|
for (int i = 0; i < hook.argumentMatch.args.size(); ++i) {
|
||||||
const QString ¶m = hook.argumentMatch.at(i);
|
const QString ¶m = hook.argumentMatch.args.at(i);
|
||||||
if (param.isNull())
|
if (param.isNull())
|
||||||
continue; // don't try to match against this
|
continue; // don't try to match against this
|
||||||
if (param == arguments.at(i).toString())
|
if (param == arguments.at(i).toString())
|
||||||
@ -1638,7 +1646,15 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
|
|||||||
if (!matched)
|
if (!matched)
|
||||||
continue;
|
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);
|
activateSignal(hook, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2180,10 +2196,21 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QDBusConnectionPrivate::connectSignal(const QString &service,
|
bool QDBusConnectionPrivate::connectSignal(const QString &service,
|
||||||
const QString &path, const QString &interface, const QString &name,
|
const QString &path, const QString &interface, const QString &name,
|
||||||
const QStringList &argumentMatch, const QString &signature,
|
const QStringList &argumentMatch, const QString &signature,
|
||||||
QObject *receiver, const char *slot)
|
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
|
// check the slot
|
||||||
QDBusConnectionPrivate::SignalHook hook;
|
QDBusConnectionPrivate::SignalHook hook;
|
||||||
@ -2241,9 +2268,11 @@ bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook
|
|||||||
WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
|
WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
|
||||||
if (++data.refcount == 1) {
|
if (++data.refcount == 1) {
|
||||||
// we need to watch for this service changing
|
// we need to watch for this service changing
|
||||||
|
ArgMatchRules rules;
|
||||||
|
rules.args << hook.service;
|
||||||
q_dbus_bus_add_match(connection,
|
q_dbus_bus_add_match(connection,
|
||||||
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
|
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
|
||||||
QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
|
QDBusUtil::nameOwnerChanged(), rules, QString()),
|
||||||
NULL);
|
NULL);
|
||||||
data.owner = getNameOwnerNoCache(hook.service);
|
data.owner = getNameOwnerNoCache(hook.service);
|
||||||
qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
|
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;
|
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,
|
bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
|
||||||
const QString &path, const QString &interface, const QString &name,
|
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)
|
QObject *receiver, const char *slot)
|
||||||
{
|
{
|
||||||
// check the slot
|
// check the slot
|
||||||
@ -2288,7 +2327,7 @@ bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHo
|
|||||||
entry.signature == hook.signature &&
|
entry.signature == hook.signature &&
|
||||||
entry.obj == hook.obj &&
|
entry.obj == hook.obj &&
|
||||||
entry.midx == hook.midx &&
|
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
|
// no need to compare the parameters if it's the same slot
|
||||||
removeSignalHookNoLock(it);
|
removeSignalHookNoLock(it);
|
||||||
return true; // it was there
|
return true; // it was there
|
||||||
@ -2330,9 +2369,11 @@ QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
|
|||||||
if (sit != watchedServices.end()) {
|
if (sit != watchedServices.end()) {
|
||||||
if (--sit.value().refcount == 0) {
|
if (--sit.value().refcount == 0) {
|
||||||
watchedServices.erase(sit);
|
watchedServices.erase(sit);
|
||||||
|
ArgMatchRules rules;
|
||||||
|
rules.args << hook.service;
|
||||||
q_dbus_bus_remove_match(connection,
|
q_dbus_bus_remove_match(connection,
|
||||||
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
|
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
|
||||||
QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
|
QDBusUtil::nameOwnerChanged(), rules, QString()),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2393,7 +2434,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service,
|
|||||||
QByteArray sig;
|
QByteArray sig;
|
||||||
sig.append(QSIGNAL_CODE + '0');
|
sig.append(QSIGNAL_CODE + '0');
|
||||||
sig.append(signal.methodSignature());
|
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))
|
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
|
||||||
return; // don't connect
|
return; // don't connect
|
||||||
|
|
||||||
@ -2414,7 +2455,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
|
|||||||
QByteArray sig;
|
QByteArray sig;
|
||||||
sig.append(QSIGNAL_CODE + '0');
|
sig.append(QSIGNAL_CODE + '0');
|
||||||
sig.append(signal.methodSignature());
|
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))
|
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
|
||||||
return; // don't disconnect
|
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)
|
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(),
|
connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||||
matchArgs, QString(), obj, member);
|
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)
|
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(),
|
disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
|
||||||
matchArgs, QString(), obj, member);
|
matchArgs, QString(), obj, member);
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,17 @@ void QDBusServiceWatcherPrivate::removeService(const QString &service)
|
|||||||
QDBusConnectionInterface::serviceOwnerChanged() signal because it allows
|
QDBusConnectionInterface::serviceOwnerChanged() signal because it allows
|
||||||
one to receive only the signals for which the class is interested in.
|
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
|
\sa QDBusConnection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -34,22 +34,27 @@
|
|||||||
class tst_QDBusServiceWatcher: public QObject
|
class tst_QDBusServiceWatcher: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QString serviceName;
|
|
||||||
int testCounter;
|
int testCounter;
|
||||||
public:
|
public:
|
||||||
tst_QDBusServiceWatcher();
|
tst_QDBusServiceWatcher();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
void init();
|
void watchForCreation_data();
|
||||||
|
|
||||||
void watchForCreation();
|
void watchForCreation();
|
||||||
|
void watchForDisappearance_data();
|
||||||
void watchForDisappearance();
|
void watchForDisappearance();
|
||||||
void watchForDisappearanceUniqueConnection();
|
void watchForDisappearanceUniqueConnection();
|
||||||
|
void watchForOwnerChange_data();
|
||||||
void watchForOwnerChange();
|
void watchForOwnerChange();
|
||||||
|
void modeChange_data();
|
||||||
void modeChange();
|
void modeChange();
|
||||||
void disconnectedConnection();
|
void disconnectedConnection();
|
||||||
|
void setConnection_data();
|
||||||
void setConnection();
|
void setConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString generateServiceName();
|
||||||
};
|
};
|
||||||
|
|
||||||
tst_QDBusServiceWatcher::tst_QDBusServiceWatcher()
|
tst_QDBusServiceWatcher::tst_QDBusServiceWatcher()
|
||||||
@ -63,18 +68,45 @@ void tst_QDBusServiceWatcher::initTestCase()
|
|||||||
QVERIFY(con.isConnected());
|
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
|
QTest::addColumn<QString>("watchedName");
|
||||||
serviceName = "com.example.TestService" + QString::number(testCounter++);
|
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()
|
void tst_QDBusServiceWatcher::watchForCreation()
|
||||||
{
|
{
|
||||||
|
QFETCH(QString, watchedName);
|
||||||
|
QFETCH(QString, registeredName);
|
||||||
|
|
||||||
QDBusConnection con = QDBusConnection::sessionBus();
|
QDBusConnection con = QDBusConnection::sessionBus();
|
||||||
QVERIFY(con.isConnected());
|
QVERIFY(con.isConnected());
|
||||||
|
|
||||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
|
QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration);
|
||||||
|
|
||||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||||
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
||||||
@ -82,18 +114,18 @@ void tst_QDBusServiceWatcher::watchForCreation()
|
|||||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
||||||
|
|
||||||
// register a name
|
// register a name
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
|
|
||||||
QCOMPARE(spyR.count(), 1);
|
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(spyU.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyO.count(), 1);
|
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());
|
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
|
||||||
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
||||||
|
|
||||||
@ -102,31 +134,39 @@ void tst_QDBusServiceWatcher::watchForCreation()
|
|||||||
spyO.clear();
|
spyO.clear();
|
||||||
|
|
||||||
// unregister it:
|
// unregister it:
|
||||||
con.unregisterService(serviceName);
|
con.unregisterService(registeredName);
|
||||||
|
|
||||||
// and register again
|
// and register again
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
|
|
||||||
QCOMPARE(spyR.count(), 1);
|
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(spyU.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyO.count(), 1);
|
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());
|
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
|
||||||
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QDBusServiceWatcher::watchForDisappearance_data()
|
||||||
|
{
|
||||||
|
tst_QDBusServiceWatcher::watchForCreation_data();
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QDBusServiceWatcher::watchForDisappearance()
|
void tst_QDBusServiceWatcher::watchForDisappearance()
|
||||||
{
|
{
|
||||||
|
QFETCH(QString, watchedName);
|
||||||
|
QFETCH(QString, registeredName);
|
||||||
|
|
||||||
QDBusConnection con = QDBusConnection::sessionBus();
|
QDBusConnection con = QDBusConnection::sessionBus();
|
||||||
QVERIFY(con.isConnected());
|
QVERIFY(con.isConnected());
|
||||||
|
|
||||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForUnregistration);
|
QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration);
|
||||||
watcher.setObjectName("watcher for disappearance");
|
watcher.setObjectName("watcher for disappearance");
|
||||||
|
|
||||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||||
@ -135,10 +175,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance()
|
|||||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
|
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
|
||||||
|
|
||||||
// register a name
|
// register a name
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
// unregister it:
|
// unregister it:
|
||||||
con.unregisterService(serviceName);
|
con.unregisterService(registeredName);
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
@ -146,10 +186,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance()
|
|||||||
QCOMPARE(spyR.count(), 0);
|
QCOMPARE(spyR.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyU.count(), 1);
|
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.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());
|
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
|
||||||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||||
}
|
}
|
||||||
@ -188,12 +228,20 @@ void tst_QDBusServiceWatcher::watchForDisappearanceUniqueConnection()
|
|||||||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QDBusServiceWatcher::watchForOwnerChange_data()
|
||||||
|
{
|
||||||
|
watchForCreation_data();
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QDBusServiceWatcher::watchForOwnerChange()
|
void tst_QDBusServiceWatcher::watchForOwnerChange()
|
||||||
{
|
{
|
||||||
|
QFETCH(QString, watchedName);
|
||||||
|
QFETCH(QString, registeredName);
|
||||||
|
|
||||||
QDBusConnection con = QDBusConnection::sessionBus();
|
QDBusConnection con = QDBusConnection::sessionBus();
|
||||||
QVERIFY(con.isConnected());
|
QVERIFY(con.isConnected());
|
||||||
|
|
||||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForOwnerChange);
|
QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForOwnerChange);
|
||||||
|
|
||||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||||
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
||||||
@ -201,18 +249,18 @@ void tst_QDBusServiceWatcher::watchForOwnerChange()
|
|||||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
||||||
|
|
||||||
// register a name
|
// register a name
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
|
|
||||||
QCOMPARE(spyR.count(), 1);
|
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(spyU.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyO.count(), 1);
|
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());
|
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
|
||||||
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
||||||
|
|
||||||
@ -221,35 +269,43 @@ void tst_QDBusServiceWatcher::watchForOwnerChange()
|
|||||||
spyO.clear();
|
spyO.clear();
|
||||||
|
|
||||||
// unregister it:
|
// unregister it:
|
||||||
con.unregisterService(serviceName);
|
con.unregisterService(registeredName);
|
||||||
|
|
||||||
// and register again
|
// and register again
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
|
|
||||||
QCOMPARE(spyR.count(), 1);
|
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.count(), 1);
|
||||||
QCOMPARE(spyU.at(0).at(0).toString(), serviceName);
|
QCOMPARE(spyU.at(0).at(0).toString(), registeredName);
|
||||||
|
|
||||||
QCOMPARE(spyO.count(), 2);
|
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());
|
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
|
||||||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
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());
|
QVERIFY(spyO.at(1).at(1).toString().isEmpty());
|
||||||
QCOMPARE(spyO.at(1).at(2).toString(), con.baseService());
|
QCOMPARE(spyO.at(1).at(2).toString(), con.baseService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QDBusServiceWatcher::modeChange_data()
|
||||||
|
{
|
||||||
|
watchForCreation_data();
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QDBusServiceWatcher::modeChange()
|
void tst_QDBusServiceWatcher::modeChange()
|
||||||
{
|
{
|
||||||
|
QFETCH(QString, watchedName);
|
||||||
|
QFETCH(QString, registeredName);
|
||||||
|
|
||||||
QDBusConnection con = QDBusConnection::sessionBus();
|
QDBusConnection con = QDBusConnection::sessionBus();
|
||||||
QVERIFY(con.isConnected());
|
QVERIFY(con.isConnected());
|
||||||
|
|
||||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
|
QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration);
|
||||||
|
|
||||||
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
|
||||||
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
|
||||||
@ -257,18 +313,18 @@ void tst_QDBusServiceWatcher::modeChange()
|
|||||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
|
||||||
|
|
||||||
// register a name
|
// register a name
|
||||||
QVERIFY(con.registerService(serviceName));
|
QVERIFY(con.registerService(registeredName));
|
||||||
|
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||||
|
|
||||||
QCOMPARE(spyR.count(), 1);
|
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(spyU.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyO.count(), 1);
|
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());
|
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
|
||||||
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
|
||||||
|
|
||||||
@ -279,7 +335,7 @@ void tst_QDBusServiceWatcher::modeChange()
|
|||||||
watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
||||||
|
|
||||||
// unregister it:
|
// unregister it:
|
||||||
con.unregisterService(serviceName);
|
con.unregisterService(registeredName);
|
||||||
|
|
||||||
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
|
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
|
||||||
QTestEventLoop::instance().enterLoop(1);
|
QTestEventLoop::instance().enterLoop(1);
|
||||||
@ -288,10 +344,10 @@ void tst_QDBusServiceWatcher::modeChange()
|
|||||||
QCOMPARE(spyR.count(), 0);
|
QCOMPARE(spyR.count(), 0);
|
||||||
|
|
||||||
QCOMPARE(spyU.count(), 1);
|
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.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());
|
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
|
||||||
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
|
||||||
}
|
}
|
||||||
@ -301,7 +357,7 @@ void tst_QDBusServiceWatcher::disconnectedConnection()
|
|||||||
QDBusConnection con("");
|
QDBusConnection con("");
|
||||||
QVERIFY(!con.isConnected());
|
QVERIFY(!con.isConnected());
|
||||||
|
|
||||||
QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
|
QDBusServiceWatcher watcher(generateServiceName(), con, QDBusServiceWatcher::WatchForRegistration);
|
||||||
watcher.addWatchedService("com.example.somethingelse");
|
watcher.addWatchedService("com.example.somethingelse");
|
||||||
watcher.addWatchedService("org.freedesktop.DBus");
|
watcher.addWatchedService("org.freedesktop.DBus");
|
||||||
|
|
||||||
@ -311,8 +367,15 @@ void tst_QDBusServiceWatcher::disconnectedConnection()
|
|||||||
watcher.setWatchedServices(QStringList());
|
watcher.setWatchedServices(QStringList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QDBusServiceWatcher::setConnection_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("serviceName");
|
||||||
|
QTest::newRow("normal") << generateServiceName();
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QDBusServiceWatcher::setConnection()
|
void tst_QDBusServiceWatcher::setConnection()
|
||||||
{
|
{
|
||||||
|
QFETCH(QString, serviceName);
|
||||||
// begin with a disconnected connection
|
// begin with a disconnected connection
|
||||||
QDBusConnection con("");
|
QDBusConnection con("");
|
||||||
QVERIFY(!con.isConnected());
|
QVERIFY(!con.isConnected());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user