342 lines
12 KiB
C++
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();
|
|
}
|
|
}
|
|
|
|
};
|
|
|