1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtSystems module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33#include <QCoreApplication>
34#include <QTimer>
35#include <qremoteserviceregister.h>
36#include <qservicemanager.h>
37#include <QDebug>
38#include <QTest>
39#include <QFileInfo>
40
41#include <qservicefilter.h> //only used to test custom metatype
42#ifdef QT_BUILD_INTERNAL
43#include <private/instancemanager_p.h>
44#endif
45
46QT_USE_NAMESPACE
47Q_DECLARE_METATYPE(QServiceFilter);
48Q_DECLARE_METATYPE(QVariant);
49Q_DECLARE_METATYPE(QList<QString>);
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
70class SharedTestService : public QObject
71{
72 Q_OBJECT
73 Q_PROPERTY(QString value READ value WRITE setValue RESET resetValue NOTIFY valueChanged SCRIPTABLE true DESIGNABLE true STORED true);
74
75public:
76 SharedTestService(QObject* parent = 0)
77 : QObject(parent)
78 {
79 qFatal(msg: "Insecure constructor called, this should never be called if a secured constructor is available");
80 resetValue();
81 }
82
83 Q_INVOKABLE SharedTestService(QServiceClientCredentials *creds)
84 : QObject(0)
85 {
86 creds->setClientAccepted(true);
87 resetValue();
88 }
89
90 Q_INVOKABLE void verifyNewServiceClientCredentials(QServiceClientCredentials *creds)
91 {
92 creds->setClientAccepted(true);
93 }
94
95 QString value() const
96 {
97 return m_value;
98 }
99
100 void setValue(const QString& value)
101 {
102 m_value = value;
103 emit valueChanged();
104 }
105
106 void resetValue()
107 {
108 m_value = "FFF";
109 emit valueChanged();
110 }
111
112 Q_INVOKABLE QString testFunctionWithReturnValue(int input)
113 {
114 QString output("%1 + 3 = %2");
115 output = output.arg(a: input).arg(a: input+3);
116 return output;
117 }
118
119 Q_INVOKABLE QVariant testFunctionWithVariantReturnValue(const QVariant& input)
120 {
121 m_hash = qHash(key: input.toString());
122 return input;
123 }
124
125 Q_INVOKABLE QServiceFilter testFunctionWithCustomReturnValue()
126 {
127 QServiceFilter f("com.nokia.qt.ipcunittest", "6.2");
128 f.setServiceName("MySharedService");
129 return f;
130 }
131
132 Q_INVOKABLE uint slotConfirmation() const
133 {
134 return m_hash;
135 }
136
137 Q_INVOKABLE void setConfirmationHash(uint hash)
138 {
139 m_hash = hash;
140 }
141
142Q_SIGNALS:
143 void signalWithIntParam(int);
144 void signalWithVariousParam(QVariant,QString,QServiceFilter);
145 void valueChanged();
146
147public slots:
148 void triggerSignalWithIntParam()
149 {
150 QTimer::singleShot(msec: 2000, receiver: this, SLOT(triggerSignalWithIntParamExecute()));
151 }
152
153 void triggerSignalWithVariousParam()
154 {
155 QTimer::singleShot(msec: 2000, receiver: this, SLOT(triggerSignalWithVariousParamExecute()));
156 }
157
158 void triggerSignalWithIntParamExecute()
159 {
160 emit signalWithIntParam( 5 );
161 }
162
163 void triggerSignalWithVariousParamExecute()
164 {
165 QServiceFilter f("com.nokia.qt.ipcunittest", "6.7");
166 f.setServiceName("MyService");
167 emit signalWithVariousParam( QVariant(), QString("string-value"), f );
168 }
169 void testSlot()
170 {
171 m_hash = qHash(key: QString("testSlot()"));
172 }
173
174 void testSlotWithArgs(const QByteArray& d, int a, const QVariant& variant)
175 {
176 QString output("%1, %2, %3, %4");
177 output = output.arg(a: d.constData()).arg(a).arg(a: variant.toString()).arg(a: variant.isValid());
178 m_hash = qHash(key: output);
179 }
180
181 void testSlotWithCustomArg(const QServiceFilter& f)
182 {
183 QString output("%1: %2 - %3.%4");
184 output = output.arg(a: f.serviceName()).arg(a: f.interfaceName())
185 .arg(a: f.majorVersion()).arg(a: f.minorVersion());
186 m_hash = qHash(key: output);
187 }
188
189 void testSlotWithUnknownArg(const QServiceInterfaceDescriptor& )
190 {
191 m_hash = 1;
192 }
193
194 void testSlotWithComplexArg(QVariantHash arg)
195 {
196 QHashIterator<QString, QVariant> i(arg);
197 QString output;
198 while (i.hasNext()) {
199 i.next();
200// qDebug() << i.key() << ": " << i.value();
201 output += i.key();
202 output += "=";
203 output += i.value().toString();
204 output += ", ";
205 }
206 qDebug() << output;
207 m_hash = qHash(key: output);
208 }
209
210 void testIpcFailure()
211 {
212 qApp->exit(retcode: 0); // exit to show failure
213 }
214
215private:
216 QString m_value;
217 uint m_hash;
218};
219
220class UniqueTestService : public QObject
221{
222 Q_OBJECT
223 Q_CLASSINFO("UniqueTestService", "First test")
224 Q_CLASSINFO("Key", "Value")
225
226 Q_PROPERTY(QString value READ value WRITE setValue RESET resetValue NOTIFY valueChanged SCRIPTABLE true DESIGNABLE true STORED true)
227 Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
228 Q_PROPERTY(ServiceFlag serviceFlags READ flags WRITE setFlags)
229 Q_PROPERTY(QString blockingValue READ blockingValue)
230 Q_PROPERTY(QString releaseBlockingRead READ releaseBlockingRead)
231 Q_ENUMS(Priority)
232 Q_FLAGS(ServiceFlag ServiceFlags)
233
234public:
235 enum ServiceFlag {
236 FirstBit = 0x01,
237 SecondBit = 0x02,
238 ThirdBit = 0x04
239 };
240 Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag)
241
242 ServiceFlags flags() const { return m_flags; }
243 void setFlags(ServiceFlags f) {
244 m_flags = f;
245 }
246
247 enum Priority { High, Low, VeryLow, ExtremelyLow };
248
249 void setPriority(Priority p) {
250 m_priority = p;
251 emit priorityChanged();
252 }
253
254 Priority priority() const
255 {
256 return m_priority;
257 }
258
259 UniqueTestService(QObject* parent = 0)
260 : QObject(parent)
261 {
262 qFatal(msg: "Wrong constructor called, must call secure constructor only");
263 abort();
264 resetValue();
265 }
266
267 Q_INVOKABLE UniqueTestService(QServiceClientCredentials *creds)
268 : QObject(0), m_priority(UniqueTestService::High), m_flags(ThirdBit)
269 {
270 // accept everyone
271 creds->setClientAccepted(true);
272 resetValue();
273 }
274
275 QString value() const
276 {
277 return m_value;
278 }
279
280 void setValue(const QString& value)
281 {
282 m_value = value;
283 emit valueChanged();
284 }
285
286 void resetValue()
287 {
288 m_value = "FFF";
289 emit valueChanged();
290 }
291
292 QString blockingValue()
293 {
294 emit blockingValueRead();
295 m_loop.exec();
296 return QStringLiteral("blockingValueReturned");
297 }
298
299 QString releaseBlockingRead()
300 {
301 m_loop.quit();
302 return QStringLiteral("releaseBlockingReadReturned");
303 }
304
305 Q_INVOKABLE QString testFunctionWithReturnValue(int input)
306 {
307 QString output("%1 x 3 = %2");
308 output = output.arg(a: input).arg(a: input*3);
309 return output;
310 }
311
312 Q_INVOKABLE QVariant testFunctionWithVariantReturnValue(const QVariant& input)
313 {
314 return input;
315 }
316
317 Q_INVOKABLE QServiceFilter testFunctionWithCustomReturnValue()
318 {
319 QServiceFilter f("com.nokia.qt.ipcunittest", "6.7");
320 f.setServiceName("MyUniqueService");
321 return f;
322 }
323
324 Q_INVOKABLE QList<QString> testFunctionWithListReturn()
325 {
326 QList<QString> list;
327 list << "1" << "2" << "3";
328 return list;
329 }
330
331 Q_INVOKABLE uint slotConfirmation() const
332 {
333 return m_hash;
334 }
335
336 Q_INVOKABLE void setConfirmationHash(uint hash)
337 {
338 m_hash = hash;
339 }
340
341Q_SIGNALS:
342 void signalWithIntParam(int);
343 void signalWithVariousParam(QVariant,QString,QServiceFilter,QVariant);
344 void valueChanged();
345 void priorityChanged();
346 void count(int value);
347 void blockingValueRead();
348
349public slots:
350 void triggerSignalWithIntParam()
351 {
352 QTimer::singleShot(msec: 2000, receiver: this, SLOT(triggerSignalWithIntParamExecute()));
353 }
354
355 void triggerSignalWithVariousParam()
356 {
357 QTimer::singleShot(msec: 2000, receiver: this, SLOT(triggerSignalWithVariousParamExecute()));
358 }
359
360 void triggerSignalWithIntParamExecute()
361 {
362 emit signalWithIntParam( 5 );
363 }
364
365 void triggerSignalWithVariousParamExecute()
366 {
367 QServiceFilter f("com.nokia.qt.ipcunittest", "6.7");
368 f.setServiceName("MyService");
369 emit signalWithVariousParam( QVariant("CAN'T BE NULL"), QString("string-value"), f, QVariant(5) );
370 }
371
372 void testSlot() {
373 m_hash = qHash(key: QString("testSlot()"));
374 }
375
376 void testSlotWithArgs(const QByteArray& d, int a, const QVariant& variant)
377 {
378 QString output("%1, %2, %3, %4");
379 output = output.arg(a: d.constData()).arg(a).arg(a: variant.toString()).arg(a: variant.isValid());
380 m_hash = qHash(key: output);
381 }
382
383 void testSlotWithCustomArg(const QServiceFilter& f)
384 {
385 QString output("%1: %2 - %3.%4");
386 output = output.arg(a: f.serviceName()).arg(a: f.interfaceName())
387 .arg(a: f.majorVersion()).arg(a: f.minorVersion());
388 m_hash = qHash(key: output);
389 }
390
391 void testSlotWithUnknownArg(const QServiceInterfaceDescriptor& )
392 {
393 m_hash = 1;
394 }
395
396 void testSlotWithListArg(QList<QString> list)
397 {
398 QString output;
399 for (int i=0; i<list.size(); i++) {
400 output += list[i];
401 if (i<list.size()-1)
402 output += ", ";
403 }
404 m_hash = qHash(key: output);
405 }
406
407 void testSlotWithComplexArg(QVariantHash arg)
408 {
409 QHashIterator<QString, QVariant> i(arg);
410 QStringList lines;
411 while (i.hasNext()) {
412 i.next();
413 QString line = i.key();
414 line += "=";
415 line += i.value().toString();
416 lines << line;
417 }
418 lines.sort();
419 QString output = lines.join(QStringLiteral(","));
420 m_hash = qHash(key: output);
421 }
422
423 void testSlotWithData(QByteArray data)
424 {
425 m_data = data;
426 }
427
428 QByteArray testInvoableWithReturnData()
429 {
430 return m_data;
431 }
432
433 int testSignalSlotOrdering() {
434 m_count = 0;
435 QMetaObject::invokeMethod(obj: this, member: "generateSignal", type: Qt::QueuedConnection);
436
437 return 0;
438 }
439
440 void generateSignal() {
441 emit count(value: m_count++);
442 if (m_count < 20) {
443 QMetaObject::invokeMethod(obj: this, member: "generateSignal", type: Qt::QueuedConnection);
444 }
445 }
446
447 void testIpcFailure() {
448 qApp->exit(retcode: 0); // exit to show failure
449 }
450
451private:
452 QString m_value;
453 Priority m_priority;
454 ServiceFlags m_flags;
455 uint m_hash;
456 QByteArray m_data;
457 int m_count;
458 QEventLoop m_loop;
459};
460
461class FailureTestServiceCreation : public QObject
462{
463 Q_OBJECT
464 Q_CLASSINFO("FailureTestServiceCreation", "Fails to be created");
465
466};
467
468class MiscTestService : public QObject
469{
470 Q_OBJECT
471public:
472 MiscTestService(QObject* parent = 0)
473 : QObject(parent)
474 {
475 qFatal(msg: "Invalid constructor called");
476 }
477
478 Q_INVOKABLE MiscTestService(QServiceClientCredentials *creds)
479 : QObject(0)
480 {
481 creds->setClientAccepted(true);
482 }
483
484
485 Q_INVOKABLE bool addTwice()
486 {
487 QRemoteServiceRegister* serviceRegister = new QRemoteServiceRegister();
488
489 //register the unique service
490 QRemoteServiceRegister::Entry uniqueEntry =
491 serviceRegister->createEntry<SharedTestService>(
492 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.5");
493
494 QRemoteServiceRegister::Entry uniqueEntry2 =
495 serviceRegister->createEntry<SharedTestService>(
496 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.5");
497 return (uniqueEntry == uniqueEntry2);
498
499 }
500
501 Q_INVOKABLE bool getInvalidEntry()
502 {
503#ifdef QT_BUILD_INTERNAL
504 InstanceManager *i = InstanceManager::instance();
505 QRemoteServiceRegister::Entry e; // entry should be invalid
506 const QMetaObject *o = i->metaObject(ident: e); // should return null
507 return (o == 0);
508#else
509 return true;
510#endif
511 }
512};
513
514class SecurityTestService : public QObject
515{
516 Q_OBJECT
517public:
518 SecurityTestService(QObject* parent = 0)
519 : QObject(parent)
520 {
521 qFatal(msg: "Invalid constructor called");
522 }
523
524 Q_INVOKABLE SecurityTestService(QServiceClientCredentials *creds)
525 : QObject(0)
526 {
527 qDebug() << "Creds" << creds->getProcessIdentifier() << creds->getUserIdentifier() << creds->getGroupIdentifier();
528 creds->setClientAccepted(false);
529 }
530};
531
532class GlobalSecurityTestService : public QObject
533{
534 Q_OBJECT
535public:
536 GlobalSecurityTestService(QObject* parent = 0)
537 : QObject(parent)
538 {
539 qFatal(msg: "Invalid constructor called");
540 // If this called, fail the rest of the tests, reverse this value
541 disabled = true;
542 }
543
544 Q_INVOKABLE GlobalSecurityTestService(QServiceClientCredentials *creds)
545 : QObject(0)
546 {
547 creds->setClientAccepted(true);
548 disabled = false;
549 }
550
551 Q_INVOKABLE void verifyNewServiceClientCredentials(QServiceClientCredentials *creds)
552 {
553 creds->setClientAccepted(!disabled);
554 }
555
556 Q_INVOKABLE bool disableConnections(bool disable)
557 {
558 this->disabled = disable;
559 return this->disabled;
560 }
561
562private:
563 bool disabled;
564};
565
566
567Q_DECLARE_METATYPE(QMetaType::Type);
568
569QT_BEGIN_NAMESPACE
570template <>
571QObject* qServiceTypeConstructHelper<FailureTestServiceCreation>()
572{
573 return 0x0;
574}
575QT_END_NAMESPACE
576
577int main(int argc, char** argv)
578{
579 QCoreApplication app(argc, argv);
580
581 qRegisterMetaType<QServiceFilter>();
582 qRegisterMetaTypeStreamOperators<QServiceFilter>(typeName: "QServiceFilter");
583
584 qRegisterMetaType<QVariant>();
585 qRegisterMetaTypeStreamOperators<QVariant>(typeName: "QVariant");
586
587 qRegisterMetaType<QList<QString> >();
588 qRegisterMetaTypeStreamOperators<QList<QString> >(typeName: "QList<QString>");
589
590 qRegisterMetaTypeStreamOperators<QVariantHash>(typeName: "QVariantHash");
591 qRegisterMetaType<QVariantHash>(typeName: "QVariantHash");
592#ifdef SFW_USE_DBUS_BACKEND
593 qDBusRegisterMetaType<QVariantHash>();
594#endif
595
596 QRemoteServiceRegister* serviceRegister = new QRemoteServiceRegister();
597
598 //register the unique service
599 QRemoteServiceRegister::Entry uniqueEntry =
600 serviceRegister->createEntry<UniqueTestService>(
601 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.5");
602 uniqueEntry.setInstantiationType(QRemoteServiceRegister::PrivateInstance);
603
604 //register the shared srevice
605 QRemoteServiceRegister::Entry sharedEntry =
606 serviceRegister->createEntry<SharedTestService>(
607 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.4");
608 sharedEntry.setInstantiationType(QRemoteServiceRegister::GlobalInstance);
609
610 // register the class to test creation failure
611 QRemoteServiceRegister::Entry creationEntry =
612 serviceRegister->createEntry<FailureTestServiceCreation>(
613 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.6");
614 creationEntry.setInstantiationType(QRemoteServiceRegister::GlobalInstance);
615
616 // register the class to test creation failure
617 QRemoteServiceRegister::Entry creationEntryPriv =
618 serviceRegister->createEntry<FailureTestServiceCreation>(
619 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.7");
620 creationEntryPriv.setInstantiationType(QRemoteServiceRegister::PrivateInstance);
621
622 // register the class to test creation failure
623 QRemoteServiceRegister::Entry miscEntry =
624 serviceRegister->createEntry<MiscTestService>(
625 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.8");
626 creationEntryPriv.setInstantiationType(QRemoteServiceRegister::GlobalInstance);
627
628 // register the class to test creation failure
629 QRemoteServiceRegister::Entry securityEntry =
630 serviceRegister->createEntry<SecurityTestService>(
631 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.9");
632 securityEntry.setInstantiationType(QRemoteServiceRegister::PrivateInstance);
633
634 // register the class to test creation failure
635 QRemoteServiceRegister::Entry globalSecurityEntry =
636 serviceRegister->createEntry<GlobalSecurityTestService>(
637 serviceName: "IPCExampleService", interfaceName: "com.nokia.qt.ipcunittest", version: "3.10");
638 globalSecurityEntry.setInstantiationType(QRemoteServiceRegister::GlobalInstance);
639
640 //publish the registered services
641 serviceRegister->publishEntries(ident: "qt_sfw_example_ipc_unittest");
642 int res = app.exec();
643 delete serviceRegister;
644
645 return res;
646}
647
648
649#include "main.moc"
650

source code of qtsystems/tests/auto/serviceframework/qservicemanager_ipc/service/main.cpp