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
@@ -30,8 +30,8 @@ namespace AZ
if (text && textLength > 0)
{
static constexpr const char trueString[] = "true";
static constexpr const char falseString[] = "false";
static constexpr const char* trueString = "true";
static constexpr const char* falseString = "false";
// remove null terminator for string length counts
// rapidjson stringlength doesn't include it in length calculations, but sizeof() will
static constexpr size_t trueStringLength = sizeof(trueString) - 1;
@@ -82,12 +82,18 @@ namespace AZ
bool* valAsBool = reinterpret_cast<bool*>(outputValue);
if (IsExplicitDefault(inputValue))
{
*valAsBool = false;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Boolean value set to default of 'false'.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
// fallthrough
[[fallthrough]];
case rapidjson::kObjectType:
// fallthrough
[[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Booleans can't be read from arrays, objects or null.");
@@ -96,7 +102,7 @@ namespace AZ
return SerializerInternal::TextToValue(valAsBool, inputValue.GetString(), inputValue.GetStringLength(), context);
case rapidjson::kFalseType:
// fallthrough
[[fallthrough]];
case rapidjson::kTrueType:
*valAsBool = inputValue.GetBool();
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read boolean.");
@@ -145,4 +151,9 @@ namespace AZ
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "Default boolean used.");
}
auto JsonBoolSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
} // namespace AZ
@@ -27,5 +27,6 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
};
} // namespace AZ
@@ -62,19 +62,26 @@ namespace AZ
}
template <typename T>
static JsonSerializationResult::Result Load(T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
static JsonSerializationResult::Result Load(
T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
static_assert(AZStd::is_floating_point<T>::value, "Expected T to be a floating point type");
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
if (isExplicitDefault)
{
*outputValue = 0.0f;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Double value set to default of 0.0.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
// fallthrough
[[fallthrough]];
case rapidjson::kObjectType:
// fallthrough
[[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Floating point values can't be read from arrays, objects or null.");
@@ -83,7 +90,7 @@ namespace AZ
return TextToValue(outputValue, inputValue.GetString(), context);
case rapidjson::kFalseType:
// fallthrough
[[fallthrough]];
case rapidjson::kTrueType:
*outputValue = inputValue.GetBool() ? 1.0f : 0.0f;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success,
@@ -144,7 +151,8 @@ namespace AZ
"Unable to deserialize double to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerFloatingPointInternal::Load(reinterpret_cast<double*>(outputValue), inputValue, context);
return SerializerFloatingPointInternal::Load(
reinterpret_cast<double*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonDoubleSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -156,6 +164,11 @@ namespace AZ
return SerializerFloatingPointInternal::Store<double>(outputValue, inputValue, defaultValue, context);
}
auto JsonDoubleSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
JsonSerializationResult::Result JsonFloatSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
@@ -163,7 +176,8 @@ namespace AZ
"Unable to deserialize float to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerFloatingPointInternal::Load(reinterpret_cast<float*>(outputValue), inputValue, context);
return SerializerFloatingPointInternal::Load(
reinterpret_cast<float*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonFloatSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -174,4 +188,9 @@ namespace AZ
AZ_UNUSED(valueTypeId);
return SerializerFloatingPointInternal::Store<float>(outputValue, inputValue, defaultValue, context);
}
auto JsonFloatSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
} // namespace AZ
@@ -28,6 +28,7 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
};
class JsonFloatSerializer
@@ -40,5 +41,6 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
};
} // namespace AZ
@@ -25,6 +25,8 @@
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(BaseJsonIntegerSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonCharSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonShortSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonIntSerializer, SystemAllocator, 0);
@@ -56,19 +58,25 @@ namespace AZ
template <typename T>
static JsonSerializationResult::Result LoadInt(T* outputValue, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
JsonDeserializerContext& context, bool isDefaultValue)
{
namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
static_assert(AZStd::is_integral<T>(), "Expected T to be a signed or unsigned type");
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
if (isDefaultValue)
{
*outputValue = 0;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Integer value set to default of zero.");
}
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
// fallthrough
[[fallthrough]];
case rapidjson::kObjectType:
// fallthrough
[[fallthrough]];
case rapidjson::kNullType:
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported,
"Unsupported type. Integers can't be read from arrays, objects or null.");
@@ -77,7 +85,7 @@ namespace AZ
return TextToValue(outputValue, inputValue.GetString(), context);
case rapidjson::kFalseType:
// fallthrough
[[fallthrough]];
case rapidjson::kTrueType:
*outputValue = inputValue.GetBool() ? 1 : 0;
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success,
@@ -125,6 +133,11 @@ namespace AZ
}
} // namespace SerializerInternal
auto BaseJsonIntegerSerializer::GetOperationsFlags() const -> OperationFlags
{
return OperationFlags::ManualDefault;
}
JsonSerializationResult::Result JsonCharSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
@@ -132,7 +145,7 @@ namespace AZ
"Unable to deserialize char to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<char*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(reinterpret_cast<char*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -151,7 +164,7 @@ namespace AZ
"Unable to deserialize short to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<short*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(reinterpret_cast<short*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -170,7 +183,7 @@ namespace AZ
"Unable to deserialize int to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<int*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(reinterpret_cast<int*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -189,7 +202,7 @@ namespace AZ
"Unable to deserialize long to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<long*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(reinterpret_cast<long*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -208,7 +221,7 @@ namespace AZ
"Unable to deserialize long long to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<long long*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(reinterpret_cast<long long*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -227,7 +240,8 @@ namespace AZ
"Unable to deserialize unsigned char to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<unsigned char*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(
reinterpret_cast<unsigned char*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -246,7 +260,8 @@ namespace AZ
"Unable to deserialize unsigned short to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<unsigned short*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(
reinterpret_cast<unsigned short*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -265,7 +280,8 @@ namespace AZ
"Unable to deserialize unsigned int to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<unsigned int*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(
reinterpret_cast<unsigned int*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -284,7 +300,8 @@ namespace AZ
"Unable to deserialize unsigned long to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<unsigned long*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(
reinterpret_cast<unsigned long*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -303,7 +320,8 @@ namespace AZ
"Unable to deserialize unsigned long long to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
return SerializerInternal::LoadInt(reinterpret_cast<unsigned long long*>(outputValue), inputValue, context);
return SerializerInternal::LoadInt(
reinterpret_cast<unsigned long long*>(outputValue), inputValue, context, IsExplicitDefault(inputValue));
}
JsonSerializationResult::Result JsonUnsignedLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
@@ -18,11 +18,18 @@
namespace AZ
{
class JsonCharSerializer
: public BaseJsonSerializer
class BaseJsonIntegerSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonSerializer);
AZ_RTTI(BaseJsonIntegerSerializer, "{FD060F54-D3B5-4D5B-B64A-AFE371CD6F20}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
OperationFlags GetOperationsFlags() const override;
};
class JsonCharSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -30,11 +37,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonShortSerializer
: public BaseJsonSerializer
class JsonShortSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonSerializer);
AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -42,11 +48,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonIntSerializer
: public BaseJsonSerializer
class JsonIntSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonSerializer);
AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -54,11 +59,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonLongSerializer
: public BaseJsonSerializer
class JsonLongSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonSerializer);
AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -66,11 +70,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonLongLongSerializer
: public BaseJsonSerializer
class JsonLongLongSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonSerializer);
AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -78,11 +81,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonUnsignedCharSerializer
: public BaseJsonSerializer
class JsonUnsignedCharSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonSerializer);
AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -90,11 +92,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonUnsignedShortSerializer
: public BaseJsonSerializer
class JsonUnsignedShortSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonSerializer);
AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -102,11 +103,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonUnsignedIntSerializer
: public BaseJsonSerializer
class JsonUnsignedIntSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonSerializer);
AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -114,11 +114,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonUnsignedLongSerializer
: public BaseJsonSerializer
class JsonUnsignedLongSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonSerializer);
AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -126,11 +125,10 @@ namespace AZ
const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
class JsonUnsignedLongLongSerializer
: public BaseJsonSerializer
class JsonUnsignedLongLongSerializer : public BaseJsonIntegerSerializer
{
public:
AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonSerializer);
AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonIntegerSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
@@ -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>(); }