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

220 lines
11 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#include "tests/common/helpers.h"
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/mockResultHelper.h"
#include "tests/mock/parametersMockHelper.h"
#include <../private/ubiservices/core/extensions/enumeration.h>
namespace US_NS {;
US_DEFINE_TEST(TestExtendSession);
typedef AuthenticationFixture<1> EXTEND_SESSION;
typedef LoginMockFixture<false> EXTEND_SESSION_MOCK_NOLOGIN;
namespace TestSuspendedMode_BF
{
#if defined(US_SDK_S2S)
const char* const EXTEND_SESSION_ENDPOINT = "/applications/sessions";
#else
const char* const EXTEND_SESSION_ENDPOINT = "/profiles/sessions";
#endif
#if !defined(US_SDK_S2S)
AuthenticationNotificationType waitForExtendSessionNotification(Facade& facade, DurationNano waitTime);
#endif
AuthenticationNotificationType waitForExtendSessionNotification(ListenerHandler<AuthenticationNotification>& listener, DurationNano waitTime);
}
namespace TestExtendSession_BF
{
AuthenticationNotificationType waitForNotification(
ListenerHandler<AuthenticationNotification>& listener,
DurationMicro waitNano = DurationMicro(DurationMilli(NS_COMMON::DEFAULT_WAIT_TIME)))
{
return TestSuspendedMode_BF::waitForExtendSessionNotification(listener, DurationNano(waitNano));
}
}
#if !defined(US_DLL)
#if !defined(DECLARE_TEST_EXTEND_SESSION_HELPER)
#define DECLARE_TEST_EXTEND_SESSION_HELPER
struct TestExtendSessionHelper
{
US_FRIEND_TEST(EXTEND_SESSION, US_ExtendSession);
US_FRIEND_TEST(USTK_NOLOGIN_NOSCHEDULER, USNOT_ExerciseRenewTicket);
static void reduceSessionDuration(Facade& facade, uint64 expirationTimeMs); // For test purposes ONLY
};
#endif // !defined(DECLARE_TEST_EXTEND_SESSION_HELPER)
TEST_F(EXTEND_SESSION, US_ExtendSession)
{
//#define ENABLING_VERBOSE_LOGGING
#if defined(ENABLING_VERBOSE_LOGGING)
LoggingHelper::enableVerbose();
LoggingHelper::enableMultiLines();
#endif
//setupDebugLogging();
waitForPostLoginCompletion();
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
TestExtendSessionHelper::reduceSessionDuration(getFacade(), ClockSteady::getTimeMilli() + 500); // Setup expiration
ASSERT_EQ(AuthenticationNotificationType::SessionInfoChanged, TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(5))));
const SessionInfo sessionInfo = getFacade().getAuthenticationClient().getSessionInfo();
ASSERT_TRUE(sessionInfo.hasValidSession());
#if defined(US_SDK_S2S)
EXPECT_FALSE(sessionInfo.getTicket().isEmpty());
#else
EXPECT_FALSE(sessionInfo.getNameOnPlatform().isEmpty());
EXPECT_TRUE(sessionInfo.getProfileId().isValid());
// Running next line triggers an assert if the PlayerCredential is not set.
sessionInfo.getPlayerCredentials();
#endif
}
#endif
/// @test Checks that the extend session is retried appropriately
TEST_F(EXTEND_SESSION_MOCK_NOLOGIN, USNOT_LONG_ExtendSessionRetry)
{
{
const uint8 SESSION_DURATION_SECONDS = 20; // TODO: Review this value to shorten the test duration
const MockAsyncResult sessionResult = getMockedLoginShortSession(SESSION_DURATION_SECONDS, false);
const MockAsyncResult failedExtendSession = MockResultHelper::createRestErrorResult(RestStatusCode::Error404, 1000);
mockFullLogin(&sessionResult);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, TestSuspendedMode_BF::EXTEND_SESSION_ENDPOINT)
.Times(3)
.WillOnce(testing::Return(failedExtendSession))
.WillOnce(testing::Return(failedExtendSession))
.WillOnce(testing::Return(getMockedLoginResponseNoUbiAccount())); //works on last attempt.
}
// Performs a login to trigger the extend session
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(GET_CREDENTIALS(), {}, {})));
const AuthenticationNotificationType notifCreateSession = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(6)));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notifCreateSession) << "We didn't get the expected notification for createSession.";
const AuthenticationNotificationType notif = TestExtendSession_BF::waitForNotification(notificationListener);
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notif) << "We didn't get the expected client notification.";
}
/// @test Checks that the extend session is retried and that it sends the according notification when it fails.
TEST_F(EXTEND_SESSION_MOCK_NOLOGIN, USNOT_LONG_ExtendSessionFailure)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
// Note : Since we return an error, all mandatory fields in SessionInfo are missing and will all raise a log
// This will happen for each extend session retry
// so there should be (number of session retries) * (number of mandatory sessionInfo fields) logs
const uint32 NUMBER_OF_EXTENDSESSION_RETRIES = 3;
const uint32 NUMBER_OF_MANDATORY_FIELDS_IN_SESSIONINFO = 9;
US_EXPECT_LOG("Missing mandatory field:", LogLevel::Error,
Times(NUMBER_OF_EXTENDSESSION_RETRIES * NUMBER_OF_MANDATORY_FIELDS_IN_SESSIONINFO));
US_EXPECT_LOG("Failed to extend the current session because of invalid JSON:", LogLevel::Error, Times(3));
});
{
const uint8 SESSION_DURATION_SECONDS = 20; // TODO: Review this value to shorten the test duration
const MockAsyncResult sessionResult = getMockedLoginShortSession(SESSION_DURATION_SECONDS, false);
mockFullLogin(&sessionResult);
const MockAsyncResult failedExtendSession = MockResultHelper::createRestErrorResult(RestStatusCode::Error404, 1000);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, TestSuspendedMode_BF::EXTEND_SESSION_ENDPOINT)
.Times(3)
.WillRepeatedly(testing::Return(failedExtendSession)); // fails on all attempts
}
// Performs a login to trigger the extend session
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(GET_CREDENTIALS(), {}, {})));
const AuthenticationNotificationType notifCreateSession = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(6)));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notifCreateSession) << "We didn't get the expected notification for createSession.";
const AuthenticationNotificationType notifExtendSessionFailed = TestExtendSession_BF::waitForNotification(notificationListener);
EXPECT_EQ(AuthenticationNotificationType::SessionExtensionFailed, notifExtendSessionFailed);
}
/// @test Checks that the extend session is periodic and is achieved several times.
TEST_F(EXTEND_SESSION_MOCK_NOLOGIN, USNOT_SeveralExtendSession)
{
const int ITERATION_COUNT = 3;
{
const Duration<uint8> SESSION_DURATION_SECONDS = 5;
const MockAsyncResult sessionResult = getMockedLoginShortSession(SESSION_DURATION_SECONDS, false);
mockFullLogin(&sessionResult);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, TestSuspendedMode_BF::EXTEND_SESSION_ENDPOINT)
.Times(ITERATION_COUNT)
.WillRepeatedly(testing::Return(sessionResult));
}
// Performs a login to trigger the extend session
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(GET_CREDENTIALS(), {}, {})));
const AuthenticationNotificationType notifCreateSession = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(6)));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notifCreateSession) << "We didn't get the expected notification for createSession.";
for (int i = 0; i < ITERATION_COUNT; i++)
{
PRINT_PROGRESS(i + 1, ITERATION_COUNT, "Waiting notification %d", i + 1);
const AuthenticationNotificationType notifExtendSessionFailed = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(6)));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notifExtendSessionFailed) << "We didn't get the expected notification for session extension.";
}
}
/// @test Checks that there is no session extension when the ExtendSession switch is off.
/// @note This test is not in the testKillSwitches file mainly because everything
/// is set in this file to ease making this test. Furthermore, the extendSession
/// switch does not deactivate communication like other switches, it disables a feature.
/// Having it in a separate file is therefore not completely absurd...
TEST_F(EXTEND_SESSION_MOCK_NOLOGIN, USNOT_SwitchedExtendSessionOff)
{
const Duration<uint8> SESSION_DURATION_SECONDS = 5;
{
const MockAsyncResult sessionResult = getMockedLoginShortSession(SESSION_DURATION_SECONDS, false);
auto parametersApplicationResult = getMockedParametersApplication();
auto parametersSpaceResult = MockResultHelper::createSuccessResult(ParametersSpaceMockHelper().changeFeatureSwitch(FeatureSwitchId::ExtendSession,
FeatureSwitchState::Disabled).getParameters().renderContent());
mockFullLogin(&sessionResult, &parametersApplicationResult, &parametersSpaceResult);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, TestSuspendedMode_BF::EXTEND_SESSION_ENDPOINT).Times(0);
}
// Performs a login to trigger the extend session
// Create listener before triggering state change, so we can catch notification
ListenerHandler<AuthenticationNotification> notificationListener = getFacade().getAuthenticationClient().createNotificationListener();
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(GET_CREDENTIALS(), {}, {})));
const AuthenticationNotificationType notifCreateSession = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(Duration<>(6)));
EXPECT_EQ(AuthenticationNotificationType::SessionInfoChanged, notifCreateSession) << "We didn't get the expected notification for createSession.";
const AuthenticationNotificationType notifNone = TestExtendSession_BF::waitForNotification(notificationListener, DurationMicro(2*SESSION_DURATION_SECONDS));
EXPECT_EQ(AuthenticationNotificationType::None, notifNone) << "There should not be an extend session notification.";
}
};