PrefabTestDomUtils.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 <Prefab/PrefabTestDomUtils.h>
  9. #include <AzCore/Interface/Interface.h>
  10. #include <AzCore/JSON/prettywriter.h>
  11. #include <AzCore/Serialization/Json/JsonSerialization.h>
  12. #include <AzCore/std/optional.h>
  13. #include <AzTest/AzTest.h>
  14. #include <AzToolsFramework/Prefab/Instance/TemplateInstanceMapperInterface.h>
  15. #include <AzToolsFramework/Prefab/PrefabDomUtils.h>
  16. namespace UnitTest
  17. {
  18. namespace PrefabTestDomUtils
  19. {
  20. void SetPrefabDomInstance(
  21. PrefabDom& prefabDom,
  22. const char* instanceName,
  23. const char* source,
  24. const PrefabDomValue& patches)
  25. {
  26. rapidjson::SetValueByPointer(prefabDom, GetPrefabDomSourcePath(instanceName), source);
  27. if (!patches.IsNull())
  28. {
  29. rapidjson::SetValueByPointer(prefabDom, GetPrefabDomPatchesPath(instanceName), patches, prefabDom.GetAllocator());
  30. }
  31. }
  32. PrefabDom CreatePrefabDom()
  33. {
  34. PrefabDom newPrefabDom;
  35. rapidjson::SetValueByPointer(newPrefabDom, "/Entities", rapidjson::Value());
  36. return newPrefabDom;
  37. }
  38. PrefabDom CreatePrefabDom(
  39. const AZStd::vector<InstanceData>& instancesData)
  40. {
  41. PrefabDom newPrefabDom = CreatePrefabDom();
  42. for (auto& instanceData : instancesData)
  43. {
  44. PrefabTestDomUtils::SetPrefabDomInstance(
  45. newPrefabDom, instanceData.m_name.c_str(),
  46. instanceData.m_source.c_str(), instanceData.m_patches);
  47. }
  48. return newPrefabDom;
  49. }
  50. void ValidateInstances(
  51. TemplateId templateId,
  52. const PrefabDomValue& expectedContent,
  53. const PrefabDomPath& contentPath,
  54. bool isContentAnInstance,
  55. bool shouldCompareContainerEntities)
  56. {
  57. TemplateInstanceMapperInterface* templateInstanceMapper =
  58. AZ::Interface<TemplateInstanceMapperInterface>::Get();
  59. ASSERT_TRUE(templateInstanceMapper != nullptr);
  60. ASSERT_TRUE(templateId != AzToolsFramework::Prefab::InvalidTemplateId);
  61. auto instancesReference = templateInstanceMapper->FindInstancesOwnedByTemplate(templateId);
  62. ASSERT_TRUE(instancesReference.has_value());
  63. auto& actualInstances = instancesReference->get();
  64. for (auto instance : actualInstances)
  65. {
  66. PrefabDom instancePrefabDom;
  67. const bool result = PrefabDomUtils::StoreInstanceInPrefabDom(*instance, instancePrefabDom);
  68. ASSERT_TRUE(result);
  69. auto* actualContent = contentPath.Get(instancePrefabDom);
  70. ASSERT_TRUE(actualContent != nullptr);
  71. if (isContentAnInstance)
  72. {
  73. ComparePrefabDoms(*actualContent, expectedContent, false, shouldCompareContainerEntities);
  74. }
  75. else
  76. {
  77. ComparePrefabDomValues(*actualContent, expectedContent);
  78. }
  79. }
  80. }
  81. void ValidatePrefabDomEntities(const AZStd::vector<EntityAlias>& entityAliases, PrefabDom& prefabDom)
  82. {
  83. PrefabDomValueReference templateEntities = PrefabDomUtils::FindPrefabDomValue(prefabDom, "Entities");
  84. ASSERT_TRUE(templateEntities.has_value());
  85. for (EntityAlias entityAlias : entityAliases)
  86. {
  87. EXPECT_TRUE(PrefabDomUtils::FindPrefabDomValue(templateEntities->get(), entityAlias.c_str()).has_value());
  88. }
  89. }
  90. void ValidatePrefabDomInstances(
  91. const AZStd::vector<InstanceAlias>& instanceAliases,
  92. const AzToolsFramework::Prefab::PrefabDom& prefabDom,
  93. const AzToolsFramework::Prefab::PrefabDom& expectedNestedInstanceDom,
  94. bool shouldCompareContainerEntities)
  95. {
  96. PrefabDomValueConstReference templateInstances = PrefabDomUtils::FindPrefabDomValue(prefabDom, "Instances");
  97. ASSERT_TRUE(templateInstances.has_value());
  98. for (InstanceAlias instanceAlias : instanceAliases)
  99. {
  100. PrefabDomValueConstReference actualNestedInstanceDom = PrefabDomUtils::FindPrefabDomValue(templateInstances->get(), instanceAlias.c_str());
  101. ASSERT_TRUE(actualNestedInstanceDom.has_value());
  102. ComparePrefabDoms(actualNestedInstanceDom, expectedNestedInstanceDom, false, shouldCompareContainerEntities);
  103. }
  104. }
  105. void ComparePrefabDoms(
  106. PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB, bool shouldCompareLinkIds,
  107. bool shouldCompareContainerEntities)
  108. {
  109. ASSERT_TRUE(valueA.has_value());
  110. ASSERT_TRUE(valueB.has_value());
  111. const PrefabDomValue& valueADom = valueA->get();
  112. const PrefabDomValue& valueBDom = valueB->get();
  113. if (shouldCompareLinkIds)
  114. {
  115. PrefabDomValueConstReference actualNestedInstanceDomLinkId =
  116. PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::LinkIdName);
  117. PrefabDomValueConstReference expectedNestedInstanceDomLinkId =
  118. PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::LinkIdName);
  119. ComparePrefabDomValues(actualNestedInstanceDomLinkId, expectedNestedInstanceDomLinkId);
  120. }
  121. if (shouldCompareContainerEntities)
  122. {
  123. PrefabDomValueConstReference actualNestedInstanceDomContainerEntity =
  124. PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::ContainerEntityName);
  125. PrefabDomValueConstReference expectedNestedInstanceDomContainerEntity =
  126. PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::ContainerEntityName);
  127. ComparePrefabDomValues(actualNestedInstanceDomContainerEntity, expectedNestedInstanceDomContainerEntity);
  128. }
  129. // Compare the source values of the two DOMs.
  130. PrefabDomValueConstReference actualNestedInstanceDomSource =
  131. PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::SourceName);
  132. PrefabDomValueConstReference expectedNestedInstanceDomSource =
  133. PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::SourceName);
  134. ComparePrefabDomValues(actualNestedInstanceDomSource, expectedNestedInstanceDomSource);
  135. // Compare the entities values of the two DOMs.
  136. PrefabDomValueConstReference actualNestedInstanceDomEntities =
  137. PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabTestDomUtils::EntitiesValueName);
  138. PrefabDomValueConstReference expectedNestedInstanceDomEntities =
  139. PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabTestDomUtils::EntitiesValueName);
  140. ComparePrefabDomValues(actualNestedInstanceDomEntities, expectedNestedInstanceDomEntities);
  141. // Compare the instances values of the two DOMs, which involves iterating over each expected instance and comparing it
  142. // with its counterpart in the actual instance.
  143. PrefabDomValueConstReference actualNestedInstanceDomInstances =
  144. PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::InstancesName);
  145. PrefabDomValueConstReference expectedNestedInstanceDomInstances =
  146. PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::InstancesName);
  147. if (expectedNestedInstanceDomInstances.has_value())
  148. {
  149. ASSERT_TRUE(actualNestedInstanceDomInstances.has_value());
  150. if (expectedNestedInstanceDomInstances->get().IsArray())
  151. {
  152. ASSERT_TRUE(actualNestedInstanceDomInstances->get().IsArray());
  153. const size_t expectedArraySize = expectedNestedInstanceDomInstances->get().GetArray().Size();
  154. EXPECT_EQ(0, expectedArraySize);
  155. const size_t actualArraySize = actualNestedInstanceDomInstances->get().GetArray().Size();
  156. EXPECT_EQ(0, actualArraySize);
  157. }
  158. if (expectedNestedInstanceDomInstances->get().IsObject())
  159. {
  160. ASSERT_TRUE(actualNestedInstanceDomInstances->get().IsObject());
  161. for (auto instanceIterator = expectedNestedInstanceDomInstances->get().MemberBegin();
  162. instanceIterator != expectedNestedInstanceDomInstances->get().MemberEnd(); ++instanceIterator)
  163. {
  164. ComparePrefabDoms(
  165. instanceIterator->value,
  166. PrefabDomUtils::FindPrefabDomValue(actualNestedInstanceDomInstances->get(), instanceIterator->name.GetString()),
  167. shouldCompareLinkIds, shouldCompareContainerEntities);
  168. }
  169. }
  170. }
  171. }
  172. void ComparePrefabDomValues(PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB)
  173. {
  174. if (!valueA.has_value())
  175. {
  176. EXPECT_FALSE(valueB.has_value());
  177. }
  178. else
  179. {
  180. EXPECT_TRUE(valueB.has_value());
  181. EXPECT_EQ(AZ::JsonSerialization::Compare(valueA->get(), valueB->get()), AZ::JsonSerializerCompareResult::Equal);
  182. }
  183. }
  184. void ValidateEntitiesOfInstances(
  185. AzToolsFramework::Prefab::TemplateId templateId,
  186. const AzToolsFramework::Prefab::PrefabDom& expectedPrefabDom,
  187. const AZStd::vector<EntityAlias>& entityAliases)
  188. {
  189. for (auto& entityAlias : entityAliases)
  190. {
  191. PrefabDomPath entityPath = PrefabTestDomUtils::GetPrefabDomEntityPath(entityAlias);
  192. const PrefabDomValue* expectedEntityValue = PrefabTestDomUtils::GetPrefabDomEntity(expectedPrefabDom, entityAlias);
  193. ASSERT_TRUE(expectedEntityValue != nullptr);
  194. PrefabTestDomUtils::ValidateInstances(templateId, *expectedEntityValue, entityPath);
  195. }
  196. }
  197. void ValidateNestedInstancesOfInstances(
  198. AzToolsFramework::Prefab::TemplateId templateId,
  199. const AzToolsFramework::Prefab::PrefabDom& expectedPrefabDom,
  200. const AZStd::vector<InstanceAlias>& nestedInstanceAliases)
  201. {
  202. for (auto& nestedInstanceAlias : nestedInstanceAliases)
  203. {
  204. PrefabDomPath nestedInstancePath = PrefabTestDomUtils::GetPrefabDomInstancePath(nestedInstanceAlias);
  205. const PrefabDomValue* nestedInstanceValue =
  206. PrefabTestDomUtils::GetPrefabDomInstance(expectedPrefabDom, nestedInstanceAlias);
  207. ASSERT_TRUE(nestedInstanceValue != nullptr);
  208. PrefabTestDomUtils::ValidateInstances(templateId, *nestedInstanceValue, nestedInstancePath, true, false);
  209. }
  210. }
  211. void ValidateComponentsDomHasId(const PrefabDomValue& componentsDom, const char* componentName, AZ::u64 componentId)
  212. {
  213. PrefabDomValueConstReference entityComponentValue = PrefabDomUtils::FindPrefabDomValue(componentsDom, componentName);
  214. ASSERT_TRUE(entityComponentValue);
  215. PrefabDomValueConstReference entityComponentIdValue =
  216. PrefabDomUtils::FindPrefabDomValue(entityComponentValue->get(), PrefabTestDomUtils::ComponentIdName);
  217. EXPECT_EQ(componentId, entityComponentIdValue->get().GetUint64());
  218. }
  219. AZStd::string DomToString(const AzToolsFramework::Prefab::PrefabDom& dom)
  220. {
  221. rapidjson::StringBuffer prefabFileContentBuffer;
  222. rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(prefabFileContentBuffer);
  223. dom.Accept(writer);
  224. return AZStd::string(prefabFileContentBuffer.GetString());
  225. }
  226. }
  227. }