DomJsonTests.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/DOM/Backends/JSON/JsonBackend.h>
  9. #include <AzCore/DOM/Backends/JSON/JsonSerializationUtils.h>
  10. #include <AzCore/DOM/DomUtils.h>
  11. #include <AzCore/Name/NameDictionary.h>
  12. #include <AzCore/Serialization/Json/JsonSerialization.h>
  13. #include <AzCore/Serialization/Json/JsonUtils.h>
  14. #include <AzCore/UnitTest/TestTypes.h>
  15. #include <Tests/DOM/DomFixtures.h>
  16. namespace AZ::Dom::Tests
  17. {
  18. class DomJsonTests : public DomTestFixture
  19. {
  20. public:
  21. void SetUp() override
  22. {
  23. DomTestFixture::SetUp();
  24. m_document = AZStd::make_unique<rapidjson::Document>();
  25. }
  26. void TearDown() override
  27. {
  28. m_document.reset();
  29. DomTestFixture::TearDown();
  30. }
  31. rapidjson::Value CreateString(const AZStd::string& text)
  32. {
  33. rapidjson::Value key;
  34. key.SetString(text.c_str(), static_cast<rapidjson::SizeType>(text.length()), m_document->GetAllocator());
  35. return key;
  36. }
  37. template<class T>
  38. void AddValue(const AZStd::string& key, T value)
  39. {
  40. m_document->AddMember(CreateString(key), rapidjson::Value(value), m_document->GetAllocator());
  41. }
  42. // Validate round-trip serialization to and from rapidjson::Document and a UTF-8 encoded string
  43. void PerformSerializationChecks()
  44. {
  45. // Generate a canonical serializaed representation of this document using rapidjson
  46. // This will be pretty-printed using the same rapidjson pretty printer we use, so should be binary identical
  47. // to any output generated by the visitor API
  48. AZStd::string canonicalSerializedDocument;
  49. AZ::JsonSerializationUtils::WriteJsonString(*m_document, canonicalSerializedDocument);
  50. auto visitDocumentFn = [this](AZ::Dom::Visitor& visitor)
  51. {
  52. return Json::VisitRapidJsonValue(*m_document, visitor, Lifetime::Temporary);
  53. };
  54. // Document -> Document
  55. {
  56. auto result = Json::WriteToRapidJsonDocument(visitDocumentFn);
  57. EXPECT_TRUE(result.IsSuccess());
  58. EXPECT_EQ(AZ::JsonSerialization::Compare(*m_document, result.GetValue()), AZ::JsonSerializerCompareResult::Equal);
  59. }
  60. // Document -> string
  61. {
  62. AZStd::string serializedDocument;
  63. JsonBackend backend;
  64. auto result = backend.WriteToBuffer(serializedDocument, visitDocumentFn);
  65. EXPECT_TRUE(result.IsSuccess());
  66. EXPECT_EQ(canonicalSerializedDocument, serializedDocument);
  67. }
  68. // string -> Document
  69. {
  70. auto result = Json::WriteToRapidJsonDocument(
  71. [&canonicalSerializedDocument](AZ::Dom::Visitor& visitor)
  72. {
  73. JsonBackend backend;
  74. return Dom::Utils::ReadFromString(backend, canonicalSerializedDocument, Lifetime::Temporary, visitor);
  75. });
  76. EXPECT_TRUE(result.IsSuccess());
  77. EXPECT_EQ(AZ::JsonSerialization::Compare(*m_document, result.GetValue()), JsonSerializerCompareResult::Equal);
  78. }
  79. // string -> string
  80. {
  81. AZStd::string serializedDocument;
  82. JsonBackend backend;
  83. auto result = backend.WriteToBuffer(
  84. serializedDocument,
  85. [&backend, &canonicalSerializedDocument](AZ::Dom::Visitor& visitor)
  86. {
  87. return Dom::Utils::ReadFromString(backend, canonicalSerializedDocument, Lifetime::Temporary, visitor);
  88. });
  89. EXPECT_TRUE(result.IsSuccess());
  90. EXPECT_EQ(canonicalSerializedDocument, serializedDocument);
  91. }
  92. }
  93. AZStd::unique_ptr<rapidjson::Document> m_document;
  94. };
  95. TEST_F(DomJsonTests, EmptyArray)
  96. {
  97. m_document->SetArray();
  98. PerformSerializationChecks();
  99. }
  100. TEST_F(DomJsonTests, SimpleArray)
  101. {
  102. m_document->SetArray();
  103. for (int i = 0; i < 5; ++i)
  104. {
  105. m_document->PushBack(i, m_document->GetAllocator());
  106. }
  107. PerformSerializationChecks();
  108. }
  109. TEST_F(DomJsonTests, NestedArrays)
  110. {
  111. m_document->SetArray();
  112. for (int j = 0; j < 7; ++j)
  113. {
  114. rapidjson::Value nestedArray(rapidjson::kArrayType);
  115. for (int i = 0; i < 5; ++i)
  116. {
  117. nestedArray.PushBack(i, m_document->GetAllocator());
  118. }
  119. m_document->PushBack(nestedArray.Move(), m_document->GetAllocator());
  120. }
  121. PerformSerializationChecks();
  122. }
  123. TEST_F(DomJsonTests, EmptyObject)
  124. {
  125. m_document->SetObject();
  126. PerformSerializationChecks();
  127. }
  128. TEST_F(DomJsonTests, SimpleObject)
  129. {
  130. m_document->SetObject();
  131. for (int i = 0; i < 5; ++i)
  132. {
  133. m_document->AddMember(CreateString(AZStd::string::format("Key%i", i)), rapidjson::Value(i), m_document->GetAllocator());
  134. }
  135. PerformSerializationChecks();
  136. }
  137. TEST_F(DomJsonTests, NestedObjects)
  138. {
  139. m_document->SetObject();
  140. for (int j = 0; j < 7; ++j)
  141. {
  142. rapidjson::Value nestedObject(rapidjson::kObjectType);
  143. for (int i = 0; i < 5; ++i)
  144. {
  145. nestedObject.AddMember(CreateString(AZStd::string::format("Key%i", i)), rapidjson::Value(i), m_document->GetAllocator());
  146. }
  147. m_document->AddMember(CreateString(AZStd::string::format("Obj%i", j)), nestedObject.Move(), m_document->GetAllocator());
  148. }
  149. PerformSerializationChecks();
  150. }
  151. TEST_F(DomJsonTests, Int64)
  152. {
  153. m_document->SetObject();
  154. AddValue("int64_min", AZStd::numeric_limits<int64_t>::min());
  155. AddValue("int64_max", AZStd::numeric_limits<int64_t>::max());
  156. PerformSerializationChecks();
  157. }
  158. TEST_F(DomJsonTests, Uint64)
  159. {
  160. m_document->SetObject();
  161. AddValue("uint64_min", AZStd::numeric_limits<uint64_t>::min());
  162. AddValue("uint64_max", AZStd::numeric_limits<uint64_t>::max());
  163. PerformSerializationChecks();
  164. }
  165. TEST_F(DomJsonTests, Double)
  166. {
  167. m_document->SetObject();
  168. AddValue("double_min", AZStd::numeric_limits<double>::min());
  169. AddValue("double_max", AZStd::numeric_limits<double>::max());
  170. PerformSerializationChecks();
  171. }
  172. TEST_F(DomJsonTests, Null)
  173. {
  174. m_document->SetObject();
  175. m_document->AddMember(CreateString("null_value"), rapidjson::Value(rapidjson::kNullType), m_document->GetAllocator());
  176. PerformSerializationChecks();
  177. }
  178. TEST_F(DomJsonTests, Bool)
  179. {
  180. m_document->SetObject();
  181. AddValue("true_value", true);
  182. AddValue("false_value", false);
  183. PerformSerializationChecks();
  184. }
  185. TEST_F(DomJsonTests, String)
  186. {
  187. m_document->SetObject();
  188. m_document->AddMember(CreateString("empty_string"), CreateString(""), m_document->GetAllocator());
  189. m_document->AddMember(CreateString("short_string"), CreateString("test"), m_document->GetAllocator());
  190. m_document->AddMember(
  191. CreateString("long_string"), CreateString("abcdefghijklmnopqrstuvwxyz0123456789"), m_document->GetAllocator());
  192. PerformSerializationChecks();
  193. }
  194. } // namespace AZ::Dom::Tests