JD2022-TU1/main/extern/UbiServices/custom/testsIntegration/testTLogClient.cpp

1081 lines
43 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Technology Group //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#if defined(US_SDK_FULL) || defined(US_SDK_S2S)
#include <gmock/gmock-spec-builders.h>
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/mock/MockHttpClientImpl.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/mockResultHelper.h"
#include "tests/mock/parametersMockHelper.h"
#include <ubiservices/core/errors/errorDetails.h>
#include <ubiservices/facade.h>
#include <ubiservices/services/http/request/httpPost.h>
#include <ubiservices/services/parameters/parametersClient.h>
#include <ubiservices/services/secondaryStore/secondaryStoreClient.h>
#include <ubiservices/services/tLog/tLog.h>
#include <ubiservices/services/tLog/tLogClient.h>
#if defined(US_TARGET_PS4)
#include "usCommon/ps4/firstPartyInit.h"
#elif defined(US_TARGET_SWITCH)
#include "usCommon/nnx/firstPartyInit.h"
#elif defined(US_TARGET_YETI)
#include "usCommon/yeti/firstPartyInit.h"
#elif defined(US_TARGET_KILI)
#include "usCommon/kili/firstPartyInit.h"
#endif
#include <../private/ubiservices/core/encoding/md5.h>
#include <../private/ubiservices/services/parameters/featureSwitch.h>
#include <../private/ubiservices/services/parameters/parametersClientProxy.h>
namespace US_NS {;
US_DEFINE_TEST(TestTLogClient);
#if !defined (US_DLL)
namespace TestTLog_BF
{
static const char* const TLOG_APP_ID_USSDK = "1004740";
static const char* const TLOG_APP_NAME_USSDK = "Ubisoft HarbourSdkTests";
static const char* const TLOG_MOCKED_APP_KEY_USSDK = "11112222";
static const uint32 MD5_HASH_STRING_SIZE = 32;
static const uint32 TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS = 2000;
static const uint32 MAX_QUEUE_SIZE = 1000;
static const uint32 MAX_TLOG_PER_REQUEST = 10;
struct CustomTLogMockFixtureBase : public LoginMockFixtureNoInit
{
template<typename _TTestInstance>
class ScopedInitCustom final
{
public:
ScopedInitCustom(_TTestInstance& testInstance)
: m_testInstance(testInstance)
{
initializeSdk();
}
~ScopedInitCustom()
{
m_testInstance.uninitDefaultSDK();
}
private:
_TTestInstance& m_testInstance;
};
};
static ConfigureResult initSdkForChinaContext(bool forceOnlineContextToStandard = false)
{
ApplicationId chinaPcAppId("586cc2e2-29c0-4522-8626-a1159939abe4");
String chinaPcBuildId("CHINA_IS_PROD");
OnlineAccessContext onlineContext(OnlineAccessContext::China);
if (forceOnlineContextToStandard)
{
onlineContext = OnlineAccessContext::Standard;
}
#if defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
GameConfigConsole configConsole(NS_COMMON::FIRSTPARTY_APP_ID, NS_COMMON::CLIENT_ID, NS_COMMON::STORE_SERVICE_LABEL);
#elif defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP)
GameConfigConsole configConsole(NS_COMMON::FIRSTPARTY_APP_ID);
#endif
#if defined(ENABLE_PROXY_SETTINGS_TEST)
US_NS::HttpConfig httpConfig;
httpConfig.m_proxy.m_host = "127.0.0.1"; // Fiddler proxy port
httpConfig.m_proxy.m_port = 8888; // Fiddler proxy port
httpConfig.m_proxy.m_username = "username";
httpConfig.m_proxy.m_username = "password";
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
#else
const US_NS::HttpConfig httpConfig;
#endif
GameConfig gameConfig = GameConfig(
chinaPcAppId,
chinaPcBuildId,
onlineContext,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>(), {},
NS_COMMON::Options::getApplicationSecretKey().c_str())
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
, configConsole
#endif
);
const SystemConfig systemConfig(US_NS::ThreadingConfig(), httpConfig);
return configureSdk(gameConfig, systemConfig);
}
String renderValidTLogResponse()
{
JsonWriter responseWriter;
{
JsonWriter writer;
writer["app_id"] = TLOG_APP_ID_USSDK;
writer["app_name"] = TLOG_APP_NAME_USSDK;
writer["timestamp"] = 1544129254;
writer["seq_id"] = 1;
writer["retry_times"] = 0;
writer["key_x"] = 1;
writer["key_y"] = "y";
responseWriter["title"] = writer.getJson();
}
{
JsonWriter writer;
writer["code"] = 200;
writer["msg"] = "OK";
responseWriter["data"] = writer.getJson();
}
return responseWriter.renderContent();
}
String renderInvalidTLogResponse()
{
JsonWriter responseWriter;
{
JsonWriter writer;
writer["app_id"] = TLOG_APP_ID_USSDK;
writer["app_name"] = TLOG_APP_NAME_USSDK;
writer["timestamp"] = 1544129254;
writer["seq_id"] = 1;
writer["retry_times"] = 0;
writer["key_x"] = 1;
writer["key_y"] = "y";
responseWriter["title"] = writer.getJson();
}
// Invalid response is missing "data"
return responseWriter.renderContent();
}
String renderTLogResponseWithDataErrorCode(int errorCode)
{
JsonWriter responseWriter;
{
JsonWriter writer;
writer["app_id"] = TLOG_APP_ID_USSDK;
writer["app_name"] = TLOG_APP_NAME_USSDK;
writer["timestamp"] = 1544129254;
writer["seq_id"] = 1;
writer["retry_times"] = 0;
writer["key_x"] = 1;
writer["key_y"] = "y";
responseWriter["title"] = writer.getJson();
}
{
JsonWriter writer;
writer["code"] = errorCode;
writer["msg"] = "Error Message";
responseWriter["data"] = writer.getJson();
}
return responseWriter.renderContent();
}
uint32 countOccurrenceOfTLog(const String& bodyData)
{
size_t foundAtPos = 0;
uint32 occurrenceCount = 0;
String tempBody(bodyData);
String logNameTag("log_name");
do
{
foundAtPos = tempBody.findSubstringNoCase(logNameTag);
if (foundAtPos != -1)
{
occurrenceCount++;
tempBody = tempBody.substr(foundAtPos + logNameTag.getLength(), tempBody.getLength());
}
} while (foundAtPos != -1);
return occurrenceCount;
}
void validateTLogRequest(HttpPost& request, const Vector<String>& expectedLogsName)
{
String body(request.getBodyAsString());
PRINT_LINE("Request Body: %s", body.getUtf8());
auto numTLogsInRequest = countOccurrenceOfTLog(body);
EXPECT_EQ(numTLogsInRequest, expectedLogsName.size());
for (const String& expectedLog : expectedLogsName)
{
PRINT_LINE("Search for [%s] in TLogs", expectedLog.getUtf8());
EXPECT_TRUE(body.findSubstringNoCase(expectedLog) != -1);
}
}
};
typedef AuthenticationFixture<> TLOGCLIENT;
typedef LeakChecker TLOGCLIENT_NOLOGIN;
typedef LeakCheckerNoInit TLOGCLIENT_NO_INIT;
typedef LoginMockFixtureNoInit TLOGCLIENT_MOCK_NOINIT;
typedef TestTLog_BF::CustomTLogMockFixtureBase TLOGCLIENT_MOCK_NOINIT_CUSTOM;
#if defined(US_SDK_TEST_CHINA)
TEST_F(TLOGCLIENT_NO_INIT, US_MINRUN_TestSendLogSuccess)
{
const US_TEST_NS::ScopedInit autoInit;
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
// Perform the login
const String sessionRailId(US_TEST_NS::WEGAME_SESSION_ID);
const US_NS::String playerRailId(US_TEST_NS::WEGAME_PROFILE_RAIL_ID);
const String gameRailId(US_TEST_NS::WEGAME_GAME_RAIL_ID);
const String weGameToken(CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, CredentialsType::WeGame, playerRailId);
Facade facade;
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(credentials, {}, {})));
TestHelpers_BF::waitForPostLoginCompletion(facade);
TLogClient& tLogClient = facade.getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
{
TLog tLog("itemPurchased");
tLog.addField("key_3", "value_3");
tLog.addField("key_4", 4);
tLog.addField("key_5", 5);
// UTF-8 Chinese char are 3 bytes
// Ex: '中' is 0xE4B8AD while 'A' is 0x41
// Below translated text: Chinese (Traditional)
tLog.addField("key_6", L"中国語 (繁体)");
tLogClient.sendLog(tLog);
}
{
// With chars to be escaped
TLog tLog("gameStop");
tLog.addField("key_7", "value|7");
tLog.addField("key_8", "value&8");
tLog.addField("key_9", "value=9");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#endif
// Send a TLog that succeed
// Validate Request Headers and Body content
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_ValidateTLogRequestHeadersAndBodyContent)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_ValidateTLogRequestHeadersAndBodyContent_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
// UTF-8 Chinese char are 3 bytes
// Ex: '中' is 0xE4B8AD while 'A' is 0x41
// Below translated text: Chinese (Traditional)
tLog.addField("key_2", L"中国語 (繁体)");
// Add dtEventTime here so it never change.
// This allow us to calculate MD5 signature.
// Note the T is datetime will be remove in redering !
tLog.addField("dtEventTime", "2018-01-01T12:01:02");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
// Validate Headers
const HttpHeader headers = requestSendTLog.getAllHeader();
EXPECT_EQ(headers.getHeaderCount(), 3);
EXPECT_EQ("application/json", headers.getValue("Content-Type"));
EXPECT_EQ("1.0", headers.getValue("version"));
// Validate Body content
Json bodyJson(requestSendTLog.getBodyAsString());
PRINT_LINE("Request Body: %s", bodyJson.renderContent().getUtf8());
ASSERT_EQ(bodyJson.getItemsCount(), 2);
// Validate MD5 Signature
MD5 md5;
// MD5 Signature is made of body content + TLog Application Key
const String messageAndKey(bodyJson.renderContent() + TestTLog_BF::TLOG_MOCKED_APP_KEY_USSDK);
PRINT_LINE("Message+AppKey = %s", messageAndKey.getUtf8());
md5.add(messageAndKey.getUtf8(), messageAndKey.getLength());
String md5Signature(md5.getHash().c_str());
// Typical MD5 Hash: 01a7595dd47529f388360d0498718d2c
const String& signatureInHeader(headers.getValue("signature"));
EXPECT_EQ(TestTLog_BF::MD5_HASH_STRING_SIZE, signatureInHeader.getLength());
EXPECT_EQ(md5Signature, signatureInHeader);
// Title
EXPECT_EQ(TestTLog_BF::TLOG_APP_ID_USSDK, bodyJson["title"]["app_id"].getValueString());
EXPECT_EQ(TestTLog_BF::TLOG_APP_NAME_USSDK, bodyJson["title"]["app_name"].getValueString());
EXPECT_TRUE(bodyJson["title"]["timestamp"].getValueDouble() != 0);
EXPECT_EQ(0, bodyJson["title"]["seq_id"].getValueInteger());
EXPECT_EQ(0, bodyJson["title"]["retry_time"].getValueInteger());
// Data
const Vector<Json> tLogs = bodyJson["data"].getItems();
ASSERT_EQ(1, tLogs.size());
EXPECT_EQ("gameStart", tLogs[0]["log_name"].getValueString());
#if defined(US_SDK_TEST_CHINA)
String dataContent(L"key_1=1&key_2=中国語 (繁体)&dtEventTime=2018-01-01 12:01:02&serverID=0&clientIP=127.0.0.1&rail_id=");
dataContent += US_TEST_NS::WEGAME_PROFILE_RAIL_ID;
#else
String dataContent(L"key_1=1&key_2=中国語 (繁体)&dtEventTime=2018-01-01 12:01:02&serverID=0&clientIP=127.0.0.1&rail_id=");
#endif
EXPECT_EQ(dataContent, tLogs[0]["log_fields"].getValueString());
}
}
// Send a first TLog that succeed
// Send a second TLog that also succeed, validating there is only this second TLog in the request body.
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsSuccess)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsSuccess_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStop" });
}
}
// Send a first TLog that fails
// Send a second TLog that succeed, validating there is two TLog in the second request body.
// Send a third TLog that succeed, validating only the 3rd TLog is in the request body.
// If first call fails, first TLog is put back in the queue
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsFailsFirstCall)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsFailsFirstCall_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
const MockAsyncResult mockResultFailed = MockResultHelper::createErrorResult(ErrorDetails());
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultFailed)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
// First call fails
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
// Second call succeed
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart", "gameStop" });
// Third call also succeed
// Will only contain this TLog
{
TLog tLog("playerStart");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "playerStart" });
}
}
// Send a first TLog that receive invalid Data Json in response
// Send a second TLog that succeed, validating there is two TLog in the second request body.
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsInvalidResponseDataJson)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsInvalidResponseDataJson_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const String mockResponseInvalidJson = TestTLog_BF::renderInvalidTLogResponse();
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponseInvalidJson);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultFailed)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
// First call fails
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
// Second call succeed
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart", "gameStop" });
}
}
// Send a first TLog that receive a Data error code that is not success
// Send a second TLog that succeed, validating there is two TLog in the second request body.
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsWithDataErrorCodeNotSuccess)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsWithDataErrorCodeNotSuccess_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const String mockResponseDataErrorCode = TestTLog_BF::renderTLogResponseWithDataErrorCode(405);
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponseDataErrorCode);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultFailed)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
// First call fails
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
// Second call succeed
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart", "gameStop" });
}
}
// Send a first TLog that receive a Data error code that is not success (1001)
// Error 1001 result is flushing the active queue since there is invalid data in it
// Send a second TLog that succeed, validating there is only one TLog in the second request body.
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsWithDataErrorCode1001)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsWithDataErrorCode1001_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const String mockResponseDataErrorCode = TestTLog_BF::renderTLogResponseWithDataErrorCode(1001);
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponseDataErrorCode);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultFailed)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
// First call fails
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
// Second call succeed
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
// gameStart was flushed because of error 1001
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStop" });
}
}
// Send a first TLog that receive a Data error code that is not success (1002)
// Error 1002 result is flushing the active queue since there is invalid data in it
// Send a second TLog that succeed, validating there is one TLog in the second request body.
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestSendTLogsWithDataErrorCode1002)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestSendTLogsWithDataErrorCode1002_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String mockResponse = TestTLog_BF::renderValidTLogResponse();
const String mockResponseDataErrorCode = TestTLog_BF::renderTLogResponseWithDataErrorCode(1002);
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult(mockResponse);
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponseDataErrorCode);
HttpPost requestSendTLog((StringUrl()), String());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultFailed)))
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestSendTLog)), testing::Return(mockResultSuccess)));
// First call fails
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStart" });
// Second call succeed
{
TLog tLog("gameStop");
tLog.addField("key_1", 1);
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
// gameStart was flushed because of error 1001
TestTLog_BF::validateTLogRequest(requestSendTLog, Vector<String>{ "gameStop" });
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestFeatureSwitchOff)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestFeatureSwitchOff_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
const FeatureSwitchId FEATURE_ID = FeatureSwitchId::TLog;
{
const MockAsyncResult parametersSpaceMock = MockResultHelper::createSuccessResult(
ParametersSpaceMockHelper().changeFeatureSwitch(FEATURE_ID, FeatureSwitchState::Disabled).getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(nullptr, nullptr, &parametersSpaceMock);
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FEATURE_ID));
}
// Make sure call will not occurs
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog").Times(0);
// Call will not occurs, feature sw is off
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestApplicationParameterTLogAppIdMissing)
{
class ParametersApplicationMockNoChinaGroup : public ParametersApplicationMockHelper
{
public:
ParametersApplicationMockNoChinaGroup() {}
protected:
Json buildParameterGroupSdkClientChina() const override
{
JsonWriter fields;
//fields["tLogApplicationId"] = TestTLog_BF::TLOG_APP_ID_USSDK;
fields["tLogApplicationName"] = TestTLog_BF::TLOG_APP_NAME_USSDK;
fields["tLogApplicationKey"] = TestTLog_BF::TLOG_MOCKED_APP_KEY_USSDK;
return renderParameterGroup(fields.getJson());
}
};
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestApplicationParameterTLogAppIdMissing_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
const auto parametersApplicationMock = MockResultHelper::createSuccessResult(
ParametersApplicationMockNoChinaGroup().getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(nullptr, &parametersApplicationMock);
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Make sure call will not occurs
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog").Times(0);
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestApplicationParameterTLogAppNameMissing)
{
class ParametersApplicationMockNoChinaGroup : public ParametersApplicationMockHelper
{
public:
ParametersApplicationMockNoChinaGroup() {}
protected:
Json buildParameterGroupSdkClientChina() const override
{
JsonWriter fields;
fields["tLogApplicationId"] = TestTLog_BF::TLOG_APP_ID_USSDK;
//fields["tLogApplicationName"] = TestTLog_BF::TLOG_APP_NAME_USSDK;
fields["tLogApplicationKey"] = TestTLog_BF::TLOG_MOCKED_APP_KEY_USSDK;
return renderParameterGroup(fields.getJson());
}
};
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestApplicationParameterTLogAppNameMissing_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
const auto parametersApplicationMock = MockResultHelper::createSuccessResult(
ParametersApplicationMockNoChinaGroup().getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(nullptr, &parametersApplicationMock);
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Make sure call will not occurs
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog").Times(0);
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestApplicationParameterTLogAppKeyMissing)
{
class ParametersApplicationMockNoChinaGroup : public ParametersApplicationMockHelper
{
public:
ParametersApplicationMockNoChinaGroup() {}
protected:
Json buildParameterGroupSdkClientChina() const override
{
JsonWriter fields;
fields["tLogApplicationId"] = TestTLog_BF::TLOG_APP_ID_USSDK;
fields["tLogApplicationName"] = TestTLog_BF::TLOG_APP_NAME_USSDK;
//fields["tLogApplicationKey"] = TestTLog_BF::TLOG_MOCKED_APP_KEY_USSDK;
return renderParameterGroup(fields.getJson());
}
};
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestApplicationParameterTLogAppKeyMissing_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
{
const auto parametersApplicationMock = MockResultHelper::createSuccessResult(
ParametersApplicationMockNoChinaGroup().getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(nullptr, &parametersApplicationMock);
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Make sure call will not occurs
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog").Times(0);
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
tLogClient.sendLog(tLog);
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); // Should be sufficient for the last send to be finished
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestQueueSizeMaxLimit)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestQueueSizeMaxLimit_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
setupWebsocketMock();
mockFullLogin();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const String mockResponse = TestTLog_BF::renderInvalidTLogResponse();
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponse);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(mockResultFailed));
TLogClient& tLogClient = getFacade().getTLogClient();
for(uint32 i=0; i < TestTLog_BF::MAX_QUEUE_SIZE * 3; ++i)
{
TLog tLog("gameStart");
tLog.addField("key", i);
if (!tLogClient.sendLog(tLog))
{
EXPECT_GE(i, TestTLog_BF::MAX_QUEUE_SIZE);
// 1000 + 10 (10 were pushed back in queue because request fails)
EXPECT_LE(i, TestTLog_BF::MAX_QUEUE_SIZE + TestTLog_BF::MAX_QUEUE_SIZE);
break;
}
}
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestQueueSizeMaxLimitFilteringNonImportant)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestQueueSizeMaxLimitFilteringNonImportant_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
setupWebsocketMock();
mockFullLogin();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const String mockResponse = TestTLog_BF::renderInvalidTLogResponse();
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponse);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(mockResultFailed));
TLogClient& tLogClient = getFacade().getTLogClient();
{
TLog tLog("NonImportant", TLogLevel::Unimportant);
tLog.addField("key", 0);
EXPECT_TRUE(tLogClient.sendLog(tLog));
}
for (uint32 i = 0; i < TestTLog_BF::MAX_QUEUE_SIZE-1; ++i)
{
TLog tLog("gameStart", TLogLevel::Important);
tLog.addField("key", i);
EXPECT_TRUE(tLogClient.sendLog(tLog));
// Due to timing and how fast response is being treated
// This allow us to have enough attempt on the unimportant TLog
if (i % 100 == 0)
{
US_TEST_NS::Helper::sleep(50);
}
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); //Give enough time to have everything in queue and processed
{
//The non important is removed from the filtering
TLog tLog("tLogRemovingNonImportant", TLogLevel::Important);
tLog.addField("key", 1012);
EXPECT_TRUE(tLogClient.sendLog(tLog));
}
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestQueueSizeMaxLimitFilteringImportant)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestQueueSizeMaxLimitFilteringImportant_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
setupWebsocketMock();
mockFullLogin();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const String mockResponse = TestTLog_BF::renderInvalidTLogResponse();
const MockAsyncResult mockResultFailed = MockResultHelper::createSuccessResult(mockResponse);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(mockResultFailed));
TLogClient& tLogClient = getFacade().getTLogClient();
for (uint32 i = 0; i < TestTLog_BF::MAX_QUEUE_SIZE ; ++i)
{
TLog tLog("gameStart", TLogLevel::Important);
tLog.addField("key", i);
EXPECT_TRUE(tLogClient.sendLog(tLog));
}
US_TEST_NS::Helper::sleep(TestTLog_BF::TIME_REQUIRED_FOR_JOB_TO_COMPLETE_MS); //Give enough time to have everything in queue and processed
for(uint32 i = 0; i < 5; ++i)
{
//Only important TLog exists, none will be removed
TLog tLog("tLogImportant", TLogLevel::Important);
tLog.addField("key", i);
EXPECT_FALSE(tLogClient.sendLog(tLog));
}
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_TestLogNotQueuedSessionNotValid)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_TestLogNotQueuedSessionNotValid_Test> autoInit(*this);
{
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext());
SetUpAfterInit();
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog")
.Times(0);
TLogClient& tLogClient = getFacade().getTLogClient();
TLog tLog("gameStart");
tLog.addField("key", "value");
EXPECT_FALSE(tLogClient.sendLog(tLog));
}
}
TEST_F(TLOGCLIENT_MOCK_NOINIT_CUSTOM, USNOT_ValidateTLogNotSentInOnlineContextStandard)
{
ScopedInitCustom<TLOGCLIENT_MOCK_NOINIT_CUSTOM_USNOT_ValidateTLogNotSentInOnlineContextStandard_Test> autoInit(*this);
{
bool forceOnlineContextToStandard = true;
ASSERT_EQ(ConfigureResult::Success, TestTLog_BF::initSdkForChinaContext(forceOnlineContextToStandard));
SetUpAfterInit();
{
setupWebsocketMock();
mockFullLogin();
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-tLog").Times(0);
TLogClient& tLogClient = getFacade().getTLogClient();
TLog tLog("gameStart");
tLog.addField("key_1", 1);
tLog.addField("key_2", "value_2");
EXPECT_FALSE(tLogClient.sendLog(tLog));
}
}
#endif // !defined (US_DLL)
};
#endif // defined(US_SDK_FULL)