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

342 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "testsIntegration/notificationHelper.h"
#if defined(US_SDK_LIGHT_MOBILE)
#error This file shall not be part of the solution
#endif
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include <ubiservices/core/errors/errorDetails.h>
#include <ubiservices/core/types/typesId/applicationId.h>
#include <ubiservices/services/authentication/authenticationClient.h>
#include <ubiservices/services/authentication/sessionInfo.h>
#include <ubiservices/services/notification/notificationClient.h>
#include <ubiservices/services/notification/notificationOutgoing.h>
#include <ubiservices/services/parameters/parametersClient.h>
#include <ubiservices/facade.h>
namespace US_NS {;
NotificationHelper::MultiConnection::MultiConnection(Vector<Facade*>& facades, const Vector<String> types, const String& json)
: m_facades(facades)
, m_testConnetionTypes({ types.front() })
, m_jsonData(json)
{
for (const auto& itFacade : m_facades)
{
m_profiles.push_back(itFacade->getAuthenticationClient().getSessionInfo().getProfileId());
m_handlers.push_back(itFacade->getNotificationClient().createNotificationListenerCustom());
}
}
void NotificationHelper::MultiConnection::checkConnection(const bool canCheckSelf)
{
for (const auto& itFacade : m_facades)
{
ASSERT_TRUE(itFacade->getAuthenticationClient().getSessionInfo().hasValidSession());
}
m_connectionInfos.clear();
for (uint32 i = 0; i < m_facades.size(); ++i) // TODO: Use iterator
{
Vector<ProfileId> profiles;
for (uint32 j = 0; j < m_profiles.size(); ++j) // TODO: Use iterator
{
if (j != i || canCheckSelf)
{
profiles.push_back(m_profiles[j]);
}
}
const Vector<ApplicationId> appIds = { ApplicationId(m_facades[i]->getParametersClient().getUsApplicationId()) };
const AsyncResult<Map<ProfileId, Vector<ConnectionInfo> > > result =
m_facades[i]->getNotificationClient().requestConnections(profiles, appIds, m_testConnetionTypes);
EXPECT_TRUE(result.wait());
US_EXPECT_SUCCESS(result);
filterConnectionInfo(result.getResult());
}
ASSERT_EQ(m_facades.size(), m_connectionInfos.size());
}
void NotificationHelper::MultiConnection::filterConnectionInfo(const Map<ProfileId, Vector<ConnectionInfo> >& connectionMappings)
{
for (const auto& itMapping : connectionMappings)
{
const Vector<ConnectionInfo>& connections = itMapping.second;
ConnectionInfo filteredConnection;
bool isFound = false;
for (const auto& info : connections)
{
const Json reader(info.m_jsonData);
String testId;
if (reader["Testproperty"].getValue(testId) && testId == m_testConnetionTypes.front())
{
filteredConnection = info;
isFound = true;
break;
}
}
#if defined(US_LOG_ENABLED)
if (!isFound)
{
for (const auto& info : connections)
{
StringStream str;
str << info;
std::cout << str.getContent() << ::std::endl;
}
}
#endif
ASSERT_TRUE(isFound);
m_connectionInfos.push_back(filteredConnection);
}
// Remove duplicates
for (Vector<ConnectionInfo>::iterator i = m_connectionInfos.begin(); i != m_connectionInfos.end(); ++i)
{
for (Vector<ConnectionInfo>::iterator j = i + 1; j != m_connectionInfos.end(); ++j)
{
if ((*i) == (*j))
{
j = m_connectionInfos.erase(j, j + 1);
j--;
}
}
}
}
const AsyncResult<Map<ProfileId, Vector<ConnectionInfo> > > NotificationHelper::MultiConnection::checkConnectionsNoResultCheck(uint32 facadeIndex, const bool canCheckSelf)
{
m_connectionInfos.clear();
EXPECT_LT(facadeIndex, m_facades.size());
if (facadeIndex >= m_facades.size())
{
return AsyncResult<Map<ProfileId, Vector<ConnectionInfo> > >("checkConnectionsNoResultCheck error");
}
Vector<ProfileId> profiles;
uint32 j = 0;
for (Vector<ProfileId>::const_iterator it = m_profiles.begin(); it != m_profiles.end(); ++it, ++j)
{
if (j != facadeIndex || canCheckSelf)
{
profiles.push_back(m_profiles[j]);
}
}
const Vector<ApplicationId> appIds = { ApplicationId(m_facades[facadeIndex]->getParametersClient().getUsApplicationId()) };
NotificationClient& connection = m_facades[facadeIndex]->getNotificationClient();
const AsyncResult<Map<ProfileId, Vector<ConnectionInfo> > > result = connection.requestConnections(profiles, appIds, m_testConnetionTypes);
return result;
}
void NotificationHelper::MultiConnection::sendMessage(uint32 sourceId, const Vector<uint32>& targets, SendType type, String* out)
{
ASSERT_LT(sourceId, m_facades.size());
ASSERT_LE(targets.size(), m_facades.size());
ASSERT_EQ(m_facades.size(), m_connectionInfos.size());
NotificationClient& client = m_facades[sourceId]->getNotificationClient();
JsonWriter msgData;
msgData["field1"] = "value1";
const NotificationOutgoing msg(m_testConnetionTypes.front(), msgData.renderContent());
bool success = false;
if (type == SendType::UsingConnectionInfo)
{
Vector<ConnectionInfo> connectionInfo;
connectionInfo.reserve(targets.size());
for (uint32 i = 0; i != targets.size(); ++i) // TODO: Use iterator
{
connectionInfo.push_back(m_connectionInfos[targets[i]]);
}
const AsyncResultBatch<ConnectionInfo, Empty> result = client.sendNotificationInSequenceNoBroker(connectionInfo, msg);
EXPECT_TRUE(result.wait());
US_EXPECT_SUCCESS(result);
}
else
{
Vector<ProfileId> profiles;
profiles.reserve(targets.size());
for (uint32 i = 0; i < targets.size(); ++i) // TODO: Use iterator
{
profiles.push_back(m_profiles[targets[i]]);
}
const AsyncResultBatch<ProfileId, Empty> result = client.sendNotificationInSequence(profiles, msg);
EXPECT_TRUE(result.wait());
// hasPartiallySucceeded() returns false if all async have succeeded.
// There might be one or multiple connection info active for a profile
// (build machine use the same profile or a "zombie" connection).
// This test use the message type is use to filter between the
// connection which mean that if there's multiple message type
// between the connection the send message will not work on all
// of them and hasPartiallySucceeded will return true. However,
// if there's only one connection hasPartiallySucceeded will return
// false but hasSucceeded will return true.
success = result.hasPartiallySucceeded() || result.hasSucceeded();
EXPECT_TRUE(success) << "Sending Notification (to " <<
profiles.size() << " profiles) failed (partially [" << result.hasPartiallySucceeded() << "] or totally)";
}
if (out != NULL)
{
*out = success ? "MESSAGE SENT" : "SEND MESSAGE FAILED!";
}
}
const AsyncResultBatch<ConnectionInfo, Empty> NotificationHelper::MultiConnection::sendMessageNoResultCheckConnectionId(
uint32 sourceId, const bool canSendSelf)
{
EXPECT_LT(sourceId, m_facades.size());
EXPECT_EQ(m_facades.size(), m_connectionInfos.size());
if ((sourceId >= m_facades.size()) || (m_facades.size() != m_connectionInfos.size()))
{
return AsyncResultBatch<ConnectionInfo, Empty>();
}
JsonWriter msgData;
msgData["field1"] = "value1";
const NotificationOutgoing msg(m_testConnetionTypes.front(), msgData.renderContent());
Vector<ConnectionInfo> connectionInfo;
for (size_t i = 0; i != m_facades.size(); ++i)
{
if (i != sourceId || canSendSelf)
{
connectionInfo.push_back(m_connectionInfos[i]);
}
}
return m_facades[sourceId]->getNotificationClient().sendNotificationInSequenceNoBroker(connectionInfo, msg);
}
const AsyncResultBatch<ProfileId, Empty> NotificationHelper::MultiConnection::sendMessageNoResultCheckProfileId(
uint32 sourceId, const bool canSendSelf)
{
EXPECT_LT(sourceId, m_facades.size());
EXPECT_EQ(m_facades.size(), m_connectionInfos.size());
if ((sourceId >= m_facades.size()) || (m_facades.size() != m_connectionInfos.size()))
{
return AsyncResultBatch<ProfileId, Empty>();
}
JsonWriter msgData;
msgData["field1"] = "value1";
const NotificationOutgoing msg(m_testConnetionTypes.front(), msgData.renderContent());
Vector<ProfileId> profiles;
for (size_t i = 0; i < m_facades.size(); ++i)
{
if (i != sourceId || canSendSelf)
{
profiles.push_back(m_profiles[i]);
}
}
return m_facades[sourceId]->getNotificationClient().sendNotificationInSequence(profiles, msg);
}
void NotificationHelper::MultiConnection::sendUnsupportedMessage(uint32 sourceId, SendType useConnectionInfo, const bool canSendSelf)
{
ASSERT_LT(sourceId, m_facades.size());
ASSERT_EQ(m_facades.size(), m_connectionInfos.size());
NotificationClient& client = m_facades[sourceId]->getNotificationClient();
JsonWriter msgData;
msgData["field1"] = "value1";
const NotificationOutgoing msg("Test_InvalidType", msgData.renderContent());
if (useConnectionInfo == SendType::UsingConnectionInfo)
{
Vector<ConnectionInfo> connectionInfo;
for (size_t i = 0; i != m_facades.size(); ++i)
{
if (i != sourceId || canSendSelf)
{
connectionInfo.push_back(m_connectionInfos[i]);
}
}
const AsyncResultBatch<ConnectionInfo, Empty> result = client.sendNotificationInSequenceNoBroker(connectionInfo, msg);
EXPECT_TRUE(result.wait());
US_EXPECT_FAILURE(result, Errors::NOTIFICATION_SEND_FAILED);
}
else
{
Vector<ProfileId> profiles;
for (size_t i = 0; i != m_facades.size(); ++i)
{
if (i != sourceId || canSendSelf)
{
profiles.push_back(m_profiles[i]);
}
}
const AsyncResultBatch<ProfileId, Empty> result = client.sendNotificationInSequence(profiles, msg);
EXPECT_TRUE(result.wait());
EXPECT_FALSE(result.hasPartiallySucceeded());
}
}
void NotificationHelper::MultiConnection::validatePopMsgData(const String& msgData)
{
const Json reader(msgData);
EXPECT_TRUE(reader.isValid());
for (const auto& item : reader.getItems())
{
EXPECT_EQ(String("field1"), item.getKey());
EXPECT_EQ(String("value1"), item.getValueString());
}
}
void NotificationHelper::MultiConnection::waitForMessageAndPop(uint32 sourceId, uint32 expectedMessageCount, String* out)
{
ASSERT_LT(sourceId, m_facades.size());
NotificationSource<NotificationCustom>::ListenerHandler& handler = m_handlers[sourceId];
uint32 messageCount = 0;
const uint32 iterationCount = (expectedMessageCount > 0 ? 150u : 1u); //15 sec tolerance on expected result
for (uint32 i = 0; i < iterationCount && messageCount != expectedMessageCount; i++)
{
if (handler.isNotificationAvailable())
{
const NotificationCustom incoming = handler.popNotification();
EXPECT_EQ(m_testConnetionTypes.front(), incoming.m_type);
validatePopMsgData(incoming.m_content);
if (out != NULL)
{
*out = "MESSAGE RECEIVED.";
}
messageCount++;
}
else
{
Helper::sleep(100);
}
}
if (messageCount != expectedMessageCount)
{
ADD_FAILURE();
}
}
};