summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorBrett Stottlemyer <bstottle@ford.com>2018-07-15 20:43:18 -0400
committerBrett Stottlemyer <bstottle@ford.com>2018-08-15 18:54:13 +0000
commite170cbe42b8f654894e4035c8ddfd6759a034be8 (patch)
treea0bf0b811aed03836f85df6acfa2414a552f0153 /tests
parent8761c1a282f596a64e0fc624c87added43fb47d8 (diff)
Support externally generated QIODevices
This adds the APIs that will be necessary to create SSL sockets flexibly (and outside of QtRO) and pass them in. The integration tests are extended to show everything works if the tcp/ip connection is created outside QtRO. The Registry is supported by allowing an "external schema" to be set as the HostNode's url, which is then used by the registry as the address for any remoted() source objects. The client Node calls registerExternalSchema() with a std::function callback that can create the client-side QIODevice given the registry provided url. Change-Id: I0f2d0ea270771e096a787134ef87d537769045f6 Reviewed-by: Michael Brasser <michael.brasser@live.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/auto.pro2
-rw-r--r--tests/auto/integration/tst_integration.cpp59
-rw-r--r--tests/auto/integration_external/MyInterface.rep18
-rw-r--r--tests/auto/integration_external/client/client.pro16
-rw-r--r--tests/auto/integration_external/client/main.cpp202
-rw-r--r--tests/auto/integration_external/external/external.pro9
-rw-r--r--tests/auto/integration_external/external/tst_integration_external.cpp110
-rw-r--r--tests/auto/integration_external/integration_external.pro2
-rw-r--r--tests/auto/integration_external/server/main.cpp121
-rw-r--r--tests/auto/integration_external/server/mytestserver.cpp74
-rw-r--r--tests/auto/integration_external/server/mytestserver.h59
-rw-r--r--tests/auto/integration_external/server/server.pro19
12 files changed, 685 insertions, 6 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index c5f7abc..1627198 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -22,4 +22,4 @@ SUBDIRS += \
sub_localsockettestserver
qtHaveModule(qml): SUBDIRS += qml
-qtConfig(process): SUBDIRS += integration_multiprocess
+qtConfig(process): SUBDIRS += integration_multiprocess integration_external
diff --git a/tests/auto/integration/tst_integration.cpp b/tests/auto/integration/tst_integration.cpp
index d89e537..1eb7604 100644
--- a/tests/auto/integration/tst_integration.cpp
+++ b/tests/auto/integration/tst_integration.cpp
@@ -32,11 +32,12 @@
#include <QMetaType>
#include <QProcess>
#include <QFileInfo>
+#include <QTcpServer>
+#include <QTcpSocket>
#include <QRemoteObjectReplica>
#include <QRemoteObjectNode>
#include <QRemoteObjectSettingsStore>
-
#include "engine.h"
#include "speedometer.h"
#include "rep_engine_replica.h"
@@ -136,6 +137,21 @@ class tst_Integration: public QObject
{
Q_OBJECT
+ void setupTcp()
+ {
+ if (!tcpServer) {
+ tcpServer = new QTcpServer;
+ tcpServer->listen(QHostAddress::Any, 65511);
+ socketClient = new QTcpSocket;
+ socketClient->connectToHost(QHostAddress::LocalHost, tcpServer->serverPort());
+ QVERIFY(socketClient->waitForConnected(5000));
+
+ QVERIFY(tcpServer->waitForNewConnection(5000));
+ QVERIFY(tcpServer->hasPendingConnections());
+ socketServer = tcpServer->nextPendingConnection();
+ }
+ }
+
void setupHost(bool useRegistry=false)
{
QFETCH_GLOBAL(QUrl, hostUrl);
@@ -146,6 +162,9 @@ class tst_Integration: public QObject
host->setHostUrl(hostUrl);
if (useRegistry)
host->setRegistryUrl(registryUrl);
+ } else {
+ setupTcp();
+ host->addHostSideConnection(socketServer);
}
}
@@ -153,16 +172,19 @@ class tst_Integration: public QObject
{
QFETCH_GLOBAL(QUrl, hostUrl);
QFETCH_GLOBAL(QUrl, registryUrl);
+ client = new QRemoteObjectNode;
+ Q_SET_OBJECT_NAME(*client);
if (!hostUrl.isEmpty())
{
if (useRegistry)
- client = new QRemoteObjectNode(registryUrl);
+ client->setRegistryUrl(registryUrl);
else {
- client = new QRemoteObjectNode;
client->connectToNode(hostUrl);
}
+ } else {
+ setupTcp();
+ client->addClientSideConnection(socketClient);
}
- Q_SET_OBJECT_NAME(*client);
}
void setupRegistry()
@@ -179,16 +201,20 @@ private:
QRemoteObjectHost *host;
QRemoteObjectNode *client;
QRemoteObjectRegistryHost *registry;
+ QTcpServer *tcpServer;
+ QPointer<QTcpSocket> socketClient, socketServer;
private slots:
void initTestCase_data()
{
QTest::addColumn<QUrl>("hostUrl");
QTest::addColumn<QUrl>("registryUrl");
+
#ifndef SKIP_LOCAL
QTest::newRow("local") << QUrl(QLatin1String("local:replica_local_integration")) << QUrl(QLatin1String("local:registry_local_integration"));
#endif
QTest::newRow("tcp") << QUrl(QLatin1String("tcp://127.0.0.1:65511")) << QUrl(QLatin1String("tcp://127.0.0.1:65512"));
+ QTest::newRow("external") << QUrl() << QUrl();
#ifdef __QNXNTO__
QTest::newRow("qnx") << QUrl(QLatin1String("qnx:replica")) << QUrl(QLatin1String("qnx:registry"));
#endif
@@ -208,6 +234,9 @@ private slots:
registry = nullptr;
host = nullptr;
client = nullptr;
+ tcpServer = nullptr;
+ socketClient = nullptr;
+ socketServer = nullptr;
}
void cleanup()
@@ -215,6 +244,13 @@ private slots:
delete registry;
delete host;
delete client;
+ delete tcpServer;
+ if (socketClient) {
+ socketClient->deleteLater();
+ }
+ if (socketServer) {
+ socketServer->deleteLater();
+ }
// wait for delivery of RemoveObject events to the source
QTest::qWait(200);
}
@@ -424,6 +460,9 @@ private slots:
void registryAddedTest()
{
+ QFETCH_GLOBAL(QUrl, registryUrl);
+ if (registryUrl.isEmpty())
+ QSKIP("Skipping registry tests for external QIODevice types.");
setupRegistry();
setupHost(true);
@@ -489,6 +528,9 @@ private slots:
void registryTest()
{
+ QFETCH_GLOBAL(QUrl, registryUrl);
+ if (registryUrl.isEmpty())
+ QSKIP("Skipping registry tests for external QIODevice types.");
setupRegistry();
TcpDataCenterSimpleSource source1;
source1.setData1(5);
@@ -558,7 +600,9 @@ private slots:
void noRegistryTest()
{
- setupHost(true);
+ QFETCH_GLOBAL(QUrl, registryUrl);
+ if (registryUrl.isEmpty())
+ QSKIP("Skipping registry tests for external QIODevice types."); setupHost(true);
const bool res = host->waitForRegistry(3000);
QVERIFY(!res);
QCOMPARE(host->registry()->isInitialized(), false);
@@ -571,6 +615,8 @@ private slots:
{
QFETCH_GLOBAL(QUrl, hostUrl);
QFETCH_GLOBAL(QUrl, registryUrl);
+ if (registryUrl.isEmpty())
+ QSKIP("Skipping registry tests for external QIODevice types.");
setupClient(true);
// create a replica before the registry host started
@@ -1219,10 +1265,13 @@ private slots:
void SchemeTest()
{
QFETCH_GLOBAL(QUrl, hostUrl);
+ QFETCH_GLOBAL(QUrl, registryUrl);
QRemoteObjectHost valid(hostUrl);
QVERIFY(valid.lastError() == QRemoteObjectNode::NoError);
QRemoteObjectHost invalid(QUrl(QLatin1String("invalid:invalid")));
QVERIFY(invalid.lastError() == QRemoteObjectNode::HostUrlInvalid);
+ QRemoteObjectHost validExternal(QUrl(QLatin1String("invalid:invalid")), registryUrl, QRemoteObjectHost::AllowExternalRegistration);
+ QVERIFY(validExternal.lastError() == QRemoteObjectNode::NoError);
QRemoteObjectNode invalidRegistry(QUrl(QLatin1String("invalid:invalid")));
QVERIFY(invalidRegistry.lastError() == QRemoteObjectNode::RegistryNotAcquired);
}
diff --git a/tests/auto/integration_external/MyInterface.rep b/tests/auto/integration_external/MyInterface.rep
new file mode 100644
index 0000000..dfb8752
--- /dev/null
+++ b/tests/auto/integration_external/MyInterface.rep
@@ -0,0 +1,18 @@
+#include <QtCore>
+
+class MyInterface
+{
+ ENUM Enum1 { First, Second, Third }
+ PROP(Enum1 enum1 = First READWRITE)
+
+ PROP(bool started = false)
+
+ SLOT(bool start())
+ SLOT(bool stop())
+ SLOT(bool quit())
+ SLOT(bool next())
+ SLOT(void testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int))
+
+ SIGNAL(advance())
+ SIGNAL(testEnumParamsInSignals(Enum1 enumSignalParam, bool signalParam2, QString))
+};
diff --git a/tests/auto/integration_external/client/client.pro b/tests/auto/integration_external/client/client.pro
new file mode 100644
index 0000000..4c42f5c
--- /dev/null
+++ b/tests/auto/integration_external/client/client.pro
@@ -0,0 +1,16 @@
+TEMPLATE = app
+QT += remoteobjects core testlib
+QT -= gui
+
+TARGET = client
+DESTDIR = ./
+CONFIG += c++11
+CONFIG -= app_bundle
+
+REPC_REPLICA = ../MyInterface.rep
+
+SOURCES += main.cpp \
+
+HEADERS += \
+
+INCLUDEPATH += $$PWD
diff --git a/tests/auto/integration_external/client/main.cpp b/tests/auto/integration_external/client/main.cpp
new file mode 100644
index 0000000..05f7f59
--- /dev/null
+++ b/tests/auto/integration_external/client/main.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rep_MyInterface_replica.h"
+
+#include <QCoreApplication>
+#include <QtRemoteObjects/qremoteobjectnode.h>
+#include <QtTest/QtTest>
+
+const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212"));
+
+class tst_Client_Process : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase()
+ {
+ m_repNode.setRegistryUrl(registryUrl);
+ QRemoteObjectNode::RemoteObjectSchemaHandler setupTcp = [this](QUrl url) {
+ QTcpSocket *socket = new QTcpSocket(&this->m_repNode);
+ connect(socket, &QTcpSocket::connected,
+ [socket, this]() {
+ this->m_repNode.addClientSideConnection(socket);
+ });
+ connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error),
+ [socket](QAbstractSocket::SocketError error) {
+ qDebug() << "SocketError" << error;
+ delete socket;
+ });
+ socket->connectToHost(url.host(), url.port());
+ };
+ m_repNode.registerExternalSchema(QStringLiteral("exttcp"), setupTcp);
+ QVERIFY(m_repNode.waitForRegistry(3000));
+ m_rep.reset(m_repNode.acquire<MyInterfaceReplica>());
+ }
+
+ void testRun()
+ {
+
+ QVERIFY(m_rep->waitForSource());
+ auto reply = m_rep->start();
+ QVERIFY(reply.waitForFinished());
+
+ // BEGIN: Testing
+ QSignalSpy advanceSpy(m_rep.data(), SIGNAL(advance()));
+
+ QSignalSpy spy(m_rep.data(), SIGNAL(enum1Changed(MyInterfaceReplica::Enum1)));
+ QVERIFY(advanceSpy.wait());
+
+ QCOMPARE(spy.count(), 2);
+ // END: Testing
+
+ reply = m_rep->stop();
+ QVERIFY(reply.waitForFinished());
+ }
+
+ void testEnumDetails()
+ {
+ QHash<QByteArray, int> kvs = {{"First", 0}, {"Second", 1}, {"Third", 2}};
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QVERIFY(rep->waitForSource());
+
+ auto mo = rep->metaObject();
+ int enumIdx = mo->indexOfEnumerator("Enum1");
+ QVERIFY(enumIdx != -1);
+ auto enumerator = mo->enumerator(enumIdx);
+ QCOMPARE(enumerator.name(), "Enum1");
+ QCOMPARE(enumerator.keyCount(), 3);
+ for (int i = 0; i < 3; ++i) {
+ auto key = enumerator.key(i);
+ auto val = enumerator.value(i);
+ auto it = kvs.find(key);
+ QVERIFY(it != kvs.end());
+ QCOMPARE(*it, val);
+ kvs.erase(it);
+ }
+
+ int propIdx = mo->indexOfProperty("enum1");
+ QVERIFY(propIdx != -1);
+ auto property = mo->property(propIdx);
+ property.write(rep.data(), 1);
+ QTRY_COMPARE(property.read(rep.data()).toInt(), 1);
+ }
+
+ void testMethodSignalParamDetails()
+ {
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QVERIFY(rep->waitForSource());
+
+ auto mo = rep->metaObject();
+ int signalIdx = mo->indexOfSignal("testEnumParamsInSignals(MyInterfaceReplica::Enum1,bool,QString)");
+ QVERIFY(signalIdx != -1);
+ auto simm = mo->method(signalIdx);
+ {
+ QCOMPARE(simm.parameterCount(), 3);
+ auto paramNames = simm.parameterNames();
+ QCOMPARE(paramNames.size(), 3);
+ QCOMPARE(paramNames.at(0), QByteArrayLiteral("enumSignalParam"));
+ QCOMPARE(paramNames.at(1), QByteArrayLiteral("signalParam2"));
+ QCOMPARE(paramNames.at(2), QByteArrayLiteral("__repc_variable_1"));
+ QCOMPARE(simm.parameterType(0), QMetaType::type("MyInterfaceReplica::Enum1"));
+ QCOMPARE(simm.parameterType(1), int(QMetaType::Bool));
+ QCOMPARE(simm.parameterType(2), int(QMetaType::QString));
+ }
+
+ int slotIdx = mo->indexOfSlot("testEnumParamsInSlots(Enum1,bool,int)");
+ QVERIFY(slotIdx != -1);
+ auto slmm = mo->method(slotIdx);
+ {
+ QCOMPARE(slmm .parameterCount(), 3);
+ auto paramNames = slmm .parameterNames();
+ QCOMPARE(paramNames.size(), 3);
+ QCOMPARE(paramNames.at(0), QByteArrayLiteral("enumSlotParam"));
+ QCOMPARE(paramNames.at(1), QByteArrayLiteral("slotParam2"));
+ QCOMPARE(paramNames.at(2), QByteArrayLiteral("__repc_variable_1"));
+ }
+
+ int enumVal = 0;
+ mo->invokeMethod(rep.data(), "testEnumParamsInSlots",
+ QGenericArgument("Enum1", &enumVal),
+ Q_ARG(bool, true), Q_ARG(int, 1234));
+
+ int enumIdx = mo->indexOfProperty("enum1");
+ QVERIFY(enumIdx != -1);
+ QTRY_COMPARE(mo->property(enumIdx).read(rep.data()).toInt(), 0);
+
+ int startedIdx = mo->indexOfProperty("started");
+ QVERIFY(startedIdx != -1);
+ QTRY_COMPARE(mo->property(startedIdx).read(rep.data()).toBool(), true);
+ }
+
+ void testMethodSignal()
+ {
+ QScopedPointer<MyInterfaceReplica> rep(new MyInterfaceReplica());
+ rep->setNode(&m_repNode);
+ QVERIFY(rep->waitForSource());
+
+ rep->testEnumParamsInSlots(MyInterfaceReplica::Second, false, 74);
+
+ connect(rep.data(), &MyInterfaceReplica::testEnumParamsInSignals,
+ [](MyInterfaceReplica::Enum1 enumSignalParam) { QCOMPARE(enumSignalParam, MyInterfaceReplica::Second); });
+
+ QTRY_COMPARE(rep->enum1(), MyInterfaceReplica::Second);
+ QTRY_COMPARE(rep->started(), false);
+ }
+
+ void testDisconnect()
+ {
+ auto reply = m_rep->next();
+ QSignalSpy stateSpy(m_rep.data(), &MyInterfaceReplica::stateChanged);
+ QVERIFY(reply.waitForFinished());
+
+ QVERIFY(stateSpy.wait());
+ QVERIFY(m_rep->state() == QRemoteObjectReplica::Suspect);
+
+ stateSpy.clear();
+ QVERIFY(stateSpy.wait());
+ QVERIFY(m_rep->state() == QRemoteObjectReplica::Valid);
+ // Make sure we updated to the correct enum1 value
+ QVERIFY(m_rep->enum1() == MyInterfaceReplica::First);
+ }
+
+ void cleanupTestCase()
+ {
+ auto reply = m_rep->quit();
+ QVERIFY(reply.waitForFinished());
+ }
+
+private:
+ QRemoteObjectNode m_repNode;
+ QScopedPointer<MyInterfaceReplica> m_rep;
+};
+
+QTEST_MAIN(tst_Client_Process)
+
+#include "main.moc"
diff --git a/tests/auto/integration_external/external/external.pro b/tests/auto/integration_external/external/external.pro
new file mode 100644
index 0000000..5fcf5be
--- /dev/null
+++ b/tests/auto/integration_external/external/external.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase c++11
+CONFIG -= app_bundle
+TARGET = tst_integration_external
+DESTDIR = ./
+QT += testlib remoteobjects
+QT -= gui
+
+SOURCES += \
+ tst_integration_external.cpp
diff --git a/tests/auto/integration_external/external/tst_integration_external.cpp b/tests/auto/integration_external/external/tst_integration_external.cpp
new file mode 100644
index 0000000..8994db8
--- /dev/null
+++ b/tests/auto/integration_external/external/tst_integration_external.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QMetaType>
+#include <QProcess>
+#include <QStandardPaths>
+
+namespace {
+
+QString findExecutable(const QString &executableName, const QStringList &paths)
+{
+ const auto path = QStandardPaths::findExecutable(executableName, paths);
+ if (!path.isEmpty()) {
+ return path;
+ }
+
+ qWarning() << "Could not find executable:" << executableName << "in any of" << paths;
+ return QString();
+}
+
+}
+
+class tst_Integration_External: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ QLoggingCategory::setFilterRules("qt.remoteobjects.warning=false");
+ }
+
+ void cleanup()
+ {
+ // wait for delivery of RemoveObject events to the source
+ QTest::qWait(200);
+ }
+
+ void testRun_data()
+ {
+ QTest::addColumn<bool>("templated");
+ QTest::newRow("non-templated enableRemoting") << false;
+ QTest::newRow("templated enableRemoting") << true;
+ }
+
+ void testRun()
+ {
+ QFETCH(bool, templated);
+
+ qDebug() << "Starting server process";
+ QProcess serverProc;
+ serverProc.setProcessChannelMode(QProcess::ForwardedChannels);
+ if (templated) {
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert("TEMPLATED_REMOTING", "true");
+ serverProc.setProcessEnvironment(env);
+ }
+ serverProc.start(findExecutable("server", {
+ QCoreApplication::applicationDirPath() + "/../server/"
+ }));
+ QVERIFY(serverProc.waitForStarted());
+
+ // wait for server start
+ QTest::qWait(200);
+
+ qDebug() << "Starting client process";
+ QProcess clientProc;
+ clientProc.setProcessChannelMode(QProcess::ForwardedChannels);
+ clientProc.start(findExecutable("client", {
+ QCoreApplication::applicationDirPath() + "/../client/"
+ }));
+ QVERIFY(clientProc.waitForStarted());
+
+ QVERIFY(clientProc.waitForFinished());
+ QVERIFY(serverProc.waitForFinished());
+
+ QCOMPARE(serverProc.exitCode(), 0);
+ QCOMPARE(clientProc.exitCode(), 0);
+ }
+};
+
+QTEST_MAIN(tst_Integration_External)
+
+#include "tst_integration_external.moc"
diff --git a/tests/auto/integration_external/integration_external.pro b/tests/auto/integration_external/integration_external.pro
new file mode 100644
index 0000000..6dead73
--- /dev/null
+++ b/tests/auto/integration_external/integration_external.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = client server external
diff --git a/tests/auto/integration_external/server/main.cpp b/tests/auto/integration_external/server/main.cpp
new file mode 100644
index 0000000..e97408b
--- /dev/null
+++ b/tests/auto/integration_external/server/main.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mytestserver.h"
+
+#include <QCoreApplication>
+#include <QTcpServer>
+#include <QtTest/QtTest>
+
+const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212"));
+const QUrl extUrl = QUrl(QStringLiteral("exttcp://127.0.0.1:65213"));
+const QUrl extUrl2 = QUrl(QStringLiteral("exttcp://127.0.0.1:65214"));
+
+class tst_Server_Process : public QObject
+{
+ Q_OBJECT
+
+ struct Device
+ {
+ Device(QUrl url) : srcNode(url, registryUrl, QRemoteObjectHost::AllowExternalRegistration)
+ {
+ tcpServer.listen(QHostAddress(url.host()), url.port());
+ QVERIFY(srcNode.waitForRegistry(3000));
+ QObject::connect(&tcpServer, &QTcpServer::newConnection, [this]() {
+ auto conn = this->tcpServer.nextPendingConnection();
+ this->srcNode.addHostSideConnection(conn);
+ });
+ }
+ QTcpServer tcpServer;
+ QRemoteObjectHost srcNode;
+ };
+
+private Q_SLOTS:
+ void testRun()
+ {
+ QRemoteObjectRegistryHost registry(registryUrl);
+
+ Device dev1(extUrl);
+ MyTestServer myTestServer;
+ bool templated = qEnvironmentVariableIsSet("TEMPLATED_REMOTING");
+ if (templated)
+ QVERIFY(dev1.srcNode.enableRemoting<MyInterfaceSourceAPI>(&myTestServer));
+ else
+ QVERIFY(dev1.srcNode.enableRemoting(&myTestServer));
+
+ qDebug() << "Waiting for incoming connections";
+
+ QSignalSpy waitForStartedSpy(&myTestServer, SIGNAL(startedChanged(bool)));
+ QVERIFY(waitForStartedSpy.isValid());
+ QVERIFY(waitForStartedSpy.wait());
+ QCOMPARE(waitForStartedSpy.value(0).value(0).toBool(), true);
+
+ // wait for delivery of events
+ QTest::qWait(200);
+
+ qDebug() << "Client connected";
+
+ // BEGIN: Testing
+
+ // make sure continuous changes to enums don't mess up the protocol
+ myTestServer.setEnum1(MyTestServer::Second);
+ myTestServer.setEnum1(MyTestServer::Third);
+
+ emit myTestServer.advance();
+
+ waitForStartedSpy.clear();
+ QVERIFY(waitForStartedSpy.wait());
+ QCOMPARE(waitForStartedSpy.value(0).value(0).toBool(), false);
+
+ bool next = false;
+ connect(&myTestServer, &MyTestServer::nextStep, [&next]{ next = true; });
+ QTRY_VERIFY_WITH_TIMEOUT(next, 5000);
+ dev1.srcNode.disableRemoting(&myTestServer);
+
+ // Change a value while replica is suspect
+ myTestServer.setEnum1(MyTestServer::First);
+
+ // Share the object on a different "device", make sure registry updates and connects
+ Device dev2(extUrl2);
+ dev2.srcNode.enableRemoting(&myTestServer);
+
+ // wait for quit
+ bool quit = false;
+ connect(&myTestServer, &MyTestServer::quitApp, [&quit]{quit = true;});
+ QTRY_VERIFY_WITH_TIMEOUT(quit, 5000);
+
+ // wait for delivery of events
+ QTest::qWait(200);
+
+ qDebug() << "Done. Shutting down.";
+ }
+};
+
+QTEST_MAIN(tst_Server_Process)
+
+#include "main.moc"
diff --git a/tests/auto/integration_external/server/mytestserver.cpp b/tests/auto/integration_external/server/mytestserver.cpp
new file mode 100644
index 0000000..44421f4
--- /dev/null
+++ b/tests/auto/integration_external/server/mytestserver.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdebug.h>
+
+#include "mytestserver.h"
+#include "rep_MyInterface_source.h"
+
+MyTestServer::MyTestServer(QObject *parent)
+ : MyInterfaceSimpleSource(parent)
+{
+ qDebug() << "Server started";
+}
+
+MyTestServer::~MyTestServer()
+{
+ qDebug() << "Server stopped";
+}
+
+bool MyTestServer::start()
+{
+ setStarted(true);
+ return true;
+}
+
+bool MyTestServer::stop()
+{
+ setStarted(false);
+ return true;
+}
+
+bool MyTestServer::quit()
+{
+ emit quitApp();
+ return true;
+}
+
+bool MyTestServer::next()
+{
+ emit nextStep();
+ return true;
+}
+
+void MyTestServer::testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int number)
+{
+ setEnum1(enumSlotParam);
+ setStarted(slotParam2);
+ emit testEnumParamsInSignals(enum1(), started(), QString::number(number));
+}
diff --git a/tests/auto/integration_external/server/mytestserver.h b/tests/auto/integration_external/server/mytestserver.h
new file mode 100644
index 0000000..c0edda0
--- /dev/null
+++ b/tests/auto/integration_external/server/mytestserver.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MYTESTSERVER_H
+#define MYTESTSERVER_H
+
+#include <QTimer>
+
+#include <QtRemoteObjects/qremoteobjectnode.h>
+#include <QtRemoteObjects/qremoteobjectsource.h>
+
+#include "rep_MyInterface_source.h"
+
+class MyTestServer : public MyInterfaceSimpleSource
+{
+ Q_OBJECT
+
+public:
+ MyTestServer(QObject *parent = nullptr);
+ ~MyTestServer() override;
+
+public Q_SLOTS:
+ bool start() override;
+ bool stop() override;
+ bool quit() override;
+ bool next() override;
+ void testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int __repc_variable_1) override;
+
+Q_SIGNALS:
+ void quitApp();
+ void nextStep();
+};
+
+#endif // MYTESTSERVER_H
diff --git a/tests/auto/integration_external/server/server.pro b/tests/auto/integration_external/server/server.pro
new file mode 100644
index 0000000..fea0c03
--- /dev/null
+++ b/tests/auto/integration_external/server/server.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+QT += remoteobjects core testlib
+QT -= gui
+
+TARGET = server
+DESTDIR = ./
+CONFIG += c++11
+CONFIG -= app_bundle
+
+REPC_SOURCE = $$PWD/../MyInterface.rep
+
+SOURCES += main.cpp \
+ mytestserver.cpp
+
+HEADERS += \
+ mytestserver.h
+ $$OUT_PWD/rep_MyInterface_source.h
+
+INCLUDEPATH += $$PWD