Fix PODs not initializing in Json Serialization

When pointers are used new instances are created for pod types, which will have random values at that point. The Json Serialization did not set a value for these if they were explicitly set to defaults. This change adds initialization for explicit defaults in the bool, integer and double serializer plus unit tests to verify.
This commit is contained in:
AMZN-koppersr
2021-06-11 13:41:54 -07:00
parent 6f50207b06
commit a98355e000
9 changed files with 229 additions and 55 deletions
@@ -63,6 +63,18 @@ namespace JsonSerializationTests
: public BaseJsonSerializerFixture
{
public:
struct BoolPointerWrapper
{
AZ_TYPE_INFO(BoolPointerWrapper, "{2E67C069-BB0F-4F00-A704-E964F5FE5ED2}");
bool* m_value{ nullptr };
~BoolPointerWrapper()
{
azfree(m_value);
}
};
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
@@ -75,6 +87,12 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->Class<BoolPointerWrapper>()
->Field("Value", &BoolPointerWrapper::m_value);
}
void Load(rapidjson::Value& testVal, bool expectedBool, AZ::JsonSerializationResult::Outcomes expectedOutcome)
{
using namespace AZ::JsonSerializationResult;
@@ -242,4 +260,24 @@ namespace JsonSerializationTests
Load(m_jsonValue.SetDouble(-1.0f), true, AZ::JsonSerializationResult::Outcomes::Success);
Load(m_jsonValue.SetDouble(2.0), true, AZ::JsonSerializationResult::Outcomes::Success);
}
TEST_F(JsonBoolSerializerTests, Load_LoadDefaultToPointer_ValueIsIsInitialized)
{
using namespace AZ::JsonSerializationResult;
BoolPointerWrapper instance;
this->m_jsonDocument->Parse(R"({ "Value": {}})");
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Load(instance, *this->m_jsonDocument, settings);
EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, instance.m_value);
EXPECT_FALSE(*instance.m_value);
}
} // namespace JsonSerializationTests
@@ -71,6 +71,20 @@ namespace JsonSerializationTests
: public BaseJsonSerializerFixture
{
public:
struct DoublePointerWrapper
{
AZ_TYPE_INFO(DoublePointerWrapper, "{C2FD9E0B-2641-4D24-A3D9-A29FD1A21A81}");
double* m_double{ nullptr };
float* m_float{ nullptr };
~DoublePointerWrapper()
{
azfree(m_float);
azfree(m_double);
}
};
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
@@ -85,6 +99,13 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->Class<DoublePointerWrapper>()
->Field("Double", &DoublePointerWrapper::m_double)
->Field("Float", &DoublePointerWrapper::m_float);
}
void TestSerializers(rapidjson::Value& testVal, double expectedValue, AZ::JsonSerializationResult::Outcomes expectedOutcome)
{
using namespace AZ::JsonSerializationResult;
@@ -275,4 +296,32 @@ namespace JsonSerializationTests
EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome());
EXPECT_EQ(42.0f, value);
}
// Pointers
TEST_F(JsonDoubleSerializerTests, Load_LoadDefaultToPointer_ValuesArIsInitialized)
{
using namespace AZ::JsonSerializationResult;
DoublePointerWrapper instance;
this->m_jsonDocument->Parse(R"(
{
"Double": {},
"Float": {}
})");
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Load(instance, *this->m_jsonDocument, settings);
EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, instance.m_double);
ASSERT_NE(nullptr, instance.m_float);
EXPECT_DOUBLE_EQ(0.0, *instance.m_double);
EXPECT_FLOAT_EQ(0.0f, *instance.m_float);
}
} // namespace JsonSerializationTests
@@ -147,6 +147,18 @@ namespace JsonSerializationTests
: public BaseJsonSerializerFixture
{
public:
struct IntegerPointerWrapper
{
AZ_TYPE_INFO(IntegerPointerWrapper, "{F6B3BEF1-59A4-4E45-BF02-DDA868C38A28}");
typename SerializerInfo<SerializerType>::DataType* m_value{ nullptr };
~IntegerPointerWrapper()
{
azfree(m_value);
}
};
AZStd::unique_ptr<SerializerType> m_serializer;
void SetUp() override
@@ -161,6 +173,12 @@ namespace JsonSerializationTests
BaseJsonSerializerFixture::TearDown();
}
void RegisterAdditional(AZStd::unique_ptr<AZ::SerializeContext>& serializeContext) override
{
serializeContext->Class<IntegerPointerWrapper>()
->Field("Value", &IntegerPointerWrapper::m_value);
}
template<typename T, typename AZStd::enable_if_t<AZStd::is_floating_point<T>::value, int> = 0>
void SetValue(rapidjson::Value& out, T in)
{
@@ -487,6 +505,26 @@ namespace JsonSerializationTests
EXPECT_EQ(typename SerializerInfo<TypeParam>::DataType(), convertedValue);
}
TYPED_TEST(TypedJsonIntSerializerTests, Load_LoadDefaultToPointer_ValueIsIsInitialized)
{
using namespace AZ::JsonSerializationResult;
IntegerPointerWrapper instance;
this->m_jsonDocument->Parse(R"({ "Value": {}})");
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Load(instance, *this->m_jsonDocument, settings);
EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, instance.m_value);
EXPECT_EQ(0, *instance.m_value);
}
TYPED_TEST(TypedJsonIntSerializerTests, Load_MaxInt8Value_ConvertIfFitsOrUnsupported) { this->template TestMaxValue<int8_t>(); }
TYPED_TEST(TypedJsonIntSerializerTests, Load_MaxShortValue_ConvertIfFitsOrUnsupported) { this->template TestMaxValue<short>(); }
TYPED_TEST(TypedJsonIntSerializerTests, Load_MaxIntValue_ConvertIfFitsOrUnsupported) { this->template TestMaxValue<int>(); }