Added tests. Made network spawnable to serialize in binary

Signed-off-by: pereslav <pereslav@amazon.com>
monroegm-disable-blank-issue-2
pereslav 4 years ago
parent fc72a1a327
commit b1a76feead

@ -163,6 +163,7 @@ if (PAL_TRAIT_BUILD_TESTS_SUPPORTED)
NAMESPACE Gem
FILES_CMAKE
multiplayer_tests_files.cmake
multiplayer_autogen_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Tests
@ -175,6 +176,16 @@ if (PAL_TRAIT_BUILD_TESTS_SUPPORTED)
PRIVATE
AZ::AzTest
Gem::Multiplayer.Static
AUTOGEN_RULES
*.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h
*.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl
*.AutoPackets.xml,AutoPackets_Source.jinja,$path/$fileprefix.AutoPackets.cpp
*.AutoPackets.xml,AutoPacketDispatcher_Header.jinja,$path/$fileprefix.AutoPacketDispatcher.h
*.AutoPackets.xml,AutoPacketDispatcher_Inline.jinja,$path/$fileprefix.AutoPacketDispatcher.inl
*.AutoComponent.xml,AutoComponent_Header.jinja,$path/$fileprefix.AutoComponent.h
*.AutoComponent.xml,AutoComponent_Source.jinja,$path/$fileprefix.AutoComponent.cpp
*.AutoComponent.xml,AutoComponentTypes_Header.jinja,$path/AutoComponentTypes.h
*.AutoComponent.xml,AutoComponentTypes_Source.jinja,$path/AutoComponentTypes.cpp
)
ly_add_googletest(
NAME Gem::Multiplayer.Tests

@ -110,7 +110,7 @@ namespace Multiplayer
auto serializer = [](AZStd::vector<uint8_t>& output, const ProcessedObjectStore& object) -> bool {
AZ::IO::ByteContainerStream stream(&output);
auto& asset = object.GetAsset();
return AZ::Utils::SaveObjectToStream(stream, AZ::DataStream::ST_JSON, &asset, asset.GetType());
return AZ::Utils::SaveObjectToStream(stream, AZ::DataStream::ST_BINARY, &asset, asset.GetType());
};
auto&& [object, networkSpawnable] =

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<Component
Name="TestMultiplayerComponent"
Namespace="MultiplayerTest"
OverrideComponent="true"
OverrideController="true"
OverrideInclude="Tests/TestMultiplayerComponent.h"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NetworkInput Type="uint64_t" Name="OwnerId" Init="0" />
</Component>

@ -16,6 +16,8 @@
#include <Multiplayer/Components/NetBindComponent.h>
#include <Multiplayer/Components/NetworkHierarchyChildComponent.h>
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
#include <Source/NetworkInput/NetworkInputArray.h>
#include <Source/NetworkEntity/NetworkEntityManager.h>
namespace Multiplayer
{
@ -175,10 +177,10 @@ namespace Multiplayer
void CreateSimpleHierarchy(EntityInfo& root, EntityInfo& child)
{
PopulateHierarchicalEntity(root);
SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Client);
SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Autonomous);
PopulateHierarchicalEntity(child);
SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Client);
SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Autonomous);
// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller)
SetParentIdOnNetworkTransform(child.m_entity, root.m_netId);
@ -330,7 +332,7 @@ namespace Multiplayer
void CreateDeepHierarchyOnClient(EntityInfo& childOfChild)
{
PopulateHierarchicalEntity(childOfChild);
SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Client);
SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Autonomous);
// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller)
SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childOfChild->m_netId);
@ -387,4 +389,66 @@ namespace Multiplayer
);
}
}
TEST_F(ClientDeepHierarchyTests, CreateProcessInputTest)
{
using MultiplayerTest::TestMultiplayerComponent;
using MultiplayerTest::TestMultiplayerComponentController;
using MultiplayerTest::TestMultiplayerComponentNetworkInput;
auto* rootNetBind = m_root->m_entity->FindComponent<NetBindComponent>();
NetworkInputArray inputArray(rootNetBind->GetEntityHandle());
NetworkInput& input = inputArray[0];
const float deltaTime = 0.16f;
rootNetBind->CreateInput(input, deltaTime);
auto ValidateCreatedInput = [](const NetworkInput& input, const HierarchyTests::EntityInfo& entityInfo)
{
// Validate test input for the root entity's TestMultiplayerComponent
auto* testInput = input.FindComponentInput<TestMultiplayerComponentNetworkInput>();
EXPECT_NE(testInput, nullptr);
auto* testMultiplayerComponent = entityInfo.m_entity->FindComponent<TestMultiplayerComponent>();
EXPECT_NE(testMultiplayerComponent, nullptr);
EXPECT_EQ(testInput->m_ownerId, testMultiplayerComponent->GetId());
};
// Validate root input
ValidateCreatedInput(input, *m_root);
// Validate children input
{
NetworkHierarchyRootComponentNetworkInput* rootHierarchyInput = input.FindComponentInput<NetworkHierarchyRootComponentNetworkInput>();
const AZStd::vector<NetworkInputChild>& childInputs = rootHierarchyInput->m_childInputs;
EXPECT_EQ(childInputs.size(), 2);
ValidateCreatedInput(childInputs[0].GetNetworkInput(), *m_child);
ValidateCreatedInput(childInputs[1].GetNetworkInput(), *m_childOfChild);
}
// Test ProcessInput
{
AZStd::unordered_set<NetEntityId> inputProcessedEntities;
size_t processInputCallCounter = 0;
auto processInputCallback = [&inputProcessedEntities, &processInputCallCounter](NetEntityId netEntityId)
{
inputProcessedEntities.insert(netEntityId);
processInputCallCounter++;
};
// Set the callbacks for processing input. This allows us to inspect how many times the input was processed
// and which entity's controller was invoked.
m_root->m_entity->FindComponent<TestMultiplayerComponent>()->m_processInputCallback = processInputCallback;
m_child->m_entity->FindComponent<TestMultiplayerComponent>()->m_processInputCallback = processInputCallback;
m_childOfChild->m_entity->FindComponent<TestMultiplayerComponent>()->m_processInputCallback = processInputCallback;
rootNetBind->ProcessInput(input, deltaTime);
EXPECT_EQ(processInputCallCounter, 3);
EXPECT_EQ(inputProcessedEntities,
AZStd::unordered_set<NetEntityId>({ m_root->m_netId, m_child->m_netId, m_childOfChild->m_netId }));
}
}
}

@ -30,6 +30,7 @@
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
#include <NetworkEntity/NetworkEntityAuthorityTracker.h>
#include <NetworkEntity/NetworkEntityTracker.h>
#include <Tests/TestMultiplayerComponent.h>
namespace Multiplayer
{
@ -93,6 +94,12 @@ namespace Multiplayer
m_netTransformDescriptor.reset(NetworkTransformComponent::CreateDescriptor());
m_netTransformDescriptor->Reflect(m_serializeContext.get());
m_testMultiplayerComponentDescriptor.reset(MultiplayerTest::TestMultiplayerComponent::CreateDescriptor());
m_testMultiplayerComponentDescriptor->Reflect(m_serializeContext.get());
m_testInputDriverComponentDescriptor.reset(MultiplayerTest::TestInputDriverComponent::CreateDescriptor());
m_testInputDriverComponentDescriptor->Reflect(m_serializeContext.get());
m_mockMultiplayer = AZStd::make_unique<NiceMock<MockMultiplayer>>();
AZ::Interface<IMultiplayer>::Register(m_mockMultiplayer.get());
@ -103,6 +110,7 @@ namespace Multiplayer
GetMultiplayer()->GetStats().ReserveComponentStats(Multiplayer::InvalidNetComponentId, 50, 0);
m_mockNetworkEntityManager = AZStd::make_unique<NiceMock<MockNetworkEntityManager>>();
AZ::Interface<INetworkEntityManager>::Register(m_mockNetworkEntityManager.get());
ON_CALL(*m_mockNetworkEntityManager, AddEntityToEntityMap(_, _)).WillByDefault(Invoke(this, &HierarchyTests::AddEntityToEntityMap));
ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::GetEntity));
@ -136,6 +144,7 @@ namespace Multiplayer
m_multiplayerComponentRegistry = AZStd::make_unique<MultiplayerComponentRegistry>();
ON_CALL(*m_mockNetworkEntityManager, GetMultiplayerComponentRegistry()).WillByDefault(Return(m_multiplayerComponentRegistry.get()));
RegisterMultiplayerComponents();
MultiplayerTest::RegisterMultiplayerComponents();
}
void TearDown() override
@ -157,6 +166,7 @@ namespace Multiplayer
AZ::Interface<INetworkTime>::Unregister(m_mockNetworkTime.get());
AZ::Interface<AZ::ITime>::Unregister(m_mockTime.get());
AZ::Interface<INetworkEntityManager>::Unregister(m_mockNetworkEntityManager.get());
AZ::Interface<IMultiplayer>::Unregister(m_mockMultiplayer.get());
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(m_mockComponentApplicationRequests.get());
@ -165,6 +175,8 @@ namespace Multiplayer
m_mockNetworkEntityManager.reset();
m_mockMultiplayer.reset();
m_testInputDriverComponentDescriptor.reset();
m_testMultiplayerComponentDescriptor.reset();
m_transformDescriptor.reset();
m_netTransformDescriptor.reset();
m_hierarchyRootDescriptor.reset();
@ -186,6 +198,8 @@ namespace Multiplayer
AZStd::unique_ptr<AZ::ComponentDescriptor> m_hierarchyRootDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_hierarchyChildDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_netTransformDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_testMultiplayerComponentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_testInputDriverComponentDescriptor;
AZStd::unique_ptr<NiceMock<MockMultiplayer>> m_mockMultiplayer;
AZStd::unique_ptr<MockNetworkEntityManager> m_mockNetworkEntityManager;
@ -394,6 +408,9 @@ namespace Multiplayer
entityInfo.m_entity->CreateComponent<AzFramework::TransformComponent>();
entityInfo.m_entity->CreateComponent<NetBindComponent>();
entityInfo.m_entity->CreateComponent<NetworkTransformComponent>();
entityInfo.m_entity->CreateComponent<MultiplayerTest::TestMultiplayerComponent>();
entityInfo.m_entity->CreateComponent<MultiplayerTest::TestInputDriverComponent>();
switch (entityInfo.m_role)
{
case EntityInfo::Role::Root:

@ -0,0 +1,78 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Tests/TestMultiplayerComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace MultiplayerTest
{
void TestInputDriverComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<TestInputDriverComponent, AZ::Component>()
->Version(1);
}
}
void TestMultiplayerComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<TestMultiplayerComponent, TestMultiplayerComponentBase>()
->Version(1);
}
TestMultiplayerComponentBase::Reflect(context);
}
void TestMultiplayerComponent::OnInit()
{
}
void TestMultiplayerComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
}
void TestMultiplayerComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
}
TestMultiplayerComponentController::TestMultiplayerComponentController(TestMultiplayerComponent& parent)
: TestMultiplayerComponentControllerBase(parent)
{
}
void TestMultiplayerComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
}
void TestMultiplayerComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
{
}
void TestMultiplayerComponentController::CreateInput(Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime)
{
auto* networkInput = input.FindComponentInput<TestMultiplayerComponentNetworkInput>();
networkInput->m_ownerId = GetParent().GetId();
}
void TestMultiplayerComponentController::ProcessInput(Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime)
{
auto& component = GetParent();
auto* networkInput = input.FindComponentInput<TestMultiplayerComponentNetworkInput>();
AZ_Assert(networkInput->m_ownerId == component.GetId(), "Input Id doesn't match the owner component Id");
if (component.m_processInputCallback)
{
component.m_processInputCallback(GetNetEntityId());
}
}
}

@ -0,0 +1,61 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Tests/AutoGen/TestMultiplayerComponent.AutoComponent.h>
namespace MultiplayerTest
{
// Dummy class for satisfying "MultiplayerInputDriver" component dependency
class TestInputDriverComponent : public AZ::Component
{
public:
AZ_COMPONENT(TestInputDriverComponent, "{C3877905-3B61-45AE-A636-9845C3AAA39D}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.emplace_back(AZ_CRC_CE("MultiplayerInputDriver"));
}
void Activate(){};
void Deactivate(){};
};
// Test multiplayer component with ability to create and process network input
class TestMultiplayerComponent
: public TestMultiplayerComponentBase
{
public:
AZ_MULTIPLAYER_COMPONENT(MultiplayerTest::TestMultiplayerComponent, s_testMultiplayerComponentConcreteUuid, MultiplayerTest::TestMultiplayerComponentBase);
static void Reflect(AZ::ReflectContext* context);
void OnInit() override;
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
AZStd::function<void(Multiplayer::NetEntityId)> m_processInputCallback;
};
// Multiplayer controller for the test component
class TestMultiplayerComponentController
: public TestMultiplayerComponentControllerBase
{
public:
TestMultiplayerComponentController(TestMultiplayerComponent& parent);
//! TestMultiplayerComponentControllerBase
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
//! MultiplayerController interface
void CreateInput(Multiplayer::NetworkInput& input, float deltaTime) override;
void ProcessInput(Multiplayer::NetworkInput& input, float deltaTime) override;
};
}

@ -7,6 +7,12 @@
#
set(FILES
Include/Multiplayer/AutoGen/AutoComponentTypes_Header.jinja
Include/Multiplayer/AutoGen/AutoComponentTypes_Source.jinja
Include/Multiplayer/AutoGen/AutoComponent_Common.jinja
Include/Multiplayer/AutoGen/AutoComponent_Header.jinja
Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
Tests/AutoGen/TestMultiplayerComponent.AutoComponent.xml
Tests/ClientHierarchyTests.cpp
Tests/ServerHierarchyBenchmarks.cpp
Tests/CommonHierarchySetup.h
@ -19,4 +25,6 @@ set(FILES
Tests/RewindableContainerTests.cpp
Tests/RewindableObjectTests.cpp
Tests/ServerHierarchyTests.cpp
Tests/TestMultiplayerComponent.h
Tests/TestMultiplayerComponent.cpp
)

Loading…
Cancel
Save