434 lines
No EOL
14 KiB
C++
434 lines
No EOL
14 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @cond PREVENTS_DOXYGEN_WARNING
|
|
#pragma once
|
|
#include "tests/common/helpers.h"
|
|
#include <../private/ubiservices/core/chrono/chronometer.h>
|
|
#include <../private/ubiservices/core/debug/systemChecker.h>
|
|
#include <ubiservices/core/errors/errorDetails.h>
|
|
#include <../private/ubiservices/core/helpers/instancesManager.h>
|
|
#include <../private/ubiservices/core/helpers/streamOperators.h>
|
|
#include <ubiservices/core/JSON/jsonWriter.h>
|
|
#include <ubiservices/core/log/devices/logDeviceConsole.h>
|
|
#include <ubiservices/core/log/outputFormat.h>
|
|
#include <ubiservices/facade.h>
|
|
#include <ubiservices/loggingHelper.h>
|
|
#include <ubiservices/services/authentication/authenticationClient.h>
|
|
#include <ubiservices/services/authentication/sessionInfo.h>
|
|
#include <ubiservices/services/event/eventClient.h>
|
|
#include <ubiservices/services/event/eventNotification.h>
|
|
#include <ubiservices/services/notification/notificationClient.h>
|
|
#include <../private/ubiservices/services/parameters/featureSwitch.h>
|
|
#include <usCommon/authenticationHelper.h>
|
|
#include <usCommon/options.h>
|
|
#include <usCommon/settings.h>
|
|
|
|
namespace US_NS {;
|
|
|
|
bool EventsNotificationHelper::waitForEventConfig(ListenerHandler<EventNotification>& handler)
|
|
{
|
|
bool isRequestEventConfigDone = false;
|
|
bool isConfigSuccess = false;
|
|
|
|
HighResolutionChrono chrono;
|
|
|
|
while(!isRequestEventConfigDone && chrono.getElapsed()/1000u < NS_COMMON::DEFAULT_WAIT_TIME*1000u)
|
|
{
|
|
do
|
|
{
|
|
Helper::sleep(25);
|
|
|
|
if (handler.isNotificationAvailable())
|
|
{
|
|
const EventNotification notif = handler.popNotification();
|
|
if(notif.m_type == EventNotificationType::EventConfigFailure)
|
|
{
|
|
isRequestEventConfigDone = true;
|
|
isConfigSuccess = false;
|
|
}
|
|
if(notif.m_type == EventNotificationType::EventConfigSuccess)
|
|
{
|
|
isRequestEventConfigDone = true;
|
|
isConfigSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
while (handler.isNotificationAvailable());
|
|
}
|
|
|
|
return isConfigSuccess;
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
AuthenticationFixture<facadesCount, executeLogin>::AuthenticationFixture()
|
|
#if !defined(US_SDK_S2S)
|
|
: m_notificationContentTypes(NULL)
|
|
#endif
|
|
{
|
|
for(uint32 i = 0; i < facadesCount; i++)
|
|
{
|
|
m_loginIsSuccessfulArray[i] = false;
|
|
m_facades[i] = NULL;
|
|
#if !defined(US_SDK_S2S)
|
|
m_credentials[i] = NULL;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
AuthenticationFixture<facadesCount, executeLogin>::~AuthenticationFixture()
|
|
{
|
|
US_DELETE(m_notificationContentTypes);
|
|
}
|
|
#endif
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
void AuthenticationFixture<facadesCount, executeLogin>::SetUp()
|
|
{
|
|
LeakChecker::SetUp(); // Done first to maximize memory leak coverage
|
|
|
|
for(uint32 i = 0; i < facadesCount; i++)
|
|
{
|
|
SetUp(i);
|
|
}
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
void AuthenticationFixture<facadesCount, executeLogin>::TearDown()
|
|
{
|
|
// Code here is called right after each test (before the destructor).
|
|
|
|
for(uint32 i = 0; i < facadesCount; i++)
|
|
{
|
|
TearDown(i);
|
|
}
|
|
|
|
LeakChecker::TearDown(); // Done last to maximize memory leak coverage
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
uint32 AuthenticationFixture<facadesCount, executeLogin>::getInstancesCount() const
|
|
{
|
|
return m_facadesCount;
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
bool AuthenticationFixture<facadesCount, executeLogin>::isLoginRequired() const
|
|
{
|
|
return m_executeLogin;
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
Facade& AuthenticationFixture<facadesCount, executeLogin>::getFacade(uint32 index)
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *m_facades[index];
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
const Facade& AuthenticationFixture<facadesCount, executeLogin>::getFacade(uint32 index) const
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *m_facades[index];
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
const Facade& AuthenticationFixture<facadesCount, executeLogin>::getFacadeConst(uint32 index) const
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *m_facades[index];
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
FacadeInternal& AuthenticationFixture<facadesCount, executeLogin>::getFacadeInternal(uint32 index)
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *reinterpret_cast<FacadeInternal*>(m_facades[index]->m_facadeInternal.getPtr());
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
const FacadeInternal& AuthenticationFixture<facadesCount, executeLogin>::getFacadeInternal(uint32 index) const
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *reinterpret_cast<FacadeInternal*>(m_facades[index]->m_facadeInternal.getPtr());
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
ListenerHandler<EventNotification>& AuthenticationFixture<facadesCount, executeLogin>::getHandler(uint32 index)
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *m_handlers[index];
|
|
}
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
const PlayerCredentials& AuthenticationFixture<facadesCount, executeLogin>::getCredentials(uint32 index) const
|
|
{
|
|
US_TEST_ASSERT(index < facadesCount, "Index out of range");
|
|
return *m_credentials[index];
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
Vector<String> AuthenticationFixture<facadesCount, executeLogin>::getWebSocketContentTypes() const
|
|
{
|
|
// Create a somewhat unique tag for types to be able to filter connections
|
|
if (m_notificationContentTypes == NULL)
|
|
{
|
|
m_notificationContentTypes = US_NEW(Vector<String>);
|
|
#if defined(US_CHINA_PROD_NOTIFICATION_TYPE)
|
|
*m_notificationContentTypes = {
|
|
"OnlineNotificationType*",
|
|
};
|
|
#else
|
|
const String typeTag = String::formatText("_%llu", ClockSteady::getTimeNano());
|
|
*m_notificationContentTypes = {
|
|
"OnlineNotificationType Test content type 1" + typeTag,
|
|
"OnlineNotificationType Test content type 2" + typeTag,
|
|
};
|
|
#endif
|
|
|
|
}
|
|
|
|
return *m_notificationContentTypes;
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
String AuthenticationFixture<facadesCount, executeLogin>::getWebSocketJsonData() const
|
|
{
|
|
if (m_notificationContentTypes == NULL)
|
|
{
|
|
US_IGNORE_RESULT(getWebSocketContentTypes());
|
|
}
|
|
|
|
JsonWriter jsonWriter;
|
|
jsonWriter["Testproperty"] = m_notificationContentTypes->front(); //"TestValue";
|
|
const String jsonData = jsonWriter.renderContent();
|
|
return jsonData;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
bool AuthenticationFixture<facadesCount, executeLogin>::isEnvironmentNot(Environment target)
|
|
{
|
|
return (
|
|
getFacade().getAuthenticationClient().getSessionInfo().hasValidSession() &&
|
|
(getFacade().getAuthenticationClient().getSessionInfo().getEnvironmentCode()) != target);
|
|
}
|
|
#endif
|
|
|
|
#if !defined(US_DLL)
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
void AuthenticationFixture<facadesCount, executeLogin>::waitForPostLoginCompletion(uint32 waitTimeInMSec)
|
|
{
|
|
if (!TestHelpers_BF::waitForPostLoginCompletion(getFacade(), waitTimeInMSec))
|
|
{
|
|
GTEST_FAIL();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
void AuthenticationFixture<facadesCount, executeLogin>::SetUp(uint32 index)
|
|
{
|
|
m_facades[index] = US_NEW(US_NS::Facade);
|
|
m_handlers[index] = US_NEW(ListenerHandler<EventNotification>, m_facades[index]->getEventClient().createNotificationListener());
|
|
|
|
resetLogLevel();
|
|
setMultiLinesLog(true);
|
|
#if defined(US_LOG_ENABLED) && defined(DEBUGGING)
|
|
LoggingHelper::enableVerbose(true);
|
|
LoggingHelper::disableCategory(LogCategory::HttpEngine);
|
|
#endif
|
|
|
|
uint32 count = facadesCount; // avoids warning "conditional expression is constant"
|
|
#if defined(US_SDK_S2S)
|
|
ASSERT_TRUE(count == 1) << "There is no such thing as multiple players in s2s context.";
|
|
#else
|
|
if(count > 1)
|
|
{
|
|
m_credentials[index] = NS_COMMON::AuthenticationHelper::createPlayerCredentials(index);
|
|
}
|
|
else
|
|
{
|
|
ASSERT_TRUE(index == 0);
|
|
m_credentials[index] = NS_COMMON::AuthenticationHelper::createPlayerCredentials();
|
|
}
|
|
ASSERT_TRUE(m_credentials[index] != NULL);
|
|
#endif
|
|
|
|
if (!isLoginRequired())
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint32 triesCount = 3;
|
|
|
|
while (triesCount > 0)
|
|
{
|
|
PRINT_DEBUG("CALLING UbiServices Login...");
|
|
|
|
const AsyncResult<Empty> resultLogin = m_facades[index]->createSession(
|
|
#if defined(US_SDK_S2S)
|
|
GET_CREDENTIALS(), {}, {}
|
|
#else
|
|
*m_credentials[index], {}, {}, EventsParams(), getWebSocketJsonData()
|
|
#endif
|
|
);
|
|
|
|
if (!resultLogin.isProcessing())
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
GTEST_FATAL_FAILURE_("Login initialization failed");
|
|
}
|
|
InstancesManager* mgr = InstancesManager::getInstance();
|
|
ASSERT_TRUE(mgr != NULL);
|
|
|
|
if (!resultLogin.wait(NS_COMMON::DEFAULT_WAIT_TIME))
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
#if defined(ENABLE_STRONG_VALIDATION)
|
|
GTEST_FATAL_FAILURE_("Login failed with a timeout"); // Commenting this line to allow retries
|
|
#else
|
|
m_facades[index] = US_NEW(US_NS::Facade);
|
|
m_handlers[index] = US_NEW(ListenerHandler<EventNotification>, m_facades[index]->getEventClient().createNotificationListener());
|
|
#if defined(US_SDK_S2S)
|
|
ASSERT_TRUE(count == 1) << "There is no such thing as multiple players in s2s context.";
|
|
#else
|
|
if(count > 1)
|
|
{
|
|
m_credentials[index] = NS_COMMON::AuthenticationHelper::createPlayerCredentials(index);
|
|
}
|
|
else
|
|
{
|
|
ASSERT_TRUE(index == 0);
|
|
m_credentials[index] = NS_COMMON::AuthenticationHelper::createPlayerCredentials();
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
if (resultLogin.hasFailed() && (triesCount == 1))
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
StringStream ss;
|
|
#if defined(US_LOG_ENABLED)
|
|
ss << "Login failed with an error (" << resultLogin.getError() << ")";
|
|
#else
|
|
ss << "Login failed with an error (" << resultLogin.getError().m_code << ")";
|
|
#endif
|
|
GTEST_FATAL_FAILURE_(ss.getContent().getUtf8());
|
|
}
|
|
|
|
if (resultLogin.hasSucceeded())
|
|
{
|
|
//PRINT_LINE("UbiServices Login OK!");
|
|
triesCount = 0;
|
|
}
|
|
else
|
|
{
|
|
triesCount--;
|
|
if (triesCount > 0)
|
|
{
|
|
PRINT_LINE("RETRYING UbiServices login... %d", triesCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Checks if the facade is connected.
|
|
if (!getFacade(index).getAuthenticationClient().getSessionInfo().hasValidSession())
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
GTEST_FATAL_FAILURE_("UbiServices facade is not connected to Uplay");
|
|
}
|
|
|
|
m_loginIsSuccessfulArray[index] = true;
|
|
}
|
|
|
|
template<uint32 facadesCount, bool executeLogin>
|
|
void AuthenticationFixture<facadesCount, executeLogin>::TearDown(uint32 index)
|
|
{
|
|
if (m_loginIsSuccessfulArray[index])
|
|
{
|
|
AsyncResult<Empty> deleteSessionAsync = m_facades[index]->deleteSession();
|
|
|
|
if (!deleteSessionAsync.isProcessing())
|
|
{
|
|
// Add this test in case the job finishes before we get to this point (can occur when log level is Debug)
|
|
if(!deleteSessionAsync.hasFailed() && !deleteSessionAsync.hasSucceeded())
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
GTEST_FATAL_FAILURE_("Delete session initialization failed");
|
|
}
|
|
}
|
|
|
|
if (!deleteSessionAsync.wait(NS_COMMON::DEFAULT_WAIT_TIME))
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
#if defined(ENABLE_STRONG_VALIDATION)
|
|
GTEST_FATAL_FAILURE_("Delete session failed with a timeout");
|
|
#else
|
|
PRINT_LINE("ERROR: WARNING: Delete session TIMED OUT");
|
|
#endif
|
|
}
|
|
else if (deleteSessionAsync.hasFailed())
|
|
{
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
StringStream ss;
|
|
#if defined(US_LOG_ENABLED)
|
|
ss << "Delete session failed with an error (" << deleteSessionAsync.getError() << ")";
|
|
#else
|
|
ss << "Delete session failed with an error (" << deleteSessionAsync.getError().m_code << ")";
|
|
#endif
|
|
GTEST_FATAL_FAILURE_(ss.getContent().getUtf8());
|
|
}
|
|
}
|
|
|
|
US_DELETE(m_handlers[index]);
|
|
US_DELETE(m_facades[index]);
|
|
#if !defined(US_SDK_S2S)
|
|
US_DELETE(m_notificationContentTypes);
|
|
US_DELETE(m_credentials[index]);
|
|
#endif
|
|
}
|
|
|
|
};
|
|
|
|
/// @endcond
|