JD2022-TU1/main/extern/UbiServices/custom/testsUnit/testWebSocket.cpp

768 lines
38 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#if defined(US_SDK_FULL)
#include "tests/common/cancelTest.h"
#include "tests/common/helpers.h"
#include "tests/common/restStatusCode.h"
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/fixture/paramFixture.h"
#include "tests/mock/mockLogDevice.h"
#include "testsUnit/mock/mockWebsocketClient.h"
#include "testsUnit/mock/mockWebsocketStreamImpl.h"
#include <ubiservices/core/chrono/chronometer.h>
#include <ubiservices/core/http/httpObfuscatorHelper.h>
#include <ubiservices/core/types/containerspriv.h>
#include <ubiservices/core/websocket/websocketHelper.h>
#include <ubiservices/services/websocket/websocketClient.h>
#include <ubiservices/services/websocket/buffers/textBuffer.h>
#include <ubiservices/facade.h>
namespace US_NS {;
US_DEFINE_TEST(TestWebSocket);
};
#if !defined(US_DLL)
namespace US_NS {;
typedef LeakChecker WEBSOCKET;
typedef AuthenticationFixture<1, false> WEBSOCKET_NOLOGIN;
typedef LeakChecker WEBSOCKET_NOLOGIN2;
typedef LoginMockFixture<false> WEBSOCKET_MOCK;
// Cancel test settings
typedef AuthenticationFixtureWithParam<TestConfigCancel,1U, false>::type WEBSOCKET_CANCEL;
US_DEFINE_LONG_TEST_P(WEBSOCKET_CANCEL, TestConfigCancel(200), TestConfigCancel(10));
namespace TestWebSocket_BF
{
//const static char* s_ECHO_URI = "sandbox.kaazing.net/echo"; // in case echo.websocket.org fails again
const static char* s_ECHO_URI = "echo.websocket.org";
const static char* s_MOCK_URL_WITH_PINNING = "ws://mock.ubiservices.ubi.com";
WebSocketConnectionPtr connectWebsocket(WebSocketClient& client, const String& uriStr, bool secure, const ProxySettings& proxy)
{
URLInfo uri(uriStr);
uri.setScheme(secure ? "wss" : "ws");
const AsyncResult<WebSocketConnectionPtr> result = client.openConnection(uri.getStringValue(), HttpHeader(), WebSocketConfiguration(), proxy);
EXPECT_TRUE(AsyncHelper::waitSuccess(result));
if (result.hasSucceeded())
{
EXPECT_TRUE(result.getResult()->isConnected());
EXPECT_EQ(secure, result.getResult()->isSecure());
#if !defined(US_TARGET_XONE) && !defined(US_TARGET_UWP) && !defined(US_TARGET_MANJARO)
EXPECT_EQ(RestStatusCode::SwitchingProtocols, result.getResult()->getHandshakeResponse().getStatusCode());
#endif
}
return result.getResult();
}
void disconnectWebsocket(WebSocketClient& client, WebSocketConnectionPtr connection)
{
EXPECT_TRUE(AsyncHelper::waitSuccess(client.closeConnection(connection)));
EXPECT_FALSE(connection->isConnected());
}
bool getMessage(WebSocketClient& client, WebSocketConnectionPtr connection, WebSocketBufferPtr& buffer)
{
HighResolutionChrono chrono;
while (chrono.getElapsed() < ClockSteady::getNanoFromMilli(NS_COMMON::DEFAULT_WAIT_TIME) && connection->isConnected())
{
if (connection->isDataAvailable())
{
buffer = client.readStream(connection);
return buffer.isValid();
}
Helper::sleep(10);
}
return false;
}
void runConnectDisconnectTest(WebSocketClient& client, const String& uri, bool secure, const ProxySettings& proxy)
{
WebSocketConnectionPtr connection = connectWebsocket(client, uri, secure, proxy);
disconnectWebsocket(client, connection);
}
void runConnectDisconnectMultipleTimesTest(WebSocketClient& client, const String& uri, bool secure)
{
for (int8 i = 0; i < 5; ++i)
{
WebSocketConnectionPtr connection = connectWebsocket(client, uri, secure, ProxySettings());
disconnectWebsocket(client, connection);
}
}
void runSendReceiveMultipleMessagesInSequenceTest(WebSocketClient& client, const String& uri, bool secure)
{
const String message1 = "This is the first test message.";
const String message2 = "This is the second test message.";
WebSocketConnectionPtr connection = connectWebsocket(client, uri, secure, ProxySettings());
// Send #1
{
WebSocketBufferPtr buffer; // ???
WebSocketBufferPtr buffer1 = US_NEW(TextBuffer, message1);
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer1)));
}
// Reception #1
{
WebSocketBufferPtr buffer;
EXPECT_TRUE(getMessage(client, connection, buffer));
EXPECT_EQ(message1, WebSocketHelper::getBufferContent(buffer));
}
// Send #2
{
WebSocketBufferPtr buffer; // ???
WebSocketBufferPtr buffer2 = US_NEW(TextBuffer, message2);
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer2)));
}
// Reception #2
{
WebSocketBufferPtr buffer;
EXPECT_TRUE(getMessage(client, connection, buffer));
EXPECT_EQ(message2, WebSocketHelper::getBufferContent(buffer));
}
disconnectWebsocket(client, connection);
}
void runSendReceiveMultipleMessagesInParallelTest(WebSocketClient& client, const String& uri, bool secure)
{
const String message1 = "This is the first test message.";
const String message2 = "This is the second test message.";
WebSocketConnectionPtr connection = connectWebsocket(client, uri, secure, ProxySettings());
WebSocketBufferPtr buffer1 = US_NEW(TextBuffer, message1);
WebSocketBufferPtr buffer2 = US_NEW(TextBuffer, message2);
// Parallel Sending
{
const AsyncResult<Empty> result1 = client.writeStream(connection, buffer1);
const AsyncResult<Empty> result2 = client.writeStream(connection, buffer2);
}
// Parallel Reception
{
WebSocketBufferPtr buffer;
//Expect 2 reflected messages, but we are not expecting them necessarily in order
{
EXPECT_TRUE(getMessage(client, connection, buffer));
const String messageReceived1 = WebSocketHelper::getBufferContent(buffer);
EXPECT_TRUE(messageReceived1 == message1 || messageReceived1 == message2);
}
{
EXPECT_TRUE(getMessage(client, connection, buffer));
const String messageReceived2 = WebSocketHelper::getBufferContent(buffer);
EXPECT_TRUE(messageReceived2 == message1 || messageReceived2 == message2);
}
}
disconnectWebsocket(client, connection);
}
}
namespace TestWebSocketAutobahn_BF
{
const static uint32 s_AUTOBAHN_PORT = 9001;
const static char* s_AUTOBAHN_URI = "localhost:%u/%s";
Set<uint16> constructTestCase(uint16 startIndex, uint16 endIndex, Set<uint16> excludeIndex)
{
Set<uint16> indexes;
uint16 i = startIndex;
do
{
indexes.insert(i);
}
while(++i < endIndex);
Set<uint16> result;
std::set_difference(indexes.begin(), indexes.end(), excludeIndex.begin(), excludeIndex.end(), std::inserter(result, result.end()));
return result;
}
void updateAutobahnReport(WebSocketClient& client, bool secure)
{
URLInfo uri(String::formatText(s_AUTOBAHN_URI, s_AUTOBAHN_PORT, "updateReports?agent=UbiServices-WebSocket-client/1.0"));
uri.setScheme(secure ? "wss" : "ws");
AsyncResult<WebSocketConnectionPtr> connectionResult = client.openConnection(uri.getStringValue(), HttpHeader(), WebSocketConfiguration(), ProxySettings());
EXPECT_TRUE(connectionResult.wait());
WebSocketConnectionPtr websocketConnection = connectionResult.getResult();
// No need to disconnect. Autobahn does it automatically
if (websocketConnection != NULL)
{
while (websocketConnection->isConnected())
{
Helper::sleep(50);
}
}
}
void runAutobahnTestCase(Set<uint16> testIds, WebSocketClient& client, bool secure)
{
for (const auto& it : testIds)
{
const String urlParameter = String::formatText("runCase?case=%u&agent=UbiServices-WebSocket-client/1.0", it);
URLInfo uri(String::formatText(s_AUTOBAHN_URI, s_AUTOBAHN_PORT, urlParameter.getUtf8()));
uri.setScheme(secure ? "wss" : "ws");
AsyncResult<WebSocketConnectionPtr> connectionResult = client.openConnection(uri.getStringValue(), HttpHeader(), WebSocketConfiguration(), ProxySettings());
EXPECT_TRUE(connectionResult.wait());
US_EXPECT_SUCCESS(connectionResult);
if (connectionResult.hasFailed())
{
return;
}
WebSocketConnectionPtr websocketConnection = connectionResult.getResult();
while (websocketConnection->isConnected())
{
WebSocketBufferPtr messageBuffer;
if (TestWebSocket_BF::getMessage(client, websocketConnection, messageBuffer))
{
AsyncResult<Empty> write = client.writeStream(websocketConnection, messageBuffer); //echoing every message received
EXPECT_TRUE(write.wait());
EXPECT_TRUE(write.hasSucceeded());
}
Helper::sleep(10);
}
updateAutobahnReport(client, secure);
}
}
void runAutobahnTestSuite(Facade& facade, bool secure)
{
WebSocketClient& client = facade.getWebsocketClient();
// See https://mdc-web-tomcat17.ubisoft.org/confluence/display/ubiservices/Results+with+Autobahn+testsuite
// for details on disabled tests.
// Please update this page if the status of some tests is changed.
Set<uint16> excludeList;
#if defined(US_TARGET_XONE)
excludeList.insert(excludeList.end(), 1u); // 1.1.1 : payload with length 0 (Microsoft issue, will not fix)
excludeList.insert(excludeList.end(), 9u); // 1.2.1 : payload with length 0 (Microsoft issue, will not fix)
excludeList.insert(excludeList.end(), 26u); // 2.10 : several pings two pongs (Microsoft issue)
excludeList.insert(excludeList.end(), 65u); // 6.1.1 : payload with length 0 (Microsoft issue, will not fix)
excludeList.insert(excludeList.end(), 66u); // 6.1.2 : payload with length 0 (Microsoft issue, will not fix)
excludeList.insert(excludeList.end(), 94u); // 6.7.1 : payload \x00 is transformed in an empty string automatically -> echo a payload with length 0
//excludeList.insert(excludeList.end(), 169u); // 6.22.1 : This test is pass when launched alone, but fail when launched along with the whole testsuite.
//excludeList.insert(excludeList.end(), 231u); // 7.7.9 : test is pass but sending errorCode 1011 when closing websocket produces an exception (Microsoft issue)
runAutobahnTestCase(constructTestCase(1, 9, excludeList), client, secure); // Framing Text 1.1.1 - 1.1.8 (8)
runAutobahnTestCase(constructTestCase(9, 17, excludeList), client, secure); // Framing Binary 1.2.1 - 1.2.8 (8)
runAutobahnTestCase(constructTestCase(17, 28, excludeList), client, secure); // 2. Pings/Pongs 2.1 - 2.11 (11)
runAutobahnTestCase(constructTestCase(28, 35, excludeList), client, secure); // 3. Reserved bits 3.1 - 3.7 (7)
runAutobahnTestCase(constructTestCase(35, 40, excludeList), client, secure); // 4.1 Opcodes Non-Control 4.1.1 - 4.1.5 (5)
runAutobahnTestCase(constructTestCase(40, 45, excludeList), client, secure); // 4.2 Opcodes Control 4.2.1 - 4.2.5 (5)
runAutobahnTestCase(constructTestCase(45, 65, excludeList), client, secure); // Fragmentation 5.1 - 5.20 (20)
runAutobahnTestCase(constructTestCase(65, 210, excludeList), client, secure); // UTF8 handling (145)
runAutobahnTestCase(constructTestCase(210, 251, excludeList), client, secure); // Close handling (41)
#else
//excludeList.insert(excludeList.end(), 169u); // 6.22.1 : This test is pass when launched alone, but fail when launched along with the whole testsuite and verbose is enabled.
runAutobahnTestCase(constructTestCase(1, 9, excludeList), client, secure); // Framing Text 1.1.1 - 1.1.8 (8)
runAutobahnTestCase(constructTestCase(9, 17, excludeList), client, secure); // Framing Binary 1.2.1 - 1.2.8 (8)
runAutobahnTestCase(constructTestCase(17, 28, excludeList), client, secure); // 2. Pings/Pongs 2.1 - 2.11 (11)
runAutobahnTestCase(constructTestCase(28, 35, excludeList), client, secure); // 3. Reserved bits 3.1 - 3.7 (7)
runAutobahnTestCase(constructTestCase(35, 40, excludeList), client, secure); // 4.1 Opcodes Non-Control 4.1.1 - 4.1.5 (5)
runAutobahnTestCase(constructTestCase(40, 45, excludeList), client, secure); // 4.2 Opcodes Control 4.2.1 - 4.2.5 (5)
runAutobahnTestCase(constructTestCase(45, 65, excludeList), client, secure); // Fragmentation 5.1 - 5.20 (20)
runAutobahnTestCase(constructTestCase(65, 210, excludeList), client, secure); // UTF8 handling (145)
runAutobahnTestCase(constructTestCase(210, 251, excludeList), client, secure); // Close handling (41)
#endif
//Performance tests Should be run in retail mode. Else the logging process fail some test.
#if defined(US_RETAIL)
#if defined(US_TARGET_XONE)
excludeList.insert(excludeList.end(), 293u); // 9.7.1 : payload with length 0 (Microsoft issue, will not fix)
excludeList.insert(excludeList.end(), 299u); // 9.8.1 : payload with length 0 (Microsoft issue, will not fix)
runAutobahnTestCase(constructTestCase(251, 306, excludeList), client, secure); // Performance (56)
//NOT IMPLEMENTED runAutobahnTestCase(constructTestCase(306, 358, excludeList), client, secure); // Latency/Compression (50)
#else
runAutobahnTestCase(constructTestCase(251, 306, excludeList), client, secure); // Performance (56)
//NOT IMPLEMENTED runAutobahnTestCase(constructTestCase(308, 358, Set<uint16>()), client, secure); // Latency/Compression (50)
#endif
#endif
}
}
/// @note WARNING: This test fails if the gaming gateway (OpenVPN) is enabled.
TEST_F(WEBSOCKET_NOLOGIN2, USNOT_ConnectDisconnect)
{
Facade facade;
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(facade.getWebsocketClient(), TestWebSocket_BF::s_ECHO_URI, false, ProxySettings());
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.getWebsocketClient().closeConnection(connection)));
EXPECT_FALSE(connection->isConnected());
}
#if defined(US_TARGET_SWITCH)
TEST_F(WEBSOCKET_NOLOGIN, USNOT_ConnectDisconnect_WSS)
{
TestWebSocket_BF::runConnectDisconnectTest(getFacade(0).getWebsocketClient(), TestWebSocket_BF::s_ECHO_URI, true, ProxySettings());
}
#endif
/// @test Shows how to open a websocket connexion to the UbiServices notification server
/// @note This test requires to update the Authorization ticket AND the Ubi-SessionId value to succeed.
TEST_F(WEBSOCKET, DISABLED_MANUAL_ConnectDisconnect_UbiAmazon_ProxyOFF)
{
//LoggingHelper::enableVerbose();
//LoggingHelper::enableMultiLines();
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(),
"uat-public-ws.aws-ubiservices.ubi.com/v2/websocket"
"?Ubi-AppId=1521fc83-86e3-4d7b-bc64-f0b2dc2f6e89" // US_TEST_NS::APP_ID_US_SDK_PC
"&Ubi-SessionId=a35ea03f-1787-4560-9090-77fcad1d455a"
"&Authorization=Ubi_v1%20t=ew0KICAidmVyIjogIjEiLA0KICAiYWlkIjogIjE1MjFmYzgzLTg2ZTMtNGQ3Yi1iYzY0LWYwYjJkYzJmNmU4OSIsDQogICJlbnYiOiAiVUFUIiwNCiAgInNpZCI6ICJhMzVlYTAzZi0xNzg3LTQ1NjAtOTA5MC03N2ZjYWQxZDQ1NWEiLA0KICAidHlwIjogIkpXRSIsDQogICJlbmMiOiAiQTEyOENCQyIsDQogICJpdiI6ICI2N1lQdzNlSG1TMGl0VkVCQU5ZMDB3IiwNCiAgImludCI6ICJIUzI1NiINCn0.D4kyJX6RDxuyWX_l3e2Y0MQ01SaFt1vj5P5H7Qvv5Ho8-eJNGJe3Kt5WNJEsyL-GdCyJujWsZShPdAWL_3Pd92WTn6nJtRe9_7gnk8LjSbHwhTGvJoOv75AVExleoYYASjKaecOE-Dgo1I_pB_iYUitSceEySSpuvcS_-1ZUDKaEf4fL0duRDL8q1IcSLDuA2eZoPLvz60EJ7Qq0wLnEGBxVqSMDMWb00Lz_7pSPIrsZk1ZnxPq5qyEh5mWVWhl9YpNnwURn7xBuBKktSKbHJhx9C7RRp9AjAwkMsCCTNqq7HdVvcfoCvFV7YwJNHUi9244AwV9K0FpChXB_QA-5EfwvJGyx1y5IaBKyeT-skLrJs7JATpTVxgc6kpVvEQwyv0XHoMTFGwnVzHTs-9j5wDONUAxdFlFfTzpaMejVPWmSijIuQPDFq_QQtb6Lx8NA3S_ibb4BQkBosFAHxKtP2vpzDLXmzKcATK5Hv5naUGHuQADQqdr0m3IOK2-HWBC4Ti6pYg4SlNYKrDRWd-zkqOaiUQcZapf9EIghAQvVwN2KDZteb_-YGbqDV19pHZkNNjudfZoMV1SOlW6vj89l-patFxkHq1-ivtYZHWniFem78-rJI4yibk3mCMnBSFELPIaR4Nu_oIqsfwX0w-eBRUllCo3oLWjbkJFrViCPjSOPDNvDS3yWrOp5Q6BHyiqs9n8FQdI1Htio_aWwKZfIq6xc_m2ymOlihdJBJsd6cN_R96O0gX6geoH0xvw5LWaeJ9MhCHonM-epjLU_2UgvOaqBF5DrvPt2E1XwRm7KfwwrO4DnWdPHrNhWeCz2msoO7en1P-_o-BiTJz0XrZ2Gl6Sz614VUcSVqRR3Z5uqnN_9MNK92zuqYJ00kq0b5Yer85ECoGCf94gLwgwHEe_XSA5zEn-xfIhTUePNOps0Fx-EcVM4SDjzHfe3SHkOvhKQP_-gkne1ec5iQ7A8OF-Wa-ZAcm6TdmVY63_KzK3u25mhf8UaJ70p9-Sm8WotQ9V6cIGkXcb1hIBAcTrTca-jErdk8xsTDSyX56d76sHetszWE4R6M9zzVZfeMIcg_Rlunb3psGx3wCs-_BZXWO8MFM8kmBaRU6oHfHNU9VboV9Ejr09226bBE0V3aZLyVJ8oZnnc1h96nyYK_FWD4N1z3kshtPxJ0XQjh34a2Apc6uGc5UZoSL-YBWwdq64JU3xwPVfKJMh-oTPqpj82zgchw47M-Ni-sBHD7fHff7xTRBEzZEfIFnThCUbsh84_Z13Us1H-Gh1sMJhPlEXhGB5YpUglg3VRGf8RSH1gF3JtmCS0rJZbtpNJrmQyfILgf_k0KTL7byjB38pKOw2B8Zj3xh-2KLl0mNzgFYjvo1zymusMWx2XDZ_uMmxixC7--aXSubPqnkVoiN4lF8dCHJzMagQ0CxPJnAPmqKFFBXXbkyoh4jau72J6w4Yi8eLhZRDnVR5IUJYkqn-SdL74N_WBWIc319ufypsSvCpDbMQ_5KbGC1TuCd4s5ToRICUvEcntEN9fGh5lcElxJK1_ZoTfr8kc9XoE5aIGXvoOUjAghLtKXnGskEtZkxCpETW4n93baSC39dGQdXjIqvq_6YztiJV0Be__TgpcC6C1oCmVx3P1LZMlxnY_cDedPzXtKIUNNJ6jN_WK3DEfs0lFMZfofrPYOSWGfYOMen27IKk3MoCKv1g0vZt5rgs2kfgqJiXAV2B5p4UM3IF9UrMWh3UTkWcnXL9tJeK0o8DxqqDGOsXyFqQnDiBX2ETrYvxYir8QljNDt1rN_fD-WYT9y4qY5rEnucfkhBvFTGwpMQa21zfONfXN3Fob4hxJMMpnYkhuwICM016TBQRUwbLrsfHiq5tYhcgixPvHPMisr71aX2hnrA3veRjhu9QvJeW0owwK1p_DVbknUBxfDHZGdc_ekLB9hkVNShMvNuXUibWbtUXx2vmedQsf0z3qgLIh5R-aiGrKD8zd-NcfqNBRkIDifMo5ewrD7WEm6ACZzn0mO-XQ5MLQf8LZCIcpKeuYh0kx.B8CCOhF3O0zR4a48DCg0RDdxMigEmUTz36a-o4Z_C8g"
"&SpaceIds=d0b38ea5-d884-4444-895d-fa99ec47a76a"
"&NotificationTypes=OnlineNotificationType", false, ProxySettings());
}
/// @test Shows how to open a websocket connexion to the UbiServices notification server (through proxy)
/// @note This test requires to update the Authorization ticket AND the Ubi-SessionId value to succeed.
TEST_F(WEBSOCKET, DISABLED_MANUAL_ConnectDisconnect_UbiAmazon_ProxyON)
{
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(),
"uat-public-ws.aws-ubiservices.ubi.com/v2/websocket"
"?Ubi-AppId=1521fc83-86e3-4d7b-bc64-f0b2dc2f6e89" // US_TEST_NS::APP_ID_US_SDK_PC
"&Ubi-SessionId=a35ea03f-1787-4560-9090-77fcad1d455a"
"&Authorization=Ubi_v1%20t=ew0KICAidmVyIjogIjEiLA0KICAiYWlkIjogIjE1MjFmYzgzLTg2ZTMtNGQ3Yi1iYzY0LWYwYjJkYzJmNmU4OSIsDQogICJlbnYiOiAiVUFUIiwNCiAgInNpZCI6ICJhMzVlYTAzZi0xNzg3LTQ1NjAtOTA5MC03N2ZjYWQxZDQ1NWEiLA0KICAidHlwIjogIkpXRSIsDQogICJlbmMiOiAiQTEyOENCQyIsDQogICJpdiI6ICI2N1lQdzNlSG1TMGl0VkVCQU5ZMDB3IiwNCiAgImludCI6ICJIUzI1NiINCn0.D4kyJX6RDxuyWX_l3e2Y0MQ01SaFt1vj5P5H7Qvv5Ho8-eJNGJe3Kt5WNJEsyL-GdCyJujWsZShPdAWL_3Pd92WTn6nJtRe9_7gnk8LjSbHwhTGvJoOv75AVExleoYYASjKaecOE-Dgo1I_pB_iYUitSceEySSpuvcS_-1ZUDKaEf4fL0duRDL8q1IcSLDuA2eZoPLvz60EJ7Qq0wLnEGBxVqSMDMWb00Lz_7pSPIrsZk1ZnxPq5qyEh5mWVWhl9YpNnwURn7xBuBKktSKbHJhx9C7RRp9AjAwkMsCCTNqq7HdVvcfoCvFV7YwJNHUi9244AwV9K0FpChXB_QA-5EfwvJGyx1y5IaBKyeT-skLrJs7JATpTVxgc6kpVvEQwyv0XHoMTFGwnVzHTs-9j5wDONUAxdFlFfTzpaMejVPWmSijIuQPDFq_QQtb6Lx8NA3S_ibb4BQkBosFAHxKtP2vpzDLXmzKcATK5Hv5naUGHuQADQqdr0m3IOK2-HWBC4Ti6pYg4SlNYKrDRWd-zkqOaiUQcZapf9EIghAQvVwN2KDZteb_-YGbqDV19pHZkNNjudfZoMV1SOlW6vj89l-patFxkHq1-ivtYZHWniFem78-rJI4yibk3mCMnBSFELPIaR4Nu_oIqsfwX0w-eBRUllCo3oLWjbkJFrViCPjSOPDNvDS3yWrOp5Q6BHyiqs9n8FQdI1Htio_aWwKZfIq6xc_m2ymOlihdJBJsd6cN_R96O0gX6geoH0xvw5LWaeJ9MhCHonM-epjLU_2UgvOaqBF5DrvPt2E1XwRm7KfwwrO4DnWdPHrNhWeCz2msoO7en1P-_o-BiTJz0XrZ2Gl6Sz614VUcSVqRR3Z5uqnN_9MNK92zuqYJ00kq0b5Yer85ECoGCf94gLwgwHEe_XSA5zEn-xfIhTUePNOps0Fx-EcVM4SDjzHfe3SHkOvhKQP_-gkne1ec5iQ7A8OF-Wa-ZAcm6TdmVY63_KzK3u25mhf8UaJ70p9-Sm8WotQ9V6cIGkXcb1hIBAcTrTca-jErdk8xsTDSyX56d76sHetszWE4R6M9zzVZfeMIcg_Rlunb3psGx3wCs-_BZXWO8MFM8kmBaRU6oHfHNU9VboV9Ejr09226bBE0V3aZLyVJ8oZnnc1h96nyYK_FWD4N1z3kshtPxJ0XQjh34a2Apc6uGc5UZoSL-YBWwdq64JU3xwPVfKJMh-oTPqpj82zgchw47M-Ni-sBHD7fHff7xTRBEzZEfIFnThCUbsh84_Z13Us1H-Gh1sMJhPlEXhGB5YpUglg3VRGf8RSH1gF3JtmCS0rJZbtpNJrmQyfILgf_k0KTL7byjB38pKOw2B8Zj3xh-2KLl0mNzgFYjvo1zymusMWx2XDZ_uMmxixC7--aXSubPqnkVoiN4lF8dCHJzMagQ0CxPJnAPmqKFFBXXbkyoh4jau72J6w4Yi8eLhZRDnVR5IUJYkqn-SdL74N_WBWIc319ufypsSvCpDbMQ_5KbGC1TuCd4s5ToRICUvEcntEN9fGh5lcElxJK1_ZoTfr8kc9XoE5aIGXvoOUjAghLtKXnGskEtZkxCpETW4n93baSC39dGQdXjIqvq_6YztiJV0Be__TgpcC6C1oCmVx3P1LZMlxnY_cDedPzXtKIUNNJ6jN_WK3DEfs0lFMZfofrPYOSWGfYOMen27IKk3MoCKv1g0vZt5rgs2kfgqJiXAV2B5p4UM3IF9UrMWh3UTkWcnXL9tJeK0o8DxqqDGOsXyFqQnDiBX2ETrYvxYir8QljNDt1rN_fD-WYT9y4qY5rEnucfkhBvFTGwpMQa21zfONfXN3Fob4hxJMMpnYkhuwICM016TBQRUwbLrsfHiq5tYhcgixPvHPMisr71aX2hnrA3veRjhu9QvJeW0owwK1p_DVbknUBxfDHZGdc_ekLB9hkVNShMvNuXUibWbtUXx2vmedQsf0z3qgLIh5R-aiGrKD8zd-NcfqNBRkIDifMo5ewrD7WEm6ACZzn0mO-XQ5MLQf8LZCIcpKeuYh0kx.B8CCOhF3O0zR4a48DCg0RDdxMigEmUTz36a-o4Z_C8g"
"&SpaceIds=d0b38ea5-d884-4444-895d-fa99ec47a76a"
"&NotificationTypes=OnlineNotificationType", false, ProxySettings(US_TEST_NS::PROXY_NAME, US_TEST_NS::PROXY_PORT));
}
/// @test Opens and closes a websocket connexion to websocket.org directly (no endpoint involved)
TEST_F(WEBSOCKET, USNOT_ConnectDisconnect_EchoWebsocket_ProxyOFF)
{
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(), "echo.websocket.org", false, ProxySettings());
}
/// @test Opens and closes a websocket connexion to websocket.org through proxy (no endpoint involved)
/// @note The test targets Windows only for the reason that they are not setup on the same VLAN (and do not have access to the same proxies)
TEST_F(WEBSOCKET, USNOT_Win32ConnectDisconnect_EchoWebsocket_ProxyON)
{
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(), "echo.websocket.org", false, ProxySettings(US_TEST_NS::PROXY_NAME, US_TEST_NS::PROXY_PORT));
}
/// @test Opens and closes a websocket connexion to kaazing.net/echo directly (endpoint /echo)
/// @note : This test failed again one week after being reenable => We cannot use kaazing for our automatic tests
/// JIRA US-16870 to find another server/solution
TEST_F(WEBSOCKET, DISABLED_USNOT_ConnectDisconnect_KaazingNet_ProxyOFF)
{
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(), "sandbox.kaazing.net/echo", false, ProxySettings());
}
/// @test Opens and closes a websocket connexion to kaazing.net/echo through proxy (endpoint /echo)
/// @note The test targets Windows only for the reason that they are not setup on the same VLAN (and do not have access to the same proxies)
/// @note : This test failed again one week after being reenable => We cannot use kaazing for our automatic tests
/// JIRA US-16870 to find another server/solution
TEST_F(WEBSOCKET, DISABLED_USNOT_Win32ConnectDisconnect_KaazingNet_ProxyON)
{
TestWebSocket_BF::runConnectDisconnectTest(Facade().getWebsocketClient(), "sandbox.kaazing.net/echo", false, ProxySettings(US_TEST_NS::PROXY_NAME, US_TEST_NS::PROXY_PORT));
}
/// @note WARNING: This test fails if the gaming gateway (OpenVPN) is enabled.
TEST_F(WEBSOCKET_NOLOGIN, USNOT_ConnectDisconnectMultipleTimes)
{
for (int8 i = 0; i < 5; ++i)
{
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(getFacade(0).getWebsocketClient(), TestWebSocket_BF::s_ECHO_URI, false, ProxySettings());
TestWebSocket_BF::disconnectWebsocket(getFacade(0).getWebsocketClient(), connection);
}
}
/// @note WARNING: This test fails if the gaming gateway (OpenVPN) is enabled.
TEST_F(WEBSOCKET_NOLOGIN, USNOT_SendReceiveMessage)
{
struct Local
{
static void runSendReceiveMessageTest(WebSocketClient& client, const String& uri, bool secure, const String& message)
{
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(client, uri, secure, ProxySettings());
{
WebSocketBufferPtr buffer = US_NEW(TextBuffer, message);
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer)));
}
{
WebSocketBufferPtr buffer;
const bool isMessageRetrieved = TestWebSocket_BF::getMessage(client, connection, buffer);
EXPECT_TRUE(isMessageRetrieved);
if (isMessageRetrieved)
{
EXPECT_EQ(buffer->getDataFrame(), WebSocketFrame::Text); //Is frame still text on return? Shouldn't be Binary.
EXPECT_EQ(message, WebSocketHelper::getBufferContent(buffer));
}
}
TestWebSocket_BF::disconnectWebsocket(client, connection);
}
};
Local::runSendReceiveMessageTest(getFacade(0).getWebsocketClient(), TestWebSocket_BF::s_ECHO_URI, false, "This is a test message.");
Local::runSendReceiveMessageTest(getFacade(0).getWebsocketClient(), TestWebSocket_BF::s_ECHO_URI, false, std::string(6000ull, 'a').c_str());
}
/// @note WARNING: This test fails if the gaming gateway (OpenVPN) is enabled.
TEST_F(WEBSOCKET_NOLOGIN, USNOT_SendReceiveMultipleMessagesInSequence)
{
const String message1 = "This is the test message #1.";
const String message2 = "This is the test message #2.";
WebSocketClient& client = getFacade(0).getWebsocketClient();
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(client, TestWebSocket_BF::s_ECHO_URI, false, ProxySettings());
{ // Send #1
WebSocketBufferPtr buffer; // ???
WebSocketBufferPtr buffer1 = US_NEW(TextBuffer, message1);
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer1)));
}
{ // Reception #1
WebSocketBufferPtr buffer;
EXPECT_TRUE(TestWebSocket_BF::getMessage(client, connection, buffer));
EXPECT_EQ(message1, WebSocketHelper::getBufferContent(buffer));
}
{ // Send #2
WebSocketBufferPtr buffer; // ???
WebSocketBufferPtr buffer2 = US_NEW(TextBuffer, message2);
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer2)));
}
{ // Reception #2
WebSocketBufferPtr buffer;
EXPECT_TRUE(TestWebSocket_BF::getMessage(client, connection, buffer));
EXPECT_EQ(message2, WebSocketHelper::getBufferContent(buffer));
}
TestWebSocket_BF::disconnectWebsocket(client, connection);
}
/// @note WARNING: This test fails if the gaming gateway (OpenVPN) is enabled.
TEST_F(WEBSOCKET_NOLOGIN, USNOT_SendReceiveMultipleMessagesInParallel)
{
const String message1 = "This is the test message #1.";
const String message2 = "This is the test message #2.";
WebSocketClient& client = getFacade(0).getWebsocketClient();
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(client, TestWebSocket_BF::s_ECHO_URI, false, ProxySettings());
WebSocketBufferPtr buffer1 = US_NEW(TextBuffer, message1);
WebSocketBufferPtr buffer2 = US_NEW(TextBuffer, message2);
// Parallel Sending
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer1)));
EXPECT_TRUE(AsyncHelper::waitSuccess(client.writeStream(connection, buffer2)));
// Parallel Reception (not necessarily in order)
{
WebSocketBufferPtr buffer;
EXPECT_TRUE(TestWebSocket_BF::getMessage(client, connection, buffer));
const String messageReceived1 = WebSocketHelper::getBufferContent(buffer);
EXPECT_TRUE(messageReceived1 == message1 || messageReceived1 == message2);
}
{
WebSocketBufferPtr buffer;
EXPECT_TRUE(TestWebSocket_BF::getMessage(client, connection, buffer));
const String messageReceived2 = WebSocketHelper::getBufferContent(buffer);
EXPECT_TRUE(messageReceived2 == message1 || messageReceived2 == message2);
}
TestWebSocket_BF::disconnectWebsocket(client, connection);
}
#if defined(US_TARGET_XONE)
/// @disabled This test may freeze on XBox One. Jira US-3827 to fix this issue (may be a first party issue)
// https://mdc-tomcat-jira104.ubisoft.org/jira/browse/US-3827
TEST_P(WEBSOCKET_CANCEL, DISABLED_USNOT_CancelConnect) // TODO: Disabled for XONE (JIRA US-3827)
#else
TEST_P(WEBSOCKET_CANCEL, USNOT_CancelConnect)
#endif
{
WebSocketClient& client = getFacade().getWebsocketClient();
TestConfigCancel& config = this->getParam();
TestCanceler<> canceler(config);
URLInfo uri(TestWebSocket_BF::s_ECHO_URI);
uri.setScheme("ws");
while (!canceler.isComplete())
{
EXPECT_TRUE(canceler.cancel(client.openConnection(uri.getStringValue())));
Helper::sleep(10);
}
}
TEST_P(WEBSOCKET_CANCEL, USNOT_CancelDisconnect)
{
WebSocketClient& client = getFacade().getWebsocketClient();
TestConfigCancel& config = this->getParam();
TestCanceler<> canceler(config);
const String url(TestWebSocket_BF::s_ECHO_URI);
while (!canceler.isComplete())
{
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(client, url, false, ProxySettings());
EXPECT_TRUE(canceler.cancel(client.closeConnection(connection)));
}
}
TEST_P(WEBSOCKET_CANCEL, USNOT_CancelWrite)
{
WebSocketClient& client = getFacade().getWebsocketClient();
TestConfigCancel& config = this->getParam();
TestCanceler<> canceler(config);
while (!canceler.isComplete())
{
WebSocketBufferPtr buffer = US_NEW(TextBuffer, "Dummy Cancel Message");
WebSocketConnectionPtr connection = TestWebSocket_BF::connectWebsocket(client, String(TestWebSocket_BF::s_ECHO_URI), false, ProxySettings());
EXPECT_TRUE(canceler.cancel(client.writeStream(connection, buffer)));
TestWebSocket_BF::disconnectWebsocket(client, connection);
}
}
///@test Validates that the client keeps a stream connected before and after the cleanup operations, if it is alive.
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientCreateDestroyConnection)
{
const StringUrl url(TestWebSocket_BF::s_MOCK_URL_WITH_PINNING);
MockWebSocketEngine engine;
MockWebSocketStreamImpl* mockStream = US_NEW(MockWebSocketStreamImpl, url,
InstancesManager::getInstance()->getSSLPinningKeys(),
HttpObfuscatorHelper::getObfuscator());
{
engine.mockConnection(mockStream);
EXPECT_CALL(*mockStream, readStream(testing::_)).Times(0);
EXPECT_CALL(*mockStream, writeStream(testing::_)).Times(1).WillOnce(testing::Return(Errors::SUCCESS));
}
{
SmartPtr<NotificationQueue<NotificationUbiServices> > notificationsQueue;
AsyncResult<WebSocketConnectionPtr> result = engine.openConnection(url, notificationsQueue);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
WebSocketConnectionPtr websocketConnection = result.getResult();
WebSocketBufferPtr buffer = US_NEW(TextBuffer, String("DummyMessage"));
{
ASSERT_TRUE(AsyncHelper::waitSuccess(engine.writeStream(websocketConnection, buffer)));
EXPECT_TRUE(websocketConnection->isConnected());
}
{
mockStream->pushData(buffer);
EXPECT_TRUE(websocketConnection->isDataAvailable());
WebSocketBufferPtr result2 = engine.readStream(websocketConnection);
EXPECT_EQ(result2, buffer);
EXPECT_TRUE(websocketConnection->isConnected());
}
}
}
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientConnectionWrongUri)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("URL shall begin with 'ws://' or 'wss://'. Scheme unexpected: http", LogLevel::Error, Times(2));
});
WebSocketClient& client = getFacade().getWebsocketClient();
EXPECT_TRUE(AsyncHelper::waitFailure(client.openConnection("http://wronguri.ubi.com"), // Wrong scheme for websocket
Errors::WEBSOCKET_CONNECTION_FAILED));
EXPECT_TRUE(AsyncHelper::waitFailure(client.openConnection("wronguri.ubi.com"), // Empty scheme defaults to HTTP
Errors::WEBSOCKET_CONNECTION_FAILED));
}
///@test Validates that the client cannot write/read throughout an absent connection.
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientConnectionNotFound)
{
WebSocketClient& client = getFacade().getWebsocketClient();
WebSocketBufferPtr buffer = US_NEW(TextBuffer, String("DummyMessage"));
EXPECT_TRUE(AsyncHelper::waitFailure(client.writeStream(WebSocketConnectionPtr(), buffer), Errors::WEBSOCKET_INVALID_CONNECTION));
WebSocketBufferPtr result = client.readStream(WebSocketConnectionPtr());
EXPECT_EQ(result, WebSocketBufferPtr());
EXPECT_TRUE(AsyncHelper::waitFailure(client.closeConnection(WebSocketConnectionPtr()), Errors::WEBSOCKET_INVALID_CONNECTION));
}
///@test Validates that the client gets an error when a user tries to send in a invalid/disconnected connection.
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientInvalidConnectionDisconnected)
{
const StringUrl url(TestWebSocket_BF::s_MOCK_URL_WITH_PINNING);
MockWebSocketEngine engine;
MockWebSocketStreamImpl* mockStream = US_NEW(MockWebSocketStreamImpl, url,
InstancesManager::getInstance()->getSSLPinningKeys(),
HttpObfuscatorHelper::getObfuscator());
{
engine.mockConnection(mockStream);
EXPECT_CALL(*mockStream, writeStream(testing::_)).Times(0);
EXPECT_CALL(*mockStream, readStream(testing::_)).Times(0);
}
{
SmartPtr<NotificationQueue<NotificationUbiServices> > notificationsQueue;
const AsyncResult<WebSocketConnectionPtr> result = engine.openConnection(url, notificationsQueue);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
WebSocketConnectionPtr websocketConnection = result.getResult();
{
EXPECT_TRUE(mockStream->getConnection()->isConnected());
mockStream->setConnected(false);
EXPECT_FALSE(mockStream->getConnection()->isConnected());
}
{
WebSocketBufferPtr buffer = US_NEW(TextBuffer, String("DummyMessage"));
EXPECT_TRUE(AsyncHelper::waitFailure(engine.writeStream(websocketConnection, buffer), Errors::WEBSOCKET_DISCONNECTED));
}
{
WebSocketBufferPtr readResult = engine.readStream(websocketConnection);
EXPECT_EQ(readResult, WebSocketBufferPtr());
}
ASSERT_TRUE(AsyncHelper::waitSuccess(engine.closeConnection(websocketConnection, false)));
}
}
///@test Verifies if a buffer sent is valid before any sent it done.
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientInvalidWriteBuffer)
{
const StringUrl url(TestWebSocket_BF::s_MOCK_URL_WITH_PINNING);
MockWebSocketEngine engine;
MockWebSocketStreamImpl* mockStream = US_NEW(MockWebSocketStreamImpl, url,
InstancesManager::getInstance()->getSSLPinningKeys(),
HttpObfuscatorHelper::getObfuscator());
{
engine.mockConnection(mockStream);
EXPECT_CALL(*mockStream, writeStream(testing::_)).Times(0);
EXPECT_CALL(*mockStream, readStream(testing::_)).Times(0);
}
SmartPtr<NotificationQueue<NotificationUbiServices> > notificationsQueue;
const AsyncResult<WebSocketConnectionPtr> result = engine.openConnection(url, notificationsQueue);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
WebSocketConnectionPtr websocketConnection = result.getResult();
{
const AsyncResult<Empty> resultWrite = engine.writeStream(websocketConnection, WebSocketBufferPtr());
EXPECT_TRUE(resultWrite.wait());
US_EXPECT_FAILURE(resultWrite, Errors::WEBSOCKET_WRITE_FAILURE);
}
}
//@test Verifies if the websocket connection returns a proper empty pointer when there's not data available.
TEST_F(WEBSOCKET_MOCK, LOCAL_WebsocketClientReadEmptyStream)
{
const StringUrl url(TestWebSocket_BF::s_MOCK_URL_WITH_PINNING);
MockWebSocketEngine engine;
MockWebSocketStreamImpl* mockStream = US_NEW(MockWebSocketStreamImpl, url,
InstancesManager::getInstance()->getSSLPinningKeys(),
HttpObfuscatorHelper::getObfuscator());
{
engine.mockConnection(mockStream);
EXPECT_CALL(*mockStream, writeStream(testing::_)).Times(0);
EXPECT_CALL(*mockStream, readStream(testing::_)).Times(0);
}
SmartPtr<NotificationQueue<NotificationUbiServices> > notificationsQueue;
const AsyncResult<WebSocketConnectionPtr> result = engine.openConnection(url, notificationsQueue);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
WebSocketConnectionPtr websocketConnection = result.getResult();
WebSocketBufferPtr readResult = engine.readStream(websocketConnection);
EXPECT_EQ(readResult, WebSocketBufferPtr());
}
/// Autobahn Test Suite (LOCAL)
///
/// To run the tests, AutobahnTestSuite is needed to be installed (http://autobahn.ws/testsuite/installation/).
///
/// Regardless of what the installation says, you should be using pip instead of easy_install.
///
/// To start the test, first run in a command prompt wstest -m fuzzingserver. Then run
/// the following test case. You can also pass --debug to this command line to have
/// some logs from the server process.
///
/// To get the result, point you web browser to http://localhost:8080/cwd/reports/clients/.
TEST_F(WEBSOCKET_MOCK, DISABLED_MANUAL_WebSocketAutobahnTestSuite)
{
TestWebSocketAutobahn_BF::runAutobahnTestSuite(getFacade(), false);
}
// In order to run Autobahn test suite over SSL, you need a certificate and
// private key first. Then, you need to run wstest with a spec and specify
// a secure websocket address in order to test it over SSL. Using the -w
// param didn't work for me and looking in the code of autobahn, it seems it
// shouldn't since the url does not get passed down.
//
// Here's an example of the spec I used:
// {
// "url": "wss://127.0.0.1:9001",
// "key": "ssl_cert.key",
// "cert": "ssl_cert.crt",
//
// "options": {"failByDrop": false},
// "outdir": "./reports/clients",
// "webport": 8080,
//
// "cases": ["*"],
// "exclude-cases": [],
// "exclude-agent-cases": {}
// }
// 2014/03/04 : The autobahn fuzzingserver is buggy (autobahnWS 0.8.4-2 and autobahntestSuite 0.6.0)
// and cannot be launched using SSL.
// key and crt files are not taken into account in both command line parameters and spec files.
// This error is therefore raised : Exception: Secure WebSocket listen requested, but no SSL context factory given
TEST_F(WEBSOCKET_MOCK, DISABLED_MANUAL_WebSocketSecureAutobahnTestSuiteSecure)
{
TestWebSocketAutobahn_BF::runAutobahnTestSuite(getFacade(), true);
}
};
#endif // DLL
#endif // defined(US_SDK_FULL)