| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. |
| 4 | ** Copyright (C) 2016 Intel Corporation. |
| 5 | ** Contact: https://www.qt.io/licensing/ |
| 6 | ** |
| 7 | ** This file is part of the test suite of the Qt Toolkit. |
| 8 | ** |
| 9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| 10 | ** Commercial License Usage |
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 12 | ** accordance with the commercial license agreement provided with the |
| 13 | ** Software or, alternatively, in accordance with the terms contained in |
| 14 | ** a written agreement between you and The Qt Company. For licensing terms |
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 16 | ** information use the contact form at https://www.qt.io/contact-us. |
| 17 | ** |
| 18 | ** GNU General Public License Usage |
| 19 | ** Alternatively, this file may be used under the terms of the GNU |
| 20 | ** General Public License version 3 as published by the Free Software |
| 21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| 22 | ** included in the packaging of this file. Please review the following |
| 23 | ** information to ensure the GNU General Public License requirements will |
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| 25 | ** |
| 26 | ** $QT_END_LICENSE$ |
| 27 | ** |
| 28 | ****************************************************************************/ |
| 29 | |
| 30 | #include <QtDBus/QDBusServiceWatcher> |
| 31 | #include <QtDBus> |
| 32 | #include <QtTest> |
| 33 | |
| 34 | class tst_QDBusServiceWatcher: public QObject |
| 35 | { |
| 36 | Q_OBJECT |
| 37 | int testCounter; |
| 38 | public: |
| 39 | tst_QDBusServiceWatcher(); |
| 40 | |
| 41 | private slots: |
| 42 | void initTestCase(); |
| 43 | void watchForCreation_data(); |
| 44 | void watchForCreation(); |
| 45 | void watchForDisappearance_data(); |
| 46 | void watchForDisappearance(); |
| 47 | void watchForDisappearanceUniqueConnection(); |
| 48 | void watchForOwnerChange_data(); |
| 49 | void watchForOwnerChange(); |
| 50 | void modeChange_data(); |
| 51 | void modeChange(); |
| 52 | void disconnectedConnection(); |
| 53 | void setConnection_data(); |
| 54 | void setConnection(); |
| 55 | |
| 56 | private: |
| 57 | QString generateServiceName(); |
| 58 | }; |
| 59 | |
| 60 | tst_QDBusServiceWatcher::tst_QDBusServiceWatcher() |
| 61 | : testCounter(0) |
| 62 | { |
| 63 | } |
| 64 | |
| 65 | void tst_QDBusServiceWatcher::initTestCase() |
| 66 | { |
| 67 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 68 | QVERIFY(con.isConnected()); |
| 69 | } |
| 70 | |
| 71 | QString tst_QDBusServiceWatcher::generateServiceName() { |
| 72 | return "com.example.TestService" + QString::number(testCounter++); |
| 73 | } |
| 74 | |
| 75 | void tst_QDBusServiceWatcher::watchForCreation_data() |
| 76 | { |
| 77 | QTest::addColumn<QString>(name: "watchedName" ); |
| 78 | QTest::addColumn<QString>(name: "registeredName" ); |
| 79 | |
| 80 | //com.example.TestService5 matches com.example.TestService5 |
| 81 | QString name = generateServiceName(); |
| 82 | QTest::newRow(dataTag: "normal" ) << name << name; |
| 83 | |
| 84 | //com.example* matches com.example.TestService5 |
| 85 | name = generateServiceName(); |
| 86 | QTest::newRow(dataTag: "wildcard" ) << "com.example*" << name; |
| 87 | |
| 88 | //com.example.TestService5* matches com.example.TestService5 |
| 89 | name = generateServiceName(); |
| 90 | QTest::newRow(dataTag: "wildcard_exact" ) << name+"*" << name; |
| 91 | |
| 92 | //com.example.TestService5* matches com.example.TestService5.Foo |
| 93 | name = generateServiceName(); |
| 94 | QTest::newRow(dataTag: "wildcard_subdomain" ) << name+"*" << name + ".Foo" ; |
| 95 | |
| 96 | //com.example.TestService5* matches com.example.TestService5.Foo.Bar |
| 97 | name = generateServiceName(); |
| 98 | QTest::newRow(dataTag: "wildcard_subsubdomain" ) << name+"*" << name + ".Foo.Bar" ; |
| 99 | } |
| 100 | |
| 101 | void tst_QDBusServiceWatcher::watchForCreation() |
| 102 | { |
| 103 | QFETCH(QString, watchedName); |
| 104 | QFETCH(QString, registeredName); |
| 105 | |
| 106 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 107 | QVERIFY(con.isConnected()); |
| 108 | |
| 109 | QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration); |
| 110 | |
| 111 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 112 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 113 | QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString))); |
| 114 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); |
| 115 | |
| 116 | // register a name |
| 117 | QVERIFY(con.registerService(registeredName)); |
| 118 | |
| 119 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 120 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 121 | |
| 122 | QCOMPARE(spyR.count(), 1); |
| 123 | QCOMPARE(spyR.at(0).at(0).toString(), registeredName); |
| 124 | |
| 125 | QCOMPARE(spyU.count(), 0); |
| 126 | |
| 127 | QCOMPARE(spyO.count(), 1); |
| 128 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 129 | QVERIFY(spyO.at(0).at(1).toString().isEmpty()); |
| 130 | QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); |
| 131 | |
| 132 | spyR.clear(); |
| 133 | spyU.clear(); |
| 134 | spyO.clear(); |
| 135 | |
| 136 | // unregister it: |
| 137 | con.unregisterService(serviceName: registeredName); |
| 138 | |
| 139 | // and register again |
| 140 | QVERIFY(con.registerService(registeredName)); |
| 141 | |
| 142 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 143 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 144 | |
| 145 | QCOMPARE(spyR.count(), 1); |
| 146 | QCOMPARE(spyR.at(0).at(0).toString(), registeredName); |
| 147 | |
| 148 | QCOMPARE(spyU.count(), 0); |
| 149 | |
| 150 | QCOMPARE(spyO.count(), 1); |
| 151 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 152 | QVERIFY(spyO.at(0).at(1).toString().isEmpty()); |
| 153 | QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); |
| 154 | } |
| 155 | |
| 156 | void tst_QDBusServiceWatcher::watchForDisappearance_data() |
| 157 | { |
| 158 | tst_QDBusServiceWatcher::watchForCreation_data(); |
| 159 | } |
| 160 | |
| 161 | void tst_QDBusServiceWatcher::watchForDisappearance() |
| 162 | { |
| 163 | QFETCH(QString, watchedName); |
| 164 | QFETCH(QString, registeredName); |
| 165 | |
| 166 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 167 | QVERIFY(con.isConnected()); |
| 168 | |
| 169 | QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration); |
| 170 | watcher.setObjectName("watcher for disappearance" ); |
| 171 | |
| 172 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 173 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 174 | QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString))); |
| 175 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop())); |
| 176 | |
| 177 | // register a name |
| 178 | QVERIFY(con.registerService(registeredName)); |
| 179 | |
| 180 | // unregister it: |
| 181 | con.unregisterService(serviceName: registeredName); |
| 182 | |
| 183 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 184 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 185 | |
| 186 | QCOMPARE(spyR.count(), 0); |
| 187 | |
| 188 | QCOMPARE(spyU.count(), 1); |
| 189 | QCOMPARE(spyU.at(0).at(0).toString(), registeredName); |
| 190 | |
| 191 | QCOMPARE(spyO.count(), 1); |
| 192 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 193 | QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); |
| 194 | QVERIFY(spyO.at(0).at(2).toString().isEmpty()); |
| 195 | } |
| 196 | |
| 197 | void tst_QDBusServiceWatcher::watchForDisappearanceUniqueConnection() |
| 198 | { |
| 199 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 200 | QVERIFY(con.isConnected()); |
| 201 | |
| 202 | // second connection |
| 203 | QString watchedName = QDBusConnection::connectToBus(type: QDBusConnection::SessionBus, name: "session2" ).baseService(); |
| 204 | QVERIFY(!watchedName.isEmpty()); |
| 205 | |
| 206 | QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration); |
| 207 | watcher.setObjectName("watcher for disappearance" ); |
| 208 | |
| 209 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 210 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 211 | QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString))); |
| 212 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop())); |
| 213 | |
| 214 | // unregister it: |
| 215 | QDBusConnection::disconnectFromBus(name: "session2" ); |
| 216 | |
| 217 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 218 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 219 | |
| 220 | QCOMPARE(spyR.count(), 0); |
| 221 | |
| 222 | QCOMPARE(spyU.count(), 1); |
| 223 | QCOMPARE(spyU.at(0).at(0).toString(), watchedName); |
| 224 | |
| 225 | QCOMPARE(spyO.count(), 1); |
| 226 | QCOMPARE(spyO.at(0).at(0).toString(), watchedName); |
| 227 | QCOMPARE(spyO.at(0).at(1).toString(), watchedName); |
| 228 | QVERIFY(spyO.at(0).at(2).toString().isEmpty()); |
| 229 | } |
| 230 | |
| 231 | void tst_QDBusServiceWatcher::watchForOwnerChange_data() |
| 232 | { |
| 233 | watchForCreation_data(); |
| 234 | } |
| 235 | |
| 236 | void tst_QDBusServiceWatcher::watchForOwnerChange() |
| 237 | { |
| 238 | QFETCH(QString, watchedName); |
| 239 | QFETCH(QString, registeredName); |
| 240 | |
| 241 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 242 | QVERIFY(con.isConnected()); |
| 243 | |
| 244 | QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForOwnerChange); |
| 245 | |
| 246 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 247 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 248 | QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString))); |
| 249 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); |
| 250 | |
| 251 | // register a name |
| 252 | QVERIFY(con.registerService(registeredName)); |
| 253 | |
| 254 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 255 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 256 | |
| 257 | QCOMPARE(spyR.count(), 1); |
| 258 | QCOMPARE(spyR.at(0).at(0).toString(), registeredName); |
| 259 | |
| 260 | QCOMPARE(spyU.count(), 0); |
| 261 | |
| 262 | QCOMPARE(spyO.count(), 1); |
| 263 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 264 | QVERIFY(spyO.at(0).at(1).toString().isEmpty()); |
| 265 | QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); |
| 266 | |
| 267 | spyR.clear(); |
| 268 | spyU.clear(); |
| 269 | spyO.clear(); |
| 270 | |
| 271 | // unregister it: |
| 272 | con.unregisterService(serviceName: registeredName); |
| 273 | |
| 274 | // and register again |
| 275 | QVERIFY(con.registerService(registeredName)); |
| 276 | |
| 277 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 278 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 279 | |
| 280 | QCOMPARE(spyR.count(), 1); |
| 281 | QCOMPARE(spyR.at(0).at(0).toString(), registeredName); |
| 282 | |
| 283 | QCOMPARE(spyU.count(), 1); |
| 284 | QCOMPARE(spyU.at(0).at(0).toString(), registeredName); |
| 285 | |
| 286 | QCOMPARE(spyO.count(), 2); |
| 287 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 288 | QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); |
| 289 | QVERIFY(spyO.at(0).at(2).toString().isEmpty()); |
| 290 | QCOMPARE(spyO.at(1).at(0).toString(), registeredName); |
| 291 | QVERIFY(spyO.at(1).at(1).toString().isEmpty()); |
| 292 | QCOMPARE(spyO.at(1).at(2).toString(), con.baseService()); |
| 293 | } |
| 294 | |
| 295 | void tst_QDBusServiceWatcher::modeChange_data() |
| 296 | { |
| 297 | watchForCreation_data(); |
| 298 | } |
| 299 | |
| 300 | void tst_QDBusServiceWatcher::modeChange() |
| 301 | { |
| 302 | QFETCH(QString, watchedName); |
| 303 | QFETCH(QString, registeredName); |
| 304 | |
| 305 | QDBusConnection con = QDBusConnection::sessionBus(); |
| 306 | QVERIFY(con.isConnected()); |
| 307 | |
| 308 | QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration); |
| 309 | |
| 310 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 311 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 312 | QSignalSpy spyO(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString))); |
| 313 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop())); |
| 314 | |
| 315 | // register a name |
| 316 | QVERIFY(con.registerService(registeredName)); |
| 317 | |
| 318 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 319 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 320 | |
| 321 | QCOMPARE(spyR.count(), 1); |
| 322 | QCOMPARE(spyR.at(0).at(0).toString(), registeredName); |
| 323 | |
| 324 | QCOMPARE(spyU.count(), 0); |
| 325 | |
| 326 | QCOMPARE(spyO.count(), 1); |
| 327 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 328 | QVERIFY(spyO.at(0).at(1).toString().isEmpty()); |
| 329 | QCOMPARE(spyO.at(0).at(2).toString(), con.baseService()); |
| 330 | |
| 331 | spyR.clear(); |
| 332 | spyU.clear(); |
| 333 | spyO.clear(); |
| 334 | |
| 335 | watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); |
| 336 | |
| 337 | // unregister it: |
| 338 | con.unregisterService(serviceName: registeredName); |
| 339 | |
| 340 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop())); |
| 341 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 342 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 343 | |
| 344 | QCOMPARE(spyR.count(), 0); |
| 345 | |
| 346 | QCOMPARE(spyU.count(), 1); |
| 347 | QCOMPARE(spyU.at(0).at(0).toString(), registeredName); |
| 348 | |
| 349 | QCOMPARE(spyO.count(), 1); |
| 350 | QCOMPARE(spyO.at(0).at(0).toString(), registeredName); |
| 351 | QCOMPARE(spyO.at(0).at(1).toString(), con.baseService()); |
| 352 | QVERIFY(spyO.at(0).at(2).toString().isEmpty()); |
| 353 | } |
| 354 | |
| 355 | void tst_QDBusServiceWatcher::disconnectedConnection() |
| 356 | { |
| 357 | QDBusConnection con("" ); |
| 358 | QVERIFY(!con.isConnected()); |
| 359 | |
| 360 | QDBusServiceWatcher watcher(generateServiceName(), con, QDBusServiceWatcher::WatchForRegistration); |
| 361 | watcher.addWatchedService(newService: "com.example.somethingelse" ); |
| 362 | watcher.addWatchedService(newService: "org.freedesktop.DBus" ); |
| 363 | |
| 364 | watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); |
| 365 | watcher.setWatchMode(QDBusServiceWatcher::WatchForOwnerChange); |
| 366 | |
| 367 | watcher.setWatchedServices(QStringList()); |
| 368 | } |
| 369 | |
| 370 | void tst_QDBusServiceWatcher::setConnection_data() |
| 371 | { |
| 372 | QTest::addColumn<QString>(name: "serviceName" ); |
| 373 | QTest::newRow(dataTag: "normal" ) << generateServiceName(); |
| 374 | } |
| 375 | |
| 376 | void tst_QDBusServiceWatcher::setConnection() |
| 377 | { |
| 378 | QFETCH(QString, serviceName); |
| 379 | // begin with a disconnected connection |
| 380 | QDBusConnection con("" ); |
| 381 | QVERIFY(!con.isConnected()); |
| 382 | |
| 383 | QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration); |
| 384 | |
| 385 | QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString))); |
| 386 | QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString))); |
| 387 | QTestEventLoop::instance().connect(asender: &watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(exitLoop())); |
| 388 | |
| 389 | // move to the session bus |
| 390 | con = QDBusConnection::sessionBus(); |
| 391 | QVERIFY(con.isConnected()); |
| 392 | watcher.setConnection(con); |
| 393 | |
| 394 | // register a name |
| 395 | QVERIFY(con.registerService(serviceName)); |
| 396 | |
| 397 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 398 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 399 | |
| 400 | QCOMPARE(spyR.count(), 1); |
| 401 | QCOMPARE(spyR.at(0).at(0).toString(), serviceName); |
| 402 | QCOMPARE(spyU.count(), 0); |
| 403 | |
| 404 | // is the system bus available? |
| 405 | if (!QDBusConnection::systemBus().isConnected()) |
| 406 | return; |
| 407 | |
| 408 | // connect to the system bus and ask to watch that base service |
| 409 | QString watchedName = QDBusConnection::connectToBus(type: QDBusConnection::SystemBus, name: "system2" ).baseService(); |
| 410 | watcher.setWatchedServices(QStringList() << watchedName); |
| 411 | watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); |
| 412 | |
| 413 | // move to the system bus |
| 414 | watcher.setConnection(QDBusConnection::systemBus()); |
| 415 | spyR.clear(); |
| 416 | spyU.clear(); |
| 417 | |
| 418 | QDBusConnection::disconnectFromBus(name: "system2" ); |
| 419 | |
| 420 | QTestEventLoop::instance().enterLoop(secs: 1); |
| 421 | QVERIFY(!QTestEventLoop::instance().timeout()); |
| 422 | |
| 423 | QCOMPARE(spyR.count(), 0); |
| 424 | |
| 425 | QCOMPARE(spyU.count(), 1); |
| 426 | QCOMPARE(spyU.at(0).at(0).toString(), watchedName); |
| 427 | } |
| 428 | |
| 429 | QTEST_MAIN(tst_QDBusServiceWatcher) |
| 430 | #include "tst_qdbusservicewatcher.moc" |
| 431 | |