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#include <QtCore/QObject>
29#include <QtCore/QVariant>
30#include <QtCore/QList>
31#include <QtCore/QVector>
32#include <QtTest/QtTest>
33#include <QtDBus>
34
35typedef QMap<int,QString> IntStringMap;
36Q_DECLARE_METATYPE(IntStringMap)
37
38struct MyStruct
39{
40 int i;
41 QString s;
42
43 MyStruct() : i(1), s("String") { }
44 bool operator==(const MyStruct &other) const
45 { return i == other.i && s == other.s; }
46};
47Q_DECLARE_METATYPE(MyStruct)
48
49QDBusArgument &operator<<(QDBusArgument &arg, const MyStruct &ms)
50{
51 arg.beginStructure();
52 arg << ms.i << ms.s;
53 arg.endStructure();
54 return arg;
55}
56
57const QDBusArgument &operator>>(const QDBusArgument &arg, MyStruct &ms)
58{
59 arg.beginStructure();
60 arg >> ms.i >> ms.s;
61 arg.endStructure();
62 return arg;
63}
64
65class TypesInterface;
66class tst_QDBusPendingReply: public QObject
67{
68 Q_OBJECT
69 QDBusInterface *iface;
70 TypesInterface *adaptor;
71public:
72 tst_QDBusPendingReply();
73
74private slots:
75 void initTestCase()
76 {
77 qDBusRegisterMetaType<IntStringMap>();
78 qDBusRegisterMetaType<MyStruct>();
79 }
80
81 void init();
82 void unconnected();
83 void simpleTypes();
84 void complexTypes();
85 void wrongTypes();
86 void multipleTypes();
87
88 void synchronousSimpleTypes();
89
90 void errors();
91};
92
93class TypesInterface: public QDBusAbstractAdaptor
94{
95 Q_OBJECT
96 Q_CLASSINFO("D-Bus Interface", "org.qtproject.Qt.Autotests.TypesInterface")
97public:
98 TypesInterface(QObject *parent)
99 : QDBusAbstractAdaptor(parent)
100 { }
101
102public slots:
103 void retrieveVoid()
104 { }
105
106 bool retrieveBool()
107 {
108 return true;
109 }
110
111 uchar retrieveUChar()
112 {
113 return 'A';
114 }
115
116 short retrieveShort()
117 {
118 return -47;
119 }
120
121 ushort retrieveUShort()
122 {
123 return 42U;
124 }
125
126 int retrieveInt()
127 {
128 return -470000;
129 }
130
131 void retrieveIntInt(int &i1, int &i2)
132 {
133 i1 = -424242;
134 i2 = 434343;
135 }
136
137 uint retrieveUInt()
138 {
139 return 42424242;
140 }
141
142 qlonglong retrieveLongLong()
143 {
144 return -(Q_INT64_C(1) << 32);
145 }
146
147 qulonglong retrieveULongLong()
148 {
149 return Q_INT64_C(1) << 32;
150 }
151
152 double retrieveDouble()
153 {
154 return 1.5;
155 }
156
157 QString retrieveString()
158 {
159 return "This string you should see";
160 }
161
162 QDBusObjectPath retrieveObjectPath()
163 {
164 return QDBusObjectPath("/");
165 }
166
167 QDBusSignature retrieveSignature()
168 {
169 return QDBusSignature("g");
170 }
171
172 QDBusVariant retrieveVariant()
173 {
174 return QDBusVariant(retrieveString());
175 }
176
177 QStringList retrieveStringList()
178 {
179 return QStringList() << "one" << "two";
180 }
181
182 QByteArray retrieveByteArray()
183 {
184 return "Hello, World";
185 }
186
187 QVariantList retrieveList()
188 {
189 return QVariantList() << retrieveInt() << retrieveString()
190 << retrieveByteArray();
191 }
192
193 QVariantMap retrieveMap()
194 {
195 QVariantMap map;
196 map["one"] = 1;
197 map["two"] = 2U;
198 map["string"] = retrieveString();
199 map["stringlist"] = retrieveStringList();
200 return map;
201 }
202
203 IntStringMap retrieveIntStringMap()
204 {
205 IntStringMap map;
206 map[1] = "1";
207 map[2] = "2";
208 map[-1231456] = "foo";
209 return map;
210 }
211
212 MyStruct retrieveStruct()
213 {
214 return MyStruct();
215 }
216
217 void sendError(const QDBusMessage &msg)
218 {
219 msg.setDelayedReply(true);
220 QDBusConnection::sessionBus()
221 .send(message: msg.createErrorReply(name: "local.AnErrorName", msg: "You've got an error!"));
222 }
223};
224
225tst_QDBusPendingReply::tst_QDBusPendingReply()
226{
227 adaptor = new TypesInterface(this);
228 QDBusConnection::sessionBus().registerObject(path: "/", object: this);
229
230 iface = new QDBusInterface(QDBusConnection::sessionBus().baseService(), "/",
231 "org.qtproject.Qt.Autotests.TypesInterface",
232 QDBusConnection::sessionBus(),
233 this);
234}
235
236void tst_QDBusPendingReply::init()
237{
238 QVERIFY(iface);
239 QVERIFY(iface->isValid());
240}
241
242void tst_QDBusPendingReply::unconnected()
243{
244 QDBusConnection con("invalid stored connection");
245 QVERIFY(!con.isConnected());
246 QDBusInterface iface("doesnt.matter", "/", "doesnt.matter", con);
247 QVERIFY(!iface.isValid());
248
249 QDBusPendingReply<> rvoid = iface.asyncCall(method: "ReloadConfig");
250 QVERIFY(rvoid.isFinished());
251 QVERIFY(!rvoid.isValid());
252 QVERIFY(rvoid.isError());
253 rvoid.waitForFinished();
254 QVERIFY(!rvoid.isValid());
255 QVERIFY(rvoid.isError());
256
257 QDBusPendingReply<QString> rstring = iface.asyncCall(method: "GetId");
258 QVERIFY(rstring.isFinished());
259 QVERIFY(!rstring.isValid());
260 QVERIFY(rstring.isError());
261 rstring.waitForFinished();
262 QVERIFY(!rstring.isValid());
263 QVERIFY(rstring.isError());
264}
265
266void tst_QDBusPendingReply::simpleTypes()
267{
268 QDBusPendingReply<> rvoid = iface->asyncCall(method: "retrieveVoid");
269 rvoid.waitForFinished();
270 QVERIFY(rvoid.isFinished());
271 QVERIFY(!rvoid.isError());
272
273 QDBusPendingReply<bool> rbool = iface->asyncCall(method: "retrieveBool");
274 rbool.waitForFinished();
275 QVERIFY(rbool.isFinished());
276 QCOMPARE(rbool.argumentAt<0>(), adaptor->retrieveBool());
277
278 QDBusPendingReply<uchar> ruchar = iface->asyncCall(method: "retrieveUChar");
279 ruchar.waitForFinished();
280 QVERIFY(ruchar.isFinished());
281 QCOMPARE(ruchar.argumentAt<0>(), adaptor->retrieveUChar());
282
283 QDBusPendingReply<short> rshort = iface->asyncCall(method: "retrieveShort");
284 rshort.waitForFinished();
285 QVERIFY(rshort.isFinished());
286 QCOMPARE(rshort.argumentAt<0>(), adaptor->retrieveShort());
287
288 QDBusPendingReply<ushort> rushort = iface->asyncCall(method: "retrieveUShort");
289 rushort.waitForFinished();
290 QVERIFY(rushort.isFinished());
291 QCOMPARE(rushort.argumentAt<0>(), adaptor->retrieveUShort());
292
293 QDBusPendingReply<int> rint = iface->asyncCall(method: "retrieveInt");
294 rint.waitForFinished();
295 QVERIFY(rint.isFinished());
296 QCOMPARE(rint.argumentAt<0>(), adaptor->retrieveInt());
297
298 QDBusPendingReply<uint> ruint = iface->asyncCall(method: "retrieveUInt");
299 ruint.waitForFinished();
300 QVERIFY(ruint.isFinished());
301 QCOMPARE(ruint.argumentAt<0>(), adaptor->retrieveUInt());
302
303 QDBusPendingReply<qlonglong> rqlonglong = iface->asyncCall(method: "retrieveLongLong");
304 rqlonglong.waitForFinished();
305 QVERIFY(rqlonglong.isFinished());
306 QCOMPARE(rqlonglong.argumentAt<0>(), adaptor->retrieveLongLong());
307
308 QDBusPendingReply<qulonglong> rqulonglong = iface->asyncCall(method: "retrieveULongLong");
309 rqulonglong.waitForFinished();
310 QVERIFY(rqulonglong.isFinished());
311 QCOMPARE(rqulonglong.argumentAt<0>(), adaptor->retrieveULongLong());
312
313 QDBusPendingReply<double> rdouble = iface->asyncCall(method: "retrieveDouble");
314 rdouble.waitForFinished();
315 QVERIFY(rdouble.isFinished());
316 QCOMPARE(rdouble.argumentAt<0>(), adaptor->retrieveDouble());
317
318 QDBusPendingReply<QString> rstring = iface->asyncCall(method: "retrieveString");
319 rstring.waitForFinished();
320 QVERIFY(rstring.isFinished());
321 QCOMPARE(rstring.argumentAt<0>(), adaptor->retrieveString());
322
323 QDBusPendingReply<QDBusObjectPath> robjectpath = iface->asyncCall(method: "retrieveObjectPath");
324 robjectpath.waitForFinished();
325 QVERIFY(robjectpath.isFinished());
326 QCOMPARE(robjectpath.argumentAt<0>().path(), adaptor->retrieveObjectPath().path());
327
328 QDBusPendingReply<QDBusSignature> rsignature = iface->asyncCall(method: "retrieveSignature");
329 rsignature.waitForFinished();
330 QVERIFY(rsignature.isFinished());
331 QCOMPARE(rsignature.argumentAt<0>().signature(), adaptor->retrieveSignature().signature());
332
333 QDBusPendingReply<QDBusVariant> rdbusvariant = iface->asyncCall(method: "retrieveVariant");
334 rdbusvariant.waitForFinished();
335 QVERIFY(rdbusvariant.isFinished());
336 QCOMPARE(rdbusvariant.argumentAt<0>().variant(), adaptor->retrieveVariant().variant());
337
338 QDBusPendingReply<QVariant> rvariant = iface->asyncCall(method: "retrieveVariant");
339 rvariant.waitForFinished();
340 QVERIFY(rvariant.isFinished());
341 QCOMPARE(rvariant.argumentAt<0>(), adaptor->retrieveVariant().variant());
342
343 QDBusPendingReply<QByteArray> rbytearray = iface->asyncCall(method: "retrieveByteArray");
344 rbytearray.waitForFinished();
345 QVERIFY(rbytearray.isFinished());
346 QCOMPARE(rbytearray.argumentAt<0>(), adaptor->retrieveByteArray());
347
348 QDBusPendingReply<QStringList> rstringlist = iface->asyncCall(method: "retrieveStringList");
349 rstringlist.waitForFinished();
350 QVERIFY(rstringlist.isFinished());
351 QCOMPARE(rstringlist.argumentAt<0>(), adaptor->retrieveStringList());
352}
353
354void tst_QDBusPendingReply::complexTypes()
355{
356 QDBusPendingReply<QVariantList> rlist = iface->asyncCall(method: "retrieveList");
357 rlist.waitForFinished();
358 QVERIFY(rlist.isFinished());
359 QCOMPARE(rlist.argumentAt<0>(), adaptor->retrieveList());
360
361 QDBusPendingReply<QVariantMap> rmap = iface->asyncCall(method: "retrieveMap");
362 rmap.waitForFinished();
363 QVERIFY(rmap.isFinished());
364 QCOMPARE(rmap.argumentAt<0>(), adaptor->retrieveMap());
365
366 QDBusPendingReply<IntStringMap> rismap = iface->asyncCall(method: "retrieveIntStringMap");
367 rismap.waitForFinished();
368 QVERIFY(rismap.isFinished());
369 QCOMPARE(rismap.argumentAt<0>(), adaptor->retrieveIntStringMap());
370
371 QDBusPendingReply<MyStruct> rstruct = iface->asyncCall(method: "retrieveStruct");
372 rstruct.waitForFinished();
373 QVERIFY(rstruct.isFinished());
374 QCOMPARE(rstruct.argumentAt<0>(), adaptor->retrieveStruct());
375}
376
377#define VERIFY_WRONG_TYPE(error) \
378 QVERIFY(error.isValid()); \
379 QCOMPARE(error.type(), QDBusError::InvalidSignature)
380
381void tst_QDBusPendingReply::wrongTypes()
382{
383 QDBusError error;
384
385 QDBusPendingReply<bool> rbool = iface->asyncCall(method: "retrieveInt");
386 rbool.waitForFinished();
387 QVERIFY(rbool.isFinished());
388 QVERIFY(rbool.isError());
389 error = rbool.error();
390 VERIFY_WRONG_TYPE(error);
391
392 rbool = iface->asyncCall(method: "retrieveShort");
393 rbool.waitForFinished();
394 QVERIFY(rbool.isFinished());
395 QVERIFY(rbool.isError());
396 error = rbool.error();
397 VERIFY_WRONG_TYPE(error);
398
399 rbool = iface->asyncCall(method: "retrieveStruct");
400 rbool.waitForFinished();
401 QVERIFY(rbool.isFinished());
402 QVERIFY(rbool.isError());
403 error = rbool.error();
404 VERIFY_WRONG_TYPE(error);
405
406 QDBusPendingReply<short> rshort = iface->asyncCall(method: "retrieveInt");
407 rshort.waitForFinished();
408 QVERIFY(rshort.isFinished());
409 QVERIFY(rshort.isError());
410 error = rshort.error();
411 VERIFY_WRONG_TYPE(error);
412
413 rshort = iface->asyncCall(method: "retrieveBool");
414 rshort.waitForFinished();
415 QVERIFY(rshort.isFinished());
416 QVERIFY(rshort.isError());
417 error = rshort.error();
418 VERIFY_WRONG_TYPE(error);
419
420 rshort = iface->asyncCall(method: "retrieveStruct");
421 rshort.waitForFinished();
422 QVERIFY(rshort.isFinished());
423 QVERIFY(rshort.isError());
424 error = rshort.error();
425 VERIFY_WRONG_TYPE(error);
426
427 QDBusPendingReply<MyStruct> rstruct = iface->asyncCall(method: "retrieveInt");
428 rstruct.waitForFinished();
429 QVERIFY(rstruct.isFinished());
430 QVERIFY(rstruct.isError());
431 error = rstruct.error();
432 VERIFY_WRONG_TYPE(error);
433
434 rstruct = iface->asyncCall(method: "retrieveShort");
435 rstruct.waitForFinished();
436 QVERIFY(rstruct.isFinished());
437 QVERIFY(rstruct.isError());
438 error = rstruct.error();
439 VERIFY_WRONG_TYPE(error);
440
441 rstruct = iface->asyncCall(method: "retrieveIntStringMap");
442 rstruct.waitForFinished();
443 QVERIFY(rstruct.isFinished());
444 QVERIFY(rstruct.isError());
445 error = rstruct.error();
446 VERIFY_WRONG_TYPE(error);
447}
448
449void tst_QDBusPendingReply::multipleTypes()
450{
451 QDBusPendingReply<int, int> rintint = iface->asyncCall(method: "retrieveIntInt");
452 rintint.waitForFinished();
453 QVERIFY(rintint.isFinished());
454 QVERIFY(!rintint.isError());
455
456 int i1, i2;
457 adaptor->retrieveIntInt(i1, i2);
458 QCOMPARE(rintint.argumentAt<0>(), i1);
459 QCOMPARE(rintint.argumentAt<1>(), i2);
460}
461
462void tst_QDBusPendingReply::synchronousSimpleTypes()
463{
464 QDBusPendingReply<bool> rbool(iface->call(method: "retrieveBool"));
465 rbool.waitForFinished();
466 QVERIFY(rbool.isFinished());
467 QCOMPARE(rbool.argumentAt<0>(), adaptor->retrieveBool());
468
469 QDBusPendingReply<uchar> ruchar(iface->call(method: "retrieveUChar"));
470 ruchar.waitForFinished();
471 QVERIFY(ruchar.isFinished());
472 QCOMPARE(ruchar.argumentAt<0>(), adaptor->retrieveUChar());
473
474 QDBusPendingReply<short> rshort(iface->call(method: "retrieveShort"));
475 rshort.waitForFinished();
476 QVERIFY(rshort.isFinished());
477 QCOMPARE(rshort.argumentAt<0>(), adaptor->retrieveShort());
478
479 QDBusPendingReply<ushort> rushort(iface->call(method: "retrieveUShort"));
480 rushort.waitForFinished();
481 QVERIFY(rushort.isFinished());
482 QCOMPARE(rushort.argumentAt<0>(), adaptor->retrieveUShort());
483
484 QDBusPendingReply<int> rint(iface->call(method: "retrieveInt"));
485 rint.waitForFinished();
486 QVERIFY(rint.isFinished());
487 QCOMPARE(rint.argumentAt<0>(), adaptor->retrieveInt());
488
489 QDBusPendingReply<uint> ruint(iface->call(method: "retrieveUInt"));
490 ruint.waitForFinished();
491 QVERIFY(ruint.isFinished());
492 QCOMPARE(ruint.argumentAt<0>(), adaptor->retrieveUInt());
493
494 QDBusPendingReply<qlonglong> rqlonglong(iface->call(method: "retrieveLongLong"));
495 rqlonglong.waitForFinished();
496 QVERIFY(rqlonglong.isFinished());
497 QCOMPARE(rqlonglong.argumentAt<0>(), adaptor->retrieveLongLong());
498
499 QDBusPendingReply<qulonglong> rqulonglong(iface->call(method: "retrieveULongLong"));
500 rqulonglong.waitForFinished();
501 QVERIFY(rqulonglong.isFinished());
502 QCOMPARE(rqulonglong.argumentAt<0>(), adaptor->retrieveULongLong());
503
504 QDBusPendingReply<double> rdouble(iface->call(method: "retrieveDouble"));
505 rdouble.waitForFinished();
506 QVERIFY(rdouble.isFinished());
507 QCOMPARE(rdouble.argumentAt<0>(), adaptor->retrieveDouble());
508
509 QDBusPendingReply<QString> rstring(iface->call(method: "retrieveString"));
510 rstring.waitForFinished();
511 QVERIFY(rstring.isFinished());
512 QCOMPARE(rstring.argumentAt<0>(), adaptor->retrieveString());
513
514 QDBusPendingReply<QDBusObjectPath> robjectpath(iface->call(method: "retrieveObjectPath"));
515 robjectpath.waitForFinished();
516 QVERIFY(robjectpath.isFinished());
517 QCOMPARE(robjectpath.argumentAt<0>().path(), adaptor->retrieveObjectPath().path());
518
519 QDBusPendingReply<QDBusSignature> rsignature(iface->call(method: "retrieveSignature"));
520 rsignature.waitForFinished();
521 QVERIFY(rsignature.isFinished());
522 QCOMPARE(rsignature.argumentAt<0>().signature(), adaptor->retrieveSignature().signature());
523
524 QDBusPendingReply<QDBusVariant> rdbusvariant(iface->call(method: "retrieveVariant"));
525 rdbusvariant.waitForFinished();
526 QVERIFY(rdbusvariant.isFinished());
527 QCOMPARE(rdbusvariant.argumentAt<0>().variant(), adaptor->retrieveVariant().variant());
528
529 QDBusPendingReply<QByteArray> rbytearray(iface->call(method: "retrieveByteArray"));
530 rbytearray.waitForFinished();
531 QVERIFY(rbytearray.isFinished());
532 QCOMPARE(rbytearray.argumentAt<0>(), adaptor->retrieveByteArray());
533
534 QDBusPendingReply<QStringList> rstringlist(iface->call(method: "retrieveStringList"));
535 rstringlist.waitForFinished();
536 QVERIFY(rstringlist.isFinished());
537 QCOMPARE(rstringlist.argumentAt<0>(), adaptor->retrieveStringList());
538}
539
540#define VERIFY_ERROR(error) \
541 QVERIFY(error.isValid()); \
542 QCOMPARE(error.name(), QString("local.AnErrorName")); \
543 QCOMPARE(error.type(), QDBusError::Other)
544
545void tst_QDBusPendingReply::errors()
546{
547 QDBusError error;
548
549 QDBusPendingReply<> rvoid(iface->asyncCall(method: "sendError"));
550 rvoid.waitForFinished();
551 QVERIFY(rvoid.isFinished());
552 QVERIFY(rvoid.isError());
553 error = rvoid.error();
554 VERIFY_ERROR(error);
555
556 QDBusPendingReply<int> rint(iface->asyncCall(method: "sendError"));
557 rint.waitForFinished();
558 QVERIFY(rint.isFinished());
559 QVERIFY(rint.isError());
560 error = rint.error();
561 VERIFY_ERROR(error);
562 int dummyint = rint;
563 QCOMPARE(dummyint, int());
564
565 QDBusPendingReply<int,int> rintint(iface->asyncCall(method: "sendError"));
566 rintint.waitForFinished();
567 QVERIFY(rintint.isFinished());
568 QVERIFY(rintint.isError());
569 error = rintint.error();
570 VERIFY_ERROR(error);
571 dummyint = rintint;
572 QCOMPARE(dummyint, int());
573 QCOMPARE(rintint.argumentAt<1>(), int());
574
575 QDBusPendingReply<QString> rstring(iface->asyncCall(method: "sendError"));
576 rstring.waitForFinished();
577 QVERIFY(rstring.isFinished());
578 QVERIFY(rstring.isError());
579 error = rstring.error();
580 VERIFY_ERROR(error);
581 QString dummystring = rstring;
582 QCOMPARE(dummystring, QString());
583}
584
585QTEST_MAIN(tst_QDBusPendingReply)
586
587#include "tst_qdbuspendingreply.moc"
588

source code of qtbase/tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp