1
2/****************************************************************************
3**
4** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
5** Contact: http://www.qt-project.org/legal
6**
7** This file is part of the QtSystems module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL21$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see http://www.qt.io/terms-conditions. For further
16** information use the contact form at http://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 2.1 or version 3 as published by the Free
21** Software Foundation and appearing in the file LICENSE.LGPLv21 and
22** LICENSE.LGPLv3 included in the packaging of this file. Please review the
23** following information to ensure the GNU Lesser General Public License
24** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
25** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26**
27** As a special exception, The Qt Company gives you certain additional
28** rights. These rights are described in The Qt Company LGPL Exception
29** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
30**
31** $QT_END_LICENSE$
32**
33****************************************************************************/
34
35//TESTED_COMPONENT=src/serviceframework
36
37#include <QCoreApplication>
38#include "qservicemanager.h"
39#include "qservicefilter.h"
40#include <QTimer>
41#include <QMetaObject>
42#include <QMetaMethod>
43#include <QThread>
44#include <QtTest/QtTest>
45#include <qservice.h>
46#include <qremoteserviceregister.h>
47#include <qservicereply.h>
48
49#include <signal.h>
50
51#ifdef SFW_USE_DBUS_BACKEND
52#include <QtDBus/QtDBus>
53#if QT_VERSION < 0x040800
54inline QDBusArgument &operator<<(QDBusArgument &arg, const QVariantHash &map)
55{
56 arg.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>());
57 QVariantHash::ConstIterator it = map.constBegin();
58 QVariantHash::ConstIterator end = map.constEnd();
59 for ( ; it != end; ++it) {
60 arg.beginMapEntry();
61 arg << it.key() << QDBusVariant(it.value());
62 arg.endMapEntry();
63 }
64 arg.endMap();
65 return arg;
66}
67#endif
68#endif
69
70
71#ifdef Q_OS_MAC
72#include <stdlib.h>
73#include <sys/resource.h>
74#endif
75
76QT_USE_NAMESPACE
77Q_DECLARE_METATYPE(QServiceFilter);
78Q_DECLARE_METATYPE(QVariant);
79Q_DECLARE_METATYPE(QList<QString>);
80Q_DECLARE_METATYPE(QVariantHash);
81
82char serviceReuqestXml[] =
83 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
84 "<SFW version=\"1.1\">"
85 "<service>"
86 "<name>com.nokia.mt.processmanager</name>"
87 "<ipcaddress>com.nokia.mt.processmanager.ServiceRequestSocket</ipcaddress>"
88 "<interface>"
89 "<name>com.nokia.mt.processmanager.ProcessManagerController</name>"
90 "<version>1.0</version>"
91 "</interface>"
92 "</service>"
93 "</SFW>";
94
95char serviceReuqestXmlFake[] =
96 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
97 "<SFW version=\"1.1\">"
98 "<service>"
99 "<name>com.nokia.qt.does.not.exist</name>"
100 "<ipcaddress>com.nokia.qt.does.not.exist</ipcaddress>"
101 "<interface>"
102 "<name>com.nokia.qt.interface.does.not.exist</name>"
103 "<version>1.0</version>"
104 "</interface>"
105 "</service>"
106 "</SFW>";
107
108char serviceReuqestXmlStarted[] =
109 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
110 "<SFW version=\"1.1\">"
111 "<service>"
112 "<name>com.nokia.qt.tests.autostart</name>"
113 "<ipcaddress>com.nokia.qt.tests.autostart</ipcaddress>"
114 "<interface>"
115 "<name>com.nokkia.qt.tests.autostarted</name>"
116 "<version>1.0</version>"
117 "</interface>"
118 "</service>"
119 "</SFW>";
120
121
122class ServiceRequest : public QObject
123{
124 Q_OBJECT
125public:
126 ServiceRequest(QObject *o = 0) : QObject(o)
127 {
128 }
129
130 Q_INVOKABLE void startService(const QString location)
131 {
132 qDebug() << "Got startService";
133 if (location == "com.nokia.qt.tests.autostart") {
134 QMetaObject::invokeMethod(obj: this, member: "sendOk", type: Qt::DirectConnection, Q_ARG(QString, location));
135 } else {
136 QMetaObject::invokeMethod(obj: this, member: "sendError", type: Qt::DirectConnection, Q_ARG(QString, location));
137 }
138 }
139
140protected slots:
141 void sendError(const QString &location)
142 {
143 qDebug() << "Send fail";
144 emit failed(QStringLiteral("Test code failing creation"), process: location);
145 }
146
147 void sendOk(const QString &location)
148 {
149 emit launched(process: location);
150 QMetaObject::invokeMethod(obj: this, member: "startNewService", type: Qt::DirectConnection);
151 }
152
153 void startNewService()
154 {
155 QRemoteServiceRegister *r = new QRemoteServiceRegister(this);
156
157 QRemoteServiceRegister::Entry pmEntry =
158 r->createEntry<ServiceRequest>(
159 QStringLiteral("com.nokia.qt.tests.autostart"),
160 QStringLiteral("com.nokkia.qt.tests.autostarted"),
161 QStringLiteral("1.0"));
162
163 r->publishEntries(QStringLiteral("com.nokia.qt.tests.autostart"));
164 }
165
166signals:
167
168 void launched(QString process);
169 void failed(QString error, QString process);
170
171};
172
173class tst_QServiceManager_IPC: public QObject
174{
175 Q_OBJECT
176public:
177 tst_QServiceManager_IPC();
178
179protected slots:
180 void ipcError(QService::UnrecoverableIPCError error);
181 void ipcErrorNonTest(QService::UnrecoverableIPCError error);
182 void unblockRemote();
183
184private slots:
185 void initTestCase();
186 void cleanupTestCase();
187 void init();
188 void cleanup();
189
190 void verifyIsServiceRunning();
191
192 void verifySharedServiceObject(); //rough count
193 void verifySharedMethods();
194 void verifySharedMethods_data();
195 void verifySharedProperties();
196 void verifySharedProperties_data();
197
198 void verifyUniqueServiceObject(); //rough count
199 void verifyUniqueMethods();
200 void verifyUniqueMethods_data();
201
202 void verifyUniqueProperties();
203 void verifyUniqueProperties_data();
204
205 void verifyUniqueClassInfo();
206 void verifyUniqueClassInfo_data();
207
208 void verifyUniqueEnumerator();
209 void verifyUniqueEnumerator_data();
210
211 void verifyLargeDataTransfer();
212 void verifyLargeDataTransfer_data();
213
214 void verifyRemoteBlockingFunctions();
215
216 void verifyThreadSafety();
217 void verifyThreadSafety_data();
218
219 void sharedTestService();
220 void uniqueTestService();
221
222 void testInvokableFunctions();
223 void testSlotInvokation();
224 void testSignalling();
225
226 void testSignalSlotOrdering();
227
228 void verifyServiceClass();
229 void verifyFailures();
230
231 void verifyAsyncLoading();
232 void verifyAsyncLoading_data();
233
234 void testServiceSecurity();
235
236 void testProcessLaunch();
237
238 void testIpcFailure();
239
240signals:
241 void threadReady();
242 void threadRun();
243 void threadFinished();
244 void threadError();
245 void threadRemaining();
246
247private:
248 QObject* serviceUnique;
249 QObject* serviceUniqueOther;
250 QObject* serviceShared;
251 QObject* serviceSharedOther;
252 QObject* miscTest;
253 QServiceManager* manager;
254 bool verbose;
255 bool ipcfailure;
256};
257
258tst_QServiceManager_IPC::tst_QServiceManager_IPC()
259 : serviceUnique(0)
260 , serviceUniqueOther(0)
261 , serviceShared(0)
262 , serviceSharedOther(0)
263 , miscTest(0)
264 , manager(0)
265 , verbose(false)
266 , ipcfailure(false)
267{
268}
269
270#ifdef Q_OS_WIN
271static const char serviceBinaryC[] = "qt_sfw_example_ipc_unittest.exe";
272#else
273static const char serviceBinaryC[] = "qt_sfw_example_ipc_unittest";
274#endif
275
276void tst_QServiceManager_IPC::initTestCase()
277{
278 const QString serviceBinary = QFINDTESTDATA(serviceBinaryC);
279 QVERIFY(!serviceBinary.isEmpty());
280 const QFileInfo serviceBinaryInfo(serviceBinary);
281 QVERIFY(serviceBinaryInfo.isExecutable());
282 const QString serviceBinaryAbsPath = serviceBinaryInfo.absoluteFilePath();
283
284 const QString path = QFINDTESTDATA("xmldata/ipcexampleservice.xml");
285 QVERIFY(!path.isEmpty());
286
287 //verbose = true;
288 ipcfailure = false;
289 verbose = false;
290 serviceUnique = 0;
291 serviceUniqueOther = 0;
292 serviceSharedOther = 0;
293 serviceShared = 0;
294 serviceSharedOther = 0;
295 miscTest = 0;
296 qRegisterMetaType<QServiceFilter>(typeName: "QServiceFilter");
297 qRegisterMetaTypeStreamOperators<QServiceFilter>(typeName: "QServiceFilter");
298 qRegisterMetaType<QList<QString> >(typeName: "QList<QString>");
299 qRegisterMetaTypeStreamOperators<QList<QString> >(typeName: "QList<QString>");
300 qRegisterMetaTypeStreamOperators<QVariantHash>(typeName: "QVariantHash");
301 qRegisterMetaType<QVariantHash>(typeName: "QVariantHash");
302#ifdef SFW_USE_DBUS_BACKEND
303 qDBusRegisterMetaType<QVariantHash>();
304#endif
305
306#ifdef Q_OS_MAC
307 struct rlimit rlp;
308 int ret = getrlimit(RLIMIT_NOFILE, &rlp);
309 if (ret == -1) {
310 qWarning() << "Failed to get fd limit on mac, expect the threading test to fail";
311 } else {
312 rlp.rlim_cur = 512;
313 ret = setrlimit(RLIMIT_NOFILE, &rlp);
314 if (ret == -1) {
315 qWarning() << "Failed to raise the number of open files to 512, expect the threading test to fail";
316 }
317 }
318#endif
319
320 QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
321
322 QServiceManager* manager = new QServiceManager(this);
323
324 const bool r = manager->addService(xmlFilePath: path);
325 if (!r)
326 qWarning() << "Cannot register IPCExampleService" << path;
327
328#ifdef SFW_USE_DBUS_BACKEND
329 // D-Bus auto registration
330 const QString &file = QDir::homePath() + "/.local/share/dbus-1/services/" +
331 "com.nokia.qt.ipcunittest.service";
332
333 QDir dir(QDir::homePath());
334 dir.mkpath(dirPath: ".local/share/dbus-1/services/");
335 QFile data(file);
336 if (data.open(flags: QFile::WriteOnly)) {
337 QTextStream out(&data);
338 out << "[D-BUS Service]\n"
339 << "Name=com.nokia.qtmobility.sfw.IPCExampleService" << '\n'
340 << "Exec=" << serviceBinaryAbsPath << '\n';
341 data.close();
342 }
343 QVERIFY(data.exists());
344#endif // SFW_USE_DBUS_BACKEND
345
346#ifdef Q_OS_UNIX
347 char *p = getenv(name: "PATH");
348 char newpath[strlen(s: p)+3];
349 strcpy(dest: newpath, src: p);
350 strcat(dest: newpath, src: ":.");
351 setenv(name: "PATH", value: newpath, replace: 1);
352#endif
353
354 //test that the service is installed
355 QList<QServiceInterfaceDescriptor> list = manager->findInterfaces(serviceName: "IPCExampleService");
356 QVERIFY2(list.count() >= 7,"unit test specific IPCExampleService not registered/found" );
357 QServiceInterfaceDescriptor d;
358 foreach (d, list) {
359 if (d.majorVersion() == 3 && d.minorVersion() == 5) {
360 serviceUnique = manager->loadInterface(descriptor: d);
361 QVERIFY(serviceUnique);
362 serviceUniqueOther = manager->loadInterface(descriptor: d);
363 QVERIFY(serviceUniqueOther);
364 connect(sender: serviceUnique, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
365 receiver: this, SLOT(ipcErrorNonTest(QService::UnrecoverableIPCError)));
366 connect(sender: serviceUniqueOther, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
367 receiver: this, SLOT(ipcErrorNonTest(QService::UnrecoverableIPCError)));
368
369 }
370 if (d.majorVersion() == 3 && d.minorVersion() == 4) {
371 serviceShared = manager->loadInterface(descriptor: d);
372 QVERIFY(serviceShared);
373 serviceSharedOther = manager->loadInterface(descriptor: d);
374 connect(sender: serviceShared, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
375 receiver: this, SLOT(ipcErrorNonTest(QService::UnrecoverableIPCError)));
376 QVERIFY(serviceSharedOther);
377 connect(sender: serviceSharedOther, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
378 receiver: this, SLOT(ipcErrorNonTest(QService::UnrecoverableIPCError)));
379
380 }
381 if (d.majorVersion() == 3 && d.minorVersion() == 8) {
382 miscTest = manager->loadInterface(descriptor: d);
383 QVERIFY(miscTest);
384 connect(sender: miscTest, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
385 receiver: this, SLOT(ipcErrorNonTest(QService::UnrecoverableIPCError)));
386 }
387
388 }
389
390 QString errorCode = "Cannot find service. Error: %1";
391 errorCode = errorCode.arg(a: manager->error());
392 QVERIFY2(serviceUnique,errorCode.toLatin1());
393 QVERIFY2(serviceUniqueOther,errorCode.toLatin1());
394 QVERIFY2(serviceShared,errorCode.toLatin1());
395 QVERIFY2(serviceSharedOther,errorCode.toLatin1());
396
397 // all objects come from the same service, just need to connect to 1 signal
398 connect(sender: serviceSharedOther, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), receiver: this, SLOT(ipcError(QService::UnrecoverableIPCError)));
399
400 QRemoteServiceRegister *reg = new QRemoteServiceRegister();
401
402 QRemoteServiceRegister::Entry pmEntry =
403 reg->createEntry<ServiceRequest>(
404 QStringLiteral("com.nokia.mt.processmanager"),
405 QStringLiteral("com.nokia.mt.processmanager.ServiceRequest"),
406 QStringLiteral("1.0"));
407
408 reg->publishEntries(ident: "com.nokia.mt.processmanager.ServiceRequestSocket");
409
410 QByteArray ba(serviceReuqestXml);
411 QBuffer b(&ba);
412 manager->removeService(QStringLiteral("com.nokia.mt.processmanager"));
413 manager->addService(xmlDevice: &b);
414
415 QByteArray baFake(serviceReuqestXmlFake);
416 QBuffer bFake(&baFake);
417 manager->removeService(QStringLiteral("com.nokia.qt.does.not.exists"));
418 manager->addService(xmlDevice: &bFake);
419
420 QByteArray baAutoStart(serviceReuqestXmlStarted);
421 QBuffer bAutoStart(&baAutoStart);
422 manager->removeService(QStringLiteral("com.nokia.qt.tests.autostart"));
423 manager->addService(xmlDevice: &bAutoStart);
424
425}
426
427void tst_QServiceManager_IPC::ipcError(QService::UnrecoverableIPCError err)
428{
429 Q_UNUSED(err);
430 ipcfailure = true;
431}
432
433// unexpected ipc failures
434void tst_QServiceManager_IPC::ipcErrorNonTest(QService::UnrecoverableIPCError err)
435{
436 Q_UNUSED(err);
437}
438
439void tst_QServiceManager_IPC::cleanupTestCase()
440{
441#ifdef SFW_USE_DBUS_BACKEND
442 const QString &file = QDir::homePath() + "/.local/share/dbus-1/services/" +
443 "com.nokia.qt.ipcunittest.service";
444 QFile::remove(fileName: file);
445#endif
446
447 if (serviceUnique) {
448 delete serviceUnique;
449 }
450
451 if (serviceUniqueOther) {
452 delete serviceUniqueOther;
453 }
454
455 if (serviceShared) {
456 delete serviceShared;
457 }
458
459 if (serviceSharedOther) {
460 delete serviceSharedOther;
461 }
462
463 // clean up the unit, don't leave it registered
464 QServiceManager m;
465 m.removeService(serviceName: "IPCExampleService");
466 m.removeService(QStringLiteral("com.nokia.mt.processmanager"));
467 m.removeService(QStringLiteral("com.nokia.qt.does.not.exists"));
468 m.removeService(QStringLiteral("com.nokia.qt.tests.autostart"));
469}
470
471void tst_QServiceManager_IPC::init()
472{
473}
474
475void tst_QServiceManager_IPC::cleanup()
476{
477}
478
479void tst_QServiceManager_IPC::verifyIsServiceRunning()
480{
481#if defined(Q_OS_UNIX) && !defined(SFW_USE_DBUS_BACKEND)
482
483 QServiceManager m;
484
485 QCOMPARE(m.isInterfaceRunning("com.nokia.qt.ipcunittest"), true);
486 QCOMPARE(m.isInterfaceRunning("com.nokis.qt.ipcunittest.that.does.not.exsist.and.should.not.be.created"), false);
487
488 QList<QServiceInterfaceDescriptor> list = m.findInterfaces("IPCExampleService");
489 QServiceInterfaceDescriptor d;
490 foreach (d, list) {
491 QCOMPARE(m.isInterfaceRunning(d), true);
492 }
493#else
494 QSKIP("isInterfaceRunning needs more testing on supported platforms");
495#endif
496}
497
498void tst_QServiceManager_IPC::sharedTestService()
499{
500 const QMetaObject *meta = serviceShared->metaObject();
501 const QMetaObject *metaOther = serviceSharedOther->metaObject();
502
503 // test changes on the property 'value'
504 QMetaProperty prop = meta->property(index: 1);
505 QMetaProperty propOther = metaOther->property(index: 1);
506
507 // check that the property values are the same before and after an edit
508 QCOMPARE(prop.read(serviceShared), propOther.read(serviceSharedOther));
509 prop.write(obj: serviceShared, value: "Shared");
510 // write does not block so the QCOMPARE below may result in serviceSharedOther being read before
511 // the new value has been sent to the service. To avoid this, read the property back now
512 (void)prop.read(obj: serviceShared); // flush
513 QCOMPARE(prop.read(serviceShared), propOther.read(serviceSharedOther));
514 prop.reset(obj: serviceShared);
515
516 // test changes through a method call
517 uint hash, hashOther;
518 QMetaObject::invokeMethod(obj: serviceShared, member: "setConfirmationHash",
519 Q_ARG(uint, 0));
520 QMetaObject::invokeMethod(obj: serviceShared, member: "slotConfirmation",
521 Q_RETURN_ARG(uint, hash));
522 QMetaObject::invokeMethod(obj: serviceSharedOther, member: "setConfirmationHash",
523 Q_ARG(uint, 0));
524 QMetaObject::invokeMethod(obj: serviceSharedOther, member: "slotConfirmation",
525 Q_RETURN_ARG(uint, hashOther));
526 QCOMPARE(hash, (uint)0);
527 QCOMPARE(hashOther, (uint)0);
528
529 // check that the method values are the same after an edit
530 QMetaObject::invokeMethod(obj: serviceShared, member: "setConfirmationHash",
531 Q_ARG(uint, 1));
532 QMetaObject::invokeMethod(obj: serviceShared, member: "slotConfirmation",
533 Q_RETURN_ARG(uint, hash));
534 QMetaObject::invokeMethod(obj: serviceSharedOther, member: "slotConfirmation",
535 Q_RETURN_ARG(uint, hashOther));
536 QCOMPARE(hash, (uint)1);
537 QCOMPARE(hashOther, (uint)1);
538}
539
540void tst_QServiceManager_IPC::uniqueTestService()
541{
542 const QMetaObject *meta = serviceUnique->metaObject();
543 const QMetaObject *metaOther = serviceUniqueOther->metaObject();
544
545 // test changes on the property 'value'
546 QMetaProperty prop = meta->property(index: 1);
547 QMetaProperty propOther = metaOther->property(index: 1);
548
549 // check that the property values are not the same after an edit
550 QCOMPARE(prop.read(serviceUnique), propOther.read(serviceUniqueOther));
551 prop.write(obj: serviceUnique, value: "Unique");
552 QVERIFY(prop.read(serviceUnique) != propOther.read(serviceUniqueOther));
553 prop.reset(obj: serviceUnique);
554
555 // test changes through a method call
556 uint hash, hashOther;
557 QMetaObject::invokeMethod(obj: serviceUnique, member: "setConfirmationHash",
558 Q_ARG(uint, 0));
559 QMetaObject::invokeMethod(obj: serviceUnique, member: "slotConfirmation",
560 Q_RETURN_ARG(uint, hash));
561 QMetaObject::invokeMethod(obj: serviceUniqueOther, member: "setConfirmationHash",
562 Q_ARG(uint, 0));
563 QMetaObject::invokeMethod(obj: serviceUniqueOther, member: "slotConfirmation",
564 Q_RETURN_ARG(uint, hashOther));
565 QCOMPARE(hash, (uint)0);
566 QCOMPARE(hashOther, (uint)0);
567
568 // check that the method values are not the same after an edit
569 QMetaObject::invokeMethod(obj: serviceUnique, member: "setConfirmationHash",
570 Q_ARG(uint, 1));
571 QMetaObject::invokeMethod(obj: serviceUnique, member: "slotConfirmation",
572 Q_RETURN_ARG(uint, hash));
573 QMetaObject::invokeMethod(obj: serviceUniqueOther, member: "slotConfirmation",
574 Q_RETURN_ARG(uint, hashOther));
575 QCOMPARE(hash, (uint)1);
576 QCOMPARE(hashOther, (uint)0);
577}
578
579void tst_QServiceManager_IPC::verifySharedServiceObject()
580{
581 QVERIFY(serviceShared != 0);
582 const QMetaObject* mo = serviceShared->metaObject();
583 QCOMPARE(mo->className(), "SharedTestService");
584 QVERIFY(mo->superClass());
585 QCOMPARE(mo->superClass()->className(), "QServiceProxyBase");
586 QCOMPARE(mo->methodCount()-mo-> methodOffset(), 19);
587 QCOMPARE(mo->methodCount(), 25); //20 meta functions available
588 //actual function presence will be tested later
589
590// for (int i = 0; i < mo->methodCount(); i++) {
591// qDebug() << "Methods" << i << mo->method(i).methodSignature();
592// }
593
594 //test properties
595 QCOMPARE(mo->propertyCount()-mo->propertyOffset(), 1);
596 QCOMPARE(mo->propertyCount(), 2);
597
598 QCOMPARE(mo->enumeratorCount()-mo->enumeratorOffset(), 0);
599 QCOMPARE(mo->enumeratorCount(), 0);
600
601 QCOMPARE(mo->classInfoCount()-mo->classInfoOffset(), 0);
602 QCOMPARE(mo->classInfoCount(), 0);
603
604 if (verbose) {
605 qDebug() << "ServiceObject class: " << mo->className() << mo->superClass() << mo->superClass()->className();
606 qDebug() << "------------------- Meta Methods -----------";
607 qDebug() << "Methods:" << mo->methodCount()- mo->methodOffset() << "(" << mo->methodCount() << ")";
608 for (int i=0; i< mo->methodCount(); i++) {
609 QMetaMethod method = mo->method(index: i);
610 QString type;
611 switch (method.methodType()) {
612 case QMetaMethod::Signal:
613 type = "signal"; break;
614 case QMetaMethod::Slot:
615 type = "slot"; break;
616 case QMetaMethod::Constructor:
617 type = "constrcutor"; break;
618 case QMetaMethod::Method:
619 type = "method"; break;
620 }
621 qDebug() << " " << i << "." << method.methodSignature() << type;
622 }
623
624 qDebug() << "------------------- Meta Properties --------";
625 qDebug() << "Properties:" << mo->propertyCount()- mo->propertyOffset() << "(" << mo->propertyCount() << ")";
626 for (int i=0; i< mo->propertyCount(); i++) {
627 QMetaProperty property = mo->property(index: i);
628 QString info = "Readable: %1 Resettable: %2 Writeable: %3 Designable: %4 Scriptable: %5 User: %6 Stored: %7 Constant: %8 Final: %9 HasNotify: %10 EnumType: %11 FlagType: %12";
629 info = info.arg(a: property.isReadable()).arg(a: property.isResettable()).arg(a: property.isWritable());
630 info = info.arg(a: property.isDesignable()).arg(a: property.isScriptable()).arg(a: property.isUser());
631 info = info.arg(a: property.isStored()).arg(a: property.isConstant()).arg(a: property.isFinal());
632 info = info.arg(a: property.hasNotifySignal()).arg(a: property.isEnumType()).arg(a: property.isFlagType());
633
634 qDebug() << " " << i << "." << property.name() << "Type:" << property.typeName() << info;
635 }
636
637 qDebug() << "------------------- Meta Enumerators --------";
638 qDebug() << "Enums:" << mo->enumeratorCount()- mo->enumeratorOffset() << "(" << mo->enumeratorCount() << ")";
639
640 qDebug() << "------------------- Meta class info ---------";
641 qDebug() << "ClassInfos:" << mo->classInfoCount()- mo->classInfoOffset() << "(" << mo->classInfoCount() << ")";
642 }
643}
644
645void tst_QServiceManager_IPC::verifySharedMethods_data()
646{
647 QTest::addColumn<QByteArray>(name: "signature");
648 QTest::addColumn<int>(name: "metaMethodType");
649 QTest::addColumn<QByteArray>(name: "returnType");
650
651 //list of all slots, signals and invokable functions
652 QTest::newRow(dataTag: "signalWithIntParam(int)")
653 << QByteArray("signalWithIntParam(int)") << (int)( QMetaMethod::Signal) << QByteArray("void");
654 QTest::newRow(dataTag: "signalWithVariousParam(QVariant,QString,QServiceFilter)")
655 << QByteArray("signalWithVariousParam(QVariant,QString,QServiceFilter)") << (int)( QMetaMethod::Signal) << QByteArray("void");
656 QTest::newRow(dataTag: "valueChanged()")
657 << QByteArray("valueChanged()") << (int)( QMetaMethod::Signal) << QByteArray("void");
658 QTest::newRow(dataTag: "triggerSignalWithIntParam()")
659 << QByteArray("triggerSignalWithIntParam()") << (int)( QMetaMethod::Slot) << QByteArray("void");
660 QTest::newRow(dataTag: "triggerSignalWithVariousParam()")
661 << QByteArray("triggerSignalWithVariousParam()") << (int)( QMetaMethod::Slot) << QByteArray("void");
662 QTest::newRow(dataTag: "triggerSignalWithIntParamExecute()")
663 << QByteArray("triggerSignalWithIntParamExecute()") << (int)( QMetaMethod::Slot) << QByteArray("void");
664 QTest::newRow(dataTag: "triggerSignalWithVariousParamExecute()")
665 << QByteArray("triggerSignalWithVariousParamExecute()") << (int)( QMetaMethod::Slot) << QByteArray("void");
666 QTest::newRow(dataTag: "testSlot()")
667 << QByteArray("testSlot()") << (int)( QMetaMethod::Slot) << QByteArray("void");
668 QTest::newRow(dataTag: "testSlotWithArgs(QByteArray,int,QVariant)")
669 << QByteArray("testSlotWithArgs(QByteArray,int,QVariant)") << (int)( QMetaMethod::Slot) << QByteArray("void");
670 QTest::newRow(dataTag: "testSlotWithCustomArg(QServiceFilter)")
671 << QByteArray("testSlotWithCustomArg(QServiceFilter)") << (int)( QMetaMethod::Slot) << QByteArray("void");
672 QTest::newRow(dataTag: "testSlotWidthComplexArg(QVariantHash)")
673 << QByteArray("testSlotWithComplexArg(QVariantHash)") << (int)( QMetaMethod::Slot) << QByteArray("void");
674
675 //QServiceInterfaceDescriptor has not been declared as meta type
676 QTest::newRow(dataTag: "testSlotWithUnknownArg(QServiceInterfaceDescriptor)")
677 << QByteArray("testSlotWithUnknownArg(QServiceInterfaceDescriptor)") << (int)( QMetaMethod::Slot) << QByteArray("void");
678 QTest::newRow(dataTag: "testFunctionWithReturnValue(int)")
679 << QByteArray("testFunctionWithReturnValue(int)") << (int)( QMetaMethod::Method) << QByteArray("QString");
680 QTest::newRow(dataTag: "testFunctionWithVariantReturnValue(QVariant)")
681 << QByteArray("testFunctionWithVariantReturnValue(QVariant)") << (int)( QMetaMethod::Method) << QByteArray("QVariant");
682 QTest::newRow(dataTag: "testFunctionWithCustomReturnValue()")
683 << QByteArray("testFunctionWithCustomReturnValue()") << (int)( QMetaMethod::Method) << QByteArray("QServiceFilter");
684 QTest::newRow(dataTag: "slotConfirmation()")
685 << QByteArray("slotConfirmation()") << (int)( QMetaMethod::Method) << QByteArray("uint");
686 QTest::newRow(dataTag: "setConfirmationHash(uint)")
687 << QByteArray("setConfirmationHash(uint)") << (int)( QMetaMethod::Method) << QByteArray("void");
688}
689
690void tst_QServiceManager_IPC::verifySharedMethods()
691{
692 QVERIFY(serviceShared);
693 QFETCH(QByteArray, signature);
694 QFETCH(int, metaMethodType);
695 QFETCH(QByteArray, returnType);
696
697 const QMetaObject* meta = serviceShared->metaObject();
698 const int index = meta->indexOfMethod(method: signature.constData());
699 QVERIFY(index>=0);
700 QMetaMethod method = meta->method(index);
701 QCOMPARE(metaMethodType, (int)method.methodType());
702 QCOMPARE(returnType, QByteArray(method.typeName()));
703}
704
705void tst_QServiceManager_IPC::verifySharedProperties_data()
706{
707 QTest::addColumn<QByteArray>(name: "signature");
708 QTest::addColumn<QString>(name: "typeName");
709 QTest::addColumn<qint16>(name: "flags");
710 QTest::addColumn<QVariant>(name: "defaultValue");
711 QTest::addColumn<QVariant>(name: "writeValue");
712 QTest::addColumn<QVariant>(name: "expectedReturnValue");
713
714 //
715 // bit order:
716 // 0 isWritable - 1 isUser - 2 isStored - 3 isScriptable
717 // 4 isResettable - 5 isReadable - 6 isFlagType - 7 isFinal
718 // 8 isEnumType - 9 isDesignable - 10 isConstant - 11 hasNotifySgnal
719 //
720 // for more details see verifyProperties()
721 //
722
723 QTest::newRow(dataTag: "value property") << QByteArray("value")
724 << QString("QString") << qint16(0x0A3D) << QVariant(QString("FFF")) << QVariant(QString("GGG")) << QVariant(QString("GGG"));
725}
726
727void tst_QServiceManager_IPC::verifySharedProperties()
728{
729 QVERIFY(serviceShared);
730 QFETCH(QByteArray, signature);
731 QFETCH(QString, typeName);
732 QFETCH(qint16, flags);
733 QFETCH(QVariant, defaultValue);
734 QFETCH(QVariant, writeValue);
735 QFETCH(QVariant, expectedReturnValue);
736
737 const QMetaObject* meta = serviceShared->metaObject();
738 const int index = meta->indexOfProperty(name: signature.constData());
739 QVERIFY(index>=0);
740 QMetaProperty property = meta->property(index);
741 QVERIFY(property.isValid());
742 QCOMPARE(QString(property.typeName()), typeName);
743
744 QVERIFY( property.isWritable() == (bool) (flags & 0x0001) );
745 QVERIFY( property.isUser() == (bool) (flags & 0x0002) );
746 QVERIFY( property.isStored() == (bool) (flags & 0x0004) );
747 QVERIFY( property.isScriptable() == (bool) (flags & 0x0008) );
748 QVERIFY( property.isResettable() == (bool) (flags & 0x0010) );
749 QVERIFY( property.isReadable() == (bool) (flags & 0x0020) );
750 QVERIFY( property.isFlagType() == (bool) (flags & 0x0040) );
751 QVERIFY( property.isFinal() == (bool) (flags & 0x0080) );
752 QVERIFY( property.isEnumType() == (bool) (flags & 0x0100) );
753 QVERIFY( property.isDesignable() == (bool) (flags & 0x0200) );
754 QVERIFY( property.isConstant() == (bool) (flags & 0x0400) );
755 QVERIFY( property.hasNotifySignal() == (bool) (flags & 0x0800) );
756
757 if (property.isReadable()) {
758 QCOMPARE(defaultValue, serviceShared->property(signature));
759 if (property.isWritable()) {
760 serviceShared->setProperty(name: signature, value: writeValue);
761 QCOMPARE(expectedReturnValue, serviceShared->property(signature));
762 if (property.isResettable()) {
763 property.reset(obj: serviceShared);
764 QCOMPARE(defaultValue, serviceShared->property(signature));
765 }
766 serviceShared->setProperty(name: signature, value: defaultValue);
767 QCOMPARE(defaultValue, serviceShared->property(signature));
768 }
769 }
770}
771
772void tst_QServiceManager_IPC::verifyUniqueServiceObject()
773{
774 QVERIFY(serviceUnique != 0);
775 const QMetaObject* mo = serviceUnique->metaObject();
776 QCOMPARE(mo->className(), "UniqueTestService");
777 QVERIFY(mo->superClass());
778 QCOMPARE(mo->superClass()->className(), "QServiceProxyBase");
779 // TODO adding the ipc failure signal seems to break these
780 QCOMPARE(mo->methodCount()-mo-> methodOffset(), 27); // 28+1 added signal for error signal added by library
781 QCOMPARE(mo->methodCount(), 33); //33 meta functions available + 1 signal
782 //actual function presence will be tested later
783
784// for (int i = 0; i < mo->methodCount(); i++) {
785// qDebug() << "Methods" << i << mo->method(i).methodSignature();
786// }
787
788 //test properties
789 QCOMPARE(mo->propertyCount()-mo->propertyOffset(), 5);
790 QCOMPARE(mo->propertyCount(), 6);
791
792 QCOMPARE(mo->enumeratorCount()-mo->enumeratorOffset(), 3);
793 QCOMPARE(mo->enumeratorCount(), 3);
794
795 QCOMPARE(mo->classInfoCount()-mo->classInfoOffset(), 2);
796 QCOMPARE(mo->classInfoCount(), 2);
797
798 if (verbose) {
799 qDebug() << "ServiceObject class: " << mo->className() << mo->superClass() << mo->superClass()->className();
800 qDebug() << "------------------- Meta Methods -----------";
801 qDebug() << "Methods:" << mo->methodCount()- mo->methodOffset() << "(" << mo->methodCount() << ")";
802 for (int i=0; i< mo->methodCount(); i++) {
803 QMetaMethod method = mo->method(index: i);
804 QString type;
805 switch (method.methodType()) {
806 case QMetaMethod::Signal:
807 type = "signal"; break;
808 case QMetaMethod::Slot:
809 type = "slot"; break;
810 case QMetaMethod::Constructor:
811 type = "constrcutor"; break;
812 case QMetaMethod::Method:
813 type = "method"; break;
814 }
815 qDebug() << " " << i << "." << method.methodSignature() << type;
816 }
817
818 qDebug() << "------------------- Meta Properties --------";
819 qDebug() << "Properties:" << mo->propertyCount()- mo->propertyOffset() << "(" << mo->propertyCount() << ")";
820 for (int i=0; i< mo->propertyCount(); i++) {
821 QMetaProperty property = mo->property(index: i);
822 QString info = "Readable: %1 Resettable: %2 Writeable: %3 Designable: %4 Scriptable: %5 User: %6 Stored: %7 Constant: %8 Final: %9 HasNotify: %10 EnumType: %11 FlagType: %12";
823 info = info.arg(a: property.isReadable()).arg(a: property.isResettable()).arg(a: property.isWritable());
824 info = info.arg(a: property.isDesignable()).arg(a: property.isScriptable()).arg(a: property.isUser());
825 info = info.arg(a: property.isStored()).arg(a: property.isConstant()).arg(a: property.isFinal());
826 info = info.arg(a: property.hasNotifySignal()).arg(a: property.isEnumType()).arg(a: property.isFlagType());
827
828 qDebug() << " " << i << "." << property.name() << "Type:" << property.typeName() << info;
829 }
830
831 qDebug() << "------------------- Meta Enumerators --------";
832 qDebug() << "Enums:" << mo->enumeratorCount()- mo->enumeratorOffset() << "(" << mo->enumeratorCount() << ")";
833 for (int i=0; i< mo->enumeratorCount(); i++) {
834 QMetaEnum e = mo->enumerator(index: i);
835 qDebug() << " " << i << "." << e.name() << "Scope:" << e.scope() << "KeyCount: " << e.keyCount();
836 for (int j = 0; j<e.keyCount(); j++)
837 qDebug() << " " << e.key(index: j) << " - " << e.value(index: j);
838 }
839
840 qDebug() << "------------------- Meta class info ---------";
841 qDebug() << "ClassInfos:" << mo->classInfoCount()- mo->classInfoOffset() << "(" << mo->classInfoCount() << ")";
842 for (int i=0; i< mo->classInfoCount(); i++) {
843 QMetaClassInfo info = mo->classInfo(index: i);
844 qDebug() << " " << i << "." << info.name() << "Value:" << info.value();
845 }
846 }
847}
848
849void tst_QServiceManager_IPC::verifyUniqueMethods_data()
850{
851 QTest::addColumn<QByteArray>(name: "signature");
852 QTest::addColumn<int>(name: "metaMethodType");
853 QTest::addColumn<QByteArray>(name: "returnType");
854
855 //list of all slots, signals and invokable functions
856 QTest::newRow(dataTag: "signalWithIntParam(int)")
857 << QByteArray("signalWithIntParam(int)") << (int)( QMetaMethod::Signal) << QByteArray("void");
858 QTest::newRow(dataTag: "signalWithVariousParam(QVariant,QString,QServiceFilter,QVariant)")
859 << QByteArray("signalWithVariousParam(QVariant,QString,QServiceFilter,QVariant)") << (int)( QMetaMethod::Signal) << QByteArray("void");
860 QTest::newRow(dataTag: "valueChanged()")
861 << QByteArray("valueChanged()") << (int)( QMetaMethod::Signal) << QByteArray("void");
862 QTest::newRow(dataTag: "priorityChanged()")
863 << QByteArray("priorityChanged()") << (int)( QMetaMethod::Signal) << QByteArray("void");
864 QTest::newRow(dataTag: "triggerSignalWithIntParam()")
865 << QByteArray("triggerSignalWithIntParam()") << (int)( QMetaMethod::Slot) << QByteArray("void");
866 QTest::newRow(dataTag: "triggerSignalWithVariousParam()")
867 << QByteArray("triggerSignalWithVariousParam()") << (int)( QMetaMethod::Slot) << QByteArray("void");
868 QTest::newRow(dataTag: "triggerSignalWithIntParamExecute()")
869 << QByteArray("triggerSignalWithIntParamExecute()") << (int)( QMetaMethod::Slot) << QByteArray("void");
870 QTest::newRow(dataTag: "triggerSignalWithVariousParamExecute()")
871 << QByteArray("triggerSignalWithVariousParamExecute()") << (int)( QMetaMethod::Slot) << QByteArray("void");
872 QTest::newRow(dataTag: "testSlot()")
873 << QByteArray("testSlot()") << (int)( QMetaMethod::Slot) << QByteArray("void");
874 QTest::newRow(dataTag: "testSlotWithArgs(QByteArray,int,QVariant)")
875 << QByteArray("testSlotWithArgs(QByteArray,int,QVariant)") << (int)( QMetaMethod::Slot) << QByteArray("void");
876 QTest::newRow(dataTag: "testSlotWithCustomArg(QServiceFilter)")
877 << QByteArray("testSlotWithCustomArg(QServiceFilter)") << (int)( QMetaMethod::Slot) << QByteArray("void");
878
879 //QServiceInterfaceDescriptor has not been declared as meta type
880 QTest::newRow(dataTag: "testSlotWithUnknownArg(QServiceInterfaceDescriptor)")
881 << QByteArray("testSlotWithUnknownArg(QServiceInterfaceDescriptor)") << (int)( QMetaMethod::Slot) << QByteArray("void");
882 QTest::newRow(dataTag: "testFunctionWithReturnValue(int)")
883 << QByteArray("testFunctionWithReturnValue(int)") << (int)( QMetaMethod::Method) << QByteArray("QString");
884 QTest::newRow(dataTag: "testFunctionWithVariantReturnValue(QVariant)")
885 << QByteArray("testFunctionWithVariantReturnValue(QVariant)") << (int)( QMetaMethod::Method) << QByteArray("QVariant");
886 QTest::newRow(dataTag: "testFunctionWithCustomReturnValue()")
887 << QByteArray("testFunctionWithCustomReturnValue()") << (int)( QMetaMethod::Method) << QByteArray("QServiceFilter");
888 QTest::newRow(dataTag: "slotConfirmation()")
889 << QByteArray("slotConfirmation()") << (int)( QMetaMethod::Method) << QByteArray("uint");
890 QTest::newRow(dataTag: "setConfirmationHash(uint)")
891 << QByteArray("setConfirmationHash(uint)") << (int)( QMetaMethod::Method) << QByteArray("void");
892}
893
894void tst_QServiceManager_IPC::verifyUniqueMethods()
895{
896 QVERIFY(serviceUnique);
897 QFETCH(QByteArray, signature);
898 QFETCH(int, metaMethodType);
899 QFETCH(QByteArray, returnType);
900
901 const QMetaObject* meta = serviceUnique->metaObject();
902 const int index = meta->indexOfMethod(method: signature.constData());
903 QVERIFY(index>=0);
904 QMetaMethod method = meta->method(index);
905 QCOMPARE((int)method.methodType(), metaMethodType);
906 QCOMPARE(QByteArray(method.typeName()), returnType);
907}
908
909void tst_QServiceManager_IPC::verifyUniqueProperties_data()
910{
911 QTest::addColumn<QByteArray>(name: "signature");
912 QTest::addColumn<QString>(name: "typeName");
913 QTest::addColumn<qint16>(name: "flags");
914 QTest::addColumn<QVariant>(name: "defaultValue");
915 QTest::addColumn<QVariant>(name: "writeValue");
916 QTest::addColumn<QVariant>(name: "expectedReturnValue");
917
918 //
919 // bit order:
920 // 0 isWritable - 1 isUser - 2 isStored - 3 isScriptable
921 // 4 isResettable - 5 isReadable - 6 isFlagType - 7 isFinal
922 // 8 isEnumType - 9 isDesignable - 10 isConstant - 11 hasNotifySgnal
923 //
924 // for more details see verifyProperties()
925 //
926
927 QTest::newRow(dataTag: "value property") << QByteArray("value")
928 << QString("QString") << qint16(0x0A3D) << QVariant(QString("FFF")) << QVariant(QString("GGG")) << QVariant(QString("GGG"));
929#ifndef SFW_USE_DBUS_BACKEND
930 // ENUMS DONT WORK OVER DBUS
931 QTest::newRow("priority property") << QByteArray("priority")
932 << QString("Priority") << qint16(0x0B2D) << QVariant((int)0) << QVariant("Low") << QVariant((int)1) ;
933 QTest::newRow("serviceFlags property") << QByteArray("serviceFlags")
934 << QString("ServiceFlag") << qint16(0x036D) << QVariant((int)4) << QVariant("FirstBit|ThirdBit") << QVariant((int)5);
935#endif
936}
937
938void tst_QServiceManager_IPC::verifyUniqueProperties()
939{
940 QVERIFY(serviceUnique);
941 QFETCH(QByteArray, signature);
942 QFETCH(QString, typeName);
943 QFETCH(qint16, flags);
944 QFETCH(QVariant, defaultValue);
945 QFETCH(QVariant, writeValue);
946 QFETCH(QVariant, expectedReturnValue);
947
948 const QMetaObject* meta = serviceUnique->metaObject();
949 const int index = meta->indexOfProperty(name: signature.constData());
950 QVERIFY(index>=0);
951 QMetaProperty property = meta->property(index);
952 QVERIFY(property.isValid());
953 QCOMPARE(QString(property.typeName()), typeName);
954
955 QVERIFY( property.isWritable() == (bool) (flags & 0x0001) );
956 QVERIFY( property.isUser() == (bool) (flags & 0x0002) );
957 QVERIFY( property.isStored() == (bool) (flags & 0x0004) );
958 QVERIFY( property.isScriptable() == (bool) (flags & 0x0008) );
959 QVERIFY( property.isResettable() == (bool) (flags & 0x0010) );
960 QVERIFY( property.isReadable() == (bool) (flags & 0x0020) );
961 QVERIFY( property.isFlagType() == (bool) (flags & 0x0040) );
962 QVERIFY( property.isFinal() == (bool) (flags & 0x0080) );
963 QVERIFY( property.isEnumType() == (bool) (flags & 0x0100) );
964 QVERIFY( property.isDesignable() == (bool) (flags & 0x0200) );
965 QVERIFY( property.isConstant() == (bool) (flags & 0x0400) );
966 QVERIFY( property.hasNotifySignal() == (bool) (flags & 0x0800) );
967
968 if (property.isReadable()) {
969 QCOMPARE(defaultValue, serviceUnique->property(signature));
970 if (property.isWritable()) {
971 serviceUnique->setProperty(name: signature, value: writeValue);
972 QCOMPARE(expectedReturnValue, serviceUnique->property(signature));
973 if (property.isResettable()) {
974 property.reset(obj: serviceUnique);
975 QCOMPARE(defaultValue, serviceUnique->property(signature));
976 }
977 serviceUnique->setProperty(name: signature, value: defaultValue);
978 QCOMPARE(defaultValue, serviceUnique->property(signature));
979 }
980 }
981}
982
983void tst_QServiceManager_IPC::verifyUniqueClassInfo_data()
984{
985 QTest::addColumn<QString>(name: "classInfoKey");
986 QTest::addColumn<QString>(name: "classInfoValue");
987
988 QTest::newRow(dataTag: "UniqueTestService") << QString("UniqueTestService") << QString("First test");
989 QTest::newRow(dataTag: "Key") << QString("Key") << QString("Value");
990
991}
992void tst_QServiceManager_IPC::verifyUniqueClassInfo()
993{
994 QFETCH(QString, classInfoKey);
995 QFETCH(QString, classInfoValue);
996
997 const QMetaObject* meta = serviceUnique->metaObject();
998 const int index = meta->indexOfClassInfo(name: classInfoKey.toLatin1().constData());
999
1000 QMetaClassInfo info = meta->classInfo(index);
1001 QCOMPARE(classInfoKey, QString(info.name()));
1002 QCOMPARE(classInfoValue, QString(info.value()));
1003
1004}
1005
1006Q_DECLARE_METATYPE(QList<int> )
1007void tst_QServiceManager_IPC::verifyUniqueEnumerator_data()
1008{
1009 QTest::addColumn<QString>(name: "enumName");
1010 QTest::addColumn<QString>(name: "enumScope");
1011 QTest::addColumn<int>(name: "enumKeyCount");
1012 QTest::addColumn<bool>(name: "enumIsFlag");
1013 QTest::addColumn<QStringList>(name: "enumKeyNames");
1014 QTest::addColumn<QList<int> >(name: "enumKeyValues");
1015
1016
1017 QStringList keynames;
1018 keynames << "FirstBit" << "SecondBit" << "ThirdBit";
1019 QList<int> values;
1020 values << 1 << 2 << 4;
1021 QTest::newRow(dataTag: "ServiceFlag") << QString("ServiceFlag") << QString("UniqueTestService")
1022 << 3 << true << keynames << values;
1023 QTest::newRow(dataTag: "ServiceFlags") << QString("ServiceFlags") << QString("UniqueTestService")
1024 << 3 << true << keynames << values;
1025
1026 keynames.clear();
1027 values.clear();
1028
1029 keynames << "High" << "Low" << "VeryLow" << "ExtremelyLow";
1030 values << 0 << 1 << 2 << 3 ;
1031
1032 QTest::newRow(dataTag: "Priority") << QString("Priority") << QString("UniqueTestService")
1033 << 4 << false << keynames << values;
1034}
1035
1036void tst_QServiceManager_IPC::verifyUniqueEnumerator()
1037{
1038 QFETCH(QString, enumName);
1039 QFETCH(QString, enumScope);
1040 QFETCH(int, enumKeyCount);
1041 QFETCH(bool, enumIsFlag);
1042 QFETCH(QStringList, enumKeyNames);
1043 QFETCH(QList<int>, enumKeyValues);
1044
1045 const QMetaObject* meta = serviceUnique->metaObject();
1046 const int index = meta->indexOfEnumerator(name: enumName.toLatin1().constData());
1047 QMetaEnum metaEnum = meta->enumerator(index);
1048
1049 QVERIFY(metaEnum.isValid());
1050 QCOMPARE(enumScope, QString(metaEnum.scope()));
1051 QCOMPARE(enumKeyCount, metaEnum.keyCount());
1052 QCOMPARE(enumIsFlag, metaEnum.isFlag());
1053 QCOMPARE(enumKeyNames.count(), enumKeyValues.count());
1054
1055 for (int i=0; i<enumKeyNames.count(); i++) {
1056 QCOMPARE(enumKeyNames.at(i), QString(metaEnum.valueToKey(enumKeyValues.at(i))));
1057 QCOMPARE(enumKeyValues.at(i), metaEnum.keyToValue(enumKeyNames.at(i).toLatin1().constData()));
1058 }
1059}
1060
1061void tst_QServiceManager_IPC::testInvokableFunctions()
1062{
1063 // Test invokable method input with calculated return value
1064 QString temp;
1065 QString result;
1066 QString patternShared("%1 + 3 = %2");
1067 QString patternUnique("%1 x 3 = %2");
1068 for (int i = -10; i<10; i++) {
1069 result.clear(); temp.clear();
1070 QVERIFY(result.isEmpty());
1071 QVERIFY(temp.isEmpty());
1072
1073 // Shared service
1074 QMetaObject::invokeMethod(obj: serviceShared, member: "testFunctionWithReturnValue",
1075 Q_RETURN_ARG(QString, result),
1076 Q_ARG(int, i));
1077 temp = patternShared.arg(a: i).arg(a: i+3);
1078 QCOMPARE(temp, result);
1079
1080 result.clear(); temp.clear();
1081 QVERIFY(result.isEmpty());
1082 QVERIFY(temp.isEmpty());
1083
1084 // Unique service
1085 QMetaObject::invokeMethod(obj: serviceUnique, member: "testFunctionWithReturnValue",
1086 Q_RETURN_ARG(QString, result),
1087 Q_ARG(int, i));
1088 temp = patternUnique.arg(a: i).arg(a: i*3);
1089 QCOMPARE(temp, result);
1090 }
1091
1092 // Test invokable method with QVariant return type
1093 QList<QVariant> variants;
1094 variants << QVariant("CANT BE NULL") << QVariant(6) << QVariant(QString("testString"));
1095 for (int i = 0; i<variants.count(); i++) {
1096 QVariant varResult;
1097
1098 // Shared service
1099 QMetaObject::invokeMethod(obj: serviceShared, member: "testFunctionWithVariantReturnValue",
1100 Q_RETURN_ARG(QVariant, varResult),
1101 Q_ARG(QVariant, variants.at(i)));
1102 QCOMPARE(variants.at(i), varResult);
1103
1104 // Unique service
1105 QMetaObject::invokeMethod(obj: serviceUnique, member: "testFunctionWithVariantReturnValue",
1106 Q_RETURN_ARG(QVariant, varResult),
1107 Q_ARG(QVariant, variants.at(i)));
1108 QCOMPARE(variants.at(i), varResult);
1109 }
1110
1111 // Test invokable method with custom return type
1112 QServiceFilter f;
1113 // Shared service
1114 QMetaObject::invokeMethod(obj: serviceShared, member: "testFunctionWithCustomReturnValue",
1115 Q_RETURN_ARG(QServiceFilter, f));
1116 QCOMPARE(f.serviceName(), QString("MySharedService"));
1117 QCOMPARE(f.interfaceName(), QString("com.nokia.qt.ipcunittest"));
1118 QCOMPARE(f.majorVersion(), 6);
1119 QCOMPARE(f.minorVersion(), 2);
1120
1121 // Unique service
1122 QMetaObject::invokeMethod(obj: serviceUnique, member: "testFunctionWithCustomReturnValue",
1123 Q_RETURN_ARG(QServiceFilter, f));
1124 QCOMPARE(f.serviceName(), QString("MyUniqueService"));
1125 QCOMPARE(f.interfaceName(), QString("com.nokia.qt.ipcunittest"));
1126 QCOMPARE(f.majorVersion(), 6);
1127 QCOMPARE(f.minorVersion(), 7);
1128
1129 // Test invokable method with list return type
1130 QList<QString> list, retList;
1131 list << "1" << "2" << "3";
1132 QMetaObject::invokeMethod(obj: serviceUnique, member: "testFunctionWithListReturn",
1133 Q_RETURN_ARG(QList<QString>, retList));
1134 QCOMPARE(list, retList);
1135}
1136
1137void tst_QServiceManager_IPC::testSignalling()
1138{
1139 // Test signalling for simple methods
1140 QSignalSpy spy(serviceUnique, SIGNAL(signalWithIntParam(int)));
1141 QMetaObject::invokeMethod(obj: serviceUnique, member: "triggerSignalWithIntParam");
1142 QTRY_VERIFY(spy.count() > 0);
1143 QCOMPARE(spy.at(0).at(0).toInt(), 5);
1144
1145 // Test signalling for property changes
1146 QCOMPARE(QString("FFF"), serviceUnique->property("value").toString());
1147 QSignalSpy propSpy(serviceUnique, SIGNAL(valueChanged()));
1148
1149 serviceUnique->setProperty(name: "value", value: QString("GGG"));
1150 QTRY_VERIFY(propSpy.count() == 1);
1151 propSpy.clear();
1152 serviceUnique->setProperty(name: "value", value: QString("FFF"));
1153 QTRY_VERIFY(propSpy.count() == 1);
1154 QCOMPARE(QString("FFF"), serviceUnique->property("value").toString());
1155
1156 // Test signalling with custom types
1157 QSignalSpy variousSpy(serviceUnique, SIGNAL(signalWithVariousParam(QVariant,QString,QServiceFilter,QVariant)));
1158 QMetaObject::invokeMethod(obj: serviceUnique, member: "triggerSignalWithVariousParam");
1159
1160 QTRY_VERIFY(variousSpy.count() == 1);
1161 QCOMPARE(variousSpy.at(0).count(), 4);
1162 QCOMPARE(variousSpy.at(0).at(0).value<QVariant>(), QVariant("CAN'T BE NULL"));
1163 QCOMPARE(variousSpy.at(0).at(1).toString(), QString("string-value"));
1164
1165 QVariant vFilter = variousSpy.at(i: 0).at(i: 2);
1166 QServiceFilter filter;
1167 QVERIFY(vFilter.canConvert<QServiceFilter>());
1168 filter = vFilter.value<QServiceFilter>();
1169 QCOMPARE(filter.serviceName(), QString("MyService"));
1170 QCOMPARE(filter.interfaceName(), QString("com.nokia.qt.ipcunittest"));
1171 QCOMPARE(filter.majorVersion(), 6);
1172 QCOMPARE(filter.minorVersion(), 7);
1173
1174 QCOMPARE(variousSpy.at(0).at(3).value<QVariant>(), QVariant(5));
1175}
1176
1177void tst_QServiceManager_IPC::testSlotInvokation()
1178{
1179 QObject *service = serviceUnique;
1180
1181 // check the success of our invokable slot by using a hash of the method and its parameters
1182 uint hash = 1;
1183 uint expectedHash = 0;
1184 QMetaObject::invokeMethod(obj: service, member: "setConfirmationHash",
1185 Q_ARG(uint, 0));
1186 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1187 Q_RETURN_ARG(uint, hash));
1188 QCOMPARE(hash, (uint)0);
1189
1190 // Test invokable slot with no arguments
1191 QMetaObject::invokeMethod(obj: service, member: "testSlot");
1192 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1193 Q_RETURN_ARG(uint, hash));
1194 expectedHash = qHash(key: QString("testSlot()"));
1195 QCOMPARE(hash, expectedHash);
1196
1197 // Test invokable slot with various arguments
1198 QVariant test("CANT BE NULL");
1199 QByteArray d = "array";
1200 int num = 5;
1201 QString output = QString("%1, %2, %3, %4");
1202 output = output.arg(a: d.constData()).arg(a: num).arg(a: test.toString()).arg(a: test.isValid());
1203 expectedHash = qHash(key: output);
1204 QMetaObject::invokeMethod(obj: service, member: "testSlotWithArgs",
1205 Q_ARG(QByteArray, d), Q_ARG(int, num), Q_ARG(QVariant, test));
1206 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1207 Q_RETURN_ARG(uint, hash));
1208 QCOMPARE(hash, expectedHash);
1209
1210 // Test failed invokable slot since QServiceInterfaceDescriptor is not a registered meta type
1211 // by checking that the service didn't set the hash to -1 due to being called
1212 QServiceInterfaceDescriptor desc;
1213 QMetaObject::invokeMethod(obj: service, member: "testSlotWithUnknownArg",
1214 Q_ARG(QServiceInterfaceDescriptor, desc));
1215 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1216 Q_RETURN_ARG(uint, hash));
1217 QVERIFY(hash != 1);
1218
1219 // Test slot function with custom argument
1220 QServiceFilter f("com.myInterface" , "4.5");
1221 f.setServiceName("MyService");
1222 output = QString("%1: %2 - %3.%4");
1223 output = output.arg(a: f.serviceName()).arg(a: f.interfaceName())
1224 .arg(a: f.majorVersion()).arg(a: f.minorVersion());
1225 expectedHash = qHash(key: output);
1226 QMetaObject::invokeMethod(obj: service, member: "testSlotWithCustomArg",
1227 Q_ARG(QServiceFilter, f));
1228 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1229 Q_RETURN_ARG(uint, hash));
1230 QCOMPARE(hash, expectedHash);
1231
1232 // Test invokable method with a QList argument
1233 QList<QString> list;
1234 list << "one" << "two" << "three";
1235 output = "";
1236 for (int i=0; i<list.size(); i++) {
1237 output += list[i];
1238 if (i<list.size()-1)
1239 output += ", ";
1240 }
1241 expectedHash = qHash(key: output);
1242 QMetaObject::invokeMethod(obj: serviceUnique, member: "testSlotWithListArg",
1243 Q_ARG(QList<QString>, list));
1244 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1245 Q_RETURN_ARG(uint, hash));
1246 QCOMPARE(hash, expectedHash);
1247
1248 // Test slot with QHash<QString, QVariant>
1249 QHash<QString, QVariant> hashv;
1250 hashv["test"] = QVariant::fromValue(value: 1);
1251 hashv["test2"] = QVariant::fromValue(value: QString("test2 string"));
1252 hashv["test3"] = QVariant::fromValue(value: true);
1253 QHashIterator<QString, QVariant> i(hashv);
1254 output.clear();
1255 QStringList lines;
1256 while (i.hasNext()) {
1257 i.next();
1258 QString line = i.key();
1259 line += "=";
1260 line += i.value().toString();
1261 lines << line;
1262 }
1263 lines.sort();
1264 output = lines.join(QStringLiteral(","));
1265 expectedHash = qHash(key: output);
1266
1267 QMetaObject::invokeMethod(obj: serviceUnique, member: "testSlotWithComplexArg",
1268 Q_ARG(QVariantHash, hashv));
1269 QMetaObject::invokeMethod(obj: service, member: "slotConfirmation",
1270 Q_RETURN_ARG(uint, hash));
1271 QCOMPARE(hash, expectedHash);
1272
1273
1274}
1275
1276void tst_QServiceManager_IPC::verifyServiceClass()
1277{
1278 QRemoteServiceRegister *registerObject = new QRemoteServiceRegister();
1279
1280 QVERIFY2(registerObject->quitOnLastInstanceClosed() == true, "should default to true, default is to shutdown");
1281 registerObject->setQuitOnLastInstanceClosed(false);
1282 QVERIFY2(registerObject->quitOnLastInstanceClosed() == false, "must transition to false");
1283 registerObject->setQuitOnLastInstanceClosed(true);
1284 QVERIFY2(registerObject->quitOnLastInstanceClosed() == true, "must transition back to true");
1285
1286 delete registerObject;
1287}
1288
1289void tst_QServiceManager_IPC::verifyLargeDataTransfer()
1290{
1291 QFETCH(QByteArray, data);
1292
1293 QMetaObject::invokeMethod(obj: serviceUnique, member: "testSlotWithData",
1294 Q_ARG(QByteArray, data));
1295 QByteArray ret_data;
1296 QMetaObject::invokeMethod(obj: serviceUnique, member: "testInvoableWithReturnData", Q_RETURN_ARG(QByteArray, ret_data));
1297
1298 QVERIFY2(data.length() == ret_data.length(), "Returned data from the service is not the same length as data sent");
1299 QVERIFY2(data == ret_data, "Returned data from service does not match");
1300}
1301
1302void tst_QServiceManager_IPC::verifyLargeDataTransfer_data()
1303{
1304 QTest::addColumn<QByteArray>(name: "data");
1305
1306 QTest::newRow(dataTag: "Trivial") << QByteArray("c");
1307 QTest::newRow(dataTag: "1k") << QByteArray(1024, 'A');
1308 QTest::newRow(dataTag: "2k") << QByteArray(2048, 'A');
1309 QTest::newRow(dataTag: "4k") << QByteArray(4096, 'A');
1310 QTest::newRow(dataTag: "8k") << QByteArray(8192, 'A');
1311 QTest::newRow(dataTag: "16k") << QByteArray(16384, 'A');
1312 QTest::newRow(dataTag: "32k") << QByteArray(32768, 'A');
1313 QTest::newRow(dataTag: "64k") << QByteArray(65536, 'A');
1314 QTest::newRow(dataTag: "128k") << QByteArray(131072, 'A');
1315 QTest::newRow(dataTag: "1 megabyte") << QByteArray(1048576, 'A');
1316 QTest::newRow(dataTag: "Free mem") << QByteArray("");
1317}
1318
1319class FetchLotsOfProperties : public QThread
1320{
1321 Q_OBJECT
1322public:
1323 FetchLotsOfProperties(int runs, bool shared, QObject *parent = 0);
1324 void run();
1325
1326public slots:
1327 void startFetches();
1328 void printProgress();
1329
1330private slots:
1331 void setup();
1332 void fetchProperty();
1333 void ipcError();
1334
1335signals:
1336 void ready();
1337 void error();
1338
1339private:
1340 int runs;
1341 int start_runs;
1342 bool shared;
1343 QString lastValue;
1344 QObject *service;
1345 QServiceManager *mgr;
1346};
1347
1348FetchLotsOfProperties::FetchLotsOfProperties(int runs, bool shared, QObject *parent)
1349 : QThread(parent),
1350 service(0),
1351 mgr(0)
1352{
1353 this->runs = runs;
1354 this->shared = shared;
1355 this->start_runs = runs;
1356}
1357
1358void FetchLotsOfProperties::run()
1359{
1360 QMetaObject::invokeMethod(obj: this, member: "setup", type: Qt::QueuedConnection);
1361 exec();
1362}
1363
1364void FetchLotsOfProperties::setup()
1365{
1366 mgr = new QServiceManager(this);
1367
1368 if (!mgr) {
1369 qWarning() << "Failed to create a manager";
1370 emit error();
1371 exit(retcode: -1);
1372 }
1373
1374 QList<QServiceInterfaceDescriptor> list = mgr->findInterfaces(serviceName: "IPCExampleService");
1375 if (list.isEmpty()) {
1376 qWarning() << "Thread failed to query the database, or the database contained no services";
1377 emit error();
1378 exit(retcode: -1);
1379 return;
1380 }
1381 foreach (const QServiceInterfaceDescriptor &d, list) {
1382 if (d.majorVersion() == 3 && d.minorVersion() == 5 && !shared) {
1383 service = mgr->loadInterface(descriptor: d);
1384 }
1385 if (d.majorVersion() == 3 && d.minorVersion() == 4 && shared) {
1386 service = mgr->loadInterface(descriptor: d);
1387 }
1388 if (service)
1389 connect(sender: service, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), receiver: this, SLOT(ipcError()));
1390 }
1391
1392 if (!service) {
1393 qWarning() << "Thread failed to load service";
1394 emit error();
1395 exit(retcode: -1);
1396 return;
1397 }
1398
1399 connect(sender: this, SIGNAL(destroyed()), receiver: service, SLOT(deleteLater()));
1400
1401 lastValue = service->property(name: "value").toString();
1402
1403 emit ready();
1404}
1405
1406void FetchLotsOfProperties::startFetches()
1407{
1408 if (!mgr || !service) {
1409 exit(retcode: -1);
1410 }
1411
1412 if (runs > 0) {
1413 QMetaObject::invokeMethod(obj: this, member: "fetchProperty", type: Qt::QueuedConnection);
1414 }
1415 else {
1416 quit();
1417 }
1418}
1419
1420void FetchLotsOfProperties::printProgress()
1421{
1422 qWarning() << "Thread has" << runs << "left, started with" << start_runs;
1423}
1424
1425void FetchLotsOfProperties::fetchProperty()
1426{
1427 if (!service) {
1428 emit error();
1429 exit(retcode: -1);
1430 }
1431
1432 QString value = service->property(name: "value").toString();
1433 if (value != lastValue) {
1434 qWarning() << "Value changed on read! Got" << value << "wanted" << lastValue;
1435 emit error();
1436 exit(retcode: -1);
1437 }
1438
1439 if (runs-- > 0) {
1440 QMetaObject::invokeMethod(obj: this, member: "fetchProperty", type: Qt::QueuedConnection);
1441 }
1442 else {
1443 quit();
1444 }
1445}
1446
1447void FetchLotsOfProperties::ipcError()
1448{
1449
1450}
1451
1452void tst_QServiceManager_IPC::verifyThreadSafety()
1453{
1454 QFETCH(int, shared);
1455 QFETCH(int, runs);
1456 QFETCH(int, threads);
1457
1458 QSignalSpy ready(this, SIGNAL(threadReady()));
1459 QSignalSpy finished(this, SIGNAL(threadFinished()));
1460 QSignalSpy errors(this, SIGNAL(threadError()));
1461 bool mixed = true;
1462 for (int i = 0; i < threads; i++) {
1463 switch (shared) {
1464 case 0:
1465 mixed = false;
1466 break;
1467 case 1:
1468 mixed = true;
1469 break;
1470 case 2:
1471 mixed = !mixed;
1472 }
1473 FetchLotsOfProperties *fetch = new FetchLotsOfProperties(runs, mixed, this);
1474 connect(sender: this, SIGNAL(threadRun()), receiver: fetch, SLOT(startFetches()));
1475 connect(sender: fetch, SIGNAL(ready()), receiver: this, SIGNAL(threadReady()));
1476 connect(sender: fetch, SIGNAL(error()), receiver: this, SIGNAL(threadError()));
1477 connect(sender: fetch, SIGNAL(finished()), receiver: this, SIGNAL(threadFinished()));
1478 connect(sender: fetch, SIGNAL(finished()), receiver: fetch, SLOT(deleteLater()));
1479 connect(sender: this, SIGNAL(threadRemaining()), receiver: fetch, SLOT(printProgress()));
1480 fetch->start();
1481 }
1482
1483
1484#define THREAD_TIMEOUT 30*1000
1485
1486 QTimer timer;
1487 timer.setInterval(THREAD_TIMEOUT);
1488 timer.setSingleShot(true);
1489 timer.start();
1490
1491 QTime start = QTime::currentTime();
1492
1493 while (((ready.count()) < threads) && (timer.isActive())) {
1494 QCOMPARE(errors.count(), 0);
1495 QCoreApplication::processEvents();
1496 QCoreApplication::sendPostedEvents(receiver: 0, event_type: QEvent::DeferredDelete);
1497 }
1498 QTRY_COMPARE(ready.count(), threads);
1499 QVERIFY2(!errors.count(), "Threads reported errors on setup");
1500 emit threadRun();
1501
1502 qDebug() << "Waiting on" << threads << "threads to finish";
1503
1504 while (((finished.count() + errors.count()) < threads) && (timer.isActive())) {
1505 QCOMPARE(errors.count(), 0);
1506 QCoreApplication::processEvents();
1507 QCoreApplication::sendPostedEvents(receiver: 0, event_type: QEvent::DeferredDelete);
1508 }
1509
1510 qDebug() << "Waited" << start.secsTo(QTime::currentTime()) << "seconds";
1511
1512 if (finished.count() != threads){
1513 emit threadRemaining();
1514 }
1515
1516 QCOMPARE(finished.count(), threads);
1517 QVERIFY2(!errors.count(), "Threads reported errors");
1518}
1519
1520void tst_QServiceManager_IPC::verifyThreadSafety_data()
1521{
1522 QTest::addColumn<int>(name: "shared");
1523 QTest::addColumn<int>(name: "runs");
1524 QTest::addColumn<int>(name: "threads");
1525
1526 QTest::newRow(dataTag: "unique, 2 threads") << 0 << 50 << 2;
1527 QTest::newRow(dataTag: "unique, 4 threads") << 0 << 25 << 4;
1528 QTest::newRow(dataTag: "unique, 16 threads") << 0 << 5 << 16;
1529 QTest::newRow(dataTag: "shared, 2 threads") << 1 << 50 << 2;
1530 QTest::newRow(dataTag: "shared, 4 threads") << 1 << 25 << 4;
1531 QTest::newRow(dataTag: "shared, 16 threads") << 1 << 5 << 16;
1532 QTest::newRow(dataTag: "mixed, 16 threads") << 2 << 5 << 16;
1533#ifndef Q_OS_WIN // Limit on event notifiers.
1534 QTest::newRow(dataTag: "unique, 128 threads") << 0 << 5 << 128;
1535 QTest::newRow(dataTag: "shared, 128 threads") << 1 << 5 << 128;
1536 QTest::newRow(dataTag: "mixed, 128 threads") << 2 << 5 << 128;
1537#endif // Q_OS_WIN
1538}
1539
1540void tst_QServiceManager_IPC::unblockRemote()
1541{
1542 QString ret = serviceUnique->property(name: "releaseBlockingRead").toString();
1543 QCOMPARE(ret, QStringLiteral("releaseBlockingReadReturned"));
1544}
1545
1546void tst_QServiceManager_IPC::verifyRemoteBlockingFunctions()
1547{
1548#ifdef SFW_USE_DBUS_BACKEND
1549 QEXPECT_FAIL("", "Test case known to segfault on dbus, skipping, QTBUG-23168", Abort);
1550 QVERIFY(false);
1551#else
1552 connect(serviceUnique, SIGNAL(blockingValueRead()), this, SLOT(unblockRemote()));
1553
1554 QString ret = serviceUnique->property("blockingValue").toString();
1555 QCOMPARE(ret, QStringLiteral("blockingValueReturned"));
1556#endif
1557}
1558
1559void tst_QServiceManager_IPC::testSignalSlotOrdering()
1560{
1561 QSignalSpy spy(serviceUnique, SIGNAL(count(int)));
1562
1563 int value = -1;
1564 bool ret = QMetaObject::invokeMethod(obj: serviceUnique, member: "testSignalSlotOrdering", Q_RETURN_ARG(int, value));
1565 QVERIFY2(ret == true, "Verify slot call worked");
1566 QVERIFY2(value == 0, "Verify slot return value");
1567 QVERIFY2(spy.count() == 0, "Verify no signals fired before the invokeMethod returns");
1568 QTRY_COMPARE(spy.count(), 20);
1569}
1570
1571void tst_QServiceManager_IPC::testServiceSecurity()
1572{
1573
1574 QServiceManager* manager = new QServiceManager(this);
1575 QList<QServiceInterfaceDescriptor> list = manager->findInterfaces(serviceName: "IPCExampleService");
1576 QServiceInterfaceDescriptor d, dPriv, dGlobal;
1577 foreach (QServiceInterfaceDescriptor d, list){
1578 if (d.majorVersion() == 3 && d.minorVersion() == 9) {
1579 dPriv = d;
1580 }
1581 if (d.majorVersion() == 3 && d.minorVersion() == 10) {
1582 dGlobal = d;
1583 }
1584 }
1585
1586 QVERIFY(dPriv.isValid());
1587 QVERIFY(dGlobal.isValid());
1588
1589 // Rejects all connections
1590 QObject *o = manager->loadInterface(descriptor: dPriv);
1591 QVERIFY2(o == 0, "Everything should fail security/creation with this interface");
1592
1593 o = manager->loadInterface(descriptor: dGlobal);
1594 QVERIFY2(o, "Global class should allow the first connection");
1595
1596 bool status;
1597 // make sync call to ensure remote is in the same state
1598 QMetaObject::invokeMethod(obj: o, member: "disableConnections", Q_RETURN_ARG(bool, status), Q_ARG(bool, true));
1599 QCOMPARE(status, true);
1600
1601 // expect a null object back
1602 QObject *second = manager->loadInterface(descriptor: dGlobal);
1603 QVERIFY2(second == 0, "Security checks should no longer allow objects to be created");
1604
1605 // make sync call to ensure remote is in the same state
1606 QMetaObject::invokeMethod(obj: o, member: "disableConnections", Q_RETURN_ARG(bool, status), Q_ARG(bool, false));
1607
1608 second = manager->loadInterface(descriptor: dGlobal);
1609 QVERIFY2(second != 0, "Object creation should be allowed");
1610
1611 delete second;
1612
1613}
1614
1615void tst_QServiceManager_IPC::testProcessLaunch()
1616{
1617}
1618
1619void tst_QServiceManager_IPC::verifyAsyncLoading()
1620{
1621
1622 QFETCH(QString, serviceInterface);
1623 QFETCH(int, descriptor);
1624 QFETCH(bool, errors);
1625 QFETCH(int, simultaneous);
1626
1627 QServiceManager mgr;
1628
1629 QServiceReply *reply = 0;
1630 QServiceReply *replies[16]; // must be constant for windows, set to max size below
1631
1632 if (simultaneous > 0) {
1633 for (int i = 0; i < simultaneous; i++) {
1634 replies[i] = mgr.loadInterfaceRequest(interfaceName: serviceInterface);
1635 }
1636 reply = replies[0];
1637 } else if (descriptor > 0) {
1638 QList<QServiceInterfaceDescriptor> list = mgr.findInterfaces(serviceName: "IPCExampleService");
1639 QServiceInterfaceDescriptor d;
1640 foreach (d, list) {
1641 if (d.majorVersion() == 3 && d.minorVersion() == descriptor) {
1642 break;
1643 }
1644 }
1645 reply = mgr.loadInterfaceRequest(descriptor: d);
1646 } else if (!serviceInterface.isEmpty()) {
1647 reply = mgr.loadInterfaceRequest(interfaceName: serviceInterface);
1648 } else {
1649 QFAIL("No descriptor nor interface speficied");
1650 }
1651
1652
1653 QSignalSpy startedSpy(reply, SIGNAL(started()));
1654 QSignalSpy errorSpy(reply, SIGNAL(errorChanged()));
1655 QSignalSpy finishedSpy(reply, SIGNAL(finished()));
1656
1657 QCOMPARE(startedSpy.count(), 0);
1658
1659 QTRY_COMPARE(startedSpy.count(), 1);
1660 if (!errors)
1661 QCOMPARE(errorSpy.count(), 0);
1662
1663 QTRY_COMPARE(finishedSpy.count(), 1);
1664 QCOMPARE(reply->isFinished(), true);
1665 if (!errors) {
1666 QCOMPARE(errorSpy.count(), 0);
1667 QCOMPARE(reply->error(), QServiceManager::NoError);
1668 } else {
1669 QCOMPARE(errorSpy.count(), 1);
1670 QVERIFY(reply->error() != QServiceManager::NoError);
1671 }
1672
1673
1674
1675 if (simultaneous) {
1676 for (int i = 0; i < simultaneous; i++) {
1677 QTRY_COMPARE(replies[i]->isFinished(), true);
1678 QCOMPARE(replies[i]->error(), QServiceManager::NoError);
1679 }
1680 }
1681
1682 delete reply;
1683}
1684
1685void tst_QServiceManager_IPC::verifyAsyncLoading_data()
1686{
1687 QTest::addColumn<QString>(name: "serviceInterface");
1688 QTest::addColumn<int>(name: "descriptor");
1689 QTest::addColumn<bool>(name: "errors");
1690 QTest::addColumn<int>(name: "simultaneous");
1691
1692
1693 QTest::newRow(dataTag: "Load minor version 5") << QString() << 5 << false << 0;
1694 QTest::newRow(dataTag: "Load default interface") << QString("com.nokia.qt.ipcunittest") << 0 << false << 0;
1695 QTest::newRow(dataTag: "Load invalid interface") << QString("com.nokia.qt.ipcunittest.does.not.exist") << 0 << true << 0;
1696 QTest::newRow(dataTag: "Load 4 interfaces") << QString("com.nokia.qt.ipcunittest") << 1 << false << 4;
1697 QTest::newRow(dataTag: "Load 16 interfaces") << QString("com.nokia.qt.ipcunittest") << 1 << false << 16;
1698
1699}
1700
1701void tst_QServiceManager_IPC::testIpcFailure()
1702{
1703 // test deleting an object doesn't trigger an IPC fault
1704 ipcfailure = false;
1705 delete serviceShared;
1706 QVERIFY2(!ipcfailure, "Deleting an object should not cause an IPC failure message");
1707 serviceShared = 0;
1708
1709 ipcfailure = false;
1710 QMetaObject::invokeMethod(obj: serviceUnique, member: "testIpcFailure");
1711 int i = 0;
1712 while (!ipcfailure && i++ < 50)
1713 QTest::qWait(ms: 50);
1714
1715 QVERIFY(ipcfailure);
1716
1717 // TODO restart the connection
1718 //initTestCase();
1719}
1720
1721void tst_QServiceManager_IPC::verifyFailures()
1722{
1723 bool result;
1724
1725 QServiceManager* manager = new QServiceManager(this);
1726 QList<QServiceInterfaceDescriptor> list = manager->findInterfaces(serviceName: "IPCExampleService");
1727 QServiceInterfaceDescriptor d;
1728 foreach (d, list){
1729 if (d.majorVersion() == 3 && d.minorVersion() == 6) {
1730 QObject *o = manager->loadInterface(descriptor: d);
1731 QVERIFY2(o == 0, "Failure to allocate remote object returns null");
1732 }
1733 if (d.majorVersion() == 3 && d.minorVersion() == 7) {
1734 QObject *o = manager->loadInterface(descriptor: d);
1735 QVERIFY2(o == 0, "Failure to allocate remote object returns null");
1736 }
1737 }
1738
1739 QMetaObject::invokeMethod(obj: miscTest, member: "addTwice",
1740 Q_RETURN_ARG(bool, result));
1741 QVERIFY2(result, "Added the same service twice, returned different entries");
1742
1743 QMetaObject::invokeMethod(obj: miscTest, member: "getInvalidEntry",
1744 Q_RETURN_ARG(bool, result));
1745 QVERIFY2(result, "Invalid entry returns invalid meta data");
1746
1747 delete manager;
1748
1749}
1750
1751
1752
1753QTEST_MAIN(tst_QServiceManager_IPC);
1754#include "tst_qservicemanager_ipc.moc"
1755

source code of qtsystems/tests/auto/serviceframework/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp