Smart and raw pointer support in Json Serialization now behave similarly.

The behavior of smart pointers was not updated after the changes to raw pointers, in particular with how default JSON Objects were handled. They both now treat an empty JSON Object (a.k.a. the id for default instances) as meaning to create a default instance on the pointer even if the default is a nullptr. To have a nullptr a JSON Null has to be explicitly written.
This commit is contained in:
AMZN-koppersr
2021-05-04 11:10:46 -07:00
parent ea5dc5eb24
commit 11b79f567a
5 changed files with 242 additions and 61 deletions
@@ -110,7 +110,7 @@ namespace JsonSerializationTests
EXPECT_EQ(42, value);
}
TEST_F(BaseJsonSerializerTests, ContinueLoading_PointerInstance_ValueLoadedCorrectly)
TEST_F(BaseJsonSerializerTests, ContinueLoading_ToPointerInstance_ValueLoadedCorrectly)
{
using namespace AZ::JsonSerializationResult;
@@ -126,6 +126,51 @@ namespace JsonSerializationTests
EXPECT_EQ(42, value);
}
TEST_F(BaseJsonSerializerTests, ContinueLoading_ToNullPointer_ValueLoadedCorrectly)
{
using namespace AZ::JsonSerializationResult;
rapidjson::Value json;
json.Set(42);
int* ptrValue = nullptr;
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, ptrValue);
EXPECT_EQ(42, *ptrValue);
azfree(ptrValue, AZ::SystemAllocator, sizeof(int), AZStd::alignment_of<int>::value);
}
TEST_F(BaseJsonSerializerTests, ContinueLoading_DefaultToNullPointer_ValueLoadedCorrectly)
{
using namespace AZ::JsonSerializationResult;
rapidjson::Value json(rapidjson::kObjectType);
int* ptrValue = nullptr;
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, ptrValue);
azfree(ptrValue, AZ::SystemAllocator, sizeof(int), AZStd::alignment_of<int>::value);
}
TEST_F(BaseJsonSerializerTests, ContinueLoading_NullDeletesObject_ValueLoadedCorrectly)
{
using namespace AZ::JsonSerializationResult;
rapidjson::Value json(rapidjson::kNullType);
int* ptrValue = reinterpret_cast<int*>(azmalloc(sizeof(int), AZStd::alignment_of<int>::value, AZ::SystemAllocator));
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_EQ(nullptr, ptrValue);
}
//
// ContinueStoring
//
@@ -156,6 +201,64 @@ namespace JsonSerializationTests
Expect_DocStrEq("42");
}
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToFullDefaultedInstance_ValueStoredCorrectly)
{
using namespace AZ::JsonSerializationResult;
int value = 42;
int* ptrValue = &value;
int value2 = 42;
int* defaultPtrValue = &value2;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("{}");
}
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptr_ValueStoredCorrectly)
{
using namespace AZ::JsonSerializationResult;
int* ptrValue = nullptr;
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
}
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithValueDefault_ValueStoredCorrectly)
{
using namespace AZ::JsonSerializationResult;
int* ptrValue = nullptr;
int value2 = 42;
int* defaultPtrValue = &value2;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
}
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithNullPtrDefault_NullPtrIsStored)
{
using namespace AZ::JsonSerializationResult;
int* ptrValue = nullptr;
int* defaultPtrValue = nullptr;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
}
TEST_F(BaseJsonSerializerTests, ContinueStoring_ReplaceDefault_ValueStoredCorrectly)
{
using namespace AZ::JsonSerializationResult;
@@ -32,11 +32,6 @@ namespace JsonSerializationTests
return AZStd::make_shared<AZ::JsonSmartPointerSerializer>();
}
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
return AZStd::make_shared<SmartPointer>();
}
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<SmartPointer>();
@@ -51,6 +46,13 @@ namespace JsonSerializationTests
using SmartPointer = T<SimpleClass>;
using Base = SmartPointerBaseTestDescription<SmartPointer>;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew SimpleClass());
return result;
}
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
@@ -106,21 +108,6 @@ namespace JsonSerializationTests
}
};
template<template<typename...> class T>
class SmartPointerSimpleClassWithInstanceTestDescription :
public SmartPointerSimpleClassTestDescription<T>
{
public:
using SmartPointer = typename SmartPointerSimpleClassTestDescription<T>::SmartPointer;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew SimpleClass());
return result;
}
};
template<template<typename...> class T>
class SmartPointerSimpleDerivedClassTestDescription :
public SmartPointerBaseTestDescription<T<BaseClass>>
@@ -129,6 +116,13 @@ namespace JsonSerializationTests
using SmartPointer = T<BaseClass>;
using Base = SmartPointerBaseTestDescription<SmartPointer>;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew BaseClass());
return result;
}
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
{
auto* instance = aznew SimpleInheritence();
@@ -272,6 +266,13 @@ namespace JsonSerializationTests
using SmartPointer = T<BaseClass2>;
using Base = SmartPointerBaseTestDescription<SmartPointer>;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew BaseClass2());
return result;
}
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
{
auto* instance = aznew MultipleInheritence();
@@ -424,9 +425,6 @@ namespace JsonSerializationTests
SmartPointerSimpleClassTestDescription<AZStd::unique_ptr>,
SmartPointerSimpleClassTestDescription<AZStd::shared_ptr>,
SmartPointerSimpleClassTestDescription<AZStd::intrusive_ptr>,
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::unique_ptr>,
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::shared_ptr>,
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::intrusive_ptr>,
// Simple derived class, include single inheritance.
SmartPointerSimpleDerivedClassTestDescription<AZStd::unique_ptr>,
SmartPointerSimpleDerivedClassTestDescription<AZStd::shared_ptr>,
@@ -551,6 +549,37 @@ namespace JsonSerializationTests
EXPECT_EQ(nullptr, *instance);
}
TEST_F(JsonSmartPointerSerializerTests, Load_DefaultInstanceToNullptr_ReturnsSuccess)
{
namespace JSR = AZ::JsonSerializationResult;
SmartPointer instance;
AZStd::shared_ptr<SmartPointer> compare = m_description.CreateDefaultInstance();
m_jsonDocument->SetObject();
JSR::ResultCode result =
m_serializer.Load(&instance, azrtti_typeid<SmartPointer>(), *m_jsonDocument, *m_jsonDeserializationContext);
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
EXPECT_NE(nullptr, instance);
EXPECT_TRUE(m_description.AreEqual(instance, *compare));
}
TEST_F(JsonSmartPointerSerializerTests, Load_DefaultObjectDoesNotUpdateInstance_ReturnsSuccess)
{
namespace JSR = AZ::JsonSerializationResult;
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateFullySetInstance();
AZStd::shared_ptr<SmartPointer> compare = m_description.CreateFullySetInstance();
m_jsonDocument->SetObject();
JSR::ResultCode result =
m_serializer.Load(instance.get(), azrtti_typeid<SmartPointer>(), *m_jsonDocument, *m_jsonDeserializationContext);
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
EXPECT_TRUE(m_description.AreEqual(*instance, *compare));
}
TEST_F(JsonSmartPointerSerializerTests, Load_InstanceBeingReplacedWithDifferentType_ReturnsSuccess)
{
namespace JSR = AZ::JsonSerializationResult;
@@ -720,13 +749,66 @@ namespace JsonSerializationTests
namespace JSR = AZ::JsonSerializationResult;
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateFullySetInstance();
SmartPointer nullPtr;
JSR::ResultCode result = m_serializer.Store(*m_jsonDocument, instance.get(), &nullPtr,
SmartPointer defaultInstance;
JSR::ResultCode result = m_serializer.Store(
*m_jsonDocument, instance.get(), &defaultInstance,
azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome());
}
TEST_F(JsonSmartPointerSerializerTests, Store_ValuePointerIsNullPtr_ReturnsSuccessAndStoresNull)
{
namespace JSR = AZ::JsonSerializationResult;
SmartPointer instance;
AZStd::shared_ptr<SmartPointer> defaultInstance = m_description.CreateFullySetInstance();
JSR::ResultCode result = m_serializer.Store(
*m_jsonDocument, &instance, defaultInstance.get(), azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome());
EXPECT_TRUE(m_jsonDocument->IsNull());
}
TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreNullPtr_ReturnsSuccessAndStoresNull)
{
namespace JSR = AZ::JsonSerializationResult;
SmartPointer instance;
SmartPointer defaultInstance;
JSR::ResultCode result =
m_serializer.Store(*m_jsonDocument, &instance, &defaultInstance, azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
EXPECT_TRUE(m_jsonDocument->IsNull());
}
TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreBothDefault_ReturnsSuccess)
{
namespace JSR = AZ::JsonSerializationResult;
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateDefaultInstance();
AZStd::shared_ptr<SmartPointer> defaultInstance = m_description.CreateDefaultInstance();
JSR::ResultCode result =
m_serializer.Store(*m_jsonDocument, instance.get(), defaultInstance.get(), azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
Expect_ExplicitDefault(*m_jsonDocument);
}
TEST_F(JsonSmartPointerSerializerTests, Store_ValueHasDefaultValuesAndDefaultHasNullPointer_ReturnsSuccess)
{
namespace JSR = AZ::JsonSerializationResult;
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateDefaultInstance();
SmartPointer defaultInstance;
JSR::ResultCode result = m_serializer.Store(
*m_jsonDocument, instance.get(), &defaultInstance, azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
Expect_ExplicitDefault(*m_jsonDocument);
}
TEST_F(JsonSmartPointerSerializerTests, Store_DefaultPointerIsOtherClass_CompletesButDoesNotReturnDefaults)
{
namespace JSR = AZ::JsonSerializationResult;
@@ -749,7 +831,7 @@ namespace JsonSerializationTests
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
}
TEST_F(JsonSmartPointerSerializerTests, Store_SaveAnClassThatIsNotReflected_ReturnsUnknown)
TEST_F(JsonSmartPointerSerializerTests, Store_ClassThatIsNotReflected_ReturnsUnknown)
{
namespace JSR = AZ::JsonSerializationResult;