//////////////////////////////////////////////////////////////////////////////// // (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 #include #include #include #include #include #include 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 WEBSOCKET_MOCK; // Cancel test settings typedef AuthenticationFixtureWithParam::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 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 result1 = client.writeStream(connection, buffer1); const AsyncResult 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 constructTestCase(uint16 startIndex, uint16 endIndex, Set excludeIndex) { Set indexes; uint16 i = startIndex; do { indexes.insert(i); } while(++i < endIndex); Set 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 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 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 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 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 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()), 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 > notificationsQueue; AsyncResult 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 > notificationsQueue; const AsyncResult 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 > notificationsQueue; const AsyncResult result = engine.openConnection(url, notificationsQueue); ASSERT_TRUE(AsyncHelper::waitSuccess(result)); WebSocketConnectionPtr websocketConnection = result.getResult(); { const AsyncResult 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 > notificationsQueue; const AsyncResult 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)