//////////////////////////////////////////////////////////////////////////////// // (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour // //////////////////////////////////////////////////////////////////////////////// #include "tests/config.h" #include "tests/common/cancelTest.h" #include "tests/common/helpers.h" #include "tests/common/restStatusCode.h" #include "tests/fixture/authenticationFixture.h" // AsyncHelper #include "tests/fixture/loginMockFixture.h" #include "tests/fixture/memoryCheckFixture.h" #include "tests/fixture/paramFixture.h" #include "tests/mock/mockLogDevice.h" #include "tests/mock/mockResultHelper.h" #include "testsUnit/helpers/asyncResultBaseProxy.h" #include "testsUnit/mock/mockHttpRequest.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #if !defined(US_RETAIL) // extern bool US_DLL_API s_forceNonSecure; // #endif namespace US_NS {; US_DEFINE_TEST(TestHttp); template class AuthenticationFixtureHttp : public AuthenticationFixture { public: AuthenticationFixtureHttp() : AuthenticationFixture() { } protected: void SetUp() override { LeakChecker::m_skipEalMemForLibcurl = skipEalMemForLibcurl; AuthenticationFixture::SetUp(); } }; typedef LeakChecker CORE_HTTP; typedef LeakCheckerHttpClient CORE_HTTP_CLIENT; typedef LeakCheckerHttpClientSkipLibCurlEalMem CORE_HTTP_CLIENT_NOEALMEM; typedef LeakCheckerNoInit CORE_HTTP_NO_INIT; typedef AuthenticationFixtureHttp<1, true, true> CORE_HTTP_CANCEL_LOGIN; typedef AuthenticationFixtureHttp<2, false> CORE_HTTP_PROXY_X2; typedef ParamFixture CORE_HTTP_CANCEL; US_DEFINE_LONG_TEST_P(CORE_HTTP_CANCEL, TestConfigCancel(100u), TestConfigCancel(20u)); typedef LeakCheckerNoInitWithParam::type CORE_HTTP_CANCEL_NO_INIT; US_DEFINE_LONG_TEST_P(CORE_HTTP_CANCEL_NO_INIT, TestConfigCancel(200u), TestConfigCancel(20u)); TEST_F(CORE_HTTP, LOCAL_CheckProxyConfig) { const HttpProxyConfig defaultProxy; EXPECT_STREQ("", defaultProxy.m_host.getUtf8()); EXPECT_EQ(0u, defaultProxy.m_port); EXPECT_STREQ("", defaultProxy.m_username.getUtf8()); EXPECT_STREQ("", defaultProxy.m_password.getUtf8()); const String host("proxy.ubi.com"); const uint32 PORT = 9090; const String username("player2"); const String password("Im 3l33t!"); const HttpProxyConfig proxyNoAuth(host, PORT); EXPECT_EQ(host, proxyNoAuth.m_host); EXPECT_EQ(PORT, proxyNoAuth.m_port); EXPECT_STREQ("", proxyNoAuth.m_username.getUtf8()); EXPECT_STREQ("", proxyNoAuth.m_password.getUtf8()); const HttpProxyConfig proxyAuth(host, PORT, username, password); EXPECT_EQ(host, proxyAuth.m_host); EXPECT_EQ(PORT, proxyAuth.m_port); EXPECT_EQ(username, proxyAuth.m_username); EXPECT_EQ(password, proxyAuth.m_password); const HttpProxyConfig copy(proxyAuth); EXPECT_EQ(proxyAuth.m_host, copy.m_host); EXPECT_EQ(proxyAuth.m_port, copy.m_port); EXPECT_EQ(proxyAuth.m_username, copy.m_username); EXPECT_EQ(proxyAuth.m_password, copy.m_password); HttpProxyConfig copy2; copy2 = copy; EXPECT_EQ(copy.m_host, copy2.m_host); EXPECT_EQ(copy.m_port, copy2.m_port); EXPECT_EQ(copy.m_username, copy2.m_username); EXPECT_EQ(copy.m_password, copy2.m_password); } TEST_F(CORE_HTTP, LOCAL_HttpHeader) { SAVE_ALLOC_COUNT(testCount); { HttpHeader headersSource; headersSource["field1"] = "value1"; headersSource["field2"] = "value2"; EXPECT_TRUE(headersSource.hasHeader("field1")); EXPECT_TRUE(headersSource.hasHeader("field2")); EXPECT_EQ(2u, headersSource.getHeaderCount()); const String lines1 = "field1: value1"; const String lines2 = "field2: value2"; HttpHeader headersTarget; EXPECT_STREQ("field1", headersTarget.addHeaderLine(lines1).getUtf8()); EXPECT_STREQ("field2", headersTarget.addHeaderLine(lines2).getUtf8()); EXPECT_EQ(lines1.getLength() + lines2.getLength(), headersTarget.getSize()); EXPECT_TRUE(headersTarget.hasHeader("field1")); EXPECT_TRUE(headersTarget.hasHeader("field2")); EXPECT_EQ(lines1, headersTarget.getLine("field1")); EXPECT_EQ(headersSource.getLine("field1"), headersTarget.getLine("field1")); EXPECT_EQ(lines2, headersTarget.getLine("field2")); EXPECT_EQ(headersSource.getLine("field2"), headersTarget.getLine("field2")); EXPECT_EQ(headersSource, headersTarget); } { HttpHeader header; EXPECT_EQ(-1, header.getContentLength()); header["Content-Length"] = "5"; EXPECT_EQ(5u, header.getContentLength()); } { HttpHeader header; EXPECT_EQ(-1, header.getContentLength()); header["content-Length"] = "5"; EXPECT_EQ(5u, header.getContentLength()); } { HttpHeader caseInsentiveHeader; const String value1 = "value1"; caseInsentiveHeader["field1"] = value1; EXPECT_EQ(value1, caseInsentiveHeader.getValue("FIELD1")); EXPECT_EQ(1u, caseInsentiveHeader.getHeaderCount()); caseInsentiveHeader["fiElD1"] = "value1"; EXPECT_EQ(value1, caseInsentiveHeader.getValue("field1")); EXPECT_EQ(1u, caseInsentiveHeader.getHeaderCount()); EXPECT_TRUE(caseInsentiveHeader.hasHeader("field1")); EXPECT_TRUE(caseInsentiveHeader.hasHeader("fiElD1")); caseInsentiveHeader.addHeader("field2", "value2"); EXPECT_EQ(2u, caseInsentiveHeader.getHeaderCount()); caseInsentiveHeader.addHeader("FiELd2", "value2"); EXPECT_EQ(2u, caseInsentiveHeader.getHeaderCount()); EXPECT_TRUE(caseInsentiveHeader.hasHeader("field2")); EXPECT_TRUE(caseInsentiveHeader.hasHeader("FiELd2")); caseInsentiveHeader.removeHeader("fiElD1"); EXPECT_EQ(1u, caseInsentiveHeader.getHeaderCount()); caseInsentiveHeader.removeHeader("FiELd2"); EXPECT_EQ(0u, caseInsentiveHeader.getHeaderCount()); EXPECT_FALSE(caseInsentiveHeader.hasHeader("field2")); EXPECT_FALSE(caseInsentiveHeader.hasHeader("FiELd2")); } { HttpHeader headersSource; EXPECT_EQ(0u, headersSource.getHeaderCount()); headersSource["field1"] = "value1"; EXPECT_EQ(1u, headersSource.getHeaderCount()); headersSource.addHeader("field1", "value1"); // redundant adding EXPECT_EQ(1u, headersSource.getHeaderCount()); headersSource.addHeader("field2", "value2"); EXPECT_EQ(2u, headersSource.getHeaderCount()); headersSource.removeHeader("NotFound"); EXPECT_EQ(2u, headersSource.getHeaderCount()); headersSource.removeHeader("field1"); headersSource.removeHeader("field2"); EXPECT_EQ(0, headersSource.getHeaderCount()); } EXPECT_ALLOC_COUNT_PC_X1_EQ(114u, 114, testCount); } #if defined(US_TARGET_WINDOWS) #pragma warning(disable:4068) // unknown pragma #pragma BullseyeCoverage save off #pragma warning(default:4068) #endif /// @test Retrieves the user-agent sent from UbiServices and checks it is present and correct TEST_F(CORE_HTTP_CLIENT, HTTPBOX_CheckUserAgent) { Facade facade; const HttpGet request(TestHelpers_BF::getHttpTestUrl("get"), TestHelpers_BF::getHttpBoxHeader()); const AsyncResult result = facade.getHttpClient().sendRequest(request); ASSERT_TRUE(AsyncHelper::waitSuccess(result)); EXPECT_EQ(RestStatusCode::OK, result.getResult().getStatusCode()); const Json bodyReader(result.getResult().getBodyAsString()); ASSERT_TRUE(bodyReader.isValid()); const Json headersReader = bodyReader["headers"]; ASSERT_TRUE(headersReader.isValid()); const Json userAgentReader = headersReader["User-Agent"]; ASSERT_TRUE(userAgentReader.isValid()); ASSERT_TRUE(userAgentReader.isTypeString()); const String userAgent = userAgentReader.getValueString(); #if defined(US_SDK_S2S) #if defined(US_UNITY3D) const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_Unity_Server_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #else const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_Server_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #endif #elif defined(US_SDK_LIGHT_MOBILE) #if defined(US_UNITY3D) const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_Unity_Light_Mobile_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #else const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_Light_Mobile_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #endif #else //Full SDK #if defined(US_UNITY3D) const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_Unity_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #else const StringUrl expectedUserAgent = String::formatText("UbiServices_SDK_" US_SDK_VERSION_CONST_CHAR "_%s", US_PLATFORM_NAME); #endif #endif // Check if the string is found in the retrieved user-agent // Avoid checking that the full string are equal as libraries may add some prefix or suffix (e.g. PS4) EXPECT_NE(String::npos, userAgent.findSubstringCase(expectedUserAgent)); PRINT_LINE("User Agent: %s", userAgent.getAnsi().c_str()); } /// Executes multiple (PARALLEL_COUNT) HTTP requests in parallel /// (repeating the exercise EXECUTION_COUNT times) TEST_F(CORE_HTTP_CLIENT, HTTPBOX_ParalleleRequests) { const uint32 EXECUTION_COUNT = 10; const uint32 PARALLEL_COUNT = 6; Facade facade; String data; for(uint32 i = 0; i < 1000; i++) { data += "Test"; } // Force UAT environment. Since there is no login, prod would be used every time const StringUrl url = TestHelpers_BF::getHttpTestUrl("get"); HttpHeader headers = TestHelpers_BF::getHttpBoxHeader(); headers["DummyData"] = data.getAnsi(); // Sending a large request for (uint32 count = 0; count < EXECUTION_COUNT; count++) { Vector > responses(PARALLEL_COUNT); for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { *it = facade.getHttpClient().sendRequest(HttpGet(url, headers)); // FIXME, this does not validate the test. The requests are not truly made in parallel. #if defined(US_TARGET_XONE) Helper::sleep(250); // Arbitrary delay attempting to improve success (some requests time out...) #endif } for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { EXPECT_TRUE((*it).wait()); US_EXPECT_SUCCESS((*it)); EXPECT_TRUE(!(*it).getResult().getBodyAsString().isEmpty()); } } } /// Same test as above, but for SSL requests TEST_F(CORE_HTTP_CLIENT, HTTPBOX_ParalleleRequestsSecure) { const uint32 EXECUTION_COUNT = 10; const uint32 PARALLEL_COUNT = 6; Facade facade; String data; for(uint32 i = 0; i < 1000; i++) { data += "Test"; } HttpHeader headers = TestHelpers_BF::getHttpBoxHeader(); headers["DummyData"] = data.getAnsi(); //Sending a large request const HttpGet request(TestHelpers_BF::getHttpTestUrl("get", String(), false, false), headers); for (uint32 count = 0; count < EXECUTION_COUNT; count++) { { Vector > responses(PARALLEL_COUNT); for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { *it = facade.getHttpClient().sendRequest(request); } for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { EXPECT_TRUE((*it).wait()); US_EXPECT_SUCCESS((*it)); EXPECT_TRUE(it->getResult().isSuccessStatusCode()); } } } } #if !defined(US_DLL) /* Test the prefix of the the user agent */ TEST_F(CORE_HTTP_CLIENT, HTTP_GetUserAgentPrefix) { const String agent = HttpHelper::getUserAgent(); #if defined(US_SDK_S2S) #if defined(US_UNITY3D) EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_Unity_Server_") == 0); #else EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_Server_") == 0); #endif //defined(US_UNITY3D) #elif defined(US_SDK_LIGHT_MOBILE) #if defined(US_UNITY3D) EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_Unity_Light_Mobile_") == 0); #else EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_Light_Mobile_") == 0); #endif #else //Full Client SDK #if defined(US_UNITY3D) EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_Unity_") == 0); #else EXPECT_TRUE(agent.findSubstringCase("UbiServices_SDK_") == 0); #endif //defined(US_UNITY3D) #endif //defined(US_SDK_S2S) } #endif TEST_F(CORE_HTTP_CLIENT, HTTPBOX_TrafficStatsBasicUpload) { Facade facade; HttpClient& client = facade.getHttpClient(); { client.resetTrafficStats(); const HttpStatistics stats = client.getTrafficStats(); EXPECT_EQ(0u, stats.getTotalStatistics(HttpTrafficWay::Upload, HttpTrafficType::Http)); EXPECT_EQ(0u, stats.getTotalStatistics(HttpTrafficWay::Download, HttpTrafficType::Http)); EXPECT_EQ(0u, stats.getNbRequest(HttpTrafficType::Http)); } const StringUrl testUrl = TestHelpers_BF::getHttpTestUrl("put"); const String testBody = "Look at me sexy body! - Fat Bastard"; HttpHeader testHeader = TestHelpers_BF::getHttpContentHeader(); testHeader["dummyKey"] = "dummyValue"; ASSERT_TRUE(AsyncHelper::waitSuccess(facade.getHttpClient().sendRequest(HttpPut(testUrl, testHeader, testBody)))); { const HttpStatistics stats = client.getTrafficStats(); EXPECT_EQ(1u, stats.getNbRequest(HttpTrafficType::Http)); const uint32 testUploadUrl = stats.getStatistic(HttpTrafficWay::Upload, HttpTrafficType::Http, HttpTrafficStatistic::UrlSize); const uint32 testUploadHeader = stats.getStatistic(HttpTrafficWay::Upload, HttpTrafficType::Http, HttpTrafficStatistic::HeaderSize); const uint32 testUploadBody = stats.getStatistic(HttpTrafficWay::Upload, HttpTrafficType::Http, HttpTrafficStatistic::BodySize); EXPECT_EQ(testUrl.getLength(), testUploadUrl); EXPECT_EQ(testHeader.getSize(), testUploadHeader); EXPECT_EQ(testBody.getLength(), testUploadBody); EXPECT_EQ(testUploadUrl + testUploadHeader + testUploadBody, stats.getTotalStatistics(HttpTrafficWay::Upload, HttpTrafficType::Http)); } { client.resetTrafficStats(); const HttpStatistics stats = client.getTrafficStats(); EXPECT_EQ(0u, stats.getTotalStatistics(HttpTrafficWay::Upload, HttpTrafficType::Http)); EXPECT_EQ(0u, stats.getTotalStatistics(HttpTrafficWay::Download, HttpTrafficType::Http)); EXPECT_EQ(0u, stats.getNbRequest(HttpTrafficType::Http)); } } #if !defined(US_DLL) TEST_F(CORE_HTTP_CLIENT, HTTPBOX_TrafficStatsBasicDownload) { Facade facade; HttpClient& client = facade.getHttpClient(); client.resetTrafficStats(); const String receivedData("DUMMY_DATA."); const size_t uReceivedDataSize = receivedData.getLength(); const String sReceivedDataSize = String::formatText("%d", uReceivedDataSize).getUtf8(); // by using the httpbox "bytes/11" url, the httpbox will send back 11 random bytes const StringUrl testUrl = TestHelpers_BF::getHttpTestUrl(String(("bytes/") + sReceivedDataSize)); const AsyncResult requestAsync = facade.getHttpClient().sendRequest(HttpGet(testUrl, TestHelpers_BF::getHttpBoxHeader())); EXPECT_TRUE(requestAsync.wait()); US_EXPECT_SUCCESS(requestAsync); JsonWriter expectedResponseBody; { //innacurate but only the body size is important expectedResponseBody["data"] = receivedData; } HttpHeader expectedResponseHeader; { //some of the headers values might be innacurate but only the header content size bothers. expectedResponseHeader["Cache-Control"] = "no-cache"; expectedResponseHeader["Connection"] = "keep-alive"; expectedResponseHeader["Pragma"] = "no-cache"; expectedResponseHeader["Content-Type"] = "application/octet-stream"; expectedResponseHeader["Expires"] = "-1"; expectedResponseHeader["Server"] = "UbiServices Gateway /1.5.0"; expectedResponseHeader["Strict-Transport-Security"] = "max-age=63072000"; expectedResponseHeader["Ubi-Forwarded-By"] = "ue1-d-us-public-nginx-0cc428d17f577b72d msr-dev-us nginx02"; expectedResponseHeader["Ubi-transactionId"] = "e6a31c3e-ab29-4049-aa17-747e80c8d327"; expectedResponseHeader["X-AspNet-Version"] = "4.0.30319"; expectedResponseHeader["X-Powered-By"] = "ASP.NET"; expectedResponseHeader["X-Content-Type-Options"] = "nosniff"; expectedResponseHeader["X-Frame-Options"] = "DENY"; expectedResponseHeader["Date"] = "Fri, 31 Oct 2014 13:07:57 GMT"; expectedResponseHeader["Content-Length"] = sReceivedDataSize; expectedResponseHeader["ETag"] = "\"786ce1d467b1f7d99e942ad95787b1082c990fc0\""; EXPECT_EQ(expectedResponseHeader.getSize(), requestAsync.getResult().getAllHeader().getSize()); } { const HttpStatistics stats = client.getTrafficStats(); EXPECT_EQ(1u, stats.getNbRequest(HttpTrafficType::Http)); const uint32 testDownloadHeader = stats.getStatistic(HttpTrafficWay::Download, HttpTrafficType::Http, HttpTrafficStatistic::HeaderSize); const uint32 testDownloadBody = stats.getStatistic(HttpTrafficWay::Download, HttpTrafficType::Http, HttpTrafficStatistic::BodySize); const uint32 testDownloadedBytes = stats.getTotalStatistics(HttpTrafficWay::Download, HttpTrafficType::Http); EXPECT_EQ(testDownloadHeader, expectedResponseHeader.getSize()); EXPECT_EQ(testDownloadBody, uReceivedDataSize); EXPECT_EQ(testDownloadBody + testDownloadHeader, testDownloadedBytes); } client.resetTrafficStats(); } #endif /// @test Verifies that HTTP requests have all the same behavior when a HTTP timeout occurs #if !defined(US_DLL) TEST_F(CORE_HTTP_CLIENT, HTTPBOX_HttpErrorCode) { using namespace testing; struct Helper { static AssertionResult sendRequest(HttpClient& client, const HttpRequest& request, uint32 statusCode) { HttpRetryConfig retryConfig = HttpRetryConfig(0); /* Disable retry feature */ const AsyncResult result = client.sendRequest(request, retryConfig); if (!result.wait()) { return ::testing::AssertionFailure() << "Wait failed"; } if (result.hasFailed()) { return ::testing::AssertionFailure() << "Async result failed"; } if (statusCode != result.getResult().getStatusCode()) { return ::testing::AssertionFailure() << "Response status code is " << result.getResult().getStatusCode() << " , expected " << statusCode; } return AssertionSuccess(); } static AssertionResult performHttpRequests(HttpClient& client, const HttpHeader& header, RestStatusCode::Enum statusCode) { { // GET const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(statusCode); const AssertionResult result = sendRequest(client, HttpGet(url, header), statusCode); if (!result) { return result; } } { // HEAD const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(statusCode); const AssertionResult result = sendRequest(client, HttpHead(url, header), statusCode); if (!result) { return result; } } { // POST const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(statusCode); const AssertionResult result = sendRequest(client, HttpPost(url, header, "body"), statusCode); if (!result) { return result; } } { // PUT const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(statusCode); const AssertionResult result = sendRequest(client, HttpPut(url, header, "body"), statusCode); if (!result) { return result; } } { // DELETE const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(statusCode); const AssertionResult result = sendRequest(client, HttpDelete(url, header, "body"), statusCode); if (!result) { return result; } } return AssertionSuccess(); } }; Facade facade; // JsonWriter writer; // writer["delete some thing"] = 0; // // On Xbox One, when we send data with a POST, PUT or DELETE and we receive an error from the server // // like a 404. The HttpCallback::OnError method get called and in that case we do not have access // // to the header and status code. It seems that since the data was not sent, the OnError method get called. // // But if we have nothing to send, it works as expected. // #if defined(US_TARGET_XONE) // const String body; // #else // const String body = writer.renderContent(); // #endif HttpClient& client = facade.getHttpClient(); const HttpHeader header = TestHelpers_BF::getHttpContentHeader(); EXPECT_TRUE(Helper::performHttpRequests(client, header, RestStatusCode::OK_202)); EXPECT_TRUE(Helper::performHttpRequests(client, header, RestStatusCode::Error400)); EXPECT_TRUE(Helper::performHttpRequests(client, header, RestStatusCode::Error403)); EXPECT_TRUE(Helper::performHttpRequests(client, header, RestStatusCode::Error500)); EXPECT_TRUE(Helper::performHttpRequests(client, header, RestStatusCode::Error503)); } TEST_F(CORE_HTTP_CLIENT, HTTPBOX_PerformHttpTimeOut) { const ClockSteady::TTimeNano TIMEOUT = 1000; // 1s HttpRetryConfig retryConfig = HttpRetryConfig(0, HttpRetryConfig::RetryParam(), HttpRetryConfig::TimeoutParam(TIMEOUT)); Facade facade; const StringUrl url = TestHelpers_BF::getHttpTestUrl("get", String::formatText("delay=%i", 3000)); const AsyncResult result = facade.getHttpClient().sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader()), retryConfig); EXPECT_TRUE(result.wait()); EXPECT_TRUE(result.hasFailed()); US_EXPECT_FAILURE(result, Errors::HTTP_TIMEOUT); } /// @test The download streaming should timeout properly when waiting for client to download next chunk TEST_F(CORE_HTTP_CLIENT, HTTPBOX_PerformHttpGETStreamTimeoutBeforeNextQuery) { // Reducing the timeout threshold since the default 60 sec is a bit long for the test. const ClockSteady::TTimeNano TIMEOUT = 5000; // 5s HttpRetryConfig retryConfig = HttpRetryConfig(0, HttpRetryConfig::RetryParam(), HttpRetryConfig::TimeoutParam(TIMEOUT)); Facade facade; const StringUrl url = TestHelpers_BF::getHttpTestUrl("get"); const uint32 DUMMY_SIZE = 1000u; HttpStreamContext context; const HttpStreamPost request(url, DUMMY_SIZE, TestHelpers_BF::getHttpBoxHeader(), context); AsyncResult result = facade.getHttpClient().sendRequest(request, retryConfig); // Do the streaming while (result.isProcessing()) { // Check notifications HttpStreamNotification::Code notification = context.popNotification(); while (notification != HttpStreamNotification::None) { switch (notification) { case HttpStreamNotification::BufferToPush: //Do nothing! case HttpStreamNotification::BufferToPop: //Do nothing! case HttpStreamNotification::ContentLengthReady: case HttpStreamNotification::None: default: break; } notification = context.popNotification(); } Helper::sleep(50); } US_EXPECT_FAILURE(result, Errors::HTTP_TIMEOUT); } // NEED CHECK AS THE STATUS CODE CONF DISAPEARED //// Test that the requests are automatically retried on configured codes : 500, 502, 503 and 504. //typedef ParamFixture CORE_HTTP_RETRY_STATUS_CODE; //INSTANTIATE_TEST_CASE_P(StatusCode, CORE_HTTP_RETRY_STATUS_CODE, ::testing::Values(500, 502, 503, 504)); //TEST_P(CORE_HTTP_RETRY_STATUS_CODE, HTTPBOX_PerformHttpRetryStatusCodes) //{ // //HttpEngineConfig& httpEngineConfig = InstancesManager::getInstance()->getHttpEngine().getConfiguration(); // //httpEngineConfig.setMaxRequestRetry(1); // //httpEngineConfig.setRetryInterval(1000); // HttpRetryConfig retryConfig = HttpRetryConfig(1, HttpRetryConfig::RetryParam(1000)); // // Facade facade; // // const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(this->getParam()); // // Set httpCode; // httpCode.insert(this->getParam()); // // const AsyncResultBase result = facade.getHttpClient().sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader(), HttpRetryConfig(httpCode))); // US_EXPECT_PROPERTY_WAIT(result, AsyncResultBase::isDelayed, true, 1500); // US_EXPECT_PROPERTY_WAIT(result, AsyncResultBase::getRetryCount, static_cast(1), 5000); // // EXPECT_TRUE(result.wait()); // EXPECT_TRUE(result.hasSucceeded()) << "The request should be considered successful even if the http code returned is not a 200."; // // // Retry count is reset to 0 once the async is complete // EXPECT_EQ(0u, result.getRetryCount()); //} /// @test Tests that retry count is 0 on some status codes typedef ParamFixture CORE_HTTP_NO_RETRY_STATUS_CODE; INSTANTIATE_TEST_CASE_P(StatusCode, CORE_HTTP_NO_RETRY_STATUS_CODE, ::testing::Values(RestStatusCode::OK, RestStatusCode::Error403, RestStatusCode::Error501, RestStatusCode::Error508)); TEST_P(CORE_HTTP_NO_RETRY_STATUS_CODE, HTTPBOX_PerformHttpNoRetryStatusCodes) { HttpRetryConfig retryConfig = HttpRetryConfig(1); Facade facade; const StringUrl url = TestHelpers_BF::getHttpStatusCodeTestUrl(this->getParam()); const AsyncResult result = facade.getHttpClient().sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader()), retryConfig); EXPECT_TRUE(result.wait()); EXPECT_TRUE(result.hasSucceeded()); EXPECT_EQ(0u, AsyncResultBaseProxy::getRetryCount(result)); } #endif // DLL //////////////////////////////////////////////////////////////////////////////// // Cancel tests /// @test Cancels HTTP requests with various delays. TEST_P(CORE_HTTP_CANCEL, HTTPBOX_CancelGet) { { TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); // getCount vs. getCompleteCountMax could bring issue since count may be > completeCountMax. // getCompleteCount vs. getCompleteCountMax should not have any issue, but the progression bar may not progress during several steps //PRINT_PROGRESS((canceler.m_testConfig.getCompleteCount() + 1), (canceler.m_testConfig.getCompleteCountMax() + 1), "Processing Time Interval: %d ms", canceler.m_testConfig.getTimeInterval()); const StringUrl url(TestHelpers_BF::getHttpTestUrl("get")); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader())))); } } } /// @test Cancels HTTP requests with various delays. /// (Normal cancel flow over secure since SSL does some more process) TEST_P(CORE_HTTP_CANCEL, US_CancelGetSecure) { TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); const String urlPath("https://uat-public-ubiservices.ubi.com/v1/applications/{applicationId}/configuration"); const StringUrl url(urlPath.replace("{applicationId}", NS_COMMON::Options::getApplicationId().c_str())); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader())))); } } /// @test Cancels HTTP requests with various delays. TEST_P(CORE_HTTP_CANCEL, HTTPBOX_CancelHead) { TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpHead(TestHelpers_BF::getHttpTestUrl("head"), TestHelpers_BF::getHttpBoxHeader())))); } } /// @test Cancels HTTP requests with various delays. TEST_P(CORE_HTTP_CANCEL, HTTPBOX_CancelPost) { const StringUrl url(TestHelpers_BF::getHttpTestUrl("post")); TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpPost(url, TestHelpers_BF::getHttpContentHeader(), "In Soviet Russia, queries post you.")))); } } /// @test Cancels HTTP requests with various delays. /// @note Disabled on XB1/2013-08 QFE2 until further investigation /// (XHTTPRequest::Open failed: -2146697208 [0x800C0008]) /// (HttpCallback::OnError failed: 0x800C000E [INET_E_SECURITY_PROBLEM]) #if defined(US_TARGET_XONE) && (_XDK_VER >= 9837) // Fails on SDK August QFE2 TEST_P(CORE_HTTP_CANCEL, DISABLED_HTTPBOX_CancelPut) // TODO: REVIEW: Disabled for XONE #else TEST_P(CORE_HTTP_CANCEL, HTTPBOX_CancelPut) #endif { const StringUrl url(TestHelpers_BF::getHttpTestUrl("put")); TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpPut(url, TestHelpers_BF::getHttpContentHeader(), "In Soviet Russia, queries delete you.")))); } } /// @test Cancels HTTP requests with various delays. TEST_P(CORE_HTTP_CANCEL, HTTPBOX_CancelDelete) { const StringUrl url(TestHelpers_BF::getHttpTestUrl("delete")); TestCanceler<> canceler(this->getParam()); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpDelete(url, TestHelpers_BF::getHttpBoxHeader(), "In Soviet Russia, queries delete you.")))); } } /// @test Cancels HTTP requests with uninit TEST_P(CORE_HTTP_CANCEL_NO_INIT, HTTPBOX_RequestInProgressUninit) { initializeSdk(); class UninitRequestGet : public CancelRequest { public: UninitRequestGet() {} virtual ~UninitRequestGet() {} virtual AsyncResultBase launchRequest(Facade& facade) { const StringUrl url(TestHelpers_BF::getHttpTestUrl("get")); return facade.getHttpClient().sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader())); } }; { TestCanceler canceler(this->getParam()); UninitRequestGet getRequest; while (!canceler.isComplete()) { EXPECT_TRUE(canceler.cancel(getRequest)); } } uninitDefaultSDK(); } /// This case targets a problematic URL. The server is reachable but the URL /// cannot be resolved and hangs (invalid port). TEST_P(CORE_HTTP_CANCEL, HTTPBOX_RequestTimeoutHostResolvedUrlHangs) { TestConfigCancel& config = this->getParam(); config.setMaxCount(5); TestCanceler<> canceler(config); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpGet("http://msr-d-us-iis01.ubisoft.onbe:8001", TestHelpers_BF::getHttpBoxHeader())))); } } /// @test Cancels HTTP requests with various delays. /// This case targets a slow server. The server is reachable but URL takes time to answer. TEST_P(CORE_HTTP_CANCEL, HTTPBOX_RequestTimeoutHostResolvedUrlDelayAnswer) { const StringUrl url(TestHelpers_BF::getHttpTestUrl("get", "delay=5")); TestConfigCancel& config = this->getParam(); config.setMaxCount(5); TestCanceler<> canceler(config); while (!canceler.isComplete()) { Facade facade; HttpClient& client = facade.getHttpClient(); EXPECT_TRUE(canceler.cancel(client.sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader())))); } } /// @test Sends a long(delayed) request and then, send an immediate request /// The first request shall still be in progress when the second is finished TEST_F(CORE_HTTP_CLIENT, HTTPBOX_NonBlockingRequests) { Facade facade; HttpClient& client = facade.getHttpClient(); const StringUrl urlDelayed(TestHelpers_BF::getHttpTestUrl("get", "delay=10")); const StringUrl urlImmediate(TestHelpers_BF::getHttpTestUrl("get")); AsyncResult resultDelayed = client.sendRequest(HttpGet(urlDelayed, TestHelpers_BF::getHttpBoxHeader())); EXPECT_TRUE(resultDelayed.isProcessing()); US_TEST_NS::Helper::sleep(500); // Ensure the second request starts after the first one AsyncResult resultImmediate = client.sendRequest(HttpGet(urlImmediate, TestHelpers_BF::getHttpBoxHeader())); EXPECT_TRUE(resultDelayed.isProcessing()); EXPECT_TRUE(resultImmediate.wait()); EXPECT_TRUE(resultDelayed.isProcessing()); US_EXPECT_SUCCESS(resultImmediate); EXPECT_TRUE(!resultImmediate.getResult().getBodyAsString().isEmpty()); EXPECT_TRUE(resultDelayed.isProcessing()); resultDelayed.cancel(); EXPECT_TRUE(resultDelayed.wait()); EXPECT_FALSE(resultDelayed.hasSucceeded()); } /// @test Ensures that cancels are not blocking each other when several requests are pending TEST_F(CORE_HTTP_CLIENT, HTTPBOX_NonBlockingCancels) { Facade facade; HttpClient& client = facade.getHttpClient(); const StringUrl url1(TestHelpers_BF::getHttpTestUrl("get", "delay=3")); const StringUrl url2(TestHelpers_BF::getHttpTestUrl("get", "delay=5")); HighResolutionChrono chrono; chrono.resetState(); AsyncResult result1 = client.sendRequest(HttpGet(url1, TestHelpers_BF::getHttpBoxHeader())); EXPECT_TRUE(result1.isProcessing()); US_TEST_NS::Helper::sleep(500); // Ensure the second request starts after the first one AsyncResult result2 = client.sendRequest(HttpGet(url2, TestHelpers_BF::getHttpBoxHeader())); EXPECT_TRUE(result1.isProcessing()); US_TEST_NS::Helper::sleep(500); // Ensure the second request has started result1.cancel(); // The cancel shall not wait for the first request to finish EXPECT_LT(chrono.getElapsed(), ClockSteady::getNanoFromMilli(3000)); // The cancel shall not wait for the second request to finish EXPECT_TRUE(result1.wait()); EXPECT_FALSE(result1.hasSucceeded()); EXPECT_LT(chrono.getElapsed(), ClockSteady::getNanoFromMilli(5000)); // Cancel the next requests to clean the test result2.cancel(); EXPECT_TRUE(result2.wait()); } #if !defined(US_DLL) /// @test Validates that sending a request creation should not block the main thread. TEST_F(CORE_HTTP_CLIENT, HTTPBOX_NonBlockingMainThreadRequests) { Facade facade; HttpClient& client = facade.getHttpClient(); const StringUrl url(TestHelpers_BF::getHttpTestUrl("get")); const HttpGet request(url, TestHelpers_BF::getHttpBoxHeader()); const uint32 MAX_ACTIVE_CALL = InstancesManager::getInstance()->getHttpEngine().getConfiguration().getMaxActiveRequest(); Vector > responses(MAX_ACTIVE_CALL); const uint32 LOOP_COUNT = 10; for (uint32 i = 0; i < LOOP_COUNT; i++) { for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { HighResolutionChrono chrono; *it = client.sendRequest(request); #if defined(US_RETAIL) EXPECT_LT(chrono.getElapsed(), DurationNano(DurationMilli(2))); // Tolerance delay #else EXPECT_LT(chrono.getElapsed(), DurationNano(DurationMilli(15))); // Sanity check since debug/release are very inaccurate #endif // Needed to ensure the current request will have been processed before the next request starts while (!it->isProcessing()) { Helper::sleep(1); } } for(Vector >::iterator it = responses.begin(); it != responses.end(); ++it) { EXPECT_TRUE(it->wait()); } } } #if !defined(US_DLL) namespace HttpClientImpl_BF { extern uint32 s_MAX_CONCURRENT_US_CALLS; } #if !defined(US_SDK_S2S) #if defined(US_TARGET_SWITCH) // The SWITCH console requires to limit the number of concurrent HTTPS requests (custom or not). TEST_F(CORE_HTTP_PROXY_X2, HTTPBOX_MaximumRequestsPerFacade) #else TEST_F(CORE_HTTP_PROXY_X2, HTTPBOX_Win32MaximumRequestsPerFacade) #endif { const uint32 DELAY = 1; // Ensure the requests will be launched in parallel by setting a two seconds delay const StringUrl url(TestHelpers_BF::getHttpTestUrl("get", String::formatText("delay=%d", DELAY))); Vector > results; for (uint32 i = 0; i < HttpClientImpl_BF::s_MAX_CONCURRENT_US_CALLS; i++) { for (uint32 f = 0; f < getInstancesCount(); f++) { results.push_back(getFacade(f).getHttpClient().sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader()))); } } const uint32 CHECKS_PER_SECOND = 10; uint32 done = 0; #if defined(US_TARGET_SWITCH) bool maxReached = false; #endif for (int x = 0; x < ((DELAY*10)*CHECKS_PER_SECOND) && done < HttpClientImpl_BF::s_MAX_CONCURRENT_US_CALLS * getInstancesCount(); x++) { US_TEST_NS::Helper::sleep(1000/CHECKS_PER_SECOND); int delayed = 0; done = 0; for (Vector >::iterator it = results.begin(); it != results.end(); ++it) { if (AsyncResultBaseProxy::isCurrentlyDelayed(*it)) delayed++; if (it->hasSucceeded() || it->hasFailed()) done++; } #if defined(US_TARGET_SWITCH) maxReached = maxReached || (delayed == HttpClientImpl_BF::s_MAX_CONCURRENT_US_CALLS); #else // Not useful, the final ASSERT should detect when MAX_CONCURRENT not reached // ASSERT_EQ(0u, delayed); #endif } ASSERT_EQ(HttpClientImpl_BF::s_MAX_CONCURRENT_US_CALLS * getInstancesCount(), done); #if defined(US_TARGET_SWITCH) ASSERT_TRUE(maxReached); #endif } #endif #endif namespace testHttp_BF { void validateTimeOutTest(const AsyncResult& result, uint32 RETRY_COUNT, DurationMilli TIMEOUT_INTERVAL_MILLI, DurationMilli TIMEOUT_INCREMENT_MILLI) { HighResolutionChrono chrono; Vector deltas; uint32 previousCount = 0; DurationMilli startTime = ClockSteady::getTimeMilli(); while (result.isProcessing()) { const uint32 count = AsyncResultBaseProxy::getRetryCount(result); if (previousCount != count) { deltas.push_back(ClockSteady::getTimeMilli() - startTime); previousCount = count; startTime = ClockSteady::getTimeMilli(); } US_TEST_NS::Helper::sleep(100u); } result.wait(); EXPECT_FALSE(result.hasSucceeded()); EXPECT_EQ(RETRY_COUNT, static_cast(deltas.size())) << "Must match the max retry count in the parameters."; EXPECT_EQ(result.getError().m_code, Errors::HTTP_TIMEOUT) << "The final error code should be a timeout."; ASSERT_EQ(RETRY_COUNT, deltas.size()); for (uint32 i = 1; i < (RETRY_COUNT + 1); i++) { #if defined(US_TARGET_IOS) const uint32 TOLERANCE = 150u; #else const uint32 TOLERANCE = 100u; #endif EXPECT_GE(deltas.at(i - 1), TIMEOUT_INTERVAL_MILLI + (i*(i - 1)*TIMEOUT_INCREMENT_MILLI) - TOLERANCE); EXPECT_LT(deltas.at(i - 1), TIMEOUT_INTERVAL_MILLI + (i*(i - 0)*TIMEOUT_INCREMENT_MILLI) + TOLERANCE); } } } /// @test Checks that HTTP timeout is actually increased by the right value at each retry. /// In this test, the timeout parameters should be taken from the local HTTP timeout config TEST_F(CORE_HTTP_CLIENT, HTTPBOX_TestIncrementalTimeoutPerRequestConfig) { PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device) { US_EXPECT_LOG("HttpTimeoutComponent request timeout after 0 sec", LogLevel::Error, Times(1)); US_EXPECT_LOG("HttpTimeoutComponent request timeout after 1 sec", LogLevel::Error, Times(1)); US_EXPECT_LOG("HttpTimeoutComponent request timeout after 2 sec", LogLevel::Error, Times(1)); US_EXPECT_LOG("HttpTimeoutComponent request timeout after 3 sec", LogLevel::Error, Times(1)); }); Facade facade; const uint32 RETRY_COUNT = 3; const DurationMilli TIMEOUT_INTERVAL = 500u; const DurationMilli TIMEOUT_INCREMENT = 250u; HttpRetryConfig retryConfig(RETRY_COUNT, HttpRetryConfig::RetryParam(0, 0, 0), HttpRetryConfig::TimeoutParam(TIMEOUT_INTERVAL, TIMEOUT_INCREMENT)); const StringUrl url = TestHelpers_BF::getHttpTestUrl("get", "delay=1000"); //delay so high we don't care about it. testHttp_BF::validateTimeOutTest(facade.getHttpClient().sendRequest( HttpGet(url), retryConfig), RETRY_COUNT, TIMEOUT_INTERVAL, TIMEOUT_INCREMENT); } #if defined(US_TARGET_WINDOWS) /// @test Checks that HTTP timeout is actually increased by the right value at each retry /// In this test, the timeout parameters should be taken from the custom HTTP timeout config #if defined(US_SDK_S2S) || defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) /// @disabled Test disabled on S2S because the us-sdkServerSettingsHttpGame (or any server group) is not set up on the portal TEST_F(CORE_HTTP_NO_INIT, DISABLED_US_TestIncrementalTimeoutFromConfigCustom) #else TEST_F(CORE_HTTP_NO_INIT, US_TestIncrementalTimeoutFromConfigCustom) #endif { initializeSdk(); // This applicationId has the following HTTP custom config // httpParam : { // maxCount : 2, // RetryParam : { // initialDelayMsec : 0, // incrementFactorMsec : 0, // randomDelayMsec : 0 // }, // TimeoutParam : { // initialDelayMsec : 1000, // incrementFactorMsec : 1000 // } // } { const GameConfig gameConfig( ApplicationId(US_TEST_NS::APP_ID_US_SDK_SPECIAL_TESTS_PC), NS_COMMON::Options::getApplicationBuildId().c_str() #if defined(US_SDK_S2S) , NS_COMMON::Options::environment() #endif , OnlineAccessContext::Standard #if !defined(US_SDK_S2S) , GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector()) #endif ); configureSdk(gameConfig); { SmartPtr facade(US_NEW(FacadeInternal)); #if defined(US_SDK_S2S) AsyncResult resultLogin = facade->createSession(S2S_SECRET, {}, {}); #else AsyncResult resultLogin = facade->createSession(GET_CREDENTIALS(), {}, {}); #endif EXPECT_TRUE(AsyncHelper::waitSuccess(resultLogin)); const ParametersSettingsHttpGame& httpCustomParam = ParametersClientProxy::getParametersInfo(*facade).m_paramsSettingsHttpGame; const StringUrl url = TestHelpers_BF::getHttpTestUrl("get", "delay=1000"); //delay so high we don't shouldn't care about it. testHttp_BF::validateTimeOutTest(facade->getHttpClient().sendRequest(HttpGet(url)), httpCustomParam.m_maxCount, httpCustomParam.m_timeoutInitialDelayMsec.getCount(), httpCustomParam.m_timeoutIncrementFactorMsec.getCount()); } } US_TEST_NS::Helper::uninitializeSdk(); } #endif typedef ParamFixture CORE_HTTP_CLIENT_SERVICES_RETRY_CODE; INSTANTIATE_TEST_CASE_P(StatusCode, CORE_HTTP_CLIENT_SERVICES_RETRY_CODE, ::testing::Values( RestStatusCode::Error500, RestStatusCode::Error502, RestStatusCode::Error503, RestStatusCode::Error504)); /// @test Validates that request are retried when the service returns specific HTTP status codes. TEST_P(CORE_HTTP_CLIENT_SERVICES_RETRY_CODE, LOCAL_UbiServicesRetryHandler) { const uint32 MAX_RETRY_COUNT = 3; HttpRequestContext context = MockHttpRequest_BF::createDummyContext(HttpMethod::HTTP_POST, US_NEW(HttpStringEntity), US_NEW(HttpStringEntity)); context.setStatusCode(this->getParam()); const_cast(const_cast(context.getRetryHandler()).getRetryConfig()).m_retryCount = MAX_RETRY_COUNT; const HttpRetryHandler handler(context.getRetryHandler().getRetryConfig(), true); ASSERT_TRUE(handler.isValid(context)); uint32 retryCount = 0; while (handler.processRequestRetry(context)) { retryCount++; } EXPECT_EQ(retryCount, MAX_RETRY_COUNT); } /// @test No retry should be performed if the server returns a status code 503 TEST_F(CORE_HTTP, LOCAL_UbiServicesRetryHandlerRest503status5003) { const uint32 MAX_RETRY_COUNT = 3; const String restErrorBody = MockResultHelper::createRestErrorResult(RestStatusCode::Error503, 5003u).getResult().getBodyAsString(); HttpStringEntity* responseData = US_NEW(HttpStringEntity); responseData->setBody(restErrorBody); HttpRequestContext context = MockHttpRequest_BF::createDummyContext(HttpMethod::HTTP_POST, US_NEW(HttpStringEntity), responseData); const_cast(const_cast(context.getRetryHandler()).getRetryConfig()).m_retryCount = MAX_RETRY_COUNT; context.setStatusCode(RestStatusCode::Error503); const HttpRetryHandler handler(context.getRetryHandler().getRetryConfig(), true); ASSERT_TRUE(handler.isValid(context)); uint32 retryCount = 0; while (handler.processRequestRetry(context)) { retryCount++; } EXPECT_EQ(0u, retryCount) << "We shouldn't retry on a services with HTTP 503 code with a rest code 5003."; } typedef ParamFixture CORE_HTTP_CLIENT_SERVICES_NO_RETRY_CODE; INSTANTIATE_TEST_CASE_P(StatusCode, CORE_HTTP_CLIENT_SERVICES_NO_RETRY_CODE, ::testing::Values( RestStatusCode::Error400,RestStatusCode::Error401, RestStatusCode::Error402, RestStatusCode::Error403, RestStatusCode::Error404, RestStatusCode::Error405, RestStatusCode::Error407, RestStatusCode::Error409, RestStatusCode::Error413, RestStatusCode::Error414, RestStatusCode::Error418, RestStatusCode::Error429)); /// @test Validates that request are not retried when the service returns specific HTTP status codes. TEST_P(CORE_HTTP_CLIENT_SERVICES_NO_RETRY_CODE, LOCAL_UbiServicesRetryHandler) { const uint32 MAX_RETRY_COUNT = 3; HttpRequestContext context = MockHttpRequest_BF::createDummyContext(HttpMethod::HTTP_POST, US_NEW(HttpStringEntity), US_NEW(HttpStringEntity)); const_cast(const_cast(context.getRetryHandler()).getRetryConfig()).m_retryCount = MAX_RETRY_COUNT; context.setStatusCode(this->getParam()); const HttpRetryHandler handler(context.getRetryHandler().getRetryConfig(), true); ASSERT_TRUE(handler.isValid(context)); uint32 retryCount = 0; while (handler.processRequestRetry(context)) { retryCount++; } EXPECT_EQ(0u, retryCount) << "No retry is expected on the http code : " << this->getParam(); } #endif // US_DLL #if defined(US_TARGET_WINDOWS) #pragma warning(disable:4068) // unknown pragma #pragma BullseyeCoverage restore #pragma warning(default:4068) #endif };