~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
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 Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
#include <qcoreapplication.h>
 
42
#include <qdebug.h>
 
43
 
 
44
#include <QtTest/QtTest>
 
45
 
 
46
#include <QtDBus>
 
47
 
 
48
#include "../qdbusmarshall/common.h"
 
49
#include "myobject.h"
 
50
 
 
51
static const char serviceName[] = "org.qtproject.autotests.qmyserver";
 
52
static const char objectPath[] = "/org/qtproject/qmyserver";
 
53
static const char *interfaceName = serviceName;
 
54
 
 
55
const char *slotSpy;
 
56
QString valueSpy;
 
57
 
 
58
QT_BEGIN_NAMESPACE
 
59
namespace QTest {
 
60
    char *toString(QDBusMessage::MessageType t)
 
61
    {
 
62
        switch (t)
 
63
        {
 
64
        case QDBusMessage::InvalidMessage:
 
65
            return qstrdup("InvalidMessage");
 
66
        case QDBusMessage::MethodCallMessage:
 
67
            return qstrdup("MethodCallMessage");
 
68
        case QDBusMessage::ReplyMessage:
 
69
            return qstrdup("ReplyMessage");
 
70
        case QDBusMessage::ErrorMessage:
 
71
            return qstrdup("ErrorMessage");
 
72
        case QDBusMessage::SignalMessage:
 
73
            return qstrdup("SignalMessage");
 
74
        default:
 
75
            return 0;
 
76
        }
 
77
    }
 
78
}
 
79
QT_END_NAMESPACE
 
80
 
 
81
class TypesInterface: public QDBusAbstractAdaptor
 
82
{
 
83
    Q_OBJECT
 
84
    Q_CLASSINFO("D-Bus Interface", "local.TypesInterface")
 
85
public:
 
86
    TypesInterface(QObject *parent)
 
87
        : QDBusAbstractAdaptor(parent)
 
88
    { }
 
89
 
 
90
    union
 
91
    {
 
92
        bool b;
 
93
        uchar uc;
 
94
        short s;
 
95
        ushort us;
 
96
        int i;
 
97
        uint ui;
 
98
        qlonglong ll;
 
99
        qulonglong ull;
 
100
        double d;
 
101
    } dataSpy;
 
102
    QVariant variantSpy;
 
103
    QString stringSpy;
 
104
    QVariantList listSpy;
 
105
    QStringList stringlistSpy;
 
106
    QByteArray bytearraySpy;
 
107
    QVariantMap mapSpy;
 
108
    StringStringMap ssmapSpy;
 
109
    LLDateTimeMap lldtmapSpy;
 
110
    MyStruct structSpy;
 
111
 
 
112
public slots:
 
113
    void methodBool(bool b)
 
114
    {
 
115
        slotSpy = "void TypesInterface::methodBool(bool)";
 
116
        dataSpy.b = b;
 
117
    }
 
118
 
 
119
    void methodUChar(uchar uc)
 
120
    {
 
121
        slotSpy = "void TypesInterface::methodUChar(uchar)";
 
122
        dataSpy.uc = uc;
 
123
    }
 
124
 
 
125
    void methodShort(short s)
 
126
    {
 
127
        slotSpy = "void TypesInterface::methodShort(short)";
 
128
        dataSpy.s = s;
 
129
    }
 
130
 
 
131
    void methodUShort(ushort us)
 
132
    {
 
133
        slotSpy = "void TypesInterface::methodUShort(ushort)";
 
134
        dataSpy.us = us;
 
135
    }
 
136
 
 
137
    void methodInt(int i)
 
138
    {
 
139
        slotSpy = "void TypesInterface::methodInt(int)";
 
140
        dataSpy.i = i;
 
141
    }
 
142
 
 
143
    void methodUInt(uint ui)
 
144
    {
 
145
        slotSpy = "void TypesInterface::methodUInt(uint)";
 
146
        dataSpy.ui = ui;
 
147
    }
 
148
 
 
149
    void methodLongLong(qlonglong ll)
 
150
    {
 
151
        slotSpy = "void TypesInterface::methodLongLong(qlonglong)";
 
152
        dataSpy.ll = ll;
 
153
    }
 
154
 
 
155
    void methodULongLong(qulonglong ull)
 
156
    {
 
157
        slotSpy = "void TypesInterface::methodULongLong(qulonglong)";
 
158
        dataSpy.ull = ull;
 
159
    }
 
160
 
 
161
    void methodDouble(double d)
 
162
    {
 
163
        slotSpy = "void TypesInterface::methodDouble(double)";
 
164
        dataSpy.d = d;
 
165
    }
 
166
 
 
167
    void methodString(const QString &s)
 
168
    {
 
169
        slotSpy = "void TypesInterface::methodString(const QString &)";
 
170
        stringSpy = s;
 
171
    }
 
172
 
 
173
    void methodObjectPath(const QDBusObjectPath &op)
 
174
    {
 
175
        slotSpy = "void TypesInterface::methodObjectPath(const QDBusObjectPath &)";
 
176
        stringSpy = op.path();
 
177
    }
 
178
 
 
179
    void methodSignature(const QDBusSignature &s)
 
180
    {
 
181
        slotSpy = "void TypesInterface::methodSignature(const QDBusSignature &)";
 
182
        stringSpy = s.signature();
 
183
    }
 
184
 
 
185
    void methodVariant(const QDBusVariant &v)
 
186
    {
 
187
        slotSpy = "void TypesInterface::methodVariant(const QDBusVariant &)";
 
188
        variantSpy = v.variant();
 
189
    }
 
190
 
 
191
    void methodList(const QVariantList &l)
 
192
    {
 
193
        slotSpy = "void TypesInterface::methodList(const QVariantList &)";
 
194
        listSpy = l;
 
195
    }
 
196
 
 
197
    void methodStringList(const QStringList &sl)
 
198
    {
 
199
        slotSpy = "void TypesInterface::methodStringList(const QStringList &)";
 
200
        stringlistSpy = sl;
 
201
    }
 
202
 
 
203
    void methodByteArray(const QByteArray &ba)
 
204
    {
 
205
        slotSpy = "void TypesInterface::methodByteArray(const QByteArray &)";
 
206
        bytearraySpy = ba;
 
207
    }
 
208
 
 
209
    void methodMap(const QVariantMap &m)
 
210
    {
 
211
        slotSpy = "void TypesInterface::methodMap(const QVariantMap &)";
 
212
        mapSpy = m;
 
213
    }
 
214
 
 
215
    void methodSSMap(const StringStringMap &ssmap)
 
216
    {
 
217
        slotSpy = "void TypesInterface::methodSSMap(const StringStringMap &)";
 
218
        ssmapSpy = ssmap;
 
219
    }
 
220
 
 
221
    void methodLLDateTimeMap(const LLDateTimeMap &lldtmap)
 
222
    {
 
223
        slotSpy = "void TypesInterface::methodLLDateTimeMap(const LLDateTimeMap &)";
 
224
        lldtmapSpy = lldtmap;
 
225
    }
 
226
 
 
227
    void methodStruct(const MyStruct &s)
 
228
    {
 
229
        slotSpy = "void TypesInterface::methodStruct(const MyStruct &)";
 
230
        structSpy = s;
 
231
    }
 
232
 
 
233
    bool retrieveBool()
 
234
    {
 
235
        return dataSpy.b;
 
236
    }
 
237
 
 
238
    uchar retrieveUChar()
 
239
    {
 
240
        return dataSpy.uc;
 
241
    }
 
242
 
 
243
    short retrieveShort()
 
244
    {
 
245
        return dataSpy.s;
 
246
    }
 
247
 
 
248
    ushort retrieveUShort()
 
249
    {
 
250
        return dataSpy.us;
 
251
    }
 
252
 
 
253
    int retrieveInt()
 
254
    {
 
255
        return dataSpy.i;
 
256
    }
 
257
 
 
258
    uint retrieveUInt()
 
259
    {
 
260
        return dataSpy.ui;
 
261
    }
 
262
 
 
263
    qlonglong retrieveLongLong()
 
264
    {
 
265
        return dataSpy.ll;
 
266
    }
 
267
 
 
268
    qulonglong retrieveULongLong()
 
269
    {
 
270
        return dataSpy.ull;
 
271
    }
 
272
 
 
273
    double retrieveDouble()
 
274
    {
 
275
        return dataSpy.d;
 
276
    }
 
277
 
 
278
    QString retrieveString()
 
279
    {
 
280
        return stringSpy;
 
281
    }
 
282
 
 
283
    QDBusObjectPath retrieveObjectPath()
 
284
    {
 
285
        return QDBusObjectPath(stringSpy);
 
286
    }
 
287
 
 
288
    QDBusSignature retrieveSignature()
 
289
    {
 
290
        return QDBusSignature(stringSpy);
 
291
    }
 
292
 
 
293
    QDBusVariant retrieveVariant()
 
294
    {
 
295
        return QDBusVariant(variantSpy);
 
296
    }
 
297
 
 
298
    QVariantList retrieveList()
 
299
    {
 
300
        return listSpy;
 
301
    }
 
302
 
 
303
    QStringList retrieveStringList()
 
304
    {
 
305
        return stringlistSpy;
 
306
    }
 
307
 
 
308
    QByteArray retrieveByteArray()
 
309
    {
 
310
        return bytearraySpy;
 
311
    }
 
312
 
 
313
    QVariantMap retrieveMap()
 
314
    {
 
315
        return mapSpy;
 
316
    }
 
317
 
 
318
    StringStringMap retrieveSSMap()
 
319
    {
 
320
        return ssmapSpy;
 
321
    }
 
322
 
 
323
    LLDateTimeMap retrieveLLDateTimeMap()
 
324
    {
 
325
        return lldtmapSpy;
 
326
    }
 
327
 
 
328
    MyStruct retrieveStruct()
 
329
    {
 
330
        return structSpy;
 
331
    }
 
332
};
 
333
 
 
334
void newMyObjectPeer(int nInterfaces = 4)
 
335
{
 
336
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "newMyObject");
 
337
    req << nInterfaces;
 
338
    QDBusMessage reply = QDBusConnection::sessionBus().call(req);
 
339
}
 
340
 
 
341
void registerMyObjectPeer(const QString & path, QDBusConnection::RegisterOptions options = QDBusConnection::ExportAdaptors)
 
342
{
 
343
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "registerMyObject");
 
344
    req << path;
 
345
    req << (int)options;
 
346
    QDBusMessage reply = QDBusConnection::sessionBus().call(req);
 
347
}
 
348
 
 
349
void emitSignalPeer(const QString &interface, const QString &name, const QVariant &parameter)
 
350
{
 
351
    if (parameter.isValid())
 
352
    {
 
353
        QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal");
 
354
        req << interface;
 
355
        req << name;
 
356
        req << QVariant::fromValue(QDBusVariant(parameter));
 
357
        QDBusConnection::sessionBus().send(req);
 
358
    }
 
359
    else
 
360
    {
 
361
        QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal2");
 
362
        req << interface;
 
363
        req << name;
 
364
        QDBusConnection::sessionBus().send(req);
 
365
    }
 
366
 
 
367
    QTest::qWait(1000);
 
368
}
 
369
 
 
370
const char* slotSpyPeer()
 
371
{
 
372
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "slotSpyServer");
 
373
    QDBusMessage reply = QDBusConnection::sessionBus().call(req);
 
374
    return reply.arguments().at(0).toString().toLatin1().data();
 
375
}
 
376
 
 
377
QString valueSpyPeer()
 
378
{
 
379
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "valueSpyServer");
 
380
    QDBusMessage reply = QDBusConnection::sessionBus().call(req);
 
381
    return reply.arguments().at(0).toString();
 
382
}
 
383
 
 
384
void clearValueSpyPeer()
 
385
{
 
386
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "clearValueSpy");
 
387
    QDBusMessage reply = QDBusConnection::sessionBus().call(req);
 
388
}
 
389
 
 
390
class tst_QDBusAbstractAdaptor: public QObject
 
391
{
 
392
    Q_OBJECT
 
393
 
 
394
private slots:
 
395
    void initTestCase();
 
396
    void cleanupTestCase();
 
397
 
 
398
    void methodCalls_data();
 
399
    void methodCalls();
 
400
    void methodCallScriptable();
 
401
    void signalEmissions_data();
 
402
    void signalEmissions();
 
403
    void sameSignalDifferentPaths();
 
404
    void sameObjectDifferentPaths();
 
405
    void scriptableSignalOrNot();
 
406
    void overloadedSignalEmission_data();
 
407
    void overloadedSignalEmission();
 
408
    void readProperties();
 
409
    void readPropertiesInvalidInterface();
 
410
    void readPropertiesEmptyInterface_data();
 
411
    void readPropertiesEmptyInterface();
 
412
    void readAllProperties();
 
413
    void readAllPropertiesInvalidInterface();
 
414
    void readAllPropertiesEmptyInterface_data();
 
415
    void readAllPropertiesEmptyInterface();
 
416
    void writeProperties();
 
417
 
 
418
    void methodCallsPeer_data();
 
419
    void methodCallsPeer();
 
420
    void methodCallScriptablePeer();
 
421
    void signalEmissionsPeer_data();
 
422
    void signalEmissionsPeer();
 
423
    void sameSignalDifferentPathsPeer();
 
424
    void sameObjectDifferentPathsPeer();
 
425
    void scriptableSignalOrNotPeer();
 
426
    void overloadedSignalEmissionPeer_data();
 
427
    void overloadedSignalEmissionPeer();
 
428
    void readPropertiesPeer();
 
429
    void readPropertiesInvalidInterfacePeer();
 
430
    void readPropertiesEmptyInterfacePeer_data();
 
431
    void readPropertiesEmptyInterfacePeer();
 
432
    void readAllPropertiesPeer();
 
433
    void readAllPropertiesInvalidInterfacePeer();
 
434
    void readAllPropertiesEmptyInterfacePeer_data();
 
435
    void readAllPropertiesEmptyInterfacePeer();
 
436
    void writePropertiesPeer();
 
437
 
 
438
    void typeMatching_data();
 
439
    void typeMatching();
 
440
 
 
441
    void methodWithMoreThanOneReturnValue();
 
442
    void methodWithMoreThanOneReturnValuePeer();
 
443
private:
 
444
    QProcess proc;
 
445
};
 
446
 
 
447
class WaitForQMyServer: public QObject
 
448
{
 
449
    Q_OBJECT
 
450
public:
 
451
    WaitForQMyServer();
 
452
    bool ok();
 
453
public Q_SLOTS:
 
454
    void ownerChange(const QString &name)
 
455
    {
 
456
        if (name == serviceName)
 
457
            loop.quit();
 
458
    }
 
459
 
 
460
private:
 
461
    QEventLoop loop;
 
462
};
 
463
 
 
464
WaitForQMyServer::WaitForQMyServer()
 
465
{
 
466
    QDBusConnection con = QDBusConnection::sessionBus();
 
467
    if (!ok()) {
 
468
        connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
 
469
                SLOT(ownerChange(QString)));
 
470
        QTimer::singleShot(2000, &loop, SLOT(quit()));
 
471
        loop.exec();
 
472
    }
 
473
}
 
474
 
 
475
bool WaitForQMyServer::ok()
 
476
{
 
477
    return QDBusConnection::sessionBus().isConnected() &&
 
478
        QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName);
 
479
}
 
480
 
 
481
void tst_QDBusAbstractAdaptor::initTestCase()
 
482
{
 
483
    commonInit();
 
484
 
 
485
    // start peer server
 
486
    #ifdef Q_OS_WIN
 
487
    proc.start("qmyserver");
 
488
    #else
 
489
    proc.start("./qmyserver/qmyserver");
 
490
    #endif
 
491
    QVERIFY(proc.waitForStarted());
 
492
 
 
493
    WaitForQMyServer w;
 
494
    QVERIFY(w.ok());
 
495
    //QTest::qWait(2000);
 
496
 
 
497
    // get peer server address
 
498
    QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "address");
 
499
    QDBusMessage rpl = QDBusConnection::sessionBus().call(req);
 
500
    QVERIFY(rpl.type() == QDBusMessage::ReplyMessage);
 
501
    QString address = rpl.arguments().at(0).toString();
 
502
 
 
503
    // connect to peer server
 
504
    QDBusConnection peercon = QDBusConnection::connectToPeer(address, "peer");
 
505
    QVERIFY(peercon.isConnected());
 
506
 
 
507
    QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "isConnected");
 
508
    QDBusMessage rpl2 = QDBusConnection::sessionBus().call(req2);
 
509
    QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage);
 
510
    QVERIFY(rpl2.arguments().at(0).toBool());
 
511
}
 
512
 
 
513
void tst_QDBusAbstractAdaptor::cleanupTestCase()
 
514
{
 
515
    proc.close();
 
516
    proc.kill();
 
517
}
 
518
 
 
519
void tst_QDBusAbstractAdaptor::methodCalls_data()
 
520
{
 
521
    QTest::addColumn<int>("nInterfaces");
 
522
    QTest::newRow("0") << 0;
 
523
    QTest::newRow("1") << 1;
 
524
    QTest::newRow("2") << 2;
 
525
    QTest::newRow("3") << 3;
 
526
    QTest::newRow("4") << 4;
 
527
}
 
528
 
 
529
void tst_QDBusAbstractAdaptor::methodCalls()
 
530
{
 
531
    QDBusConnection con = QDBusConnection::sessionBus();
 
532
    QVERIFY(con.isConnected());
 
533
 
 
534
    //QDBusInterface emptycon.baseService(), "/", QString());
 
535
 
 
536
    {
 
537
        // must fail: no object
 
538
        QDBusInterface if1(con.baseService(), "/", "local.Interface1", con);
 
539
        QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage);
 
540
    }
 
541
 
 
542
    QFETCH(int, nInterfaces);
 
543
    MyObject obj(nInterfaces);
 
544
    con.registerObject("/", &obj);
 
545
 
 
546
    QDBusInterface if1(con.baseService(), "/", "local.Interface1", con);
 
547
    QDBusInterface if2(con.baseService(), "/", "local.Interface2", con);
 
548
    QDBusInterface if3(con.baseService(), "/", "local.Interface3", con);
 
549
    QDBusInterface if4(con.baseService(), "/", "local.Interface4", con);
 
550
 
 
551
    // must fail: no such method
 
552
    QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage);
 
553
    if (!nInterfaces--)
 
554
        return;
 
555
    if (!nInterfaces--)
 
556
        return;
 
557
 
 
558
    // simple call: one such method exists
 
559
    QCOMPARE(if2.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage);
 
560
    QCOMPARE(slotSpy, "void Interface2::method()");
 
561
    if (!nInterfaces--)
 
562
        return;
 
563
 
 
564
    // multiple methods in multiple interfaces, no name overlap
 
565
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage);
 
566
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage);
 
567
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage);
 
568
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage);
 
569
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage);
 
570
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage);
 
571
 
 
572
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ReplyMessage);
 
573
    QCOMPARE(slotSpy, "void Interface3::methodVoid()");
 
574
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodInt", 42).type(), QDBusMessage::ReplyMessage);
 
575
    QCOMPARE(slotSpy, "void Interface3::methodInt(int)");
 
576
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodString", QString("")).type(), QDBusMessage::ReplyMessage);
 
577
    QCOMPARE(slotSpy, "void Interface3::methodString(QString)");
 
578
 
 
579
    if (!nInterfaces--)
 
580
        return;
 
581
 
 
582
    // method overloading: different interfaces
 
583
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage);
 
584
    QCOMPARE(slotSpy, "void Interface4::method()");
 
585
 
 
586
    // method overloading: different parameters
 
587
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method.i", 42).type(), QDBusMessage::ReplyMessage);
 
588
    QCOMPARE(slotSpy, "void Interface4::method(int)");
 
589
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method.s", QString()).type(), QDBusMessage::ReplyMessage);
 
590
    QCOMPARE(slotSpy, "void Interface4::method(QString)");
 
591
 
 
592
}
 
593
 
 
594
void tst_QDBusAbstractAdaptor::methodCallScriptable()
 
595
{
 
596
    QDBusConnection con = QDBusConnection::sessionBus();
 
597
    QVERIFY(con.isConnected());
 
598
 
 
599
    MyObject obj(2);
 
600
    con.registerObject("/", &obj);
 
601
 
 
602
    QDBusInterface if2(con.baseService(), "/", "local.Interface2", con);
 
603
 
 
604
    QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage);
 
605
    QCOMPARE(slotSpy, "void Interface2::scriptableMethod()");
 
606
}
 
607
 
 
608
static void emitSignal(MyObject *obj, const QString &iface, const QString &name,
 
609
                       const QVariant &parameter)
 
610
{
 
611
    if (iface.endsWith('2'))
 
612
        obj->if2->emitSignal(name, parameter);
 
613
    else if (iface.endsWith('3'))
 
614
        obj->if3->emitSignal(name, parameter);
 
615
    else if (iface.endsWith('4'))
 
616
        obj->if4->emitSignal(name, parameter);
 
617
    else
 
618
        obj->emitSignal(name, parameter);
 
619
 
 
620
    QTest::qWait(200);
 
621
}
 
622
 
 
623
void tst_QDBusAbstractAdaptor::signalEmissions_data()
 
624
{
 
625
    QTest::addColumn<QString>("interface");
 
626
    QTest::addColumn<QString>("name");
 
627
    QTest::addColumn<QString>("signature");
 
628
    QTest::addColumn<QVariant>("parameter");
 
629
 
 
630
    QTest::newRow("Interface2.signal") << "local.Interface2" << "signal" << QString() << QVariant();
 
631
    QTest::newRow("Interface3.signalVoid") << "local.Interface3" << "signalVoid" << QString() << QVariant();
 
632
    QTest::newRow("Interface3.signalInt") << "local.Interface3" << "signalInt" << "i" << QVariant(1);
 
633
    QTest::newRow("Interface3.signalString") << "local.Interface3" << "signalString" << "s" << QVariant("foo");
 
634
    QTest::newRow("MyObject.scriptableSignalVoid") << "local.MyObject" << "scriptableSignalVoid" << QString() << QVariant();
 
635
    QTest::newRow("MyObject.scriptableSignalInt") << "local.MyObject" << "scriptableSignalInt" << "i" << QVariant(1);
 
636
    QTest::newRow("MyObject.nySignalString") << "local.MyObject" << "scriptableSignalString" << "s" << QVariant("foo");
 
637
}
 
638
 
 
639
void tst_QDBusAbstractAdaptor::signalEmissions()
 
640
{
 
641
    QFETCH(QString, interface);
 
642
    QFETCH(QString, name);
 
643
    QFETCH(QVariant, parameter);
 
644
 
 
645
    QDBusConnection con = QDBusConnection::sessionBus();
 
646
    QVERIFY(con.isConnected());
 
647
    con.registerService("org.qtproject.tst_QDBusAbstractAdaptor");
 
648
 
 
649
    MyObject obj(3);
 
650
    con.registerObject("/", &obj, QDBusConnection::ExportAdaptors
 
651
                                  | QDBusConnection::ExportScriptableSignals);
 
652
 
 
653
    // connect all signals and emit only one
 
654
    {
 
655
        QDBusSignalSpy spy;
 
656
        con.connect(con.baseService(), "/", "local.Interface2", "signal",
 
657
                    &spy, SLOT(slot(QDBusMessage)));
 
658
        con.connect(con.baseService(), "/", "local.Interface3", "signalVoid",
 
659
                    &spy, SLOT(slot(QDBusMessage)));
 
660
        con.connect(con.baseService(), "/", "local.Interface3", "signalInt",
 
661
                    &spy, SLOT(slot(QDBusMessage)));
 
662
        con.connect(con.baseService(), "/", "local.Interface3", "signalString",
 
663
                    &spy, SLOT(slot(QDBusMessage)));
 
664
        con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalVoid",
 
665
                    &spy, SLOT(slot(QDBusMessage)));
 
666
        con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalInt",
 
667
                    &spy, SLOT(slot(QDBusMessage)));
 
668
        con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalString",
 
669
                    &spy, SLOT(slot(QDBusMessage)));
 
670
 
 
671
        emitSignal(&obj, interface, name, parameter);
 
672
 
 
673
        QCOMPARE(spy.count, 1);
 
674
        QCOMPARE(spy.interface, interface);
 
675
        QCOMPARE(spy.name, name);
 
676
        QTEST(spy.signature, "signature");
 
677
        QCOMPARE(spy.value, parameter);
 
678
    }
 
679
 
 
680
    // connect one signal and emit them all
 
681
    {
 
682
        QDBusSignalSpy spy;
 
683
        con.connect(con.baseService(), "/", interface, name, &spy, SLOT(slot(QDBusMessage)));
 
684
        emitSignal(&obj, "local.Interface2", "signal", QVariant());
 
685
        emitSignal(&obj, "local.Interface3", "signalVoid", QVariant());
 
686
        emitSignal(&obj, "local.Interface3", "signalInt", QVariant(1));
 
687
        emitSignal(&obj, "local.Interface3", "signalString", QVariant("foo"));
 
688
        emitSignal(&obj, "local.MyObject", "scriptableSignalVoid", QVariant());
 
689
        emitSignal(&obj, "local.MyObject", "scriptableSignalInt", QVariant(1));
 
690
        emitSignal(&obj, "local.MyObject", "scriptableSignalString", QVariant("foo"));
 
691
 
 
692
        QCOMPARE(spy.count, 1);
 
693
        QCOMPARE(spy.interface, interface);
 
694
        QCOMPARE(spy.name, name);
 
695
        QTEST(spy.signature, "signature");
 
696
        QCOMPARE(spy.value, parameter);
 
697
    }
 
698
}
 
699
 
 
700
void tst_QDBusAbstractAdaptor::sameSignalDifferentPaths()
 
701
{
 
702
    QDBusConnection con = QDBusConnection::sessionBus();
 
703
    QVERIFY(con.isConnected());
 
704
 
 
705
    MyObject obj(2);
 
706
 
 
707
    con.registerObject("/p1",&obj);
 
708
    con.registerObject("/p2",&obj);
 
709
 
 
710
    QDBusSignalSpy spy;
 
711
    con.connect(con.baseService(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
712
    obj.if2->emitSignal(QString(), QVariant());
 
713
    QTest::qWait(200);
 
714
 
 
715
    QCOMPARE(spy.count, 1);
 
716
    QCOMPARE(spy.interface, QString("local.Interface2"));
 
717
    QCOMPARE(spy.name, QString("signal"));
 
718
    QVERIFY(spy.signature.isEmpty());
 
719
 
 
720
    // now connect the other one
 
721
    spy.count = 0;
 
722
    con.connect(con.baseService(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
723
    obj.if2->emitSignal(QString(), QVariant());
 
724
    QTest::qWait(200);
 
725
 
 
726
    QCOMPARE(spy.count, 2);
 
727
}
 
728
 
 
729
void tst_QDBusAbstractAdaptor::sameObjectDifferentPaths()
 
730
{
 
731
    QDBusConnection con = QDBusConnection::sessionBus();
 
732
    QVERIFY(con.isConnected());
 
733
 
 
734
    MyObject obj(2);
 
735
 
 
736
    con.registerObject("/p1",&obj);
 
737
    con.registerObject("/p2",&obj, 0); // don't export anything
 
738
 
 
739
    QDBusSignalSpy spy;
 
740
    con.connect(con.baseService(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
741
    con.connect(con.baseService(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
742
    obj.if2->emitSignal(QString(), QVariant());
 
743
    QTest::qWait(200);
 
744
 
 
745
    QCOMPARE(spy.count, 1);
 
746
    QCOMPARE(spy.interface, QString("local.Interface2"));
 
747
    QCOMPARE(spy.name, QString("signal"));
 
748
    QVERIFY(spy.signature.isEmpty());
 
749
}
 
750
 
 
751
void tst_QDBusAbstractAdaptor::scriptableSignalOrNot()
 
752
{
 
753
    QDBusConnection con = QDBusConnection::sessionBus();
 
754
    QVERIFY(con.isConnected());
 
755
 
 
756
    {
 
757
        MyObject obj(0);
 
758
 
 
759
        con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals);
 
760
        con.registerObject("/p2",&obj, 0); // don't export anything
 
761
 
 
762
        QDBusSignalSpy spy;
 
763
        con.connect(con.baseService(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
764
        con.connect(con.baseService(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
765
        con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
766
        con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
767
        obj.emitSignal("scriptableSignalVoid", QVariant());
 
768
        obj.emitSignal("nonScriptableSignalVoid", QVariant());
 
769
        QTest::qWait(200);
 
770
 
 
771
        QCOMPARE(spy.count, 1);     // only /p1 must have emitted
 
772
        QCOMPARE(spy.interface, QString("local.MyObject"));
 
773
        QCOMPARE(spy.name, QString("scriptableSignalVoid"));
 
774
        QCOMPARE(spy.path, QString("/p1"));
 
775
        QVERIFY(spy.signature.isEmpty());
 
776
    }
 
777
 
 
778
    {
 
779
        MyObject obj(0);
 
780
 
 
781
        con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals);
 
782
        con.registerObject("/p2",&obj, QDBusConnection::ExportScriptableSignals
 
783
                                       | QDBusConnection::ExportNonScriptableSignals);
 
784
 
 
785
        QDBusSignalSpy spy;
 
786
        con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
787
        con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
788
        obj.emitSignal("nonScriptableSignalVoid", QVariant());
 
789
        QTest::qWait(200);
 
790
 
 
791
        QCOMPARE(spy.count, 1);     // only /p2 must have emitted now
 
792
        QCOMPARE(spy.interface, QString("local.MyObject"));
 
793
        QCOMPARE(spy.name, QString("nonScriptableSignalVoid"));
 
794
        QCOMPARE(spy.path, QString("/p2"));
 
795
        QVERIFY(spy.signature.isEmpty());
 
796
    }
 
797
 
 
798
    {
 
799
        QDBusSignalSpy spy;
 
800
        con.connect(con.baseService(), "/p1", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
 
801
        con.connect(con.baseService(), "/p2", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
 
802
 
 
803
        {
 
804
            MyObject obj(0);
 
805
 
 
806
            con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals);
 
807
            con.registerObject("/p2",&obj, QDBusConnection::ExportScriptableSignals
 
808
                                           | QDBusConnection::ExportNonScriptableSignals);
 
809
        } // <--- QObject emits the destroyed(QObject*) signal at this point
 
810
 
 
811
        QTest::qWait(200);
 
812
 
 
813
        QCOMPARE(spy.count, 0);
 
814
    }
 
815
}
 
816
 
 
817
void tst_QDBusAbstractAdaptor::overloadedSignalEmission_data()
 
818
{
 
819
    QTest::addColumn<QString>("signature");
 
820
    QTest::addColumn<QVariant>("parameter");
 
821
    QTest::newRow("void") << QString("") << QVariant();
 
822
    QTest::newRow("int") << "i" << QVariant(1);
 
823
    QTest::newRow("string") << "s" << QVariant("foo");
 
824
}
 
825
 
 
826
void tst_QDBusAbstractAdaptor::overloadedSignalEmission()
 
827
{
 
828
    QDBusConnection con = QDBusConnection::sessionBus();
 
829
    QVERIFY(con.isConnected());
 
830
 
 
831
    MyObject obj;
 
832
    con.registerObject("/", &obj);
 
833
 
 
834
    QString interface = "local.Interface4";
 
835
    QString name = "signal";
 
836
    QFETCH(QVariant, parameter);
 
837
    //QDBusInterface *if4 = new QDBusInterface(con.baseService(), "/", interface, con);
 
838
 
 
839
    // connect all signals and emit only one
 
840
    {
 
841
        QDBusSignalSpy spy;
 
842
        con.connect(con.baseService(), "/", "local.Interface4", "signal", "",
 
843
                    &spy, SLOT(slot(QDBusMessage)));
 
844
        con.connect(con.baseService(), "/", "local.Interface4", "signal", "i",
 
845
                    &spy, SLOT(slot(QDBusMessage)));
 
846
        con.connect(con.baseService(), "/", "local.Interface4", "signal", "s",
 
847
                    &spy, SLOT(slot(QDBusMessage)));
 
848
 
 
849
        emitSignal(&obj, interface, name, parameter);
 
850
 
 
851
        QCOMPARE(spy.count, 1);
 
852
        QCOMPARE(spy.interface, interface);
 
853
        QCOMPARE(spy.name, name);
 
854
        QTEST(spy.signature, "signature");
 
855
        QCOMPARE(spy.value, parameter);
 
856
    }
 
857
 
 
858
    QFETCH(QString, signature);
 
859
    // connect one signal and emit them all
 
860
    {
 
861
        QDBusSignalSpy spy;
 
862
        con.connect(con.baseService(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage)));
 
863
        emitSignal(&obj, "local.Interface4", "signal", QVariant());
 
864
        emitSignal(&obj, "local.Interface4", "signal", QVariant(1));
 
865
        emitSignal(&obj, "local.Interface4", "signal", QVariant("foo"));
 
866
 
 
867
        QCOMPARE(spy.count, 1);
 
868
        QCOMPARE(spy.interface, interface);
 
869
        QCOMPARE(spy.name, name);
 
870
        QTEST(spy.signature, "signature");
 
871
        QCOMPARE(spy.value, parameter);
 
872
    }
 
873
}
 
874
 
 
875
void tst_QDBusAbstractAdaptor::readProperties()
 
876
{
 
877
    QDBusConnection con = QDBusConnection::sessionBus();
 
878
    QVERIFY(con.isConnected());
 
879
 
 
880
    MyObject obj;
 
881
    con.registerObject("/", &obj);
 
882
 
 
883
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
884
    for (int i = 2; i <= 4; ++i) {
 
885
        QString name = QString("Interface%1").arg(i);
 
886
 
 
887
        for (int j = 1; j <= 2; ++j) {
 
888
            QString propname = QString("prop%1").arg(j);
 
889
            QDBusReply<QVariant> reply =
 
890
                properties.call(QDBus::BlockWithGui, "Get", "local." + name, propname);
 
891
            QVariant value = reply;
 
892
 
 
893
            QCOMPARE(value.userType(), int(QVariant::String));
 
894
            QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname));
 
895
        }
 
896
    }
 
897
}
 
898
 
 
899
void tst_QDBusAbstractAdaptor::readPropertiesInvalidInterface()
 
900
{
 
901
    QDBusConnection con = QDBusConnection::sessionBus();
 
902
    QVERIFY(con.isConnected());
 
903
 
 
904
    MyObject obj;
 
905
    con.registerObject("/", &obj);
 
906
 
 
907
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
908
 
 
909
    // test an invalid interface:
 
910
    QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "local.DoesntExist", "prop1");
 
911
    QVERIFY(!reply.isValid());
 
912
}
 
913
 
 
914
void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterface_data()
 
915
{
 
916
    QTest::addColumn<QVariantMap>("expectedProperties");
 
917
    QTest::addColumn<bool>("existing");
 
918
 
 
919
    QVariantMap expectedProperties;
 
920
    expectedProperties["prop1"] = QVariant();
 
921
    expectedProperties["prop2"] = QVariant();
 
922
    expectedProperties["interface3prop"] = "QString Interface3::interface3prop() const";
 
923
    expectedProperties["interface4prop"] = "QString Interface4::interface4prop() const";
 
924
    QTest::newRow("existing") << expectedProperties << true;
 
925
 
 
926
    expectedProperties.clear();
 
927
    expectedProperties["prop5"] = QVariant();
 
928
    expectedProperties["foobar"] = QVariant();
 
929
    QTest::newRow("non-existing") << expectedProperties << false;
 
930
}
 
931
 
 
932
void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterface()
 
933
{
 
934
    QDBusConnection con = QDBusConnection::sessionBus();
 
935
    QVERIFY(con.isConnected());
 
936
 
 
937
    MyObject obj;
 
938
    con.registerObject("/", &obj);
 
939
 
 
940
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
941
 
 
942
    QFETCH(QVariantMap, expectedProperties);
 
943
    QFETCH(bool, existing);
 
944
 
 
945
    QVariantMap::ConstIterator it = expectedProperties.constBegin();
 
946
    for ( ; it != expectedProperties.constEnd(); ++it) {
 
947
        QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "", it.key());
 
948
 
 
949
        if (existing) {
 
950
            QVERIFY2(reply.isValid(), qPrintable(it.key()));
 
951
        } else {
 
952
            QVERIFY2(!reply.isValid(), qPrintable(it.key()));
 
953
            continue;
 
954
        }
 
955
 
 
956
        QCOMPARE(int(reply.value().type()), int(QVariant::String));
 
957
        if (it.value().isValid())
 
958
            QCOMPARE(reply.value().toString(), it.value().toString());
 
959
    }
 
960
}
 
961
 
 
962
void tst_QDBusAbstractAdaptor::readAllProperties()
 
963
{
 
964
    QDBusConnection con = QDBusConnection::sessionBus();
 
965
    QVERIFY(con.isConnected());
 
966
 
 
967
    MyObject obj;
 
968
    con.registerObject("/", &obj);
 
969
 
 
970
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
971
    for (int i = 2; i <= 4; ++i) {
 
972
        QString name = QString("Interface%1").arg(i);
 
973
        QDBusReply<QVariantMap> reply =
 
974
            properties.call(QDBus::BlockWithGui, "GetAll", "local." + name);
 
975
 
 
976
        for (int j = 1; j <= 2; ++j) {
 
977
            QString propname = QString("prop%1").arg(j);
 
978
            QVERIFY2(reply.value().contains(propname),
 
979
                     qPrintable(propname + " on " + name));
 
980
            QVariant value = reply.value().value(propname);
 
981
 
 
982
            QCOMPARE(value.userType(), int(QVariant::String));
 
983
            QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname));
 
984
        }
 
985
    }
 
986
}
 
987
 
 
988
void tst_QDBusAbstractAdaptor::readAllPropertiesInvalidInterface()
 
989
{
 
990
    QDBusConnection con = QDBusConnection::sessionBus();
 
991
    QVERIFY(con.isConnected());
 
992
 
 
993
    MyObject obj;
 
994
    con.registerObject("/", &obj);
 
995
 
 
996
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
997
 
 
998
    // test an invalid interface:
 
999
    QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "local.DoesntExist");
 
1000
    QVERIFY(!reply.isValid());
 
1001
}
 
1002
 
 
1003
void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterface_data()
 
1004
{
 
1005
    readPropertiesEmptyInterface_data();
 
1006
}
 
1007
 
 
1008
void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterface()
 
1009
{
 
1010
    QDBusConnection con = QDBusConnection::sessionBus();
 
1011
    QVERIFY(con.isConnected());
 
1012
 
 
1013
    MyObject obj;
 
1014
    con.registerObject("/", &obj);
 
1015
 
 
1016
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
1017
 
 
1018
    QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "");
 
1019
    QVERIFY(reply.isValid());
 
1020
 
 
1021
    QVariantMap allprops = reply;
 
1022
 
 
1023
    QFETCH(QVariantMap, expectedProperties);
 
1024
    QFETCH(bool, existing);
 
1025
 
 
1026
    QVariantMap::ConstIterator it = expectedProperties.constBegin();
 
1027
    if (existing) {
 
1028
        for ( ; it != expectedProperties.constEnd(); ++it) {
 
1029
            QVERIFY2(allprops.contains(it.key()), qPrintable(it.key()));
 
1030
 
 
1031
            QVariant propvalue = allprops.value(it.key());
 
1032
            QVERIFY2(!propvalue.isNull(), qPrintable(it.key()));
 
1033
            QVERIFY2(propvalue.isValid(), qPrintable(it.key()));
 
1034
 
 
1035
            QString stringvalue = propvalue.toString();
 
1036
            QVERIFY2(!stringvalue.isEmpty(), qPrintable(it.key()));
 
1037
 
 
1038
            if (it.value().isValid())
 
1039
                QCOMPARE(stringvalue, it.value().toString());
 
1040
 
 
1041
            // remove this property from the map
 
1042
            allprops.remove(it.key());
 
1043
        }
 
1044
 
 
1045
        QVERIFY2(allprops.isEmpty(),
 
1046
                 qPrintable(QStringList(allprops.keys()).join(' ')));
 
1047
    } else {
 
1048
        for ( ; it != expectedProperties.constEnd(); ++it)
 
1049
            QVERIFY2(!allprops.contains(it.key()), qPrintable(it.key()));
 
1050
    }
 
1051
}
 
1052
 
 
1053
void tst_QDBusAbstractAdaptor::writeProperties()
 
1054
{
 
1055
    QDBusConnection con = QDBusConnection::sessionBus();
 
1056
    QVERIFY(con.isConnected());
 
1057
 
 
1058
    MyObject obj;
 
1059
    con.registerObject("/", &obj);
 
1060
 
 
1061
    QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con);
 
1062
    for (int i = 2; i <= 4; ++i) {
 
1063
        QString name = QString("Interface%1").arg(i);
 
1064
 
 
1065
        valueSpy.clear();
 
1066
        properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop1"),
 
1067
                        QVariant::fromValue(QDBusVariant(name)));
 
1068
        QVERIFY(valueSpy.isEmpty()); // call mustn't have succeeded
 
1069
 
 
1070
        properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop2"),
 
1071
                        QVariant::fromValue(QDBusVariant(name)));
 
1072
        QCOMPARE(valueSpy, name);
 
1073
        QCOMPARE(QString(slotSpy), QString("void %1::setProp2(const QString &)").arg(name));
 
1074
    }
 
1075
}
 
1076
 
 
1077
void tst_QDBusAbstractAdaptor::methodCallsPeer_data()
 
1078
{
 
1079
    methodCalls_data();
 
1080
}
 
1081
 
 
1082
void tst_QDBusAbstractAdaptor::methodCallsPeer()
 
1083
{
 
1084
    QDBusConnection con("peer");
 
1085
    QVERIFY(con.isConnected());
 
1086
 
 
1087
    {
 
1088
        // must fail: no object
 
1089
        QDBusInterface if1(QString(), "/", "local.Interface1", con);
 
1090
        QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage);
 
1091
    }
 
1092
 
 
1093
    QFETCH(int, nInterfaces);
 
1094
    newMyObjectPeer(nInterfaces);
 
1095
    registerMyObjectPeer("/");
 
1096
 
 
1097
    QDBusInterface if1(QString(), "/", "local.Interface1", con);
 
1098
    QDBusInterface if2(QString(), "/", "local.Interface2", con);
 
1099
    QDBusInterface if3(QString(), "/", "local.Interface3", con);
 
1100
    QDBusInterface if4(QString(), "/", "local.Interface4", con);
 
1101
 
 
1102
    // must fail: no such method
 
1103
    QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage);
 
1104
    if (!nInterfaces--)
 
1105
        return;
 
1106
    if (!nInterfaces--)
 
1107
        return;
 
1108
 
 
1109
    // simple call: one such method exists
 
1110
    QCOMPARE(if2.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage);
 
1111
    QCOMPARE(slotSpyPeer(), "void Interface2::method()");
 
1112
    if (!nInterfaces--)
 
1113
        return;
 
1114
 
 
1115
    // multiple methods in multiple interfaces, no name overlap
 
1116
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage);
 
1117
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage);
 
1118
    QCOMPARE(if1.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage);
 
1119
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage);
 
1120
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage);
 
1121
    QCOMPARE(if2.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage);
 
1122
 
 
1123
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ReplyMessage);
 
1124
    QCOMPARE(slotSpyPeer(), "void Interface3::methodVoid()");
 
1125
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodInt", 42).type(), QDBusMessage::ReplyMessage);
 
1126
    QCOMPARE(slotSpyPeer(), "void Interface3::methodInt(int)");
 
1127
    QCOMPARE(if3.call(QDBus::BlockWithGui, "methodString", QString("")).type(), QDBusMessage::ReplyMessage);
 
1128
    QCOMPARE(slotSpyPeer(), "void Interface3::methodString(QString)");
 
1129
 
 
1130
    if (!nInterfaces--)
 
1131
        return;
 
1132
 
 
1133
    // method overloading: different interfaces
 
1134
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage);
 
1135
    QCOMPARE(slotSpyPeer(), "void Interface4::method()");
 
1136
 
 
1137
    // method overloading: different parameters
 
1138
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method.i", 42).type(), QDBusMessage::ReplyMessage);
 
1139
    QCOMPARE(slotSpyPeer(), "void Interface4::method(int)");
 
1140
    QCOMPARE(if4.call(QDBus::BlockWithGui, "method.s", QString()).type(), QDBusMessage::ReplyMessage);
 
1141
    QCOMPARE(slotSpyPeer(), "void Interface4::method(QString)");
 
1142
}
 
1143
 
 
1144
void tst_QDBusAbstractAdaptor::methodCallScriptablePeer()
 
1145
{
 
1146
    QDBusConnection con("peer");
 
1147
    QVERIFY(con.isConnected());
 
1148
 
 
1149
    newMyObjectPeer(2);
 
1150
    registerMyObjectPeer("/");
 
1151
 
 
1152
    QDBusInterface if2(QString(), "/", "local.Interface2", con);
 
1153
 
 
1154
    QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage);
 
1155
    QCOMPARE(slotSpyPeer(), "void Interface2::scriptableMethod()");
 
1156
}
 
1157
 
 
1158
void tst_QDBusAbstractAdaptor::signalEmissionsPeer_data()
 
1159
{
 
1160
    signalEmissions_data();
 
1161
}
 
1162
 
 
1163
void tst_QDBusAbstractAdaptor::signalEmissionsPeer()
 
1164
{
 
1165
    QFETCH(QString, interface);
 
1166
    QFETCH(QString, name);
 
1167
    QFETCH(QVariant, parameter);
 
1168
 
 
1169
    QDBusConnection con("peer");
 
1170
    QVERIFY(con.isConnected());
 
1171
 
 
1172
    newMyObjectPeer(3);
 
1173
    registerMyObjectPeer("/", QDBusConnection::ExportAdaptors
 
1174
                            | QDBusConnection::ExportScriptableSignals);
 
1175
 
 
1176
    // connect all signals and emit only one
 
1177
    {
 
1178
        QDBusSignalSpy spy;
 
1179
        con.connect(QString(), "/", "local.Interface2", "signal",
 
1180
                    &spy, SLOT(slot(QDBusMessage)));
 
1181
        con.connect(QString(), "/", "local.Interface3", "signalVoid",
 
1182
                    &spy, SLOT(slot(QDBusMessage)));
 
1183
        con.connect(QString(), "/", "local.Interface3", "signalInt",
 
1184
                    &spy, SLOT(slot(QDBusMessage)));
 
1185
        con.connect(QString(), "/", "local.Interface3", "signalString",
 
1186
                    &spy, SLOT(slot(QDBusMessage)));
 
1187
        con.connect(QString(), "/", "local.MyObject", "scriptableSignalVoid",
 
1188
                    &spy, SLOT(slot(QDBusMessage)));
 
1189
        con.connect(QString(), "/", "local.MyObject", "scriptableSignalInt",
 
1190
                    &spy, SLOT(slot(QDBusMessage)));
 
1191
        con.connect(QString(), "/", "local.MyObject", "scriptableSignalString",
 
1192
                    &spy, SLOT(slot(QDBusMessage)));
 
1193
 
 
1194
        emitSignalPeer(interface, name, parameter);
 
1195
 
 
1196
        QCOMPARE(spy.count, 1);
 
1197
        QCOMPARE(spy.interface, interface);
 
1198
        QCOMPARE(spy.name, name);
 
1199
        QTEST(spy.signature, "signature");
 
1200
        QCOMPARE(spy.value, parameter);
 
1201
    }
 
1202
 
 
1203
    // connect one signal and emit them all
 
1204
    {
 
1205
        QDBusSignalSpy spy;
 
1206
        con.connect(QString(), "/", interface, name, &spy, SLOT(slot(QDBusMessage)));
 
1207
        emitSignalPeer("local.Interface2", "signal", QVariant());
 
1208
        emitSignalPeer("local.Interface3", "signalVoid", QVariant());
 
1209
        emitSignalPeer("local.Interface3", "signalInt", QVariant(1));
 
1210
        emitSignalPeer("local.Interface3", "signalString", QVariant("foo"));
 
1211
        emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant());
 
1212
        emitSignalPeer("local.MyObject", "scriptableSignalInt", QVariant(1));
 
1213
        emitSignalPeer("local.MyObject", "scriptableSignalString", QVariant("foo"));
 
1214
 
 
1215
        QCOMPARE(spy.count, 1);
 
1216
        QCOMPARE(spy.interface, interface);
 
1217
        QCOMPARE(spy.name, name);
 
1218
        QTEST(spy.signature, "signature");
 
1219
        QCOMPARE(spy.value, parameter);
 
1220
    }
 
1221
}
 
1222
 
 
1223
void tst_QDBusAbstractAdaptor::sameSignalDifferentPathsPeer()
 
1224
{
 
1225
    QDBusConnection con("peer");
 
1226
    QVERIFY(con.isConnected());
 
1227
 
 
1228
    newMyObjectPeer(2);
 
1229
 
 
1230
    registerMyObjectPeer("/p1");
 
1231
    registerMyObjectPeer("/p2");
 
1232
 
 
1233
    QDBusSignalSpy spy;
 
1234
    con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
1235
    emitSignalPeer("local.Interface2", QString(), QVariant());
 
1236
    QTest::qWait(200);
 
1237
 
 
1238
    QCOMPARE(spy.count, 1);
 
1239
    QCOMPARE(spy.interface, QString("local.Interface2"));
 
1240
    QCOMPARE(spy.name, QString("signal"));
 
1241
    QVERIFY(spy.signature.isEmpty());
 
1242
 
 
1243
    // now connect the other one
 
1244
    spy.count = 0;
 
1245
    con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
1246
    emitSignalPeer("local.Interface2", QString(), QVariant());
 
1247
    QTest::qWait(200);
 
1248
 
 
1249
    QCOMPARE(spy.count, 2);
 
1250
}
 
1251
 
 
1252
void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer()
 
1253
{
 
1254
    QDBusConnection con("peer");
 
1255
    QVERIFY(con.isConnected());
 
1256
 
 
1257
    newMyObjectPeer(2);
 
1258
 
 
1259
    registerMyObjectPeer("/p1");
 
1260
    registerMyObjectPeer("/p2", 0); // don't export anything
 
1261
 
 
1262
    QDBusSignalSpy spy;
 
1263
    con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
1264
    con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
 
1265
    emitSignalPeer("local.Interface2", QString(), QVariant());
 
1266
    QTest::qWait(200);
 
1267
 
 
1268
    QCOMPARE(spy.count, 1);
 
1269
    QCOMPARE(spy.interface, QString("local.Interface2"));
 
1270
    QCOMPARE(spy.name, QString("signal"));
 
1271
    QVERIFY(spy.signature.isEmpty());
 
1272
}
 
1273
 
 
1274
void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer()
 
1275
{
 
1276
    QDBusConnection con("peer");;
 
1277
    QVERIFY(con.isConnected());
 
1278
 
 
1279
    {
 
1280
        newMyObjectPeer(0);
 
1281
 
 
1282
        registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
 
1283
        registerMyObjectPeer("/p2", 0); // don't export anything
 
1284
 
 
1285
        QDBusSignalSpy spy;
 
1286
        con.connect(QString(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1287
        con.connect(QString(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1288
        con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1289
        con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1290
        emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant());
 
1291
        emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant());
 
1292
        QTest::qWait(200);
 
1293
 
 
1294
        QCOMPARE(spy.count, 1);     // only /p1 must have emitted
 
1295
        QCOMPARE(spy.interface, QString("local.MyObject"));
 
1296
        QCOMPARE(spy.name, QString("scriptableSignalVoid"));
 
1297
        QCOMPARE(spy.path, QString("/p1"));
 
1298
        QVERIFY(spy.signature.isEmpty());
 
1299
    }
 
1300
 
 
1301
    {
 
1302
        newMyObjectPeer(0);
 
1303
 
 
1304
        registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
 
1305
        registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals
 
1306
                                | QDBusConnection::ExportNonScriptableSignals);
 
1307
 
 
1308
        QDBusSignalSpy spy;
 
1309
        con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1310
        con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
 
1311
        emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant());
 
1312
        QTest::qWait(200);
 
1313
 
 
1314
        QCOMPARE(spy.count, 1);     // only /p2 must have emitted now
 
1315
        QCOMPARE(spy.interface, QString("local.MyObject"));
 
1316
        QCOMPARE(spy.name, QString("nonScriptableSignalVoid"));
 
1317
        QCOMPARE(spy.path, QString("/p2"));
 
1318
        QVERIFY(spy.signature.isEmpty());
 
1319
    }
 
1320
 
 
1321
    {
 
1322
        QDBusSignalSpy spy;
 
1323
        con.connect(QString(), "/p1", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
 
1324
        con.connect(QString(), "/p2", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
 
1325
 
 
1326
        {
 
1327
            newMyObjectPeer(0);
 
1328
 
 
1329
            registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
 
1330
            registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals
 
1331
                                    | QDBusConnection::ExportNonScriptableSignals);
 
1332
        } // <--- QObject emits the destroyed(QObject*) signal at this point
 
1333
 
 
1334
        QTest::qWait(200);
 
1335
 
 
1336
        QCOMPARE(spy.count, 0);
 
1337
    }
 
1338
}
 
1339
 
 
1340
void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer_data()
 
1341
{
 
1342
    overloadedSignalEmission_data();
 
1343
}
 
1344
 
 
1345
void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer()
 
1346
{
 
1347
    QDBusConnection con("peer");
 
1348
    QVERIFY(con.isConnected());
 
1349
 
 
1350
    newMyObjectPeer();
 
1351
    registerMyObjectPeer("/");
 
1352
 
 
1353
    QString interface = "local.Interface4";
 
1354
    QString name = "signal";
 
1355
    QFETCH(QVariant, parameter);
 
1356
    //QDBusInterface *if4 = new QDBusInterface(QString(), "/", interface, con);
 
1357
 
 
1358
    // connect all signals and emit only one
 
1359
    {
 
1360
        QDBusSignalSpy spy;
 
1361
        con.connect(QString(), "/", "local.Interface4", "signal", "",
 
1362
                    &spy, SLOT(slot(QDBusMessage)));
 
1363
        con.connect(QString(), "/", "local.Interface4", "signal", "i",
 
1364
                    &spy, SLOT(slot(QDBusMessage)));
 
1365
        con.connect(QString(), "/", "local.Interface4", "signal", "s",
 
1366
                    &spy, SLOT(slot(QDBusMessage)));
 
1367
 
 
1368
        emitSignalPeer(interface, name, parameter);
 
1369
 
 
1370
        QCOMPARE(spy.count, 1);
 
1371
        QCOMPARE(spy.interface, interface);
 
1372
        QCOMPARE(spy.name, name);
 
1373
        QTEST(spy.signature, "signature");
 
1374
        QCOMPARE(spy.value, parameter);
 
1375
    }
 
1376
 
 
1377
    QFETCH(QString, signature);
 
1378
    // connect one signal and emit them all
 
1379
    {
 
1380
        QDBusSignalSpy spy;
 
1381
        con.connect(QString(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage)));
 
1382
        emitSignalPeer("local.Interface4", "signal", QVariant());
 
1383
        emitSignalPeer("local.Interface4", "signal", QVariant(1));
 
1384
        emitSignalPeer("local.Interface4", "signal", QVariant("foo"));
 
1385
 
 
1386
        QCOMPARE(spy.count, 1);
 
1387
        QCOMPARE(spy.interface, interface);
 
1388
        QCOMPARE(spy.name, name);
 
1389
        QTEST(spy.signature, "signature");
 
1390
        QCOMPARE(spy.value, parameter);
 
1391
    }
 
1392
}
 
1393
 
 
1394
void tst_QDBusAbstractAdaptor::readPropertiesPeer()
 
1395
{
 
1396
    QDBusConnection con("peer");
 
1397
    QVERIFY(con.isConnected());
 
1398
 
 
1399
    newMyObjectPeer();
 
1400
    registerMyObjectPeer("/");
 
1401
 
 
1402
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1403
    for (int i = 2; i <= 4; ++i) {
 
1404
        QString name = QString("Interface%1").arg(i);
 
1405
 
 
1406
        for (int j = 1; j <= 2; ++j) {
 
1407
            QString propname = QString("prop%1").arg(j);
 
1408
            QDBusReply<QVariant> reply =
 
1409
                properties.call(QDBus::BlockWithGui, "Get", "local." + name, propname);
 
1410
            QVariant value = reply;
 
1411
 
 
1412
            QCOMPARE(value.userType(), int(QVariant::String));
 
1413
            QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname));
 
1414
        }
 
1415
    }
 
1416
}
 
1417
 
 
1418
void tst_QDBusAbstractAdaptor::readPropertiesInvalidInterfacePeer()
 
1419
{
 
1420
    QDBusConnection con("peer");
 
1421
    QVERIFY(con.isConnected());
 
1422
 
 
1423
    newMyObjectPeer();
 
1424
    registerMyObjectPeer("/");
 
1425
 
 
1426
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1427
 
 
1428
    // test an invalid interface:
 
1429
    QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "local.DoesntExist", "prop1");
 
1430
    QVERIFY(!reply.isValid());
 
1431
}
 
1432
 
 
1433
void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer_data()
 
1434
{
 
1435
    readPropertiesEmptyInterface_data();
 
1436
}
 
1437
 
 
1438
void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer()
 
1439
{
 
1440
    QDBusConnection con("peer");
 
1441
    QVERIFY(con.isConnected());
 
1442
 
 
1443
    newMyObjectPeer();
 
1444
    registerMyObjectPeer("/");
 
1445
 
 
1446
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1447
 
 
1448
    QFETCH(QVariantMap, expectedProperties);
 
1449
    QFETCH(bool, existing);
 
1450
 
 
1451
    QVariantMap::ConstIterator it = expectedProperties.constBegin();
 
1452
    for ( ; it != expectedProperties.constEnd(); ++it) {
 
1453
        QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "", it.key());
 
1454
 
 
1455
        if (existing) {
 
1456
            QVERIFY2(reply.isValid(), qPrintable(it.key()));
 
1457
        } else {
 
1458
            QVERIFY2(!reply.isValid(), qPrintable(it.key()));
 
1459
            continue;
 
1460
        }
 
1461
 
 
1462
        QCOMPARE(int(reply.value().type()), int(QVariant::String));
 
1463
        if (it.value().isValid())
 
1464
            QCOMPARE(reply.value().toString(), it.value().toString());
 
1465
    }
 
1466
}
 
1467
 
 
1468
void tst_QDBusAbstractAdaptor::readAllPropertiesPeer()
 
1469
{
 
1470
    QDBusConnection con("peer");
 
1471
    QVERIFY(con.isConnected());
 
1472
 
 
1473
    newMyObjectPeer();
 
1474
    registerMyObjectPeer("/");
 
1475
 
 
1476
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1477
    for (int i = 2; i <= 4; ++i) {
 
1478
        QString name = QString("Interface%1").arg(i);
 
1479
        QDBusReply<QVariantMap> reply =
 
1480
            properties.call(QDBus::BlockWithGui, "GetAll", "local." + name);
 
1481
 
 
1482
        for (int j = 1; j <= 2; ++j) {
 
1483
            QString propname = QString("prop%1").arg(j);
 
1484
            QVERIFY2(reply.value().contains(propname),
 
1485
                     qPrintable(propname + " on " + name));
 
1486
            QVariant value = reply.value().value(propname);
 
1487
 
 
1488
            QCOMPARE(value.userType(), int(QVariant::String));
 
1489
            QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname));
 
1490
        }
 
1491
    }
 
1492
}
 
1493
 
 
1494
void tst_QDBusAbstractAdaptor::readAllPropertiesInvalidInterfacePeer()
 
1495
{
 
1496
    QDBusConnection con("peer");
 
1497
    QVERIFY(con.isConnected());
 
1498
 
 
1499
    newMyObjectPeer();
 
1500
    registerMyObjectPeer("/");
 
1501
 
 
1502
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1503
 
 
1504
    // test an invalid interface:
 
1505
    QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "local.DoesntExist");
 
1506
    QVERIFY(!reply.isValid());
 
1507
}
 
1508
 
 
1509
void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer_data()
 
1510
{
 
1511
    readAllPropertiesEmptyInterface_data();
 
1512
}
 
1513
 
 
1514
void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer()
 
1515
{
 
1516
    QDBusConnection con("peer");
 
1517
    QVERIFY(con.isConnected());
 
1518
 
 
1519
    newMyObjectPeer();
 
1520
    registerMyObjectPeer("/");
 
1521
 
 
1522
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1523
 
 
1524
    QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "");
 
1525
    QVERIFY(reply.isValid());
 
1526
 
 
1527
    QVariantMap allprops = reply;
 
1528
 
 
1529
    QFETCH(QVariantMap, expectedProperties);
 
1530
    QFETCH(bool, existing);
 
1531
 
 
1532
    QVariantMap::ConstIterator it = expectedProperties.constBegin();
 
1533
    if (existing) {
 
1534
        for ( ; it != expectedProperties.constEnd(); ++it) {
 
1535
            QVERIFY2(allprops.contains(it.key()), qPrintable(it.key()));
 
1536
 
 
1537
            QVariant propvalue = allprops.value(it.key());
 
1538
            QVERIFY2(!propvalue.isNull(), qPrintable(it.key()));
 
1539
            QVERIFY2(propvalue.isValid(), qPrintable(it.key()));
 
1540
 
 
1541
            QString stringvalue = propvalue.toString();
 
1542
            QVERIFY2(!stringvalue.isEmpty(), qPrintable(it.key()));
 
1543
 
 
1544
            if (it.value().isValid())
 
1545
                QCOMPARE(stringvalue, it.value().toString());
 
1546
 
 
1547
            // remove this property from the map
 
1548
            allprops.remove(it.key());
 
1549
        }
 
1550
 
 
1551
        QVERIFY2(allprops.isEmpty(),
 
1552
                 qPrintable(QStringList(allprops.keys()).join(' ')));
 
1553
    } else {
 
1554
        for ( ; it != expectedProperties.constEnd(); ++it)
 
1555
            QVERIFY2(!allprops.contains(it.key()), qPrintable(it.key()));
 
1556
    }
 
1557
}
 
1558
 
 
1559
void tst_QDBusAbstractAdaptor::writePropertiesPeer()
 
1560
{
 
1561
    QDBusConnection con("peer");
 
1562
    QVERIFY(con.isConnected());
 
1563
 
 
1564
    newMyObjectPeer();
 
1565
    registerMyObjectPeer("/");
 
1566
 
 
1567
    QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
 
1568
    for (int i = 2; i <= 4; ++i) {
 
1569
        QString name = QString("Interface%1").arg(i);
 
1570
 
 
1571
        clearValueSpyPeer();
 
1572
        properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop1"),
 
1573
                        QVariant::fromValue(QDBusVariant(name)));
 
1574
        QVERIFY(valueSpyPeer().isEmpty()); // call mustn't have succeeded
 
1575
 
 
1576
        properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop2"),
 
1577
                        QVariant::fromValue(QDBusVariant(name)));
 
1578
        QCOMPARE(valueSpyPeer(), name);
 
1579
        QCOMPARE(QString(slotSpyPeer()), QString("void %1::setProp2(const QString &)").arg(name));
 
1580
    }
 
1581
}
 
1582
 
 
1583
#if 0
 
1584
void tst_QDBusAbstractAdaptor::adaptorIntrospection_data()
 
1585
{
 
1586
    methodCalls_data();
 
1587
}
 
1588
 
 
1589
void tst_QDBusAbstractAdaptor::adaptorIntrospection()
 
1590
{
 
1591
    QDBusConnection con = QDBus::sessionBus();
 
1592
    QVERIFY(con.isConnected());
 
1593
 
 
1594
    QObject obj;
 
1595
    con.registerObject("/", &obj);
 
1596
 
 
1597
    QFETCH(int, nInterfaces);
 
1598
    switch (nInterfaces)
 
1599
    {
 
1600
    case 4:
 
1601
        new Interface4(&obj);
 
1602
    case 3:
 
1603
        new Interface3(&obj);
 
1604
    case 2:
 
1605
        new Interface2(&obj);
 
1606
    case 1:
 
1607
        new Interface1(&obj);
 
1608
    }
 
1609
 
 
1610
    QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1611
    QVERIFY(dobj.isValid());
 
1612
 
 
1613
    QString xml = dobj.introspect();
 
1614
    QVERIFY(!xml.isEmpty());
 
1615
 
 
1616
    QStringList interfaces = dobj.interfaces();
 
1617
    QCOMPARE(interfaces.count(), nInterfaces + 2);
 
1618
    switch (nInterfaces)
 
1619
    {
 
1620
    case 4: {
 
1621
        QVERIFY(interfaces.contains("local.Interface4"));
 
1622
        QDBusInterface iface(dobj, "local.Interface4");
 
1623
        QCOMPARE(iface.methodData(), Interface4::methodData);
 
1624
        QCOMPARE(iface.signalData(), Interface4::signalData);
 
1625
        QCOMPARE(iface.propertyData(), Interface4::propertyData);
 
1626
    }
 
1627
    case 3: {
 
1628
        QVERIFY(interfaces.contains("local.Interface3"));
 
1629
        QDBusInterface iface(dobj, "local.Interface3");
 
1630
        QCOMPARE(iface.methodData(), Interface3::methodData);
 
1631
        QCOMPARE(iface.signalData(), Interface3::signalData);
 
1632
        QCOMPARE(iface.propertyData(), Interface3::propertyData);
 
1633
    }
 
1634
    case 2: {
 
1635
        QVERIFY(interfaces.contains("local.Interface2"));
 
1636
        QDBusInterface iface(dobj, "local.Interface2");
 
1637
        QCOMPARE(iface.methodData(), Interface2::methodData);
 
1638
        QCOMPARE(iface.signalData(), Interface2::signalData);
 
1639
        QCOMPARE(iface.propertyData(), Interface2::propertyData);
 
1640
    }
 
1641
    case 1: {
 
1642
        QVERIFY(interfaces.contains("local.Interface1"));
 
1643
        QDBusInterface iface(dobj, "local.Interface1");
 
1644
        QCOMPARE(iface.methodData(), Interface1::methodData);
 
1645
        QCOMPARE(iface.signalData(), Interface1::signalData);
 
1646
        QCOMPARE(iface.propertyData(), Interface1::propertyData);
 
1647
    }
 
1648
    }
 
1649
}
 
1650
 
 
1651
void tst_QDBusAbstractAdaptor::objectTreeIntrospection()
 
1652
{
 
1653
    QDBusConnection con = QDBus::sessionBus();
 
1654
    QVERIFY(con.isConnected());
 
1655
 
 
1656
    {
 
1657
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1658
        QString xml = dobj.introspect();
 
1659
 
 
1660
        QDBusIntrospection::Object tree =
 
1661
            QDBusIntrospection::parseObject(xml);
 
1662
        QVERIFY(tree.childObjects.isEmpty());
 
1663
    }
 
1664
 
 
1665
    QObject root;
 
1666
    con.registerObject("/", &root);
 
1667
    {
 
1668
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1669
        QString xml = dobj.introspect();
 
1670
 
 
1671
        QDBusIntrospection::Object tree =
 
1672
            QDBusIntrospection::parseObject(xml);
 
1673
        QVERIFY(tree.childObjects.isEmpty());
 
1674
    }
 
1675
 
 
1676
    QObject p1;
 
1677
    con.registerObject("/p1", &p1);
 
1678
    {
 
1679
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1680
        QString xml = dobj.introspect();
 
1681
 
 
1682
        QDBusIntrospection::Object tree =
 
1683
            QDBusIntrospection::parseObject(xml);
 
1684
        QVERIFY(tree.childObjects.contains("p1"));
 
1685
    }
 
1686
 
 
1687
    con.unregisterObject("/");
 
1688
    {
 
1689
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1690
        QString xml = dobj.introspect();
 
1691
 
 
1692
        QDBusIntrospection::Object tree =
 
1693
            QDBusIntrospection::parseObject(xml);
 
1694
        QVERIFY(tree.childObjects.contains("p1"));
 
1695
    }
 
1696
 
 
1697
    con.registerObject("/p1/q/r", &root);
 
1698
    {
 
1699
        QDBusObject dobj = con.findObject(con.baseService(), "/p1");
 
1700
        QString xml = dobj.introspect();
 
1701
 
 
1702
        QDBusIntrospection::Object tree =
 
1703
            QDBusIntrospection::parseObject(xml);
 
1704
        QVERIFY(tree.childObjects.contains("q"));
 
1705
    }
 
1706
    {
 
1707
        QDBusObject dobj = con.findObject(con.baseService(), "/p1/q");
 
1708
        QString xml = dobj.introspect();
 
1709
 
 
1710
        QDBusIntrospection::Object tree =
 
1711
            QDBusIntrospection::parseObject(xml);
 
1712
        QVERIFY(tree.childObjects.contains("r"));
 
1713
    }
 
1714
 
 
1715
    con.unregisterObject("/p1", QDBusConnection::UnregisterTree);
 
1716
    {
 
1717
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1718
        QString xml = dobj.introspect();
 
1719
 
 
1720
        QDBusIntrospection::Object tree =
 
1721
            QDBusIntrospection::parseObject(xml);
 
1722
        QVERIFY(tree.childObjects.isEmpty());
 
1723
    }
 
1724
 
 
1725
    QObject p2;
 
1726
    con.registerObject("/p2", &p2, QDBusConnection::ExportChildObjects);
 
1727
    {
 
1728
        QDBusObject dobj = con.findObject(con.baseService(), "/");
 
1729
        QString xml = dobj.introspect();
 
1730
 
 
1731
        QDBusIntrospection::Object tree =
 
1732
            QDBusIntrospection::parseObject(xml);
 
1733
        QVERIFY(!tree.childObjects.contains("p1"));
 
1734
        QVERIFY(tree.childObjects.contains("p2"));
 
1735
    }
 
1736
 
 
1737
    QObject q;
 
1738
    q.setParent(&p2);
 
1739
    {
 
1740
        QDBusObject dobj = con.findObject(con.baseService(), "/p2");
 
1741
        QString xml = dobj.introspect();
 
1742
 
 
1743
        QDBusIntrospection::Object tree =
 
1744
            QDBusIntrospection::parseObject(xml);
 
1745
        QVERIFY(!tree.childObjects.contains("q"));
 
1746
    }
 
1747
 
 
1748
    q.setObjectName("q");
 
1749
    {
 
1750
        QDBusObject dobj = con.findObject(con.baseService(), "/p2");
 
1751
        QString xml = dobj.introspect();
 
1752
 
 
1753
        QDBusIntrospection::Object tree =
 
1754
            QDBusIntrospection::parseObject(xml);
 
1755
        QVERIFY(tree.childObjects.contains("q"));
 
1756
    }
 
1757
 
 
1758
    q.setParent(0);
 
1759
    {
 
1760
        QDBusObject dobj = con.findObject(con.baseService(), "/p2");
 
1761
        QString xml = dobj.introspect();
 
1762
 
 
1763
        QDBusIntrospection::Object tree =
 
1764
            QDBusIntrospection::parseObject(xml);
 
1765
        QVERIFY(!tree.childObjects.contains("q"));
 
1766
    }
 
1767
}
 
1768
#endif
 
1769
 
 
1770
void tst_QDBusAbstractAdaptor::typeMatching_data()
 
1771
{
 
1772
    QTest::addColumn<QString>("basename");
 
1773
    QTest::addColumn<QString>("signature");
 
1774
    QTest::addColumn<QVariant>("value");
 
1775
 
 
1776
    QTest::newRow("bool") << "Bool" << "b" << QVariant(true);
 
1777
    QTest::newRow("byte") << "UChar" << "y" << QVariant::fromValue(uchar(42));
 
1778
    QTest::newRow("short") << "Short" << "n" << QVariant::fromValue(short(-43));
 
1779
    QTest::newRow("ushort") << "UShort" << "q" << QVariant::fromValue(ushort(44));
 
1780
    QTest::newRow("int") << "Int" << "i" << QVariant(42);
 
1781
    QTest::newRow("uint") << "UInt" << "u" << QVariant(42U);
 
1782
    QTest::newRow("qlonglong") << "LongLong" << "x" << QVariant(Q_INT64_C(42));
 
1783
    QTest::newRow("qulonglong") << "ULongLong" << "t" << QVariant(Q_UINT64_C(42));
 
1784
    QTest::newRow("double") << "Double" << "d" << QVariant(2.5);
 
1785
    QTest::newRow("string") << "String" << "s" << QVariant("Hello, World!");
 
1786
 
 
1787
    QTest::newRow("variant") << "Variant" << "v" << QVariant::fromValue(QDBusVariant("Hello again!"));
 
1788
    QTest::newRow("list") << "List" << "av" << QVariant(QVariantList()
 
1789
                                                        << 42
 
1790
                                                        << QString("foo")
 
1791
                                                        << QByteArray("bar")
 
1792
                                                        << QVariant::fromValue(QDBusVariant(QString("baz"))));
 
1793
    QTest::newRow("stringlist") << "StringList" << "as" << QVariant(QStringList() << "Hello" << "world");
 
1794
    QTest::newRow("bytearray") << "ByteArray" << "ay" << QVariant(QByteArray("foo"));
 
1795
 
 
1796
    QVariantMap map;
 
1797
    map["one"] = 1;       // int
 
1798
    map["The answer to life, the Universe and everything"] = 42u; // uint
 
1799
    map["In the beginning..."] = QString("There was nothing"); // string
 
1800
    map["but Unix came and said"] = QByteArray("\"Hello, World\""); // bytearray
 
1801
    map["two"] = QVariant::fromValue(short(2)); // short
 
1802
    QTest::newRow("map") << "Map" << "a{sv}" << QVariant(map);
 
1803
 
 
1804
    StringStringMap ssmap;
 
1805
    ssmap["a"] = "A";
 
1806
    ssmap["A"] = "a";
 
1807
    QTest::newRow("ssmap") << "SSMap" << "a{ss}" << QVariant::fromValue(ssmap);
 
1808
 
 
1809
    LLDateTimeMap lldtmap;
 
1810
    lldtmap[-1] = QDateTime();
 
1811
    QDateTime now = QDateTime::currentDateTime();
 
1812
    lldtmap[now.toTime_t()] = now; // array of struct of int64 and struct of 3 ints and struct of 4 ints and int
 
1813
    QTest::newRow("lldtmap") << "LLDateTimeMap" << "a{x((iii)(iiii)i)}" << QVariant::fromValue(lldtmap);
 
1814
 
 
1815
    MyStruct s;
 
1816
    s.i = 42;
 
1817
    s.s = "A value";
 
1818
    QTest::newRow("struct") << "Struct" << "(is)" << QVariant::fromValue(s);
 
1819
}
 
1820
 
 
1821
void tst_QDBusAbstractAdaptor::typeMatching()
 
1822
{
 
1823
    QObject obj;
 
1824
    new TypesInterface(&obj);
 
1825
 
 
1826
    QDBusConnection con = QDBusConnection::sessionBus();
 
1827
    con.registerObject("/types", &obj);
 
1828
 
 
1829
    QFETCH(QString, basename);
 
1830
    QFETCH(QString, signature);
 
1831
    QFETCH(QVariant, value);
 
1832
 
 
1833
    QDBusMessage reply;
 
1834
    QDBusInterface iface(con.baseService(), "/types", "local.TypesInterface", con);
 
1835
 
 
1836
    reply = iface.callWithArgumentList(QDBus::BlockWithGui, "method" + basename,
 
1837
                                        QVariantList() << value);
 
1838
    QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
 
1839
 
 
1840
    reply = iface.call(QDBus::BlockWithGui, "retrieve" + basename);
 
1841
    QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
 
1842
    QCOMPARE(reply.arguments().count(), 1);
 
1843
 
 
1844
    const QVariant &retval = reply.arguments().at(0);
 
1845
    QVERIFY(compare(retval, value));
 
1846
}
 
1847
 
 
1848
void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValue()
 
1849
{
 
1850
    QDBusConnection con = QDBusConnection::sessionBus();
 
1851
    QVERIFY(con.isConnected());
 
1852
 
 
1853
    MyObject obj;
 
1854
    con.registerObject("/", &obj);
 
1855
 
 
1856
    QString testString = "This is a test string.";
 
1857
 
 
1858
    QDBusInterface remote(con.baseService(), "/", "local.Interface3", con);
 
1859
    QDBusMessage reply = remote.call(QDBus::BlockWithGui, "methodStringString", testString);
 
1860
    QVERIFY(reply.arguments().count() == 2);
 
1861
 
 
1862
    QDBusReply<int> intreply = reply;
 
1863
    QVERIFY(intreply.isValid());
 
1864
    QCOMPARE(intreply.value(), 42);
 
1865
 
 
1866
    QCOMPARE(reply.arguments().at(1).userType(), int(QVariant::String));
 
1867
    QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString);
 
1868
}
 
1869
 
 
1870
void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValuePeer()
 
1871
{
 
1872
    QDBusConnection con("peer");
 
1873
    QVERIFY(con.isConnected());
 
1874
 
 
1875
    newMyObjectPeer();
 
1876
    registerMyObjectPeer("/");
 
1877
 
 
1878
    QString testString = "This is a test string.";
 
1879
 
 
1880
    QDBusInterface remote(QString(), "/", "local.Interface3", con);
 
1881
    QDBusMessage reply = remote.call(QDBus::BlockWithGui, "methodStringString", testString);
 
1882
    QVERIFY(reply.arguments().count() == 2);
 
1883
 
 
1884
    QDBusReply<int> intreply = reply;
 
1885
    QVERIFY(intreply.isValid());
 
1886
    QCOMPARE(intreply.value(), 42);
 
1887
 
 
1888
    QCOMPARE(reply.arguments().at(1).userType(), int(QVariant::String));
 
1889
    QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString);
 
1890
}
 
1891
 
 
1892
QTEST_MAIN(tst_QDBusAbstractAdaptor)
 
1893
 
 
1894
#include "tst_qdbusabstractadaptor.moc"