SerializationDependenciesTests.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 <AzTest/AzTest.h>
  9. #include <AzCore/Asset/AssetSerializer.h>
  10. #include <AssetBuilderSDK/SerializationDependencies.h>
  11. #include <Tests/SerializeContextFixture.h>
  12. namespace SerializationDependencyTests
  13. {
  14. class ClassWithAssetId
  15. {
  16. public:
  17. AZ_RTTI(ClassWithAssetId, "{F6970E05-890B-4E5D-A944-1F58E9751922}");
  18. virtual ~ClassWithAssetId() {}
  19. static void Reflect(AZ::ReflectContext* reflection)
  20. {
  21. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  22. if (serializeContext)
  23. {
  24. serializeContext->Class<ClassWithAssetId>()
  25. ->Field("m_assetId", &ClassWithAssetId::m_assetId);
  26. }
  27. }
  28. AZ::Data::AssetId m_assetId;
  29. };
  30. class ClassWithAsset
  31. {
  32. public:
  33. AZ_RTTI(ClassWithAsset, "{D2BCF9BF-3E64-4942-8AFB-BD3E8453CB52}");
  34. virtual ~ClassWithAsset() {}
  35. static void Reflect(AZ::ReflectContext* reflection)
  36. {
  37. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  38. if (serializeContext)
  39. {
  40. serializeContext->Class<ClassWithAsset>()
  41. ->Field("m_asset", &ClassWithAsset::m_asset);
  42. }
  43. }
  44. AZ::Data::Asset<AZ::Data::AssetData> m_asset;
  45. };
  46. class ClassWithNoLoadAsset
  47. {
  48. public:
  49. AZ_RTTI(ClassWithNoLoadAsset, "{C38D0DFA-A19E-48EF-BC0E-2BE4E320F65A}");
  50. ClassWithNoLoadAsset() : m_asset(AZ::Data::AssetLoadBehavior::NoLoad)
  51. {
  52. }
  53. virtual ~ClassWithNoLoadAsset() {}
  54. static void Reflect(AZ::ReflectContext* reflection)
  55. {
  56. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  57. if (serializeContext)
  58. {
  59. serializeContext->Class<ClassWithNoLoadAsset>()
  60. ->Field("m_asset", &ClassWithNoLoadAsset::m_asset);
  61. }
  62. }
  63. AZ::Data::Asset<AZ::Data::AssetData> m_asset;
  64. };
  65. class SimpleAssetMock : public AzFramework::SimpleAssetReferenceBase
  66. {
  67. public:
  68. AZ_RTTI(SimpleAssetMock, "{AA2CDA39-A357-441D-BABA-B1AD3C3A8083}", AzFramework::SimpleAssetReferenceBase);
  69. static void Reflect(AZ::ReflectContext* reflection)
  70. {
  71. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  72. if (serializeContext)
  73. {
  74. serializeContext->Class<SimpleAssetMock, AzFramework::SimpleAssetReferenceBase>();
  75. }
  76. }
  77. AZ::Data::AssetType GetAssetType() const override
  78. {
  79. // Use an arbitrary ID for the asset type.
  80. return AZ::Data::AssetType("{03FD33E2-DA2F-4021-A266-0DC9714FF84D}");
  81. }
  82. const char* GetFileFilter() const override
  83. {
  84. return nullptr;
  85. }
  86. };
  87. class ClassWithSimpleAsset
  88. {
  89. public:
  90. AZ_RTTI(ClassWithSimpleAsset, "{F4F50653-692C-46F8-A9B0-73C19523E56A}");
  91. virtual ~ClassWithSimpleAsset() {}
  92. static void Reflect(AZ::ReflectContext* reflection)
  93. {
  94. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
  95. if (serializeContext)
  96. {
  97. serializeContext->Class<ClassWithSimpleAsset>()
  98. ->Field("m_simpleAsset", &ClassWithSimpleAsset::m_simpleAsset);
  99. }
  100. }
  101. SimpleAssetMock m_simpleAsset;
  102. };
  103. class SerializationDependenciesTests
  104. : public UnitTest::SerializeContextFixture
  105. , public UnitTest::TraceBusRedirector
  106. {
  107. protected:
  108. void SetUp() override
  109. {
  110. SerializeContextFixture::SetUp();
  111. AZ::Debug::TraceMessageBus::Handler::BusConnect();
  112. AZ::Data::AssetId::Reflect(m_serializeContext);
  113. AZ::Data::AssetData::Reflect(m_serializeContext);
  114. AzFramework::SimpleAssetReferenceBase::Reflect(m_serializeContext);
  115. ClassWithAssetId::Reflect(m_serializeContext);
  116. ClassWithAsset::Reflect(m_serializeContext);
  117. SimpleAssetMock::Reflect(m_serializeContext);
  118. ClassWithSimpleAsset::Reflect(m_serializeContext);
  119. ClassWithNoLoadAsset::Reflect(m_serializeContext);
  120. }
  121. void TearDown() override
  122. {
  123. AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
  124. UnitTest::SerializeContextFixture::TearDown();
  125. }
  126. };
  127. int GetProductDependencySlot(const AZStd::vector<AssetBuilderSDK::ProductDependency>& productDependencies, const AZ::Data::AssetId& assetId)
  128. {
  129. for (int productDependencySlot = 0; productDependencySlot < aznumeric_cast<int>(productDependencies.size()); ++productDependencySlot)
  130. {
  131. if (productDependencies[productDependencySlot].m_dependencyId == assetId)
  132. {
  133. return productDependencySlot;
  134. }
  135. }
  136. return false;
  137. }
  138. bool FindAssetIdInProductDependencies(const AZStd::vector<AssetBuilderSDK::ProductDependency>& productDependencies, const AZ::Data::AssetId& assetId)
  139. {
  140. return (GetProductDependencySlot(productDependencies, assetId) != -1);
  141. }
  142. TEST_F(SerializationDependenciesTests, GatherProductDependencies_NullData_NoCrash)
  143. {
  144. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  145. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  146. // Using a known type for the nullptr instead of a void* so the template resolves properly for the call.
  147. ClassWithAssetId* nullClass = nullptr;
  148. AZ_TEST_START_TRACE_SUPPRESSION;
  149. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, nullClass, productDependencies, productPathDependencySet);
  150. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  151. ASSERT_FALSE(gatherResult);
  152. ASSERT_EQ(productDependencies.size(), 0);
  153. ASSERT_EQ(productPathDependencySet.size(), 0);
  154. }
  155. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasValidAssetId_AssetIdFound)
  156. {
  157. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  158. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  159. ClassWithAssetId classWithAssetId;
  160. classWithAssetId.m_assetId = AZ::Data::AssetId("{3008D6F9-1E56-4699-95F9-91A3758A964E}", 33);
  161. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithAssetId, productDependencies, productPathDependencySet);
  162. ASSERT_TRUE(gatherResult);
  163. ASSERT_EQ(productDependencies.size(), 1);
  164. ASSERT_TRUE(FindAssetIdInProductDependencies(productDependencies, classWithAssetId.m_assetId));
  165. ASSERT_EQ(productPathDependencySet.size(), 0);
  166. }
  167. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasNullAssetId_NoDependencyEmitted)
  168. {
  169. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  170. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  171. ClassWithAssetId classWithAssetId;
  172. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithAssetId, productDependencies, productPathDependencySet);
  173. ASSERT_TRUE(gatherResult);
  174. ASSERT_EQ(productDependencies.size(), 0);
  175. ASSERT_EQ(productPathDependencySet.size(), 0);
  176. }
  177. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasValidAsset_AssetIdFound)
  178. {
  179. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  180. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  181. ClassWithAsset classWithAsset;
  182. AZ::Data::AssetId testAssetId("{CAAC5458-0738-43F6-A2BD-4E315C64BFD3}", 71);
  183. classWithAsset.m_asset = AZ::Data::Asset<AZ::Data::AssetData>(
  184. testAssetId,
  185. azrtti_typeid<AZ::Data::AssetData>());
  186. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithAsset, productDependencies, productPathDependencySet);
  187. ASSERT_TRUE(gatherResult);
  188. ASSERT_EQ(productDependencies.size(), 1);
  189. ASSERT_TRUE(FindAssetIdInProductDependencies(productDependencies, testAssetId));
  190. ASSERT_EQ(productPathDependencySet.size(), 0);
  191. }
  192. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasNullAsset_NoDependencyEmitted)
  193. {
  194. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  195. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  196. ClassWithAsset classWithAsset;
  197. AZ::Data::AssetId testAssetId;
  198. testAssetId.SetInvalid(); // Make it clear that this is an invalid ID.
  199. classWithAsset.m_asset = AZ::Data::Asset<AZ::Data::AssetData>(
  200. testAssetId,
  201. azrtti_typeid<AZ::Data::AssetData>());
  202. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithAsset, productDependencies, productPathDependencySet);
  203. ASSERT_TRUE(gatherResult);
  204. ASSERT_EQ(productDependencies.size(), 0);
  205. ASSERT_EQ(productPathDependencySet.size(), 0);
  206. }
  207. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasValidSimpleAsset_AssetPathFound)
  208. {
  209. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  210. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  211. ClassWithSimpleAsset classWithSimpleAsset;
  212. const AZStd::string expectedAssetPath("TestAssetPathString.txt");
  213. classWithSimpleAsset.m_simpleAsset.SetAssetPath(expectedAssetPath.c_str());
  214. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithSimpleAsset, productDependencies, productPathDependencySet);
  215. ASSERT_TRUE(gatherResult);
  216. ASSERT_EQ(productDependencies.size(), 0);
  217. ASSERT_EQ(productPathDependencySet.size(), 1);
  218. ASSERT_TRUE(productPathDependencySet.begin()->m_dependencyPath.compare(expectedAssetPath) == 0);
  219. ASSERT_TRUE(productPathDependencySet.begin()->m_dependencyType == AssetBuilderSDK::ProductPathDependencyType::ProductFile);
  220. }
  221. TEST_F(SerializationDependenciesTests, GatherProductDependencies_DependencyFlagsSerialization_Success)
  222. {
  223. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  224. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  225. ClassWithNoLoadAsset classWithNoLoadAsset;
  226. AZ::Data::AssetId testAssetId("{CAAC5458-0738-43F6-A2BD-4E315C64BFD3}", 71);
  227. classWithNoLoadAsset.m_asset = AZ::Data::Asset<AZ::Data::AssetData>(
  228. testAssetId,
  229. azrtti_typeid<AZ::Data::AssetData>());
  230. classWithNoLoadAsset.m_asset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::NoLoad);
  231. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithNoLoadAsset, productDependencies, productPathDependencySet);
  232. ASSERT_TRUE(gatherResult);
  233. ASSERT_EQ(productDependencies.size(), 1);
  234. auto behaviorFromFlags = AZ::Data::ProductDependencyInfo::LoadBehaviorFromFlags(productDependencies[0].m_flags);
  235. ASSERT_EQ(behaviorFromFlags, AZ::Data::AssetLoadBehavior::NoLoad);
  236. }
  237. TEST_F(SerializationDependenciesTests, GatherProductDependencies_HasEmptyStringSimpleAsset_NoDependencyEmitted)
  238. {
  239. AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
  240. AssetBuilderSDK::ProductPathDependencySet productPathDependencySet;
  241. ClassWithSimpleAsset classWithSimpleAsset;
  242. classWithSimpleAsset.m_simpleAsset.SetAssetPath("");
  243. bool gatherResult = AssetBuilderSDK::GatherProductDependencies(*m_serializeContext, &classWithSimpleAsset, productDependencies, productPathDependencySet);
  244. ASSERT_TRUE(gatherResult);
  245. ASSERT_EQ(productDependencies.size(), 0);
  246. ASSERT_EQ(productPathDependencySet.size(), 0);
  247. }
  248. }