AssetUtils.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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/std/containers/unordered_map.h>
  9. #include <AzCore/std/functional.h>
  10. #include <AzCore/std/utils.h>
  11. #include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
  12. #include <AzCore/UnitTest/TestTypes.h>
  13. #include <AzFramework/StringFunc/StringFunc.h>
  14. #include <AzToolsFramework/Application/ToolsApplication.h>
  15. #include <AzToolsFramework/Asset/AssetUtils.h>
  16. #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
  17. namespace //anonymous
  18. {
  19. const char DummyProjectName[] = "DummyProject";
  20. const char GemsFolder[] = "Gems";
  21. const char GemAName[] = "GemA";
  22. const char GemBName[] = "GemB";
  23. const char GemCName[] = "GemC";
  24. constexpr int TotalNumberFiles = 5;
  25. const char* FileNames[TotalNumberFiles] = { "gems.json" , "project.json" , "gem.json", "gem.json" , "gem.json" };
  26. const int FileHandles[TotalNumberFiles] = { 1111, 2222, 3333, 4444, 5555 };
  27. const int GemsIdx = 0;
  28. const int ProjectIdx = 1;
  29. const int GemAGemIdx = 2;
  30. const int GemBGemIdx = 3;
  31. const int GemCGemIdx = 4;
  32. const char GemsFileContent[] = R"({
  33. "GemListFormatVersion": 2,
  34. "Gems" : [
  35. {
  36. "Path": "Gems/GemA",
  37. "Uuid" : "044a63ea67d04479aa5daf62ded9d9cb",
  38. "Version" : "0.1.0",
  39. "_comment" : "GemA"
  40. },
  41. {
  42. "Path": "Gems/GemB",
  43. "Uuid" : "07375b61b1a2424bb03088bbdf28b2c9",
  44. "Version" : "0.1.0",
  45. "_comment" : "GemB"
  46. },
  47. {
  48. "Path": "Gems/GemC",
  49. "Uuid" : "0945e21b7ae848ac80b4ec1f34c459cd",
  50. "Version" : "0.1.0",
  51. "_comment" : "GemC"
  52. }
  53. ]
  54. })";
  55. const char ProjectFileContent[] = R"({
  56. "project_name": "DummyProject",
  57. "product_name": "DummyProject",
  58. "executable_name": "DummyProjectLauncher",
  59. "modules" : [],
  60. "project_id": "{91FB81A1-072C-4A80-8FCC-7E2C4C767B4D}",
  61. })";
  62. const char GemAGemFileContent[] = R"({
  63. "GemFormatVersion": 4,
  64. "Uuid": "044A63EA67D04479AA5DAF62DED9D9CB",
  65. "Name": "GemA",
  66. "DisplayName": "GemA",
  67. "Version": "0.1.0",
  68. "Summary": "Only for unit test purposes.",
  69. "Tags": ["Foo"],
  70. "IconPath": "preview.png",
  71. "EditorModule": true
  72. })";
  73. const char GemBGemFileContent[] = R"({
  74. "GemFormatVersion": 4,
  75. "Uuid": "07375B61B1A2424BB03088BBDF28B2C9",
  76. "Name": "GemB",
  77. "DisplayName": "GemB",
  78. "Version": "0.1.0",
  79. "Summary": "Only for unit test purposes.",
  80. "Tags": ["Foo"],
  81. "IconPath": "preview.png",
  82. "EditorModule": true
  83. })";
  84. const char GemCGemFileContent[] = R"({
  85. "GemFormatVersion": 4,
  86. "Uuid" : "0945E21B7AE848AC80B4EC1F34C459CD",
  87. "Name" : "GemC",
  88. "DisplayName" : "GemC",
  89. "Version" : "0.1.0",
  90. "Summary" : "Only for unit test purposes.",
  91. "Tags" : ["Foo"],
  92. "IconPath" : "preview.png",
  93. "EditorModule" : true
  94. })";
  95. const char* FileContents[TotalNumberFiles] = { GemsFileContent , ProjectFileContent, GemAGemFileContent, GemBGemFileContent, GemCGemFileContent };
  96. }
  97. namespace UnitTest
  98. {
  99. using ::testing::NiceMock;
  100. using ::testing::_;
  101. using ::testing::Return;
  102. class MockFileIO
  103. : public AZ::IO::MockFileIOBase
  104. {
  105. public:
  106. MockFileIO()
  107. {
  108. PopulateData();
  109. SetupMocks();
  110. }
  111. void PopulateData()
  112. {
  113. AZStd::string gemsSettingsFilePath;
  114. AzFramework::StringFunc::Path::Join(DummyProjectName, FileNames[GemsIdx], gemsSettingsFilePath);
  115. m_fileHandleContentMap[AZ::Uuid::CreateName(gemsSettingsFilePath.c_str())] = AZStd::make_pair(FileHandles[GemsIdx], FileContents[GemsIdx]);
  116. AZStd::string projectSettingsFilePath;
  117. AzFramework::StringFunc::Path::Join(DummyProjectName, FileNames[ProjectIdx], projectSettingsFilePath);
  118. m_fileHandleContentMap[AZ::Uuid::CreateName(projectSettingsFilePath.c_str())] = AZStd::make_pair(FileHandles[ProjectIdx], FileContents[ProjectIdx]);
  119. AZStd::string gemAGemFilePath;
  120. AzFramework::StringFunc::Path::Join(GemsFolder, GemAName, gemAGemFilePath);
  121. AzFramework::StringFunc::Path::Join(gemAGemFilePath.c_str(), FileNames[GemAGemIdx], gemAGemFilePath);
  122. m_fileHandleContentMap[AZ::Uuid::CreateName(gemAGemFilePath.c_str())] = AZStd::make_pair(FileHandles[GemAGemIdx], FileContents[GemAGemIdx]);
  123. AZStd::string gemBGemFilePath;
  124. AzFramework::StringFunc::Path::Join(GemsFolder, GemBName, gemBGemFilePath);
  125. AzFramework::StringFunc::Path::Join(gemBGemFilePath.c_str(), FileNames[GemBGemIdx], gemBGemFilePath);
  126. m_fileHandleContentMap[AZ::Uuid::CreateName(gemBGemFilePath.c_str())] = AZStd::make_pair(FileHandles[GemBGemIdx], FileContents[GemBGemIdx]);
  127. AZStd::string gemCGemFilePath;
  128. AzFramework::StringFunc::Path::Join(GemsFolder, GemCName, gemCGemFilePath);
  129. AzFramework::StringFunc::Path::Join(gemCGemFilePath.c_str(), FileNames[GemCGemIdx], gemCGemFilePath);
  130. m_fileHandleContentMap[AZ::Uuid::CreateName(gemCGemFilePath.c_str())] = AZStd::make_pair(FileHandles[GemCGemIdx], FileContents[GemCGemIdx]);
  131. }
  132. void SetupMocks()
  133. {
  134. ON_CALL(*this, Open(_, _, _)).WillByDefault(testing::Invoke(
  135. [&](const char* filePath, AZ::IO::OpenMode mode, AZ::IO::HandleType& fileHandle)
  136. {
  137. auto found = m_fileHandleContentMap.find(AZ::Uuid::CreateName(filePath));
  138. if (found == m_fileHandleContentMap.end())
  139. {
  140. return AZ::IO::Result(AZ::IO::ResultCode::Error);
  141. }
  142. fileHandle = found->second.first;
  143. return AZ::IO::Result(AZ::IO::ResultCode::Success);
  144. }
  145. ));
  146. ON_CALL(*this, Read(_, _, _, _, _)).WillByDefault(testing::Invoke(
  147. [&](AZ::IO::HandleType fileHandle, void* buffer, AZ::u64 size, bool failOnFewerThanSizeBytesRead, AZ::u64* bytesRead)
  148. {
  149. for (auto iter = m_fileHandleContentMap.begin(); iter != m_fileHandleContentMap.end(); iter++)
  150. {
  151. if (iter->second.first == fileHandle)
  152. {
  153. memcpy(buffer, iter->second.second.c_str(), iter->second.second.length() + 1);
  154. return AZ::IO::Result(AZ::IO::ResultCode::Success);
  155. }
  156. }
  157. return AZ::IO::Result(AZ::IO::ResultCode::Error);
  158. }
  159. ));
  160. ON_CALL(*this, Size(testing::Matcher<AZ::IO::HandleType>(_), testing::Matcher<AZ::u64&>(_))).WillByDefault(testing::Invoke(
  161. [&](AZ::IO::HandleType fileHandle, AZ::u64& size)
  162. {
  163. for (auto iter = m_fileHandleContentMap.begin(); iter != m_fileHandleContentMap.end(); iter++)
  164. {
  165. if (iter->second.first == fileHandle)
  166. {
  167. size = iter->second.second.length();
  168. return AZ::IO::Result(AZ::IO::ResultCode::Success);
  169. }
  170. }
  171. return AZ::IO::Result(AZ::IO::ResultCode::Error);
  172. }
  173. ));
  174. ON_CALL(*this, Exists(_)).WillByDefault(testing::Invoke(
  175. [&](const char* filePath)
  176. {
  177. auto found = m_fileHandleContentMap.find(AZ::Uuid::CreateName(filePath));
  178. if (found == m_fileHandleContentMap.end())
  179. {
  180. return false;
  181. }
  182. return true;
  183. }
  184. ));
  185. ON_CALL(*this, Close(_))
  186. .WillByDefault(
  187. Return(AZ::IO::Result(AZ::IO::ResultCode::Success)));
  188. }
  189. AZStd::unordered_map<AZ::Uuid, AZStd::pair<AZ::IO::HandleType, AZStd::string>> m_fileHandleContentMap;
  190. };
  191. class AssetUtilitiesGemsTest
  192. : public ::testing::Test
  193. {
  194. public:
  195. void SetUp() override
  196. {
  197. m_data = AZStd::make_unique<StaticData>();
  198. m_data->m_priorFileIO = AZ::IO::FileIOBase::GetInstance();
  199. m_data->m_application.reset(aznew AzToolsFramework::ToolsApplication);
  200. m_data->m_application->Start(AzFramework::Application::Descriptor());
  201. m_data->m_localFileIO = new ::testing::NiceMock<MockFileIO>();
  202. AZ::IO::FileIOBase::SetInstance(nullptr);
  203. AZ::IO::FileIOBase::SetInstance(m_data->m_localFileIO);
  204. }
  205. void TearDown() override
  206. {
  207. delete m_data->m_localFileIO;
  208. AZ::IO::FileIOBase::SetInstance(m_data->m_priorFileIO);
  209. m_data->m_application->Stop();
  210. m_data->m_application.reset();
  211. m_data.reset();
  212. }
  213. struct StaticData
  214. {
  215. AZStd::unique_ptr<MockFileIO> m_fileIO;
  216. AZStd::string m_testEngineRoot;
  217. AZStd::unique_ptr<AzToolsFramework::ToolsApplication> m_application = {};
  218. AZStd::vector<AzToolsFramework::AssetUtils::GemInfo> m_gemInfoList;
  219. AZ::IO::FileIOBase* m_priorFileIO = nullptr;
  220. AZ::IO::FileIOBase* m_localFileIO = nullptr;
  221. };
  222. AZStd::unique_ptr<StaticData> m_data;
  223. };
  224. TEST_F(AssetUtilitiesGemsTest, GemSystem_RetreiveGemsList_OK)
  225. {
  226. AzToolsFramework::AssetUtils::GetGemsInfo(m_data->m_testEngineRoot.c_str(), m_data->m_testEngineRoot.c_str(), DummyProjectName, m_data->m_gemInfoList);
  227. EXPECT_EQ(m_data->m_gemInfoList.size(), 3);
  228. AZStd::unordered_set<AZStd::string> gemsNameMap{ "GemA", "GemB", "GemC" };
  229. for (const AzToolsFramework::AssetUtils::GemInfo& gemInfo : m_data->m_gemInfoList)
  230. {
  231. gemsNameMap.erase(gemInfo.m_gemName);
  232. }
  233. ASSERT_EQ(gemsNameMap.size(), 0);
  234. }
  235. }