1048 lines
54 KiB
C++
1048 lines
54 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#include <tests/config.h>
|
|
#include <tests/common/badEvents.h>
|
|
#include <tests/fixture/memoryCheckFixture.h>
|
|
#include <tests/mock/mockLogDevice.h>
|
|
#include <testsIntegration/event/eventsConfigMockHelper.h>
|
|
#include <ubiservices/loggingHelper.h>
|
|
#include <ubiservices/core/chrono/chronometer.h>
|
|
#include <ubiservices/core/chrono/clockSystem.h>
|
|
#include <ubiservices/core/JSON/jsonWriter.h>
|
|
#include <ubiservices/core/types/dateTimeHelper.h>
|
|
#include <ubiservices/core/types/string.h>
|
|
#include <ubiservices/services/event/eventQueue.h>
|
|
#include <ubiservices/services/event/eventRequest.h>
|
|
#include <ubiservices/services/event/eventConfigInfo.h>
|
|
#include <ubiservices/services/event/pushEventResult.h>
|
|
#include <ubiservices/services/event/types/eventInfoBaseProxy.h>
|
|
#if !defined(US_SDK_S2S)
|
|
#include <ubiservices/services/event/types/eventInfoCustom.h>
|
|
#endif
|
|
#include <ubiservices/services/event/types/eventInfoService.h>
|
|
#if !defined(US_SDK_S2S)
|
|
#include <ubiservices/services/event/types/eventInfoContextStart.h>
|
|
#include <ubiservices/services/event/types/eventInfoContextStop.h>
|
|
#include <ubiservices/services/event/types/eventInfoPlayerPosition.h>
|
|
#endif
|
|
|
|
namespace US_NS {;
|
|
US_DEFINE_TEST(TestEventQueue);
|
|
|
|
#if !defined(US_DLL)
|
|
|
|
typedef LeakChecker SERVICES_EVENT_QUEUE;
|
|
|
|
namespace TestEventQueue_BF
|
|
{
|
|
#if !defined(US_SDK_S2S)
|
|
static const char* s_mockContextType = "dummyContextType";
|
|
static const char* s_mockContextName = "dummyContextName";
|
|
static const char* s_currentSession = "4d9061de-7c20-4cc9-9f55-b8d6228da6ae";
|
|
static const char* s_currentSpaceId = "4d9061de-7c20-4cc9-9f55-b8d6228da6af";
|
|
#endif
|
|
testing::AssertionResult validateEvents(const Vector<String>& ecxpectedEvents, const Json& outputRequest)
|
|
{
|
|
const Vector<Json> resultEvents = outputRequest["events"].getItems();
|
|
|
|
if (resultEvents.size() != ecxpectedEvents.size())
|
|
{
|
|
return testing::AssertionFailure() << "We don't have the expected amount of events.";
|
|
}
|
|
|
|
Vector<String>::const_iterator expectedEventIt = ecxpectedEvents.begin();
|
|
|
|
for (Vector<Json>::const_iterator resultEventIt = resultEvents.begin(); resultEventIt != resultEvents.end(); ++resultEventIt)
|
|
{
|
|
if ((*resultEventIt)["type"].getValueString() != *expectedEventIt)
|
|
{
|
|
return testing::AssertionFailure() << "The events result doesn't match the expected events.";
|
|
}
|
|
|
|
++expectedEventIt;
|
|
}
|
|
|
|
return testing::AssertionSuccess();
|
|
}
|
|
#if !defined(US_SDK_S2S)
|
|
const ClockSteady::TTimeMilli s_PLAYTIME_WAIT_ONESECOND = 1100u; //extra 100 ms to remove flakiness...
|
|
#endif
|
|
}
|
|
|
|
|
|
/// @test Validates that the timestamp is correctly set at push time.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventTimeStamp)
|
|
{
|
|
#if !defined(US_SDK_S2S)
|
|
EventInfoCustom customEvent("Test"); //Can't do the getTimeStamp on the mock.
|
|
#else
|
|
EventInfoService customEvent = TestHelpers_BF::getServiceEvent("Test");
|
|
#endif
|
|
|
|
{
|
|
ASSERT_EQ(0u, EventInfoBaseProxy::getTimeStamp(customEvent)) << "The timestamp should not be computed at construction time.";
|
|
#if !defined(US_SDK_S2S)
|
|
EventInfoCustom copy = customEvent;
|
|
#else
|
|
EventInfoService copy = customEvent;
|
|
#endif
|
|
ASSERT_EQ(0u, EventInfoBaseProxy::getTimeStamp(copy)) << "The timestamp should linger on copy.";
|
|
}
|
|
|
|
EventQueue eventQueue;
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(customEvent));
|
|
ASSERT_EQ(0, EventInfoBaseProxy::getTimeStamp(customEvent)) << "We shouldn't be modifying the prod event since they could reuse their event.";
|
|
|
|
#if defined(US_SDK_S2S)
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(EventConfigInfo());
|
|
#else
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
#endif
|
|
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
|
|
#if defined(US_SDK_S2S)
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(eventConfig).front();
|
|
#else
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSpaceId, eventConfig).front();
|
|
#endif
|
|
|
|
|
|
const Json resultJson(requestResult);
|
|
#if defined(US_SDK_S2S)
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "service.Test" }, resultJson));
|
|
const String createdDate = resultJson["events"].getItems().at(0u)["createdDate"].getValueString();
|
|
#else
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start", "custom.Test" }, resultJson));
|
|
const String createdDate = resultJson["events"].getItems().at(1u)["createdDate"].getValueString();
|
|
#endif
|
|
|
|
// Since the events were never sent and oEventRequest::outputUnsentFormat() was never called, the date has a place holder instead of a real date.
|
|
ASSERT_EQ(createdDate, "OFFLINE_TIMESTAMP_PLACEHOLDER");
|
|
}
|
|
#if !defined(US_SDK_S2S)
|
|
/// @test Validates that the context.start and context.stop have the same id when context.stop is pushed.
|
|
/// @test Verifies that the Id increments appropriately after other context push.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextCheckId)
|
|
{
|
|
EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
ASSERT_EQ(-1, EventInfoBaseProxy::getContextId(contextStartEvent));
|
|
ASSERT_EQ(-1, EventInfoBaseProxy::getContextId(contextStopEvent));
|
|
|
|
EventQueue eventQueue;
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
ASSERT_EQ(-1, EventInfoBaseProxy::getContextId(contextStartEvent)) << "We shouldn't be modifying the prod event since they could reuse their event.";
|
|
ASSERT_EQ(-1, EventInfoBaseProxy::getContextId(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(0)["contexts"].getItemsCount()) << "game.start shouldn't have any context set.";
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(1)["typeData"]["contextId"].getValueInteger());
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(2)["typeData"]["contextId"].getValueInteger());
|
|
}
|
|
|
|
/// @test Verifies that the Id increments appropriately after multiple context push.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextIdIncrements)
|
|
{
|
|
const EventInfoContextStart contextStartEvent1(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const String otherName = "OtherType";
|
|
const EventInfoContextStart contextStartEvent2(otherName, TestEventQueue_BF::s_mockContextName);
|
|
|
|
EventQueue eventQueue;
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent1));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent2));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.start.%s", otherName.getUtf8()) }, resultJson));
|
|
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(0)["contexts"].getItemsCount()) << "game.start shouldn't have any context set.";
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(1)["typeData"]["contextId"].getValueInteger());
|
|
ASSERT_EQ(1u, resultJson["events"].getItems().at(2)["typeData"]["contextId"].getValueInteger());
|
|
}
|
|
|
|
/// @test Validates that the context stop takes the accumulates chrono in the context.start at push time
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextCheckDuration)
|
|
{
|
|
EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
EventQueue eventQueue;
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
|
|
const ClockSystem::TTimeMilli CONTEXT_DURATION = 100;
|
|
#if defined(US_TARGET_IOS)
|
|
const ClockSteady::TTimeNano ref = ClockSteady::getTimeNano();
|
|
while ((ClockSteady::getTimeNano() - ref) < CONTEXT_DURATION * 1000000ul)
|
|
{
|
|
}
|
|
#else
|
|
US_TEST_NS::Helper::sleep(CONTEXT_DURATION);
|
|
#endif
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_GE(resultJson["events"].getItems().at(2)["typeData"]["contextDuration"].getValueInteger(), (CONTEXT_DURATION / 2)) << "Event Result : " << requestResult.getUtf8();
|
|
ASSERT_LT(resultJson["events"].getItems().at(2)["typeData"]["contextDuration"].getValueInteger(), (CONTEXT_DURATION / 2) + CONTEXT_DURATION);
|
|
}
|
|
|
|
/// @test Validates that adding a context is non blocking for other context
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextNonBlocking)
|
|
{
|
|
const String anotherContextType = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
const String anotherContextName = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStart contextStartEventAnotherTypeAndName(anotherContextType, anotherContextName);
|
|
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEventAnotherTypeAndName(anotherContextType, anotherContextName);
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEventAnotherTypeAndName));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEventAnotherTypeAndName));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
}
|
|
}
|
|
|
|
/// @test Validates that we can close the context in any order
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextAnyOrder)
|
|
{
|
|
const String anotherContextType = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
const String anotherContextName = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStart contextStartEventAnotherType(anotherContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEventAnotherType(anotherContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
}
|
|
}
|
|
|
|
/// @test Validates that we get a error on push on a malformed context.start
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextStartFailureInvalid)
|
|
{
|
|
const EventInfoContextStart contextStartEventInvalid1(String(), TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStart contextStartEventInvalid2(TestEventQueue_BF::s_mockContextType, String());
|
|
const EventInfoContextStart contextStartEventInvalid3((String()), String());
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::ContextCreationInvalid, eventQueue.pushEvent(contextStartEventInvalid1));
|
|
EXPECT_EQ(PushEventResult::ContextCreationInvalid, eventQueue.pushEvent(contextStartEventInvalid2));
|
|
EXPECT_EQ(PushEventResult::ContextCreationInvalid, eventQueue.pushEvent(contextStartEventInvalid3));
|
|
}
|
|
}
|
|
|
|
/// @test Validates that we get a error on push when the context.start is already present
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextStartFailurePresent)
|
|
{
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStart contextStartEventAnotherName(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName + String("AnotherName"));
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::ContextCreationButAlreadyExist, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::ContextCreationButAlreadyExist, eventQueue.pushEvent(contextStartEventAnotherName));
|
|
}
|
|
}
|
|
|
|
/// @test Validates that we cannot stop a context if it is not started or if it is already stopped.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventContextStopFailure)
|
|
{
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::ContextDeletionButDoesNotExist, eventQueue.pushEvent(contextStopEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
EXPECT_EQ(PushEventResult::ContextDeletionButDoesNotExist, eventQueue.pushEvent(contextStopEvent));
|
|
}
|
|
}
|
|
|
|
/// @test Validates that a events accumulates the current context Ids in its inner list.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventWithContext)
|
|
{
|
|
struct Local
|
|
{
|
|
static Vector<int32> getContextFromEvent(Json event)
|
|
{
|
|
Vector<int32> contexts;
|
|
const Vector<Json> contextsNode = event["contexts"].getItems();
|
|
for (Vector<Json>::const_iterator contextIt = contextsNode.begin(); contextIt != contextsNode.end(); ++contextIt)
|
|
{
|
|
contexts.push_back(contextIt->getValueInteger());
|
|
}
|
|
|
|
return contexts;
|
|
}
|
|
};
|
|
|
|
const String anotherContextType = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
const String anotherContextName = String("Another") + TestEventQueue_BF::s_mockContextType;
|
|
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStart contextStartEventAnotherType(anotherContextType, anotherContextName);
|
|
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEventAnotherType(anotherContextType, anotherContextName);
|
|
|
|
EventQueue eventQueue;
|
|
{
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent("TestService")));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEventAnotherType));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent("TestService")));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
EXPECT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
}
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
const Vector<String> eventNames
|
|
{
|
|
"game.start",
|
|
"custom.Test",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
"service.TestService",
|
|
String::formatText("context.start.%s", anotherContextType.getUtf8()),
|
|
"custom.Test",
|
|
String::formatText("context.stop.%s", anotherContextType.getUtf8()),
|
|
"service.TestService",
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType),
|
|
"custom.Test"
|
|
};
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents(eventNames, resultJson));
|
|
|
|
const Vector<int32> contextStart = { 0u };
|
|
const Vector<int32> contextStartBoth = { 0u ,1u };
|
|
|
|
{
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(0)), Vector<int32>());
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(1)), Vector<int32>());
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(2)), contextStart);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(3)), contextStart);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(4)), contextStartBoth);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(5)), contextStartBoth);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(6)), contextStart);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(7)), contextStart);
|
|
EXPECT_THAT(Local::getContextFromEvent(resultJson["events"].getItems().at(8)), Vector<int32>());
|
|
}
|
|
}
|
|
|
|
/// @test Validates that the context duration are accumulating the suspended time.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_ContextDurationSuspendedMode)
|
|
{
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const ClockSystem::TTimeMilli SLEEP_SUSPEND_TIME = 300;
|
|
const uint32 SUSPENDED_COUNT = 4;
|
|
const ClockSystem::TTimeMilli SLEEP_CONTEXT_TIME = 50;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.pushEvent(contextStartEvent);
|
|
|
|
// Need to know precisely the context time. The sleep duration cannot be trusted
|
|
// because of the sleep resolution on some platforms, e.g 15 ms on XboxOne
|
|
HighResolutionChrono chronoContextSleep;
|
|
US_TEST_NS::Helper::sleep(SLEEP_CONTEXT_TIME);
|
|
const uint64 expectedContextDuration = ClockSteady::getMilliFromNano(chronoContextSleep.getElapsed());
|
|
|
|
for (uint32 i = 0; i < SUSPENDED_COUNT; i++)
|
|
{
|
|
// Need to know precisely the suspend time. The sleep duration cannot be trusted
|
|
// because of the sleep resolution on some platforms, e.g 15 ms on XboxOne
|
|
HighResolutionChrono chronoSuspend;
|
|
US_TEST_NS::Helper::sleep(SLEEP_SUSPEND_TIME);
|
|
eventQueue.notifySuspendedAwake(chronoSuspend.getElapsed());
|
|
}
|
|
|
|
eventQueue.pushEvent(contextStopEvent);
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
Vector<String> expectedEvents;
|
|
expectedEvents.push_back("game.start");
|
|
expectedEvents.push_back(String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType));
|
|
expectedEvents.push_back(String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType));
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents(expectedEvents, resultJson));
|
|
|
|
EXPECT_GT((*resultJson["events"].getItems().rbegin())["typeData"]["contextDuration"].getValueInteger(), expectedContextDuration / 2);
|
|
// The EXPECT_LT has a higher margin than EXPECT_GT due to the different processing time that are not measured in the test
|
|
// e.g the time taken by the for loop, or to put the events in the queue
|
|
EXPECT_LT((*resultJson["events"].getItems().rbegin())["typeData"]["contextDuration"].getValueInteger(), expectedContextDuration * 2);
|
|
}
|
|
#endif
|
|
/// @test Validates that we filter an event when the event tag is not in the event config
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PopRequestEventFilter)
|
|
{
|
|
EventQueue eventQueue;
|
|
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
ASSERT_EQ(1, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size()) << "First pop should purge the game.start and player.start.";
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size()) << "There should be no events left in the queue at this point.";
|
|
{
|
|
ASSERT_TRUE(eventConfig.validateEventTag("custom.Testing")) << "The event should be in the config";
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME)));
|
|
ASSERT_EQ(1, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size());
|
|
}
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size()) << "There should be no events left in the queue at this point.";
|
|
|
|
{
|
|
ASSERT_FALSE(eventConfig.validateEventTag("custom.NotPushableEvent")) << "The event should not be in the config";
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("NotPushableEvent")));
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size());
|
|
}
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig).size()) << "There should be no events left in the queue at this point.";
|
|
#else
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(eventConfig).size()) << "There should be no events left in the queue at this point.";
|
|
{
|
|
ASSERT_TRUE(eventConfig.validateEventTag("service.Testing")) << "The event should be in the config";
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent()));
|
|
ASSERT_EQ(1, eventQueue.popEventRequests(eventConfig).size());
|
|
}
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(eventConfig).size()) << "There should be no events left in the queue at this point.";
|
|
#endif
|
|
|
|
}
|
|
|
|
#if defined(US_SDK_S2S)
|
|
/// @test Validates that a log is sent if number of events is higher than the maxBatchSize set in the config
|
|
/// TODO : Update this test once the maxBatchSize will be implemented, i.e. when the SDK will send several requests if
|
|
/// more than maxBatchSize events are in the queue
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventMaxBatchSize)
|
|
{
|
|
setupDebugLogging();
|
|
|
|
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
|
|
{
|
|
US_EXPECT_LOG("higher than the maxBatchSize", LogLevel::Warning, Times(1));
|
|
});
|
|
|
|
const uint32 MAX_BATCH_SIZE = 3;
|
|
|
|
EventQueue eventQueue;
|
|
|
|
for (uint32 i = 0; i < MAX_BATCH_SIZE + 1; i++)
|
|
{
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent()));
|
|
}
|
|
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBodyServer(MAX_BATCH_SIZE), eventConfig));
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(eventConfig);
|
|
}
|
|
#endif
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
/// @test Validates that we have an appropriate sequence id on request creation.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PushEventSequenceId)
|
|
{
|
|
EventQueue eventQueue;
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
const Vector<String> expectedEvents
|
|
{
|
|
"game.start",
|
|
"custom.Test",
|
|
"custom.Test",
|
|
"custom.Test",
|
|
"custom.Test",
|
|
};
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents(expectedEvents, resultJson));
|
|
|
|
const String eventStr(resultJson["events"].getItems().at(0).renderContent());
|
|
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(0)["seqId"].getValueInteger());
|
|
ASSERT_EQ(1, resultJson["events"].getItems().at(1)["seqId"].getValueInteger());
|
|
ASSERT_EQ(2, resultJson["events"].getItems().at(2)["seqId"].getValueInteger());
|
|
ASSERT_EQ(3, resultJson["events"].getItems().at(3)["seqId"].getValueInteger());
|
|
ASSERT_EQ(4, resultJson["events"].getItems().at(4)["seqId"].getValueInteger());
|
|
}
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom("Test")));
|
|
|
|
//We should still have a increment after a request creation
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "custom.Test" }, resultJson));
|
|
ASSERT_EQ(5, resultJson["events"].getItems().at(0)["seqId"].getValueInteger());
|
|
}
|
|
}
|
|
|
|
/// @test Validates that no request is created if there are only a few non critical events like player.position
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_NoRequestWhenOnlyFewPlayerPosition)
|
|
{
|
|
EventQueue eventQueue;
|
|
|
|
// Pop a first request to get rid of events like game.start
|
|
{
|
|
eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
}
|
|
|
|
const uint32 MAX_NON_CRITICAL_EVENTS = 30;
|
|
// Until MAX_NON_CRITICAL_EVENTS player.position events, the request should not be sent
|
|
for (uint32 i = 0; i < MAX_NON_CRITICAL_EVENTS - 1; i++)
|
|
{
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoPlayerPosition(Json().renderContent())));
|
|
}
|
|
|
|
{
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo()).size());
|
|
}
|
|
|
|
// Reaching MAX_NON_CRITICAL_EVENTS -> The request should be sent
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoPlayerPosition(Json().renderContent())));
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
ASSERT_EQ(1, requests.size());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
EXPECT_EQ(MAX_NON_CRITICAL_EVENTS, resultJson["events"].getItems().size());
|
|
}
|
|
}
|
|
|
|
/// @test Validates that a request is created if there are only a few non critical events like player.position, but at least one "critical" event is present
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_RequestCreatedWhenAtLeastOneCriticalEventIsInQueue)
|
|
{
|
|
EventQueue eventQueue;
|
|
|
|
// Pop a first request to get rid of events like game.start
|
|
{
|
|
eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
}
|
|
|
|
// Only a few player.position events -> no request
|
|
for (uint32 i = 0; i < 5; i++)
|
|
{
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoPlayerPosition(Json().renderContent())));
|
|
}
|
|
|
|
{
|
|
ASSERT_EQ(0, eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo()).size());
|
|
}
|
|
|
|
// Adding a "critical" event
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent("TestingService")));
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
ASSERT_EQ(1, requests.size());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
EXPECT_EQ(6, resultJson["events"].getItems().size());
|
|
}
|
|
}
|
|
|
|
|
|
/// @test Validates that we can get play time even if it has never been set
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_GetPlayTimeNotSet)
|
|
{
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(0u), EventQueue().m_playTimeAbsoluteTimePoint)
|
|
<< "Play time should be 0 if it has never been set.";
|
|
}
|
|
|
|
/// @test Validates that we can set play time to a given value
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeSet)
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME = 10ul;
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME), eventQueue.m_playTimeAbsoluteTimePoint)
|
|
<< "Play time should be equal to the value set.";
|
|
}
|
|
|
|
/// @test Validates that the play time clock can be set several times consecutively
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeReSet)
|
|
{
|
|
EventQueue eventQueue;
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_1 = 0ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1));
|
|
}
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_2 = 10ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_2));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_2), eventQueue.m_playTimeAbsoluteTimePoint);
|
|
}
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_3 = 100ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_3));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_3), eventQueue.m_playTimeAbsoluteTimePoint);
|
|
}
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_4 = 1000ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_4));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_4), eventQueue.m_playTimeAbsoluteTimePoint);
|
|
}
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_5 = 10000ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_5));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_5), eventQueue.m_playTimeAbsoluteTimePoint);
|
|
}
|
|
{
|
|
// Validating that we can set the play time backwards without issue.
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_6 = 1000ul;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_6));
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_6), eventQueue.m_playTimeAbsoluteTimePoint);
|
|
}
|
|
}
|
|
|
|
/// @test Validates that the play time clock does not change over time unless directly changed.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeStableOverTime)
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME = 2000ul;
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME));
|
|
|
|
// Arbitrary but sufficient amount of time for possible instabilities to affect set play time.
|
|
US_TEST_NS::Helper::sleep(5000);
|
|
|
|
ASSERT_EQ(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME), eventQueue.m_playTimeAbsoluteTimePoint)
|
|
<< "Play time should remain unchanged and stable over time if it has net been intentionally directly set";
|
|
}
|
|
|
|
|
|
/// @test Validates that the play time is stable and accurate over several sets and events.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimePushAbsolute)
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_1 = 100ul;
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_2 = 200ul;
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_3 = 200ul;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME)));
|
|
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
|
|
//Play time should not change after request creation
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start", "custom.Testing" }, resultJson));
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_1, static_cast<TimeSeconds>(resultJson["events"].getItems().at(1)["absolutePlaytime"].getValueInteger()));
|
|
}
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_2));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME)));
|
|
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "custom.Testing" }, resultJson));
|
|
const TimeSeconds eventPlayTime = static_cast<TimeSeconds>(resultJson["events"].getItems().at(0)["absolutePlaytime"].getValueInteger());
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_2, eventPlayTime);
|
|
}
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_3));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent("TestingService")));
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "service.TestingService" }, resultJson));
|
|
const TimeSeconds eventPlayTime = static_cast<TimeSeconds>(resultJson["events"].getItems().at(0)["absolutePlaytime"].getValueInteger());
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_3, eventPlayTime) << "ABSOLUTE_PLAYTIME_3 time should have passed.";
|
|
}
|
|
}
|
|
|
|
/// @test Validates that the events pushed have the correct session playTime
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimePush)
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_1 = 100ul;
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_2 = 200ul;
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_3 = 300ul;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME)));
|
|
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
|
|
//Play time should not change after request creation
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start", "custom.Testing" }, resultJson));
|
|
ASSERT_EQ(0ul, static_cast<TimeSeconds>(resultJson["events"].getItems().at(1)["relativePlaytime"].getValueInteger()));
|
|
}
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_2));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoCustom(CUSTOM_EVENT_NAME)));
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "custom.Testing" }, resultJson));
|
|
const TimeSeconds eventPlaytime = static_cast<TimeSeconds>(resultJson["events"].getItems().at(0)["relativePlaytime"].getValueInteger());
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_2 - ABSOLUTE_PLAYTIME_1, eventPlaytime);
|
|
}
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_3));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(TestHelpers_BF::getServiceEvent("TestingService")));
|
|
{
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, eventConfig);
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "service.TestingService" }, resultJson));
|
|
const TimeSeconds eventPlaytime = static_cast<TimeSeconds>(resultJson["events"].getItems().at(0)["relativePlaytime"].getValueInteger());
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_3 - ABSOLUTE_PLAYTIME_1, eventPlaytime) << "ABSOLUTE_PLAYTIME_2 time should have passed.";
|
|
}
|
|
}
|
|
|
|
/// @test Validates that playTime clock doesn't accumulate ticks when returning from the application suspended state.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeSuspended)
|
|
{
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_START = 100ul;
|
|
const TimeSeconds SUSPENDED_PLAYTIME = 1ul;
|
|
const TimeSeconds SESSION_PLAYTIME = 1ul;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START));
|
|
|
|
US_TEST_NS::Helper::sleep(SUSPENDED_PLAYTIME * TestEventQueue_BF::s_PLAYTIME_WAIT_ONESECOND);
|
|
|
|
eventQueue.notifySuspendedAwake(ClockSteady::getNanoFromSeconds(SUSPENDED_PLAYTIME));
|
|
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_START, ClockSteady::getSecondsFromNano(eventQueue.m_playTimeAbsoluteTimePoint))
|
|
<< "Play time should have been affected by suspend.";
|
|
|
|
US_TEST_NS::Helper::sleep((SUSPENDED_PLAYTIME + SESSION_PLAYTIME) * TestEventQueue_BF::s_PLAYTIME_WAIT_ONESECOND);
|
|
|
|
eventQueue.notifySuspendedAwake(ClockSteady::getNanoFromSeconds(SUSPENDED_PLAYTIME));
|
|
|
|
ASSERT_EQ(ABSOLUTE_PLAYTIME_START, ClockSteady::getSecondsFromNano(eventQueue.m_playTimeAbsoluteTimePoint))
|
|
<< "Awaken. Play time should not be affected.";
|
|
}
|
|
|
|
/// @test Validates the context event has the right playTime duration value.
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeContextDuration)
|
|
{
|
|
const EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
const EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_1 = 100ul;
|
|
const TimeSeconds CONTEXT_DURATION = 3ul;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
|
|
// Arbitrary sleep time value, only to ensure that the playtime duration is not impacted by the actual time.
|
|
US_TEST_NS::Helper::sleep(10ul);
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1 + CONTEXT_DURATION));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_EQ(CONTEXT_DURATION, resultJson["events"].getItems().at(2)["typeData"]["contextDurationInPlaytime"].getValueInteger())
|
|
<< "Contexts starting and stopping should not affect the play time.";
|
|
}
|
|
|
|
/// @test Validates that if the playtime is decremented, the context duration is 0 if the context.start is detected
|
|
/// later than the context.stop. (No "negative" value)
|
|
/// Note : In this test, the time shift is not sufficient to go back before the absolute playtime start
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeContextDurationWithLowTimeShift)
|
|
{
|
|
EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_START = 100ul;
|
|
const TimeSeconds TIME_BEFORE_CONTEXT = 10ul;
|
|
const TimeSeconds TIME_SHIFT_DURING_CONTEXT = 5ul; // Should be lower than TIME_BEFORE_CONTEXT
|
|
|
|
EventQueue eventQueue;
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START));
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START + TIME_BEFORE_CONTEXT));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START + TIME_BEFORE_CONTEXT - TIME_SHIFT_DURING_CONTEXT));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(2)["typeData"]["contextDurationInPlaytime"].getValueInteger())
|
|
<< "The context playTime duration should be set to 0 if the playtime is decremented during the context.";
|
|
ASSERT_EQ(TIME_BEFORE_CONTEXT - TIME_SHIFT_DURING_CONTEXT, resultJson["events"].getItems().at(2)["relativePlaytime"].getValueInteger())
|
|
<< "The context.stop relative playTime should still be calculated based on the ABSOLUTE_PLAYTIME_START value.";
|
|
}
|
|
|
|
/// @test Validates that if the playtime is decremented, the context duration is 0 if the context.start is detected
|
|
/// later than the context.stop. (No "negative" value)
|
|
/// Note : In this test, the time shift is not sufficient to go back before the absolute playtime start
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeContextDurationWithHighTimeShift)
|
|
{
|
|
EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_START = 100ul;
|
|
const TimeSeconds TIME_BEFORE_CONTEXT = 10ul;
|
|
const TimeSeconds TIME_SHIFT_DURING_CONTEXT = 20ul; // Should be higher than TIME_BEFORE_CONTEXT
|
|
|
|
EventQueue eventQueue;
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START));
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START + TIME_BEFORE_CONTEXT));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_START + TIME_BEFORE_CONTEXT - TIME_SHIFT_DURING_CONTEXT));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(2)["typeData"]["contextDurationInPlaytime"].getValueInteger())
|
|
<< "The context playTime duration should be set to 0 if the playtime is decremented during the context.";
|
|
ASSERT_EQ(0u, resultJson["events"].getItems().at(2)["relativePlaytime"].getValueInteger())
|
|
<< "The context playTime duration should be set to 0 if the playtime is decremented to a value below ABSOLUTE_PLAYTIME_START during the context.";
|
|
}
|
|
|
|
/// @test Validates the context playTime duration value doesn't accumulate time while suspended
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimeContextDurationSuspended)
|
|
{
|
|
EventInfoContextStart contextStartEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStop contextStopEvent(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
|
|
const TimeSeconds ABSOLUTE_PLAYTIME_1 = 100ul;
|
|
const TimeSeconds SUSPENDED_PLAYTIME = 1ul;
|
|
const TimeSeconds CONTEXT_PLAYTIME = 20ul;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent));
|
|
eventQueue.notifySuspendedAwake(ClockSteady::getNanoFromSeconds(SUSPENDED_PLAYTIME));
|
|
|
|
// Arbitrary sleep time value, only to ensure that the playtime duration is not impacted by the actual time.
|
|
US_TEST_NS::Helper::sleep(10ul);
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_1 + CONTEXT_PLAYTIME));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStopEvent));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
ASSERT_EQ(CONTEXT_PLAYTIME, resultJson["events"].getItems().at(2)["typeData"]["contextDurationInPlaytime"].getValueInteger())
|
|
<< "Contexts starting and stopping should affect play time even when they are suspended.";
|
|
}
|
|
|
|
/// @test Validates that pushing an event while the playtime clock isn't set doesn't output
|
|
TEST_F(SERVICES_EVENT_QUEUE, LOCAL_PlayTimePushEventNoTimeplay)
|
|
{
|
|
EventQueue eventQueue;
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoContextStart(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName)));
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(EventInfoContextStop(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName)));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
ASSERT_TRUE(TestEventQueue_BF::validateEvents({ "game.start",
|
|
String::formatText("context.start.%s", TestEventQueue_BF::s_mockContextType),
|
|
String::formatText("context.stop.%s", TestEventQueue_BF::s_mockContextType) }, resultJson));
|
|
|
|
const Json contextStop = resultJson["events"].getItems().at(0);
|
|
ASSERT_FALSE(contextStop["absolutePlaytime"].isTypeNumber());
|
|
ASSERT_FALSE(contextStop["relativePlaytime"].isTypeNumber());
|
|
ASSERT_FALSE(contextStop["typeData"]["contextDurationInPlaytime"].isTypeNumber());
|
|
}
|
|
|
|
TEST_F(SERVICES_EVENT_QUEUE, US_TestAbsoluteAndRelativePlaytimeDifferences)
|
|
{
|
|
const int32 ABSOLUTE_PLAYTIME_REFERENCE_VALUE_1 = 1000u;
|
|
const int32 ABSOLUTE_PLAYTIME_REFERENCE_VALUE_2 = 1100u;
|
|
const int32 RELATIVE_PLAYTIME_REFERENCE_VALUE = ABSOLUTE_PLAYTIME_REFERENCE_VALUE_2 - ABSOLUTE_PLAYTIME_REFERENCE_VALUE_1;
|
|
|
|
EventQueue eventQueue;
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_REFERENCE_VALUE_1));
|
|
|
|
EventInfoContextStart contextStartEvent1(TestEventQueue_BF::s_mockContextType, TestEventQueue_BF::s_mockContextName);
|
|
EventInfoContextStart contextStartEvent2("OtherType", TestEventQueue_BF::s_mockContextName);
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent1));
|
|
|
|
eventQueue.setPlayTime(ClockSteady::getNanoFromSeconds(ABSOLUTE_PLAYTIME_REFERENCE_VALUE_2));
|
|
|
|
ASSERT_EQ(PushEventResult::Success, eventQueue.pushEvent(contextStartEvent2));
|
|
|
|
const Vector<EventRequestPtr> requests = eventQueue.popEventRequests(TestEventQueue_BF::s_currentSession, EventConfigInfo());
|
|
EventConfigInfo eventConfig;
|
|
ASSERT_TRUE(EventConfigInfoPrivate::extractData(EventsConfigMockHelper::getBody(), eventConfig));
|
|
const String requestResult = requests[0]->outputHttpBodyFormat(TestEventQueue_BF::s_currentSession, eventConfig).front();
|
|
|
|
const Json resultJson(requestResult);
|
|
|
|
if (resultJson["events"].getItemsCount() > 0)
|
|
{
|
|
EXPECT_EQ(ABSOLUTE_PLAYTIME_REFERENCE_VALUE_1, resultJson["events"].getItems().at(1)["absolutePlaytime"].getValueInteger());
|
|
EXPECT_EQ(0u, resultJson["events"].getItems().at(1)["relativePlaytime"].getValueInteger());
|
|
|
|
EXPECT_EQ(ABSOLUTE_PLAYTIME_REFERENCE_VALUE_2, resultJson["events"].getItems().at(2)["absolutePlaytime"].getValueInteger());
|
|
EXPECT_EQ(RELATIVE_PLAYTIME_REFERENCE_VALUE, resultJson["events"].getItems().at(2)["relativePlaytime"].getValueInteger());
|
|
}
|
|
else
|
|
{
|
|
ADD_FAILURE() << "Expected a event request valid body: " << requestResult.getUtf8();
|
|
}
|
|
}
|
|
#endif // !defined(US_SDK_S2S)
|
|
#endif // US_DLL
|
|
|
|
};
|