Add some intial tests

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-12-09 17:47:01 -08:00
parent e7c92b5658
commit a2d474cc4f
6 changed files with 350 additions and 18 deletions
+115 -8
View File
@@ -97,6 +97,16 @@ namespace AZ::Dom
return Value(&value);
}
Value::Value(int32_t value)
: m_value(aznumeric_cast<int64_t>(value))
{
}
Value::Value(uint32_t value)
: m_value(aznumeric_cast<uint64_t>(value))
{
}
Value::Value(int64_t value)
: m_value(value)
{
@@ -107,6 +117,11 @@ namespace AZ::Dom
{
}
Value::Value(float value)
: m_value(aznumeric_cast<double>(value))
{
}
Value::Value(double value)
: m_value(value)
{
@@ -117,6 +132,40 @@ namespace AZ::Dom
{
}
Value::Value(Type type)
{
switch (type)
{
case Type::NullType:
// Null is the default initialized value
break;
case Type::FalseType:
m_value = false;
break;
case Type::TrueType:
m_value = true;
break;
case Type::ObjectType:
SetObject();
break;
case Type::ArrayType:
SetArray();
break;
case Type::StringType:
SetString("");
break;
case Type::NumberType:
m_value = 0.0;
break;
case Type::NodeType:
SetNode("");
break;
case Type::OpaqueType:
AZ_Assert(false, "AZ::Dom::Value may not be constructed with an empty opaque type");
break;
}
}
Value& Value::operator=(const Value& other)
{
m_value = other.m_value;
@@ -139,11 +188,11 @@ namespace AZ::Dom
{
if (IsInt())
{
return GetInt() == rhs.GetInt();
return GetInt64() == rhs.GetInt64();
}
else if (IsUint())
{
return GetUint() == rhs.GetUint();
return GetUint64() == rhs.GetUint64();
}
else
{
@@ -315,7 +364,7 @@ namespace AZ::Dom
AZ_Assert(
type == Type::ArrayType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or a node");
if (type == Type::ObjectType)
if (type == Type::ArrayType)
{
return AZStd::get<ArrayPtr>(m_value)->m_values;
}
@@ -331,7 +380,7 @@ namespace AZ::Dom
AZ_Assert(
type == Type::ArrayType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node");
if (type == Type::ObjectType)
if (type == Type::ArrayType)
{
return CheckCopyOnWrite(AZStd::get<ArrayPtr>(m_value))->m_values;
}
@@ -702,7 +751,7 @@ namespace AZ::Dom
return Value();
}
int64_t Value::GetInt() const
int64_t Value::GetInt64() const
{
switch (m_value.index())
{
@@ -717,12 +766,22 @@ namespace AZ::Dom
return {};
}
void Value::SetInt(int64_t value)
void Value::SetInt64(int64_t value)
{
m_value = value;
}
uint64_t Value::GetUint() const
int32_t Value::GetInt32() const
{
return aznumeric_cast<int32_t>(GetInt64());
}
void Value::SetInt32(int32_t value)
{
m_value = aznumeric_cast<int64_t>(value);
}
uint64_t Value::GetUint64() const
{
switch (m_value.index())
{
@@ -737,11 +796,21 @@ namespace AZ::Dom
return {};
}
void Value::SetUint(uint64_t value)
void Value::SetUint64(uint64_t value)
{
m_value = value;
}
uint32_t Value::GetUint32() const
{
return aznumeric_cast<uint32_t>(GetUint64());
}
void Value::SetUint32(uint32_t value)
{
m_value = aznumeric_cast<uint64_t>(value);
}
bool Value::GetBool() const
{
if (IsBool())
@@ -777,6 +846,16 @@ namespace AZ::Dom
m_value = value;
}
float Value::GetFloat() const
{
return aznumeric_cast<float>(GetDouble());
}
void Value::SetFloat(float value)
{
m_value = aznumeric_cast<double>(value);
}
AZStd::string_view Value::GetString() const
{
switch (m_value.index())
@@ -861,6 +940,11 @@ namespace AZ::Dom
const Object::ContainerType& object = GetObjectInternal();
for (const Object::EntryType& entry : object)
{
result = visitor.Key(entry.first);
if (!result.IsSuccess())
{
return;
}
result = entry.second.Accept(visitor, copyStrings);
if (!result.IsSuccess())
{
@@ -896,6 +980,11 @@ namespace AZ::Dom
const Object::ContainerType& object = GetObjectInternal();
for (const Object::EntryType& entry : object)
{
result = visitor.Key(entry.first);
if (!result.IsSuccess())
{
return;
}
result = entry.second.Accept(visitor, copyStrings);
if (!result.IsSuccess())
{
@@ -932,6 +1021,16 @@ namespace AZ::Dom
bool Value::DeepCompareIsEqual(const Value& other) const
{
if (IsString() && other.IsString())
{
// If we both hold the same ref counted string we don't need to do a full comparison
if (AZStd::holds_alternative<AZStd::shared_ptr<AZStd::string>>(m_value) && m_value == other.m_value)
{
return true;
}
return GetString() == other.GetString();
}
if (m_value.index() != other.m_value.index())
{
return false;
@@ -1045,4 +1144,12 @@ namespace AZ::Dom
},
m_value);
}
Value Value::DeepCopy(bool copyStrings) const
{
Value newValue;
AZStd::unique_ptr<Visitor> writer = newValue.GetWriteHandler();
Accept(*writer, copyStrings);
return newValue;
}
} // namespace AZ::Dom
+20 -8
View File
@@ -109,10 +109,15 @@ namespace AZ::Dom
Value(Value&&) noexcept;
Value(AZStd::string_view string, bool copy);
explicit Value(int64_t value);
explicit Value(uint64_t value);
explicit Value(double value);
explicit Value(bool value);
Value(int32_t value);
Value(uint32_t value);
Value(int64_t value);
Value(uint64_t value);
Value(float value);
Value(double value);
Value(bool value);
explicit Value(Type type);
static Value FromOpaqueValue(AZStd::any& value);
@@ -226,12 +231,16 @@ namespace AZ::Dom
Value GetNodeValue() const;
// int API...
int64_t GetInt() const;
void SetInt(int64_t);
int64_t GetInt64() const;
void SetInt64(int64_t);
int32_t GetInt32() const;
void SetInt32(int32_t);
// uint API...
uint64_t GetUint() const;
void SetUint(uint64_t);
uint64_t GetUint64() const;
void SetUint64(uint64_t);
uint32_t GetUint32() const;
void SetUint32(uint32_t);
// bool API...
bool GetBool() const;
@@ -240,6 +249,8 @@ namespace AZ::Dom
// double API...
double GetDouble() const;
void SetDouble(double);
float GetFloat() const;
void SetFloat(float);
// string API...
AZStd::string_view GetString() const;
@@ -264,6 +275,7 @@ namespace AZ::Dom
AZStd::unique_ptr<Visitor> GetWriteHandler();
bool DeepCompareIsEqual(const Value& other) const;
Value DeepCopy(bool copyStrings = true) const;
private:
const Node& GetNodeInternal() const;
@@ -39,13 +39,13 @@ namespace AZ::Dom
Visitor::Result ValueWriter::Int64(AZ::s64 value)
{
CurrentValue().SetInt(value);
CurrentValue().SetInt64(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Uint64(AZ::u64 value)
{
CurrentValue().SetUint(value);
CurrentValue().SetUint64(value);
return FinishWrite();
}
@@ -0,0 +1,211 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/DOM/Backends/JSON/JsonBackend.h>
#include <AzCore/DOM/Backends/JSON/JsonSerializationUtils.h>
#include <AzCore/DOM/DomUtils.h>
#include <AzCore/DOM/DomValue.h>
#include <AzCore/Name/NameDictionary.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace AZ::Dom::Tests
{
class DomValueTests : public UnitTest::AllocatorsFixture
{
public:
void SetUp() override
{
UnitTest::AllocatorsFixture::SetUp();
NameDictionary::Create();
}
void TearDown() override
{
m_value = Value();
NameDictionary::Destroy();
UnitTest::AllocatorsFixture::TearDown();
}
void PerformValueChecks()
{
Value shallowCopy = m_value;
EXPECT_EQ(m_value, shallowCopy);
EXPECT_TRUE(m_value.DeepCompareIsEqual(shallowCopy));
Value deepCopy = m_value.DeepCopy();
EXPECT_TRUE(m_value.DeepCompareIsEqual(deepCopy));
}
Value m_value;
};
TEST_F(DomValueTests, EmptyArray)
{
m_value.SetArray();
EXPECT_TRUE(m_value.IsArray());
EXPECT_EQ(m_value.Size(), 0);
PerformValueChecks();
}
TEST_F(DomValueTests, SimpleArray)
{
m_value.SetArray();
for (int i = 0; i < 5; ++i)
{
m_value.PushBack(Value(i));
EXPECT_EQ(m_value.Size(), i + 1);
EXPECT_EQ(m_value[i].GetInt32(), i);
}
PerformValueChecks();
}
TEST_F(DomValueTests, NestedArrays)
{
m_value.SetArray();
for (int j = 0; j < 5; ++j)
{
Value nestedArray(Type::ArrayType);
for (int i = 0; i < 5; ++i)
{
nestedArray.PushBack(Value(i));
}
m_value.PushBack(AZStd::move(nestedArray));
}
EXPECT_EQ(m_value.Size(), 5);
for (int i = 0; i < 3; ++i)
{
EXPECT_EQ(m_value[i].Size(), 5);
for (int j = 0; j < 5; ++j)
{
EXPECT_EQ(m_value[i][j].GetInt32(), j);
}
}
PerformValueChecks();
}
TEST_F(DomValueTests, EmptyObject)
{
m_value.SetObject();
EXPECT_EQ(m_value.MemberCount(), 0);
PerformValueChecks();
}
TEST_F(DomValueTests, SimpleObject)
{
m_value.SetObject();
for (int i = 0; i < 5; ++i)
{
AZStd::string key = AZStd::string::format("Key%i", i);
m_value.AddMember(key, Value(i));
EXPECT_EQ(m_value.MemberCount(), i + 1);
EXPECT_EQ(m_value[key].GetInt32(), i);
}
PerformValueChecks();
}
TEST_F(DomValueTests, NestedObjects)
{
m_value.SetObject();
for (int j = 0; j < 3; ++j)
{
Value nestedObject(Type::ObjectType);
for (int i = 0; i < 5; ++i)
{
nestedObject.AddMember(AZStd::string::format("Key%i", i), Value(i));
}
m_value.AddMember(AZStd::string::format("Obj%i", j), AZStd::move(nestedObject));
}
EXPECT_EQ(m_value.MemberCount(), 3);
for (int j = 0; j < 3; ++j)
{
const Value& nestedObject = m_value[AZStd::string::format("Obj%i", j)];
EXPECT_EQ(nestedObject.MemberCount(), 5);
for (int i = 0; i < 5; ++i)
{
EXPECT_EQ(nestedObject[AZStd::string::format("Key%i", i)].GetInt32(), i);
}
}
PerformValueChecks();
}
TEST_F(DomValueTests, EmptyNode)
{
m_value.SetNode("Test");
EXPECT_EQ(m_value.GetNodeName(), AZ::Name("Test"));
EXPECT_EQ(m_value.MemberCount(), 0);
EXPECT_EQ(m_value.Size(), 0);
PerformValueChecks();
}
TEST_F(DomValueTests, SimpleNode)
{
m_value.SetNode("Test");
for (int i = 0; i < 10; ++i)
{
m_value.PushBack(Value(i));
EXPECT_EQ(m_value.Size(), i + 1);
EXPECT_EQ(m_value[i].GetInt32(), i);
if (i < 5)
{
AZ::Name key = AZ::Name(AZStd::string::format("TwoTimes%i", i));
m_value.AddMember(key, Value(i * 2));
EXPECT_EQ(m_value.MemberCount(), i + 1);
EXPECT_EQ(m_value[key].GetInt32(), i * 2);
}
}
PerformValueChecks();
}
TEST_F(DomValueTests, NestedNodes)
{
m_value.SetNode("TopLevel");
const AZ::Name childNodeName("ChildNode");
for (int i = 0; i < 5; ++i)
{
Value childNode(Type::NodeType);
childNode.SetNodeName(childNodeName);
childNode.SetNodeValue(i);
childNode.AddMember("foo", i);
childNode.AddMember("bar", Value("test", false));
m_value.PushBack(childNode);
}
EXPECT_EQ(m_value.Size(), 5);
for (int i = 0; i < 5; ++i)
{
const Value& childNode = m_value[i];
EXPECT_EQ(childNode.GetNodeName(), childNodeName);
EXPECT_EQ(childNode.GetNodeValue().GetInt32(), i);
EXPECT_EQ(childNode["foo"].GetInt32(), i);
EXPECT_EQ(childNode["bar"].GetString(), "test");
}
PerformValueChecks();
}
} // namespace AZ::Dom::Tests
@@ -215,6 +215,8 @@ set(FILES
AZStd/VectorAndArray.cpp
DOM/DomJsonTests.cpp
DOM/DomJsonBenchmarks.cpp
DOM/DomValueTests.cpp
DOM/DomValueBenchmarks.cpp
)
# Prevent the following files from being grouped in UNITY builds