2022-07-13 03:11:55 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "TestArrayPropertyNetSerializer.h"
# include "TestNetSerializerFixture.h"
# include "Iris/ReplicationState/InternalReplicationStateDescriptorUtils.h"
# include "Iris/ReplicationState/PropertyNetSerializerInfoRegistry.h"
2023-04-18 12:49:50 -04:00
# include "Iris/ReplicationState/PropertyReplicationState.h"
2022-07-13 03:11:55 -04:00
# include "Iris/ReplicationState/ReplicationStateDescriptorBuilder.h"
2023-04-18 12:49:50 -04:00
# include "Iris/ReplicationState/ReplicationStateUtil.h"
2022-07-13 03:11:55 -04:00
# include "Iris/Serialization/InternalNetSerializers.h"
# include "Iris/Serialization/NetSerializers.h"
# include "Iris/Serialization/InternalNetSerializationContext.h"
2023-04-18 12:49:50 -04:00
# include "Net/Core/NetBitArray.h"
# include "Net/UnrealNetwork.h"
# include "Tests/Serialization/MockNetSerializer.h"
2022-07-13 03:11:55 -04:00
namespace UE : : Net : : Private
{
class FTestArrayPropertyNetSerializerBase : public FNetworkAutomationTestSuiteFixture
{
public :
FTestArrayPropertyNetSerializerBase ( ) : FNetworkAutomationTestSuiteFixture ( ) , ArrayPropertyNetSerializerConfig ( nullptr ) { }
protected :
virtual void SetUp ( ) override ;
virtual void TearDown ( ) override ;
template < typename ArrayType > void Quantize ( const ArrayType & Source , void * StateBuffer ) ;
template < typename ArrayType > void Dequantize ( const void * StateBuffer , ArrayType & Target ) ;
void FreeDynamicState ( void * StateBuffer ) ;
void Serialize ( const void * StateBuffer , void * BitstreamBuffer , SIZE_T BitStreamBufferSize ) ;
void SerializeDelta ( const void * StateBuffer , const void * PrevStateBuffer , void * BitStreamBuffer , SIZE_T BitStreamBufferSize ) ;
protected :
TRefCountPtr < const FReplicationStateDescriptor > ReplicationStateDescriptor ;
FNetSerializationContext NetSerializationContext ;
FInternalNetSerializationContext InternalContext ;
FMockNetSerializerCallCounter MockNetSerializerCallCounter ;
FMockNetSerializerReturnValues MockNetSerializerReturnValues ;
FMockNetSerializerConfig MockNetSerializerConfig ;
FArrayPropertyNetSerializerConfig * ArrayPropertyNetSerializerConfig ;
const FNetSerializer * ArrayPropertyNetSerializer = & UE_NET_GET_SERIALIZER ( FArrayPropertyNetSerializer ) ;
FReplicationStateMemberSerializerDescriptor OriginalMemberSerializerDescriptor ;
FReplicationStateMemberSerializerDescriptor MockMemberSerializerDescriptor ;
FNetBitStreamReader Reader ;
FNetBitStreamWriter Writer ;
enum : uint32
{
BufferSize = 1024 ,
} ;
alignas ( 16 ) uint8 StateBuffer0 [ BufferSize ] = { } ;
alignas ( 16 ) uint8 StateBuffer1 [ BufferSize ] = { } ;
alignas ( 16 ) uint8 BitStreamBuffer0 [ BufferSize ] ;
alignas ( 16 ) uint8 BitStreamBuffer1 [ BufferSize ] ;
} ;
class FTestSimpleArrayPropertyNetSerializer : public FTestArrayPropertyNetSerializerBase
{
protected :
virtual void SetUp ( ) override ;
virtual void TearDown ( ) override ;
void TestDescriptorHasDynamicStateTrait ( ) ;
void TestQuantize ( ) ;
void TestDequantize ( ) ;
void TestCloneDynamicState ( ) ;
void TestFreeDynamicState ( ) ;
void TestSerialize ( ) ;
void TestDeserialize ( ) ;
void TestSerializeDelta ( ) ;
void TestDeserializeDelta ( ) ;
void TestIsEqual ( ) ;
void TestValidate ( ) ;
void SetupForMockSerializer ( ) ;
void SetupForOriginalSerializer ( ) ;
protected :
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest EmptyArrayInstance0 ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest EmptyArrayInstance1 ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance0 ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance1 ;
} ;
class FTestComplexArrayPropertyNetSerializer : public FTestArrayPropertyNetSerializerBase
{
public :
FTestComplexArrayPropertyNetSerializer ( ) : FTestArrayPropertyNetSerializerBase ( ) , InnerArrayPropertyNetSerializerConfig ( nullptr ) { }
protected :
virtual void SetUp ( ) override ;
virtual void TearDown ( ) override ;
void TestQuantize ( ) ;
void TestDequantize ( ) ;
void TestCloneDynamicState ( ) ;
void TestFreeDynamicState ( ) ;
void TestSerialize ( ) ;
void TestDeserialize ( ) ;
void TestSerializeDelta ( ) ;
void TestDeserializeDelta ( ) ;
void TestIsEqual ( ) ;
void TestValidate ( ) ;
void SetupForMockSerializer ( ) ;
void SetupForOriginalSerializer ( ) ;
protected :
enum : uint32 { TotalNumberOfElementsInNonEmptyArray = 6 } ;
FArrayPropertyNetSerializerConfig * InnerArrayPropertyNetSerializerConfig ;
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest EmptyArrayInstance0 ;
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest EmptyArrayInstance1 ;
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance0 ;
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance1 ;
} ;
2023-04-18 12:49:50 -04:00
class FTestElementChangeMaskForArrayPropertyNetSerializer : public FTestArrayPropertyNetSerializerBase
{
protected :
virtual void SetUp ( ) override ;
virtual void TearDown ( ) override ;
} ;
2022-07-13 03:11:55 -04:00
// Basic tests
UE_NET_TEST_FIXTURE ( FTestArrayPropertyNetSerializerBase , TestHasIsForwardingSerializerTrait )
{
UE_NET_ASSERT_TRUE ( EnumHasAnyFlags ( ArrayPropertyNetSerializer - > Traits , ENetSerializerTraits : : IsForwardingSerializer ) ) ;
}
UE_NET_TEST_FIXTURE ( FTestArrayPropertyNetSerializerBase , TestHasDynamicStateTrait )
{
UE_NET_ASSERT_TRUE ( EnumHasAnyFlags ( ArrayPropertyNetSerializer - > Traits , ENetSerializerTraits : : HasDynamicState ) ) ;
}
// Tests for array of primitive type
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestDescriptorHasDynamicStateTrait )
{
TestDescriptorHasDynamicStateTrait ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestQuantize )
{
TestQuantize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestDequantize )
{
TestDequantize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestCloneDynamicState )
{
TestCloneDynamicState ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestFreeDynamicState )
{
TestFreeDynamicState ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestSerialize )
{
TestSerialize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestDeserialize )
{
TestDeserialize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestSerializeDelta )
{
TestSerializeDelta ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestDeserializeDelta )
{
TestDeserializeDelta ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestIsEqual )
{
TestIsEqual ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestSimpleArrayPropertyNetSerializer , TestValidate )
{
TestValidate ( ) ;
}
// Tests for nested array
UE_NET_TEST_FIXTURE ( FTestComplexArrayPropertyNetSerializer , TestQuantize )
{
TestQuantize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestComplexArrayPropertyNetSerializer , TestDequantize )
{
TestDequantize ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestComplexArrayPropertyNetSerializer , TestCloneDynamicState )
{
TestCloneDynamicState ( ) ;
}
UE_NET_TEST_FIXTURE ( FTestComplexArrayPropertyNetSerializer , TestFreeDynamicState )
{
TestFreeDynamicState ( ) ;
}
2023-04-18 12:49:50 -04:00
// Tests for array element changemask
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestChangeMaskIsModifiedWhenAddingElements )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
// Add one element at a time until the last bit in the changemask is set and make sure the array is always marked as dirty as well as the corresponding element
for ( unsigned ElementIt = 0 , ElementEndIt = FPropertyReplicationState : : TArrayElementChangeMaskBits ; ElementIt ! = ElementEndIt ; + + ElementIt )
{
Source - > ArrayOfUint . Add ( 0 ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayPropertyChangeMaskBitIndex ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayElementChangeMaskBitOffset + ElementIt ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , 2U ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
}
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestChangeMaskIsModifiedWhenAddingElementsBeyondChangeMaskCapacity )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
// First add elements up to the max element changemask capacity.
{
Source - > ArrayOfUint . SetNum ( FPropertyReplicationState : : TArrayElementChangeMaskBits ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , ArrayChangeMask . GetNumBits ( ) ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
// Double the array size by adding one element at a time until the last bit in the changemask is set and make sure the array is always marked as dirty as well as the corresponding element.
for ( unsigned ElementIt = 0 , ElementEndIt = FPropertyReplicationState : : TArrayElementChangeMaskBits ; ElementIt ! = ElementEndIt ; + + ElementIt )
{
Source - > ArrayOfUint . Add ( 0 ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayPropertyChangeMaskBitIndex ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayElementChangeMaskBitOffset + ElementIt ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , 2U ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
}
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestChangeMaskIsModifiedWhenModifyingElements )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
// First add elements up to the max element changemask capacity.
{
Source - > ArrayOfUint . SetNum ( FPropertyReplicationState : : TArrayElementChangeMaskBits ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
// Modify one element at a time until the last bit in the changemask is set and make sure the array is always marked as dirty as well as the corresponding element
for ( unsigned ElementIt = 0 , ElementEndIt = FPropertyReplicationState : : TArrayElementChangeMaskBits ; ElementIt ! = ElementEndIt ; + + ElementIt )
{
Source - > ArrayOfUint [ ElementIt ] ^ = 7U ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayPropertyChangeMaskBitIndex ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayElementChangeMaskBitOffset + ElementIt ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , 2U ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
}
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestChangeMaskIsModifiedWhenModifyingElementsBeyondChangeMaskCapacity )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
// First add elements up to double the max element changemask capacity.
{
Source - > ArrayOfUint . SetNum ( 2 * FPropertyReplicationState : : TArrayElementChangeMaskBits ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
// Double the array size by adding one element at a time until the last bit in the changemask is set and make sure the array is always marked as dirty as well as the corresponding element.
for ( unsigned ElementIt = 0 , ElementEndIt = FPropertyReplicationState : : TArrayElementChangeMaskBits ; ElementIt ! = ElementEndIt ; + + ElementIt )
{
Source - > ArrayOfUint [ FPropertyReplicationState : : TArrayElementChangeMaskBits + ElementIt ] ^ = 7U ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayPropertyChangeMaskBitIndex ) ) ;
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayElementChangeMaskBitOffset + ElementIt ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , 2U ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
}
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestChangeMaskIsModifiedWhenModifyingMultipleArbitraryElements )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
constexpr int32 ElementCount = 17 ;
// First add some elements
{
Source - > ArrayOfUint . SetNum ( ElementCount ) ;
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
}
// Modify some arbitrary elements
const int32 ElementIndicesToModify [ ] = { 3 , 7 , 11 } ;
for ( int32 ElementIndex : ElementIndicesToModify )
{
Source - > ArrayOfUint [ ElementIndex ] ^ = 471147114711U ;
}
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
// Verify the elements were marked as dirty
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayPropertyChangeMaskBitIndex ) ) ;
UE_NET_ASSERT_EQ ( ArrayChangeMask . CountSetBits ( ) , uint32 ( UE_ARRAY_COUNT ( ElementIndicesToModify ) + 1U ) ) ;
for ( int32 ElementIndex : ElementIndicesToModify )
{
UE_NET_ASSERT_TRUE ( ArrayChangeMask . GetBit ( FPropertyReplicationState : : TArrayElementChangeMaskBitOffset + ElementIndex ) ) ;
}
}
UE_NET_TEST_FIXTURE ( FTestElementChangeMaskForArrayPropertyNetSerializer , TestSerializingFewElementsUsesLessBandwidth )
{
FPropertyReplicationState ReplicationState ( ReplicationStateDescriptor ) ;
TObjectPtr < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > Source = NewObject < UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ;
FNetBitArrayView ArrayChangeMask = UE : : Net : : Private : : GetMemberChangeMask ( ReplicationState . GetStateBuffer ( ) , ReplicationStateDescriptor ) ;
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
constexpr int32 ElementCount = 17 ;
// First add some elements
{
Source - > ArrayOfUint . SetNum ( ElementCount ) ;
// Modify all elements
for ( uint32 & Element : Source - > ArrayOfUint )
{
Element ^ = 101U ;
}
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
}
NetSerializationContext . SetChangeMask ( & ArrayChangeMask ) ;
FNetSerializeArgs SerializeArgs = { } ;
{
SerializeArgs . Version = ArrayPropertyNetSerializer - > Version ;
SerializeArgs . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
SerializeArgs . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
SerializeArgs . ChangeMaskInfo = FNetSerializerChangeMaskParam { 0 , static_cast < uint16 > ( ArrayChangeMask . GetNumBits ( ) ) } ;
}
uint32 BitsWrittenForFullArray = 0 ;
{
Quantize ( Source - > ArrayOfUint , StateBuffer0 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
ArrayPropertyNetSerializer - > Serialize ( NetSerializationContext , SerializeArgs ) ;
Writer . CommitWrites ( ) ;
BitsWrittenForFullArray = Writer . GetPosBits ( ) ;
UE_NET_ASSERT_GT ( BitsWrittenForFullArray , 0U ) ;
FreeDynamicState ( StateBuffer0 ) ;
}
// Modify a few elements
{
2024-05-16 13:31:10 -04:00
ArrayChangeMask . ClearAllBits ( ) ;
2023-04-18 12:49:50 -04:00
const int32 ElementIndicesToModify [ ] = { 3 , 7 , 11 } ;
for ( int32 ElementIndex : ElementIndicesToModify )
{
Source - > ArrayOfUint [ ElementIndex ] + = 1U ;
}
ReplicationState . PollPropertyReplicationState ( Source . Get ( ) ) ;
}
uint32 BitsWrittenForPartialArray = 0 ;
{
Quantize ( Source - > ArrayOfUint , StateBuffer0 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
ArrayPropertyNetSerializer - > Serialize ( NetSerializationContext , SerializeArgs ) ;
Writer . CommitWrites ( ) ;
BitsWrittenForPartialArray = Writer . GetPosBits ( ) ;
UE_NET_ASSERT_GT ( BitsWrittenForPartialArray , 0U ) ;
FreeDynamicState ( StateBuffer0 ) ;
}
UE_NET_ASSERT_LT ( BitsWrittenForPartialArray , BitsWrittenForFullArray ) ;
}
2022-07-13 03:11:55 -04:00
// FTestArrayPropertyNetSerializerBase implementation
void FTestArrayPropertyNetSerializerBase : : SetUp ( )
{
FMockNetSerializerConfig & SerializerConfig = MockNetSerializerConfig ;
SerializerConfig . CallCounter = & MockNetSerializerCallCounter ;
SerializerConfig . ReturnValues = & MockNetSerializerReturnValues ;
MockMemberSerializerDescriptor . Serializer = & UE_NET_GET_SERIALIZER ( FMockNetSerializer ) ;
MockMemberSerializerDescriptor . SerializerConfig = & SerializerConfig ;
}
void FTestArrayPropertyNetSerializerBase : : TearDown ( )
{
}
template < typename ArrayType >
void FTestArrayPropertyNetSerializerBase : : Quantize ( const ArrayType & Array , void * StateBuffer )
{
FNetQuantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer ) ;
Args . Source = NetSerializerValuePointer ( & Array ) ;
ArrayPropertyNetSerializer - > Quantize ( NetSerializationContext , Args ) ;
}
template < typename ArrayType >
void FTestArrayPropertyNetSerializerBase : : Dequantize ( const void * StateBuffer , ArrayType & Array )
{
FNetDequantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer ) ;
Args . Target = NetSerializerValuePointer ( & Array ) ;
ArrayPropertyNetSerializer - > Dequantize ( NetSerializationContext , Args ) ;
}
void FTestArrayPropertyNetSerializerBase : : FreeDynamicState ( void * StateBuffer )
{
FNetFreeDynamicStateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer ) ;
ArrayPropertyNetSerializer - > FreeDynamicState ( NetSerializationContext , Args ) ;
}
void FTestArrayPropertyNetSerializerBase : : Serialize ( const void * StateBuffer , void * BitStreamBuffer , SIZE_T BitStreamBufferSize )
{
2023-11-06 09:55:13 -05:00
Writer . InitBytes ( BitStreamBuffer , IntCastChecked < uint32 > ( BitStreamBufferSize ) ) ;
2022-07-13 03:11:55 -04:00
FNetSerializeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer ) ;
ArrayPropertyNetSerializer - > Serialize ( NetSerializationContext , Args ) ;
Writer . CommitWrites ( ) ;
}
void FTestArrayPropertyNetSerializerBase : : SerializeDelta ( const void * StateBuffer , const void * PrevStateBuffer , void * BitStreamBuffer , SIZE_T BitStreamBufferSize )
{
2023-11-06 09:55:13 -05:00
Writer . InitBytes ( BitStreamBuffer , IntCastChecked < uint32 > ( BitStreamBufferSize ) ) ;
2022-07-13 03:11:55 -04:00
FNetSerializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer ) ;
Args . Prev = NetSerializerValuePointer ( PrevStateBuffer ) ;
ArrayPropertyNetSerializer - > SerializeDelta ( NetSerializationContext , Args ) ;
Writer . CommitWrites ( ) ;
}
// FTestSimpleArrayPropertyNetSerializer implementation
void FTestSimpleArrayPropertyNetSerializer : : SetUp ( )
{
FTestArrayPropertyNetSerializerBase : : SetUp ( ) ;
ReplicationStateDescriptor = FReplicationStateDescriptorBuilder : : CreateDescriptorForStruct ( StaticStruct < FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest > ( ) ) ;
2023-02-13 20:09:19 -05:00
UE_NET_ASSERT_EQ_MSG ( ReplicationStateDescriptor - > MemberCount , uint16 ( 1 ) , " Expected FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest to only contain a single array " ) ;
2022-07-13 03:11:55 -04:00
ArrayPropertyNetSerializerConfig = const_cast < FArrayPropertyNetSerializerConfig * > ( static_cast < const FArrayPropertyNetSerializerConfig * > ( ReplicationStateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) ) ;
2023-02-13 20:09:19 -05:00
UE_NET_ASSERT_EQ_MSG ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberCount , uint16 ( 1 ) , " Expected array element descriptor to only contain a single member " ) ;
2022-07-13 03:11:55 -04:00
OriginalMemberSerializerDescriptor = ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ;
NonEmptyArrayInstance0 . ArrayOfUint . SetNumZeroed ( 3 ) ;
NonEmptyArrayInstance1 . ArrayOfUint . SetNumZeroed ( 3 ) ;
2023-11-06 09:55:13 -05:00
for ( int32 It = 0 , EndIt = 3 ; It ! = EndIt ; + + It )
2022-07-13 03:11:55 -04:00
{
NonEmptyArrayInstance0 . ArrayOfUint [ It ] = It + 1 ;
NonEmptyArrayInstance1 . ArrayOfUint [ It ] = It + 1 ;
}
// Setup a NetSerializationContext that allows memory allocations and can write to a bit stream
{
NetSerializationContext = FNetSerializationContext ( & Reader , & Writer ) ;
NetSerializationContext . SetInternalContext ( & InternalContext ) ;
}
}
void FTestSimpleArrayPropertyNetSerializer : : TearDown ( )
{
ArrayPropertyNetSerializerConfig = nullptr ;
ReplicationStateDescriptor . SafeRelease ( ) ;
FTestArrayPropertyNetSerializerBase : : TearDown ( ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : SetupForMockSerializer ( )
{
FReplicationStateMemberSerializerDescriptor & ArrayElementSerializerDescriptor = const_cast < FReplicationStateMemberSerializerDescriptor & > ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ;
ArrayElementSerializerDescriptor = MockMemberSerializerDescriptor ;
}
void FTestSimpleArrayPropertyNetSerializer : : SetupForOriginalSerializer ( )
{
FReplicationStateMemberSerializerDescriptor & ArrayElementSerializerDescriptor = const_cast < FReplicationStateMemberSerializerDescriptor & > ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ;
ArrayElementSerializerDescriptor = OriginalMemberSerializerDescriptor ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestDescriptorHasDynamicStateTrait ( )
{
UE_NET_ASSERT_TRUE ( EnumHasAnyFlags ( ReplicationStateDescriptor - > Traits , EReplicationStateTraits : : HasDynamicState ) ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestQuantize ( )
{
SetupForMockSerializer ( ) ;
// The storage need to be cleared in order for the test to succeed.
UE_NET_ASSERT_EQ ( FMemory : : Memcmp ( StateBuffer0 , StateBuffer1 , sizeof ( StateBuffer0 ) ) , 0 ) ;
// Use a non-empty array so we can see that we actually get calls
FNetQuantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( & NonEmptyArrayInstance0 . ArrayOfUint ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > Quantize ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Quantize , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
// While we have no knowledge about the internal quantized state we expect it to not be full of zeros for a non-empty array.
UE_NET_ASSERT_NE ( FMemory : : Memcmp ( StateBuffer0 , StateBuffer1 , sizeof ( StateBuffer0 ) ) , 0 ) ;
FreeDynamicState ( StateBuffer0 ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestDequantize ( )
{
SetupForOriginalSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) + 1 ) ;
FNetDequantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Target = NetSerializerValuePointer ( & TargetStruct . ArrayOfUint ) ;
ArrayPropertyNetSerializer - > Dequantize ( NetSerializationContext , Args ) ;
FreeDynamicState ( StateBuffer0 ) ;
// Test array size and contents is correct.
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) , TargetStruct . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfUint [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue , DequantizedValue ) ;
}
}
void FTestSimpleArrayPropertyNetSerializer : : TestCloneDynamicState ( )
{
SetupForOriginalSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
FNetCloneDynamicStateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
ArrayPropertyNetSerializer - > CloneDynamicState ( NetSerializationContext , Args ) ;
// Dequantize and validate contents to verify that the cloning is correct
{
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
Dequantize ( StateBuffer1 , TargetStruct . ArrayOfUint ) ;
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) , TargetStruct . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < uint32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfUint [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue , DequantizedValue ) ;
}
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestFreeDynamicState ( )
{
SetupForMockSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
FNetFreeDynamicStateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > FreeDynamicState ( NetSerializationContext , Args ) ;
// We don't really have a good way to test an array of simple elements. However, FreeDynamicState must be re-entrant.
// So we test that it's working as intended by calling FreeDynamicState again and assume a bad implementation would crash.
ArrayPropertyNetSerializer - > FreeDynamicState ( NetSerializationContext , Args ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestSerialize ( )
{
SetupForMockSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
FNetSerializeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > Serialize ( NetSerializationContext , Args ) ;
FreeDynamicState ( StateBuffer0 ) ;
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Serialize , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestDeserialize ( )
{
SetupForOriginalSerializer ( ) ;
// Need to prepare for serializing the data.
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Serialize ( StateBuffer0 , BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
// Deserialize.
{
Reader . InitBits ( BitStreamBuffer0 , Writer . GetPosBits ( ) ) ;
FNetDeserializeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
ArrayPropertyNetSerializer - > Deserialize ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_FALSE ( NetSerializationContext . HasErrorOrOverflow ( ) ) ;
UE_NET_ASSERT_EQ ( Reader . GetPosBits ( ) , Writer . GetPosBits ( ) ) ;
}
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) + 1 ) ;
Dequantize ( StateBuffer0 , TargetStruct . ArrayOfUint ) ;
// Verify state
{
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) , TargetStruct . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfUint [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue , DequantizedValue ) ;
}
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
void FTestSimpleArrayPropertyNetSerializer : : TestSerializeDelta ( )
{
SetupForMockSerializer ( ) ;
// Delta non-empty array against empty array
{
Quantize ( EmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
MockNetSerializerCallCounter . Reset ( ) ;
FNetSerializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > SerializeDelta ( NetSerializationContext , Args ) ;
// Since we're delta compressing against an empty buffer we do expect one serialize or serializedelta call per array element.
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Serialize + MockNetSerializerCallCounter . SerializeDelta , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
// Delta empty array against non-empty array
{
Quantize ( EmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
MockNetSerializerCallCounter . Reset ( ) ;
FNetSerializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer1 ) ;
ArrayPropertyNetSerializer - > SerializeDelta ( NetSerializationContext , Args ) ;
// Since we're delta compressing against an empty buffer we do expect one serialize or serializedelta call per array element.
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Serialize + MockNetSerializerCallCounter . SerializeDelta , 0U ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
// Delta non-empty array against different non-empty array
{
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance ;
NonEmptyArrayInstance . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ;
Quantize ( NonEmptyArrayInstance . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
Writer . InitBytes ( BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
MockNetSerializerCallCounter . Reset ( ) ;
FNetSerializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > SerializeDelta ( NetSerializationContext , Args ) ;
// Since we're delta compressing against an empty buffer we do expect one serialize or serializedelta call per array element.
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Serialize + MockNetSerializerCallCounter . SerializeDelta , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
}
void FTestSimpleArrayPropertyNetSerializer : : TestDeserializeDelta ( )
{
SetupForOriginalSerializer ( ) ;
// Delta non-empty array against empty array
{
Quantize ( EmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
SerializeDelta ( StateBuffer1 , StateBuffer0 , BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
FreeDynamicState ( StateBuffer1 ) ;
Reader . InitBits ( BitStreamBuffer0 , Writer . GetPosBits ( ) ) ;
FNetDeserializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > DeserializeDelta ( NetSerializationContext , Args ) ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) + 1 ) ;
Dequantize ( StateBuffer1 , TargetStruct . ArrayOfUint ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
// Verify state
{
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) , TargetStruct . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfUint [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue , DequantizedValue ) ;
}
}
}
// Delta empty array against non-empty array
{
Quantize ( EmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
SerializeDelta ( StateBuffer1 , StateBuffer0 , BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
FreeDynamicState ( StateBuffer1 ) ;
Reader . InitBits ( BitStreamBuffer0 , Writer . GetPosBits ( ) ) ;
FNetDeserializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > DeserializeDelta ( NetSerializationContext , Args ) ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfUint . SetNumZeroed ( 1 ) ;
Dequantize ( StateBuffer1 , TargetStruct . ArrayOfUint ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
UE_NET_ASSERT_EQ ( TargetStruct . ArrayOfUint . Num ( ) , 0 ) ;
}
// Delta non-empty array against different non-empty array
{
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance ;
NonEmptyArrayInstance . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ;
Quantize ( NonEmptyArrayInstance . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer1 ) ;
SerializeDelta ( StateBuffer1 , StateBuffer0 , BitStreamBuffer0 , sizeof ( BitStreamBuffer0 ) ) ;
FreeDynamicState ( StateBuffer1 ) ;
Reader . InitBits ( BitStreamBuffer0 , Writer . GetPosBits ( ) ) ;
FNetDeserializeDeltaArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . Prev = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > DeserializeDelta ( NetSerializationContext , Args ) ;
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfUint . SetNumZeroed ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) + 1 ) ;
Dequantize ( StateBuffer1 , TargetStruct . ArrayOfUint ) ;
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
// Verify state
{
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) , TargetStruct . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfUint [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue , DequantizedValue ) ;
}
}
}
}
void FTestSimpleArrayPropertyNetSerializer : : TestIsEqual ( )
{
// Check empty arrays are considered equal
for ( const bool bIsUsingMockSerializer : { false , true } )
{
bIsUsingMockSerializer ? SetupForMockSerializer ( ) : SetupForOriginalSerializer ( ) ;
{
// The MockNetSerializer shouldn't be called at all but we do the call count check to detect that.
MockNetSerializerReturnValues . bIsEqual = true ;
MockNetSerializerCallCounter . Reset ( ) ;
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( & EmptyArrayInstance0 . ArrayOfUint ) ;
Args . Source1 = NetSerializerValuePointer ( & EmptyArrayInstance1 . ArrayOfUint ) ;
Args . bStateIsQuantized = false ;
const bool bEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . IsEqual , 0U ) ;
}
}
{
Quantize ( EmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( EmptyArrayInstance1 . ArrayOfUint , StateBuffer1 ) ;
// The MockNetSerializer shouldn't be called at all but we do the call count check to detect that.
MockNetSerializerReturnValues . bIsEqual = true ;
MockNetSerializerCallCounter . Reset ( ) ;
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Source1 = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . bStateIsQuantized = true ;
const bool bQuantizedEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bQuantizedEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . IsEqual , 0U ) ;
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
}
// Check non-empty identical arrays are considered equal
for ( const bool bIsUsingMockSerializer : { false , true } )
{
bIsUsingMockSerializer ? SetupForMockSerializer ( ) : SetupForOriginalSerializer ( ) ;
{
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( & NonEmptyArrayInstance0 . ArrayOfUint ) ;
Args . Source1 = NetSerializerValuePointer ( & NonEmptyArrayInstance1 . ArrayOfUint ) ;
Args . bStateIsQuantized = false ;
MockNetSerializerReturnValues . bIsEqual = true ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bNonEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bNonEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . IsEqual , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
}
}
{
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance1 . ArrayOfUint , StateBuffer1 ) ;
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Source1 = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . bStateIsQuantized = true ;
MockNetSerializerReturnValues . bIsEqual = true ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bQuantizedNonEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bQuantizedNonEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . IsEqual , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
}
// Check non-empty non-identical arrays aren't considered equal when using proper element serializer
for ( const bool bIsUsingMockSerializer : { false , true } )
{
2023-04-18 12:49:50 -04:00
bIsUsingMockSerializer ? SetupForMockSerializer ( ) : SetupForOriginalSerializer ( ) ;
2022-07-13 03:11:55 -04:00
FStructWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest NonEmptyArrayInstance = NonEmptyArrayInstance0 ;
NonEmptyArrayInstance . ArrayOfUint [ 1 ] = NonEmptyArrayInstance0 . ArrayOfUint [ 1 ] ^ 1U ;
{
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( & NonEmptyArrayInstance0 . ArrayOfUint ) ;
Args . Source1 = NetSerializerValuePointer ( & NonEmptyArrayInstance . ArrayOfUint ) ;
Args . bStateIsQuantized = false ;
MockNetSerializerReturnValues . bIsEqual = false ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bNonEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_FALSE ( bNonEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_GE ( MockNetSerializerCallCounter . IsEqual , 1U ) ;
}
}
{
Quantize ( NonEmptyArrayInstance0 . ArrayOfUint , StateBuffer0 ) ;
Quantize ( NonEmptyArrayInstance . ArrayOfUint , StateBuffer1 ) ;
FNetIsEqualArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source0 = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Source1 = NetSerializerValuePointer ( StateBuffer1 ) ;
Args . bStateIsQuantized = true ;
MockNetSerializerReturnValues . bIsEqual = false ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bQuantizedNonEmptyArraysAreEqual = ArrayPropertyNetSerializer - > IsEqual ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_FALSE ( bQuantizedNonEmptyArraysAreEqual ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_GE ( MockNetSerializerCallCounter . IsEqual , 1U ) ;
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
}
}
void FTestSimpleArrayPropertyNetSerializer : : TestValidate ( )
{
// Test empty array is valid
for ( const bool bIsUsingMockSerializer : { false , true } )
{
bIsUsingMockSerializer ? SetupForMockSerializer ( ) : SetupForOriginalSerializer ( ) ;
FNetValidateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( & EmptyArrayInstance0 . ArrayOfUint ) ;
MockNetSerializerReturnValues . bValidate = false ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bEmptyArrayIsValid = ArrayPropertyNetSerializer - > Validate ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bEmptyArrayIsValid ) ;
}
// Test non-empty array is valid
for ( const bool bIsUsingMockSerializer : { false , true } )
{
bIsUsingMockSerializer ? SetupForMockSerializer ( ) : SetupForOriginalSerializer ( ) ;
FNetValidateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( & NonEmptyArrayInstance0 . ArrayOfUint ) ;
MockNetSerializerReturnValues . bValidate = true ;
MockNetSerializerCallCounter . Reset ( ) ;
const bool bNonEmptyArrayIsValid = ArrayPropertyNetSerializer - > Validate ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_TRUE ( bNonEmptyArrayIsValid ) ;
if ( bIsUsingMockSerializer )
{
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Validate , uint32 ( NonEmptyArrayInstance0 . ArrayOfUint . Num ( ) ) ) ;
}
}
}
// FTestComplexArrayPropertyNetSerializer implementation
void FTestComplexArrayPropertyNetSerializer : : SetUp ( )
{
FTestArrayPropertyNetSerializerBase : : SetUp ( ) ;
ReplicationStateDescriptor = FReplicationStateDescriptorBuilder : : CreateDescriptorForStruct ( StaticStruct < FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest > ( ) ) ;
2023-02-13 20:09:19 -05:00
UE_NET_ASSERT_EQ_MSG ( ReplicationStateDescriptor - > MemberCount , uint16 ( 1 ) , " Expected FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest to only contain a single array " ) ;
2022-07-13 03:11:55 -04:00
ArrayPropertyNetSerializerConfig = const_cast < FArrayPropertyNetSerializerConfig * > ( static_cast < const FArrayPropertyNetSerializerConfig * > ( ReplicationStateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) ) ;
2023-02-13 20:09:19 -05:00
UE_NET_ASSERT_EQ_MSG ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberCount , uint16 ( 1 ) , " Expected array element descriptor to only contain a single member " ) ;
2022-07-13 03:11:55 -04:00
UE_NET_ASSERT_TRUE ( IsUsingStructNetSerializer ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ) ;
UE_NET_ASSERT_TRUE ( IsUsingArrayPropertyNetSerializer ( static_cast < const FStructNetSerializerConfig * > ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ) ;
const FStructNetSerializerConfig * StructSerializerConfig = static_cast < const FStructNetSerializerConfig * > ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) ;
InnerArrayPropertyNetSerializerConfig = const_cast < FArrayPropertyNetSerializerConfig * > ( static_cast < const FArrayPropertyNetSerializerConfig * > ( StructSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) ) ;
OriginalMemberSerializerDescriptor = InnerArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ;
NonEmptyArrayInstance0 . ArrayOfStructWithArray . Empty ( 3 ) ;
NonEmptyArrayInstance0 . ArrayOfStructWithArray . SetNum ( 3 ) ;
NonEmptyArrayInstance1 . ArrayOfStructWithArray . Empty ( 3 ) ;
NonEmptyArrayInstance1 . ArrayOfStructWithArray . SetNum ( 3 ) ;
2023-11-06 09:55:13 -05:00
for ( int32 It = 0 , EndIt = 3 ; It ! = EndIt ; + + It )
2022-07-13 03:11:55 -04:00
{
NonEmptyArrayInstance0 . ArrayOfStructWithArray [ It ] . ArrayOfUint . SetNumZeroed ( It + 1 ) ;
NonEmptyArrayInstance1 . ArrayOfStructWithArray [ It ] . ArrayOfUint . SetNumZeroed ( It + 1 ) ;
}
// Setup a NetSerializationContext that allows memory allocations and can write to a bit stream
{
NetSerializationContext = FNetSerializationContext ( & Reader , & Writer ) ;
NetSerializationContext . SetInternalContext ( & InternalContext ) ;
}
}
void FTestComplexArrayPropertyNetSerializer : : TearDown ( )
{
ArrayPropertyNetSerializerConfig = nullptr ;
InnerArrayPropertyNetSerializerConfig = nullptr ;
ReplicationStateDescriptor . SafeRelease ( ) ;
FTestArrayPropertyNetSerializerBase : : TearDown ( ) ;
}
void FTestComplexArrayPropertyNetSerializer : : SetupForMockSerializer ( )
{
FReplicationStateMemberSerializerDescriptor & ArrayElementSerializerDescriptor = const_cast < FReplicationStateMemberSerializerDescriptor & > ( InnerArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ;
ArrayElementSerializerDescriptor = MockMemberSerializerDescriptor ;
}
void FTestComplexArrayPropertyNetSerializer : : SetupForOriginalSerializer ( )
{
FReplicationStateMemberSerializerDescriptor & ArrayElementSerializerDescriptor = const_cast < FReplicationStateMemberSerializerDescriptor & > ( InnerArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ;
ArrayElementSerializerDescriptor = OriginalMemberSerializerDescriptor ;
}
void FTestComplexArrayPropertyNetSerializer : : TestQuantize ( )
{
SetupForMockSerializer ( ) ;
// The storage need to be cleared in order for the test to succeed.
UE_NET_ASSERT_EQ ( FMemory : : Memcmp ( StateBuffer0 , StateBuffer1 , sizeof ( StateBuffer0 ) ) , 0 ) ;
// Use a non-empty array so we can see that we actually get calls
FNetQuantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( & NonEmptyArrayInstance0 . ArrayOfStructWithArray ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > Quantize ( NetSerializationContext , Args ) ;
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . Quantize , uint32 ( TotalNumberOfElementsInNonEmptyArray ) ) ;
// While we have no knowledge about the internal quantized state we expect it to not be full of zeros for a non-empty array.
UE_NET_ASSERT_NE ( FMemory : : Memcmp ( StateBuffer0 , StateBuffer1 , sizeof ( StateBuffer0 ) ) , 0 ) ;
FreeDynamicState ( StateBuffer0 ) ;
}
void FTestComplexArrayPropertyNetSerializer : : TestDequantize ( )
{
SetupForOriginalSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfStructWithArray , StateBuffer0 ) ;
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest TargetStruct ;
TargetStruct . ArrayOfStructWithArray . SetNum ( NonEmptyArrayInstance0 . ArrayOfStructWithArray . Num ( ) + 1 ) ;
FNetDequantizeArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Target = NetSerializerValuePointer ( & TargetStruct . ArrayOfStructWithArray ) ;
ArrayPropertyNetSerializer - > Dequantize ( NetSerializationContext , Args ) ;
FreeDynamicState ( StateBuffer0 ) ;
// Test array size and contents is correct.
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfStructWithArray . Num ( ) , TargetStruct . ArrayOfStructWithArray . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfStructWithArray ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfStructWithArray . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfStructWithArray [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue . ArrayOfUint . Num ( ) , DequantizedValue . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalInnerValue : MakeArrayView ( OriginalValue . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 InnerElementIndex = static_cast < int32 > ( & OriginalInnerValue - OriginalValue . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedInnerValue = DequantizedValue . ArrayOfUint [ InnerElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalInnerValue , DequantizedInnerValue ) ;
}
}
}
void FTestComplexArrayPropertyNetSerializer : : TestCloneDynamicState ( )
{
SetupForOriginalSerializer ( ) ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfStructWithArray , StateBuffer0 ) ;
FNetCloneDynamicStateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
Args . Target = NetSerializerValuePointer ( StateBuffer1 ) ;
ArrayPropertyNetSerializer - > CloneDynamicState ( NetSerializationContext , Args ) ;
// Dequantize and validate contents to verify that the cloning is correct
{
FStructWithDynamicArrayOfComplexTypeForArrayPropertyNetSerializerTest TargetStruct ;
Dequantize ( StateBuffer1 , TargetStruct . ArrayOfStructWithArray ) ;
UE_NET_ASSERT_EQ ( NonEmptyArrayInstance0 . ArrayOfStructWithArray . Num ( ) , TargetStruct . ArrayOfStructWithArray . Num ( ) ) ;
for ( const auto & OriginalValue : MakeArrayView ( NonEmptyArrayInstance0 . ArrayOfStructWithArray ) )
{
2023-11-06 09:55:13 -05:00
const int32 ElementIndex = static_cast < int32 > ( & OriginalValue - NonEmptyArrayInstance0 . ArrayOfStructWithArray . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedValue = TargetStruct . ArrayOfStructWithArray [ ElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalValue . ArrayOfUint . Num ( ) , DequantizedValue . ArrayOfUint . Num ( ) ) ;
for ( const auto & OriginalInnerValue : MakeArrayView ( OriginalValue . ArrayOfUint ) )
{
2023-11-06 09:55:13 -05:00
const int32 InnerElementIndex = static_cast < int32 > ( & OriginalInnerValue - OriginalValue . ArrayOfUint . GetData ( ) ) ;
2022-07-13 03:11:55 -04:00
const auto & DequantizedInnerValue = DequantizedValue . ArrayOfUint [ InnerElementIndex ] ;
UE_NET_ASSERT_EQ ( OriginalInnerValue , DequantizedInnerValue ) ;
}
}
}
FreeDynamicState ( StateBuffer0 ) ;
FreeDynamicState ( StateBuffer1 ) ;
}
void FTestComplexArrayPropertyNetSerializer : : TestFreeDynamicState ( )
{
// Special setup to trap recursive calls to FreeDynamicState
FReplicationStateMemberSerializerDescriptor & ArrayElementSerializerDescriptor = const_cast < FReplicationStateMemberSerializerDescriptor & > ( ArrayPropertyNetSerializerConfig - > StateDescriptor - > MemberSerializerDescriptors [ 0 ] ) ;
FReplicationStateMemberSerializerDescriptor OriginalElementSerializerDescriptor = ArrayElementSerializerDescriptor ;
ArrayElementSerializerDescriptor = MockMemberSerializerDescriptor ;
Quantize ( NonEmptyArrayInstance0 . ArrayOfStructWithArray , StateBuffer0 ) ;
FNetFreeDynamicStateArgs Args = { } ;
Args . Version = ArrayPropertyNetSerializer - > Version ;
Args . NetSerializerConfig = NetSerializerConfigParam ( ArrayPropertyNetSerializerConfig ) ;
Args . Source = NetSerializerValuePointer ( StateBuffer0 ) ;
ArrayPropertyNetSerializer - > FreeDynamicState ( NetSerializationContext , Args ) ;
// Restore the original element descriptor before asserting as it may return from the function
{
ArrayElementSerializerDescriptor = OriginalElementSerializerDescriptor ;
}
// As the array contains a struct with array elements we expect each array element to get a FreeDynamicState call.
UE_NET_ASSERT_EQ ( MockNetSerializerCallCounter . FreeDynamicState , uint32 ( NonEmptyArrayInstance0 . ArrayOfStructWithArray . Num ( ) ) ) ;
}
2023-04-18 12:49:50 -04:00
// FTestElementChangeMaskForArrayPropertyNetSerializer
void FTestElementChangeMaskForArrayPropertyNetSerializer : : SetUp ( )
{
FTestArrayPropertyNetSerializerBase : : SetUp ( ) ;
FReplicationStateDescriptorBuilder : : FResult Descriptors ;
FReplicationStateDescriptorBuilder : : CreateDescriptorsForClass ( Descriptors , UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest : : StaticClass ( ) ) ;
UE_NET_ASSERT_GT ( Descriptors . Num ( ) , 0 ) ;
ReplicationStateDescriptor = Descriptors [ 0 ] ;
ArrayPropertyNetSerializerConfig = const_cast < FArrayPropertyNetSerializerConfig * > ( static_cast < const FArrayPropertyNetSerializerConfig * > ( ReplicationStateDescriptor - > MemberSerializerDescriptors [ 0 ] . SerializerConfig ) ) ;
NetSerializationContext = FNetSerializationContext ( & Reader , & Writer ) ;
NetSerializationContext . SetInternalContext ( & InternalContext ) ;
}
void FTestElementChangeMaskForArrayPropertyNetSerializer : : TearDown ( )
{
ReplicationStateDescriptor . SafeRelease ( ) ;
FTestArrayPropertyNetSerializerBase : : TearDown ( ) ;
}
}
void UClassWithDynamicArrayOfPrimitiveTypeForArrayPropertyNetSerializerTest : : GetLifetimeReplicatedProps ( TArray < FLifetimeProperty > & OutLifetimeProps ) const
{
DOREPLIFETIME ( ThisClass , ArrayOfUint ) ;
2022-07-13 03:11:55 -04:00
}