1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28/* -*- C++ -*-
29 */
30
31#include <qcoreapplication.h>
32#include <qmetatype.h>
33#include <QtTest/QtTest>
34#include <QtCore/qvariant.h>
35#include <QtDBus/QtDBus>
36#include <QtDBus/private/qdbus_symbols_p.h>
37#include <qdebug.h>
38#include "../qdbusmarshall/common.h"
39#include "myobject.h"
40
41#define TEST_INTERFACE_NAME "org.qtproject.QtDBus.MyObject"
42#define TEST_SIGNAL_NAME "somethingHappened"
43
44static const char serviceName[] = "org.qtproject.autotests.qmyserver";
45static const char objectPath[] = "/org/qtproject/qmyserver";
46static const char *interfaceName = serviceName;
47
48int MyObject::callCount = 0;
49QVariantList MyObject::callArgs;
50
51class MyObjectUnknownType: public QObject
52{
53 Q_OBJECT
54 Q_CLASSINFO("D-Bus Interface", "org.qtproject.QtDBus.MyObject")
55 Q_CLASSINFO("D-Bus Introspection", ""
56" <interface name=\"org.qtproject.QtDBus.MyObjectUnknownTypes\" >\n"
57" <property access=\"readwrite\" type=\"~\" name=\"prop1\" />\n"
58" <signal name=\"somethingHappened\" >\n"
59" <arg direction=\"out\" type=\"~\" />\n"
60" </signal>\n"
61" <method name=\"ping\" >\n"
62" <arg direction=\"in\" type=\"~\" name=\"ping\" />\n"
63" <arg direction=\"out\" type=\"~\" name=\"ping\" />\n"
64" </method>\n"
65" <method name=\"regularMethod\" />\n"
66" </interface>\n"
67 "")
68};
69
70class Spy: public QObject
71{
72 Q_OBJECT
73public:
74 QString received;
75 int count;
76
77 Spy() : count(0)
78 { }
79
80public slots:
81 void spySlot(const QString& arg)
82 {
83 received = arg;
84 ++count;
85 }
86};
87
88class DerivedFromQDBusInterface: public QDBusInterface
89{
90 Q_OBJECT
91public:
92 DerivedFromQDBusInterface()
93 : QDBusInterface("com.example.Test", "/")
94 {}
95
96public slots:
97 void method() {}
98};
99
100// helper function
101void emitSignal(const QString &interface, const QString &name, const QString &arg)
102{
103 QDBusMessage msg = QDBusMessage::createSignal(path: "/", interface, name);
104 msg << arg;
105 QDBusConnection::sessionBus().send(message: msg);
106
107 QTest::qWait(ms: 1000);
108}
109
110void emitSignalPeer(const QString &interface, const QString &name, const QString &arg)
111{
112 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "emitSignal");
113 req << interface;
114 req << name;
115 req << arg;
116 QDBusConnection::sessionBus().send(message: req);
117
118 QTest::qWait(ms: 1000);
119}
120
121int callCountPeer()
122{
123 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "callCount");
124 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
125 return reply.arguments().at(i: 0).toInt();
126}
127
128QVariantList callArgsPeer()
129{
130 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "callArgs");
131 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
132 return qdbus_cast<QVariantList>(v: reply.arguments().at(i: 0));
133}
134
135void setProp1Peer(int val)
136{
137 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "setProp1");
138 req << val;
139 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
140}
141
142int prop1Peer()
143{
144 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "prop1");
145 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
146 return reply.arguments().at(i: 0).toInt();
147}
148
149void setComplexPropPeer(QList<int> val)
150{
151 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "setComplexProp");
152 req << QVariant::fromValue(value: val);
153 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
154}
155
156QList<int> complexPropPeer()
157{
158 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "complexProp");
159 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
160 return qdbus_cast<QList<int> >(v: reply.arguments().at(i: 0));
161}
162
163void resetPeer()
164{
165 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "reset");
166 QDBusConnection::sessionBus().call(message: req);
167}
168
169class tst_QDBusInterface: public QObject
170{
171 Q_OBJECT
172 MyObject obj;
173
174public slots:
175 void testServiceOwnerChanged(const QString &service)
176 {
177 if (service == "com.example.Test")
178 QTestEventLoop::instance().exitLoop();
179 }
180
181private slots:
182 void initTestCase();
183 void cleanupTestCase();
184
185 void notConnected();
186 void notValid();
187 void notValidDerived();
188 void invalidAfterServiceOwnerChanged();
189 void introspect();
190 void introspectUnknownTypes();
191 void introspectVirtualObject();
192 void callMethod();
193 void invokeMethod();
194 void invokeMethodWithReturn();
195 void invokeMethodWithMultiReturn();
196 void invokeMethodWithComplexReturn();
197
198 void introspectPeer();
199 void callMethodPeer();
200 void invokeMethodPeer();
201 void invokeMethodWithReturnPeer();
202 void invokeMethodWithMultiReturnPeer();
203 void invokeMethodWithComplexReturnPeer();
204
205 void signal();
206 void signalPeer();
207
208 void propertyRead();
209 void propertyWrite();
210 void complexPropertyRead();
211 void complexPropertyWrite();
212
213 void propertyReadPeer();
214 void propertyWritePeer();
215 void complexPropertyReadPeer();
216 void complexPropertyWritePeer();
217
218 void interactiveAuthorizationRequired();
219private:
220 QProcess proc;
221};
222
223class WaitForQMyServer: public QObject
224{
225 Q_OBJECT
226public:
227 WaitForQMyServer();
228 bool ok();
229public Q_SLOTS:
230 void ownerChange(const QString &name)
231 {
232 if (name == serviceName)
233 loop.quit();
234 }
235
236private:
237 QEventLoop loop;
238};
239
240WaitForQMyServer::WaitForQMyServer()
241{
242 QDBusConnection con = QDBusConnection::sessionBus();
243 if (!ok()) {
244 connect(asender: con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
245 SLOT(ownerChange(QString)));
246 QTimer::singleShot(msec: 2000, receiver: &loop, SLOT(quit()));
247 loop.exec();
248 }
249}
250
251bool WaitForQMyServer::ok()
252{
253 return QDBusConnection::sessionBus().isConnected() &&
254 QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName);
255}
256
257void tst_QDBusInterface::initTestCase()
258{
259 QDBusConnection con = QDBusConnection::sessionBus();
260 QVERIFY(con.isConnected());
261 QTest::qWait(ms: 500);
262
263 con.registerObject(path: "/", object: &obj, options: QDBusConnection::ExportAllProperties
264 | QDBusConnection::ExportAllSlots
265 | QDBusConnection::ExportAllInvokables);
266
267#ifdef Q_OS_WIN
268# define EXE ".exe"
269#else
270# define EXE ""
271#endif
272 proc.setProcessChannelMode(QProcess::ForwardedErrorChannel);
273 proc.start(QFINDTESTDATA("qmyserver/qmyserver" EXE));
274 QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString()));
275 QVERIFY(proc.waitForReadyRead());
276
277 WaitForQMyServer w;
278 QVERIFY(w.ok());
279 //QTest::qWait(2000);
280
281 // get peer server address
282 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "address");
283 QDBusMessage rpl = con.call(message: req);
284 QCOMPARE(rpl.type(), QDBusMessage::ReplyMessage);
285 QString address = rpl.arguments().at(i: 0).toString();
286
287 // connect to peer server
288 QDBusConnection peercon = QDBusConnection::connectToPeer(address, name: "peer");
289 QVERIFY(peercon.isConnected());
290
291 QDBusMessage req2 = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "waitForConnected");
292 QDBusMessage rpl2 = con.call(message: req2);
293 QCOMPARE(rpl2.type(), QDBusMessage::ReplyMessage);
294 QVERIFY2(rpl2.type() == QDBusMessage::ReplyMessage, rpl2.errorMessage().toLatin1());
295}
296
297void tst_QDBusInterface::cleanupTestCase()
298{
299 QDBusMessage msg = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "quit");
300 QDBusConnection::sessionBus().call(message: msg);
301 proc.waitForFinished(msecs: 200);
302 proc.close();
303}
304
305void tst_QDBusInterface::notConnected()
306{
307 QDBusConnection connection("");
308 QVERIFY(!connection.isConnected());
309
310 QDBusInterface interface("org.freedesktop.DBus", "/", "org.freedesktop.DBus",
311 connection);
312
313 QVERIFY(!interface.isValid());
314 QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
315}
316
317void tst_QDBusInterface::notValid()
318{
319 QDBusConnection connection("");
320 QVERIFY(!connection.isConnected());
321
322 QDBusInterface interface("com.example.Test", QString(), "org.example.Test",
323 connection);
324
325 QVERIFY(!interface.isValid());
326 QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
327}
328
329void tst_QDBusInterface::notValidDerived()
330{
331 DerivedFromQDBusInterface c;
332 QVERIFY(!c.isValid());
333 QMetaObject::invokeMethod(obj: &c, member: "method", type: Qt::DirectConnection);
334}
335
336void tst_QDBusInterface::invalidAfterServiceOwnerChanged()
337{
338 // this test is technically the same as tst_QDBusAbstractInterface::followSignal
339 QDBusConnection conn = QDBusConnection::sessionBus();
340 QDBusConnectionInterface *connIface = conn.interface();
341
342 QDBusInterface validInterface(conn.baseService(), "/");
343 QVERIFY(validInterface.isValid());
344 QDBusInterface invalidInterface("com.example.Test", "/");
345 QVERIFY(!invalidInterface.isValid());
346
347 QTestEventLoop::instance().connect(asender: connIface, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
348 SLOT(exitLoop()));
349 QCOMPARE(connIface->registerService("com.example.Test").value(), QDBusConnectionInterface::ServiceRegistered);
350
351 QTestEventLoop::instance().enterLoop(secs: 5);
352
353 QVERIFY(!QTestEventLoop::instance().timeout());
354 QVERIFY(invalidInterface.isValid());
355}
356
357void tst_QDBusInterface::introspect()
358{
359 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
360 TEST_INTERFACE_NAME);
361
362 const QMetaObject *mo = iface.metaObject();
363
364 QCOMPARE(mo->methodCount() - mo->methodOffset(), 7);
365 QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
366
367 QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2);
368 QVERIFY(mo->indexOfProperty("prop1") != -1);
369 QVERIFY(mo->indexOfProperty("complexProp") != -1);
370}
371
372void tst_QDBusInterface::introspectUnknownTypes()
373{
374 QDBusConnection con = QDBusConnection::sessionBus();
375 MyObjectUnknownType obj;
376 con.registerObject(path: "/unknownTypes", object: &obj, options: QDBusConnection::ExportAllContents);
377 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/unknownTypes"),
378 "org.qtproject.QtDBus.MyObjectUnknownTypes");
379
380 const QMetaObject *mo = iface.metaObject();
381 QVERIFY(mo->indexOfMethod("regularMethod()") != -1); // this is the control
382 QVERIFY(mo->indexOfMethod("somethingHappened(QDBusRawType<0x7e>*)") != -1);
383
384 QVERIFY(mo->indexOfMethod("ping(QDBusRawType<0x7e>*)") != -1);
385 int midx = mo->indexOfMethod(method: "ping(QDBusRawType<0x7e>*)");
386 QCOMPARE(mo->method(midx).typeName(), "QDBusRawType<0x7e>*");
387
388 QVERIFY(mo->indexOfProperty("prop1") != -1);
389 int pidx = mo->indexOfProperty(name: "prop1");
390 QCOMPARE(mo->property(pidx).typeName(), "QDBusRawType<0x7e>*");
391
392
393
394 QDBusMessage message = QDBusMessage::createMethodCall(destination: con.baseService(), path: "/unknownTypes", interface: "org.freedesktop.DBus.Introspectable", method: "Introspect");
395 QDBusMessage reply = con.call(message, mode: QDBus::Block, timeout: 5000);
396 qDebug() << "REPL: " << reply.arguments();
397
398}
399
400
401class VirtualObject: public QDBusVirtualObject
402{
403 Q_OBJECT
404public:
405 VirtualObject() :success(true) {}
406
407 QString introspect(const QString &path) const {
408 Q_ASSERT(QThread::currentThread() == thread());
409 if (path == "/some/path/superNode")
410 return "zitroneneis";
411 if (path == "/some/path/superNode/foo")
412 return " <interface name=\"org.qtproject.QtDBus.VirtualObject\">\n"
413 " <method name=\"klingeling\" />\n"
414 " </interface>\n" ;
415 return QString();
416 }
417
418 bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) {
419 Q_ASSERT(QThread::currentThread() == thread());
420 ++callCount;
421 lastMessage = message;
422
423 if (success) {
424 QDBusMessage reply = message.createReply(arguments: replyArguments);
425 connection.send(message: reply);
426 }
427 emit messageReceived(message);
428 return success;
429 }
430signals:
431 void messageReceived(const QDBusMessage &message) const;
432
433public:
434 mutable QDBusMessage lastMessage;
435 QVariantList replyArguments;
436 mutable int callCount;
437 bool success;
438};
439
440void tst_QDBusInterface::introspectVirtualObject()
441{
442 QDBusConnection con = QDBusConnection::sessionBus();
443 QVERIFY(con.isConnected());
444 VirtualObject obj;
445
446 obj.success = false;
447
448 QString path = "/some/path/superNode";
449 QVERIFY(con.registerVirtualObject(path, &obj, QDBusConnection::SubPath));
450
451 QDBusMessage message = QDBusMessage::createMethodCall(destination: con.baseService(), path, interface: "org.freedesktop.DBus.Introspectable", method: "Introspect");
452 QDBusMessage reply = con.call(message, mode: QDBus::Block, timeout: 5000);
453 QVERIFY(reply.arguments().at(0).toString().contains(
454 QRegExp("<node>.*zitroneneis.*<interface name=") ));
455
456 QDBusMessage message2 = QDBusMessage::createMethodCall(destination: con.baseService(), path: path + "/foo", interface: "org.freedesktop.DBus.Introspectable", method: "Introspect");
457 QDBusMessage reply2 = con.call(message: message2, mode: QDBus::Block, timeout: 5000);
458 QVERIFY(reply2.arguments().at(0).toString().contains(
459 QRegExp("<node>.*<interface name=\"org.qtproject.QtDBus.VirtualObject\">"
460 ".*<method name=\"klingeling\" />\n"
461 ".*</interface>.*<interface name=") ));
462}
463
464void tst_QDBusInterface::callMethod()
465{
466 QDBusConnection con = QDBusConnection::sessionBus();
467 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
468 TEST_INTERFACE_NAME);
469
470 MyObject::callCount = 0;
471
472 // call a SLOT method
473 QDBusMessage reply = iface.call(method: "ping", args: QVariant::fromValue(value: QDBusVariant("foo")));
474 QCOMPARE(MyObject::callCount, 1);
475 QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
476
477 // verify what the callee received
478 QCOMPARE(MyObject::callArgs.count(), 1);
479 QVariant v = MyObject::callArgs.at(i: 0);
480 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
481 QCOMPARE(dv.variant().type(), QVariant::String);
482 QCOMPARE(dv.variant().toString(), QString("foo"));
483
484 // verify reply
485 QCOMPARE(reply.arguments().count(), 1);
486 v = reply.arguments().at(i: 0);
487 dv = qdbus_cast<QDBusVariant>(v);
488 QCOMPARE(dv.variant().type(), QVariant::String);
489 QCOMPARE(dv.variant().toString(), QString("foo"));
490
491 // call an INVOKABLE method
492 reply = iface.call(method: "ping_invokable", args: QVariant::fromValue(value: QDBusVariant("bar")));
493 QCOMPARE(MyObject::callCount, 2);
494 QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
495
496 // verify what the callee received
497 QCOMPARE(MyObject::callArgs.count(), 1);
498 v = MyObject::callArgs.at(i: 0);
499 dv = qdbus_cast<QDBusVariant>(v);
500 QCOMPARE(dv.variant().type(), QVariant::String);
501 QCOMPARE(dv.variant().toString(), QString("bar"));
502
503 // verify reply
504 QCOMPARE(reply.arguments().count(), 1);
505 v = reply.arguments().at(i: 0);
506 dv = qdbus_cast<QDBusVariant>(v);
507 QCOMPARE(dv.variant().type(), QVariant::String);
508 QCOMPARE(dv.variant().toString(), QString("bar"));
509}
510
511void tst_QDBusInterface::invokeMethod()
512{
513 QDBusConnection con = QDBusConnection::sessionBus();
514 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
515 TEST_INTERFACE_NAME);
516
517 MyObject::callCount = 0;
518
519 // make the SLOT call without a return type
520 QDBusVariant arg("foo");
521 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg)));
522 QCOMPARE(MyObject::callCount, 1);
523
524 // verify what the callee received
525 QCOMPARE(MyObject::callArgs.count(), 1);
526 QVariant v = MyObject::callArgs.at(i: 0);
527 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
528 QCOMPARE(dv.variant().type(), QVariant::String);
529 QCOMPARE(dv.variant().toString(), QString("foo"));
530
531 // make the INVOKABLE call without a return type
532 QDBusVariant arg2("bar");
533 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2)));
534 QCOMPARE(MyObject::callCount, 2);
535
536 // verify what the callee received
537 QCOMPARE(MyObject::callArgs.count(), 1);
538 v = MyObject::callArgs.at(i: 0);
539 dv = qdbus_cast<QDBusVariant>(v);
540 QCOMPARE(dv.variant().type(), QVariant::String);
541 QCOMPARE(dv.variant().toString(), QString("bar"));
542}
543
544void tst_QDBusInterface::invokeMethodWithReturn()
545{
546 QDBusConnection con = QDBusConnection::sessionBus();
547 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
548 TEST_INTERFACE_NAME);
549
550 MyObject::callCount = 0;
551 QDBusVariant retArg;
552
553 // make the SLOT call without a return type
554 QDBusVariant arg("foo");
555 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg)));
556 QCOMPARE(MyObject::callCount, 1);
557
558 // verify what the callee received
559 QCOMPARE(MyObject::callArgs.count(), 1);
560 QVariant v = MyObject::callArgs.at(i: 0);
561 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
562 QCOMPARE(dv.variant().type(), QVariant::String);
563 QCOMPARE(dv.variant().toString(), arg.variant().toString());
564
565 // verify that we got the reply as expected
566 QCOMPARE(retArg.variant(), arg.variant());
567
568 // make the INVOKABLE call without a return type
569 QDBusVariant arg2("bar");
570 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2)));
571 QCOMPARE(MyObject::callCount, 2);
572
573 // verify what the callee received
574 QCOMPARE(MyObject::callArgs.count(), 1);
575 v = MyObject::callArgs.at(i: 0);
576 dv = qdbus_cast<QDBusVariant>(v);
577 QCOMPARE(dv.variant().type(), QVariant::String);
578 QCOMPARE(dv.variant().toString(), arg2.variant().toString());
579
580 // verify that we got the reply as expected
581 QCOMPARE(retArg.variant(), arg2.variant());
582}
583
584void tst_QDBusInterface::invokeMethodWithMultiReturn()
585{
586 QDBusConnection con = QDBusConnection::sessionBus();
587 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
588 TEST_INTERFACE_NAME);
589
590 MyObject::callCount = 0;
591 QDBusVariant retArg, retArg2;
592
593 // make the SLOT call without a return type
594 QDBusVariant arg("foo"), arg2("bar");
595 QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
596 Q_RETURN_ARG(QDBusVariant, retArg),
597 Q_ARG(QDBusVariant, arg),
598 Q_ARG(QDBusVariant, arg2),
599 Q_ARG(QDBusVariant&, retArg2)));
600 QCOMPARE(MyObject::callCount, 1);
601
602 // verify what the callee received
603 QCOMPARE(MyObject::callArgs.count(), 2);
604 QVariant v = MyObject::callArgs.at(i: 0);
605 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
606 QCOMPARE(dv.variant().type(), QVariant::String);
607 QCOMPARE(dv.variant().toString(), arg.variant().toString());
608
609 v = MyObject::callArgs.at(i: 1);
610 dv = qdbus_cast<QDBusVariant>(v);
611 QCOMPARE(dv.variant().type(), QVariant::String);
612 QCOMPARE(dv.variant().toString(), arg2.variant().toString());
613
614 // verify that we got the replies as expected
615 QCOMPARE(retArg.variant(), arg.variant());
616 QCOMPARE(retArg2.variant(), arg2.variant());
617
618 // make the INVOKABLE call without a return type
619 QDBusVariant arg3("hello"), arg4("world");
620 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable",
621 Q_RETURN_ARG(QDBusVariant, retArg),
622 Q_ARG(QDBusVariant, arg3),
623 Q_ARG(QDBusVariant, arg4),
624 Q_ARG(QDBusVariant&, retArg2)));
625 QCOMPARE(MyObject::callCount, 2);
626
627 // verify what the callee received
628 QCOMPARE(MyObject::callArgs.count(), 2);
629 v = MyObject::callArgs.at(i: 0);
630 dv = qdbus_cast<QDBusVariant>(v);
631 QCOMPARE(dv.variant().type(), QVariant::String);
632 QCOMPARE(dv.variant().toString(), arg3.variant().toString());
633
634 v = MyObject::callArgs.at(i: 1);
635 dv = qdbus_cast<QDBusVariant>(v);
636 QCOMPARE(dv.variant().type(), QVariant::String);
637 QCOMPARE(dv.variant().toString(), arg4.variant().toString());
638
639 // verify that we got the replies as expected
640 QCOMPARE(retArg.variant(), arg3.variant());
641 QCOMPARE(retArg2.variant(), arg4.variant());
642}
643
644void tst_QDBusInterface::invokeMethodWithComplexReturn()
645{
646 QDBusConnection con = QDBusConnection::sessionBus();
647 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
648 TEST_INTERFACE_NAME);
649
650 MyObject::callCount = 0;
651 QList<int> retArg;
652
653 // make the SLOT call without a return type
654 QList<int> arg = QList<int>() << 42 << -47;
655 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg)));
656 QCOMPARE(MyObject::callCount, 1);
657
658 // verify what the callee received
659 QCOMPARE(MyObject::callArgs.count(), 1);
660 QVariant v = MyObject::callArgs.at(i: 0);
661 QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
662 QCOMPARE(qdbus_cast<QList<int> >(v), arg);
663
664 // verify that we got the reply as expected
665 QCOMPARE(retArg, arg);
666
667 // make the INVOKABLE call without a return type
668 QList<int> arg2 = QList<int>() << 24 << -74;
669 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2)));
670 QCOMPARE(MyObject::callCount, 2);
671
672 // verify what the callee received
673 QCOMPARE(MyObject::callArgs.count(), 1);
674 v = MyObject::callArgs.at(i: 0);
675 QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
676 QCOMPARE(qdbus_cast<QList<int> >(v), arg2);
677
678 // verify that we got the reply as expected
679 QCOMPARE(retArg, arg2);
680}
681
682void tst_QDBusInterface::introspectPeer()
683{
684 QDBusConnection con("peer");
685 QDBusInterface iface(QString(), QLatin1String("/"),
686 TEST_INTERFACE_NAME, con);
687
688 const QMetaObject *mo = iface.metaObject();
689
690 QCOMPARE(mo->methodCount() - mo->methodOffset(), 7);
691 QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
692
693 QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2);
694 QVERIFY(mo->indexOfProperty("prop1") != -1);
695 QVERIFY(mo->indexOfProperty("complexProp") != -1);
696}
697
698void tst_QDBusInterface::callMethodPeer()
699{
700 QDBusConnection con("peer");
701 QDBusInterface iface(QString(), QLatin1String("/"),
702 TEST_INTERFACE_NAME, con);
703
704 resetPeer();
705
706 // call a SLOT method
707 QDBusMessage reply = iface.call(method: "ping", args: QVariant::fromValue(value: QDBusVariant("foo")));
708 QCOMPARE(callCountPeer(), 1);
709 QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
710
711 // verify what the callee received
712 QVariantList callArgs = callArgsPeer();
713 QCOMPARE(callArgs.count(), 1);
714 QVariant v = callArgs.at(i: 0);
715 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
716 QCOMPARE(dv.variant().type(), QVariant::String);
717 QCOMPARE(dv.variant().toString(), QString("foo"));
718
719 // verify reply
720 QCOMPARE(reply.arguments().count(), 1);
721 v = reply.arguments().at(i: 0);
722 dv = qdbus_cast<QDBusVariant>(v);
723 QCOMPARE(dv.variant().type(), QVariant::String);
724 QCOMPARE(dv.variant().toString(), QString("foo"));
725
726 // call an INVOKABLE method
727 reply = iface.call(method: "ping_invokable", args: QVariant::fromValue(value: QDBusVariant("bar")));
728 QCOMPARE(callCountPeer(), 2);
729 QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
730
731 // verify what the callee received
732 callArgs = callArgsPeer();
733 QCOMPARE(callArgs.count(), 1);
734 v = callArgs.at(i: 0);
735 dv = qdbus_cast<QDBusVariant>(v);
736 QCOMPARE(dv.variant().type(), QVariant::String);
737 QCOMPARE(dv.variant().toString(), QString("bar"));
738
739 // verify reply
740 QCOMPARE(reply.arguments().count(), 1);
741 v = reply.arguments().at(i: 0);
742 dv = qdbus_cast<QDBusVariant>(v);
743 QCOMPARE(dv.variant().type(), QVariant::String);
744 QCOMPARE(dv.variant().toString(), QString("bar"));
745}
746
747void tst_QDBusInterface::invokeMethodPeer()
748{
749 QDBusConnection con("peer");
750 QDBusInterface iface(QString(), QLatin1String("/"),
751 TEST_INTERFACE_NAME, con);
752
753 resetPeer();
754
755 // make the SLOT call without a return type
756 QDBusVariant arg("foo");
757 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg)));
758 QCOMPARE(callCountPeer(), 1);
759
760 // verify what the callee received
761 QVariantList callArgs = callArgsPeer();
762 QCOMPARE(callArgs.count(), 1);
763 QVariant v = callArgs.at(i: 0);
764 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
765 QCOMPARE(dv.variant().type(), QVariant::String);
766 QCOMPARE(dv.variant().toString(), QString("foo"));
767
768 // make the INVOKABLE call without a return type
769 QDBusVariant arg2("bar");
770 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2)));
771 QCOMPARE(callCountPeer(), 2);
772
773 // verify what the callee received
774 callArgs = callArgsPeer();
775 QCOMPARE(callArgs.count(), 1);
776 v = callArgs.at(i: 0);
777 dv = qdbus_cast<QDBusVariant>(v);
778 QCOMPARE(dv.variant().type(), QVariant::String);
779 QCOMPARE(dv.variant().toString(), QString("bar"));
780}
781
782void tst_QDBusInterface::invokeMethodWithReturnPeer()
783{
784 QDBusConnection con("peer");
785 QDBusInterface iface(QString(), QLatin1String("/"),
786 TEST_INTERFACE_NAME, con);
787
788 resetPeer();
789 QDBusVariant retArg;
790
791 // make the SLOT call without a return type
792 QDBusVariant arg("foo");
793 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg)));
794 QCOMPARE(callCountPeer(), 1);
795
796 // verify what the callee received
797 QVariantList callArgs = callArgsPeer();
798 QCOMPARE(callArgs.count(), 1);
799 QVariant v = callArgs.at(i: 0);
800 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
801 QCOMPARE(dv.variant().type(), QVariant::String);
802 QCOMPARE(dv.variant().toString(), arg.variant().toString());
803
804 // verify that we got the reply as expected
805 QCOMPARE(retArg.variant(), arg.variant());
806
807 // make the INVOKABLE call without a return type
808 QDBusVariant arg2("bar");
809 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2)));
810 QCOMPARE(callCountPeer(), 2);
811
812 // verify what the callee received
813 callArgs = callArgsPeer();
814 QCOMPARE(callArgs.count(), 1);
815 v = callArgs.at(i: 0);
816 dv = qdbus_cast<QDBusVariant>(v);
817 QCOMPARE(dv.variant().type(), QVariant::String);
818 QCOMPARE(dv.variant().toString(), arg2.variant().toString());
819
820 // verify that we got the reply as expected
821 QCOMPARE(retArg.variant(), arg2.variant());
822}
823
824void tst_QDBusInterface::invokeMethodWithMultiReturnPeer()
825{
826 QDBusConnection con("peer");
827 QDBusInterface iface(QString(), QLatin1String("/"),
828 TEST_INTERFACE_NAME, con);
829
830 resetPeer();
831 QDBusVariant retArg, retArg2;
832
833 // make the SLOT call without a return type
834 QDBusVariant arg("foo"), arg2("bar");
835 QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
836 Q_RETURN_ARG(QDBusVariant, retArg),
837 Q_ARG(QDBusVariant, arg),
838 Q_ARG(QDBusVariant, arg2),
839 Q_ARG(QDBusVariant&, retArg2)));
840 QCOMPARE(callCountPeer(), 1);
841
842 // verify what the callee received
843 QVariantList callArgs = callArgsPeer();
844 QCOMPARE(callArgs.count(), 2);
845 QVariant v = callArgs.at(i: 0);
846 QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
847 QCOMPARE(dv.variant().type(), QVariant::String);
848 QCOMPARE(dv.variant().toString(), arg.variant().toString());
849
850 v = callArgs.at(i: 1);
851 dv = qdbus_cast<QDBusVariant>(v);
852 QCOMPARE(dv.variant().type(), QVariant::String);
853 QCOMPARE(dv.variant().toString(), arg2.variant().toString());
854
855 // verify that we got the replies as expected
856 QCOMPARE(retArg.variant(), arg.variant());
857 QCOMPARE(retArg2.variant(), arg2.variant());
858
859 // make the INVOKABLE call without a return type
860 QDBusVariant arg3("hello"), arg4("world");
861 QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable",
862 Q_RETURN_ARG(QDBusVariant, retArg),
863 Q_ARG(QDBusVariant, arg3),
864 Q_ARG(QDBusVariant, arg4),
865 Q_ARG(QDBusVariant&, retArg2)));
866 QCOMPARE(callCountPeer(), 2);
867
868 // verify what the callee received
869 callArgs = callArgsPeer();
870 QCOMPARE(callArgs.count(), 2);
871 v = callArgs.at(i: 0);
872 dv = qdbus_cast<QDBusVariant>(v);
873 QCOMPARE(dv.variant().type(), QVariant::String);
874 QCOMPARE(dv.variant().toString(), arg3.variant().toString());
875
876 v = callArgs.at(i: 1);
877 dv = qdbus_cast<QDBusVariant>(v);
878 QCOMPARE(dv.variant().type(), QVariant::String);
879 QCOMPARE(dv.variant().toString(), arg4.variant().toString());
880
881 // verify that we got the replies as expected
882 QCOMPARE(retArg.variant(), arg3.variant());
883 QCOMPARE(retArg2.variant(), arg4.variant());
884}
885
886void tst_QDBusInterface::invokeMethodWithComplexReturnPeer()
887{
888 QDBusConnection con("peer");
889 QDBusInterface iface(QString(), QLatin1String("/"),
890 TEST_INTERFACE_NAME, con);
891
892 resetPeer();
893 QList<int> retArg;
894
895 // make the SLOT call without a return type
896 QList<int> arg = QList<int>() << 42 << -47;
897 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg)));
898 QCOMPARE(callCountPeer(), 1);
899
900 // verify what the callee received
901 QVariantList callArgs = callArgsPeer();
902 QCOMPARE(callArgs.count(), 1);
903 QVariant v = callArgs.at(i: 0);
904 QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
905 QCOMPARE(qdbus_cast<QList<int> >(v), arg);
906
907 // verify that we got the reply as expected
908 QCOMPARE(retArg, arg);
909
910 // make the INVOKABLE call without a return type
911 QList<int> arg2 = QList<int>() << 24 << -74;
912 QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2)));
913 QCOMPARE(callCountPeer(), 2);
914
915 // verify what the callee received
916 callArgs = callArgsPeer();
917 QCOMPARE(callArgs.count(), 1);
918 v = callArgs.at(i: 0);
919 QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
920 QCOMPARE(qdbus_cast<QList<int> >(v), arg2);
921
922 // verify that we got the reply as expected
923 QCOMPARE(retArg, arg2);
924}
925
926void tst_QDBusInterface::signal()
927{
928 QDBusConnection con = QDBusConnection::sessionBus();
929 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
930 TEST_INTERFACE_NAME);
931
932 QString arg = "So long and thanks for all the fish";
933 {
934 Spy spy;
935 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
936
937 emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
938 QCOMPARE(spy.count, 1);
939 QCOMPARE(spy.received, arg);
940 }
941
942 QDBusInterface iface2(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
943 TEST_INTERFACE_NAME);
944 {
945 Spy spy;
946 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
947 spy.connect(asender: &iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
948
949 emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
950 QCOMPARE(spy.count, 2);
951 QCOMPARE(spy.received, arg);
952 }
953
954 {
955 Spy spy, spy2;
956 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
957 spy2.connect(asender: &iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
958
959 emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
960 QCOMPARE(spy.count, 1);
961 QCOMPARE(spy.received, arg);
962 QCOMPARE(spy2.count, 1);
963 QCOMPARE(spy2.received, arg);
964 }
965}
966
967void tst_QDBusInterface::signalPeer()
968{
969 QDBusConnection con("peer");
970 QDBusInterface iface(QString(), QLatin1String("/"),
971 TEST_INTERFACE_NAME, con);
972
973 QString arg = "So long and thanks for all the fish";
974 {
975 Spy spy;
976 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
977
978 emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
979 QCOMPARE(spy.count, 1);
980 QCOMPARE(spy.received, arg);
981 }
982
983 QDBusInterface iface2(QString(), QLatin1String("/"),
984 TEST_INTERFACE_NAME, con);
985 {
986 Spy spy;
987 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
988 spy.connect(asender: &iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
989
990 emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
991 QCOMPARE(spy.count, 2);
992 QCOMPARE(spy.received, arg);
993 }
994
995 {
996 Spy spy, spy2;
997 spy.connect(asender: &iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
998 spy2.connect(asender: &iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
999
1000 emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
1001 QCOMPARE(spy.count, 1);
1002 QCOMPARE(spy.received, arg);
1003 QCOMPARE(spy2.count, 1);
1004 QCOMPARE(spy2.received, arg);
1005 }
1006}
1007
1008void tst_QDBusInterface::propertyRead()
1009{
1010 QDBusConnection con = QDBusConnection::sessionBus();
1011 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
1012 TEST_INTERFACE_NAME);
1013
1014 int arg = obj.m_prop1 = 42;
1015 MyObject::callCount = 0;
1016
1017 QVariant v = iface.property(name: "prop1");
1018 QVERIFY(v.isValid());
1019 QCOMPARE(v.userType(), int(QVariant::Int));
1020 QCOMPARE(v.toInt(), arg);
1021 QCOMPARE(MyObject::callCount, 1);
1022}
1023
1024void tst_QDBusInterface::propertyWrite()
1025{
1026 QDBusConnection con = QDBusConnection::sessionBus();
1027 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
1028 TEST_INTERFACE_NAME);
1029
1030 int arg = 42;
1031 obj.m_prop1 = 0;
1032 MyObject::callCount = 0;
1033
1034 QVERIFY(iface.setProperty("prop1", arg));
1035 QCOMPARE(MyObject::callCount, 1);
1036 QCOMPARE(obj.m_prop1, arg);
1037}
1038
1039void tst_QDBusInterface::complexPropertyRead()
1040{
1041 QDBusConnection con = QDBusConnection::sessionBus();
1042 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
1043 TEST_INTERFACE_NAME);
1044
1045 QList<int> arg = obj.m_complexProp = QList<int>() << 42 << -47;
1046 MyObject::callCount = 0;
1047
1048 QVariant v = iface.property(name: "complexProp");
1049 QVERIFY(v.isValid());
1050 QCOMPARE(v.userType(), qMetaTypeId<QList<int> >());
1051 QCOMPARE(v.value<QList<int> >(), arg);
1052 QCOMPARE(MyObject::callCount, 1);
1053}
1054
1055void tst_QDBusInterface::complexPropertyWrite()
1056{
1057 QDBusConnection con = QDBusConnection::sessionBus();
1058 QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
1059 TEST_INTERFACE_NAME);
1060
1061 QList<int> arg = QList<int>() << -47 << 42;
1062 obj.m_complexProp.clear();
1063 MyObject::callCount = 0;
1064
1065 QVERIFY(iface.setProperty("complexProp", QVariant::fromValue(arg)));
1066 QCOMPARE(MyObject::callCount, 1);
1067 QCOMPARE(obj.m_complexProp, arg);
1068}
1069
1070void tst_QDBusInterface::propertyReadPeer()
1071{
1072 QDBusConnection con("peer");
1073 QDBusInterface iface(QString(), QLatin1String("/"),
1074 TEST_INTERFACE_NAME, con);
1075
1076 resetPeer();
1077 int arg = 42;
1078 setProp1Peer(42);
1079
1080 QVariant v = iface.property(name: "prop1");
1081 QVERIFY(v.isValid());
1082 QCOMPARE(v.userType(), int(QVariant::Int));
1083 QCOMPARE(v.toInt(), arg);
1084 QCOMPARE(callCountPeer(), 1);
1085}
1086
1087void tst_QDBusInterface::propertyWritePeer()
1088{
1089 QDBusConnection con("peer");
1090 QDBusInterface iface(QString(), QLatin1String("/"),
1091 TEST_INTERFACE_NAME, con);
1092
1093 resetPeer();
1094 int arg = 42;
1095 setProp1Peer(0);
1096
1097 QVERIFY(iface.setProperty("prop1", arg));
1098 QCOMPARE(callCountPeer(), 1);
1099 QCOMPARE(prop1Peer(), arg);
1100}
1101
1102void tst_QDBusInterface::complexPropertyReadPeer()
1103{
1104 QDBusConnection con("peer");
1105 QDBusInterface iface(QString(), QLatin1String("/"),
1106 TEST_INTERFACE_NAME, con);
1107
1108 resetPeer();
1109 QList<int> arg = QList<int>() << 42 << -47;
1110 setComplexPropPeer(arg);
1111
1112 QVariant v = iface.property(name: "complexProp");
1113 QVERIFY(v.isValid());
1114 QCOMPARE(v.userType(), qMetaTypeId<QList<int> >());
1115 QCOMPARE(v.value<QList<int> >(), arg);
1116 QCOMPARE(callCountPeer(), 1);
1117}
1118
1119void tst_QDBusInterface::complexPropertyWritePeer()
1120{
1121 QDBusConnection con("peer");
1122 QDBusInterface iface(QString(), QLatin1String("/"),
1123 TEST_INTERFACE_NAME, con);
1124
1125 resetPeer();
1126 QList<int> arg = QList<int>() << -47 << 42;
1127
1128 QVERIFY(iface.setProperty("complexProp", QVariant::fromValue(arg)));
1129 QCOMPARE(callCountPeer(), 1);
1130 QCOMPARE(complexPropPeer(), arg);
1131}
1132
1133void tst_QDBusInterface::interactiveAuthorizationRequired()
1134{
1135 int major;
1136 int minor;
1137 int micro;
1138 q_dbus_get_version(major_version: &major, minor_version: &minor, micro_version: &micro);
1139
1140 QVersionNumber dbusVersion(major, minor, micro);
1141 if (dbusVersion < QVersionNumber(1, 9, 2))
1142 QSKIP("Your DBus library is too old to support interactive authorization");
1143
1144 QDBusMessage req = QDBusMessage::createMethodCall(destination: serviceName, path: objectPath, interface: interfaceName, method: "interactiveAuthorization");
1145 QDBusMessage reply = QDBusConnection::sessionBus().call(message: req);
1146
1147 QCOMPARE(reply.type(), QDBusMessage::ErrorMessage);
1148 QCOMPARE(reply.errorName(), QStringLiteral("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"));
1149
1150 req.setInteractiveAuthorizationAllowed(true);
1151 reply = QDBusConnection::sessionBus().call(message: req);
1152
1153 QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
1154 QVERIFY(reply.arguments().at(0).toBool());
1155}
1156
1157QTEST_MAIN(tst_QDBusInterface)
1158
1159#include "tst_qdbusinterface.moc"
1160

source code of qtbase/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp