Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2017 Ford Motor Company
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtRemoteObjects module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "../../shared/testutils.h"
30
31#include <QtTest/QtTest>
32#include <QMetaType>
33#include <QProcess>
34#include <QFileInfo>
35#include <QTcpServer>
36#include <QTcpSocket>
37
38#include <QRemoteObjectReplica>
39#include <QRemoteObjectNode>
40#include <QRemoteObjectSettingsStore>
41#include "engine.h"
42#include "speedometer.h"
43#include "rep_engine_replica.h"
44#include "rep_speedometer_merged.h"
45#include "rep_enum_merged.h"
46#include "rep_pod_merged.h"
47#include "rep_localdatacenter_source.h"
48#include "rep_tcpdatacenter_source.h"
49#include "rep_localdatacenter_replica.h"
50#include "rep_tcpdatacenter_replica.h"
51
52#define SET_NODE_NAME(obj) (obj).setName(QLatin1String(#obj))
53
54//DUMMY impl for variant comparison
55bool operator<(const QVector<int> &lhs, const QVector<int> &rhs)
56{
57 return lhs.size() < rhs.size();
58}
59
60class TestLargeData: public QObject
61{
62 Q_OBJECT
63
64Q_SIGNALS:
65 void send(const QByteArray &data);
66};
67
68class TestDynamicBase : public QObject
69{
70 Q_OBJECT
71public:
72 TestDynamicBase(QObject *parent=nullptr) : QObject(parent) {}
73
74signals:
75 void otherValueChanged();
76};
77
78
79class TestDynamic : public TestDynamicBase
80{
81 Q_OBJECT
82 Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
83 Q_PROPERTY(int otherValue READ otherValue WRITE setOtherValue NOTIFY otherValueChanged)
84public:
85 TestDynamic(QObject *parent=nullptr) :
86 TestDynamicBase(parent),
87 m_value(0),
88 m_otherValue(0) {}
89
90 int value() const { return m_value; }
91 void setValue(int value)
92 {
93 if (m_value == value)
94 return;
95
96 m_value = value;
97 emit valueChanged();
98 }
99
100 int otherValue() const { return m_otherValue; }
101 void setOtherValue(int otherValue)
102 {
103 if (m_otherValue == otherValue)
104 return;
105
106 m_otherValue = otherValue;
107 emit otherValueChanged();
108 }
109
110signals:
111 void valueChanged();
112
113private:
114 int m_value;
115 int m_otherValue;
116};
117
118class TestPersistedStore : public QRemoteObjectAbstractPersistedStore
119{
120 Q_OBJECT
121
122public:
123 TestPersistedStore() : type(EngineReplica::HYBRID) {}
124 void saveProperties(const QString &, const QByteArray &, const QVariantList &values) override
125 {
126 type = values.at(0).value<EngineReplica::EngineType>();
127 }
128 QVariantList restoreProperties(const QString &, const QByteArray &) override
129 {
130 return QVariantList() << QVariant::fromValue(type);
131 }
132private:
133 EngineReplica::EngineType type;
134};
135
136class tst_Integration: public QObject
137{
138 Q_OBJECT
139
140 void setupTcp()
141 {
142 if (!tcpServer) {
143 tcpServer = new QTcpServer;
144 tcpServer->listen(QHostAddress::Any, 65511);
145 socketClient = new QTcpSocket;
146 socketClient->connectToHost(QHostAddress::LocalHost, tcpServer->serverPort());
147 QVERIFY(socketClient->waitForConnected(5000));
148
149 QVERIFY(tcpServer->waitForNewConnection(5000));
150 QVERIFY(tcpServer->hasPendingConnections());
151 socketServer = tcpServer->nextPendingConnection();
152 }
153 }
154
155 void setupHost(bool useRegistry=false)
156 {
157 QFETCH_GLOBAL(QUrl, hostUrl);
158 QFETCH_GLOBAL(QUrl, registryUrl);
159 host = new QRemoteObjectHost;
160 SET_NODE_NAME(*host);
161 if (!hostUrl.isEmpty()) {
162 host->setHostUrl(hostUrl);
163 if (useRegistry)
164 host->setRegistryUrl(registryUrl);
165 } else {
166 setupTcp();
167 host->addHostSideConnection(socketServer);
168 }
169 }
170
171 void setupClient(bool useRegistry=false)
172 {
173 QFETCH_GLOBAL(QUrl, hostUrl);
174 QFETCH_GLOBAL(QUrl, registryUrl);
175 client = new QRemoteObjectNode;
176 Q_SET_OBJECT_NAME(*client);
177 if (!hostUrl.isEmpty())
178 {
179 if (useRegistry)
180 client->setRegistryUrl(registryUrl);
181 else {
182 client->connectToNode(hostUrl);
183 }
184 } else {
185 setupTcp();
186 client->addClientSideConnection(socketClient);
187 }
188 }
189
190 void setupRegistry()
191 {
192 QFETCH_GLOBAL(QUrl, registryUrl);
193 registry = new QRemoteObjectRegistryHost(registryUrl);
194 SET_NODE_NAME(*registry);
195 }
196
197signals:
198 void forwardResult(int);
199
200private:
201 QRemoteObjectHost *host;
202 QRemoteObjectNode *client;
203 QRemoteObjectRegistryHost *registry;
204 QTcpServer *tcpServer;
205 QPointer<QTcpSocket> socketClient, socketServer;
206
207private slots:
208 void initTestCase_data()
209 {
210 QTest::addColumn<QUrl>("hostUrl");
211 QTest::addColumn<QUrl>("registryUrl");
212
213 QTest::newRow("tcp") << QUrl(QLatin1String("tcp://127.0.0.1:65511")) << QUrl(QLatin1String("tcp://127.0.0.1:65512"));
214#ifdef __QNXNTO__
215 QTest::newRow("qnx") << QUrl(QLatin1String("qnx:replica")) << QUrl(QLatin1String("qnx:registry"));
216#endif
217#ifndef SKIP_LOCAL
218 QTest::newRow("local") << QUrl(QLatin1String("local:replica_local_integration")) << QUrl(QLatin1String("local:registry_local_integration"));
219#endif
220 QTest::newRow("external") << QUrl() << QUrl();
221 }
222
223 void initTestCase()
224 {
225 QLoggingCategory::setFilterRules("qt.remoteobjects.warning=false");
226
227 // use different paths in QRemoteObjectSettingsStore
228 QCoreApplication::setOrganizationName(QLatin1String("QtProject"));
229 QStandardPaths::setTestModeEnabled(true);
230 }
231
232 void init()
233 {
234 registry = nullptr;
235 host = nullptr;
236 client = nullptr;
237 tcpServer = nullptr;
238 socketClient = nullptr;
239 socketServer = nullptr;
240 }
241
242 void cleanup()
243 {
244 delete registry;
245 delete host;
246 delete client;
247 delete tcpServer;
248 if (socketClient) {
249 socketClient->deleteLater();
250 }
251 if (socketServer) {
252 socketServer->deleteLater();
253 }
254 // wait for delivery of RemoveObject events to the source
255 QTest::qWait(200);
256 }
257
258 void basicTest()
259 {
260 setupHost();
261 Engine e;
262 e.setRpm(1234);
263 host->enableRemoting(&e);
264
265 setupClient();
266 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
267 engine_r->waitForSource();
268 QCOMPARE(engine_r->rpm(), e.rpm());
269 }
270
271 void persistRestoreTest()
272 {
273 QRemoteObjectNode _client;
274 Q_SET_OBJECT_NAME(_client);
275 TestPersistedStore store;
276 _client.setPersistedStore(&store);
277
278 const QScopedPointer<EngineReplica> engine_r(_client.acquire<EngineReplica>());
279 QCOMPARE(engine_r->engineType(), EngineReplica::HYBRID);
280 }
281
282 void persistTest()
283 {
284 QRemoteObjectSettingsStore store;
285
286 setupHost();
287 Engine e;
288 e.setEngineType(EngineSimpleSource::ELECTRIC);
289 host->enableRemoting(&e);
290
291 setupClient();
292 client->setPersistedStore(&store);
293
294 QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
295 engine_r->waitForSource();
296 QCOMPARE(engine_r->engineType(), EngineReplica::ELECTRIC);
297
298 // Delete to persist
299 engine_r.reset();
300 host->disableRemoting(&e);
301
302 engine_r.reset(client->acquire<EngineReplica>());
303 QCOMPARE(engine_r->waitForSource(1000), false);
304 QCOMPARE(engine_r->engineType(), EngineReplica::ELECTRIC);
305 }
306
307 // ensure we don't crash when ObjectList iterates over in process replicas
308 void inProcessObjectList()
309 {
310 setupRegistry();
311 setupHost(true);
312 setupClient(true);
313 Engine e;
314 host->enableRemoting(&e);
315 e.setStarted(false);
316
317 const QScopedPointer<EngineReplica> engine_r(host->acquire<EngineReplica>());
318 const QScopedPointer<EngineReplica> engine_r2(client->acquire<EngineReplica>());
319 engine_r->waitForSource(1000);
320 engine_r2->waitForSource(1000);
321 QCOMPARE(engine_r->started(), false);
322 QCOMPARE(engine_r2->started(), false);
323 engine_r->pushStarted(true);
324
325 QTRY_COMPARE(engine_r->started(), true);
326 QTRY_COMPARE(engine_r2->started(), true);
327 }
328
329 void enumTest()
330 {
331 setupHost();
332
333 setupClient();
334
335 TestClassSimpleSource tc;
336 tc.setTestEnum(TestEnum::FALSE);
337 tc.setClassEnum(TestClassSimpleSource::One);
338 tc.setClassEnumRW(TestClassSimpleSource::One);
339 host->enableRemoting(&tc);
340 const QScopedPointer<TestClassReplica> tc_rep(client->acquire<TestClassReplica>());
341 tc_rep->waitForSource();
342 QCOMPARE(tc.testEnum(), tc_rep->testEnum());
343 QCOMPARE((qint32)tc.classEnum(), (qint32)TestClassSimpleSource::One);
344
345 // set property on the replica (test property change packet)
346 {
347 QSignalSpy spy(tc_rep.data(), SIGNAL(classEnumChanged(TestClassReplica::ClassEnum)));
348 QVERIFY(spy.isValid());
349 tc_rep->pushClassEnum(TestClassReplica::Two);
350 QVERIFY(spy.count() || spy.wait());
351
352 QCOMPARE((qint32)tc.classEnum(), (qint32)tc_rep->classEnum());
353 }
354
355 // set property on the source (test property change packet)
356 {
357 QSignalSpy spy(tc_rep.data(), SIGNAL(classEnumChanged(TestClassReplica::ClassEnum)));
358 tc.setClassEnum(TestClassSimpleSource::One);
359 QVERIFY(spy.wait());
360
361 QCOMPARE((qint32)tc.classEnum(), (qint32)tc_rep->classEnum());
362 }
363
364 QScopedPointer<QRemoteObjectDynamicReplica> tc_repDynamic(client->acquireDynamic(QStringLiteral("TestClass")));
365
366 tc_repDynamic->waitForSource(1000);
367 QVERIFY(tc_repDynamic->isInitialized());
368
369 const QMetaObject *metaObject = tc_repDynamic->metaObject();
370
371 int propertyIndex = metaObject->indexOfProperty("classEnumRW");
372 QVERIFY(propertyIndex >= 0);
373
374 QMetaProperty property = metaObject->property(propertyIndex);
375 QVERIFY(property.isValid());
376 QCOMPARE(property.typeName(), "ClassEnum");
377
378 // read enum on the dynamic replica
379 {
380 QCOMPARE(property.read(tc_repDynamic.data()).value<TestClassReplica::ClassEnum>(), TestClassReplica::One);
381 }
382
383 // write enum on the dynamic replica
384 {
385 QSignalSpy spy(tc_rep.data(), SIGNAL(classEnumRWChanged(TestClassReplica::ClassEnum)));
386 property.write(tc_repDynamic.data(), TestClassReplica::Two);
387 QVERIFY(spy.wait());
388
389 QCOMPARE(tc_rep->classEnumRW(), TestClassReplica::Two);
390 }
391
392 propertyIndex = metaObject->indexOfProperty("classEnum");
393 QVERIFY(propertyIndex >= 0);
394
395 property = metaObject->property(propertyIndex);
396 QVERIFY(property.isValid());
397 QCOMPARE(property.typeName(), "ClassEnum");
398
399 // read enum on the dynamic replica
400 {
401 QCOMPARE(property.read(tc_repDynamic.data()).value<TestClassReplica::ClassEnum>(), TestClassReplica::One);
402 }
403
404 // ensure write enum fails on ReadPush
405 {
406 QSignalSpy spy(tc_rep.data(), SIGNAL(classEnumChanged(TestClassReplica::ClassEnum)));
407 bool res = property.write(tc_repDynamic.data(), TestClassReplica::Two);
408 QVERIFY(!res);
409 int methodIndex = metaObject->indexOfMethod("pushClassEnum(TestClassReplica::ClassEnum)");
410 QVERIFY(methodIndex >= 0);
411 QMetaMethod method = metaObject->method(methodIndex);
412 QVERIFY(method.isValid());
413
414 QVERIFY(method.invoke(tc_repDynamic.data(), Q_ARG(TestClassReplica::ClassEnum, TestClassReplica::Two)));
415 QVERIFY(spy.wait());
416
417 QCOMPARE(tc_rep->classEnum(), TestClassReplica::Two);
418 }
419 }
420
421 void namedObjectTest()
422 {
423 setupHost();
424
425 setupClient();
426
427 Engine e;
428 e.setRpm(3333);
429 Engine *e2 = new Engine();
430 QScopedPointer<Engine> engineSave;
431 engineSave.reset(e2);
432 e2->setRpm(4444);
433 host->enableRemoting(&e);
434 host->enableRemoting(e2, QStringLiteral("MyTestEngine"));
435
436 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
437 const QScopedPointer<EngineReplica> namedEngine_r(client->acquire<EngineReplica>(QStringLiteral("MyTestEngine")));
438 engine_r->waitForSource();
439 QCOMPARE(engine_r->cylinders(), e.cylinders());
440 QCOMPARE(engine_r->rpm(), 3333);
441 namedEngine_r->waitForSource();
442 QCOMPARE(namedEngine_r->cylinders(), e2->cylinders());
443 QCOMPARE(namedEngine_r->rpm(), 4444);
444
445 engineSave.reset();
446 //Deleting the object before disable remoting will cause disable remoting to
447 //return false;
448 QVERIFY(!host->disableRemoting(e2));
449 }
450
451 void multipleInstancesTest()
452 {
453 setupHost();
454 Engine e;
455 host->enableRemoting(&e);
456
457 setupClient();
458
459 auto instances = client->instances<EngineReplica>();
460 QCOMPARE(instances, QStringList());
461
462 Engine e2;
463 host->enableRemoting(&e2, QStringLiteral("Engine2"));
464
465 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
466 const QScopedPointer<EngineReplica> engine2_r(client->acquire<EngineReplica>(QStringLiteral("Engine2")));
467 const QScopedPointer<EngineReplica> engine3_r(client->acquire<EngineReplica>(QStringLiteral("Engine_doesnotexist")));
468 QVERIFY(engine_r->waitForSource());
469 QVERIFY(engine2_r->waitForSource());
470 QVERIFY(!engine3_r->waitForSource(500));
471
472 instances = client->instances<EngineReplica>();
473 QCOMPARE(instances, QStringList({"Engine", "Engine2"}));
474
475 QSignalSpy spy(engine_r.data(), SIGNAL(stateChanged(State,State)));
476 host->disableRemoting(&e);
477 spy.wait();
478 QCOMPARE(spy.count(), 1);
479
480 instances = client->instances<EngineReplica>();
481 QCOMPARE(instances, QStringList({"Engine2"}));
482 }
483
484 void registryAddedTest()
485 {
486 QFETCH_GLOBAL(QUrl, registryUrl);
487 if (registryUrl.isEmpty())
488 QSKIP("Skipping registry tests for external QIODevice types.");
489 setupRegistry();
490
491 setupHost(true);
492
493 setupClient(true);
494
495 QScopedPointer<EngineReplica> regBase, regNamed;
496 QScopedPointer<QRemoteObjectDynamicReplica> regDynamic, regDynamicNamed;
497
498 int regAdded = 0;
499 connect(client->registry(), &QRemoteObjectRegistry::remoteObjectAdded, [&](QRemoteObjectSourceLocation entry)
500 {
501 if (entry.first == QLatin1String("Engine")) {
502 ++regAdded;
503 //Add regular replica first, then dynamic one
504 regBase.reset(client->acquire<EngineReplica>());
505 regDynamic.reset(client->acquireDynamic(QStringLiteral("Engine")));
506 }
507 if (entry.first == QLatin1String("MyTestEngine")) {
508 regAdded += 2;
509 //Now add dynamic replica first, then regular one
510 regDynamicNamed.reset(client->acquireDynamic(QStringLiteral("MyTestEngine")));
511 regNamed.reset(client->acquire<EngineReplica>(QStringLiteral("MyTestEngine")));
512 }
513 });
514
515 QSignalSpy addedSpy(client->registry(), SIGNAL(remoteObjectAdded(QRemoteObjectSourceLocation)));
516
517 Engine e;
518 e.setRpm(1111);
519 host->enableRemoting(&e);
520 Engine e2;
521 e2.setRpm(2222);
522 host->enableRemoting(&e2, QStringLiteral("MyTestEngine"));
523 while (regAdded < 3) {
524 addedSpy.wait(100);
525 }
526 regBase->waitForSource(100);
527 regNamed->waitForSource(100);
528 regDynamic->waitForSource(100);
529 regDynamicNamed->waitForSource(100);
530 QVERIFY(regBase->isInitialized());
531 QCOMPARE(regBase->rpm(),e.rpm());
532 QVERIFY(regNamed->isInitialized());
533 QCOMPARE(regNamed->rpm(),e2.rpm());
534
535 QVERIFY(regDynamic->isInitialized());
536 const QMetaObject *metaObject = regDynamic->metaObject();
537
538 const int propertyIndex = metaObject->indexOfProperty("rpm");
539 QVERIFY(propertyIndex >= 0);
540 const QMetaProperty property = metaObject->property(propertyIndex);
541 QVERIFY(property.isValid());
542
543 QCOMPARE(property.read(regDynamic.data()).toInt(),e.rpm());
544
545 QVERIFY(regDynamicNamed->isInitialized());
546 QCOMPARE(property.read(regDynamicNamed.data()).toInt(),e2.rpm());
547
548 QVERIFY(host->disableRemoting(&e));
549 QVERIFY(host->disableRemoting(&e2));
550 }
551
552 void registryTest()
553 {
554 QFETCH_GLOBAL(QUrl, registryUrl);
555 if (registryUrl.isEmpty())
556 QSKIP("Skipping registry tests for external QIODevice types.");
557 setupRegistry();
558 TcpDataCenterSimpleSource source1;
559 source1.setData1(5);
560 source1.setData2(5.0);
561 source1.setData3(QStringLiteral("tcp"));
562 source1.setData4(QVector<int>() << 1 << 2 << 3 << 4 << 5);
563 registry->enableRemoting(&source1);
564
565 setupHost(true);
566 LocalDataCenterSimpleSource source2;
567 source2.setData1(5);
568 source2.setData2(5.0);
569 source2.setData3(QStringLiteral("local"));
570 source2.setData4(QVector<int>() << 1 << 2 << 3 << 4 << 5);
571 host->enableRemoting(&source2);
572 QVERIFY(host->waitForRegistry(1000));
573
574 setupClient(true);
575
576 const QScopedPointer<TcpDataCenterReplica> tcpCentre(client->acquire<TcpDataCenterReplica>());
577 const QScopedPointer<LocalDataCenterReplica> localCentre(client->acquire<LocalDataCenterReplica>());
578 QTRY_VERIFY(localCentre->waitForSource(100));
579 QTRY_VERIFY(tcpCentre->waitForSource(100));
580
581 QCOMPARE(client->registry()->sourceLocations(), host->registry()->sourceLocations());
582 QCOMPARE(client->registry()->sourceLocations(), registry->registry()->sourceLocations());
583 QTRY_VERIFY(localCentre->isInitialized());
584 QTRY_VERIFY(tcpCentre->isInitialized());
585
586 QCOMPARE(tcpCentre->data1(), 5 );
587 QCOMPARE(tcpCentre->data2(), 5.0);
588 QCOMPARE(tcpCentre->data3(), QStringLiteral("tcp"));
589 QCOMPARE(tcpCentre->data4(), QVector<int>() << 1 << 2 << 3 << 4 << 5);
590
591 QCOMPARE(localCentre->data1(), 5);
592 QCOMPARE(localCentre->data2(), 5.0);
593 QCOMPARE(localCentre->data3(), QStringLiteral("local"));
594 QCOMPARE(localCentre->data4(), QVector<int>() << 1 << 2 << 3 << 4 << 5);
595 }
596
597 void invalidUrlsTest()
598 {
599 QFETCH_GLOBAL(QUrl, hostUrl);
600 QFETCH_GLOBAL(QUrl, registryUrl);
601 const QUrl invalidUrl;
602 {
603 QRemoteObjectHost _host(invalidUrl, registryUrl);
604 SET_NODE_NAME(_host);
605 const bool res = _host.waitForRegistry(3000);
606 QVERIFY(!res);
607 }
608
609 {
610 QRemoteObjectHost _host(hostUrl, invalidUrl);
611 SET_NODE_NAME(_host);
612 const bool res = _host.waitForRegistry(3000);
613 QVERIFY(!res);
614 }
615
616 {
617 QRemoteObjectHost _host(invalidUrl, invalidUrl);
618 SET_NODE_NAME(_host);
619 const bool res = _host.waitForRegistry(3000);
620 QVERIFY(!res);
621 }
622 }
623
624 void noRegistryTest()
625 {
626 QFETCH_GLOBAL(QUrl, registryUrl);
627 if (registryUrl.isEmpty())
628 QSKIP("Skipping registry tests for external QIODevice types."); setupHost(true);
629 const bool res = host->waitForRegistry(3000);
630 QVERIFY(!res);
631 QCOMPARE(host->registry()->isInitialized(), false);
632 const QScopedPointer<Engine> localEngine(new Engine);
633 host->enableRemoting(localEngine.data());
634 QCOMPARE(host->registry()->sourceLocations().keys().isEmpty(), true);
635 }
636
637 void delayedRegistryTest()
638 {
639 QFETCH_GLOBAL(QUrl, hostUrl);
640 QFETCH_GLOBAL(QUrl, registryUrl);
641 if (registryUrl.isEmpty())
642 QSKIP("Skipping registry tests for external QIODevice types.");
643 setupClient(true);
644
645 // create a replica before the registry host started
646 // to check whether it gets valid later on
647 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
648 Q_SET_OBJECT_NAME(engine_r.data());
649 QTRY_VERIFY(!engine_r->waitForSource(100));
650
651 setupHost(true);
652 const bool res = host->waitForRegistry(3000);
653 QVERIFY(!res);
654 QCOMPARE(host->registry()->isInitialized(), false);
655
656 const QScopedPointer<Engine> localEngine(new Engine);
657 host->enableRemoting(localEngine.data());
658 QCOMPARE(host->registry()->sourceLocations().keys().isEmpty(), true);
659
660 QSignalSpy spy(host->registry(), SIGNAL(initialized()));
661 QSignalSpy addedSpy(host->registry(), SIGNAL(remoteObjectAdded(QRemoteObjectSourceLocation)));
662 setupRegistry();
663 bool added = addedSpy.wait();
664 QVERIFY(spy.count() > 0);
665 QCOMPARE(added, true);
666 QCOMPARE(host->registry()->sourceLocations().keys().isEmpty(), false);
667 QCOMPARE(host->registry()->sourceLocations().keys().at(0), QStringLiteral("Engine"));
668 QCOMPARE(host->registry()->sourceLocations().value(QStringLiteral("Engine")).hostUrl, hostUrl);
669
670 // the replicate should be valid now
671 QTRY_VERIFY(engine_r->isInitialized());
672 QTRY_VERIFY(engine_r->isReplicaValid());
673
674 //This should produce a warning...
675 registry->enableRemoting(localEngine.data());
676 QVERIFY(host->registry()->sourceLocations().value(QStringLiteral("Engine")).hostUrl != registryUrl);
677 }
678
679 void defaultValueTest()
680 {
681 setupHost();
682 Engine e;
683 host->enableRemoting(&e);
684
685 setupClient();
686
687 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
688 engine_r->waitForSource();
689 QCOMPARE(engine_r->cylinders(), 4);
690 }
691
692 void notifyTest()
693 {
694 setupHost();
695 Engine e;
696 host->enableRemoting(&e);
697
698 setupClient();
699
700 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
701 QSignalSpy spy(engine_r.data(), SIGNAL(rpmChanged(int)));
702 e.setRpm(2345);
703
704 spy.wait();
705 QCOMPARE(spy.count(), 1);
706 const QList<QVariant> &arguments = spy.first();
707 bool ok;
708 int res = arguments.at(0).toInt(&ok);
709 QVERIFY(ok);
710 QCOMPARE(res, e.rpm());
711 QCOMPARE(engine_r->rpm(), e.rpm());
712 }
713
714 void dynamicNotifyTest()
715 {
716 setupHost();
717 Engine e;
718 host->enableRemoting(&e);
719
720 setupClient();
721
722 QSignalSpy spy(this, SIGNAL(forwardResult(int)));
723 QScopedPointer<QRemoteObjectDynamicReplica> engine_dr(client->acquireDynamic(QStringLiteral("Engine")));
724 connect(engine_dr.data(), &QRemoteObjectDynamicReplica::initialized, [&]()
725 {
726 const QMetaObject *metaObject = engine_dr->metaObject();
727 const int propIndex = metaObject->indexOfProperty("rpm");
728 QVERIFY(propIndex >= 0);
729 const QMetaProperty mp = metaObject->property(propIndex);
730 QVERIFY(connect(engine_dr.data(), QByteArray(QByteArrayLiteral("2")+mp.notifySignal().methodSignature().constData()), this, SIGNAL(forwardResult(int))));
731 });
732 e.setRpm(3456);
733 spy.wait();
734 QCOMPARE(spy.count(), 1);
735 const QList<QVariant> &arguments = spy.first();
736 bool ok;
737 int res = arguments.at(0).toInt(&ok);
738 QVERIFY(ok);
739 QCOMPARE(res, e.rpm());
740 }
741
742 void slotTest()
743 {
744 setupHost();
745 Engine e;
746 host->enableRemoting(&e);
747
748 setupClient();
749 e.setStarted(false);
750
751 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
752 QEventLoop loop;
753 QTimer::singleShot(100, &loop, &QEventLoop::quit);
754 connect(engine_r.data(), &EngineReplica::initialized, &loop, &QEventLoop::quit);
755 if (!engine_r->isInitialized())
756 loop.exec();
757 QCOMPARE(engine_r->started(), false);
758
759 QRemoteObjectPendingReply<bool> reply = engine_r->start();
760 QCOMPARE(reply.error(), QRemoteObjectPendingCall::InvalidMessage);
761 QVERIFY(reply.waitForFinished());
762 QVERIFY(reply.isFinished());
763 QCOMPARE(reply.returnValue(), true);
764 QCOMPARE(reply.error(), QRemoteObjectPendingCall::NoError);
765
766 QCOMPARE(engine_r->started(), true);
767 }
768
769 void slotTestWithWatcher()
770 {
771 setupHost();
772 Engine e;
773 host->enableRemoting(&e);
774
775 setupClient();
776 e.setStarted(false);
777
778 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
779 QEventLoop loop;
780 QTimer::singleShot(100, &loop, &QEventLoop::quit);
781 connect(engine_r.data(), &EngineReplica::initialized, &loop, &QEventLoop::quit);
782 if (!engine_r->isInitialized())
783 loop.exec();
784 QCOMPARE(engine_r->started(), false);
785
786 QRemoteObjectPendingReply<bool> reply = engine_r->start();
787 QCOMPARE(reply.error(), QRemoteObjectPendingCall::InvalidMessage);
788
789 QRemoteObjectPendingCallWatcher watcher(reply);
790 QSignalSpy spy(&watcher, SIGNAL(finished(QRemoteObjectPendingCallWatcher *)));
791 spy.wait();
792 QCOMPARE(spy.count(), 1);
793
794 QVERIFY(reply.isFinished());
795 QCOMPARE(reply.returnValue(), true);
796 QCOMPARE(engine_r->started(), true);
797 }
798
799 void slotTestDynamicReplica()
800 {
801 setupHost();
802 Engine e;
803 host->enableRemoting(&e);
804
805 setupClient();
806 e.setStarted(false);
807
808 const QScopedPointer<QRemoteObjectDynamicReplica> engine_r(client->acquireDynamic(QStringLiteral("Engine")));
809 Q_ASSERT(engine_r);
810 QEventLoop loop;
811 QTimer::singleShot(100, &loop, &QEventLoop::quit);
812 connect(engine_r.data(), &EngineReplica::initialized, &loop, &QEventLoop::quit);
813 if (!engine_r->isInitialized())
814 loop.exec();
815
816 const QMetaObject *metaObject = engine_r->metaObject();
817 const int propIndex = metaObject->indexOfProperty("started");
818 QVERIFY(propIndex >= 0);
819 const QMetaProperty property = metaObject->property(propIndex);
820 bool started = property.read(engine_r.data()).value<bool>();
821 QCOMPARE(started, false);
822
823 const int methodIndex = metaObject->indexOfMethod("start()");
824 QVERIFY(methodIndex >= 0);
825 const QMetaMethod method = metaObject->method(methodIndex);
826 QRemoteObjectPendingCall call;
827 QVERIFY(method.invoke(engine_r.data(), Q_RETURN_ARG(QRemoteObjectPendingCall, call)));
828 QCOMPARE(call.error(), QRemoteObjectPendingCall::InvalidMessage);
829 QVERIFY(call.waitForFinished());
830 QVERIFY(call.isFinished());
831 QCOMPARE(call.returnValue().type(), QVariant::Bool);
832 QCOMPARE(call.returnValue().toBool(), true);
833 started = property.read(engine_r.data()).value<bool>();
834 QCOMPARE(started, true);
835 }
836
837 void slotTestDynamicReplicaWithArguments()
838 {
839 setupHost();
840 Engine e;
841 host->enableRemoting(&e);
842
843 setupClient();
844
845 const QScopedPointer<QRemoteObjectDynamicReplica> engine_r(client->acquireDynamic(QStringLiteral("Engine")));
846 Q_ASSERT(engine_r);
847 bool ok = engine_r->waitForSource();
848 QVERIFY(ok);
849 const QMetaObject *metaObject = engine_r->metaObject();
850
851 int methodIndex = metaObject->indexOfMethod("setMyTestString(QString)");
852 QVERIFY(methodIndex >= 0);
853 QMetaMethod method = metaObject->method(methodIndex);
854 QVERIFY(method.isValid());
855
856 // The slot has no return-value, calling it with a Q_RETURN_ARG should fail.
857 QRemoteObjectPendingCall setCall;
858 QString s = QLatin1String("Hello World 1");
859 QVERIFY(!method.invoke(engine_r.data(), Q_RETURN_ARG(QRemoteObjectPendingCall, setCall), Q_ARG(QString, s)));
860 QVERIFY(!setCall.waitForFinished());
861 QVERIFY(!setCall.isFinished());
862 QCOMPARE(setCall.error(), QRemoteObjectPendingCall::InvalidMessage);
863
864 // Now call the method without return-value, that should succeed.
865 s = QLatin1String("Hello World 2");
866 QVERIFY(method.invoke(engine_r.data(), Q_ARG(QString, s)));
867
868 // Verify that the passed argument was proper set.
869 methodIndex = metaObject->indexOfMethod("myTestString()");
870 QVERIFY(methodIndex >= 0);
871 method = metaObject->method(methodIndex);
872 QRemoteObjectPendingCall getCall;
873 QVERIFY(method.invoke(engine_r.data(), Q_RETURN_ARG(QRemoteObjectPendingCall, getCall)));
874 QVERIFY(getCall.waitForFinished());
875 QVERIFY(getCall.isFinished());
876 QCOMPARE(getCall.error(), QRemoteObjectPendingCall::NoError);
877 QCOMPARE(getCall.returnValue().type(), QVariant::String);
878 QCOMPARE(getCall.returnValue().toString(), s);
879 }
880
881 void expapiTestDynamicReplica()
882 {
883 setupHost();
884 Engine e;
885 host->enableRemoting(&e);
886
887 setupClient();
888
889 const QScopedPointer<QRemoteObjectDynamicReplica> engine_r(client->acquireDynamic(QStringLiteral("Engine")));
890 const QMetaObject *metaObject = engine_r->metaObject();
891 const int propIndex = metaObject->indexOfProperty("purchasedPart");
892 QVERIFY(propIndex < 0);
893 const int methodIndex = metaObject->indexOfMethod("setpurchasedPart(bool)");
894 QVERIFY(methodIndex < 0);
895 }
896
897 void slotTestInProcess()
898 {
899 setupHost();
900 Engine e;
901 host->enableRemoting(&e);
902 e.setStarted(false);
903
904 const QScopedPointer<EngineReplica> engine_r(host->acquire<EngineReplica>());
905 engine_r->waitForSource();
906 QCOMPARE(engine_r->started(), false);
907
908 QRemoteObjectPendingReply<bool> reply = engine_r->start();
909 QVERIFY(reply.waitForFinished());
910 QVERIFY(reply.isFinished());
911 QCOMPARE(reply.returnValue(), true);
912 QCOMPARE(reply.error(), QRemoteObjectPendingCall::NoError);
913
914 QCOMPARE(engine_r->started(), true);
915 }
916
917 void slotTestWithUnnormalizedSignature()
918 {
919 setupHost();
920 Engine e;
921 host->enableRemoting(&e);
922
923 setupClient();
924
925 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
926 engine_r->waitForSource();
927
928 engine_r->unnormalizedSignature(0, 0);
929 }
930
931 void setterTest()
932 {
933 setupHost();
934 Engine e(6);
935 QCOMPARE(e.cylinders(), 6);
936 host->enableRemoting(&e);
937
938 setupClient();
939
940 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
941 QCOMPARE(engine_r->cylinders(), 4); // Default value
942 engine_r->waitForSource();
943 QCOMPARE(engine_r->cylinders(), 6);
944 QSignalSpy spy(engine_r.data(), SIGNAL(rpmChanged(int)));
945 engine_r->setRpm(42);
946 spy.wait();
947 QCOMPARE(spy.count(), 1);
948 QCOMPARE(engine_r->rpm(), 42);
949 }
950
951 void pushTest()
952 {
953 setupHost();
954 Engine e;
955 host->enableRemoting(&e);
956
957 setupClient();
958
959 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
960 engine_r->waitForSource();
961 QCOMPARE(engine_r->started(), false);
962 QSignalSpy spy(engine_r.data(), SIGNAL(startedChanged(bool)));
963 engine_r->pushStarted(true);
964 spy.wait();
965 QCOMPARE(spy.count(), 1);
966 QCOMPARE(engine_r->started(), true);
967 }
968
969 void dynamicSetterTest()
970 {
971 setupHost();
972 Engine e(6);
973 QCOMPARE(e.cylinders(), 6);
974 host->enableRemoting(&e);
975
976 setupClient();
977
978 const QScopedPointer<QRemoteObjectDynamicReplica> engine_dr(client->acquireDynamic(QStringLiteral("Engine")));
979 engine_dr->waitForSource();
980 const QMetaObject *metaObject = engine_dr->metaObject();
981 const QMetaProperty const_mp = metaObject->property(metaObject->indexOfProperty("cylinders"));
982 QCOMPARE(const_mp.read(engine_dr.data()).toInt(), 6);
983 const int propIndex = metaObject->indexOfProperty("rpm");
984 const QMetaProperty mp = metaObject->property(propIndex);
985 QSignalSpy spy(engine_dr.data(), QByteArray(QByteArrayLiteral("2")+mp.notifySignal().methodSignature().constData()));
986 mp.write(engine_dr.data(), 44);
987 spy.wait();
988 QCOMPARE(spy.count(), 1);
989 QCOMPARE(mp.read(engine_dr.data()).toInt(), 44);
990 }
991
992 void slotWithParameterTest()
993 {
994 setupHost();
995 Engine e;
996 host->enableRemoting(&e);
997 e.setRpm(0);
998
999 setupClient();
1000
1001 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
1002 engine_r->waitForSource();
1003 QCOMPARE(engine_r->rpm(), 0);
1004
1005 QSignalSpy spy(engine_r.data(), SIGNAL(rpmChanged(int)));
1006 engine_r->increaseRpm(1000);
1007 spy.wait();
1008 QCOMPARE(spy.count(), 1);
1009 QCOMPARE(engine_r->rpm(), 1000);
1010 }
1011
1012 void slotWithUserReturnTypeTest() {
1013 setupHost();
1014 Engine e;
1015 host->enableRemoting(&e);
1016
1017 setupClient();
1018
1019 e.setTemperature(Temperature(400, QStringLiteral("Kelvin")));
1020
1021 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
1022 engine_r->waitForSource();
1023 QRemoteObjectPendingReply<Temperature> pendingReply = engine_r->temperature();
1024 pendingReply.waitForFinished();
1025 Temperature temperature = pendingReply.returnValue();
1026 QCOMPARE(temperature, Temperature(400, QStringLiteral("Kelvin")));
1027 }
1028
1029 void sequentialReplicaTest()
1030 {
1031 setupHost();
1032 Engine e;
1033 host->enableRemoting(&e);
1034
1035 setupClient();
1036
1037 e.setRpm(3456);
1038
1039 QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
1040 engine_r->waitForSource();
1041 QCOMPARE(engine_r->rpm(), e.rpm());
1042
1043 engine_r.reset(client->acquire<EngineReplica>());
1044 engine_r->waitForSource();
1045 QCOMPARE(engine_r->rpm(), e.rpm());
1046 }
1047
1048 void doubleReplicaTest()
1049 {
1050 setupHost();
1051 Engine e;
1052 host->enableRemoting(&e);
1053 e.setRpm(3412);
1054
1055 setupClient();
1056
1057 const QScopedPointer<EngineReplica> engine_r1(client->acquire< EngineReplica >());
1058 const QScopedPointer<EngineReplica> engine_r2(client->acquire< EngineReplica >());
1059
1060 engine_r1->waitForSource();
1061 engine_r2->waitForSource();
1062
1063 QCOMPARE(engine_r1->rpm(), e.rpm());
1064 QCOMPARE(engine_r2->rpm(), e.rpm());
1065 }
1066
1067 void twoReplicaTest() {
1068 setupHost();
1069 Engine e;
1070 Speedometer s;
1071 host->enableRemoting(&e);
1072 host->enableRemoting(&s);
1073
1074 setupClient();
1075
1076 e.setRpm(1234);
1077 s.setMph(70);
1078
1079 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
1080 engine_r->waitForSource();
1081 const QScopedPointer<SpeedometerReplica> speedometer_r(client->acquire<SpeedometerReplica>());
1082 speedometer_r->waitForSource();
1083
1084 QCOMPARE(engine_r->rpm(), e.rpm());
1085 QCOMPARE(speedometer_r->mph(), s.mph());
1086 }
1087
1088 void rawDynamicReplicaTest()
1089 {
1090 setupHost();
1091 TestDynamic source;
1092 host->enableRemoting(&source, "TestDynamic");
1093
1094 setupClient();
1095
1096 const QScopedPointer<QRemoteObjectDynamicReplica> replica(client->acquireDynamic(QStringLiteral("TestDynamic")));
1097 replica->waitForSource();
1098 QVERIFY(replica->isInitialized());
1099
1100 QSignalSpy spy(replica.data(), SIGNAL(valueChanged()));
1101
1102 const QMetaObject *metaObject = replica->metaObject();
1103 const int propIndex = metaObject->indexOfProperty("value");
1104 QVERIFY(propIndex != -1);
1105 const int signalIndex = metaObject->indexOfSignal("valueChanged()");
1106 QVERIFY(signalIndex != -1);
1107
1108 // replica gets source change
1109 source.setValue(1);
1110 QTRY_COMPARE(spy.count(), 1);
1111 QCOMPARE(replica->property("value"), QVariant(1));
1112
1113 // source gets replica change
1114 replica->setProperty("value", 2);
1115 QTRY_COMPARE(replica->property("value"), QVariant(2));
1116 QCOMPARE(source.value(), 2);
1117
1118 // test parent NOTIFY
1119 QSignalSpy otherSpy(replica.data(), SIGNAL(otherValueChanged()));
1120
1121 const int baseSignalIndex = metaObject->indexOfSignal("otherValueChanged()");
1122 QVERIFY(baseSignalIndex != -1);
1123
1124 // replica gets source change
1125 source.setOtherValue(1);
1126 QTRY_COMPARE(otherSpy.count(), 1);
1127 QCOMPARE(replica->property("otherValue"), QVariant(1));
1128
1129 // source gets replica change
1130 replica->setProperty("otherValue", 2);
1131 QTRY_COMPARE(replica->property("otherValue"), QVariant(2));
1132 QCOMPARE(source.otherValue(), 2);
1133 }
1134
1135 void dynamicReplicaTest()
1136 {
1137 setupHost();
1138 TcpDataCenterSimpleSource t;
1139 LocalDataCenterSimpleSource l;
1140 host->enableRemoting(&t);
1141 host->enableRemoting(&l);
1142
1143 setupClient();
1144
1145 const QScopedPointer<QRemoteObjectDynamicReplica> rep1(client->acquireDynamic(QStringLiteral("TcpDataCenter")));
1146 const QScopedPointer<QRemoteObjectDynamicReplica> rep2(client->acquireDynamic(QStringLiteral("TcpDataCenter")));
1147 const QScopedPointer<QRemoteObjectDynamicReplica> rep3(client->acquireDynamic(QStringLiteral("LocalDataCenter")));
1148 rep1->waitForSource();
1149 rep2->waitForSource();
1150 rep3->waitForSource();
1151 const QMetaObject *metaTcpRep1 = rep1->metaObject();
1152 const QMetaObject *metaLocalRep1 = rep3->metaObject();
1153 const QMetaObject *metaTcpSource = t.metaObject();
1154 const QMetaObject *metaLocalSource = l.metaObject();
1155 QVERIFY(rep1->isInitialized());
1156 QVERIFY(rep2->isInitialized());
1157 QVERIFY(rep3->isInitialized());
1158
1159 for (int i = 0; i < metaTcpRep1->propertyCount(); ++i)
1160 {
1161 const QMetaProperty propLhs = metaTcpRep1->property(i);
1162 if (qstrcmp(propLhs.name(), "isReplicaValid") == 0 || qstrcmp(propLhs.name(), "state") == 0 || qstrcmp(propLhs.name(), "node") == 0) //Ignore properties only on the Replica side
1163 continue;
1164 const QMetaProperty propRhs = metaTcpSource->property(metaTcpSource->indexOfProperty(propLhs.name()));
1165 if (propLhs.notifySignalIndex() == -1)
1166 QCOMPARE(propRhs.hasNotifySignal(), false);
1167 else {
1168 QCOMPARE(propRhs.notifySignalIndex() != -1, true);
1169 QCOMPARE(metaTcpRep1->method(propLhs.notifySignalIndex()).name(), metaTcpSource->method(propRhs.notifySignalIndex()).name());
1170 }
1171 QCOMPARE(propLhs.read(rep1.data()), propRhs.read(&t));
1172 }
1173 for (int i = 0; i < metaLocalRep1->propertyCount(); ++i )
1174 {
1175 const QMetaProperty propLhs = metaLocalRep1->property(i);
1176 if (qstrcmp(propLhs.name(), "isReplicaValid") == 0 || qstrcmp(propLhs.name(), "state") == 0 || qstrcmp(propLhs.name(), "node") == 0) //Ignore properties only on the Replica side
1177 continue;
1178 const QMetaProperty propRhs = metaLocalSource->property(metaTcpSource->indexOfProperty(propLhs.name()));
1179 if (propLhs.notifySignalIndex() == -1)
1180 QCOMPARE(propRhs.hasNotifySignal(), false);
1181 else {
1182 QCOMPARE(propRhs.notifySignalIndex() != -1, true);
1183 QCOMPARE(metaTcpRep1->method(propLhs.notifySignalIndex()).name(), metaTcpSource->method(propRhs.notifySignalIndex()).name());
1184 }
1185 QCOMPARE(propLhs.read(rep3.data()), propRhs.read(&l));
1186 }
1187
1188 }
1189
1190 void apiTest()
1191 {
1192 setupHost();
1193 Engine e;
1194 host->enableRemoting<EngineSourceAPI>(&e);
1195 e.setRpm(1234);
1196
1197 setupClient();
1198
1199 const QScopedPointer<EngineReplica> engine_r(client->acquire<EngineReplica>());
1200 engine_r->waitForSource();
1201
1202 QCOMPARE(engine_r->rpm(), e.rpm());
1203 }
1204
1205 void apiInProcTest()
1206 {
1207 setupHost();
1208 Engine e;
1209 host->enableRemoting<EngineSourceAPI>(&e);
1210 e.setRpm(1234);
1211
1212 const QScopedPointer<EngineReplica> engine_r_inProc(host->acquire<EngineReplica>());
1213 engine_r_inProc->waitForSource();
1214
1215 QCOMPARE(engine_r_inProc->rpm(), e.rpm());
1216 }
1217
1218 void errorSignalTest()
1219 {
1220 QRemoteObjectNode _client;
1221 Q_SET_OBJECT_NAME(_client);
1222 QSignalSpy errorSpy(&_client, SIGNAL(error(QRemoteObjectNode::ErrorCode)));
1223 QVERIFY(!_client.connectToNode(QUrl(QLatin1String("invalid:invalid"))));
1224 QCOMPARE(errorSpy.count(), 1);
1225 auto emittedErrorCode = errorSpy.first().at(0).value<QRemoteObjectNode::ErrorCode>();
1226 QCOMPARE(emittedErrorCode, QRemoteObjectNode::RegistryNotAcquired);
1227 QCOMPARE(_client.lastError(), QRemoteObjectNode::RegistryNotAcquired);
1228 }
1229
1230 void clientBeforeServerTest() {
1231 setupClient();
1232 const QScopedPointer<EngineReplica> engine_d(client->acquire<EngineReplica>());
1233
1234 setupHost();
1235 Engine e;
1236 host->enableRemoting<EngineSourceAPI>(&e);
1237 QSignalSpy spy(engine_d.data(), SIGNAL(rpmChanged(int)));
1238 e.setRpm(50);
1239
1240 spy.wait();
1241 QCOMPARE(spy.count(), 1);
1242
1243 QCOMPARE(engine_d->rpm(), e.rpm());
1244 }
1245
1246 void largeDataTest()
1247 {
1248 TestLargeData t;
1249 setupHost();
1250 host->enableRemoting(&t, QStringLiteral("large"));
1251
1252 setupClient();
1253 const QScopedPointer<QRemoteObjectDynamicReplica> rep(client->acquireDynamic(QStringLiteral("large")));
1254 rep->waitForSource();
1255 QVERIFY(rep->isInitialized());
1256 const QMetaObject *metaObject = rep->metaObject();
1257 const int sigIndex = metaObject->indexOfSignal("send(QByteArray)");
1258 QVERIFY(sigIndex != -1);
1259 const QMetaMethod mm = metaObject->method(sigIndex);
1260 QSignalSpy spy(rep.data(), QByteArray(QByteArrayLiteral("2")+mm.methodSignature().constData()));
1261 const QByteArray data(16384,'y');
1262 emit t.send(data);
1263 spy.wait();
1264 QCOMPARE(spy.count(), 1);
1265 const QList<QVariant> &arguments = spy.first();
1266 QVERIFY(arguments.at(0).toByteArray() == data);
1267 QVERIFY(host->disableRemoting(&t));
1268 }
1269
1270 void PODTest()
1271 {
1272 setupHost();
1273
1274 setupClient();
1275
1276 MyPOD shouldPass(1, 2.0, QStringLiteral("pass"));
1277 MyPOD shouldFail(1, 2.0, QStringLiteral("fail"));
1278 MyClassSimpleSource m;
1279 m.setMyPOD(shouldPass);
1280 host->enableRemoting(&m);
1281 const QScopedPointer<MyClassReplica> myclass_r(client->acquire<MyClassReplica>());
1282 myclass_r->waitForSource();
1283
1284 QVERIFY(myclass_r->myPOD() == m.myPOD());
1285 QVERIFY(myclass_r->myPOD() != shouldFail);
1286 }
1287
1288 void SchemeTest()
1289 {
1290 QFETCH_GLOBAL(QUrl, hostUrl);
1291 QFETCH_GLOBAL(QUrl, registryUrl);
1292 QRemoteObjectHost valid(hostUrl);
1293 QVERIFY(valid.lastError() == QRemoteObjectNode::NoError);
1294 QRemoteObjectHost invalid(QUrl(QLatin1String("invalid:invalid")));
1295 QVERIFY(invalid.lastError() == QRemoteObjectNode::HostUrlInvalid);
1296 QRemoteObjectHost validExternal(QUrl(QLatin1String("invalid:invalid")), registryUrl, QRemoteObjectHost::AllowExternalRegistration);
1297 QVERIFY(validExternal.lastError() == QRemoteObjectNode::NoError);
1298 QRemoteObjectNode invalidRegistry(QUrl(QLatin1String("invalid:invalid")));
1299 QVERIFY(invalidRegistry.lastError() == QRemoteObjectNode::RegistryNotAcquired);
1300 }
1301
1302#if defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) && !defined(SKIP_LOCAL)
1303 void localServerConnectionTest()
1304 {
1305 QFETCH_GLOBAL(QUrl, hostUrl);
1306 if (hostUrl.scheme() != QRemoteObjectStringLiterals::local())
1307 QSKIP("Skipping 'local' specific backend for non-local test.");
1308 const auto progName = TestUtils::findExecutable("localsockettestserver", {
1309 QCoreApplication::applicationDirPath() + "/../localsockettestserver"
1310 });
1311
1312 //create a fake socket as killing doesn't produce a necessarily unusable socket
1313 QFile fake(QDir::temp().absoluteFilePath(QStringLiteral("crashMe")));
1314 fake.remove();
1315 QVERIFY(fake.open(QFile::Truncate | QFile::WriteOnly));
1316 QFileInfo info(QDir::temp().absoluteFilePath(QStringLiteral("crashMe")));
1317 QVERIFY(info.exists());
1318
1319 QRemoteObjectNode localSocketTestClient;
1320 const QUrl connection = QUrl(QStringLiteral("local:crashMe"));
1321 const QString objectname = QStringLiteral("connectme");
1322 localSocketTestClient.connectToNode(connection);
1323 QVERIFY(localSocketTestClient.lastError() == QRemoteObjectNode::NoError);
1324 QScopedPointer<QRemoteObjectDynamicReplica> replica;
1325 replica.reset(localSocketTestClient.acquireDynamic(objectname));
1326
1327 QProcess testServer;
1328 testServer.start(progName);
1329 QVERIFY(testServer.waitForStarted());
1330 QVERIFY(localSocketTestClient.lastError() == QRemoteObjectNode::NoError);
1331 replica->waitForSource(1000);
1332 QVERIFY(replica->isInitialized());
1333 testServer.terminate();
1334 QVERIFY(testServer.waitForFinished());
1335 }
1336 // Tests to take over an existing socket if its still valid
1337 void localServerConnectionTest2()
1338 {
1339 QFETCH_GLOBAL(QUrl, hostUrl);
1340 if (hostUrl.scheme() != QRemoteObjectStringLiterals::local())
1341 QSKIP("Skipping 'local' specific backend for non-local test.");
1342 const auto progName = TestUtils::findExecutable("localsockettestserver", {
1343 QCoreApplication::applicationDirPath() + "/../localsockettestserver"
1344 });
1345
1346 QProcess testServer;
1347 testServer.start(progName);
1348 QVERIFY(testServer.waitForStarted());
1349 QFileInfo info(QDir::temp().absoluteFilePath(QStringLiteral("crashMe")));
1350 QVERIFY(info.exists());
1351 testServer.kill();
1352 testServer.waitForFinished();
1353 QVERIFY(info.exists());
1354
1355 QRemoteObjectNode localSocketTestClient;
1356 const QUrl connection = QUrl(QStringLiteral("local:crashMe"));
1357 const QString objectname = QStringLiteral("connectme");
1358 localSocketTestClient.connectToNode(connection);
1359 QVERIFY(localSocketTestClient.lastError() == QRemoteObjectNode::NoError);
1360 QScopedPointer<QRemoteObjectDynamicReplica> replica;
1361 replica.reset(localSocketTestClient.acquireDynamic(objectname));
1362
1363 testServer.start(progName);
1364 QVERIFY(testServer.waitForStarted());
1365 QVERIFY(localSocketTestClient.lastError() == QRemoteObjectNode::NoError);
1366 replica->waitForSource(1000);
1367 QVERIFY(replica->isInitialized());
1368 testServer.terminate();
1369 QVERIFY(testServer.waitForFinished());
1370 }
1371#endif
1372
1373 void tcpListenFailedTest()
1374 {
1375 QFETCH_GLOBAL(QUrl, registryUrl);
1376
1377 if (registryUrl.scheme() != QRemoteObjectStringLiterals::tcp())
1378 QSKIP("Skipping test for local and external backends.");
1379
1380 // Need the Host or Registry running so that the port is in use.
1381 setupRegistry();
1382 QRemoteObjectHost badHost;
1383 badHost.setHostUrl(registryUrl);
1384 QCOMPARE(badHost.lastError(), QRemoteObjectNode::ListenFailed);
1385
1386 }
1387
1388 void invalidExternalTest()
1389 {
1390 QFETCH_GLOBAL(QUrl, hostUrl);
1391 if (hostUrl.scheme() != QRemoteObjectStringLiterals::tcp())
1392 QSKIP("Skipping test for tcp and external backends.");
1393 QRemoteObjectHost srcNode;
1394 QTest::ignoreMessage(QtWarningMsg, " Overriding a valid QtRO url ( QUrl(\"tcp://127.0.0.1:65511\") ) with AllowExternalRegistration is not allowed.");
1395 srcNode.setHostUrl(hostUrl, QRemoteObjectHost::AllowExternalRegistration);
1396 QCOMPARE(srcNode.lastError(), QRemoteObjectNode::HostUrlInvalid);
1397 Engine e;
1398 bool res = srcNode.enableRemoting(&e);
1399 QVERIFY(res == false);
1400 }
1401
1402};
1403
1404QTEST_MAIN(tst_Integration)
1405
1406#include "tst_integration.moc"
1407

Warning: That file was not part of the compilation database. It may have many parsing errors.