SceneManifestRuleTests.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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 <SceneAPI/SceneCore/Containers/SceneManifest.h>
  10. #include <SceneAPI/SceneCore/Containers/Scene.h>
  11. #include <SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h>
  12. #include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
  13. #include <SceneAPI/SceneData/ReflectionRegistrar.h>
  14. #include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
  15. #include <SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h>
  16. #include <AzCore/Math/Quaternion.h>
  17. #include <AzCore/Name/NameDictionary.h>
  18. #include <AzCore/RTTI/BehaviorContext.h>
  19. #include <AzCore/RTTI/ReflectionManager.h>
  20. #include <AzCore/Serialization/Json/JsonSystemComponent.h>
  21. #include <AzCore/Serialization/Json/JsonUtils.h>
  22. #include <AzCore/Serialization/Json/RegistrationContext.h>
  23. #include <AzCore/std/smart_ptr/make_shared.h>
  24. #include <AzCore/std/smart_ptr/shared_ptr.h>
  25. #include <AzCore/UnitTest/Mocks/MockSettingsRegistry.h>
  26. #include <AzCore/UnitTest/TestTypes.h>
  27. #include <AzToolsFramework/API/EditorPythonConsoleBus.h>
  28. #include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
  29. #include <AzCore/UnitTest/Mocks/MockFileIOBase.h>
  30. extern "C" AZ_DLL_EXPORT void CleanUpSceneCoreGenericClassInfo();
  31. extern "C" AZ_DLL_EXPORT void CleanUpSceneDataGenericClassInfo();
  32. namespace AZ
  33. {
  34. class MockEditorPythonEventsInterface
  35. : public AzToolsFramework::EditorPythonEventsInterface
  36. {
  37. public:
  38. MOCK_METHOD1(StartPython, bool(bool));
  39. MOCK_METHOD1(StopPython, bool(bool));
  40. MOCK_METHOD0(IsPythonActive, bool());
  41. MOCK_METHOD0(WaitForInitialization, void());
  42. MOCK_METHOD1(ExecuteWithLock, void(AZStd::function<void()>));
  43. MOCK_METHOD1(TryExecuteWithLock, bool(AZStd::function<void()>));
  44. };
  45. class MockEditorPythonRunnerRequestBus
  46. : public AzToolsFramework::EditorPythonRunnerRequestBus::Handler
  47. {
  48. public:
  49. MockEditorPythonRunnerRequestBus()
  50. {
  51. AzToolsFramework::EditorPythonRunnerRequestBus::Handler::BusConnect();
  52. }
  53. ~MockEditorPythonRunnerRequestBus()
  54. {
  55. AzToolsFramework::EditorPythonRunnerRequestBus::Handler::BusDisconnect();
  56. }
  57. MOCK_METHOD2(ExecuteByString, void(AZStd::string_view, bool));
  58. MOCK_METHOD1(ExecuteByFilename, bool(AZStd::string_view));
  59. MOCK_METHOD2(ExecuteByFilenameWithArgs, bool(AZStd::string_view, const AZStd::vector<AZStd::string_view>&));
  60. MOCK_METHOD3(ExecuteByFilenameAsTest, bool(AZStd::string_view, AZStd::string_view, const AZStd::vector<AZStd::string_view>&));
  61. };
  62. using NiceEditorPythonEventsInterfaceMock = ::testing::NiceMock<MockEditorPythonEventsInterface>;
  63. using NiceMockEditorPythonRunnerRequestBus = ::testing::NiceMock<MockEditorPythonRunnerRequestBus>;
  64. using NiceMockFileIOBase = ::testing::NiceMock<AZ::IO::MockFileIOBase>;
  65. namespace SceneAPI
  66. {
  67. class MockRotationRule final
  68. : public DataTypes::IManifestObject
  69. {
  70. public:
  71. AZ_RTTI(MockRotationRule, "{90AECE4A-58D4-411C-9CDE-59B54C59354F}", DataTypes::IManifestObject);
  72. AZ_CLASS_ALLOCATOR(MockRotationRule, AZ::SystemAllocator);
  73. static void Reflect(ReflectContext* context)
  74. {
  75. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  76. if (serializeContext)
  77. {
  78. serializeContext->Class<MockRotationRule, DataTypes::IManifestObject>()
  79. ->Version(1)
  80. ->Field("rotation", &MockRotationRule::m_rotation);
  81. }
  82. }
  83. AZ::Quaternion m_rotation = AZ::Quaternion::CreateIdentity();
  84. };
  85. namespace Containers
  86. {
  87. class SceneManifestContainer
  88. {
  89. public:
  90. static AZ::Outcome<rapidjson::Document, AZStd::string> SaveToJsonDocumentHelper(
  91. SceneAPI::Containers::SceneManifest& manifest,
  92. SerializeContext* context,
  93. JsonRegistrationContext* registrationContext)
  94. {
  95. return manifest.SaveToJsonDocument(context, registrationContext);
  96. }
  97. };
  98. }
  99. }
  100. namespace SceneData
  101. {
  102. class SceneManifest_JSON
  103. : public UnitTest::LeakDetectionFixture
  104. {
  105. public:
  106. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  107. AZStd::unique_ptr<AZ::JsonRegistrationContext> m_jsonRegistrationContext;
  108. AZStd::unique_ptr<JsonSystemComponent> m_jsonSystemComponent;
  109. void SetUp() override
  110. {
  111. UnitTest::LeakDetectionFixture::SetUp();
  112. AZ::NameDictionary::Create();
  113. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  114. AZ::SceneAPI::RegisterDataTypeReflection(m_serializeContext.get());
  115. AZ::SceneAPI::Containers::SceneManifest::Reflect(m_serializeContext.get());
  116. AZ::SceneAPI::DataTypes::IManifestObject::Reflect(m_serializeContext.get());
  117. m_serializeContext->Class<AZ::SceneAPI::DataTypes::IRule, AZ::SceneAPI::DataTypes::IManifestObject>()->Version(1);
  118. AZ::SceneAPI::MockRotationRule::Reflect(m_serializeContext.get());
  119. m_jsonRegistrationContext = AZStd::make_unique<AZ::JsonRegistrationContext>();
  120. m_jsonSystemComponent = AZStd::make_unique<JsonSystemComponent>();
  121. m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get());
  122. m_data.reset(new DataMembers);
  123. m_data->m_settings = AZStd::make_unique<AZ::NiceSettingsRegistrySimpleMock>();
  124. using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
  125. ON_CALL(*m_data->m_settings, Get(::testing::Matcher<FixedValueString&>(::testing::_), testing::_))
  126. .WillByDefault([](FixedValueString& value, AZStd::string_view) -> bool
  127. {
  128. value = "mock_path";
  129. return true;
  130. });
  131. AZ::SettingsRegistry::Register(m_data->m_settings.get());
  132. SetupFileBaseIO();
  133. }
  134. void TearDown() override
  135. {
  136. TeardownFileBaseIO();
  137. if (m_data->m_editorPythonEventsInterfacePrepared)
  138. {
  139. Interface<AzToolsFramework::EditorPythonEventsInterface>::Unregister(&m_data->m_editorPythonEventsInterface);
  140. }
  141. m_jsonRegistrationContext->EnableRemoveReflection();
  142. m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get());
  143. m_jsonRegistrationContext->DisableRemoveReflection();
  144. m_serializeContext.reset();
  145. m_jsonRegistrationContext.reset();
  146. m_jsonSystemComponent.reset();
  147. if (m_data->m_settings)
  148. {
  149. AZ::SettingsRegistry::Unregister(m_data->m_settings.get());
  150. m_data->m_settings.reset();
  151. }
  152. m_data.reset();
  153. CleanUpSceneCoreGenericClassInfo();
  154. CleanUpSceneDataGenericClassInfo();
  155. AZ::NameDictionary::Destroy();
  156. UnitTest::LeakDetectionFixture::TearDown();
  157. }
  158. void PrepareMockPythonInterface()
  159. {
  160. ON_CALL(m_data->m_editorPythonEventsInterface, StartPython(::testing::_)).WillByDefault(::testing::Return(true));
  161. ON_CALL(m_data->m_editorPythonEventsInterface, StopPython(::testing::_)).WillByDefault(::testing::Return(true));
  162. ON_CALL(m_data->m_editorPythonEventsInterface, IsPythonActive()).WillByDefault(::testing::Return(true));
  163. ON_CALL(m_data->m_editorPythonEventsInterface, ExecuteWithLock(::testing::_))
  164. .WillByDefault([](auto callback)
  165. {
  166. callback();
  167. });
  168. ON_CALL(m_data->m_editorPythonEventsInterface, TryExecuteWithLock(::testing::_))
  169. .WillByDefault([](auto callback) -> bool
  170. {
  171. callback();
  172. return true;
  173. });
  174. Interface<AzToolsFramework::EditorPythonEventsInterface>::Register(&m_data->m_editorPythonEventsInterface);
  175. m_data->m_editorPythonEventsInterfacePrepared = true;
  176. }
  177. void SetupFileBaseIO()
  178. {
  179. m_data->m_fileIOMock = AZStd::make_unique<NiceMockFileIOBase>();
  180. m_data->m_prevFileIO = IO::FileIOBase::GetInstance();
  181. IO::FileIOBase::SetInstance(nullptr);
  182. IO::FileIOBase::SetInstance(m_data->m_fileIOMock.get());
  183. }
  184. void TeardownFileBaseIO()
  185. {
  186. if (m_data->m_fileIOMock)
  187. {
  188. IO::FileIOBase::SetInstance(nullptr);
  189. IO::FileIOBase::SetInstance(m_data->m_prevFileIO);
  190. m_data->m_fileIOMock.reset();
  191. }
  192. }
  193. struct DataMembers
  194. {
  195. NiceMockEditorPythonRunnerRequestBus m_niceMockEditorPythonRunnerRequestBus;
  196. AZStd::unique_ptr<NiceSettingsRegistrySimpleMock> m_settings;
  197. NiceEditorPythonEventsInterfaceMock m_editorPythonEventsInterface;
  198. bool m_editorPythonEventsInterfacePrepared = false;
  199. AZStd::unique_ptr<NiceMockFileIOBase> m_fileIOMock;
  200. IO::FileIOBase* m_prevFileIO = nullptr;
  201. };
  202. AZStd::unique_ptr<DataMembers> m_data;
  203. };
  204. TEST_F(SceneManifest_JSON, LoadFromString_BlankManifest_HasDefaultParts)
  205. {
  206. SceneAPI::Containers::SceneManifest sceneManifest;
  207. sceneManifest.LoadFromString("{}", m_serializeContext.get(), m_jsonRegistrationContext.get(), false);
  208. }
  209. TEST_F(SceneManifest_JSON, LoadFromString_LoadRotationRuleWithQuaternion_ReturnsTrue)
  210. {
  211. using namespace SceneAPI::Containers;
  212. SceneManifest sceneManifest;
  213. auto anglesInDegrees = AZ::Vector3(45.0f, 90.0f, 45.0f);
  214. auto originRule = AZStd::make_shared<AZ::SceneAPI::MockRotationRule>();
  215. originRule->m_rotation = Quaternion::CreateFromEulerAnglesDegrees(anglesInDegrees);
  216. sceneManifest.AddEntry(originRule);
  217. auto writeToJsonResult = SceneManifestContainer::SaveToJsonDocumentHelper(sceneManifest, m_serializeContext.get(), m_jsonRegistrationContext.get());
  218. ASSERT_TRUE(writeToJsonResult.IsSuccess());
  219. AZStd::string jsonText;
  220. auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText);
  221. ASSERT_TRUE(writeToStringResult.IsSuccess());
  222. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "MockRotationRule")"));
  223. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("rotation": [)"));
  224. SceneManifest loaded;
  225. auto loadFromStringResult = loaded.LoadFromString(jsonText, m_serializeContext.get(), m_jsonRegistrationContext.get());
  226. EXPECT_TRUE(loadFromStringResult.IsSuccess());
  227. EXPECT_FALSE(loaded.IsEmpty());
  228. ASSERT_EQ(loaded.GetEntryCount(), sceneManifest.GetEntryCount());
  229. }
  230. TEST_F(SceneManifest_JSON, LoadFromString_LoadRotationRuleWithAnglesInDegrees_ReturnsTrue)
  231. {
  232. using namespace SceneAPI::Containers;
  233. constexpr const char* jsonWithAngles = { R"JSON(
  234. {
  235. "values": [
  236. {
  237. "$type": "MockRotationRule",
  238. "rotation": { "yaw" : 45.0, "pitch" : 90.0, "roll" : 0.0 }
  239. }
  240. ]
  241. })JSON"};
  242. SceneManifest loaded;
  243. auto loadFromStringResult = loaded.LoadFromString(jsonWithAngles, m_serializeContext.get(), m_jsonRegistrationContext.get());
  244. EXPECT_TRUE(loadFromStringResult.IsSuccess());
  245. EXPECT_FALSE(loaded.IsEmpty());
  246. auto writeToJsonResult =
  247. SceneManifestContainer::SaveToJsonDocumentHelper(loaded, m_serializeContext.get(), m_jsonRegistrationContext.get());
  248. ASSERT_TRUE(writeToJsonResult.IsSuccess());
  249. AZStd::string jsonText;
  250. auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText);
  251. ASSERT_TRUE(writeToStringResult.IsSuccess());
  252. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "MockRotationRule")"));
  253. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("rotation": [)"));
  254. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(0.27)"));
  255. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(0.65)"));
  256. }
  257. TEST_F(SceneManifest_JSON, LoadFromString_CoordinateSystemRule_ReturnsTrue)
  258. {
  259. AZ::SceneAPI::SceneData::CoordinateSystemRule foo;
  260. EXPECT_FALSE(foo.GetUseAdvancedData());
  261. using namespace SceneAPI::Containers;
  262. constexpr const char* jsonCoordinateSystemRule = { R"JSON(
  263. {
  264. "values": [
  265. {
  266. "$type": "CoordinateSystemRule",
  267. "useAdvancedData": true,
  268. "originNodeName": "test_origin_name",
  269. "translation": [1.0, 2.0, 3.0],
  270. "rotation": { "yaw" : 45.0, "pitch" : 18.5, "roll" : 215.0 },
  271. "scale": 10.0
  272. }
  273. ]
  274. })JSON" };
  275. SceneManifest loaded;
  276. auto loadFromStringResult = loaded.LoadFromString(jsonCoordinateSystemRule, m_serializeContext.get(), m_jsonRegistrationContext.get());
  277. EXPECT_TRUE(loadFromStringResult.IsSuccess());
  278. EXPECT_FALSE(loaded.IsEmpty());
  279. auto writeToJsonResult =
  280. SceneManifestContainer::SaveToJsonDocumentHelper(loaded, m_serializeContext.get(), m_jsonRegistrationContext.get());
  281. ASSERT_TRUE(writeToJsonResult.IsSuccess());
  282. AZStd::string jsonText;
  283. auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText);
  284. ASSERT_TRUE(writeToStringResult.IsSuccess());
  285. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "CoordinateSystemRule")"));
  286. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("useAdvancedData": true,)"));
  287. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("originNodeName": "test_origin_name",)"));
  288. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("rotation": [)"));
  289. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(0.028)"));
  290. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(-0.40)"));
  291. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(0.85)"));
  292. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(-0.33)"));
  293. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("translation": [)"));
  294. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(1.0)"));
  295. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(2.0)"));
  296. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"(3.0)"));
  297. EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("scale": 10.0)"));
  298. }
  299. TEST_F(SceneManifest_JSON, ScriptProcessorRule_LoadWithEmptyScriptFilename_ReturnsEarly)
  300. {
  301. using namespace SceneAPI::Containers;
  302. using namespace SceneAPI::Events;
  303. constexpr const char* jsonManifest = { R"JSON(
  304. {
  305. "values": [
  306. {
  307. "$type": "ScriptProcessorRule",
  308. "scriptFilename": ""
  309. }
  310. ]
  311. })JSON" };
  312. auto scene = AZ::SceneAPI::Containers::Scene("mock");
  313. scene.SetManifestFilename("mock.fake.assetinfo");
  314. auto result = scene.GetManifest().LoadFromString(jsonManifest, m_serializeContext.get(), m_jsonRegistrationContext.get());
  315. EXPECT_TRUE(result.IsSuccess());
  316. EXPECT_FALSE(scene.GetManifest().IsEmpty());
  317. auto scriptProcessorRuleBehavior = AZ::SceneAPI::Behaviors::ScriptProcessorRuleBehavior();
  318. scriptProcessorRuleBehavior.Activate();
  319. auto update = scriptProcessorRuleBehavior.UpdateManifest(scene, AssetImportRequest::Update, AssetImportRequest::Generic);
  320. scriptProcessorRuleBehavior.Deactivate();
  321. EXPECT_EQ(update, ProcessingResult::Ignored);
  322. }
  323. TEST_F(SceneManifest_JSON, ScriptProcessorRule_DefaultFallbackLogic_Works)
  324. {
  325. using namespace AZ::SceneAPI;
  326. constexpr const char* defaultJson = { R"JSON(
  327. {
  328. "values": [
  329. {
  330. "$type": "ScriptProcessorRule",
  331. "scriptFilename": "foo.py"
  332. }
  333. ]
  334. })JSON" };
  335. auto scene = Containers::Scene("mock");
  336. scene.SetManifestFilename("mock.fake.assetinfo");
  337. auto result = scene.GetManifest().LoadFromString(defaultJson, m_serializeContext.get(), m_jsonRegistrationContext.get());
  338. EXPECT_TRUE(result.IsSuccess());
  339. EXPECT_FALSE(scene.GetManifest().IsEmpty());
  340. ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1);
  341. auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(scene.GetManifest().GetValueStorage());
  342. EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::FailBuild);
  343. }
  344. TEST_F(SceneManifest_JSON, ScriptProcessorRule_ExplicitFallbackLogic_Works)
  345. {
  346. using namespace AZ::SceneAPI;
  347. constexpr const char* fallbackLogicJson = { R"JSON(
  348. {
  349. "values": [
  350. {
  351. "$type": "ScriptProcessorRule",
  352. "scriptFilename": "foo.py",
  353. "fallbackLogic": "FailBuild"
  354. }
  355. ]
  356. })JSON" };
  357. auto scene = Containers::Scene("mock");
  358. scene.SetManifestFilename("mock.fake.assetinfo");
  359. auto result = scene.GetManifest().LoadFromString(fallbackLogicJson, m_serializeContext.get(), m_jsonRegistrationContext.get());
  360. EXPECT_TRUE(result.IsSuccess());
  361. EXPECT_FALSE(scene.GetManifest().IsEmpty());
  362. ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1);
  363. auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(scene.GetManifest().GetValueStorage());
  364. EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::FailBuild);
  365. }
  366. TEST_F(SceneManifest_JSON, ScriptProcessorRule_ContinueBuildFallbackLogic_Works)
  367. {
  368. using namespace AZ::SceneAPI;
  369. constexpr const char* fallbackLogicJson = { R"JSON(
  370. {
  371. "values": [
  372. {
  373. "$type": "ScriptProcessorRule",
  374. "scriptFilename": "foo.py",
  375. "fallbackLogic": "ContinueBuild"
  376. }
  377. ]
  378. })JSON" };
  379. auto scene = Containers::Scene("mock");
  380. scene.SetManifestFilename("mock.fake.assetinfo");
  381. auto result = scene.GetManifest().LoadFromString(fallbackLogicJson, m_serializeContext.get(), m_jsonRegistrationContext.get());
  382. EXPECT_TRUE(result.IsSuccess());
  383. EXPECT_FALSE(scene.GetManifest().IsEmpty());
  384. ASSERT_EQ(scene.GetManifest().GetEntryCount(), 1);
  385. auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(scene.GetManifest().GetValueStorage());
  386. EXPECT_EQ(view.begin()->GetScriptProcessorFallbackLogic(), DataTypes::ScriptProcessorFallbackLogic::ContinueBuild);
  387. }
  388. TEST_F(SceneManifest_JSON, ScriptProcessorRule_ScriptLogic_CallsIntoPythonInterface)
  389. {
  390. using namespace SceneAPI::Containers;
  391. using namespace SceneAPI::Events;
  392. constexpr const char* jsonManifest = { R"JSON(
  393. {
  394. "values": [
  395. {
  396. "$type": "ScriptProcessorRule",
  397. "scriptFilename": "mock_update_manifest.py"
  398. }
  399. ]
  400. })JSON" };
  401. PrepareMockPythonInterface();
  402. EXPECT_CALL(m_data->m_editorPythonEventsInterface, IsPythonActive()).Times(1);
  403. EXPECT_CALL(m_data->m_editorPythonEventsInterface, ExecuteWithLock(testing::_)).Times(1);
  404. ON_CALL(*m_data->m_fileIOMock.get(), Exists(::testing::_))
  405. .WillByDefault([](const char*) -> bool
  406. {
  407. return true;
  408. }
  409. );
  410. EXPECT_CALL(*m_data->m_fileIOMock.get(), Exists(testing::_)).Times(1);
  411. bool executeByFilenameCalled = false;
  412. ON_CALL(m_data->m_niceMockEditorPythonRunnerRequestBus, ExecuteByFilename(::testing::_))
  413. .WillByDefault([&executeByFilenameCalled](AZStd::string_view)
  414. {
  415. executeByFilenameCalled = true;
  416. return true;
  417. }
  418. );
  419. EXPECT_CALL(m_data->m_niceMockEditorPythonRunnerRequestBus, ExecuteByFilename(testing::_)).Times(1);
  420. auto scene = AZ::SceneAPI::Containers::Scene("mock");
  421. scene.SetManifestFilename("mock.fake.assetinfo");
  422. auto result = scene.GetManifest().LoadFromString(jsonManifest, m_serializeContext.get(), m_jsonRegistrationContext.get());
  423. EXPECT_TRUE(result.IsSuccess());
  424. EXPECT_FALSE(scene.GetManifest().IsEmpty());
  425. auto scriptProcessorRuleBehavior = AZ::SceneAPI::Behaviors::ScriptProcessorRuleBehavior();
  426. scriptProcessorRuleBehavior.Activate();
  427. scriptProcessorRuleBehavior.UpdateManifest(scene, AssetImportRequest::Update, AssetImportRequest::Generic);
  428. scriptProcessorRuleBehavior.Deactivate();
  429. EXPECT_TRUE(executeByFilenameCalled);
  430. }
  431. TEST_F(SceneManifest_JSON, ScriptProcessorRule_EditorPythonEventsInterface_RunsWithEditorPythonEventsInterfaceCleared)
  432. {
  433. using namespace SceneAPI::Containers;
  434. using namespace SceneAPI::Events;
  435. constexpr const char* jsonManifest = { R"JSON(
  436. {
  437. "values": [
  438. {
  439. "$type": "ScriptProcessorRule",
  440. "scriptFilename": ""
  441. }
  442. ]
  443. })JSON" };
  444. PrepareMockPythonInterface();
  445. EXPECT_CALL(m_data->m_editorPythonEventsInterface, IsPythonActive()).Times(1);
  446. EXPECT_CALL(m_data->m_editorPythonEventsInterface, StartPython(testing::_)).Times(0);
  447. EXPECT_CALL(m_data->m_editorPythonEventsInterface, StopPython(testing::_)).Times(1);
  448. auto scene = AZ::SceneAPI::Containers::Scene("mock");
  449. scene.SetManifestFilename("mock.fake.assetinfo");
  450. scene.GetManifest().LoadFromString(jsonManifest, m_serializeContext.get(), m_jsonRegistrationContext.get());
  451. auto scriptProcessorRuleBehavior = AZ::SceneAPI::Behaviors::ScriptProcessorRuleBehavior();
  452. scriptProcessorRuleBehavior.Activate();
  453. auto update = scriptProcessorRuleBehavior.UpdateManifest(scene, AssetImportRequest::Update, AssetImportRequest::Generic);
  454. EXPECT_EQ(update, ProcessingResult::Ignored);
  455. AZ::SettingsRegistry::Unregister(m_data->m_settings.get());
  456. m_data->m_settings.reset();
  457. scriptProcessorRuleBehavior.Deactivate();
  458. }
  459. }
  460. }