775 lines
24 KiB
C++
775 lines
24 KiB
C++
// Copyright (c) Samuel Kahn (samuel@kahncode.com). All Rights Reserved.
|
|
|
|
#include "BlobSerializationTests.h"
|
|
|
|
#include "Blob.h"
|
|
#include "BlobSerializationArchive.h"
|
|
#include "BlobSerializationEditorPCH.h"
|
|
#include "Misc/AutomationTest.h"
|
|
#include "Net/UnrealNetwork.h"
|
|
#include "NetSerialization.h"
|
|
#include "Serialization.h"
|
|
#include "Serialization/StructuredArchive.h"
|
|
#include "TextSerialization.h"
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
|
|
void UBlobSerializationTestClass::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
|
{
|
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
|
DOREPLIFETIME(UBlobSerializationTestClass, IntVariable);
|
|
DOREPLIFETIME(UBlobSerializationTestClass, FloatVariable);
|
|
}
|
|
|
|
namespace BlobSerialization
|
|
{
|
|
struct NotSerializable
|
|
{
|
|
};
|
|
|
|
struct TriviallySerializable
|
|
{
|
|
TriviallySerializable()
|
|
: IntVariable(987654)
|
|
, FloatVariable(123.456)
|
|
, StringVariable("Hello World")
|
|
{
|
|
}
|
|
|
|
int IntVariable;
|
|
float FloatVariable;
|
|
FString StringVariable;
|
|
|
|
bool operator==(const TriviallySerializable& Other) const
|
|
{
|
|
return IntVariable == Other.IntVariable && FloatVariable == Other.FloatVariable && StringVariable == Other.StringVariable;
|
|
}
|
|
};
|
|
|
|
inline FArchive& operator<<(FArchive& Ar, TriviallySerializable& Value)
|
|
{
|
|
Ar << Value.IntVariable;
|
|
Ar << Value.FloatVariable;
|
|
Ar << Value.StringVariable;
|
|
return Ar;
|
|
}
|
|
|
|
struct CustomSerializable
|
|
{
|
|
CustomSerializable()
|
|
: IntVariable(987654)
|
|
, FloatVariable(123.456)
|
|
, StringVariable("Hello World")
|
|
{
|
|
}
|
|
|
|
int IntVariable;
|
|
float FloatVariable;
|
|
FString StringVariable;
|
|
|
|
void Serialize(FArchive& Ar)
|
|
{
|
|
Ar << IntVariable;
|
|
Ar << FloatVariable;
|
|
Ar << StringVariable;
|
|
}
|
|
|
|
void Serialize(FStructuredArchive::FRecord Record)
|
|
{
|
|
Record << SA_VALUE(TEXT("IntVariable"), IntVariable);
|
|
Record << SA_VALUE(TEXT("FloatVariable"), FloatVariable);
|
|
Record << SA_VALUE(TEXT("StringVariable"), StringVariable);
|
|
}
|
|
|
|
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
|
|
{
|
|
Ar << IntVariable;
|
|
Ar << FloatVariable;
|
|
Ar << StringVariable;
|
|
bOutSuccess = true;
|
|
return true;
|
|
}
|
|
|
|
bool operator==(const CustomSerializable& Other) const
|
|
{
|
|
return IntVariable == Other.IntVariable && FloatVariable == Other.FloatVariable && StringVariable == Other.StringVariable;
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Test Type-Traits
|
|
|
|
static_assert(IsTriviallySerializable<TriviallySerializable>::Value, "TriviallySerializable is trivially serializable");
|
|
static_assert(IsTriviallySerializable<FBlob>::Value, "FBlob is trivially serializable");
|
|
static_assert(!IsTriviallySerializable<FBlobSerializationTestStruct>::Value, "FBlobSerializationTestStruct is not trivially serializable");
|
|
static_assert(!IsTriviallySerializable<NotSerializable>::Value, "NotSerializable is not trivially serializable");
|
|
static_assert(!IsTriviallySerializable<UObject*>::Value, "UObject* is not trivially serializable");
|
|
static_assert(!IsTriviallySerializable<UBlobSerializationTestClass*>::Value, "UBlobSerializationTestClass* is not trivially serializable");
|
|
static_assert(!IsTriviallySerializable<FBlobSerializationTestStruct*>::Value, "FBlobSerializationTestStruct* is not trivially serializable");
|
|
|
|
static_assert(!IsUObject<TriviallySerializable>::value, "TriviallySerializable is not UObject");
|
|
static_assert(!IsUObject<FBlob>::value, "FBlob is not UObject");
|
|
static_assert(!IsUObject<FBlobSerializationTestStruct>::value, "FBlobSerializationTestStruct is not UObject");
|
|
static_assert(IsUObject<UObject>::value, "UObject is UObject");
|
|
static_assert(!IsUObject<CustomSerializable>::value, "CustomSerializable is UObject");
|
|
|
|
static_assert(!IsUStruct<TriviallySerializable>::Value, "TriviallySerializable is not USTRUCT");
|
|
static_assert(IsUStruct<FBlob>::Value, "FBlob is USTRUCT");
|
|
static_assert(IsUStruct<FBlobSerializationTestStruct>::Value, "FBlobSerializationTestStruct is USTRUCT");
|
|
static_assert(!IsUStruct<UObject>::Value, "UObject is not USTRUCT");
|
|
static_assert(!IsUStruct<CustomSerializable>::Value, "CustomSerializable is not USTRUCT");
|
|
|
|
static_assert(!HasSerializeMethod<TriviallySerializable>::Value, "TriviallySerializable doesn't have Serialize()");
|
|
static_assert(!HasSerializeMethod<FBlob>::Value, "FBlob doesn't have Serialize()");
|
|
static_assert(HasSerializeMethod<UObject>::Value, "UObject has Serialize()");
|
|
static_assert(HasSerializeMethod<CustomSerializable>::Value, "CustomSerializable has Serialize()");
|
|
|
|
static_assert(!HasNetSerializeMethod<TriviallySerializable>::Value, "TriviallySerializable doesn't have NetSerialize()");
|
|
static_assert(!HasNetSerializeMethod<FBlob>::Value, "FBlob doesn't have NetSerialize()");
|
|
static_assert(!HasNetSerializeMethod<UObject>::Value, "UObject has NetSerialize()");
|
|
static_assert(HasNetSerializeMethod<CustomSerializable>::Value, "CustomSerializable doesn't have NetSerialize()");
|
|
static_assert(HasNetSerializeMethod<FBlobSerializationTestStruct2>::Value, "CustomSerializable doesn't have NetSerialize()");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(SerializationTestFArchive, "BlobSerialization.SerializationTest.FArchive",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::CommandletContext | EAutomationTestFlags::EngineFilter)
|
|
|
|
bool SerializationTestFArchive::RunTest(const FString& Parameters)
|
|
{
|
|
// TriviallySerializable
|
|
{
|
|
TriviallySerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
TriviallySerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
Serialize(Input, Writer);
|
|
Serialize(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("TriviallySerializable/Serialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("TriviallySerializable/Serialize BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// TriviallySerializable / bin
|
|
{
|
|
TriviallySerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
TriviallySerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
SerializeBin(Input, Writer);
|
|
SerializeBin(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("TriviallySerializable/SerializeBin BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("TriviallySerializable/SerializeBin BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// TriviallySerializable / bin
|
|
{
|
|
TriviallySerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
TriviallySerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
Writer.ArIsNetArchive = true;
|
|
FBlobReader Reader(Buffer);
|
|
Reader.ArIsNetArchive = true;
|
|
|
|
NetSerialize(Input, Writer, nullptr);
|
|
NetSerialize(Output, Reader, nullptr);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("TriviallySerializable/NetSerialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("TriviallySerializable/NetSerialize BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// CustomSerializable
|
|
{
|
|
CustomSerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
CustomSerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
Serialize(Input, Writer);
|
|
Serialize(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("CustomSerializable/Serialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("CustomSerializable/Serialize BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// CustomSerializable / bin
|
|
{
|
|
CustomSerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
CustomSerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
SerializeBin(Input, Writer);
|
|
SerializeBin(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("CustomSerializable/SerializeBin BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("CustomSerializable/SerializeBin BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// CustomSerializable / net
|
|
{
|
|
CustomSerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
CustomSerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
Writer.ArIsNetArchive = true;
|
|
FBlobReader Reader(Buffer);
|
|
Reader.ArIsNetArchive = true;
|
|
|
|
NetSerialize(Input, Writer, nullptr);
|
|
NetSerialize(Output, Reader, nullptr);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("CustomSerializable/NetSerialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("CustomSerializable/NetSerialize BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// UStruct
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
Serialize(Input, Writer);
|
|
Serialize(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UStruct/Serialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UStruct/Serialize BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// UStruct / bin
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
SerializeBin(Input, Writer);
|
|
SerializeBin(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UStruct/SerializeBin BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UStruct/SerializeBin BlobReader/BlobWriter test", Input == Output);
|
|
}
|
|
|
|
// UStruct / net
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
Writer.ArIsNetArchive = true;
|
|
FBlobReader Reader(Buffer);
|
|
Reader.ArIsNetArchive = true;
|
|
|
|
NetSerialize(Input, Writer, nullptr);
|
|
NetSerialize(Output, Reader, nullptr);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UStruct/NetSerialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UStruct/NetSerialize BlobReader/BlobWriter test",
|
|
Input.IntVariable == Output.IntVariable && Input.FloatVariable == Output.FloatVariable
|
|
&& Input.StringVariable != Output.StringVariable);
|
|
}
|
|
|
|
// UStruct with custom NetSerialize
|
|
{
|
|
FBlobSerializationTestStruct2 Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.BoolVariable = true;
|
|
|
|
FBlobSerializationTestStruct2 Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
Writer.ArIsNetArchive = true;
|
|
FBlobReader Reader(Buffer);
|
|
Reader.ArIsNetArchive = true;
|
|
|
|
NetSerialize(Input, Writer, nullptr);
|
|
NetSerialize(Output, Reader, nullptr);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UStruct/CustomNetSerialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UStruct/CustomNetSerialize BlobReader/BlobWriter test",
|
|
Input.IntVariable == Output.IntVariable && Input.FloatVariable == Output.FloatVariable
|
|
&& Input.BoolVariable != Output.BoolVariable);
|
|
}
|
|
|
|
// UObject
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
Serialize(Input, Writer);
|
|
Serialize(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/Serialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/Serialize BlobReader/BlobWriter test", *Input == *Output);
|
|
}
|
|
|
|
// UObject / bin
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
FBlobReader Reader(Buffer);
|
|
|
|
SerializeBin(Input, Writer);
|
|
SerializeBin(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/SerializeBin BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/SerializeBin BlobReader/BlobWriter test", *Input == *Output);
|
|
}
|
|
|
|
// UObject / net
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
Writer.ArIsNetArchive = true;
|
|
FBlobReader Reader(Buffer);
|
|
Reader.ArIsNetArchive = true;
|
|
|
|
NetSerialize(Input, Writer, nullptr);
|
|
NetSerialize(Output, Reader, nullptr);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/NetSerialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/NetSerialize BlobReader/BlobWriter test",
|
|
Input->IntVariable == Output->IntVariable && Input->FloatVariable == Output->FloatVariable
|
|
&& Input->StringVariable != Output->StringVariable);
|
|
}
|
|
|
|
// UObject / poly
|
|
{
|
|
UBlobSerializationTestClass2* Input = NewObject<UBlobSerializationTestClass2>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
Input->BoolVariable = true;
|
|
|
|
TArray<uint8> Buffer;
|
|
FBlobWriter Writer(Buffer);
|
|
SerializePoly(Input, Writer);
|
|
|
|
{
|
|
UBlobSerializationTestClass2* Output = NewObject<UBlobSerializationTestClass2>();
|
|
FBlobReader Reader(Buffer);
|
|
SerializePoly(Output, Reader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/Serialize BlobReader/BlobWriter buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/SerializePoly BlobReader/BlobWriter test", *Input == *Output);
|
|
}
|
|
|
|
{
|
|
UBlobSerializationTestClass* OutputParentClass = NewObject<UBlobSerializationTestClass>();
|
|
UBlobSerializationTestClass* OutputParentClassCache = OutputParentClass;
|
|
FBlobReader Reader(Buffer);
|
|
SerializePoly(OutputParentClass, Reader);
|
|
TestTrue("UObject/SerializePoly parent class test", OutputParentClassCache != OutputParentClass);
|
|
TestTrue("UObject/Serialize parent class test", *Input == *Cast<UBlobSerializationTestClass2>(OutputParentClass));
|
|
}
|
|
|
|
{
|
|
UBlobSerializationTestClass2* Output = nullptr;
|
|
FBlobReader Reader(Buffer);
|
|
SerializePoly(Output, Reader);
|
|
TestTrue("UObject/Serialize null input test", *Input == *Output);
|
|
}
|
|
|
|
// Next test will error
|
|
AddExpectedError(TEXT("SerializePoly"), EAutomationExpectedErrorFlags::Contains, 1);
|
|
|
|
{
|
|
UClass* OutputWrongClass = NewObject<UClass>();
|
|
FBlobReader Reader(Buffer);
|
|
SerializePoly(OutputWrongClass, Reader);
|
|
TestTrue("UObject/Serialize wrong class test", !OutputWrongClass);
|
|
}
|
|
|
|
{
|
|
TArray<UBlobSerializationTestClass*> InputArray = {Input, Input, Input};
|
|
TArray<UBlobSerializationTestClass*> OutputArray;
|
|
|
|
TArray<uint8> Buffer2;
|
|
FBlobWriter Writer2(Buffer2);
|
|
FBlobReader Reader2(Buffer2);
|
|
SerializePoly(InputArray, Writer2);
|
|
SerializePoly(OutputArray, Reader2);
|
|
|
|
TestTrue("UObject/Serialize object array", OutputArray.Num() == 3 && !OutputArray.Contains(nullptr));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(SerializationTestFStructuredArchive, "BlobSerialization.SerializationTest.FStructuredArchive",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::CommandletContext | EAutomationTestFlags::EngineFilter)
|
|
|
|
bool SerializationTestFStructuredArchive::RunTest(const FString& Parameters)
|
|
{
|
|
// TriviallySerializable
|
|
{
|
|
TriviallySerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
TriviallySerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
Serialize(Input, StructuredWriter);
|
|
Serialize(Output, StructuredReader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("TriviallySerializable/Serialize Structured buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("TriviallySerializable/Serialize Structured test", Input == Output);
|
|
}
|
|
|
|
// CustomSerializable
|
|
{
|
|
CustomSerializable Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
CustomSerializable Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
Serialize(Input, StructuredWriter);
|
|
Serialize(Output, StructuredReader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("CustomSerializable/Serialize Structured buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("CustomSerializable/Serialize Structured test", Input == Output);
|
|
}
|
|
|
|
// UStruct
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
Serialize(Input, StructuredWriter);
|
|
Serialize(Output, StructuredReader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UStruct/Serialize Structured buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UStruct/Serialize Structured test", Input == Output);
|
|
}
|
|
|
|
// UObject
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
Serialize(Input, StructuredWriter);
|
|
Serialize(Output, StructuredReader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/Serialize Structured buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/Serialize Structured test", *Input == *Output);
|
|
}
|
|
|
|
// UObject / poly
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
{
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
SerializePoly(Input, StructuredWriter);
|
|
SerializePoly(Output, StructuredReader);
|
|
|
|
UE_LOG(LogBlobSerialization, Log, TEXT("UObject/Serialize Structured buffer length: %d"), Buffer.Num());
|
|
|
|
TestTrue("UObject/Serialize Structured test", *Input == *Output);
|
|
}
|
|
|
|
{
|
|
TArray<UBlobSerializationTestClass*> InputArray = {Input, Input, Input};
|
|
TArray<UBlobSerializationTestClass*> OutputArray;
|
|
|
|
TArray<uint8> Buffer;
|
|
|
|
FBlobWriter Writer(Buffer);
|
|
FBinaryArchiveFormatter OutputFormatter(Writer);
|
|
FStructuredArchive StructuredWriter(OutputFormatter);
|
|
|
|
FBlobReader Reader(Buffer);
|
|
FBinaryArchiveFormatter InputFormatter(Reader);
|
|
FStructuredArchive StructuredReader(InputFormatter);
|
|
|
|
SerializePoly(InputArray, StructuredWriter);
|
|
SerializePoly(OutputArray, StructuredReader);
|
|
|
|
TestTrue("UObject/Serialize object array", OutputArray.Num() == 3 && !OutputArray.Contains(nullptr));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(BlobTest, "BlobSerialization.BlobTest",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::CommandletContext | EAutomationTestFlags::EngineFilter)
|
|
|
|
bool RunBlobTest(BlobTest& InTest, EBlobArchiveType ArchiveType)
|
|
{
|
|
// UStruct
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
FBlob Blob;
|
|
|
|
Blob.SerializeValue(Input, ArchiveType);
|
|
Blob.DeserializeValue(Output, ArchiveType);
|
|
|
|
if (ArchiveType == EBlobArchiveType::SaveGame)
|
|
{
|
|
InTest.TestTrue("UStruct/FBlob test SaveGame", Input.IntVariable == Output.IntVariable);
|
|
InTest.TestFalse("UStruct/FBlob test SaveGame", Input == Output);
|
|
}
|
|
else
|
|
InTest.TestTrue("UStruct/FBlob test", Input == Output);
|
|
}
|
|
|
|
// UObject
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
FBlob Blob;
|
|
|
|
Blob.SerializeValue(Input, ArchiveType);
|
|
Blob.DeserializeValue(Output, ArchiveType);
|
|
|
|
if (ArchiveType == EBlobArchiveType::SaveGame)
|
|
{
|
|
InTest.TestTrue("UObject/FBlob test SaveGame", Input->IntVariable == Output->IntVariable);
|
|
InTest.TestFalse("UObject/FBlob test SaveGame", *Input == *Output);
|
|
}
|
|
else
|
|
InTest.TestTrue("UObject/FBlob test", *Input == *Output);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BlobTest::RunTest(const FString& Parameters)
|
|
{
|
|
bool Success = true;
|
|
Success &= RunBlobTest(*this, EBlobArchiveType::Default);
|
|
Success &= RunBlobTest(*this, EBlobArchiveType::Persistent);
|
|
Success &= RunBlobTest(*this, EBlobArchiveType::SaveGame);
|
|
Success &= RunBlobTest(*this, EBlobArchiveType::Binary);
|
|
// Net unit tests will assert without a valid NetContext object, we will test them in blueprint
|
|
// Success &= RunBlobTest(*this, EBlobArchiveType::Net);
|
|
return Success;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(JsonTest, "BlobSerialization.JsonTest",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::CommandletContext | EAutomationTestFlags::EngineFilter)
|
|
|
|
bool JsonTest::RunTest(const FString& Parameters)
|
|
{
|
|
# if WITH_TEXT_ARCHIVE_SUPPORT
|
|
// UStruct
|
|
{
|
|
FBlobSerializationTestStruct Input;
|
|
Input.IntVariable = -333;
|
|
Input.FloatVariable = 33.33;
|
|
Input.StringVariable = "Hello Underworld";
|
|
|
|
FBlobSerializationTestStruct Output;
|
|
|
|
FString JsonString;
|
|
SerializeToJsonString(Input, JsonString);
|
|
SerializeFromJsonString(JsonString, Output);
|
|
|
|
TestTrue("UStruct/FBlob test", Input == Output);
|
|
}
|
|
|
|
// UObject
|
|
{
|
|
UBlobSerializationTestClass* Input = NewObject<UBlobSerializationTestClass>();
|
|
Input->IntVariable = -333;
|
|
Input->FloatVariable = 33.33;
|
|
Input->StringVariable = "Hello Underworld";
|
|
|
|
UBlobSerializationTestClass* Output = NewObject<UBlobSerializationTestClass>();
|
|
|
|
FString JsonString;
|
|
SerializeToJsonString(Input, JsonString);
|
|
SerializeFromJsonString(JsonString, Output);
|
|
|
|
TestTrue("UObject/FBlob test", *Input == *Output);
|
|
}
|
|
# endif // WITH_TEXT_ARCHIVE_SUPPORT
|
|
return true;
|
|
}
|
|
|
|
} // namespace BlobSerialization
|
|
|
|
#endif
|