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

697 lines
31 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#if defined(US_SDK_LIGHT_MOBILE)
#error This file shall not be part of the solution
#endif
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/mockResultHelper.h"
#include <../private/ubiservices/core/configs/environmentHelper.h>
#include <../private/ubiservices/core/helpers/instancesHelper.h>
#include <../private/ubiservices/services/parameters/parametersClientProxy.h>
#include <ubiservices/core/errors/errorCodes.h>
#include <ubiservices/services/authentication/sessionInfo.h>
#include <ubiservices/services/http/request/httpGet.h>
#include <ubiservices/services/profile/applicationUsedInfo.h>
#include <ubiservices/services/profile/profileClient.h>
#if defined(US_SDK_TEST_CHINA)
#define APP_ID_US_SDK_SPECIAL_TESTS_PC "586cc2e2-29c0-4522-8626-a1159939abe4"
#else
#define APP_ID_US_SDK_SPECIAL_TESTS_PC "bb875ed4-07a0-461e-bb33-882b4964dda1"
#endif
namespace US_NS {;
US_DEFINE_TEST(TestApplicationHistoryClient);
typedef AuthenticationFixture<1> APPLICATIONS_USED;
typedef LoginMockFixture<true> APPLICATIONS_USED_MOCK;
typedef LeakCheckerNoInit APPLICATIONS_USED_NOINIT;
#if !defined(US_DLL)
namespace ApplicationUsedInfoPrivate
{
bool extractData(const Json& source, ApplicationUsedInfo& target);
}
#if defined(US_TARGET_WINDOWS)
/// @test In UAT, data expires automatically after 3 months
/// Therefore we need to login (actually send a player start) from each profile,
/// on each applications used in the RequestApplicationsUsed test to avoid expiration.
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE)
TEST_F(APPLICATIONS_USED_NOINIT, DISABLED_US_RequestApplicationsUsedSetup)
#else
TEST_F(APPLICATIONS_USED_NOINIT, US_RequestApplicationsUsedSetup)
#endif // defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE)
{
struct Local
{
static void sendEventOnCurrentApp(const String& email, const String& password)
{
Facade facade;
// The createSession should trigger a player.start
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(PlayerCredentials(email, password), {}, {})));
// Need to wait until the event config has been retrieved in order to sendEvents.
ASSERT_TRUE(US_TEST_NS::Helper::waitForPostLogin(facade));
// The deleteSession should force sending the player.start
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
};
//expectProcessingJobsAtJobManagerDestruction();
// ussdk017 and ussdk018 connect to UbiServices SDK PC
initializeSdk();
{
const GameConfig gameConfig(
ApplicationId(US_TEST_NS::APP_ID_US_SDK_PC),
NS_COMMON::Options::getApplicationBuildId().c_str()
#if defined(US_SDK_S2S)
, NS_COMMON::Options::environment()
#endif
#if defined(US_SDK_TEST_CHINA)
, OnlineAccessContext::China
#else
, OnlineAccessContext::Standard
#endif
#if !defined(US_SDK_S2S)
, GameConfigEvent(US_SDK_VERSION_CONST_CHAR, US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>(),
"{}", NS_COMMON::Options::getApplicationSecretKey().c_str())
#endif
);
configureSdk(gameConfig);
Local::sendEventOnCurrentApp("ussdk017@ubisoft.com", "a1234567");
Local::sendEventOnCurrentApp("ussdk018@ubisoft.com", "a1234567");
}
US_TEST_NS::Helper::uninitializeSdk();
// ussdk018 and ussdk019 connect to UbiServices SDK Special Tests PC
initializeSdk();
{
const GameConfig gameConfig2(
ApplicationId(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(US_SDK_VERSION_CONST_CHAR, US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>(),
"{}", NS_COMMON::Options::getApplicationSecretKey().c_str())
#endif
);
configureSdk(gameConfig2);
//PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device) { US_EXPECT_LOG("Status code: 403", LogLevel::Error).Times(2); });
Local::sendEventOnCurrentApp("ussdk018@ubisoft.com", "a1234567");
Local::sendEventOnCurrentApp("ussdk019@ubisoft.com", "a1234567");
}
US_TEST_NS::Helper::uninitializeSdk();
}
#endif
#endif // !defined(US_DLL)
/// This test uses data that can expire after 3 months, in UAT, if the tested profiles are not "playing" the tested applications,
/// i.e. if the tested profile is not sending any player.start event from the the tested application.
/// @warning Only a few applications are monitored in UAT. You can get the list here
/// (and eventually request to activate other applications):
/// https://dna-center/Dashboard/Monitoring/TitleStateForApplicationUsedHistory
/// @warning This test should be working only in UAT. The applications tested are not monitored in other environments
/// @note For punctual tests, it is possible to configure application usage manually for a given profile.
/// https://dna-center/DnaServices/ApplicationUsedHistory/ViewPlayerApplications
/// However, these data will expire after three months. Do not use these data for automatic tests.
// TODO: Rework test after the friend's cache has been corrected.
// [US-12465] As Preparing2017, I want caches to follow the same pattern
TEST_F(APPLICATIONS_USED, DISABLED_US_RequestApplicationsUsed)
{
if (isEnvironmentNot(Environment::Uat))
{
return; // Configuration required in the environment.
}
// The following test requires proper server configuration.
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsedForAllApplications();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
// Note : Despite the tests are not run automatically on mobile platforms (and data could expire),
// the following line is still valid since the profile used on these platforms is the same as on PC and OSX
// The number of application used is always above 1.
EXPECT_LE(1u, result.getResult().size());
}
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
{
const Vector<ApplicationId> applications
{
ApplicationId("9edaaf7f-2cbf-42bc-8037-067e5bfed518"), // This is not a valid appId
ApplicationId("9edaaf7f-2cbf-42bc-8037-067e5bfed518")
};
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed(applications);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_EQ(0u, result.getResult().size());
}
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
{
const Vector<ProfileId> profiles =
{
ProfileId("d2fb4dfa-653e-4937-84e9-20b0d0622e41"), // ussdk017
ProfileId("4277e08e-ac55-4453-aafd-4bc7dc72afa8"), // ussdk018
ProfileId("c819ca41-6064-4f43-b9a1-2eb9c91a3c04") // ussdk019
};
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed({ ApplicationId(APP_ID_US_SDK_SPECIAL_TESTS_PC) }, profiles);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_EQ(2u, result.getResult().size());
}
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
{
const Vector<ProfileId> profiles =
{
ProfileId("d2fb4dfa-653e-4937-84e9-20b0d0622e41"), // ussdk017
ProfileId("4277e08e-ac55-4453-aafd-4bc7dc72afa8"), // ussdk018
ProfileId("c819ca41-6064-4f43-b9a1-2eb9c91a3c04") // ussdk019
};
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsedForAllApplications(profiles);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_EQ(4u, result.getResult().size());
}
}
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedForAllApplicationsWithModifiedResponseForForwardCompatibility)
{
const StringJson json =
"{"
" \"before\" : true,"
" \"applications\": ["
" {"
" \"profileId\": \"4d9061de-7c20-4cc9-9f55-b8d6228da6ae\","
" \"firstSessionDate\" : \"2017-10-18T18:19:35.659Z\","
" \"lastSessionDate\" : \"2017-10-18T18:19:39.778Z\","
" \"applicationId\" : \"043a4bd9-9336-4cc3-b51c-1da703f89f87\","
" \"sessionsCount\" : 4"
" },"
" {"
" \"profileId\": \"4d9061de-7c20-4cc9-9f55-b8d6228da6ae\","
" \"applicationId\" : \"085021fb-32ea-4b1c-b5c6-1dd39dc27d5f\","
" \"firstSessionDate\" : \"2016-08-01T14:56:02.255Z\","
" \"lastSessionDate\" : \"2016-08-01T15:34:07.064Z\","
" \"uselessArray\" : ["
" 1,"
" 2,"
" 3,"
" 4,"
" 5"
" ],"
" \"sessionsCount\" : 4"
" }"
" ],"
" \"other\" : 5"
"}";
HttpGet request(StringUrl(""));
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
StringStream expectedUrl;
expectedUrl << "/profiles/mock-applications";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrl.getContent())
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&request)), testing::Return(mockResult)));
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsedForAllApplications();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(2u, result.getResult().size());
}
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedWithModifiedResponseForForwardCompatibility)
{
const StringJson json =
"{"
" \"before\": true,"
" \"applications\": ["
" {"
" \"profileId\": \"4d9061de-7c20-4cc9-9f55-b8d6228da6ae\","
" \"firstSessionDate\" : \"2015-09-17T15:35:29.768Z\","
" \"lastSessionDate\" : \"2017-11-17T19:13:11.803Z\","
" \"applicationId\" : \"1521fc83-86e3-4d7b-bc64-f0b2dc2f6e89\","
" \"uselessArray\" : ["
" 1,"
" 2,"
" 3,"
" 4,"
" 5"
" ],"
" \"sessionsCount\" : 10540337"
" }"
" ],"
" \"other\" : 5"
"}";
HttpGet request(StringUrl(""));
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
StringStream expectedUrl;
expectedUrl << "/profiles/mock-allProfiles-applications";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrl.getContent())
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&request)), testing::Return(mockResult)));
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed(
Vector<ApplicationId>(), { ProfileId("4d9061de-7c20-4cc9-9f55-b8d6228da6ae") });
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
const Vector<ApplicationUsedInfo>& applicationUsedInfo = result.getResult();
ASSERT_EQ(1u, applicationUsedInfo.size());
ASSERT_EQ(ProfileId("4d9061de-7c20-4cc9-9f55-b8d6228da6ae"), applicationUsedInfo[0].m_profileId);
}
#if !defined(US_DLL)
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedFeatureSwitchOff)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("ApplicationUsed feature/service shut down by feature switch. Skipping the request.", LogLevel::Warning, Times(1));
});
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::ApplicationUsed, false);
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getProfileClient().requestApplicationsUsed(), Errors::SKIPPED_FEATURESWITCH));
}
#endif
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsed)
{
{
const StringJson jsonBody =
"{"
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"firstSessionDate\": \"2010-11-23T03:02:01.0000000\","
"\"lastSessionDate\": \"2011-01-03T04:05:06.0000000\","
"\"sessionsCount\": 440"
"}"
"]"
"}";
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
const ApplicationUsedInfo& info = result.getResult().front();
EXPECT_STREQ("9edaaf7f-2cbf-42bc-8037-067e5bfed518", static_cast<const String&>(info.m_applicationId).getUtf8());
EXPECT_EQ(DateTime(2010, 11, 23, 3, 2, 1), info.m_firstDatePlayed);
EXPECT_EQ(DateTime(2011, 1, 3, 4, 5, 6), info.m_lastDatePlayed);
EXPECT_EQ(440, info.m_sessionPlayedCount);
}
/// @test Requests Application Used parsing a JSON structure containing extra Root node.
// TODO: Rework test after the friend's cache has been corrected.
// [US-12465] As Preparing2017, I want caches to follow the same pattern
TEST_F(APPLICATIONS_USED_MOCK, DISABLED_USNOT_RequestApplicationsUsedWithExtraRootNode)
{
const StringJson jsonBody =
"{"
// Extra root node
"\"extraRootNode\":"
"["
"{"
"\"name\":\"extraItem\","
"\"quantity\" : 2"
"}"
"],"
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"firstSessionDate\": \"2010-11-23T03:02:01.0000000\","
"\"lastSessionDate\": \"2011-01-03T04:05:06.0000000\","
"\"sessionsCount\": 440"
"}"
"]"
"}";
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_EQ(1, result.getResult().size());
}
// TODO: Rework test after the application used cache has been corrected.
// [US-12465] As Preparing2017, I want caches to follow the same pattern
TEST_F(APPLICATIONS_USED_MOCK, DISABLED_USNOT_RequestApplicationsUsedWithFiltering)
{
const StringJson jsonBody =
"{"
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"firstSessionDate\": \"2010-11-23T03:02:01.0000000\","
"\"lastSessionDate\": \"2011-01-03T04:05:06.0000000\","
"\"sessionsCount\": 440"
"}"
"]"
"}";
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET,
"profiles/mock-applications?applicationIds=9edaaf7f-2cbf-42bc-8037-067e5bfed518", mockResult);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET,
"profiles/mock-allProfiles-applications?profileIds=9edaaf7f-2cbf-42bc-8037-067e5bfed518", mockResult);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET,
"profiles/mock-allProfiles-applications?profileIds=9edaaf7f-2cbf-42bc-8037-067e5bfed518&applicationIds=9edaaf7f-2cbf-42bc-8037-067e5bfed518", mockResult);
}
const Vector<ApplicationId> applications = { ApplicationId("9edaaf7f-2cbf-42bc-8037-067e5bfed518") };
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed(applications);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
const ApplicationUsedInfo& info = result.getResult().front();
EXPECT_STREQ("9edaaf7f-2cbf-42bc-8037-067e5bfed518", static_cast<const String&>(info.m_applicationId).getUtf8());
EXPECT_EQ(DateTime(2010, 11, 23, 3, 2, 1), info.m_firstDatePlayed);
EXPECT_EQ(DateTime(2011, 1, 3, 4, 5, 6), info.m_lastDatePlayed);
EXPECT_EQ(440, info.m_sessionPlayedCount);
}
const Vector<ProfileId> profiles{ ProfileId("9edaaf7f-2cbf-42bc-8037-067e5bfed518") };
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed(Vector<ApplicationId>(), profiles);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed(applications, profiles);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
}
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedErrorJsonSyntax)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Request Application History failed. Invalid JSON in response's body:", LogLevel::Error, Times(1));
});
const StringJson jsonBody =
//"{" // Intentionally missing
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"firstSessionDate\": \"2010-11-23T00:00:00.0000000\","
"\"lastSessionDate\": \"2011-01-03T00:00:00.0000000\","
"\"sessionsCount\": 440"
"}"
"]"
"}";
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getProfileClient().requestApplicationsUsed(), Errors::CORE_INVALID_JSON_FORMAT));
}
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedErrorMissingFields)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("issing mandatory field: firstSessionDate", LogLevel::Error, Times(1));
US_EXPECT_LOG("issing mandatory field: sessionsCount", LogLevel::Error, Times(1));
US_EXPECT_LOG("Unexpected JSON format. Ignoring ApplicationHistory:", LogLevel::Warning, Times(1));
});
const StringJson jsonBody =
"{"
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
//"\"firstSessionDate\": \"2010-11-23T00:00:00.0000000\"," // Intentionally missing
"\"lastSessionDate\": \"2011-01-03T00:00:00.0000000\""
//"\"sessionsCount\": 440" // Intentionally missing
"}"
"]"
"}";
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(0u, result.getResult().size()) << "Invalid record shall be ignored.";
}
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedExtraFields)
{
const StringJson jsonBody =
"{"
"\"applications\": ["
"{"
"\"profileId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"applicationId\": \"9edaaf7f-2cbf-42bc-8037-067e5bfed518\","
"\"firstSessionDate\": \"2010-11-23T00:00:00.0000000\","
"\"lastSessionDate\": \"2011-01-03T00:00:00.0000000\","
"\"sessionsCount\": 440,"
"\"daysPlayedExtra1\": 346,"// Extra field #1
"\"daysPlayedExtra2\": 346" // Extra field #2
"}"
"]"
"}";
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
/// @test Checks that an error is raised and no request is sent when only invalid applicationIds are given as parameter
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedForAllApplicationsDefaultValues)
{
HttpGet request(StringUrl(""));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-applications")
.WillOnce(testing::DoAll(
testing::SaveArg<0>(static_cast<HttpRequest*>(&request)),
testing::Return(MockResultHelper::createSuccessResult())));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getProfileClient().requestApplicationsUsedForAllApplications()));
const String query = URLInfo(request.getUrl()).getQuery();
EXPECT_EQ(String::npos, query.findSubstringCase("applicationIds="));
EXPECT_EQ(String::npos, query.findSubstringCase("profileIds="));
}
/// @test Checks that an error is raised and no request is sent when only invalid applicationIds are given as parameter
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedDefaultValues)
{
HttpGet request(StringUrl(""));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-applications")
.WillOnce(testing::DoAll(
testing::SaveArg<0>(static_cast<HttpRequest*>(&request)),
testing::Return(MockResultHelper::createSuccessResult())));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getProfileClient().requestApplicationsUsed()));
StringStream expectedAppIds;
expectedAppIds << "applicationIds=" << InstancesHelper::getApplicationId();
const String query = URLInfo(request.getUrl()).getQuery();
EXPECT_NE(String::npos, query.findSubstringCase(expectedAppIds.getContent()));
EXPECT_EQ(String::npos, query.findSubstringCase("profileIds="));
}
/// @test Checks that an error is raised and no request is sent when only invalid applicationIds are given as parameter
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedOnlyInvalidApplicationIds)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("ApplicationId 'Invalid Id #1' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("ApplicationId 'Invalid Id #2' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("No valid applicationId given to request applications used", LogLevel::Error, Times(1));
});
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-applications").Times(0);
const Vector<ApplicationId> applicationIds{ ApplicationId("Invalid Id #1"), ApplicationId("Invalid Id #2") };
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getProfileClient().requestApplicationsUsed(applicationIds), Errors::PROFILES_INVALID_PARAM));
}
/// @test Checks that an error is raised and no request is sent when only invalid profileIds are given as parameter
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedOnlyInvalidProfileIds)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("ProfileId 'Invalid Id #1' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("ProfileId 'Invalid Id #2' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("No valid profileId given to request applications used", LogLevel::Error, Times(1));
});
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-applications").Times(0);
const Vector<ProfileId> profiles = { ProfileId("Invalid Id #1"), ProfileId("Invalid Id #2") };
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getProfileClient().requestApplicationsUsed(Vector<ApplicationId>(), profiles), Errors::PROFILES_INVALID_PARAM));
}
/// @test Checks that an error is raised and no request is sent when only invalid profileIds are given as parameter
TEST_F(APPLICATIONS_USED_MOCK, USNOT_RequestApplicationsUsedForAllApplicationsOnlyInvalidProfileIds)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("ProfileId 'Invalid Id #1' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("ProfileId 'Invalid Id #2' is invalid. It is not used to request application used", LogLevel::Warning, Times(1));
US_EXPECT_LOG("No valid profileId given to request applications used", LogLevel::Error, Times(1));
});
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-allProfiles-applications").Times(0);
const Vector<ProfileId> profileIds = { ProfileId("Invalid Id #1"), ProfileId("Invalid Id #2") };
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getProfileClient().requestApplicationsUsedForAllApplications(profileIds), Errors::PROFILES_INVALID_PARAM));
}
#if !defined(US_DLL)
#define UST_STREAM_TITLE_VALUE(_stream, _title) _stream << _title << ": " << std::endl
#define UST_STREAM_FIELD_VALUE(_stream, _label, _value) _stream << _label << ": " << _value << std::endl
::std::ostream& operator<<(::std::ostream& stream, const DateTime& source)
{
StringStream ss;
ss << source;
stream << ss.getContent().getUtf8();
return stream;
}
::std::ostream& operator<<(::std::ostream& stream, const ApplicationUsedInfo& source)
{
UST_STREAM_TITLE_VALUE(stream, "ApplicationUsedInfo");
UST_STREAM_FIELD_VALUE(stream, "Profile Id", source.m_profileId);
UST_STREAM_FIELD_VALUE(stream, "Application Id", source.m_applicationId);
UST_STREAM_FIELD_VALUE(stream, "First Session Date", source.m_firstDatePlayed);
UST_STREAM_FIELD_VALUE(stream, "Last Session Date", source.m_lastDatePlayed);
UST_STREAM_FIELD_VALUE(stream, "Sessions Count", source.m_sessionPlayedCount);
return stream;
}
// TODO: Rework test after the friend's cache has been corrected.
// [US-12465] As Preparing2017, I want caches to follow the same pattern
TEST_F(APPLICATIONS_USED_MOCK, DISABLED_USNOT_RequestApplicationsUsedCache)
{
SAVE_ALLOC_COUNT(count);
JsonWriter writer;
ApplicationUsedInfo appUsedInfo;
EXPECT_ALLOC_COUNT_PC_EQ(5, count);
{
JsonWriter appUsed;
EXPECT_ALLOC_COUNT_PC_EQ(3, count);
appUsed["profileId"] = "9edaaf7f-2cbf-42bc-8037-067e5bfed518";
appUsed["applicationId"] = "9edaaf7f-2cbf-42bc-8037-067e5bfed518";
appUsed["firstSessionDate"] = "2010-11-23T03:02:01.0000000";
appUsed["lastSessionDate"] = "2011-01-03T04:05:06.0000000";
appUsed["sessionsCount"] = 440;
ASSERT_TRUE(ApplicationUsedInfoPrivate::extractData(appUsed.getJson(), appUsedInfo));
EXPECT_ALLOC_COUNT_PC_EQ(78, count);
writer["applications"] = Vector<Json>({ appUsed.getJson() });
}
{
const String jsonBody = writer.renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
// Second call should not send request
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
// Invalidating the cache should trigger request send
//getFacade().getProfileClient().invalidateCacheApplicationUsed();
SAVE_ALLOC_COUNT(count2);
JsonWriter writer2;
ApplicationUsedInfo appUsedInfo2;
EXPECT_ALLOC_COUNT_PC_EQ(5, count2);
{
JsonWriter appUsed;
EXPECT_ALLOC_COUNT_PC_EQ(3, count2);
appUsed["profileId"] = "1111aaaa-1111-1111-1111-aaaabbbbcccc";
appUsed["applicationId"] = "9edaaf7f-2cbf-42bc-8037-067e5bfed518";
appUsed["firstSessionDate"] = "2010-11-23T03:02:01.0000000";
appUsed["lastSessionDate"] = "2011-01-03T04:05:06.0000000";
appUsed["sessionsCount"] = 23;
ASSERT_TRUE(ApplicationUsedInfoPrivate::extractData(appUsed.getJson(), appUsedInfo2));
EXPECT_ALLOC_COUNT_PC_EQ(78, count2);
writer2["applications"] = Vector<Json>({ appUsed.getJson() });
}
const String jsonBody2 = writer2.renderContent();
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody2);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles/mock-applications", mockResult);
}
{
const AsyncResult<Vector<ApplicationUsedInfo> > result = getFacade().getProfileClient().requestApplicationsUsed();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(1u, result.getResult().size());
}
}
#endif
};
#undef APP_ID_US_SDK_SPECIAL_TESTS_PC