1057 lines
44 KiB
C++
1057 lines
44 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "ReplicationSystemServerClientTestFixture.h"
|
|
#include "Iris/ReplicationSystem/ReplicationSystem.h"
|
|
#include "Iris/ReplicationSystem/Filtering/NetObjectFilter.h"
|
|
#include "Tests/EnsureScope.h"
|
|
|
|
namespace UE::Net::Private
|
|
{
|
|
|
|
class FTestCancelPendingDestroyFixture : public FReplicationSystemServerClientTestFixture
|
|
{
|
|
};
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnCreateConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write packet
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Deliver original packet
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// Verify that the object now exists on client
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
|
|
// Modify a property on the object and make sure it's replicated as the object should now be confirmed created
|
|
ServerObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnCreateConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write packet
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on object creation
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Write and send packet and verify object is created
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnCreateConfirmationWithPacketLossNotifyBeforeCancel)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write packet
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Notify packet loss, which should set state to Invalid/not replicated
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Remove object from filter to cause object to end up in PendingCreate
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Write and send packet and verify object is created
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringCreated)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object now also exists on the client
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Modify a property on the object and make sure it's replicated as the object should still be created
|
|
ServerObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnDestroyConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the object destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Verify that object still exists on client
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
|
|
// Modify a property on the object and make sure it's replicated as the object should still be created
|
|
ServerObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnDestroyConfirmationWithPacketLossNotifyBeforeCancel)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the object destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that object still exists on client
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ServerObject->NetRefHandle));
|
|
|
|
// Modify a property on the object and make sure it's replicated as the object should still be created
|
|
ServerObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnDestroyConfirmationWithInitialPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Introduce latency by not immediately delivering packets.
|
|
Server->NetUpdate();
|
|
Server->SendTo(Client, TEXT("Create object"));
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause it to end up being PendingDestroy
|
|
Server->ReplicationSystem->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
|
|
Server->NetUpdate();
|
|
Server->SendTo(Client, TEXT("Destroy object"));
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to not destroy it.
|
|
Server->ReplicationSystem->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
|
|
// Modify object.
|
|
ServerObject->IntA += 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendTo(Client, TEXT("Update object"));
|
|
Server->PostSendUpdate();
|
|
|
|
// Drop the initial packet.
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Deliver remaining packets, if any.
|
|
{
|
|
SIZE_T PacketCount = 0;
|
|
const auto& ConnectionInfo = Server->GetConnectionInfo(Client->ConnectionIdOnServer);
|
|
PacketCount = ConnectionInfo.WrittenPackets.Count();
|
|
for (SIZE_T PacketIt = 0; PacketIt != PacketCount; ++PacketIt)
|
|
{
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
}
|
|
}
|
|
|
|
Server->UpdateAndSend({ Client });
|
|
|
|
// The object should end up being created with the latest state.
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnDestroyConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy, also modify a property
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
ServerObject->IntA ^= 1;
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Deliver object destroy packet
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// The destroy was delivered so the client object should not exist
|
|
UE_NET_ASSERT_FALSE(Client->IsValidNetRefHandle(ServerObject->NetRefHandle));
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientObject->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
// Tests for canceling a canceled pending destroy
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingDestroyDuringWaitOnCreateConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write packet
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// Verify that the object now exists on client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingDestroyDuringWaitOnCreateConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write packet
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on object creation
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Verify that the object doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object still doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingDestroyDuringCreated)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object now also exists on the client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
|
|
// Filter out object to cause a PendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingDestroyDuringWaitOnDestroyConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the object destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Verify that the object still exists on client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingDestroyDuringWaitOnDestroyConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Deliver destroy packet
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// Verify that the object doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the object still doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
|
|
// Subobject tests
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingSubObjectDestroyDuringCreated)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object with subobject on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject exists on the client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Filter out subobject to cause a SubObjectPendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove subobject from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Modify a property on the subobject and make sure it's replicated as the subobject should still exist
|
|
ServerSubObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientSubObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientSubObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientSubObject->IntA, ServerSubObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestDestroySubObjectWhenRootGoesOutOfAndInToScope)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object with subobject on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
const FNetRefHandle ObjectRefHandle = ServerObject->NetRefHandle;
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
const FNetRefHandle SubObjectRefHandle = ServerSubObject->NetRefHandle;
|
|
|
|
// Write and send packet
|
|
Server->UpdateAndSend({Client});
|
|
|
|
// Verify that the subobject exists on the client
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(SubObjectRefHandle));
|
|
|
|
// Destroy subobject to cause a SubObjectPendingDestroy
|
|
Server->DestroyObject(ServerSubObject);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out root object and write packet. This causes subobject to go from SubObjectPendingDestroy to PendingDestroy.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Lose packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Remove root object from NotReplicated group to have it end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
|
|
// Update and deliver packet
|
|
Server->UpdateAndSend({Client});
|
|
|
|
// The subobject should not exist
|
|
UE_NET_ASSERT_FALSE(Client->IsValidNetRefHandle(SubObjectRefHandle));
|
|
// The root object should still exist
|
|
UE_NET_ASSERT_TRUE(Client->IsResolvableNetRefHandle(ObjectRefHandle));
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingSubObjectDestroyDuringWaitOnDestroyConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause subobject to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove subobject from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the subobject destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Verify that object still exists on client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Modify a property on the subobject and make sure it's replicated as the subobject should still exist
|
|
ServerSubObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientSubObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientSubObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientSubObject->IntA, ServerSubObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingSubObjectDestroyDuringWaitOnDestroyConfirmationWithPacketLossNotifyBeforeCancel)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause subobject to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the subobject destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Remove subobject from filter to cause object to end up in CancelPendingDestroy
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that object still exists on client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Modify a property on the subobject and make sure it's replicated as the subobject should still exist
|
|
ServerSubObject->IntA ^= 1;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* ClientSubObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientSubObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientSubObject->IntA, ServerSubObject->IntA);
|
|
}
|
|
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingSubObjectDestroyDuringWaitOnDestroyConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause subobject to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy, also modify a property
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
ServerSubObject->IntA ^= 1;
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Deliver subobject destroy packet
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// The destroy was delivered so the client subobject should not exist
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Client subobject should have been created with the latest state
|
|
UTestReplicatedIrisObject* ClientSubObject = Cast<UTestReplicatedIrisObject>(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle));
|
|
UE_NET_ASSERT_NE(ClientSubObject, nullptr);
|
|
UE_NET_ASSERT_EQ(ClientSubObject->IntA, ServerSubObject->IntA);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingSubObjectDestroyDuringCreated)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject now also exists on the client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Filter out object to cause a SubObjectPendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause object to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the subobject to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyFromCreatedDoesNotMissChanges)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client0 = CreateClient();
|
|
|
|
// Add second client, with not filtering to keep object in scope
|
|
FReplicationSystemTestClient* Client1 = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client0, DeliverPacket);
|
|
Server->SendAndDeliverTo(Client1, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
UTestReplicatedIrisObject* Client0Object = Cast<UTestReplicatedIrisObject>(Client0->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
UTestReplicatedIrisObject* Client1Object = Cast<UTestReplicatedIrisObject>(Client1->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
|
|
// Verify that the object was replicated to all clients
|
|
UE_NET_ASSERT_NE(Client0Object, nullptr);
|
|
UE_NET_ASSERT_EQ(Client0Object->IntA, ServerObject->IntA);
|
|
UE_NET_ASSERT_NE(Client1Object, nullptr);
|
|
UE_NET_ASSERT_EQ(Client1Object->IntA, ServerObject->IntA);
|
|
|
|
// Filter out object to cause a PendingDestroy for Client0
|
|
FNetObjectGroupHandle ExclusionGroupHandle = Server->ReplicationSystem->CreateGroup(NAME_None);
|
|
Server->ReplicationSystem->AddToGroup(ExclusionGroupHandle, ServerObject->NetRefHandle);
|
|
Server->ReplicationSystem->AddExclusionFilterGroup(ExclusionGroupHandle);
|
|
|
|
Server->ReplicationSystem->SetGroupFilterStatus(ExclusionGroupHandle, Client0->ConnectionIdOnServer, ENetFilterStatus::Disallow);
|
|
Server->ReplicationSystem->SetGroupFilterStatus(ExclusionGroupHandle, Client1->ConnectionIdOnServer, ENetFilterStatus::Allow);
|
|
|
|
Server->NetUpdate();
|
|
Server->SendTo(Client0);
|
|
Server->PostSendUpdate();
|
|
|
|
// Mark dirty
|
|
ServerObject->IntA = 3;
|
|
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client1, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Allow replication again, to trigger cancel
|
|
Server->ReplicationSystem->SetGroupFilterStatus(ExclusionGroupHandle, Client0->ConnectionIdOnServer, ENetFilterStatus::Allow);
|
|
|
|
// Drop the packet with the destroy
|
|
Server->DeliverTo(Client0, false);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client0, DeliverPacket);
|
|
Server->SendAndDeliverTo(Client1, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
Client0Object = Cast<UTestReplicatedIrisObject>(Client0->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
Client1Object = Cast<UTestReplicatedIrisObject>(Client1->GetReplicationBridge()->GetReplicatedObject(ServerObject->NetRefHandle));
|
|
|
|
// Verify that the cancel worked and did not miss changed state
|
|
UE_NET_ASSERT_NE(Client0Object, nullptr);
|
|
UE_NET_ASSERT_EQ(Client0Object->IntA, ServerObject->IntA);
|
|
UE_NET_ASSERT_NE(Client1Object, nullptr);
|
|
UE_NET_ASSERT_EQ(Client1Object->IntA, ServerObject->IntA);
|
|
}
|
|
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingSubObjectDestroyDuringWaitOnDestroyConfirmationWithPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out object and write packet to cause subobject to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove object from filter to cause subobject to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the subobject to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Cause packet loss on the subobject destroy packet
|
|
Server->DeliverTo(Client, DoNotDeliverPacket);
|
|
|
|
// Verify that the object still exists on client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelingCancelPendingSubObjectDestroyDuringWaitOnDestroyConfirmationWithoutPacketLoss)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out subobject and write packet to cause subobject to end up in WaitOnDestroyConfirmation
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Remove subobject from filter to cause subobject to end up in CancelPendingDestroy...
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We want the subobject to be destroyed after all.
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Deliver destroy packet
|
|
Server->DeliverTo(Client, DeliverPacket);
|
|
|
|
// Verify that the subobject doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject still doesn't exist on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelRootObjectDestroyAfterSubObjectDestroy)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Write and send packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject now also exists on the client
|
|
UE_NET_ASSERT_NE(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
|
|
// Filter out subobject to cause a SubObjectPendingDestroy
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerSubObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Filter out root object to cause subobject to move to PendingDestroy instead
|
|
Server->GetReplicationSystem()->AddToGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// ... and cancel that thought! We don't want the object to be destroyed after all.
|
|
Server->GetReplicationSystem()->RemoveFromGroup(Server->GetReplicationSystem()->GetNotReplicatedNetObjectGroup(), ServerObject->NetRefHandle);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
// Write and send a packet
|
|
Server->NetUpdate();
|
|
Server->SendAndDeliverTo(Client, DeliverPacket);
|
|
Server->PostSendUpdate();
|
|
|
|
// Verify that the subobject was destroyed on the client
|
|
UE_NET_ASSERT_EQ(Client->GetReplicationBridge()->GetReplicatedObject(ServerSubObject->NetRefHandle), nullptr);
|
|
}
|
|
|
|
UE_NET_TEST_FIXTURE(FTestCancelPendingDestroyFixture, TestCancelPendingDestroyDuringWaitOnDestroyConfirmationDoesNotTriggerEnsure)
|
|
{
|
|
// Add a client
|
|
FReplicationSystemTestClient* Client = CreateClient();
|
|
|
|
// Spawn temp object on server to reserver low internal index
|
|
UTestReplicatedIrisObject* ServerTempObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Spawn object on server
|
|
UTestReplicatedIrisObject* ServerObject = Server->CreateObject(UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Destroy temp object and perfom an update tick to allow the internal index to be reused
|
|
{
|
|
Server->DestroyObject(ServerTempObject);
|
|
ServerTempObject = nullptr;
|
|
Server->UpdateAndSend({});
|
|
}
|
|
|
|
// Write and send packet
|
|
Server->UpdateAndSend({Client});
|
|
|
|
// Filter out object and write packet to cause object to end up in WaitOnDestroyConfirmation
|
|
FNetObjectGroupHandle ExclusionGroupHandle = Server->GetReplicationSystem()->CreateGroup(NAME_None);
|
|
Server->ReplicationSystem->AddToGroup(ExclusionGroupHandle, ServerObject->NetRefHandle);
|
|
Server->ReplicationSystem->AddExclusionFilterGroup(ExclusionGroupHandle);
|
|
Server->ReplicationSystem->SetGroupFilterStatus(ExclusionGroupHandle, Client->ConnectionIdOnServer, ENetFilterStatus::Disallow);
|
|
|
|
Server->NetUpdate();
|
|
Server->SendUpdate(Client->ConnectionIdOnServer);
|
|
Server->PostSendUpdate();
|
|
|
|
// Create subobject on server
|
|
UTestReplicatedIrisObject* ServerSubObject = Server->CreateSubObject(ServerObject->NetRefHandle, UTestReplicatedIrisObject::FComponents());
|
|
|
|
// Allow replication again to have the object end up in CancelPendingDestroy. Assert that no ensure was triggered.
|
|
{
|
|
FEnsureScope EnsureScope;
|
|
|
|
Server->ReplicationSystem->SetGroupFilterStatus(ExclusionGroupHandle, Client->ConnectionIdOnServer, ENetFilterStatus::Allow);
|
|
Server->NetUpdate();
|
|
Server->PostSendUpdate();
|
|
|
|
UE_NET_ASSERT_EQ(EnsureScope.GetCount(), 0);
|
|
}
|
|
}
|
|
|
|
// See TestObjectSplitting.cpp for cancel pending destroy on huge object
|
|
|
|
}
|