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

3238 lines
163 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#include "tests/common/configs.h"
#include "tests/common/helpers.h"
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/fixture/memoryCheckFixture.h"
#include "tests/mock/parametersMockHelper.h"
#include "tests/mock/mockResultHelper.h"
#include "tests/mock/MockHttpClientImpl.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/parametersMockHelper.h"
#include "testsUnit/helpers/ubiservicesSdkStateManagerProxy.h"
#include "testsIntegration/event/eventsConfigMockHelper.h"
#if !defined(US_SDK_LIGHT_MOBILE)
#include "testsIntegration/notificationHelper.h"
#endif
#if defined(US_SDK_FULL)
#include "testsIntegration/storeHelper.h"
#endif
#include <ubiservices/services/authentication/authenticationClient.h>
#include <../private/ubiservices/core/debug/assert.h>
#include <ubiservices/core/errors/errorDetails.h>
#include <../private/ubiservices/core/chrono/chronometer.h>
#include <../private/ubiservices/core/configs/environmentHelper.h>
#include <../private/ubiservices/core/configs/platformName.h>
#include <../private/ubiservices/core/extensions/enumeration.h>
#include <ubiservices/core/notifications/notificationSource.h>
#include <ubiservices/core/types/dateTimeHelper.h>
#include <ubiservices/facade.h>
#include <ubiservices/platformHelper.h>
#include <../private/ubiservices/platformHelperProxy.h>
#include <ubiservices/services/authentication/sessionInfo.h>
#include <../private/ubiservices/services/cacheManager.h>
#include <ubiservices/services/club/actionsGroup.h>
#include <ubiservices/services/club/clubClient.h>
#include <ubiservices/services/event/eventClient.h>
#include <ubiservices/services/event/eventNotification.h>
#include <ubiservices/services/event/types/eventInfoContextStart.h>
#include <ubiservices/services/event/types/eventInfoContextStop.h>
#include <ubiservices/services/event/types/eventInfoCustom.h>
#include <ubiservices/services/http/httpClient.h>
#include <ubiservices/services/http/httpMethod.h>
#include <ubiservices/services/http/request/httpGet.h>
#include <ubiservices/services/http/request/httpPost.h>
#include <ubiservices/services/news/newsClient.h>
#include <ubiservices/services/notification/notificationClient.h>
#include <ubiservices/services/notification/notificationOutgoing.h>
#if !defined(US_DLL)
#include <../private/ubiservices/services/notification/notificationClientProxy.h>
#endif
#include <ubiservices/services/parameters/featureSwitchId.h>
#include <ubiservices/services/parameters/parametersClient.h>
#include <../private/ubiservices/services/parameters/parametersClientProxy.h>
#include <../private/ubiservices/services/parameters/parametersInfo.h>
#include <ubiservices/services/parameters/parametersNotification.h>
#include <ubiservices/services/populations/populationClient.h>
#include <ubiservices/services/profile/profileClient.h>
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
#include <ubiservices/services/remoteLog/remoteLogClient.h>
#include <ubiservices/services/remoteLog/remoteLog.h>
#endif
#include <ubiservices/services/primaryStore/primaryStoreClient.h>
#include <ubiservices/services/secondaryStore/secondaryStoreClient.h>
#include <ubiservices/services/secondaryStore/secondaryStoreNotification.h>
#include <../private/ubiservices/services/secondaryStore/sessionManagerStoreProxy.h>
#include <../private/ubiservices/ubiServicesSdkStateInternal.h>
#include <ubiservices/core/types/dateTimeHelper.h>
#if defined(US_TARGET_XONE)
#if defined(US_XONE_USE_XSAPI_CPP)
#include <xsapi/services.h>
#else
#include "ubiservices/core/tasks/xone/xboxLiveContext.h"
#endif
#endif
#if defined(US_TARGET_SWITCH)
#include <nn/oe.h>
#endif
#include <usCommon/authenticationHelper.h>
#include <usCommon/firstPartyInit.h>
namespace US_NS {;
US_DEFINE_TEST(TestSuspendedMode);
#define UPLAYPC_DUMMY_DLCID "dummyUplayPcItemId"
#define UPLAYPC_DUMMY_CONSUMABLEID "dummyUplayPcConsumableId"
#if defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
const char* const APP_ID_SHORT_EXPIRATION = "d2943775-5ae7-46bd-b871-819f01ae64eb"; //Short Expiration PS4
#elif !defined(US_TARGET_OSX) && !defined(US_TARGET_ANDROID_VS) && !defined(US_TARGET_LINUX) && !defined(US_TARGET_GGP)
const char* const APP_ID_SHORT_EXPIRATION = "8700c8f7-c538-4ee4-8dfb-1d5650bd66ed"; //Short Expiration PC
#endif
#if !defined(US_DLL)
namespace TestPrimaryStoreClient_BF
{
String renderPrimaryStoreMapping();
#if defined(US_PRIMARY_STORE_WITHOUT_API) && !defined(US_DLL)
Vector<PrimaryStoreInventoryItem> getInventoryWithItemsForRetrySyncTrigger(uint32 balance);
#endif
};
namespace TestPrimarySecondaryStoreSync_BF
{
#if !defined(US_SDK_LIGHT_MOBILE) && !defined(US_DLL)
bool waitForNotification(ListenerHandler<SecondaryStoreNotification>& handler, SecondaryStoreNotificationType eventNotificationType, const DurationNano& waitTimeMax);
Vector<SecondaryStoreNotification> getSyncSuccessNotifications(ListenerHandler<SecondaryStoreNotification>& handler, const DurationNano& waitTimeMax);
#endif
};
namespace TestSuspendedMode_EX
{
bool areAllCachesInvalid(FacadeInternal& facade)
{
return
#if defined(US_ENABLE_CLUB)
!CacheManager::isCacheValid(facade, CacheUnit::ClubBadges) &&
!CacheManager::isCacheValid(facade, CacheUnit::ClubActions) &&
!CacheManager::isCacheValid(facade, CacheUnit::ClubRewards) &&
//!CacheManager::isCacheValid(facade, CacheUnit::ClubChallenges) && // TODO: Is this cache missing?
#endif
!CacheManager::isCacheValid(facade, CacheUnit::Friends) &&
!CacheManager::isCacheValid(facade, CacheUnit::ProfileApplicationUsed) &&
// ProfilePopulations gets filled because there is call to population in JobResume[...], so cache IS valid !
//!CacheManager::isCacheValid(facade, CacheUnit::ProfilePopulations) &&
#if defined(US_SDK_FULL)
!CacheManager::isCacheValid(facade, CacheUnit::StoreAttributesAll) &&
!CacheManager::isCacheValid(facade, CacheUnit::StoreRulesAll) &&
!CacheManager::isCacheValid(facade, CacheUnit::StoreListsOfAttributesAll) &&
#endif
!CacheManager::isCacheValid(facade, CacheUnit::NewsProfile) &&
!CacheManager::isCacheValid(facade, CacheUnit::NewsSpace);
}
void spinDelay(const uint32 delayMsec)
{
HighResolutionChrono chrono;
const uint64 delayNSec = ClockSteady::getNanoFromMilli(delayMsec);
while (chrono.getElapsed() < delayNSec)
{
// do nothing !!!
#if defined(US_TARGET_SWITCH) // TODO_NNX (The test fails otherwise... thread starving?)
Helper::sleep(1);
#endif
}
}
};
#endif
typedef LeakCheckerNoInit SUSPENDEDMODE_NOINIT;
typedef AuthenticationFixture<1> SUSPENDEDMODE;
typedef LoginMockFixture<true> SUSPENDEDMODE_MOCK_LOGIN;
typedef LoginMockFixture<false> SUSPENDEDMODE_MOCK_NOLOGIN;
namespace TestSuspendedMode_BF
{
const DurationMilli MOCK_PERIOD_JOB_WAIT_TIME = 3500;
bool waitForEventNotification(ListenerHandler<EventNotification>& handler, EventNotificationType eventNotificationType, bool mockWait)
{
class Condition : public US_TEST_NS::Helper::ConditionTemplate
{
public:
Condition(ListenerHandler<EventNotification>& handler, EventNotificationType eventNotificationType)
: m_notification(AuthenticationNotificationType::None)
, m_listener(handler)
, m_eventNotificationType(eventNotificationType)
{
}
bool operator()() const
{
return (m_listener.isNotificationAvailable() && m_listener.popNotification().m_type == m_eventNotificationType);
}
mutable AuthenticationNotificationType m_notification;
private:
//US_CLASS_COPY_NOT_ALLOWED(Condition)
Condition(const Condition& dummy) : m_listener(dummy.m_listener), m_eventNotificationType(dummy.m_eventNotificationType) {}
Condition& operator=(Condition&) { return *this; }
ListenerHandler<EventNotification>& m_listener;
const EventNotificationType m_eventNotificationType;
} condition(handler, eventNotificationType);
US_ASSERT(eventNotificationType != EventNotificationType::None, "Impossible expectation by design");
const ClockSteady::TTimeMilli waitTimeMax = mockWait
? MOCK_PERIOD_JOB_WAIT_TIME * 4
: NS_COMMON::DEFAULT_WAIT_TIME;
return US_TEST_NS::Helper::WaitFor(condition, 5ull, waitTimeMax, "event notification");
}
AuthenticationNotificationType waitForExtendSessionNotification(ListenerHandler<AuthenticationNotification>& listener, DurationNano waitTime)
{
class Condition : public US_TEST_NS::Helper::ConditionTemplate
{
public:
Condition(ListenerHandler<AuthenticationNotification>& listener)
: m_notification(AuthenticationNotificationType::None)
, m_listener(listener)
{
}
bool operator()() const
{
if (m_listener.isNotificationAvailable())
{
const AuthenticationNotificationType notif = m_listener.popNotification().m_type;
if (notif == AuthenticationNotificationType::SessionInfoChanged ||
notif == AuthenticationNotificationType::SessionExtensionFailed)
{
m_notification = notif;
return true;
}
}
return false;
}
mutable AuthenticationNotificationType m_notification;
private:
//US_CLASS_COPY_NOT_ALLOWED(Condition)
Condition(const Condition& dummy) { US_UNUSED(dummy); }
Condition& operator=(Condition&) { return *this; }
mutable ListenerHandler<AuthenticationNotification> m_listener;
} condition(listener);
return US_TEST_NS::Helper::WaitFor(condition, 5ull, waitTime, "extend session")
? condition.m_notification
: AuthenticationNotificationType::None;
}
struct Local
{
// Polls the notification client until an incoming message be available (or getting out of time)
// then test that the message has the specified type, body and space.
static ::testing::AssertionResult expectNotification(
NotificationSource<StateNotification>::ListenerHandler& handler, const StateNotificationType& type)
{
US_ASSERT(type != StateNotificationType::None, "Impossible expectation by design");
const ClockSteady::TDuration::TRep MAX_WAIT_TIME = 30*1000*1000; // microseconds
StateNotification incoming;
HighResolutionChrono chrono;
uint32 messageCount = 0;
bool done = false;
do
{
if (handler.isNotificationAvailable())
{
incoming = handler.popNotification();
done = true;
}
else if (++messageCount > 1)
{
//return ::testing::AssertionFailure() << "Two messages received within the timeframe...";
}
}
// Waits 10 seconds max (arbitrary resilience)
while (!done && chrono.getElapsed() / 1000 < MAX_WAIT_TIME);
if (!done)
{
return ::testing::AssertionFailure() <<
"No incoming data available after " << MAX_WAIT_TIME / 1000 << " ms";
}
if (type != incoming.m_type)
{
return ::testing::AssertionFailure() <<
"Incoming message type unexpected " << static_cast<uint32>(incoming.m_type) << " "
"instead of " << static_cast<uint32>(type);
}
return ::testing::AssertionSuccess();
}
};
AsyncResultBatch<Facade*, Empty> changeState(PlatformHelper::State toState)
{
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_SWITCH) || defined(US_TARGET_KILI) || defined(US_TARGET_MANJARO)
return PlatformHelperProxy::changeState(toState);
#else
return PlatformHelper::changeState(toState);
#endif
}
String renderEmptyResult(const String& label)
{
JsonWriter emptyResult;
emptyResult[label] = JsonWriter(JsonWriterType::Array).getJson();
return emptyResult.renderContent();
}
String renderPrimaryStoreMappingOnlyDLCs()
{
JsonWriter mappingDlc;
#if defined(US_PRIMARY_STORE_WITHOUT_API)
mappingDlc["primaryStoreItemId"] = String(UPLAYPC_DUMMY_DLCID);
#elif defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
mappingDlc["primaryStoreItemId"] = "UBISERVICESDLC01";
#elif defined(US_TARGET_XONE)
mappingDlc["primaryStoreItemId"] = "6df724cf-af33-4767-842f-dcd7cf86b5ac"; //DLC-Skin
#endif
mappingDlc["items"] = JsonWriter(JsonWriterType::Array).getJson();
JsonWriter mappingElements(JsonWriterType::Array);
mappingElements.addItemToArray(mappingDlc.getJson());
JsonWriter mapping;
mapping["mappings"] = mappingElements.getJson();
return mapping.renderContent();
}
String renderPrimaryStoreUpdateResult(bool hasResults = true, bool hasErrors = true, bool hasAdditionalDetails=true)
{
JsonWriter updateResult;
///mock results
if (hasResults)
{
JsonWriter inventoryItem;
inventoryItem["itemId"] = "11111111-2222-3333-4444-555566667777";
inventoryItem["quantity"] = 42;
inventoryItem["quantityBefore"] = 42;
inventoryItem["lastModified"] = DateTimeHelper::formatDateISO8601(DateTime(2015, 01, 10, 14, 03, 58));
inventoryItem["expirationDate"] = DateTimeHelper::formatDateISO8601(DateTime(2016, 02, 10, 14, 03, 58));
inventoryItem["expirationDetails"].setToNull();
JsonWriter transactionWriter;
transactionWriter["transactionId"] = "ABABABAB-CCCC-DDDD-EEEE-112233445566";
transactionWriter["items"].addItemToArray(inventoryItem.getJson());
updateResult["results"].addItemToArray(transactionWriter.getJson());
}
else
{
updateResult["results"] = JsonWriter(JsonWriterType::Array).getJson();
}
if (hasErrors) // mock errors
{
JsonWriter errorWriter;
errorWriter["errorMessage"] = "MOCKEDERROR";
errorWriter["primaryStoreItemId"] = "MOCKEDID";
updateResult["errors"].addItemToArray(errorWriter.getJson());
}
else
{
updateResult["errors"] = JsonWriter(JsonWriterType::Array).getJson();
}
if (hasAdditionalDetails)
{
JsonWriter additionalDetailsItem;
additionalDetailsItem["primaryStoreItemId"] = "11111111-2222-3333-4444-555566664444";
additionalDetailsItem["code"] = 0;
additionalDetailsItem["description"] = "Test.";
updateResult["additionalDetails"].addItemToArray(additionalDetailsItem.getJson());
}
else
{
updateResult["additionalDetails"] = JsonWriter(JsonWriterType::Array).getJson();
}
return updateResult.renderContent();
}
String renderEmptyOffersResult(const String& label = "offers")
{
JsonWriter offersResult;
offersResult[label] = JsonWriter(JsonWriterType::Array).getJson();
return offersResult.renderContent();
}
void setupMockExpectationsForPrimaryStoreAfterSuspendedMode(MockHttpClientImpl& httpClientImpl, const MockAsyncResult& result)
{
#if defined(US_PRIMARY_STORE_WITH_API)
{ // When going back to foreground, the primary store sync will be triggered
US_EXPECT_CALL_HTTP(httpClientImpl, HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.Times(testing::AtMost(1))
.WillRepeatedly(testing::Return(result))
.RetiresOnSaturation();
}
#else
US_UNUSED(httpClientImpl);
US_UNUSED(result);
#endif
}
// This simulate a spaceId change (like being assigned to a Staging spaceId)
class ParametersApplicationMockHelperWithDifferentSpaceId : public ParametersApplicationMockHelper
{
private:
Json buildParameterGroupStaging() const override
{
JsonWriter fields;
fields["spaceId"] = "00000000-1111-2222-3333-444444444444";
return renderParameterGroup(fields.getJson());
}
Json buildFeatureSwitchesParameterGroup() const override
{
JsonWriter fields;
fields["ThisIsANewFeatureSwitchForParametersApplicationMockHelperWithDifferentSpaceId"] = true;
return renderParameterGroup(fields.getJson());
}
};
class ParametersSpaceMockHelperUpdatedParams : public ParametersSpaceMockHelper
{
public:
ParametersSpaceMockHelperUpdatedParams(uint32 maxCount = 20)
:m_maxCount(maxCount)
{
}
private:
Json buildParameterGroupSettingsHttpInternal() const override
{
JsonWriter httpParamJson;
httpParamJson["maxCount"] = m_maxCount;
httpParamJson["retryIncrementFactorMsec"] = 3000;
httpParamJson["retryRandomDelayMsec"] = 4000;
httpParamJson["retryInitialDelayMsec"] = 5000;
httpParamJson["timeoutIncrementFactorMsec"] = 6000;
httpParamJson["timeoutInitialDelayMsec"] = 7000;
return renderParameterGroup(httpParamJson.getJson());
}
uint32 m_maxCount;
};
bool waitForParametersNotification(ListenerHandler<ParametersNotification>& handler, ParametersNotificationType eventNotificationType, const DurationNano& waitTimeMax)
{
HighResolutionChrono chrono;
while (chrono.getElapsed() < waitTimeMax)
{
if (handler.isNotificationAvailable())
{
ParametersNotificationType type = handler.popNotification().m_type;
if (type == eventNotificationType)
{
PRINT_LINE("Expected ParametersNotification received Type: %d", type);
return true;
}
else
{
PRINT_LINE("Unexpected ParametersNotification received Type: %d", type);
}
}
Helper::sleep(100);
}
return false;
}
bool waitForAuthentificationNotification(ListenerHandler<AuthenticationNotification>& handler, AuthenticationNotificationType eventNotificationType, const DurationNano& waitTimeMax)
{
HighResolutionChrono chrono;
while (chrono.getElapsed() < waitTimeMax)
{
if (handler.isNotificationAvailable())
{
AuthenticationNotificationType type = handler.popNotification().m_type;
if (type == eventNotificationType)
{
PRINT_LINE("Expected AuthenticationNotification received Type: %d", type);
return true;
}
else
{
PRINT_LINE("Unexpected AuthenticationNotification received Type: %d", type);
}
}
Helper::sleep(100);
}
return false;
}
class ParametersApplicationMockHelperDefaultPopulations : public ParametersApplicationMockHelper
{
public:
ParametersApplicationMockHelperDefaultPopulations(const String& name = String(), const String& subject = String(), const SpaceId& spaceId = SpaceId(MOCKED_GUID_ID1))
: m_name(name)
, m_subject(subject)
, m_spaceId(spaceId)
{
}
private:
Json buildParameterGroupStaging() const override
{
JsonWriter fields;
fields["spaceId"] = m_spaceId;
return renderParameterGroup(fields.getJson());
}
Json buildRelatedPopulationsCategory() const override
{
JsonWriter population;
{
JsonWriter writer;
writer["name"] = m_name;
writer["subject"] = m_subject;
population["relatedPopulation"] = writer.getJson();
}
return population.getJson();
}
const String m_name;
const String m_subject;
const SpaceId m_spaceId;
};
}
namespace TestPopulations_BF
{
extern const char* POPULATION_SUBJECT_DEFAULT;
extern const char* POPULATION_NAME_DEFAULT;
// The expected subject-population name
extern const char* POPULATION_SUBJECT_AFTER_PUT_POPULATION;
extern const char* POPULATION_NAME_AFTER_PUT_POPULATION;
// The expected subject-population name that makes SpaceId changes
extern const char* POPULATION_SUBJECT_WITH_NEW_SPACEID;
extern const char* POPULATION_NAME_WITH_NEW_SPACEID;
// The expected subject-population name when in new SpaceId
extern const char* POPULATION_SUBJECT_ON_NEW_SPACEID;
extern const char* POPULATION_NAME_ON_NEW_SPACEID;
// Test SpaceId created for Dynamic Population test
// Used by all platforms
extern const char* UBISERVICES_STAGING_TEST_PC_RETAIL_SPACEID;
extern const char* UBISERVICES_STAGING_TEST_PC_STAGING_SPACEID;
extern const char* SPACE_ID_FOR_NEW_POPULATION;
}
// TODO: This test does not validation much of what is stated...
/// @test Exercises the code path when there is no session created before going
/// to suspended mode (there is therefore no need to create a new session and
/// process the other related tasks for resuming).
TEST_F(SUSPENDEDMODE, US_DeleteSessionBeforeSuspended)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().deleteSession()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Ensures that existing job are canceled when the platform goes to suspended mode
TEST_F(SUSPENDEDMODE, US_CancelDuringSuspended)
{
HttpClient& client = getFacade().getHttpClient();
const StringUrl url = TestHelpers_BF::getHttpTestUrl("get", String::formatText("delay=%i", 1)); // 1 second
const AsyncResult<HttpResponse> result = client.sendRequest(HttpGet(url, TestHelpers_BF::getHttpBoxHeader()));
EXPECT_TRUE(result.isProcessing());
// The test is not that much efficient:
// The HTTP request is canceled before reaching the HTTP engine thread (verified on PS4).
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
US_TEST_NS::Helper::sleep(2000); // Should be sufficient for the sendRequest task to be finished when the SDK is not suspended.
EXPECT_TRUE(result.isProcessing());
EXPECT_FALSE(result.isCanceled());
#if defined(US_SDK_TEST_CHINA)
// Will need to be investigated !!! Slow China network speed make this test fails sometime...
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground), 60000));
#else
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
#endif
US_EXPECT_FAILURE(result, Errors::CANCELED_SUSPENDED_MODE);
EXPECT_TRUE(result.isCanceled());
}
#if !defined(US_SDK_LIGHT_MOBILE)
/// @test Ensures that new service calls that are launched while the platform is suspended return a PLATFORM_SUSPENDED error
TEST_F(SUSPENDEDMODE, US_NewCallsForbiddenDuringSuspendedMode)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
#if defined(US_ENABLE_CLUB_TEST)
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getClubClient().requestActionsAll(), Errors::PLATFORM_SUSPENDED));
#else
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestProfileNews(), Errors::PLATFORM_SUSPENDED));
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground))) <<
"Resuming is required to ensure next tests will not run in suspended mode";
}
/// @test Ensures that service calls are correctly running once the platform is back from suspended mode
#if defined(US_TARGET_IOS) && !defined(US_UPLAY_LOGIN_FOR_IOS) || defined(US_TARGET_SWITCH) || defined(US_SDK_TEST_CHINA)
TEST_F(SUSPENDEDMODE, DISABLED_US_CallsSucceedAfterSuspendedMode) // News Services does not support Game Center tickets
#else
TEST_F(SUSPENDEDMODE, US_CallsSucceedAfterSuspendedMode)
#endif
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews(SpaceId(US_TEST_NS::SPACE_ID_US_SDK_PC))));
}
#endif // !defined(US_SDK_LIGHT_MOBILE)
// UbiServicesSdkStateManagerProxy is not in the public API, and thus is not available in DLL
#if !defined(US_DLL)
/////////////////////////////////////////////////////////////////
/// There are 21 possible transitions in the SDK :
/// 1) FG->FG US_TransitionForegroundToForeground
/// 2) FG->BG US_TransitionBackgroundToBackground
/// 3) FG->SUSP US_TransitionSuspendedToSuspended
/// 4) BG->BGFG US_TransitionBackgroundToForeground
/// 5) BG->BG US_TransitionBackgroundToBackground
/// 6) BG->SUSP US_TransitionBackgroundToSuspended
/// 7) SUSP->SUSPFG US_TransitionSuspendedToForeground
/// 8) SUSP->SUSP(BG) US_TransitionSuspendedToBackgroundError
/// 9) SUSP->SUSP(SUSP) US_TransitionSuspendedToSuspended
/// 10) BGFG->BGFG US_TransitionBackgroundToForeground
/// 11) BGFG->BG US_TransitionBackgroundToForegroundToBackground
/// 12) BGFG->SUSP US_TransitionBackgroundToForegroundToSuspended
/// 13) BGFG->FG US_TransitionBackgroundToForeground
/// 14) SUSPFG->SUSPFG US_TransitionSuspendedToForeground
/// 15) SUSPFG->SUSPFGBG US_TransitionSuspendedToForegroundToBackground
/// 16) SUSPFG->SUSP US_TransitionSuspendedToForegroundToSuspended
/// 17) SUSPFG->FG US_TransitionSuspendedToForeground
/// 18) SUSPFGBG->SUSPFG US_TransitionSuspendedToForegroundToBackgroundToForeground
/// 19) SUSPFGBG->SUSPFGBG US_TransitionSuspendedToForegroundToBackgroundToBackground
/// 20) SUSPFGBG->SUSP US_TransitionSuspendedToForegroundToBackgroundToSuspended
/// 21) SUSPFGBG->BG US_TransitionSuspendedToForegroundToBackground
/// @test Validates the transition 1) Foreground to Foreground
TEST_F(SUSPENDEDMODE, US_TransitionForegroundToForeground)
{
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 2) Foreground to Background
/// and 5) Background to Background
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToBackground)
{
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 3) Foreground to Suspended
/// and 9) Suspended to Suspended from a call to transitionTo(Suspended)
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToSuspended)
{
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Validates the transition 8) Suspended to Suspended from a call to transitionTo(Background)
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToBackgroundError)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitFailure(TestSuspendedMode_BF::changeState(PlatformHelper::Background), Errors::RESUME_INVALID_STATE));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Validates the transition 4) Background to BackgroundToForeground
/// 10) BackgroundToForeground to BackgroundToForeground
/// 13) BackgroundToForeground to Foreground
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForeground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
const AsyncResultBatch<Facade*, Empty> resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultBgToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultNewBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_TRUE(resultNewBgToFg.isProcessing());
EXPECT_TRUE(resultNewBgToFg == resultBgToFg);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultBgToFg));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
}
class TestSuspendedModeHelper
{
public:
static int32 getRefCount(const Facade& facade);
static int32 getRefCount(const FacadeInternal& facade);
static void copyRef(SmartPtr<FacadeInternal>& target, const Facade& source);
static const HttpHeader& getRemoteLoggerSdkHeaders(FacadeInternal& facade);
};
/// @test Validates that a Facade can be deleted just after a transition from background to foreground.
/// The transition to foreground starts the JobResumeFocusMaster, that requires Facade(s) to be valid during its execution.
/// A SmartPtr in the Facade keeps the FacadeInternal alive while JobResumeFocusMaster runs.
/// The Facade(s) will be deleted once the JobResumeFocusMaster is done.
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForegroundWithDeletedFacade)
{
// Note:
// There is already an existing Facade when this test starts (created by AuthentificationFixture)
SmartPtr<FacadeInternal> facadeKeep;
{
Facade facade2;
// Facade has 1
// FacadesManager has 1
EXPECT_EQ(2, TestSuspendedModeHelper::getRefCount(facade2));
// Keep the newly created facade so we can validate its refcount once the JobResumeFocusMaster is done.
TestSuspendedModeHelper::copyRef(facadeKeep, facade2); //facadeKeep = facade2.m_facadeInternal;
EXPECT_EQ(3, TestSuspendedModeHelper::getRefCount(facade2));
// Go to background and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting!
const AsyncResultBatch<Facade*, Empty> result = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(result)); // Wait for transition to complete
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
US_TEST_NS::Helper::sleep(1000);
EXPECT_EQ(1, TestSuspendedModeHelper::getRefCount(*facadeKeep));
}
/// @test Validates that a Facade can be deleted by a Game just after
/// a transition from suspended to foreground.
/// The transition to foreground starts the JobResumeFromSuspended, that requires Facade(s) to be valid during its execution.
/// A SmartPtr in the Facade keep the FacadeInternal alive while JobResumeFromSuspended runs.
/// The Facade(s) will be deleted once the JobResumeFromSuspended is done.
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundWithDeletedFacade)
{
SmartPtr<FacadeInternal> facadeTemp;
AsyncResultBatch<Facade*, Empty> result;
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
// Facade has 1
// FacadesManager has 1
EXPECT_EQ(2, TestSuspendedModeHelper::getRefCount(facade2));
// Keep the newly created facade so we can validate its refcount once the JobResumeFocusMaster is done.
TestSuspendedModeHelper::copyRef(facadeTemp, facade2); //facadeTemp = facade2.m_facadeInternal;
EXPECT_EQ(3, TestSuspendedModeHelper::getRefCount(facade2));
// Go to Suspended and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting!
result = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// Only JobResumeFocusMaster and this test keep the facade alive.
// Wait for transition
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
// The facadeTemp SmartPtr is the only one keeping the Facade alive, so refcount should be 1
EXPECT_EQ(1, TestSuspendedModeHelper::getRefCount(*facadeTemp));
}
/// @test Validates that a Facade can be deleted by a Game just after
/// a transition from background to foreground.
/// The transition to foreground starts the JobResumeFocusMaster, that requires Facade(s) to be valid during its execution.
/// A SmartPtr keep the Facade alive while JobResumeFocusMaster runs.
/// The Facade(s) will be deleted once the JobResumeFocusMaster is done.
/// This test is different from the one above because there is no delay.
/// The test will crash if something is wrong !
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForegroundWithDeletedFacadeSuperFast)
{
setupDebugLogging();
uint32 ITERATION_COUNT = 5;
PrepareLoggingMock([ITERATION_COUNT](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("UbiServices SDK resuming from background mode.", LogLevel::Info, Times(ITERATION_COUNT));
});
for (uint32 i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Iteration %d/%d - State %d", i + 1, ITERATION_COUNT, PlatformHelper::getState());
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
// Go to background and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting !
AsyncResultBatch<Facade*, Empty> resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// Only JobResumeFocusMaster keep the facade alive.
// Before the use of the SmartPtr in the Facade,
// the JobResumeFocusMaster would have crash here
// because the facade would have been deleted.
}
}
/// @test Validates that a Facade can be deleted by a Game just after
/// a transition from suspended to foreground.
/// The transition to foreground starts the JobResumeFromSuspended, that requires Facade(s) to be valid during its execution.
/// A SmartPtr keep the Facade alive while JobResumeFromSuspended runs.
/// The Facade(s) will be deleted once the JobResumeFromSuspended is done.
/// This test is different from the one above because there is no delay.
/// The test will crash if something is wrong !
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundWithDeletedFacadeSuperFast)
{
setupDebugLogging();
uint32 ITERATION_COUNT = 5;
PrepareLoggingMock([ITERATION_COUNT](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("UbiServices SDK resuming from suspended mode.", LogLevel::Info, Times(ITERATION_COUNT));
});
AsyncResultBatch<Facade*, Empty> result;
for (uint32 i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Iteration %d/%d - State %d", i + 1, ITERATION_COUNT, PlatformHelper::getState());
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
// Go to Suspended and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting !
result = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// Only JobResumeFromSuspended keep the facade alive.
// Before the use of the SmartPtr in the Facade,
// the JobResumeFromSuspended would have crash here
// because the facade would have been deleted.
}
// Wait for state to be foreground
// This is required because the FacadeInternal::deleteSession()
// will raise an error is the current state is Suspended
// So we need to wait for Foreground
AsyncHelper::waitSuccess(result);
}
/// @test Validates that a Facade can be deleted by a Game just after
/// a transition from background to foreground.
/// The transition to foreground starts the JobResumeFocusMaster, that requires Facade(s) to be valid during its execution.
/// A SmartPtr keep the Facade alive while JobResumeFocusMaster runs.
/// The Facade(s) will be deleted once the JobResumeFocusMaster is done.
/// This test is different from the one above because we increment sleep time at each loop
/// The test will crash if something is wrong !
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForegroundWithDeletedFacadeWithSleep)
{
setupDebugLogging();
uint32 ITERATION_COUNT = 50;
PrepareLoggingMock([ITERATION_COUNT](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("UbiServices SDK resuming from background mode.", LogLevel::Info, Times(ITERATION_COUNT));
});
for (uint32 i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Iteration %d/%d - State %d", i + 1, ITERATION_COUNT, PlatformHelper::getState());
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
// Go to background and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting!
const AsyncResultBatch<Facade*, Empty> resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
TestSuspendedMode_EX::spinDelay(i * 10); // milliseconds
}
// The test needs to wait the transition completion to foreground...?
// while (PlatformHelper::getState() != PlatformHelper::Foreground)
// {
// PRINT_LINE("Waiting foreground");
// Helper::sleep(1);
// }
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// JobResumeFocusMaster keeps the facade alive.
// Before the use of the SmartPtr in the Facade,
// the JobResumeFocusMaster would have crash here
// because the facade would have been deleted.
}
}
/// @test Validates that a Facade can be deleted by a game just after
/// a transition from suspended to foreground.
/// The transition to foreground starts the JobResumeFromSuspended,
/// that requires Facade(s) to be valid during its execution.
/// A SmartPtr keeps the Facade alive while JobResumeFromSuspended runs.
/// The Facade(s) will be deleted once the JobResumeFromSuspended is done.
/// This test is different from the one above because we increment sleep time at each loop
/// The test crashes if something is wrong!
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundWithDeletedFacadeWithSleep)
{
setupDebugLogging();
uint32 ITERATION_COUNT = 50;
PrepareLoggingMock([ITERATION_COUNT](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("UbiServices SDK resuming from suspended mode.", LogLevel::Info, Times(ITERATION_COUNT));
});
for (uint32 i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Iteration %d/%d - State %d", i + 1, ITERATION_COUNT, PlatformHelper::getState());
AsyncResultBatch<Facade*, Empty> resultBgToFg;
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
// Go to background and wait until done
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Back to foreground, no waiting !
resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
TestSuspendedMode_EX::spinDelay(i*10); // milliseconds
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// Only JobResumeFromSuspended keep the facade alive.
// Before the use of the SmartPtr in the Facade,
// the JobResumeFromSuspended would have crash here
// because the facade would have been deleted.
// Wait for the resume to foreground to finish in order to avoid concurrency/race conditions on the jobs
// that handle the state change during the next loop.
ASSERT_TRUE(AsyncHelper::waitSuccess(resultBgToFg));
}
}
/// @test Validates that a Facade can be deleted by a Game just after
/// a transition from background to foreground.
/// The transition to foreground starts the JobResumeFocusMaster, that requires Facade(s) to be valid during its execution.
/// A SmartPtr keep the Facade alive while JobResumeFocusMaster runs.
/// The Facade(s) will be deleted once the JobResumeFocusMaster is done.
TEST_F(SUSPENDEDMODE, DISABLED_MANUAL_US_TransitionBackgroundToForegroundWithDeletedFacade)
{
uint32 loopCount = 1;
do
{
PRINT_DEBUG("Loop #%d", loopCount);
PRINT_DEBUG("Waiting for Foreground State");
while (PlatformHelper::getState() != PlatformHelper::Foreground)
{
Helper::sleep(1);
}
PRINT_DEBUG("State is now Foreground");
{
// Note:
// There is already one existing Facade before this test starts
// It was created in the AuthentificationFixture
Facade facade2;
PRINT_DEBUG("Waiting for Background State");
while (PlatformHelper::getState() != PlatformHelper::Background)
{
Helper::sleep(1);
}
PRINT_DEBUG("State is now Background");
PRINT_DEBUG("Waiting for Foreground State");
while (PlatformHelper::getState() != PlatformHelper::Foreground)
{
Helper::sleep(1);
}
PRINT_DEBUG("State is now Foreground");
}
// Facade2 is now deleted
// FacadesManager has also release the FacadeInternal
// Only JobResumeFocusMaster keep the facade alive.
// Before the use of the SmartPtr in the Facade,
// the JobResumeFocusMaster would have crash here
// because the facade would have been deleted.
}
while (++loopCount < 5);
}
/// @test Validates the transition events
TEST_F(SUSPENDEDMODE, US_ValidatePlatformTransitionStateEvent)
{
InstancesManager* instancesManager = InstancesManager::getInstance();
ASSERT_TRUE(instancesManager != nullptr);
NotificationSource<StateNotification>::ListenerHandler handler = instancesManager->createNotificationListener();
///////////////////////////////
// To Background
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
// Pop incoming notifications
EXPECT_TRUE(TestSuspendedMode_BF::Local::expectNotification(handler, StateNotificationType::Background));
///////////////////////////////
// To Foreground
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
// Pop incoming notifications
EXPECT_TRUE(TestSuspendedMode_BF::Local::expectNotification(handler, StateNotificationType::Foreground));
///////////////////////////////
// To Suspended
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Pop incoming notifications
EXPECT_TRUE(TestSuspendedMode_BF::Local::expectNotification(handler, StateNotificationType::Suspended));
///////////////////////////////
// To Foreground
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
// Pop incoming notifications
EXPECT_TRUE(TestSuspendedMode_BF::Local::expectNotification(handler, StateNotificationType::Foreground));
}
/// @test Validates the transition 6) Background to Suspended
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToSuspended)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Validates the transition 7) Suspended to SuspendedToForeground
/// 14) SuspendedToForeground to SuspendedToForeground
/// 17) SuspendedToForeground to Foreground
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForeground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultNewSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_TRUE(resultNewSuspToFg.isProcessing());
EXPECT_TRUE(resultNewSuspToFg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
}
#if defined(US_SDK_FULL)
// Test that the notification types are correctly updated in the connection when the TGO Portal parameters change during suspendedMode
// and then the SDK transition from suspended to foreground..
// Steps:
// 1. precondition: OnlineNotificationType1 is configured in the portal and OnlineNotificationTypeAfterParamUpdate is not configured.
// 2. check that sendNotificationInSequence works with OnlineNotificationType1 and does not work with OnlineNotificationTypeAfterParamUpdate.
// 3. while in suspended mode place a breakpoint, then update the portal: rename OnlineNotificationType1 as OnlineNotificationTypeAfterParamUpdate.
// When performing the update in the portal don't enable the checkbox "Update for all players connected..".
// 4. check that sendNotificationInSequence works with OnlineNotificationTypeAfterParamUpdate and does not work with OnlineNotificationType1.
// 5. in the portal rename OnlineNotificationTypeAfterParamUpdate back to OnlineNotificationType1.
TEST_F(SUSPENDEDMODE, DISABLED_MANUAL_TransitionSuspendedToForegroundToCheckNotificationTypes)
{
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
// confirm that OnlineNotificationType1 is configured in the portal and OnlineNotificationTypeAfterParamUpdate is not configured
const String body = "ABCDE";
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNotificationClient().sendNotificationInSequence(
{ getFacade().getAuthenticationClient().getSessionInfo().getProfileId() },
NotificationOutgoing("OnlineNotificationType1", body))));
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getNotificationClient().sendNotificationInSequence(
{ getFacade().getAuthenticationClient().getSessionInfo().getProfileId() },
NotificationOutgoing("OnlineNotificationTypeAfterParamUpdate", body)), Errors::NOTIFICATION_SEND_FAILED));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
// add breakpoint here. while in breakpoint rename OnlineNotificationType1 to OnlineNotificationTypeAfterParamUpdate,
// then run test until the end
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
// check that the update was done in the connection
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNotificationClient().sendNotificationInSequence(
{ getFacade().getAuthenticationClient().getSessionInfo().getProfileId() },
NotificationOutgoing("OnlineNotificationTypeAfterParamUpdate", "body after the connection was updated"))));
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getNotificationClient().sendNotificationInSequence(
{ getFacade().getAuthenticationClient().getSessionInfo().getProfileId() },
NotificationOutgoing("OnlineNotificationType1", "body after the connection was updated")), Errors::NOTIFICATION_SEND_FAILED));
// in the portal rename OnlineNotificationTypeAfterParamUpdate back to OnlineNotificationType1
}
#endif
/// @test Validates the transition 11) BackgroundToForeground to Background
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForegroundToBackground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
const AsyncResultBatch<Facade*, Empty> resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultBgToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_FALSE(resultToBg == resultBgToFg);
EXPECT_TRUE(resultBgToFg.isCanceled());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultToBg));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 12) BackgroundToForeground to Suspended
TEST_F(SUSPENDEDMODE, US_TransitionBackgroundToForegroundToSuspended)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
const AsyncResultBatch<Facade*, Empty> resultBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::BackgroundToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultBgToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultToSusp = TestSuspendedMode_BF::changeState(PlatformHelper::Suspended);
EXPECT_FALSE(resultToSusp == resultBgToFg);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultToSusp));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultBgToFg.isProcessing());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Validates the transition 15) SuspendedToForeground to SuspendedToForegroundToBackground
/// and 21) SuspendedToForegroundToBackground to Background
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundToBackground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_TRUE(resultSuspToFgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForegroundToBackground, UbiServicesSdkStateManagerProxy::getSdkState());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 16) SuspendedToForeground to Suspended
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundToSuspended)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToSusp = TestSuspendedMode_BF::changeState(PlatformHelper::Suspended);
EXPECT_FALSE(resultSuspToFgToSusp == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
/// @test Validates the transition 18) SuspendedToForegroundToBackground to SuspendedToForeground
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundToBackgroundToForeground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_TRUE(resultSuspToFgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForegroundToBackground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBgToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_TRUE(resultSuspToFgToBgToFg == resultSuspToFgToBg);
EXPECT_TRUE(resultSuspToFgToBgToFg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 19) SuspendedToForegroundToBackground to SuspendedToForegroundToBackground
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundToBackgroundToBackground)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_TRUE(resultSuspToFgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForegroundToBackground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_TRUE(resultSuspToFgToBgToBg == resultSuspToFgToBg);
EXPECT_TRUE(resultSuspToFgToBgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForegroundToBackground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
EXPECT_EQ(PlatformHelper::Background, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Background, UbiServicesSdkStateManagerProxy::getSdkState());
}
/// @test Validates the transition 20) SuspendedToForegroundToBackground to Suspended
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundToBackgroundToSuspended)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForeground, UbiServicesSdkStateManagerProxy::getSdkState());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Background);
EXPECT_TRUE(resultSuspToFgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::SuspendedToForegroundToBackground, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
const AsyncResultBatch<Facade*, Empty> resultSuspToFgToBgToBg = TestSuspendedMode_BF::changeState(PlatformHelper::Suspended);
EXPECT_FALSE(resultSuspToFgToBgToBg == resultSuspToFgToBg);
EXPECT_FALSE(resultSuspToFgToBgToBg == resultSuspToFg);
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
EXPECT_TRUE(resultSuspToFg.isProcessing());
// Go back to foreground in order to be able to finish the test cleanly
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
}
#endif // US_DLL
#if defined(US_TARGET_XONE) && !defined(US_DLL)
/// @test Validates that when resuming to foreground from suspended state, it is possible to assign an XboxLiveContext
TEST_F(SUSPENDEDMODE, US_TransitionSuspendedToForegroundUpdateXboxLiveContext)
{
///////////////////////////////
// To Suspended
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
EXPECT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Suspended, UbiServicesSdkStateManagerProxy::getSdkState());
///////////////////////////////
// To Foreground
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_EQ(PlatformHelper::Foreground, PlatformHelper::getState());
EXPECT_EQ(UbiServicesSdkStateInternal::Foreground, UbiServicesSdkStateManagerProxy::getSdkState());
// There must be at least one user online on the console
ASSERT_GT(Windows::Xbox::System::User::Users->Size, 0u);
Windows::Xbox::System::User^ user = Windows::Xbox::System::User::Users->GetAt(0);
Platform::String^ xboxId = user->XboxUserId;
#if defined(US_XONE_USE_XSAPI_CPP)
std::shared_ptr<xbox::services::xbox_live_context> xboxLiveContext(new xbox::services::xbox_live_context(user));
PlatformHelper::updateXboxLiveContext(xboxLiveContext);
ASSERT_EQ(xboxLiveContext.get(), InstancesManager::getInstance()->getXboxLiveContext(user).get());
#else
XboxLiveContext context;
context.m_context = ref new Microsoft::Xbox::Services::XboxLiveContext(user);
PlatformHelper::updateXboxLiveContext(&context);
ASSERT_EQ(context.m_context, InstancesManager::getInstance()->getXboxLiveContext(user).m_context);
#endif
}
#endif // US_TARGET_XONE && !US_DLL
#if !defined(US_DLL)
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_IOS) || defined(US_TARGET_KILI)
/// @test Checks that when coming back from suspendedMode we request a new console ticket to create a session.
/// expiration is 2 minutes on this application.
TEST_F(SUSPENDEDMODE_NOINIT, US_LONG_PS4CreateNewSessionAfterSuspendedMode)
{
const US_TEST_NS::ScopedInit autoInit;
{
configureSdk(GameConfig(ApplicationId(APP_ID_SHORT_EXPIRATION), 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>())
#endif
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
, GameConfigConsole(NS_COMMON::FIRSTPARTY_APP_ID)
#endif
));
#if !defined(US_SDK_S2S)
EXPECT_TRUE(InstancesHelper::SetBackdoorEnvironment(NS_COMMON::Options::environment()));
#endif
const std::unique_ptr<PlayerCredentials> credentials(NS_COMMON::AuthenticationHelper::createPlayerCredentials());
Facade facade;
const AsyncResult<Empty> resultLogin = facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {});
EXPECT_TRUE(AsyncHelper::waitSuccess(resultLogin));
const String ticket1 = facade.getAuthenticationClient().getSessionInfo().getTicket();
const String remoteLoggerSdkTicket1 = TestSuspendedModeHelper::getRemoteLoggerSdkHeaders(getFacadeInternal(facade))["Authorization"];
PRINT_LINE("Entering Suspended Mode");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
US_TEST_NS::Helper::sleep(60 * 1000 * 3);
PRINT_LINE("Sleep finished");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
const String ticket2 = facade.getAuthenticationClient().getSessionInfo().getTicket();
const String remoteLoggerSdkTicket2 = TestSuspendedModeHelper::getRemoteLoggerSdkHeaders(getFacadeInternal(facade))["Authorization"];
EXPECT_NE(ticket1, ticket2);
EXPECT_NE(remoteLoggerSdkTicket1, remoteLoggerSdkTicket2);
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#elif defined(US_TARGET_WINDOWS) && !defined(US_SDK_TEST_CHINA) // AppId not supported in China context
/// @test Checks that when coming back from suspendedMode we request a new console ticket to create a session.
/// expiration is 2 minutes on this application.
TEST_F(SUSPENDEDMODE_NOINIT, US_LONG_CreateNewSessionAfterSuspendedMode)
{
const US_TEST_NS::ScopedInit autoInit;
{
configureSdk(GameConfig(ApplicationId(APP_ID_SHORT_EXPIRATION), 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>())
#endif
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
, GameConfigConsole(NS_COMMON::FIRSTPARTY_APP_ID)
#endif
));
Facade facade;
const AsyncResult<Empty> resultLogin = facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {});
EXPECT_TRUE(AsyncHelper::waitSuccess(resultLogin));
const String ticket1 = facade.getAuthenticationClient().getSessionInfo().getTicket();
const String remoteLoggerSdkTicket1 = TestSuspendedModeHelper::getRemoteLoggerSdkHeaders(getFacadeInternal(facade))["Authorization"];
PRINT_LINE("Entering Suspended Mode");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
US_TEST_NS::Helper::sleep(60 * 1000 * 3);
PRINT_LINE("Sleep finished");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
const String ticket2 = facade.getAuthenticationClient().getSessionInfo().getTicket();
const String remoteLoggerSdkTicket2 = TestSuspendedModeHelper::getRemoteLoggerSdkHeaders(getFacadeInternal(facade))["Authorization"];
EXPECT_NE(ticket1, ticket2);
EXPECT_NE(remoteLoggerSdkTicket1, remoteLoggerSdkTicket2);
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#endif
#endif // US_DLL
#if !defined(US_SDK_LIGHT_MOBILE) && !defined(US_DLL)
/// @test Ensures that the notification periodic job is correctly restarted after suspended mode
/// @note This test is based on MESSAGING.US_SendRetrieveSelfMessageUsingProfileId
#if defined(US_TARGET_SWITCH)
TEST_F(SUSPENDEDMODE, DISABLED_US_NotificationAfterSuspendedMode)
#else
TEST_F(SUSPENDEDMODE, US_NotificationAfterSuspendedMode)
#endif
{
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
Vector<Facade*> facades = Vector<Facade*>({ &getFacade() });
const Vector<String> types = getWebSocketContentTypes();
NotificationHelper::MultiConnection multi(facades, types, getWebSocketJsonData());
AsyncHelper::waitSuccess(NotificationClientProxy::updateNotificationTypes(getFacade().getNotificationClient(), types));
multi.checkConnection(true);
{
String out;
multi.sendMessage(0, { 0u }, NotificationHelper::MultiConnection::SendType::UsingProfileId, &out);
//PRINT_STREAM("**********" << out << "**********");
}
{
String out;
multi.waitForMessageAndPop(0, 1, &out);
//PRINT_STREAM("**********" << out << "**********");
}
}
#endif // !defined(US_SDK_LIGHT_MOBILE) && !defined(US_DLL)
// Use the User edit page in the portal to unlink & to remove the TOS acceptance
// and then link/accept TOS once inside the test
TEST_F(SUSPENDEDMODE, DISABLED_MANUAL_SimulateResumeFocus)
{
ASSERT_TRUE(getFacade().getAuthenticationClient().getSessionInfo().hasValidSession());
const bool isLinked = getFacade().getAuthenticationClient().getSessionInfo().hasUserAccountLinked();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_EQ(PlatformHelper::Suspended, PlatformHelper::getState());
PRINT_LINE("Time to suspend and set back legal opt-ins and link");
US_TEST_NS::Helper::sleep(20000); // Increase the sleep time to test on platforms without suspended mode (Win32)
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(getFacade().getAuthenticationClient().getSessionInfo().hasValidSession());
if(!isLinked)
{
EXPECT_TRUE(getFacade().getAuthenticationClient().getSessionInfo().hasUserAccountLinked());
}
}
#if !defined(US_SDK_LIGHT_MOBILE)
#if !defined(US_DLL)
#if defined(US_TARGET_IOS) && !defined(US_UPLAY_LOGIN_FOR_IOS) || defined(US_SDK_TEST_CHINA)
TEST_F(SUSPENDEDMODE, DISABLED_US_CachesAreInvalidatedOnResumeFromSuspended) // News Services does not support Game Center tickets
#else
TEST_F(SUSPENDEDMODE, US_CachesAreInvalidatedOnResumeFromSuspended)
#endif
{
// Fill another cache
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews(SpaceId(US_TEST_NS::SPACE_ID_US_SDK_PC))));
EXPECT_TRUE(CacheManager::isCacheValid(getFacadeInternal(), CacheUnit::NewsProfile));
EXPECT_FALSE(TestSuspendedMode_EX::areAllCachesInvalid(getFacadeInternal()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_TRUE(TestSuspendedMode_EX::areAllCachesInvalid(getFacadeInternal()));
}
#if defined(US_TARGET_IOS) && !defined(US_UPLAY_LOGIN_FOR_IOS) || defined(US_SDK_TEST_CHINA)
TEST_F(SUSPENDEDMODE, DISABLED_US_CachesAreInvalidatedOnResumeFromBackground) // News Services does not support Game Center tickets
#else
TEST_F(SUSPENDEDMODE, US_CachesAreInvalidatedOnResumeFromBackground)
#endif
{
// Fill another cache
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews(SpaceId(US_TEST_NS::SPACE_ID_US_SDK_PC))));
EXPECT_TRUE(CacheManager::isCacheValid(getFacadeInternal(), CacheUnit::NewsProfile));
EXPECT_FALSE(TestSuspendedMode_EX::areAllCachesInvalid(getFacadeInternal()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
EXPECT_TRUE(TestSuspendedMode_EX::areAllCachesInvalid(getFacadeInternal()));
}
#endif // !defined(US_DLL)
#if defined(US_TARGET_WINDOWS) && !defined(US_SDK_TEST_CHINA) // AppId not supported in China context
/// @test Ensures that a new session is created and service calls are working
/// when the suspension time is above the expiration time
/// @note use ApplicationId 8700c8f7-c538-4ee4-8dfb-1d5650bd66ed (Short expiration PC)
/// or d2943775-5ae7-46bd-b871-819f01ae64eb (Short expiration PS4) to launch this test,
/// expiration is 2 minutes on this application.
TEST_F(SUSPENDEDMODE_NOINIT, LONG_US_CreateNewSessionAfterSuspendedMode)
{
const US_TEST_NS::ScopedInit autoInit;
{
// Forcing applicationId. server make check that it is the same as in the ticket's claims
configureSdk(GameConfig(ApplicationId(APP_ID_SHORT_EXPIRATION), String()
#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>())
#endif
), SystemConfig());
Facade facade;
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
EXPECT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Suspended)));
US_TEST_NS::Helper::sleep(150000);
EXPECT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Foreground)));
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.getProfileClient().requestUplayProfiles({ String("ussdk001") })));
}
}
#endif
#endif // !defined(US_SDK_LIGHT_MOBILE)
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
/// Exercises the suspend mode auto-detection on Xbox One.
/// This test ends as soon as the test goes into "constraint" mode,
/// that is, pressing the "HOME" button on the controller
/// (or pressing the POWER button of the console).
TEST_F(SUSPENDEDMODE_NOINIT, DISABLED_MANUAL_US_AutoDetectSuspendedMode)
{
const US_TEST_NS::ScopedInit autoInit;
configureSdk(GameConfig(ApplicationId(NS_COMMON::Options::getApplicationId().c_str()),
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>())
#endif
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
, GameConfigConsole(NS_COMMON::FIRSTPARTY_APP_ID)
#endif
), SystemConfig());
#if !defined(US_SDK_S2S)
EXPECT_TRUE(InstancesHelper::SetBackdoorEnvironment(NS_COMMON::Options::environment()));
#endif
{
Facade facade;
#if defined(US_TARGET_XONE)
// There must be at least one user online on the console
ASSERT_GT(Windows::Xbox::System::User::Users->Size, 0u);
Windows::Xbox::System::User^ user = Windows::Xbox::System::User::Users->GetAt(0);
Platform::String^ xboxId = user->XboxUserId;
#if defined(US_XONE_USE_XSAPI_CPP)
std::shared_ptr<xbox::services::xbox_live_context> xboxLiveContext(new xbox::services::xbox_live_context(user));
const PlayerCredentials credentials(xboxLiveContext);
#else
Microsoft::Xbox::Services::XboxLiveContext^ xblContext = ref new Microsoft::Xbox::Services::XboxLiveContext(user);
const PlayerCredentials credentials(xblContext);
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(credentials, {}, {})));
#endif
#if defined(US_TARGET_GGP)
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(PlayerCredentials(ggp::GetPrimaryPlayerId()), {}, {})));
#endif
//while(PlatformHelper::getState() != PlatformHelper::Background)
{
uint32 count = 0;
facade.getRemoteLogClient().sendRemoteLog(RemoteLogClient::Warning, "TestCategory", RemoteLog(String("TEST_AUTODETECT BEGIN")));
while(PlatformHelper::getState() != PlatformHelper::Suspended)
{
US_TEST_NS::Helper::sleep(100);
if (count++ > 10)
{
facade.getRemoteLogClient().sendRemoteLog(RemoteLogClient::Warning, "TestCategory", RemoteLog(String("TEST_AUTODETECT TICK #1")));
count = 0;
}
}
count = 0;
facade.getRemoteLogClient().sendRemoteLog(RemoteLogClient::Warning, "TestCategory", RemoteLog(String("TEST_AUTODETECT FROM SUSPENDED")));
while(PlatformHelper::getState() != PlatformHelper::Foreground)
{
US_TEST_NS::Helper::sleep(100);
if (count++ > 10)
{
facade.getRemoteLogClient().sendRemoteLog(RemoteLogClient::Warning, "TestCategory", RemoteLog(String("TEST_AUTODETECT TICK #2")));
count = 0;
}
}
facade.getRemoteLogClient().sendRemoteLog(RemoteLogClient::Warning, "TestCategory", RemoteLog(String("TEST_AUTODETECT END")));
}
Helper::sleep(30000);
}
}
#endif
#if !defined(US_DLL)
/// @test Ensures that events periodic job is relaunched after suspended mode
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_SendingEventsAfterSuspendedMode)
{
{
const MockAsyncResult eventConfigMock = MockResultHelper::createSuccessResult(
EventsConfigMockHelper::getBody(2).renderContent()); // SEND_PERIOD_SEC = 2
setupWebsocketMock();
mockFullLogin(nullptr, nullptr, nullptr, nullptr, &eventConfigMock);
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.Times(2)
.WillRepeatedly(testing::Return(MockResultHelper::createSuccessResult()));
}
ListenerHandler<EventNotification> handler = getFacade().getEventClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
// Ensure the periodic job is started before going to suspended mode
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::EventConfigSuccess, true));
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true))
<< "The game.start and player.start should be sent.";
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
TestSuspendedMode_BF::setupMockExpectationsForPrimaryStoreAfterSuspendedMode(getMockHttpClientImpl(),
getMockedNotifyPrimaryStoreUpdate());
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
const AsyncResultBatch<Facade*, Empty> result = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
ASSERT_FALSE(handler.isNotificationAvailable()) << "The event notifications should be empty at this moment.";
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
getFacade().getEventClient().pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME));
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true))
<< "The events pushed after suspended should be sent.";
}
#endif
#if !defined(US_DLL)
/// @test Ensures that events periodic job is relaunched after suspended mode,
/// even if the resume is call two times simultaneously. Without protection,
/// the first resume would cancel the event periodic job, and the second one
/// would not restart the periodic job since it shall be restarted only if it
/// was running before going to suspended mode.
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_SendingEventsAfterTwoParallelTransitionFromSuspendedMode)
{
{
const MockAsyncResult eventConfigMock = MockResultHelper::createSuccessResult(
EventsConfigMockHelper::getBody(2).renderContent()); // SEND_PERIOD_SEC = 2
setupWebsocketMock();
mockFullLogin(nullptr, nullptr, nullptr, nullptr, &eventConfigMock);
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.Times(2)
.WillRepeatedly(testing::Return(MockResultHelper::createSuccessResult()));
}
ListenerHandler<EventNotification> handler = getFacade().getEventClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
// Ensure the periodic job is started before going to suspended mode
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true))
<< "The game.start and player.start should be sent.";
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
TestSuspendedMode_BF::setupMockExpectationsForPrimaryStoreAfterSuspendedMode(getMockHttpClientImpl(),
getMockedNotifyPrimaryStoreUpdate());
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Do NOT wait intendedly for the async result to finish here.
// This test checks the behavior when two transition are done in parallel
const AsyncResultBatch<Facade*, Empty> resultFirstResume = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
const AsyncResultBatch<Facade*, Empty> resultSecondResume = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
ASSERT_FALSE(handler.isNotificationAvailable()) << "The event notifications should be empty at this moment.";
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSecondResume));
// Wait here instead, to ensure the resume is finished for the rest of the test
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFirstResume));
getFacade().getEventClient().pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME));
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true))
<< "The events pushed after suspended should be sent.";
}
#endif
#if defined(US_ENABLE_UPLAY_LOGIN) && !defined(US_SDK_TEST_CHINA)
/// A crash occurred in the websocket engine when resuming from suspended mode.
/// Both websockets on the two facades try to connect simultaneously, but when the second connects,
/// it erases the first one from the websocket engine, because it is not connected yet, and therefore
/// detected as disconnected. When trying to access the first websocket again, the crash occurs.
TEST_F(SUSPENDEDMODE, US_SuspendedForegroundWithTwoFacades)
{
setupDebugLogging();
const int ITERATION_COUNT = 10;
PrepareLoggingMockWithLogsPrinted([ITERATION_COUNT](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("UbiServices SDK resuming from suspended mode.", LogLevel::Info, Times(ITERATION_COUNT));
US_EXPECT_LOG("Connection already closed.", LogLevel::Warning, Times(ITERATION_COUNT*2));
});
Facade facade2;
ASSERT_TRUE(AsyncHelper::waitSuccess(facade2.createSession(PlayerCredentials("ussdk002@ubisoft.com", "a1234567"), {}, {})));
US_TEST_NS::Helper::sleep(2500);
for (uint32 i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Iteration %d/%d", i + 1, ITERATION_COUNT);
// Try several times, because the crash depended on timing issues
EXPECT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Suspended)));
US_TEST_NS::Helper::sleep(2000);
EXPECT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Foreground)));
US_TEST_NS::Helper::sleep(2000);
}
}
#endif
#if defined(US_TARGET_SWITCH)
/// @test Test that we remain in the same session after being in a suspended state for a long time
/// The steps are the following:
/// 1- Start the test
/// 2- Wait in DNA-LiveStream for the session to start on Short Expiration PC
/// 3- Upon session being on DNA-LiveStream, put the console on suspended physically(go back to home is sufficient)
/// 4- Wait for the ticket to expire(3+ minutes)
/// 5- Come back from suspended by pressing the home button or selecting the test in the home screen
/// 6- Wait for event to be push and verify in DNA-LiveStream that the Testing event has been sent in the same session
/// 7- Verify the test passed
TEST_F(SUSPENDEDMODE_NOINIT, DISABLED_MANUAL_US_EventPeriodicAfterExpiration)
{
const US_TEST_NS::ScopedInit autoInit;
{
ApplicationId appId(APP_ID_SHORT_EXPIRATION);
configureSdk(GameConfig(appId, 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>())
#endif
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
, GameConfigConsole(NS_COMMON::FIRSTPARTY_APP_ID)
#endif
));
#if !defined(US_SDK_S2S)
EXPECT_TRUE(InstancesHelper::SetBackdoorEnvironment(NS_COMMON::Options::environment()));
#endif
Facade facade;
const AsyncResult<Empty> resultLogin = facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {});
EXPECT_TRUE(AsyncHelper::waitSuccess(resultLogin));
const String ticket1 = facade.getAuthenticationClient().getSessionInfo().getTicket();
//Put in suspended once the session has started on DNA-LiveStream
nn::oe::SetResumeNotificationEnabled(true);
nn::oe::Message message;
while (!nn::oe::TryPopNotificationMessage(&message))
{
US_TEST_NS::Helper::sleep(150);
}
PRINT_LINE("Entering Suspended Mode");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
PRINT_LINE("Back To Foreground");
EXPECT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
auto listener = facade.getEventClient().createNotificationListener();
facade.getEventClient().pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME));
TestSuspendedMode_BF::waitForEventNotification(listener, EventNotificationType::SendingSuccessful, false);
const String ticket2 = facade.getAuthenticationClient().getSessionInfo().getTicket();
EXPECT_NE(ticket1, ticket2);
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#endif
#if !defined(US_DLL)
/// @test Ensures that events periodic job is relaunched after suspended mode
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_EventPeriodicJobNotRestartedAfterSuspendedMode)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 404", LogLevel::Error, Times(1));
});
{
const MockAsyncResult eventConfigMock = MockResultHelper::createSuccessResult(
EventsConfigMockHelper::getBody(3).renderContent()); // SEND_PERIOD_SEC = 3
setupWebsocketMock();
mockLogin(getMockedLoginResponse(), getMockedParametersApplication(), getMockedParametersSpace());
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-config-events", eventConfigMock);
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.WillOnce(testing::Return(MockResultHelper::createRestErrorResult(RestStatusCode::Error404, 1000u)));
{
const char* const JSON_POP = // "\"opaque field\": 123"
"{"
"\"populations\": ["
"{"
"\"name\": \"dummy Name 1\","
"\"obj\": {},"
"\"subject\": \"dummy Subject 1\","
"\"spaceId\": \"" DUMMY_GUID_ID1 "\","
"\"assignmentTime\": \"2012-10-15T15:46:32\""
"},"
"{"
"\"name\": \"dummy Name 2\","
"\"obj\": {},"
"\"subject\": \"dummy Subject 2\","
"\"spaceId\": \"" DUMMY_GUID_ID1 "\""
"},"
"{"
"\"name\": \"dummy Name 3\","
"\"obj\": {},"
"\"subject\": \"dummy Subject 3\","
"\"spaceId\": \"" DUMMY_GUID_ID1 "\""
"}"
"]"
"}";
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/data", MockResultHelper::createSuccessResult(JSON_POP));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-primarystoremapping")
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(getMockedSecondaryPrimaryStoreMapping()));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(getMockedNotifyPrimaryStoreUpdate()));
}
}
ListenerHandler<EventNotification> handler = getFacade().getEventClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
// Waiting for events to be sent there's no blocking popUnsentEvent
waitForStartEventSessionSuccess();
// Ensure the periodic job is started before going to suspended mode
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::EventConfigSuccess, true));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getEventClient().popUnsentEvents(String())))
<< "This will stop the periodic jobs.";
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingFailure, true))
<< "Failing a event request will stop the periodic job.";
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_FALSE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true))
<< "No events should be sent. The periodic job shouldn't be restarted.";
}
#endif //!defined(US_DLL)
#if !defined(US_DLL)
/// @test Ensures the extend session job restarts after a suspended state
/// @note This test checks the case where the user has a uplay account
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ExtendSessionAfterSuspendedModeUplayUser)
{
const uint8 SHORT_SESSION_DURATION_SECONDS = 10;
{
const MockAsyncResult sessionResult = getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, true);
mockFullLogin(&sessionResult);
}
HighResolutionChrono sessionTime;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
{
const uint8 LONG_SESSION_DURATION_SECONDS = 50;
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/sessions")
// Set a longer session here to avoid flakiness at the end of the test
// (basically, no new extend session should be triggered)
.WillOnce(testing::Return(getMockedLoginShortSession(LONG_SESSION_DURATION_SECONDS, true)));
}
{
// PS4 and XONE mocked suspended test will always do the put
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
TestSuspendedMode_BF::setupMockExpectationsForPrimaryStoreAfterSuspendedMode(getMockHttpClientImpl(),
getMockedNotifyPrimaryStoreUpdate());
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Sleep to resume "just before" the end of the session (85% of the session validity) (i.e. slightly after the moment where the
// automatic extend session would have been triggered if not suspended which is at 80% of the session duration),
// but with some time to proceed to the resume and the renew session before expiration
const uint64 sessionDurationMs = ClockSteady::getMilliFromNano(sessionTime.getElapsed());
const int64 sleepDuration = SHORT_SESSION_DURATION_SECONDS * 1000 * 85 / 100 - sessionDurationMs;
if (sleepDuration > 0)
{
US_TEST_NS::Helper::sleep(sleepDuration);
}
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, Duration<>(15ull));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
// This sleep is to catch the unwanted call to renew session in case the renew session expiration is not well calculated
// (if the waiting times are kept from the ones computed during the resume process, when relaunching the extendSession job)
// 4 seconds to be slightly above the worst case : expiration is in 10 - 8 = 2 second.
US_TEST_NS::Helper::sleep(2000);
}
/// @test Ensures the extend session job restarts after a suspended state
/// @note This test checks the case where the user does not have a uplay account (meaning an additional extend session)
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ExtendSessionAfterSuspendedMode)
{
{
const uint8 SHORT_SESSION_DURATION_SECONDS = 10;
const uint8 LONG_SESSION_DURATION_SECONDS = 50;
const MockAsyncResult sessionResult = getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, false);
mockFullLogin(&sessionResult);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/sessions")
// Extend session from the DetectLinkedUser step
.WillOnce(testing::Return(getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, false)))
// Extend session from the scheduling job.
// Set a longer session here to avoid flakiness at the end of the test
// (basically, no new extend session should be triggered)
.WillOnce(testing::Return(getMockedLoginShortSession(LONG_SESSION_DURATION_SECONDS, false)));
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
TestSuspendedMode_BF::setupMockExpectationsForPrimaryStoreAfterSuspendedMode(getMockHttpClientImpl(),
getMockedNotifyPrimaryStoreUpdate());
}
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Sleep 4 seconds to resume "just before" the end of the session (i.e. slightly after the moment where the
// automatic extend session would have been triggered if not suspended which is at 80% of the session duration),
// but with some time to proceed to the resume and the renew session before expiration
US_TEST_NS::Helper::sleep(4000);
AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
{
// Extend session from the DetectLinkedUser step
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
{
// Extend session from the scheduling job
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
// This sleep is to catch the unwanted call to renew session in case the renew session expiration is not well calculated
// (if the waiting times are kept from the ones computed during the resume process, when relaunching the extendSession job)
// 2 seconds to be slightly above the worst case : expiration is in 10 - 8 = 2 second.
US_TEST_NS::Helper::sleep(4000);
}
/// @test Ensures the extend session periodic job is still there even when an extend session has been triggered and failed
/// @note The extend session is actually triggered during the resume from background, because the user has no uplay account
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ExtendSessionAfterBackgroundMode)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 404", LogLevel::Error, Times(1));
});
{
const uint8 SHORT_SESSION_DURATION_SECONDS = 5;
const uint8 LONG_SESSION_DURATION_SECONDS = 50;
const MockAsyncResult sessionResult = getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, false);
mockFullLogin(&sessionResult);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/sessions")
// Extend session from the DetectLinkedUser step
.WillOnce(testing::Return(MockResultHelper::createRestErrorResult(RestStatusCode::Error404, 1000)))
// Extend session from the scheduling job.
// Set a longer session here to avoid flakiness at the end of the test
// (basically, no new extend session should be triggered)
.WillOnce(testing::Return(getMockedLoginShortSession(LONG_SESSION_DURATION_SECONDS, false)));
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
#if defined(US_PRIMARY_STORE_WITH_API)
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillRepeatedly(testing::Return(mockResultNotification));
}
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> authentificationNotifListener = getFacade().getAuthenticationClient().createNotificationListener();
#if defined(US_PRIMARY_STORE_WITH_API)
ListenerHandler<SecondaryStoreNotification> secondaryStoreNotifListener = getFacade().getSecondaryStoreClient().createNotificationListener();
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
{
// Extend session from the scheduling job
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(authentificationNotifListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
#if defined(US_PRIMARY_STORE_WITH_API)
//After background the notification should be received
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(secondaryStoreNotifListener, SecondaryStoreNotificationType::InventorySyncUpdate,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
#endif
}
#endif
#if defined(US_ENABLE_UPLAY_LOGIN) || defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_KILI)
/// @test Ensures that the a new session is created when coming back from suspended and the session has expired
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_CreateNewSessionWhenResumingFromSuspendedModeAfterSessionHasExpired)
{
{
const uint8 SHORT_SESSION_DURATION_SECONDS = 5;
const MockAsyncResult shortSessionResult = getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, true);
mockFullLogin(&shortSessionResult);
}
//Start creation of session
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Sleep 7 seconds to resume after the end of the session (i.e. slightly after the moment where the
// automatic creation of a new session will be triggered from JobDetectLink
US_TEST_NS::Helper::sleep(7000);
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/profiles/sessions")
// Create new session from the jobDetectLink
.WillOnce(testing::Return(getMockedLoginResponse()));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(mockResultNotification));
}
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
{
// Wait for notification for change of sessionInfo since we have a new login.
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
}
#endif
#if defined(US_ENABLE_UPLAY_LOGIN)
/// @test Ensures that the a new session is created when coming back from suspended and the session has expired with a RememberMe ticket
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_CreateNewSessionWhenResumingFromSuspendedModeAfterSessionHasExpiredWithRememberMeTicket)
{
{
const uint8 SHORT_SESSION_DURATION_SECONDS = 5;
const MockAsyncResult shortSessionResult = getMockedLoginShortSession(SHORT_SESSION_DURATION_SECONDS, true);
mockFullLogin(&shortSessionResult);
}
const PlayerCredentials credentials = PlayerCredentials(NS_COMMON::Options::email().c_str(), NS_COMMON::Options::password().c_str(), RememberMe::Enabled);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(credentials, {}, {})));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Sleep 7 seconds to resume after the end of the session (i.e. slightly after the moment where the
// automatic creation of a new session will be triggered from JobDetectLink
US_TEST_NS::Helper::sleep(7000);
// SuspdendedMode expects
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data",
getMockedPopulationsResponse());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/profiles/sessions")
// Create new session from the jobDetectLink
.WillOnce(testing::Return(getMockedLoginResponse()));
}
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
{
// Wait for notification for change of sessionInfo since we have a new login.
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
}
#endif
#if defined(US_ENABLE_UPLAY_LOGIN) || defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_KILI)
/// @test Ensures that there is no new playerSessionId when coming back from suspended despite a new UbiServices
/// session has been created.
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_CreateNewSessionWhenResumingFromSuspendedModeAfterSessionHasExpiredEventContext)
{
HttpPost httpRequestBeforeSuspend(StringUrl(""), String());
HttpPost httpRequestAfterSuspend(StringUrl(""), String());
{
const MockAsyncResult shortSessionResult = getMockedLoginShortSession(5, true); // SHORT_SESSION_DURATION_SECONDS = 5
const MockAsyncResult eventConfigMock = MockResultHelper::createSuccessResult(EventsConfigMockHelper::getBody(2).renderContent()); // SEND_PERIOD_SEC = 2
mockFullLogin(&shortSessionResult, nullptr, nullptr, nullptr, &eventConfigMock);
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&httpRequestBeforeSuspend)), testing::Return(MockResultHelper::createSuccessResult())))
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&httpRequestAfterSuspend)), testing::Return(MockResultHelper::createSuccessResult())));
}
ListenerHandler<EventNotification> handler = getFacade().getEventClient().createNotificationListener();
getFacade().getEventClient().pushEvent(EventInfoContextStart("myContextType1", "MyContextName1"));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
// Ensure the periodic job is started before going to suspended mode
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::EventConfigSuccess, true));
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true));
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
TestSuspendedMode_BF::setupMockExpectationsForPrimaryStoreAfterSuspendedMode(getMockHttpClientImpl(),
getMockedNotifyPrimaryStoreUpdate());
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
// Sleep 7 seconds to resume after the end of the session (i.e. slightly after the moment where the
// automatic creation of a new session will be triggered from JobDetectLink
US_TEST_NS::Helper::sleep(7000);
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/profiles/sessions")
// Create new session from the jobDetectLink
.WillOnce(testing::Return(getMockedLoginResponse()));
}
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
const AsyncResultBatch<Facade*, Empty> resultSuspToFg = TestSuspendedMode_BF::changeState(PlatformHelper::Foreground);
getFacade().getEventClient().pushEvent(EventInfoContextStop("myContextType1", "MyContextName1"));
{
// Wait for notification for change of sessionInfo since we have a new login.
const AuthenticationNotificationType notif = TestSuspendedMode_BF::waitForExtendSessionNotification(notificationListener, 15ull * 1000ull * 1000ull * 1000ull);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
ASSERT_TRUE(AsyncHelper::waitSuccess(resultSuspToFg));
ASSERT_TRUE(TestSuspendedMode_BF::waitForEventNotification(handler, EventNotificationType::SendingSuccessful, true));
// Expect the playerSessionId to be the same in the two requests
const String gameSessionIdBeforeSuspended = Json(httpRequestBeforeSuspend.getBodyAsString())["gameSessionId"].getValueString();
const String gameSessionIdAfterSuspended = Json(httpRequestAfterSuspend.getBodyAsString())["gameSessionId"].getValueString();
const String playerSessionIdBeforeSuspended = Json(httpRequestBeforeSuspend.getBodyAsString())["playerSessionId"].getValueString();
const String playerSessionIdAfterSuspended = Json(httpRequestAfterSuspend.getBodyAsString())["playerSessionId"].getValueString();
EXPECT_FALSE(gameSessionIdBeforeSuspended.isEmpty());
EXPECT_FALSE(gameSessionIdAfterSuspended.isEmpty());
EXPECT_EQ(gameSessionIdAfterSuspended, gameSessionIdBeforeSuspended);
EXPECT_FALSE(playerSessionIdBeforeSuspended.isEmpty());
EXPECT_FALSE(playerSessionIdAfterSuspended.isEmpty());
EXPECT_EQ(playerSessionIdAfterSuspended, playerSessionIdBeforeSuspended);
}
#endif
#if !defined(US_SDK_LIGHT_MOBILE)
#if defined(US_PRIMARY_STORE_ENABLED) && !defined(US_TARGET_SWITCH)
#define US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION
#endif
/// @test Ensures the notification to the secondary store service is sent on the first call to the inventory
/// when going back from background
#if defined(US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION)
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_SecondaryStoreUpdateNotificationAfterBackgroundMode)
#else
/// @disabled With notification not supported, this test is just like requesting the inventory "normally"
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, DISABLED_USNOT_SecondaryStoreUpdateNotificationAfterBackgroundMode)
#endif
{
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
const MockAsyncResult mockResultMapping = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreMapping());
StringStream expectedUrlMapping;
expectedUrlMapping << "/" << getFacade().getWorkingSpaceId() << "/mock-spaces-primarystoremapping";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlMapping.getContent())
.WillRepeatedly(testing::Return(mockResultMapping));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultNotification))
.WillRepeatedly(testing::Return(mockResultNotification));
const MockAsyncResult mockResultInventory = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderEmptyResult("items"));
StringStream expectedUrlInventory;
expectedUrlInventory << "/" << getFacade().getAuthenticationClient().getSessionInfo().getProfileId() << "/mock-profiles-inventory";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlInventory.getContent())
.WillOnce(testing::Return(mockResultInventory))
.WillOnce(testing::Return(mockResultInventory));
}
#if defined(US_PRIMARY_STORE_WITHOUT_API)
{
PrimaryStoreInventoryItem dlc;
dlc.m_id = UPLAYPC_DUMMY_DLCID;
dlc.m_type = PrimaryStoreItemType::Durable;
dlc.m_state = PrimaryStoreInventoryItem::InventoryItemState::ReadyToUse;
dlc.m_balance = 1;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getPrimaryStoreClient().updatePrimaryStoreProducts({ dlc })));
}
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getSecondaryStoreClient().requestInventory()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
#if defined(US_PRIMARY_STORE_WITHOUT_API)
{
PrimaryStoreInventoryItem consumable;
consumable.m_id = UPLAYPC_DUMMY_CONSUMABLEID;
consumable.m_type = PrimaryStoreItemType::Consumable;
consumable.m_state = PrimaryStoreInventoryItem::InventoryItemState::ReadyToUse;
consumable.m_balance = 8;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getPrimaryStoreClient().updatePrimaryStoreProducts({ consumable })));
}
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getSecondaryStoreClient().requestInventory()));
}
/// @test Ensures the notification to the secondary store service is sent on the first call to the inventory
/// when going back from background
#if defined(US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION)
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_SecondaryStoreUpdateNotificationAfterSuspendedMode)
#else
/// @disabled With notification not supported, this test is just like requesting the inventory "normally"
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, DISABLED_USNOT_SecondaryStoreUpdateNotificationAfterSuspendedMode)
#endif
{
#if defined(US_LOG_ENABLED) && defined(DEBUGGING)
LoggingHelper::enableVerbose();
LoggingHelper::enableMultiLines();
#endif
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
const MockAsyncResult mockResultMapping = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreMapping());
StringStream expectedUrlMapping;
expectedUrlMapping << "/" << getFacade().getWorkingSpaceId() << "/mock-spaces-primarystoremapping";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlMapping.getContent())
.WillRepeatedly(testing::Return(mockResultMapping));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultNotification))
.WillRepeatedly(testing::Return(mockResultNotification));
const MockAsyncResult mockResultInventory = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderEmptyResult("items"));
StringStream expectedUrlInventory;
expectedUrlInventory << "/" << getFacade().getAuthenticationClient().getSessionInfo().getProfileId() << "/mock-profiles-inventory";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlInventory.getContent())
.WillOnce(testing::Return(mockResultInventory))
.WillOnce(testing::Return(mockResultInventory));
}
#if defined(US_PRIMARY_STORE_WITHOUT_API)
{
PrimaryStoreInventoryItem dlc;
dlc.m_id = UPLAYPC_DUMMY_DLCID;
dlc.m_type = PrimaryStoreItemType::Durable;
dlc.m_state = PrimaryStoreInventoryItem::InventoryItemState::ReadyToUse;
dlc.m_balance = 1;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getPrimaryStoreClient().updatePrimaryStoreProducts({ dlc })));
}
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getSecondaryStoreClient().requestInventory()));
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
#if defined(US_PRIMARY_STORE_WITHOUT_API)
{
PrimaryStoreInventoryItem consumable;
consumable.m_id = UPLAYPC_DUMMY_CONSUMABLEID;
consumable.m_type = PrimaryStoreItemType::Consumable;
consumable.m_state = PrimaryStoreInventoryItem::InventoryItemState::ReadyToUse;
consumable.m_balance = 8;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getPrimaryStoreClient().updatePrimaryStoreProducts({ consumable })));
}
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getSecondaryStoreClient().requestInventory()));
}
/// @test Ensures the notification to the secondary store service is NOT sent on the first call to the inventory
/// when going back from background if no update occurred
#if defined(US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION)
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_SecondaryStoreUpdateNotificationAfterBackgroundModeNoUpdate)
#else
/// @disabled With notification not supported, this test is just like requesting the inventory "normally"
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, DISABLED_USNOT_SecondaryStoreUpdateNotificationAfterBackgroundModeNoUpdate)
#endif
{
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
const MockAsyncResult mockResultMapping = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreMapping());
StringStream expectedUrlMapping;
expectedUrlMapping << "/" << getFacade().getWorkingSpaceId() << "/mock-spaces-primarystoremapping";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlMapping.getContent())
.WillRepeatedly(testing::Return(mockResultMapping));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultNotification))
.WillRepeatedly(testing::Return(mockResultNotification));
const MockAsyncResult mockResultInventory = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderEmptyResult("items"));
StringStream expectedUrlInventory;
expectedUrlInventory << "/" << getFacade().getAuthenticationClient().getSessionInfo().getProfileId() << "/mock-profiles-inventory";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlInventory.getContent())
.WillOnce(testing::Return(mockResultInventory))
.WillOnce(testing::Return(mockResultInventory));
}
#if defined(US_PRIMARY_STORE_WITHOUT_API)
{
PrimaryStoreInventoryItem dlc;
dlc.m_id = UPLAYPC_DUMMY_DLCID;
dlc.m_type = PrimaryStoreItemType::Durable;
dlc.m_state = PrimaryStoreInventoryItem::InventoryItemState::ReadyToUse;
dlc.m_balance = 1;
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getPrimaryStoreClient().updatePrimaryStoreProducts({ dlc })));
}
#endif
SecondaryStoreClient& clientSecondaryStore = getFacade().getSecondaryStoreClient();
ASSERT_TRUE(AsyncHelper::waitSuccess(clientSecondaryStore.requestInventory()));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(AsyncHelper::waitSuccess(clientSecondaryStore.requestInventory()));
}
#if !defined(US_DLL)
/// Checks that notification is sent when returning from background
/// triggered by primary store sync.
#if defined(US_PRIMARY_STORE_WITH_API)
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, LOCAL_CheckPrimaryStoreSyncNotificationWhenReturningFromBackground)
#else
/// @disabled With notification not supported, this test is just like requesting the inventory "normally"
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, DISABLED_LOCAL_CheckPrimaryStoreSyncNotificationWhenReturningFromBackground)
#endif
{
{
mockFullLogin();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
HttpPost requestNotification(StringUrl(""), "");
{
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestNotification)), testing::Return(mockResultNotification)));
const MockAsyncResult mockResultInventory = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderEmptyOffersResult("items"));
StringStream expectedUrlInventory;
expectedUrlInventory << "/" << getFacade().getAuthenticationClient().getSessionInfo().getProfileId() << "/mock-profiles-inventory";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlInventory.getContent())
.WillOnce(testing::Return(mockResultInventory));
}
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
}
// Go to background and back to foreground to trigger Sync notification for primary store
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
// Call to secondary store to ensure that primary store sync has been completed
SecondaryStoreClient& clientSecondaryStore = getFacade().getSecondaryStoreClient();
ASSERT_TRUE(AsyncHelper::waitSuccess(clientSecondaryStore.requestInventoryItems({ StoreItemId("11111111-2222-3333-4444-555566667777") })));
const SpaceId expectedSpaceId = getFacade().getWorkingSpaceId();
// Check parameters for the notification request
ASSERT_NE(size_t(0), requestNotification.getBodyAsString().getLength());
EXPECT_NE(String::npos, requestNotification.getBodyAsString().findSubstringCase(expectedSpaceId));
#if defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
// Check that psn parameters are present in the notification
const Json body(requestNotification.getBodyAsString());
EXPECT_TRUE(body.isValid());
if (body.isValid())
{
EXPECT_TRUE(body["psn.issuerid"].isTypeNumber());
EXPECT_FALSE(body["psn.code"].getValueString().isEmpty());
EXPECT_FALSE(body["psn.clientId"].getValueString().isEmpty());
}
#endif
}
/// Checks that notification is sent when returning from suspended mode
/// triggered by primary store sync.
#if defined(US_PRIMARY_STORE_WITH_API) && !defined(US_TARGET_SWITCH)
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, LOCAL_CheckPrimaryStoreSyncNotificationWhenReturningFromSuspendedMode)
#else
/// @disabled With notification not supported, this test is just like requesting the inventory "normally"
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, DISABLED_LOCAL_CheckPrimaryStoreSyncNotificationWhenReturningFromSuspendedMode)
#endif
{
{
mockFullLogin();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
}
HttpPost requestNotification(StringUrl(""), "");
{
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestNotification)), testing::Return(mockResultNotification)));
const MockAsyncResult mockResultInventory = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderEmptyOffersResult("items"));
StringStream expectedUrlInventory;
expectedUrlInventory << "/" << getFacade().getAuthenticationClient().getSessionInfo().getProfileId() << "/mock-profiles-inventory";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlInventory.getContent())
.WillOnce(testing::Return(mockResultInventory));
}
{
// PS4 and XONE mocked suspended test will always do the put because of the consumable balance
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
}
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
// Go to background and back to foreground to trigger Sync notification for primary store
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
// Call to secondary store to ensure that primary store sync has been completed
SecondaryStoreClient& clientSecondaryStore = getFacade().getSecondaryStoreClient();
ASSERT_TRUE(AsyncHelper::waitSuccess(clientSecondaryStore.requestInventoryItems({ StoreItemId("11111111-2222-3333-4444-555566667777") })));
const SpaceId expectedSpaceId = getFacade().getWorkingSpaceId();
// Check parameters for the notification request
EXPECT_NE(String::npos, requestNotification.getBodyAsString().findSubstringCase(expectedSpaceId));
#if defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
// Check that psn parameters are present in the notification
const Json body(requestNotification.getBodyAsString());
EXPECT_TRUE(body.isValid());
if (body.isValid())
{
EXPECT_TRUE(body["psn.issuerid"].isTypeNumber());
EXPECT_FALSE(body["psn.code"].getValueString().isEmpty());
EXPECT_FALSE(body["psn.clientId"].getValueString().isEmpty());
}
#endif
}
#if defined(US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION)
#if defined(US_PRIMARY_STORE_WITHOUT_API)
///@test Checks that, when calling initialize/update primaryStore and then the sdk goes in background mode, the retry sync is still running.
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_InitializePrimaryStoreBeforeBackgroundModeDoesNotStopPrimaryStoreSyncRetries)
{
waitForPostLoginCompletion();
{
// Secondary Primary Store Mapping
const MockAsyncResult mappingResult = MockResultHelper::createSuccessResult(TestPrimaryStoreClient_BF::renderPrimaryStoreMapping());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-primarystoremapping")
.WillRepeatedly(testing::Return(mappingResult));
const MockAsyncResult mockErrorRestResult = MockResultHelper::createRestErrorResult(RestStatusCode::Error301, 1003, ""); // arbitrary error
const MockAsyncResult mockResultPartialSuccess = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreUpdateResult());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultPartialSuccess))
.WillOnce(testing::Return(mockErrorRestResult)).RetiresOnSaturation();
}
ListenerHandler<SecondaryStoreNotification> handler = getFacade().getSecondaryStoreClient().createNotificationListener();
PrimaryStoreClient& client = getFacade().getPrimaryStoreClient();
ASSERT_TRUE(AsyncHelper::waitSuccess(client.initializePrimaryStoreProducts(TestPrimaryStoreClient_BF::getInventoryWithItemsForRetrySyncTrigger(10)))); //arbitrary value
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
//After background the notification should be received
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncUpdate,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
//After background the job retry sync should still be running
const SpaceId parametersSpaceId = getFacade().getWorkingSpaceId();
ASSERT_TRUE(SessionManagerStoreProxy::hasPrimaryStorePeriodicSyncResult(getFacadeInternal(), parametersSpaceId));
ASSERT_TRUE(SessionManagerStoreProxy::getPeriodicSyncResult(getFacadeInternal(), parametersSpaceId).isProcessing());
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncError,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
ASSERT_FALSE(SessionManagerStoreProxy::hasPrimaryStorePeriodicSyncResult(getFacadeInternal(), parametersSpaceId));
}
#else
///@test Checks that, when calling primaryStore sync and then the sdk goes in background mode, the retry sync is still running.
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_PrimaryStoreBeforeBackgroundModeDoesNotStopPrimaryStoreSyncRetries)
{
{
mockLogin(getMockedLoginResponse(), getMockedParametersApplication(), getMockedParametersSpace());
setupWebsocketMock();
MockEventConfigHelper::mockEventConfig(getMockHttpClientImpl());
// Secondary Primary Store Mapping
const MockAsyncResult mappingResult = getMockedSecondaryPrimaryStoreMapping();
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-primarystoremapping")
.WillRepeatedly(testing::Return(mappingResult));
const MockAsyncResult mockErrorRestResult = MockResultHelper::createRestErrorResult(RestStatusCode::Error301, 1003, "");
const MockAsyncResult mockResultPartialSuccess = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreUpdateResult());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultPartialSuccess))
.WillOnce(testing::Return(mockErrorRestResult)).RetiresOnSaturation();
}
ListenerHandler<SecondaryStoreNotification> handler = getFacade().getSecondaryStoreClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
//After background the notification should be received and the
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncUpdate,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
//After background the job retry sync should still be running
const SpaceId parametersSpaceId = getFacade().getWorkingSpaceId();
ASSERT_TRUE(SessionManagerStoreProxy::hasPrimaryStorePeriodicSyncResult(getFacadeInternal(), parametersSpaceId));
ASSERT_TRUE(SessionManagerStoreProxy::getPeriodicSyncResult(getFacadeInternal(), parametersSpaceId).isProcessing());
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncError,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
ASSERT_FALSE(SessionManagerStoreProxy::hasPrimaryStorePeriodicSyncResult(getFacadeInternal(), parametersSpaceId));
}
///@test Checks that, when calling primaryStore sync and then the sdk goes in suspended mode, the retry sync gets canceled.
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_PrimaryStoreSyncBeforeSuspendedModeGetsCanceledAfterSuspended)
{
{
mockLogin(getMockedLoginResponse(), getMockedParametersApplication(), getMockedParametersSpace());
setupWebsocketMock();
MockEventConfigHelper::mockEventConfig(getMockHttpClientImpl());
// Secondary Primary Store Mapping
const MockAsyncResult mappingResult = getMockedSecondaryPrimaryStoreMapping();
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-primarystoremapping")
.WillRepeatedly(testing::Return(mappingResult));
const MockAsyncResult mockErrorRestResult = MockResultHelper::createRestErrorResult(RestStatusCode::Error301, 1003, "");
const MockAsyncResult mockResultPartialSuccess = MockResultHelper::createSuccessResult(StoreHelper::renderPrimaryStoreUpdateResult());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillOnce(testing::Return(mockResultPartialSuccess))
.WillOnce(testing::Return(mockErrorRestResult)).RetiresOnSaturation();
}
ListenerHandler<SecondaryStoreNotification> handler = getFacade().getSecondaryStoreClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncUpdate,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "parameters")
.WillOnce(testing::Return(getMockedParametersApplication()))
.WillOnce(testing::Return(getMockedParametersSpace()))
.RetiresOnSaturation();
}
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
const SpaceId parametersSpaceId = getFacade().getWorkingSpaceId();
ASSERT_TRUE(SessionManagerStoreProxy::hasPrimaryStorePeriodicSyncResult(getFacadeInternal(), parametersSpaceId));
ASSERT_FALSE(SessionManagerStoreProxy::getPeriodicSyncResult(getFacadeInternal(), parametersSpaceId).isProcessing());
ASSERT_TRUE(TestPrimarySecondaryStoreSync_BF::waitForNotification(handler, SecondaryStoreNotificationType::InventorySyncError,
TestSuspendedMode_BF::MOCK_PERIOD_JOB_WAIT_TIME));
}
#endif
#endif // defined(US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION)
#endif
#endif // !defined(US_SDK_LIGHT_MOBILE)
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, LOCAL_SuspendedModeWithCreateSessionFeatureSwitchOffDoesNotCreateSessionWhenComingBackFromSuspended)
{
{
const MockAsyncResult parametersSpaceMock = MockResultHelper::createSuccessResult(
ParametersSpaceMockHelper().changeFeatureSwitch(FeatureSwitchId::CreateSession, FeatureSwitchState::Disabled).getParameters().renderContent());
const MockAsyncResult parametersApplicationMock = getMockedParametersApplication();
mockLogin(getMockedLoginResponse(), parametersApplicationMock, parametersSpaceMock);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data") .Times(1);
US_EXPECT_CALL(US_TEST_NS::Action::GetConfigEvent).Times(0);
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents).Times(0);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-primarystoremapping").Times(0);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore").Times(0);
}
ASSERT_TRUE(AsyncHelper::waitFailureResponse(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {}), Errors::SKIPPED_FEATURESWITCH));
// Force a pop to validate that there isn't any call to the events service.
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getEventClient().popUnsentEvents("")));
ASSERT_FALSE(getFacade().getAuthenticationClient().getSessionInfo().hasValidSession());
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.Times(testing::AtMost(1))
.WillOnce(testing::Return(getMockedPopulationsResponse()));
}
// Go to background and back to foreground to trigger Sync notification for primary store
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_FALSE(getFacade().getAuthenticationClient().getSessionInfo().hasValidSession());
// Force a pop to validate that there isn't any call to the events service.
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getEventClient().popUnsentEvents("")));
}
#if !defined(US_DLL)
/// @test Validates config is retrieved and updated after suspended - foreground transition
/// FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId is OFF
/// Actual and retrieved SpaceID are the same
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ValidateConfigRetrievedAndUpdatedAfterSuspendedForegroundTransition)
{
setupDebugLogging();
{
Map<FeatureSwitchId, FeatureSwitchState> featureSwitches;
featureSwitches[FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId] = FeatureSwitchState::Disabled;
const auto parametersSpaceMock = MockResultHelper::createSuccessResult(ParametersSpaceMockHelper().changeFeatureSwitches(featureSwitches)
.getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(nullptr, nullptr, &parametersSpaceMock);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const SpaceId currentAppParametersSpaceId = getFacade().getWorkingSpaceId();
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(3, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
}
// SuspendedMode Expects
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-parameters")
.WillOnce(testing::Return(MockResultHelper::createSuccessResult(ParametersApplicationMockHelper().getParameters().renderContent())))
.WillOnce(testing::Return(MockResultHelper::createSuccessResult(TestSuspendedMode_BF::ParametersSpaceMockHelperUpdatedParams(20).getParameters().renderContent())));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
StringStream expectedUrlMapping;
expectedUrlMapping << "/" << getFacade().getWorkingSpaceId() << "/mock-spaces-primarystoremapping";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlMapping.getContent())
.WillRepeatedly(testing::Return(getMockedSecondaryPrimaryStoreMapping()));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillRepeatedly(testing::Return(mockResultNotification));
}
NotificationSource<ParametersNotification>::ListenerHandler handler = getFacade().getParametersClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
// We expect latest parameters to partially apply, since spaceId changed and feature switch is set to accept that case
ASSERT_TRUE(TestSuspendedMode_BF::waitForParametersNotification(handler, ParametersNotificationType::ApplicationParametersUpdated,
DurationMilli(5000)));
const SpaceId newParametersSpaceId = getFacade().getWorkingSpaceId();
// New config, but keep original spaceId
EXPECT_EQ(currentAppParametersSpaceId, newParametersSpaceId);
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(20, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
}
}
/// @test Validates config is retrieved and partially updated after suspended - foreground transition and SpaceId is different
/// Partially updated = force new config to use original SpaceId
/// FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId is OFF
/// Actual and retrieved SpaceID are NOT the same
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ValidateConfigRetrievedPartiallyUpdatedAfterSuspendedForegroundTransitionAndMismatchSpaceId)
{
setupDebugLogging();
{
Map<FeatureSwitchId, FeatureSwitchState> featureSwitches;
featureSwitches[FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId] = FeatureSwitchState::Disabled;
const auto parametersSpaceMock = MockResultHelper::createSuccessResult(ParametersSpaceMockHelper().changeFeatureSwitches(featureSwitches)
.getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(NULL, NULL, &parametersSpaceMock);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const SpaceId currentAppParametersSpaceId = getFacade().getWorkingSpaceId();
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(3, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
EXPECT_EQ(parametersInfo.m_featuresSwitches.m_parameters.end(), parametersInfo.m_featuresSwitches.m_parameters.find("ThisIsANewFeatureSwitchForParametersApplicationMockHelperWithDifferentSpaceId"));
}
{
const Json applicationParameters = TestSuspendedMode_BF::ParametersApplicationMockHelperWithDifferentSpaceId().getParameters();
const Json spaceParameters = TestSuspendedMode_BF::ParametersSpaceMockHelperUpdatedParams(10).getParameters();
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-parameters")
.WillOnce(testing::Return(MockResultHelper::createSuccessResult(applicationParameters.renderContent())))
.WillOnce(testing::Return(MockResultHelper::createSuccessResult(spaceParameters.renderContent())));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
StringStream expectedUrlMapping;
expectedUrlMapping << "/" << getFacade().getWorkingSpaceId() << "/mock-spaces-primarystoremapping";
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, expectedUrlMapping.getContent())
.WillRepeatedly(testing::Return(getMockedSecondaryPrimaryStoreMapping()));
const MockAsyncResult mockResultNotification = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::renderPrimaryStoreUpdateResult(true, false));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-profiles-inventory-primarystore")
.WillRepeatedly(testing::Return(mockResultNotification));
}
NotificationSource<ParametersNotification>::ListenerHandler handler = getFacade().getParametersClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
// We expect latest config to partially apply, since spaceId changed and feature switch is set to accept that case
ASSERT_TRUE(TestSuspendedMode_BF::waitForParametersNotification(handler, ParametersNotificationType::ApplicationParametersUpdatedPartially,
DurationMilli(5000)));
const SpaceId newParametersSpaceId = getFacade().getWorkingSpaceId();
// New config, but keep original spaceId
EXPECT_EQ(currentAppParametersSpaceId, newParametersSpaceId);
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(10, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
EXPECT_EQ(true, parametersInfo.m_featuresSwitches.m_parameters.find("ThisIsANewFeatureSwitchForParametersApplicationMockHelperWithDifferentSpaceId")->second);
}
}
/// @test Validates config is retrieved, not updated and current session is terminated, after suspended - foreground transition and SpaceId is different
/// FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId is ON
/// Actual and retrieved SpaceID are NOT the same
TEST_F(SUSPENDEDMODE_MOCK_NOLOGIN, USNOT_ValidateConfigRetrievedAndSessionTerminatedAfterSuspendedForegroundTransitionAndMismatchSpaceId)
{
setupDebugLogging();
{
Map<FeatureSwitchId, FeatureSwitchState> featureSwitches;
featureSwitches[FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId] = FeatureSwitchState::Enabled;
const auto parametersSpaceMock = MockResultHelper::createSuccessResult(ParametersSpaceMockHelper().changeFeatureSwitches(featureSwitches)
.getParameters().renderContent());
setupWebsocketMock();
mockFullLogin(NULL, NULL, &parametersSpaceMock);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(getPlayerCredentials(), {}, {})));
waitForPostLoginCompletion();
const SpaceId currentAppParametersSpaceId = getFacade().getWorkingSpaceId();
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(3, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
}
{
const auto parametersApplicationResult = MockResultHelper::createSuccessResult(TestSuspendedMode_BF::ParametersApplicationMockHelperDefaultPopulations
(TestPopulations_BF::POPULATION_NAME_DEFAULT, TestPopulations_BF::POPULATION_SUBJECT_DEFAULT, SpaceId(TestPopulations_BF::SPACE_ID_FOR_NEW_POPULATION)).getParameters().renderContent());
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-parameters")
.WillOnce(testing::Return(parametersApplicationResult));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "/profiles/me/mock-populations/data")
.WillRepeatedly(testing::Return(getMockedPopulationsResponse()));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_DELETE, "/profiles/sessions")
.WillOnce(testing::Return(MockResultHelper::createSuccessResult("{}")));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "/mock-events")
.WillOnce(testing::Return(MockResultHelper::createSuccessResult("{}")))
.RetiresOnSaturation();
}
NotificationSource<ParametersNotification>::ListenerHandler paramsNotifListener = getFacade().getParametersClient().createNotificationListener();
NotificationSource<AuthenticationNotification>::ListenerHandler authNotifListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
// We DO NOT expect latest config to be apply, since spaceId changed and feature switch is set to NOT accept that case
ASSERT_FALSE(TestSuspendedMode_BF::waitForParametersNotification(paramsNotifListener, ParametersNotificationType::ApplicationParametersUpdatedPartially,
DurationMilli(5000)));
ASSERT_TRUE(TestSuspendedMode_BF::waitForAuthentificationNotification(authNotifListener, AuthenticationNotificationType::SessionConfigurationUpdateMismatchSpaceIDSessionTerminated,
DurationMilli(5000)));
const SpaceId newParametersSpaceId= getFacade().getWorkingSpaceId();
// Same config, same spaceId
EXPECT_EQ(currentAppParametersSpaceId, newParametersSpaceId);
{
const ParametersInfo& parametersInfo = ParametersClientProxy::getParametersInfo(getFacadeInternal());
EXPECT_EQ(3, parametersInfo.m_paramsSettingsHttpInternal.m_maxCount);
}
// Session is terminated
EXPECT_FALSE(getFacade().getAuthenticationClient().getSessionInfo().hasValidSession());
#if !defined(US_SDK_LIGHT_MOBILE)
SecondaryStoreClient& clientSecondaryStore = getFacade().getSecondaryStoreClient();
const AsyncResult<Vector<InventoryElement> > result = clientSecondaryStore.requestInventory();
EXPECT_FALSE(AsyncHelper::waitSuccess(clientSecondaryStore.requestInventory()));
#endif
}
/// @test Validates config is retrieved and updated after suspended - foreground transition
/// FeatureSwitchId::TerminateSessionOnConfigurationUpdateMismatchSpaceId is ON
/// Actual and retrieved SpaceID are the same
#if defined(US_TARGET_SWITCH)
TEST_F(SUSPENDEDMODE, DISABLED_US_ValidateConfigRetrievedAndUpdatedAfterSuspendedForegroundTransition)
#else
TEST_F(SUSPENDEDMODE, US_ValidateConfigRetrievedAndUpdatedAfterSuspendedForegroundTransition)
#endif
{
setupDebugLogging();
#if defined(US_LOG_ENABLED) && defined(DEBUGGING)
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Application and Space paramaters were updated after coming back from suspended.", LogLevel::Info, Times(1));
});
#endif
NotificationSource<ParametersNotification>::ListenerHandler paramsNotifListener = getFacade().getParametersClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Suspended)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(TestSuspendedMode_BF::waitForParametersNotification(paramsNotifListener, ParametersNotificationType::ApplicationParametersUpdated,
DurationMilli(5000)));
}
/// @test Validates config is NOT retrieved and updated after background - foreground transition
#if defined(US_TARGET_SWITCH)
TEST_F(SUSPENDEDMODE, DISABLED_US_ValidateConfigNotRetrievedAndUpdatedAfterBackgroundForegroundTransition)
#else
TEST_F(SUSPENDEDMODE, US_ValidateConfigNotRetrievedAndUpdatedAfterBackgroundForegroundTransition)
#endif
{
setupDebugLogging();
#if defined(US_LOG_ENABLED) && defined(DEBUGGING)
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Application and Space paramaters were updated after coming back from suspended.", LogLevel::Info, Times(0));
});
#endif
NotificationSource<ParametersNotification>::ListenerHandler paramsNotifListener = getFacade().getParametersClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Background)));
ASSERT_TRUE(AsyncHelper::waitSuccess(TestSuspendedMode_BF::changeState(PlatformHelper::Foreground)));
ASSERT_FALSE(TestSuspendedMode_BF::waitForParametersNotification(paramsNotifListener, ParametersNotificationType::ApplicationParametersUpdated,
DurationMilli(5000)));
}
#endif
#if defined(US_TARGET_SWITCH)
/// @test Validate that Foreground to Suspended is deprecated through PlatfromHelper::changeState
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_ForegroundSuspendedTransitionDeprecated)
{
ASSERT_TRUE(PlatformHelper::getState() == PlatformHelper::Foreground);
auto foregroundToSuspendedAsync = PlatformHelper::changeState(PlatformHelper::Suspended);
ASSERT_TRUE(AsyncHelper::waitSuccess(foregroundToSuspendedAsync));
ASSERT_TRUE(foregroundToSuspendedAsync.getError().m_description == "Switch SDK uses automatic suspended/foreground detection");
}
/// @test Validate that Background to Suspended is deprecated through PlatfromHelper::changeState
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_BackgroundSuspendedTransitionDeprecated)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Background)));
ASSERT_TRUE(PlatformHelper::getState() == PlatformHelper::Background);
auto foregroundToSuspendedAsync = PlatformHelper::changeState(PlatformHelper::Suspended);
ASSERT_TRUE(AsyncHelper::waitSuccess(foregroundToSuspendedAsync));
ASSERT_TRUE(foregroundToSuspendedAsync.getError().m_description == "Switch SDK uses automatic suspended/foreground detection");
}
/// @test Validate that Foreground to Background and Background to Forefround is supported through PlatfromHelper::changeState
TEST_F(SUSPENDEDMODE_MOCK_LOGIN, USNOT_BackgroundForegroundTransitionAndForegroundBackgroundTransition)
{
ASSERT_TRUE(PlatformHelper::getState() == PlatformHelper::Foreground);
ASSERT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Background)));
ASSERT_TRUE(PlatformHelper::getState() == PlatformHelper::Background);
ASSERT_TRUE(AsyncHelper::waitSuccess(PlatformHelper::changeState(PlatformHelper::Foreground)));
ASSERT_TRUE(PlatformHelper::getState() == PlatformHelper::Foreground);
}
#endif
#undef US_PLATFORM_WITH_PRIMARYSTORE_NOTIFICATION
#undef UPLAYPC_DUMMY_DLCID
#undef UPLAYPC_DUMMY_CONSUMABLEID
};