/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2020, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. * This project including source code and documentation is protected by copyright law, and * remains the property of nymea GmbH. All rights, including reproduction, publication, * editing and translation, are reserved. The use of this project is subject to the terms of a * license agreement to be concluded with nymea GmbH in accordance with the terms * of use of nymea GmbH, available under https://nymea.io/license * * GNU General Public License Usage * Alternatively, this project may be redistributed and/or modified under * the terms of the GNU General Public License as published by the Free Software Foundation, * GNU version 3. this project is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this project. * If not, see . * * For any further details and any questions please contact us under contact@nymea.io * or see our FAQ/Licensing Information on https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "remoteproxytestsproxy.h" #include "engine.h" #include "loggingcategories.h" #include "remoteproxyconnection.h" #include "../../version.h" #include #include #include #include #include RemoteProxyTestsProxy::RemoteProxyTestsProxy(QObject *parent) : BaseTest(parent) { } void RemoteProxyTestsProxy::startStopServer() { resetDebugCategories(); addDebugCategory("ProxyServer.debug=true"); addDebugCategory("Engine.debug=true"); addDebugCategory("JsonRpc.debug=true"); addDebugCategory("TcpSocketServer.debug=true"); addDebugCategory("WebSocketServer.debug=true"); startServer(); stopServer(); resetDebugCategories(); } void RemoteProxyTestsProxy::dummyAuthenticator() { resetDebugCategories(); addDebugCategory("ProxyServer.debug=true"); cleanUpEngine(); m_configuration = new ProxyConfiguration(this); loadConfiguration(":/test-configuration.conf"); m_dummyAuthenticator = new DummyAuthenticator(this); m_authenticator = qobject_cast(m_dummyAuthenticator); // Start proxy webserver Engine::instance()->setAuthenticator(m_dummyAuthenticator); QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged); Engine::instance()->start(m_configuration); runningSpy.wait(); QVERIFY(runningSpy.count() == 1); // Make sure the server is running QVERIFY(Engine::instance()->running()); QVERIFY(Engine::instance()->webSocketServerProxy()->running()); QVERIFY(Engine::instance()->unixSocketServerProxy()->running()); QVERIFY(Engine::instance()->proxyServer()->running()); // Create request QVariantMap params; params.insert("uuid", QUuid::createUuid().toString()); params.insert("name", "test"); params.insert("token", "foobar"); QVariant response = invokeWebSocketProxyApiCall("Authentication.Authenticate", params); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); verifyAuthenticationError(response); cleanUpEngine(); } void RemoteProxyTestsProxy::monitorServer() { // Start the server startServer(); QVERIFY(Engine::instance()->monitorServer()->running()); // Create a tunnel // Configure mock authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nameConnectionOne = "Test client one"; QUuid uuidConnectionOne = QUuid::createUuid(); QString nameConnectionTwo = "Test client two"; QUuid uuidConnectionTwo = QUuid::createUuid(); QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(uuidConnectionTwo, nameConnectionTwo, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); if (connectionOneReadySpy.count() < 1) connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); if (connectionTwoReadySpy.count() < 1) connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken)); if (connectionOneAuthenticatedSpy.count() < 1) connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken)); if (connectionTwoAuthenticatedSpy.count() < 1) connectionTwoAuthenticatedSpy.wait(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); if (remoteConnectionEstablishedTwo.count() < 1) remoteConnectionEstablishedTwo.wait(); QVERIFY(remoteConnectionEstablishedOne.count() == 1); QVERIFY(remoteConnectionEstablishedTwo.count() == 1); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); QCOMPARE(connectionOne->tunnelPartnerName(), nameConnectionTwo); QCOMPARE(QUuid(connectionOne->tunnelPartnerUuid()), uuidConnectionTwo); QCOMPARE(connectionTwo->tunnelPartnerName(), nameConnectionOne); QCOMPARE(QUuid(connectionTwo->tunnelPartnerUuid()), uuidConnectionOne); // Get monitor data QLocalSocket *monitor = new QLocalSocket(this); QSignalSpy connectedSpy(monitor, &QLocalSocket::connected); monitor->connectToServer(m_configuration->monitorSocketFileName()); if (connectedSpy.count() < 1) connectedSpy.wait(); QVERIFY(connectedSpy.count() == 1); QSignalSpy dataSpy(monitor, &QLocalSocket::readyRead); if (dataSpy.count() < 1) dataSpy.wait(); QVERIFY(dataSpy.count() == 1); QByteArray data = monitor->readAll(); qDebug() << data; // TODO: verify monitor data QSignalSpy disconnectedSpy(monitor, &QLocalSocket::connected); monitor->disconnectFromServer(); if (disconnectedSpy.count() < 1) disconnectedSpy.wait(); // Clean up monitor->deleteLater(); connectionOne->deleteLater(); connectionTwo->deleteLater(); stopServer(); } void RemoteProxyTestsProxy::configuration_data() { QTest::addColumn("fileName"); QTest::addColumn("success"); QTest::newRow("valid configuration") << ":/test-configuration.conf" << true; QTest::newRow("valid configuration chain") << ":/test-configuration-chain.conf" << true; QTest::newRow("faulty filename") << ":/not-exisitng-test-configuration.conf" << false; QTest::newRow("faulty certificate") << ":/test-configuration-faulty-certificate.conf" << false; QTest::newRow("faulty key") << ":/test-configuration-faulty-key.conf" << false; QTest::newRow("faulty chain") << ":/test-configuration-faulty-chain.conf" << false; } void RemoteProxyTestsProxy::configuration() { QFETCH(QString, fileName); QFETCH(bool, success); ProxyConfiguration configuration; QCOMPARE(configuration.loadConfiguration(fileName), success); } void RemoteProxyTestsProxy::serverPortBlocked() { cleanUpEngine(); m_configuration = new ProxyConfiguration(this); loadConfiguration(":/test-configuration.conf"); m_mockAuthenticator = new MockAuthenticator(this); m_authenticator = qobject_cast(m_mockAuthenticator); // Create a dummy server which blocks the port QWebSocketServer dummyServer("dummy-server", QWebSocketServer::NonSecureMode); QVERIFY(dummyServer.listen(QHostAddress::LocalHost, m_configuration->webSocketServerProxyPort())); // Start proxy webserver QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged); Engine::instance()->setAuthenticator(m_authenticator); Engine::instance()->start(m_configuration); runningSpy.wait(); QVERIFY(runningSpy.count() == 1); // Make sure the server is not running QVERIFY(Engine::instance()->running()); // Make sure the websocket server is not running QVERIFY(!Engine::instance()->webSocketServerProxy()->running()); QSignalSpy closedSpy(&dummyServer, &QWebSocketServer::closed); dummyServer.close(); closedSpy.wait(); QVERIFY(closedSpy.count() == 1); // Try again startServer(); // Clean up stopServer(); // Do the same with the tcp server cleanUpEngine(); m_configuration = new ProxyConfiguration(this); loadConfiguration(":/test-configuration.conf"); m_mockAuthenticator = new MockAuthenticator(this); m_authenticator = qobject_cast(m_mockAuthenticator); // Create a dummy server which blocks the port QTcpServer *tcpDummyServer = new QTcpServer(this); QVERIFY(tcpDummyServer->listen(QHostAddress::LocalHost, m_configuration->tcpServerPort())); // Start proxy webserver QSignalSpy runningSpy2(Engine::instance(), &Engine::runningChanged); Engine::instance()->setAuthenticator(m_authenticator); Engine::instance()->start(m_configuration); runningSpy2.wait(); QVERIFY(runningSpy2.count() == 1); // Make sure the engine is running QVERIFY(Engine::instance()->running()); // Make sure the TCP server is not running QVERIFY(!Engine::instance()->tcpSocketServerProxy()->running()); tcpDummyServer->close(); delete tcpDummyServer; // Try again startServer(); // Make sure the TCP server is not running QVERIFY(Engine::instance()->webSocketServerProxy()->running()); QVERIFY(Engine::instance()->tcpSocketServerProxy()->running()); // Clean up stopServer(); } void RemoteProxyTestsProxy::websocketBinaryData() { // Start the server startServer(); QWebSocket *client = new QWebSocket("bad-client", QWebSocketProtocol::Version13); connect(client, &QWebSocket::sslErrors, this, &BaseTest::sslErrors); QSignalSpy spyConnection(client, SIGNAL(connected())); client->open(Engine::instance()->webSocketServerProxy()->serverUrl()); spyConnection.wait(); // Send binary data and make sure the server disconnects this socket QSignalSpy spyDisconnected(client, SIGNAL(disconnected())); client->sendBinaryMessage("trying to upload stuff...stuff...more stuff... other stuff"); spyConnection.wait(1000); QVERIFY(spyConnection.count() == 1); // Clean up stopServer(); } void RemoteProxyTestsProxy::websocketPing() { // Start the server startServer(); QWebSocket *client = new QWebSocket("bad-client", QWebSocketProtocol::Version13); connect(client, &QWebSocket::sslErrors, this, &BaseTest::sslErrors); QSignalSpy spyConnection(client, SIGNAL(connected())); client->open(Engine::instance()->webSocketServerProxy()->serverUrl()); spyConnection.wait(); QVERIFY(spyConnection.count() == 1); QByteArray pingMessage = QByteArray("ping!"); QSignalSpy pongSpy(client, &QWebSocket::pong); client->ping(pingMessage); pongSpy.wait(); QVERIFY(pongSpy.count() == 1); qDebug() << pongSpy.at(0).at(0) << pongSpy.at(0).at(1); QVERIFY(pongSpy.at(0).at(1).toByteArray() == pingMessage); // Clean up stopServer(); } void RemoteProxyTestsProxy::apiBasicCallsTcp_data() { QTest::addColumn("data"); QTest::addColumn("responseId"); QTest::addColumn("responseStatus"); QTest::newRow("valid call") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\"}") << 42 << "success"; QTest::newRow("missing id") << QByteArray("{\"method\":\"RemoteProxy.Hello\"}") << -1 << "error"; QTest::newRow("missing method") << QByteArray("{\"id\":42}") << 42 << "error"; //QTest::newRow("invalid json") << QByteArray("{\"id\":42, \"method\":\"RemoteProx") << -1 << "error"; QTest::newRow("invalid function") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Explode\"}") << 42 << "error"; QTest::newRow("invalid namespace") << QByteArray("{\"id\":42, \"method\":\"ProxyRemote.Hello\"}") << 42 << "error"; QTest::newRow("missing dot") << QByteArray("{\"id\":42, \"method\":\"RemoteProxyHello\"}") << 42 << "error"; QTest::newRow("invalid params") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\", \"params\":{\"törööö\":\"chooo-chooo\"}}") << 42 << "error"; QTest::newRow("invalid authentication params") << QByteArray("{\"id\":42, \"method\":\"Authentication.Authenticate\", \"params\":{\"your\":\"mamma\"}}") << 42 << "error"; } void RemoteProxyTestsProxy::apiBasicCallsTcp() { QFETCH(QByteArray, data); QFETCH(int, responseId); QFETCH(QString, responseStatus); // Start the server startServer(); QVariant response = injectTcpSocketProxyData(data); QVERIFY(!response.isNull()); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QCOMPARE(response.toMap().value("id").toInt(), responseId); QCOMPARE(response.toMap().value("status").toString(), responseStatus); // Clean up stopServer(); } void RemoteProxyTestsProxy::getIntrospect() { // Start the server startServer(); QVariantMap response; // WebSocket response = invokeWebSocketProxyApiCall("RemoteProxy.Introspect").toMap(); //qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QVERIFY(!response.isEmpty()); QVERIFY(response.value("status").toString() == "success"); QVERIFY(response.value("params").toMap().contains("methods")); QVERIFY(response.value("params").toMap().contains("notifications")); QVERIFY(response.value("params").toMap().contains("types")); // Tcp response.clear(); response = invokeTcpSocketProxyApiCall("RemoteProxy.Introspect").toMap(); //qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QVERIFY(!response.isEmpty()); QVERIFY(response.value("status").toString() == "success"); QVERIFY(response.value("params").toMap().contains("methods")); QVERIFY(response.value("params").toMap().contains("notifications")); QVERIFY(response.value("params").toMap().contains("types")); // Clean up stopServer(); } void RemoteProxyTestsProxy::getHello() { // Start the server startServer(); QVariantMap response; // WebSocket response = invokeWebSocketProxyApiCall("RemoteProxy.Hello").toMap(); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); // Verify data QVERIFY(!response.isEmpty()); QCOMPARE(response.value("params").toMap().value("name").toString(), Engine::instance()->configuration()->serverName()); QCOMPARE(response.value("params").toMap().value("server").toString(), QString(SERVER_NAME_STRING)); QCOMPARE(response.value("params").toMap().value("version").toString(), QString(SERVER_VERSION_STRING)); QCOMPARE(response.value("params").toMap().value("apiVersion").toString(), QString(API_VERSION_STRING)); // TCP response.clear(); response = invokeTcpSocketProxyApiCall("RemoteProxy.Hello").toMap(); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); // Verify data QVERIFY(!response.isEmpty()); QCOMPARE(response.value("params").toMap().value("name").toString(), Engine::instance()->configuration()->serverName()); QCOMPARE(response.value("params").toMap().value("server").toString(), QString(SERVER_NAME_STRING)); QCOMPARE(response.value("params").toMap().value("version").toString(), QString(SERVER_VERSION_STRING)); QCOMPARE(response.value("params").toMap().value("apiVersion").toString(), QString(API_VERSION_STRING)); // Clean up stopServer(); } void RemoteProxyTestsProxy::apiBasicCalls_data() { QTest::addColumn("data"); QTest::addColumn("responseId"); QTest::addColumn("responseStatus"); QTest::newRow("valid call") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\"}") << 42 << "success"; QTest::newRow("missing id") << QByteArray("{\"method\":\"RemoteProxy.Hello\"}") << -1 << "error"; QTest::newRow("missing method") << QByteArray("{\"id\":42}") << 42 << "error"; QTest::newRow("invalid json") << QByteArray("{\"id\":42, \"method\":\"RemoteProx}") << -1 << "error"; QTest::newRow("invalid function") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Explode\"}") << 42 << "error"; QTest::newRow("invalid namespace") << QByteArray("{\"id\":42, \"method\":\"ProxyRemote.Hello\"}") << 42 << "error"; QTest::newRow("missing dot") << QByteArray("{\"id\":42, \"method\":\"RemoteProxyHello\"}") << 42 << "error"; QTest::newRow("invalid params") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\", \"params\":{\"törööö\":\"chooo-chooo\"}}") << 42 << "error"; QTest::newRow("invalid authentication params") << QByteArray("{\"id\":42, \"method\":\"Authentication.Authenticate\", \"params\":{\"your\":\"mamma\"}}") << 42 << "error"; } void RemoteProxyTestsProxy::apiBasicCalls() { QFETCH(QByteArray, data); QFETCH(int, responseId); QFETCH(QString, responseStatus); // Start the server startServer(); QVariantMap response; // Websocket response = injectWebSocketProxyData(data).toMap(); //qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QVERIFY(!response.isEmpty()); QCOMPARE(response.value("id").toInt(), responseId); QCOMPARE(response.value("status").toString(), responseStatus); // TCP response.clear(); response = injectTcpSocketProxyData(data).toMap(); //qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QVERIFY(!response.isEmpty()); QCOMPARE(response.value("id").toInt(), responseId); QCOMPARE(response.value("status").toString(), responseStatus); // Clean up stopServer(); } void RemoteProxyTestsProxy::authenticate_data() { QTest::addColumn("uuid"); QTest::addColumn("name"); QTest::addColumn("token"); QTest::addColumn("nonce"); QTest::addColumn("timeout"); QTest::addColumn("expectedError"); QTest::newRow("success") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "" << 500 << Authenticator::AuthenticationErrorNoError; QTest::newRow("success") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "nonce" << 500 << Authenticator::AuthenticationErrorNoError; QTest::newRow("success") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "nonce" << 300 << Authenticator::AuthenticationErrorAuthenticationFailed; QTest::newRow("failed") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "" << 300 << Authenticator::AuthenticationErrorAuthenticationFailed; QTest::newRow("not responding") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "" << 500 << Authenticator::AuthenticationErrorProxyError; QTest::newRow("aborted") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "" << 300 << Authenticator::AuthenticationErrorAborted; QTest::newRow("unknown") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken << "" << 300 << Authenticator::AuthenticationErrorUnknown; } void RemoteProxyTestsProxy::authenticate() { QFETCH(QString, uuid); QFETCH(QString, name); QFETCH(QString, token); QFETCH(QString, nonce); QFETCH(int, timeout); QFETCH(Authenticator::AuthenticationError, expectedError); // Start the server startServer(); m_configuration->setAuthenticationTimeout(8000); m_configuration->setJsonRpcTimeout(10000); m_configuration->setInactiveTimeout(10000); // Configure result m_mockAuthenticator->setExpectedAuthenticationError(expectedError); m_mockAuthenticator->setTimeoutDuration(timeout); // Create request QVariantMap params; params.insert("uuid", uuid); params.insert("name", name); params.insert("token", token); if (!nonce.isEmpty()) params.insert("nonce", nonce); // WebSocket QVariantMap response; response = invokeWebSocketProxyApiCall("Authentication.Authenticate", params).toMap(); //qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); verifyAuthenticationError(response, expectedError); // TCP response = invokeTcpSocketProxyApiCall("Authentication.Authenticate", params).toMap(); verifyAuthenticationError(response, expectedError); // Clean up stopServer(); } void RemoteProxyTestsProxy::authenticateNonce() { // Start the server startServer(); QString nonce = "67af856c4e4071833ed01128e50b3ea5"; QString token = "C001L0ckingT0ken"; // Configure moch authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nameConnectionOne = "Test client one"; QUuid uuidConnectionOne = QUuid::createUuid(); QString nameConnectionTwo = "Test client two"; QUuid uuidConnectionTwo = QUuid::createUuid(); QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(uuidConnectionTwo, nameConnectionTwo, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken, nonce)); connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken, nonce)); connectionTwoAuthenticatedSpy.wait(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); if (remoteConnectionEstablishedTwo.count() < 1) remoteConnectionEstablishedTwo.wait(); QVERIFY(remoteConnectionEstablishedOne.count() == 1); QVERIFY(remoteConnectionEstablishedTwo.count() == 1); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); QCOMPARE(connectionOne->tunnelPartnerName(), nameConnectionTwo); QCOMPARE(QUuid(connectionOne->tunnelPartnerUuid()), uuidConnectionTwo); QCOMPARE(connectionTwo->tunnelPartnerName(), nameConnectionOne); QCOMPARE(QUuid(connectionTwo->tunnelPartnerUuid()), uuidConnectionOne); // Pipe data trought the tunnel QSignalSpy remoteConnectionDataOne(connectionOne, &RemoteProxyConnection::dataReady); QSignalSpy remoteConnectionDataTwo(connectionTwo, &RemoteProxyConnection::dataReady); connectionOne->sendData(dataOne); remoteConnectionDataTwo.wait(); QVERIFY(remoteConnectionDataTwo.count() == 1); QCOMPARE(remoteConnectionDataTwo.at(0).at(0).toByteArray().trimmed(), dataOne); connectionTwo->sendData(dataTwo); remoteConnectionDataOne.wait(); QVERIFY(remoteConnectionDataOne.count() == 1); QCOMPARE(remoteConnectionDataOne.at(0).at(0).toByteArray().trimmed(), dataTwo); connectionOne->deleteLater(); connectionTwo->deleteLater(); // Clean up stopServer(); } void RemoteProxyTestsProxy::authenticateSendData() { // Start the server startServer(); m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QVariantMap params; params.insert("uuid", "uuid"); params.insert("name", "name"); params.insert("token", "token"); params.insert("nonce", "nonce"); QVariantMap request; request.insert("id", m_commandCounter); request.insert("method", "Authentication.Authenticate"); request.insert("params", params); QJsonDocument jsonDoc = QJsonDocument::fromVariant(request); // Connect socket QWebSocket *socket = new QWebSocket("proxy-testclient", QWebSocketProtocol::Version13); connect(socket, &QWebSocket::sslErrors, this, &BaseTest::sslErrors); QSignalSpy spyConnection(socket, &QWebSocket::connected); socket->open(Engine::instance()->webSocketServerProxy()->serverUrl()); spyConnection.wait(); QVERIFY(spyConnection.count() == 1); // Authenticate QSignalSpy dataSpy(socket, &QWebSocket::textMessageReceived); socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact))); dataSpy.wait(); QVERIFY(dataSpy.count() == 1); // Send data again and make sure we get disconnected since sending data while waiting for the partner is forbidden QSignalSpy disconnectedSpy(socket, SIGNAL(disconnected())); socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact))); disconnectedSpy.wait(); QVERIFY(disconnectedSpy.count() == 1); socket->deleteLater(); // Clean up stopServer(); } void RemoteProxyTestsProxy::clientConnectionWebSocket() { // Start the server startServer(); // Configure moch authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); // Connect to the server using WebSocket (insecure disabled) RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this); connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect to server (insecue enabled for testing) QSignalSpy readySpy(connection, &RemoteProxyConnection::ready); QVERIFY(connection->connectServer(m_serverUrlProxyWebSocket)); readySpy.wait(); QVERIFY(readySpy.count() == 1); QVERIFY(connection->isConnected()); QVERIFY(!connection->isRemoteConnected()); QVERIFY(connection->state() == RemoteProxyConnection::StateReady); QVERIFY(connection->error() == QAbstractSocket::UnknownSocketError); QVERIFY(connection->serverUrl() == m_serverUrlProxyWebSocket); QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket); QVERIFY(connection->serverName() == SERVER_NAME_STRING); QVERIFY(connection->proxyServerName() == Engine::instance()->serverName()); QVERIFY(connection->proxyServerVersion() == SERVER_VERSION_STRING); QVERIFY(connection->proxyServerApiVersion() == API_VERSION_STRING); QSignalSpy authenticatedSpy(connection, &RemoteProxyConnection::authenticated); QVERIFY(connection->authenticate("foobar")); authenticatedSpy.wait(); QVERIFY(authenticatedSpy.count() == 1); QVERIFY(connection->isConnected()); QVERIFY(connection->isAuthenticated()); QVERIFY(connection->state() == RemoteProxyConnection::StateAuthenticated); // Disconnect and clean up QSignalSpy spyDisconnected(connection, &RemoteProxyConnection::disconnected); connection->disconnectServer(); if (spyDisconnected.count() < 1) spyDisconnected.wait(); QVERIFY(spyDisconnected.count() >= 1); QVERIFY(!connection->isConnected()); connection->deleteLater(); stopServer(); } void RemoteProxyTestsProxy::clientConnectionTcpSocket() { // Start the server startServer(); // Configure mock authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); // Connect to the server using TCP (insecure disabled) RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeTcpSocket, this); connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect to server (insecue enabled for testing) QSignalSpy readySpy(connection, &RemoteProxyConnection::ready); QVERIFY(connection->connectServer(m_serverUrlProxyTcp)); readySpy.wait(); QVERIFY(readySpy.count() == 1); QVERIFY(connection->isConnected()); QVERIFY(!connection->isRemoteConnected()); QVERIFY(connection->state() == RemoteProxyConnection::StateReady); QVERIFY(connection->error() == QAbstractSocket::UnknownSocketError); QVERIFY(connection->serverUrl() == m_serverUrlProxyTcp); QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeTcpSocket); QVERIFY(connection->serverName() == SERVER_NAME_STRING); QVERIFY(connection->proxyServerName() == Engine::instance()->serverName()); QVERIFY(connection->proxyServerVersion() == SERVER_VERSION_STRING); QVERIFY(connection->proxyServerApiVersion() == API_VERSION_STRING); QSignalSpy authenticatedSpy(connection, &RemoteProxyConnection::authenticated); QVERIFY(connection->authenticate("foobar")); authenticatedSpy.wait(); QVERIFY(authenticatedSpy.count() == 1); QVERIFY(connection->isConnected()); QVERIFY(connection->isAuthenticated()); QVERIFY(connection->state() == RemoteProxyConnection::StateAuthenticated); // Disconnect and clean up QSignalSpy spyDisconnected(connection, &RemoteProxyConnection::disconnected); connection->disconnectServer(); if (spyDisconnected.count() < 1) spyDisconnected.wait(); QVERIFY(spyDisconnected.count() >= 1); QVERIFY(!connection->isConnected()); connection->deleteLater(); stopServer(); } void RemoteProxyTestsProxy::remoteConnection() { // Start the server startServer(); // Configure mock authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nameConnectionOne = "Test client one"; QUuid uuidConnectionOne = QUuid::createUuid(); QString nameConnectionTwo = "Test client two"; QUuid uuidConnectionTwo = QUuid::createUuid(); QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(uuidConnectionTwo, nameConnectionTwo, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken)); connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken)); connectionTwoAuthenticatedSpy.wait(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); if (remoteConnectionEstablishedTwo.count() < 1) remoteConnectionEstablishedTwo.wait(); QVERIFY(remoteConnectionEstablishedOne.count() == 1); QVERIFY(remoteConnectionEstablishedTwo.count() == 1); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); QCOMPARE(connectionOne->tunnelPartnerName(), nameConnectionTwo); QCOMPARE(QUuid(connectionOne->tunnelPartnerUuid()), uuidConnectionTwo); QCOMPARE(connectionTwo->tunnelPartnerName(), nameConnectionOne); QCOMPARE(QUuid(connectionTwo->tunnelPartnerUuid()), uuidConnectionOne); // Pipe data trought the tunnel QSignalSpy remoteConnectionDataOne(connectionOne, &RemoteProxyConnection::dataReady); QSignalSpy remoteConnectionDataTwo(connectionTwo, &RemoteProxyConnection::dataReady); connectionOne->sendData(dataOne); remoteConnectionDataTwo.wait(); QVERIFY(remoteConnectionDataTwo.count() == 1); QCOMPARE(remoteConnectionDataTwo.at(0).at(0).toByteArray().trimmed(), dataOne); connectionTwo->sendData(dataTwo); remoteConnectionDataOne.wait(); QVERIFY(remoteConnectionDataOne.count() == 1); QCOMPARE(remoteConnectionDataOne.at(0).at(0).toByteArray().trimmed(), dataTwo); connectionOne->deleteLater(); connectionTwo->deleteLater(); // Clean up stopServer(); } void RemoteProxyTestsProxy::multipleRemoteConnection() { // Start the server startServer(); // Configure moch authenticator m_mockAuthenticator->setExpectedAuthenticationError(); m_mockAuthenticator->setTimeoutDuration(1000); m_configuration->setAuthenticationTimeout(2000); m_configuration->setJsonRpcTimeout(5000); m_configuration->setInactiveTimeout(5000); // Create multiple tunnels with one token, but different nonces for each connection QObject *parent = new QObject(this); for (int i = 0; i < 5; i++) { qDebug() << "============== Create remote connection" << i; bool connectionResult = createRemoteConnection(m_testToken, QUuid::createUuid().toString(), parent); if (!connectionResult) { qWarning() << "Test failed because could not create remote connection"; delete parent; } QVERIFY(connectionResult); } delete parent; // Clean up stopServer(); } void RemoteProxyTestsProxy::trippleConnection() { // Start the server startServer(); // Configure moch authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nonce = QUuid::createUuid().toString(); // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(QUuid::createUuid(), "Test client two", this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionThree = new RemoteProxyConnection(QUuid::createUuid(), "Token thief ^v^", this); connect(connectionThree, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); if (connectionOneReadySpy.count() < 1) connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); if (connectionTwoReadySpy.count() < 1) connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken, nonce)); if (connectionOneAuthenticatedSpy.count() < 1) connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken, nonce)); if (connectionTwoAuthenticatedSpy.count() < 1) connectionTwoAuthenticatedSpy.wait(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); // Now connect a third connection and make sure the client will be closed // Connect three QSignalSpy connectionThreeReadySpy(connectionThree, &RemoteProxyConnection::ready); QSignalSpy connectionThreeDisconnectedSpy(connectionThree, &RemoteProxyConnection::disconnected); QVERIFY(connectionThree->connectServer(m_serverUrlProxyTcp)); if (connectionThreeReadySpy.count() < 1) connectionThreeReadySpy.wait(); QVERIFY(connectionThreeReadySpy.count() == 1); QVERIFY(connectionThree->isConnected()); // Authenticate three QSignalSpy connectionThreeAuthenticatedSpy(connectionThree, &RemoteProxyConnection::authenticated); QVERIFY(connectionThree->authenticate(m_testToken, nonce)); if (connectionThreeAuthenticatedSpy.count() < 1) connectionThreeAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); if (connectionThreeDisconnectedSpy.count() < 1) connectionThreeDisconnectedSpy.wait(); QVERIFY(connectionThreeDisconnectedSpy.count() >= 1); // Make sure the one and two are still connected QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); // Clean up stopServer(); } void RemoteProxyTestsProxy::duplicateUuid() { // Start the server startServer(); // Configure moch authenticator m_mockAuthenticator->setTimeoutDuration(10); m_mockAuthenticator->setExpectedAuthenticationError(); QUuid connectionUuid = QUuid::createUuid(); QString nameConnectionOne = "Test client one"; QString nameConnectionTwo = "Test client two"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(connectionUuid, nameConnectionOne, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(connectionUuid, nameConnectionTwo, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); if (connectionOneReadySpy.count() < 1) connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); if (connectionTwoReadySpy.count() < 1) connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken)); if (connectionOneAuthenticatedSpy.count() < 1) connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy disconnectSpyOne(connectionOne, &RemoteProxyConnection::disconnected); QSignalSpy disconnectSpyTwo(connectionTwo, &RemoteProxyConnection::disconnected); QVERIFY(connectionTwo->authenticate(m_testToken)); if (disconnectSpyOne.count() < 1 ) disconnectSpyOne.wait(); QVERIFY(disconnectSpyOne.count() >= 1); if (disconnectSpyTwo.count() < 1 ) disconnectSpyTwo.wait(); QVERIFY(disconnectSpyTwo.count() >= 1); connectionOne->deleteLater(); connectionTwo->deleteLater(); // Clean up stopServer(); } void RemoteProxyTestsProxy::sslConfigurations() { // Start the server startServer(); // Connect to the server (insecure disabled) RemoteProxyConnection *connector = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this); QSignalSpy spyError(connector, &RemoteProxyConnection::errorOccurred); QVERIFY(connector->connectServer(m_serverUrlProxyTcp)); spyError.wait(); QVERIFY(spyError.count() == 1); qDebug() << connector->error(); QCOMPARE(connector->error(), QAbstractSocket::SslHandshakeFailedError); QVERIFY(connector->state() == RemoteProxyConnection::StateDisconnected); // Connect to server (insecue enabled) QSignalSpy spyConnected(connector, &RemoteProxyConnection::connected); connect(connector, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); connector->connectServer(m_serverUrlProxyTcp); spyConnected.wait(); QVERIFY(connector->isConnected()); // Disconnect and clean up connector->disconnectServer(); QVERIFY(!connector->isConnected()); connector->deleteLater(); stopServer(); } void RemoteProxyTestsProxy::jsonRpcTimeout() { // Start the server startServer(); // Configure result (authentication takes longer than json rpc timeout m_mockAuthenticator->setExpectedAuthenticationError(); m_mockAuthenticator->setTimeoutDuration(10000); m_configuration->setAuthenticationTimeout(10000); m_configuration->setJsonRpcTimeout(1000); m_configuration->setInactiveTimeout(10000); // Create request QVariantMap params; params.insert("uuid", "uuid"); params.insert("name", "name"); params.insert("token", "token"); QVariant response = invokeWebSocketProxyApiCall("Authentication.Authenticate", params); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); QVERIFY(response.toMap().value("status").toString() == "error"); // Clean up stopServer(); } void RemoteProxyTestsProxy::inactiveTimeout() { // Start the server startServer(); m_configuration->setInactiveTimeout(1000); RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Sleepy test client", this); connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionReadySpy(connection, &RemoteProxyConnection::ready); QSignalSpy connectionDisconnectedSpy(connection, &RemoteProxyConnection::disconnected); QVERIFY(connection->connectServer(m_serverUrlProxyTcp)); if (connectionReadySpy.count() < 1) connectionReadySpy.wait(); QVERIFY(connectionReadySpy.count() == 1); // Now wait for disconnected if (connectionDisconnectedSpy.count() < 1) connectionDisconnectedSpy.wait(); QVERIFY(connectionDisconnectedSpy.count() >= 1); // Clean up stopServer(); } void RemoteProxyTestsProxy::authenticationReplyTimeout() { // Start the server startServer(); // Configure result (authentication takes longer than json rpc timeout m_mockAuthenticator->setExpectedAuthenticationError(); m_mockAuthenticator->setTimeoutDuration(2000); m_configuration->setAuthenticationTimeout(500); m_configuration->setJsonRpcTimeout(1000); m_configuration->setInactiveTimeout(1000); // Create request QVariantMap params; params.insert("uuid", QUuid::createUuid().toString()); params.insert("name", "Sleepy test client"); params.insert("token", "sleepy token zzzZZZ"); QVariant response = invokeWebSocketProxyApiCall("Authentication.Authenticate", params); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); verifyAuthenticationError(response, Authenticator::AuthenticationErrorTimeout); // Clean up stopServer(); } void RemoteProxyTestsProxy::authenticationReplyConnection() { // Start the server startServer(); // Configure result (authentication takes longer than json rpc timeout m_mockAuthenticator->setExpectedAuthenticationError(); m_mockAuthenticator->setTimeoutDuration(1000); m_configuration->setAuthenticationTimeout(500); m_configuration->setJsonRpcTimeout(1000); m_configuration->setInactiveTimeout(1000); RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Sleepy test client", this); connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionReadySpy(connection, &RemoteProxyConnection::ready); QVERIFY(connection->connectServer(m_serverUrlProxyTcp)); connectionReadySpy.wait(); QVERIFY(connectionReadySpy.count() == 1); QSignalSpy connectionErrorSpy(connection, &RemoteProxyConnection::errorOccurred); connection->authenticate("blub"); connectionErrorSpy.wait(); QVERIFY(connectionErrorSpy.count() == 1); QVERIFY(connectionErrorSpy.at(0).at(0).toInt() == static_cast(QAbstractSocket::ProxyConnectionRefusedError)); QVERIFY(connection->error() == QAbstractSocket::ProxyConnectionRefusedError); // Clean up stopServer(); } void RemoteProxyTestsProxy::tcpRemoteConnection() { // Start the server startServer(); // Configure mock authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nameConnectionOne = "Test client one"; QUuid uuidConnectionOne = QUuid::createUuid(); QString nameConnectionTwo = "Test client two"; QUuid uuidConnectionTwo = QUuid::createUuid(); QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, RemoteProxyConnection::ConnectionTypeTcpSocket, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(uuidConnectionTwo, nameConnectionTwo, RemoteProxyConnection::ConnectionTypeTcpSocket, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyTcp)); connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken)); connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken)); connectionTwoAuthenticatedSpy.wait(); qDebug() << connectionTwoAuthenticatedSpy.count(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); if (remoteConnectionEstablishedTwo.count() < 1) remoteConnectionEstablishedTwo.wait(); QVERIFY(remoteConnectionEstablishedOne.count() == 1); QVERIFY(remoteConnectionEstablishedTwo.count() == 1); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); QCOMPARE(connectionOne->tunnelPartnerName(), nameConnectionTwo); QCOMPARE(QUuid(connectionOne->tunnelPartnerUuid()), uuidConnectionTwo); QCOMPARE(connectionTwo->tunnelPartnerName(), nameConnectionOne); QCOMPARE(QUuid(connectionTwo->tunnelPartnerUuid()), uuidConnectionOne); // Pipe data trought the tunnel QSignalSpy remoteConnectionDataOne(connectionOne, &RemoteProxyConnection::dataReady); QSignalSpy remoteConnectionDataTwo(connectionTwo, &RemoteProxyConnection::dataReady); connectionOne->sendData(dataOne); remoteConnectionDataTwo.wait(); QVERIFY(remoteConnectionDataTwo.count() == 1); QCOMPARE(remoteConnectionDataTwo.at(0).at(0).toByteArray().trimmed(), dataOne); connectionTwo->sendData(dataTwo); remoteConnectionDataOne.wait(); QVERIFY(remoteConnectionDataOne.count() == 1); QCOMPARE(remoteConnectionDataOne.at(0).at(0).toByteArray().trimmed(), dataTwo); connectionOne->deleteLater(); connectionTwo->deleteLater(); // Clean up stopServer(); } void RemoteProxyTestsProxy::tcpWebsocketRemoteConnection() { // Start the server startServer(); // Configure mock authenticator m_mockAuthenticator->setTimeoutDuration(100); m_mockAuthenticator->setExpectedAuthenticationError(); QString nameConnectionOne = "Test client one"; QUuid uuidConnectionOne = QUuid::createUuid(); QString nameConnectionTwo = "Test client two"; QUuid uuidConnectionTwo = QUuid::createUuid(); QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, RemoteProxyConnection::ConnectionTypeWebSocket, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(uuidConnectionTwo, nameConnectionTwo, RemoteProxyConnection::ConnectionTypeTcpSocket, this); connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); // Connect one QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); QVERIFY(connectionOne->connectServer(m_serverUrlProxyWebSocket)); connectionOneReadySpy.wait(); QVERIFY(connectionOneReadySpy.count() == 1); QVERIFY(connectionOne->isConnected()); // Connect two QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); QVERIFY(connectionTwo->connectServer(m_serverUrlProxyTcp)); connectionTwoReadySpy.wait(); QVERIFY(connectionTwoReadySpy.count() == 1); QVERIFY(connectionTwo->isConnected()); // Authenticate one QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated); QVERIFY(connectionOne->authenticate(m_testToken)); connectionOneAuthenticatedSpy.wait(); QVERIFY(connectionOneAuthenticatedSpy.count() == 1); QVERIFY(connectionOne->isConnected()); QVERIFY(connectionOne->isAuthenticated()); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated); // Authenticate two QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished); QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated); QVERIFY(connectionTwo->authenticate(m_testToken)); connectionTwoAuthenticatedSpy.wait(); qDebug() << connectionTwoAuthenticatedSpy.count(); QVERIFY(connectionTwoAuthenticatedSpy.count() == 1); QVERIFY(connectionTwo->isConnected()); QVERIFY(connectionTwo->isAuthenticated()); // Wait for both to be connected if (remoteConnectionEstablishedOne.count() < 1) remoteConnectionEstablishedOne.wait(); if (remoteConnectionEstablishedTwo.count() < 1) remoteConnectionEstablishedTwo.wait(); QVERIFY(remoteConnectionEstablishedOne.count() == 1); QVERIFY(remoteConnectionEstablishedTwo.count() == 1); QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected); QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected); QCOMPARE(connectionOne->tunnelPartnerName(), nameConnectionTwo); QCOMPARE(QUuid(connectionOne->tunnelPartnerUuid()), uuidConnectionTwo); QCOMPARE(connectionTwo->tunnelPartnerName(), nameConnectionOne); QCOMPARE(QUuid(connectionTwo->tunnelPartnerUuid()), uuidConnectionOne); // Pipe data trought the tunnel QSignalSpy remoteConnectionDataOne(connectionOne, &RemoteProxyConnection::dataReady); QSignalSpy remoteConnectionDataTwo(connectionTwo, &RemoteProxyConnection::dataReady); connectionOne->sendData(dataOne); remoteConnectionDataTwo.wait(); QVERIFY(remoteConnectionDataTwo.count() == 1); QCOMPARE(remoteConnectionDataTwo.at(0).at(0).toByteArray().trimmed(), dataOne); connectionTwo->sendData(dataTwo); remoteConnectionDataOne.wait(); QVERIFY(remoteConnectionDataOne.count() == 1); QCOMPARE(remoteConnectionDataOne.at(0).at(0).toByteArray().trimmed(), dataTwo); connectionOne->deleteLater(); connectionTwo->deleteLater(); // Clean up stopServer(); } QTEST_MAIN(RemoteProxyTestsProxy)