/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include #include #include #include #include // Test that editor-components wrapped within a GenericComponentWrapper // are moved out of the wrapper when a slice is loaded. const char kWrappedEditorComponent[] = R"DELIMITER( )DELIMITER"; class WrappedEditorComponentTest : public UnitTest::LeakDetectionFixture { protected: void SetUp() override { AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); auto projectPathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; AZ::IO::FixedMaxPath enginePath; registry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); registry->Set(projectPathKey, (enginePath / "AutomatedTesting").Native()); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); AZ::ComponentApplication::StartupParameters startupParameters; startupParameters.m_loadSettingsRegistry = false; m_app.Start(AZ::ComponentApplication::Descriptor(), startupParameters); // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash // in the unit tests. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); m_slice.reset(AZ::Utils::LoadObjectFromBuffer(kWrappedEditorComponent, strlen(kWrappedEditorComponent) + 1)); if (m_slice) { if (m_slice->GetNewEntities().size() > 0) { m_entityFromSlice = m_slice->GetNewEntities()[0]; if (m_entityFromSlice) { if (m_entityFromSlice->GetComponents().size() > 0) { m_componentFromSlice = m_entityFromSlice->GetComponents()[0]; } } } } } void TearDown() override { m_slice.reset(); m_app.Stop(); } AzToolsFramework::ToolsApplication m_app; AZStd::unique_ptr m_slice; AZ::Entity* m_entityFromSlice = nullptr; AZ::Component* m_componentFromSlice = nullptr; }; TEST_F(WrappedEditorComponentTest, Slice_Loaded) { EXPECT_NE(m_slice.get(), nullptr); } TEST_F(WrappedEditorComponentTest, EntityFromSlice_Exists) { EXPECT_NE(m_entityFromSlice, nullptr); } TEST_F(WrappedEditorComponentTest, ComponentFromSlice_Exists) { EXPECT_NE(m_componentFromSlice, nullptr); } TEST_F(WrappedEditorComponentTest, Component_IsNotGenericComponentWrapper) { EXPECT_EQ(azrtti_cast(m_componentFromSlice), nullptr); } // The swapped component should have adopted the GenericComponentWrapper's ComponentId. TEST_F(WrappedEditorComponentTest, ComponentId_MatchesWrapperId) { EXPECT_EQ(m_componentFromSlice->GetId(), 11874523501682509824u); } static constexpr AZ::TypeId InGameOnlyComponentTypeId{ "{1D538623-2052-464F-B0DA-D000E1520333}" }; class InGameOnlyComponent : public AZ::Component { public: AZ_COMPONENT(InGameOnlyComponent, InGameOnlyComponentTypeId); void Activate() override {} void Deactivate() override {} static void Reflect(AZ::ReflectContext* reflection) { if (auto* serializeContext = azrtti_cast(reflection)) { serializeContext->Class(); if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class("InGame Only", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")); } } } }; static constexpr AZ::Uuid NoneEditorComponentTypeId{ "{AE3454BA-D785-4EE2-A55B-A089F2B2916A}" }; class NoneEditorComponent : public AZ::Component { public: AZ_COMPONENT(NoneEditorComponent, NoneEditorComponentTypeId); void Activate() override {} void Deactivate() override {} static void Reflect(AZ::ReflectContext* reflection) { if (auto* serializeContext = azrtti_cast(reflection)) { serializeContext->Class(); if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class("None Editor", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")); } } } }; class FindWrappedComponentsTest : public UnitTest::LeakDetectionFixture { public: void SetUp() override { AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); auto projectPathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; AZ::IO::FixedMaxPath enginePath; registry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); registry->Set(projectPathKey, (enginePath / "AutomatedTesting").Native()); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); AZ::ComponentApplication::StartupParameters startupParameters; startupParameters.m_loadSettingsRegistry = false; m_app.Start(AzFramework::Application::Descriptor(), startupParameters); // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash // in the unit tests. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); m_app.RegisterComponentDescriptor(InGameOnlyComponent::CreateDescriptor()); m_app.RegisterComponentDescriptor(NoneEditorComponent::CreateDescriptor()); m_entity = new AZ::Entity("Entity1"); AZ::Component* inGameOnlyComponent = nullptr; AZ::ComponentDescriptorBus::EventResult(inGameOnlyComponent, InGameOnlyComponentTypeId, &AZ::ComponentDescriptorBus::Events::CreateComponent); AZ::Component* genericComponent0 = aznew AzToolsFramework::Components::GenericComponentWrapper(inGameOnlyComponent); m_entity->AddComponent(genericComponent0); AZ::Component* noneEditorComponent = nullptr; AZ::ComponentDescriptorBus::EventResult(noneEditorComponent, NoneEditorComponentTypeId, &AZ::ComponentDescriptorBus::Events::CreateComponent); AZ::Component* genericComponent1 = aznew AzToolsFramework::Components::GenericComponentWrapper(noneEditorComponent); m_entity->AddComponent(genericComponent1); m_entity->Init(); } void TearDown() override { m_app.Stop(); } AzToolsFramework::ToolsApplication m_app; AZ::Entity* m_entity = nullptr; }; TEST_F(FindWrappedComponentsTest, found) { InGameOnlyComponent* ingameOnlyComponent = AzToolsFramework::FindWrappedComponentForEntity(m_entity); EXPECT_NE(ingameOnlyComponent, nullptr); NoneEditorComponent* noneEditorComponent = AzToolsFramework::FindWrappedComponentForEntity(m_entity); EXPECT_NE(noneEditorComponent, nullptr); }