PlatformAddressedAssetCatalogTests.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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/Settings/SettingsRegistryImpl.h>
  9. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  10. #include <AzCore/UnitTest/TestTypes.h>
  11. #include <AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalogManager.h>
  12. #include <AzFramework/Asset/AssetRegistry.h>
  13. #include <AzCore/Interface/Interface.h>
  14. #include <AzCore/IO/FileIO.h>
  15. #include <AzFramework/IO/LocalFileIO.h>
  16. #include <Tests/AZTestShared/Utils/Utils.h>
  17. #include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
  18. #include <AzFramework/Platform/PlatformDefaults.h>
  19. #include <AzFramework/StringFunc/StringFunc.h>
  20. #include <AzTest/AzTest.h>
  21. #include <AzCore/UserSettings/UserSettingsComponent.h>
  22. #include <Utils/Utils.h>
  23. namespace
  24. {
  25. static const int s_totalAssets = 12;
  26. }
  27. namespace UnitTest
  28. {
  29. class PlatformAddressedAssetCatalogManagerTest
  30. : public AllocatorsFixture
  31. {
  32. public:
  33. void SetUp() override
  34. {
  35. using namespace AZ::Data;
  36. constexpr size_t MaxCommandArgsCount = 128;
  37. using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
  38. using ArgumentContainer = AZStd::fixed_vector<char*, MaxCommandArgsCount>;
  39. // The first command line argument is assumed to be the executable name so add a blank entry for it
  40. ArgumentContainer argContainer{ {} };
  41. // Append Command Line override for the Project Cache Path
  42. AZ::IO::Path cacheProjectRootFolder{ m_tempDir.GetDirectory() };
  43. auto projectCachePathOverride = FixedValueString::format(R"(--project-cache-path="%s")", cacheProjectRootFolder.c_str());
  44. auto projectPathOverride = FixedValueString{ R"(--project-path=AutomatedTesting)" };
  45. argContainer.push_back(projectCachePathOverride.data());
  46. argContainer.push_back(projectPathOverride.data());
  47. m_application = new ToolsTestApplication("AddressedAssetCatalogManager", aznumeric_caster(argContainer.size()), argContainer.data());
  48. m_application->Start(AzFramework::Application::Descriptor());
  49. // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
  50. // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
  51. // in the unit tests.
  52. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
  53. // By default @products@ is setup to include the platform at the end. But this test is going to
  54. // loop over all platforms and it will be included as part of the relative path of the file.
  55. // So the asset folder for these tests have to point to the cache project root folder, which
  56. // doesn't include the platform.
  57. AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
  58. for (int platformNum = AzFramework::PlatformId::PC; platformNum < AzFramework::PlatformId::NumPlatformIds; ++platformNum)
  59. {
  60. const AZStd::string platformName{ AzFramework::PlatformHelper::GetPlatformName(static_cast<AzFramework::PlatformId>(platformNum)) };
  61. if (!platformName.length())
  62. {
  63. // Do not test disabled platforms
  64. continue;
  65. }
  66. AZStd::unique_ptr<AzFramework::AssetRegistry> assetRegistry = AZStd::make_unique<AzFramework::AssetRegistry>();
  67. for (int idx = 0; idx < s_totalAssets; idx++)
  68. {
  69. m_assets[platformNum][idx] = AssetId(AZ::Uuid::CreateRandom(), 0);
  70. AZ::Data::AssetInfo info;
  71. info.m_relativePath = AZStd::move((AZ::IO::Path(platformName) / AZStd::string::format("Asset%d.txt", idx)).Native());
  72. info.m_assetId = m_assets[platformNum][idx];
  73. assetRegistry->RegisterAsset(m_assets[platformNum][idx], info);
  74. m_assetsPath[platformNum][idx] = AZStd::move((cacheProjectRootFolder / info.m_relativePath).Native());
  75. AZ_TEST_START_TRACE_SUPPRESSION;
  76. if (m_fileStreams[platformNum][idx].Open(m_assetsPath[platformNum][idx].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath))
  77. {
  78. AZ::IO::SizeType bytesWritten = m_fileStreams[platformNum][idx].Write(info.m_relativePath.size(), info.m_relativePath.data());
  79. EXPECT_EQ(bytesWritten, info.m_relativePath.size());
  80. m_fileStreams[platformNum][idx].Close();
  81. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // writing to asset cache folder
  82. }
  83. else
  84. {
  85. GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to create temporary file ( %s ) in PlatformAddressedAssetCatalogManagerTest unit tests.\n", m_assetsPath[platformNum][idx].c_str()).c_str());
  86. }
  87. }
  88. bool useRequestBus = false;
  89. AzFramework::AssetCatalog assetCatalog(useRequestBus);
  90. AZStd::string catalogPath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(static_cast<AzFramework::PlatformId>(platformNum));
  91. if (!assetCatalog.SaveCatalog(catalogPath.c_str(), assetRegistry.get()))
  92. {
  93. GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to save the asset catalog file.\n").c_str());
  94. }
  95. }
  96. m_PlatformAddressedAssetCatalogManager = new AzToolsFramework::PlatformAddressedAssetCatalogManager();
  97. }
  98. void TearDown() override
  99. {
  100. delete m_PlatformAddressedAssetCatalogManager;
  101. m_application->Stop();
  102. delete m_application;
  103. }
  104. AzToolsFramework::PlatformAddressedAssetCatalogManager* m_PlatformAddressedAssetCatalogManager = nullptr;
  105. ToolsTestApplication* m_application = nullptr;
  106. UnitTest::ScopedTemporaryDirectory m_tempDir;
  107. AZ::IO::FileIOStream m_fileStreams[AzFramework::PlatformId::NumPlatformIds][s_totalAssets];
  108. AZ::Data::AssetId m_assets[AzFramework::PlatformId::NumPlatformIds][s_totalAssets];
  109. AZStd::string m_assetsPath[AzFramework::PlatformId::NumPlatformIds][s_totalAssets];
  110. };
  111. TEST_F(PlatformAddressedAssetCatalogManagerTest, PlatformAddressedAssetCatalogManager_AllCatalogsLoaded_Success)
  112. {
  113. for (int platformNum = AzFramework::PlatformId::PC; platformNum < AzFramework::PlatformId::NumPlatformIds; ++platformNum)
  114. {
  115. AZStd::string platformName{ AzFramework::PlatformHelper::GetPlatformName(static_cast<AzFramework::PlatformId>(platformNum)) };
  116. if (!platformName.length())
  117. {
  118. // Do not test disabled platforms
  119. continue;
  120. }
  121. for (int assetNum = 0; assetNum < s_totalAssets; ++assetNum)
  122. {
  123. AZ::Data::AssetInfo assetInfo;
  124. AzToolsFramework::AssetCatalog::PlatformAddressedAssetCatalogRequestBus::EventResult(assetInfo, static_cast<AzFramework::PlatformId>(platformNum), &AZ::Data::AssetCatalogRequests::GetAssetInfoById, m_assets[platformNum][assetNum]);
  125. EXPECT_EQ(m_assets[platformNum][assetNum], assetInfo.m_assetId);
  126. }
  127. }
  128. }
  129. TEST_F(PlatformAddressedAssetCatalogManagerTest, PlatformAddressedAssetCatalogManager_CatalogExistsChecks_Success)
  130. {
  131. EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ANDROID_ID), true);
  132. AZStd::string androidCatalogPath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ANDROID_ID);
  133. if (AZ::IO::FileIOBase::GetInstance()->Exists(androidCatalogPath.c_str()))
  134. {
  135. AZ_TEST_START_TRACE_SUPPRESSION;
  136. AZ::IO::Result result = AZ::IO::FileIOBase::GetInstance()->Remove(androidCatalogPath.c_str());
  137. EXPECT_EQ(result.GetResultCode(), AZ::IO::ResultCode::Success);
  138. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // removing from asset cache folder
  139. }
  140. EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ANDROID_ID), false);
  141. }
  142. class PlatformAddressedAssetCatalogMessageTest : public AzToolsFramework::PlatformAddressedAssetCatalog
  143. {
  144. public:
  145. PlatformAddressedAssetCatalogMessageTest(AzFramework::PlatformId platformId) : AzToolsFramework::PlatformAddressedAssetCatalog(platformId)
  146. {
  147. }
  148. MOCK_METHOD1(AssetChanged, void(AzFramework::AssetSystem::AssetNotificationMessage message));
  149. MOCK_METHOD1(AssetRemoved, void(AzFramework::AssetSystem::AssetNotificationMessage message));
  150. };
  151. class PlatformAddressedAssetCatalogManagerMessageTest : public AzToolsFramework::PlatformAddressedAssetCatalogManager
  152. {
  153. public:
  154. PlatformAddressedAssetCatalogManagerMessageTest(AzFramework::PlatformId platformId) :
  155. AzToolsFramework::PlatformAddressedAssetCatalogManager(AzFramework::PlatformId::Invalid)
  156. {
  157. TakeSingleCatalog(AZStd::make_unique<PlatformAddressedAssetCatalogMessageTest>(platformId));
  158. }
  159. };
  160. class MessageTest
  161. : public AllocatorsFixture
  162. {
  163. public:
  164. void SetUp() override
  165. {
  166. constexpr size_t MaxCommandArgsCount = 128;
  167. using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
  168. using ArgumentContainer = AZStd::fixed_vector<char*, MaxCommandArgsCount>;
  169. // The first command line argument is assumed to be the executable name so add a blank entry for it
  170. ArgumentContainer argContainer{ {} };
  171. // Append Command Line override for the Project Cache Path
  172. AZ::IO::Path cacheProjectRootFolder{ m_tempDir.GetDirectory() };
  173. auto projectCachePathOverride = FixedValueString::format(R"(--project-cache-path="%s")", cacheProjectRootFolder.c_str());
  174. auto projectPathOverride = FixedValueString{ R"(--project-path=AutomatedTesting)" };
  175. argContainer.push_back(projectCachePathOverride.data());
  176. argContainer.push_back(projectPathOverride.data());
  177. m_application = new ToolsTestApplication("MessageTest", aznumeric_caster(argContainer.size()), argContainer.data());
  178. m_platformAddressedAssetCatalogManager = AZStd::make_unique<AzToolsFramework::PlatformAddressedAssetCatalogManager>(AzFramework::PlatformId::Invalid);
  179. }
  180. void TearDown() override
  181. {
  182. m_platformAddressedAssetCatalogManager.reset();
  183. delete m_application;
  184. }
  185. ToolsTestApplication* m_application = nullptr;
  186. AZStd::unique_ptr<AzToolsFramework::PlatformAddressedAssetCatalogManager> m_platformAddressedAssetCatalogManager;
  187. UnitTest::ScopedTemporaryDirectory m_tempDir;
  188. };
  189. TEST_F(MessageTest, PlatformAddressedAssetCatalogManagerMessageTest_MessagesForwarded_CountsMatch)
  190. {
  191. AzFramework::AssetSystem::AssetNotificationMessage testMessage;
  192. AzFramework::AssetSystem::NetworkAssetUpdateInterface* notificationInterface = AZ::Interface<AzFramework::AssetSystem::NetworkAssetUpdateInterface>::Get();
  193. EXPECT_NE(notificationInterface, nullptr);
  194. AZ_TEST_START_TRACE_SUPPRESSION;
  195. auto* mockCatalog = new ::testing::NiceMock<PlatformAddressedAssetCatalogMessageTest>(AzFramework::PlatformId::ANDROID_ID);
  196. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expected error not finding catalog
  197. AZStd::unique_ptr< ::testing::NiceMock<PlatformAddressedAssetCatalogMessageTest>> catalogHolder;
  198. catalogHolder.reset(mockCatalog);
  199. m_platformAddressedAssetCatalogManager->TakeSingleCatalog(AZStd::move(catalogHolder));
  200. EXPECT_CALL(*mockCatalog, AssetChanged(testing::_)).Times(0);
  201. notificationInterface->AssetChanged(testMessage);
  202. testMessage.m_platform = "android";
  203. EXPECT_CALL(*mockCatalog, AssetChanged(testing::_)).Times(1);
  204. notificationInterface->AssetChanged(testMessage);
  205. testMessage.m_platform = "pc";
  206. EXPECT_CALL(*mockCatalog, AssetChanged(testing::_)).Times(0);
  207. notificationInterface->AssetChanged(testMessage);
  208. EXPECT_CALL(*mockCatalog, AssetRemoved(testing::_)).Times(0);
  209. notificationInterface->AssetRemoved(testMessage);
  210. testMessage.m_platform = "android";
  211. EXPECT_CALL(*mockCatalog, AssetRemoved(testing::_)).Times(1);
  212. notificationInterface->AssetRemoved(testMessage);
  213. }
  214. }