697 lines
31 KiB
C++
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
|