Integrating up through commit 90f050496

This commit is contained in:
alexpete
2021-04-07 14:03:29 -07:00
parent 8f2ed080a9
commit c2cbd430fe
2694 changed files with 285622 additions and 176874 deletions
@@ -58,7 +58,7 @@ namespace Benchmark
AzToolsFramework::Prefab::InstanceUpdateExecutorInterface* m_instanceUpdateExecutorInterface = nullptr;
const char* m_pathString = "path/to/template";
AZStd::vector<AZStd::string> m_paths;
AZStd::vector<AZ::IO::Path> m_paths;
AZStd::unique_ptr <UnitTest::MockPrefabFileIOActionValidator> m_mockIOActionValidator;
};
@@ -35,7 +35,7 @@ namespace Benchmark
for (int templateCounter = 0; templateCounter < numTemplates; ++templateCounter)
{
m_prefabLoaderInterface->LoadTemplate(m_paths[templateCounter]);
m_prefabLoaderInterface->LoadTemplateFromFile(m_paths[templateCounter]);
}
state.PauseTiming();
@@ -12,7 +12,9 @@
#include <Prefab/MockPrefabFileIOActionValidator.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/JSON/prettywriter.h>
#include <Prefab/PrefabLoaderInterface.h>
namespace UnitTest
{
@@ -38,7 +40,7 @@ namespace UnitTest
}
void MockPrefabFileIOActionValidator::ReadPrefabDom(
const AZStd::string& prefabFilePath,
AZ::IO::PathView prefabFilePath,
const AzToolsFramework::Prefab::PrefabDom& prefabFileContentDom,
AZ::IO::ResultCode expectedReadResultCode,
AZ::IO::ResultCode expectedOpenResultCode,
@@ -56,7 +58,7 @@ namespace UnitTest
}
void MockPrefabFileIOActionValidator::ReadPrefabDom(
const AZStd::string& prefabFilePath,
AZ::IO::PathView prefabFilePath,
const AZStd::string& prefabFileContent,
AZ::IO::ResultCode expectedReadResultCode,
AZ::IO::ResultCode expectedOpenResultCode,
@@ -65,8 +67,10 @@ namespace UnitTest
{
AZ::IO::HandleType fileHandle = m_fileHandleCounter++;
AZ::IO::Path prefabFullPath = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get()->GetFullPath(AZStd::string_view(prefabFilePath));
EXPECT_CALL(*m_fileIOMock.get(), Open(
testing::StrEq(prefabFilePath.c_str()), testing::_, testing::_))
testing::StrEq(prefabFullPath.c_str()), testing::_, testing::_))
.WillRepeatedly(
testing::DoAll(
testing::SetArgReferee<2>(fileHandle),
@@ -26,7 +26,7 @@ namespace UnitTest
~MockPrefabFileIOActionValidator();
void ReadPrefabDom(
const AZStd::string& prefabFilePath,
AZ::IO::PathView prefabFilePath,
const AzToolsFramework::Prefab::PrefabDom& prefabFileContentDom,
AZ::IO::ResultCode expectedReadResultCode = AZ::IO::ResultCode::Success,
AZ::IO::ResultCode expectedOpenResultCode = AZ::IO::ResultCode::Success,
@@ -34,7 +34,7 @@ namespace UnitTest
AZ::IO::ResultCode expectedCloseResultCode = AZ::IO::ResultCode::Success);
void ReadPrefabDom(
const AZStd::string& prefabFilePath,
AZ::IO::PathView prefabFilePath,
const AZStd::string& prefabFileContent,
AZ::IO::ResultCode expectedReadResultCode = AZ::IO::ResultCode::Success,
AZ::IO::ResultCode expectedOpenResultCode = AZ::IO::ResultCode::Success,
@@ -49,26 +49,27 @@ namespace UnitTest
AZStd::unique_ptr<Instance> secondInstance =
m_prefabSystemComponent->InstantiatePrefab(newInstance->GetTemplateId());
// Activate the entities so that we can find them via the component application bus
secondInstance->InitializeEntities();
secondInstance->ActivateEntities();
AZ::Entity* secondNewEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(secondNewEntity,
&AZ::ComponentApplicationBus::Events::FindEntity, secondInstance->GetEntityId(newEntityAlias));
ASSERT_TRUE(secondNewEntity);
PrefabTestComponent* secondComponent = secondNewEntity->FindComponent<PrefabTestComponent>();
ASSERT_TRUE(secondComponent);
// Validate that the entity reference is preserved in the second instance
ASSERT_TRUE(secondComponent->m_entityIdProperty.IsValid());
ASSERT_EQ(secondComponent->m_entityIdProperty, secondInstance->GetEntityId(referencedEntityAlias));
bool found = false;
secondInstance->GetConstEntities([&](const AZ::Entity& entity)
{
if (entity.GetId() == secondInstance->GetEntityId(newEntityAlias))
{
PrefabTestComponent* secondComponent = entity.FindComponent<PrefabTestComponent>();
EXPECT_NE(nullptr, secondComponent);
if (secondComponent)
{
// Validate that the entity reference is preserved in the second instance
EXPECT_TRUE(secondComponent->m_entityIdProperty.IsValid());
EXPECT_EQ(secondComponent->m_entityIdProperty, secondInstance->GetEntityId(referencedEntityAlias));
}
found = true;
}
return true;
});
EXPECT_TRUE(found);
}
TEST_F(PrefabEntityAliasTests, PrefabEntityAlias_ReferenceNotInSameHierarchy_ReferenceGoesToNull)
TEST_F(PrefabEntityAliasTests, DISABLED_PrefabEntityAlias_ReferenceNotInSameHierarchy_ReferenceGoesToNull)
{
// Make a new entity with a test component
AZ::Entity* newEntity = CreateEntity("New Entity", false);
@@ -98,21 +99,19 @@ namespace UnitTest
AZStd::unique_ptr<Instance> secondInstance =
m_prefabSystemComponent->InstantiatePrefab(firstInstance->GetTemplateId());
// Activate the entities so that we can find them via the component application bus
secondInstance->InitializeEntities();
secondInstance->ActivateEntities();
AZ::Entity* secondNewEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(secondNewEntity,
&AZ::ComponentApplicationBus::Events::FindEntity, secondInstance->GetEntityId(newEntityAlias));
ASSERT_TRUE(secondNewEntity);
PrefabTestComponent* secondComponent = secondNewEntity->FindComponent<PrefabTestComponent>();
ASSERT_TRUE(secondComponent);
ASSERT_FALSE(secondComponent->m_entityIdProperty.IsValid());
size_t count = 0;
secondInstance->GetConstEntities([&](const AZ::Entity& entity)
{
count++;
PrefabTestComponent* secondComponent = entity.FindComponent<PrefabTestComponent>();
EXPECT_NE(nullptr, secondComponent);
if (secondComponent)
{
EXPECT_FALSE(secondComponent->m_entityIdProperty.IsValid());
}
return true;
});
EXPECT_EQ(1, count);
}
TEST_F(PrefabEntityAliasTests, PrefabEntityAlias_ReferenceEntityFoundInNestedInstance_ReferencePersists)
@@ -165,29 +164,27 @@ namespace UnitTest
ASSERT_TRUE(secondRootInstance);
// Activate the entities so that we can find them via the component application bus
secondRootInstance->InitializeNestedEntities();
secondRootInstance->ActivateNestedEntities();
// Find the new instances versions of the new and referenced entities using the aliases we saved
AZ::EntityId secondNewEntityId = secondRootInstance->GetEntityId(newEntityAlias);
InstanceOptionalReference secondNestedInstance = secondRootInstance->FindNestedInstance(nestedAlias);
ASSERT_TRUE(secondNestedInstance);
AZ::EntityId secondReferencedEntityId = secondNestedInstance->get().GetEntityId(referencedEntityAlias);
AZ::Entity* secondNewEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(secondNewEntity,
&AZ::ComponentApplicationBus::Events::FindEntity, secondNewEntityId);
ASSERT_TRUE(secondNewEntity);
PrefabTestComponent* secondComponent = secondNewEntity->FindComponent<PrefabTestComponent>();
ASSERT_TRUE(secondComponent);
EXPECT_TRUE(secondComponent->m_entityIdProperty.IsValid());
EXPECT_EQ(secondComponent->m_entityIdProperty, secondReferencedEntityId);
size_t count = 0;
secondRootInstance->GetConstEntities([&](const AZ::Entity& entity)
{
count++;
PrefabTestComponent* secondComponent = entity.FindComponent<PrefabTestComponent>();
EXPECT_NE(nullptr, secondComponent);
if (secondComponent)
{
EXPECT_TRUE(secondComponent->m_entityIdProperty.IsValid());
EXPECT_EQ(secondComponent->m_entityIdProperty, secondReferencedEntityId);
}
return true;
});
EXPECT_EQ(1, count);
}
TEST_F(PrefabEntityAliasTests, PrefabEntityAlias_ReferenceEntityFoundInParentInstance_ReferencePersists)
@@ -244,7 +241,8 @@ namespace UnitTest
m_instanceToTemplateInterface->GeneratePatch(patch, entityDomBeforeUpdate, entityDomAfterUpdate);
// Patch the nested prefab to reference an entity in its parent
m_instanceToTemplateInterface->PatchEntityInTemplate(patch, newEntity->GetId());
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, newEntity->GetId()));
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Using the aliases we saved grab the updated entities so we can verify the entity reference is still preserved
InstanceOptionalReference updatedNestedInstance = rootInstance->FindNestedInstance(nestedAlias);
@@ -253,10 +251,6 @@ namespace UnitTest
AZ::EntityId updatedNewEntityId = updatedNestedInstance->get().GetEntityId(entityAlias);
AZ::Entity* updatedNewEntity = nullptr;
// Activate the entities so that we can find them via the component application bus
rootInstance->InitializeNestedEntities();
rootInstance->ActivateNestedEntities();
AZ::ComponentApplicationBus::BroadcastResult(updatedNewEntity,
&AZ::ComponentApplicationBus::Events::FindEntity, updatedNewEntityId);
@@ -67,11 +67,10 @@ namespace UnitTest
m_instanceToTemplateInterface->GeneratePatch(patch, entityDomBeforeUpdate, entityDomAfterUpdate);
//update template
m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityId);
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityId));
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//activate the entity so we can access via transform bus
secondInstance->InitializeNestedEntities();
secondInstance->ActivateNestedEntities();
ValidateInstanceEntitiesActive(*secondInstance);
//get the entity id
AZ::EntityId secondEntityId = secondInstance->GetEntityId(newEntityAlias);
@@ -121,6 +120,7 @@ namespace UnitTest
//update template
m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//get the entity id
AZStd::vector<AZ::EntityId> entityIdVector;
@@ -171,6 +171,7 @@ namespace UnitTest
//update template
m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//get the entity id
AZStd::vector<AZ::EntityId> entityIdVector;
@@ -219,6 +220,7 @@ namespace UnitTest
//update template
m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
EXPECT_NE(secondInstance->FindNestedInstance(addedAlias), AZStd::nullopt);
}
@@ -238,7 +240,7 @@ namespace UnitTest
//get template id
TemplateId templateId = firstInstance->GetTemplateId();
//instantiate second instance for checking if propogation works
//instantiate second instance for checking if propagation works
AZStd::unique_ptr<Instance> secondInstance = m_prefabSystemComponent->InstantiatePrefab(templateId);
ASSERT_TRUE(secondInstance);
@@ -259,6 +261,7 @@ namespace UnitTest
//update template
m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
EXPECT_EQ(secondInstance->FindNestedInstance(addedAlias), AZStd::nullopt);
}
@@ -24,20 +24,22 @@ namespace UnitTest
TEST_F(PrefabInstantiateTest, PrefabInstantiate_NoNestingTemplate_InstantiateSucceeds)
{
AZ::Entity* newEntity = CreateEntity("New Entity");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{newEntity});
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> firstInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path");
ASSERT_TRUE(firstInstance);
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> secondInstance = m_prefabSystemComponent->InstantiatePrefab(firstInstance->GetTemplateId());
ASSERT_TRUE(secondInstance);
CompareInstances(*firstInstance, *secondInstance);
CompareInstances(*firstInstance, *secondInstance, true, false);
}
TEST_F(PrefabInstantiateTest, PrefabInstantiate_TripleNestingTemplate_InstantiateSucceeds)
{
AZ::Entity* newEntity = CreateEntity("New Entity");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{newEntity});
// Build a 3 level deep nested Template
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> firstInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path1");
ASSERT_TRUE(firstInstance);
@@ -56,13 +58,14 @@ namespace UnitTest
ASSERT_TRUE(fourthInstance);
CompareInstances(*thirdInstance, *fourthInstance, false);
CompareInstances(*thirdInstance, *fourthInstance, true, false);
}
TEST_F(PrefabInstantiateTest, PrefabInstantiate_Instantiate10Times_InstantiatesSucceed)
{
AZ::Entity* newEntity = CreateEntity("New Entity");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{newEntity});
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> firstInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path");
// Store the generated instances so that the unique_ptrs are destroyed at the end of the test
@@ -76,7 +79,7 @@ namespace UnitTest
ASSERT_TRUE(newInstance);
CompareInstances(*firstInstance, *newInstance);
CompareInstances(*firstInstance, *newInstance, true, false);
newInstances.push_back(AZStd::move(newInstance));
}
@@ -30,7 +30,7 @@ namespace UnitTest
mockIOActionValidator.ReadPrefabDom(
templateData.m_filePath, PrefabTestDomUtils::CreatePrefabDom());
templateData.m_id = m_prefabLoaderInterface->LoadTemplate(templateData.m_filePath);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templateData.m_filePath);
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
@@ -54,7 +54,7 @@ namespace UnitTest
mockIOActionValidator.ReadPrefabDom(
targetTemplateData.m_filePath, PrefabTestDomUtils::CreatePrefabDom({ targetTemplateInstanceData }));
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplate(targetTemplateData.m_filePath);
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(targetTemplateData.m_filePath);
sourceTemplateData.m_id = m_prefabSystemComponent->GetTemplateIdFromFilePath(sourceTemplateData.m_filePath);
LinkData linkData = PrefabTestDataUtils::CreateLinkData(
@@ -74,7 +74,7 @@ namespace UnitTest
MockPrefabFileIOActionValidator mockIOActionValidator;
mockIOActionValidator.ReadPrefabDom(templateData.m_filePath, templatePrefabDom);
templateData.m_id = m_prefabLoaderInterface->LoadTemplate(templateData.m_filePath);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templateData.m_filePath);
templateData.m_isLoadedWithErrors = true;
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
@@ -120,7 +120,7 @@ namespace UnitTest
targetTemplateData.m_filePath, targetTemplatePrefabDom);
// Load target and source Templates and get their Ids.
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplate(targetTemplateData.m_filePath);
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(targetTemplateData.m_filePath);
sourceTemplateData.m_id = m_prefabSystemComponent->GetTemplateIdFromFilePath(sourceTemplateData.m_filePath);
// Because of cyclical dependency, the two Templates should be loaded with errors.
@@ -149,7 +149,7 @@ namespace UnitTest
MockPrefabFileIOActionValidator mockIOActionValidator;
mockIOActionValidator.ReadPrefabDom(templateData.m_filePath, templatePrefabDom);
templateData.m_id = m_prefabLoaderInterface->LoadTemplate(templateData.m_filePath);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templateData.m_filePath);
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
@@ -166,7 +166,7 @@ namespace UnitTest
MockPrefabFileIOActionValidator mockIOActionValidator;
mockIOActionValidator.ReadPrefabDom(templateData.m_filePath, templatePrefabDom);
templateData.m_id = m_prefabLoaderInterface->LoadTemplate(templateData.m_filePath);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templateData.m_filePath);
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
@@ -188,7 +188,7 @@ namespace UnitTest
templateInstanceData.m_source, PrefabTestDomUtils::CreatePrefabDom(),
AZ::IO::ResultCode::Success, AZ::IO::ResultCode::Error);
templateData.m_id = m_prefabLoaderInterface->LoadTemplate(templateData.m_filePath);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templateData.m_filePath);
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
@@ -222,7 +222,7 @@ namespace UnitTest
}
}
templatesData.back().m_id = m_prefabLoaderInterface->LoadTemplate(templatesData.back().m_filePath);
templatesData.back().m_id = m_prefabLoaderInterface->LoadTemplateFromFile(templatesData.back().m_filePath);
for (int i = nestedHierarchyLevel - 2; i >= 0; i--)
{
templatesData[i].m_id = m_prefabSystemComponent->GetTemplateIdFromFilePath(templatesData[i].m_filePath);
@@ -264,7 +264,7 @@ namespace UnitTest
mockIOActionValidator.ReadPrefabDom(
targetTemplateData.m_filePath, PrefabTestDomUtils::CreatePrefabDom(targetTemplateInstancesData));
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplate(targetTemplateData.m_filePath);
targetTemplateData.m_id = m_prefabLoaderInterface->LoadTemplateFromFile(targetTemplateData.m_filePath);
for (int i = 0; i < numInstances; i++)
{
sourceTemplatesData[i].m_id = m_prefabSystemComponent->GetTemplateIdFromFilePath(sourceTemplatesData[i].m_filePath);
@@ -279,13 +279,63 @@ namespace UnitTest
TEST_F(PrefabLoadTemplateTest, LoadTemplate_LoadCorruptedPrefabFileData_InvalidTemplateIdReturned)
{
const AZStd::string corruptedPrefabContent = "{ Corrupted PrefabDom";
const AZStd::string pathToCorruptedPrefab = "path/to/corrupted/prefab/file";
AZ::IO::Path pathToCorruptedPrefab("path/to/corrupted/prefab/file");
pathToCorruptedPrefab.MakePreferred();
MockPrefabFileIOActionValidator mockIOActionValidator;
mockIOActionValidator.ReadPrefabDom(pathToCorruptedPrefab, corruptedPrefabContent);
auto tmeplateId = m_prefabLoaderInterface->LoadTemplate(pathToCorruptedPrefab);
TemplateId templateId = m_prefabLoaderInterface->LoadTemplateFromFile(pathToCorruptedPrefab);
EXPECT_EQ(tmeplateId, AzToolsFramework::Prefab::InvalidTemplateId);
EXPECT_EQ(templateId, AzToolsFramework::Prefab::InvalidTemplateId);
}
TEST_F(PrefabLoadTemplateTest, LoadTemplate_LoadFromString_InvalidPathReturnsInvalidTemplateId)
{
PrefabDom emptyPrefabDom = PrefabTestDomUtils::CreatePrefabDom();
AZStd::string emptyPrefabDomStr = PrefabTestDomUtils::DomToString(emptyPrefabDom);
EXPECT_EQ(m_prefabLoaderInterface->LoadTemplateFromString(emptyPrefabDomStr, "|?<>"), AzToolsFramework::Prefab::InvalidTemplateId);
EXPECT_EQ(m_prefabLoaderInterface->LoadTemplateFromString(emptyPrefabDomStr, "notAFile/"), AzToolsFramework::Prefab::InvalidTemplateId);
}
TEST_F(PrefabLoadTemplateTest, LoadTemplate_LoadFromString_LoadsEmptyPrefab)
{
TemplateData templateData;
templateData.m_filePath = "path/to/empty/prefab";
PrefabDom emptyPrefabDom = PrefabTestDomUtils::CreatePrefabDom();
AZStd::string emptyPrefabDomStr = PrefabTestDomUtils::DomToString(emptyPrefabDom);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromString(
emptyPrefabDomStr,
templateData.m_filePath
);
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
TEST_F(PrefabLoadTemplateTest, LoadTemplate_LoadFromString_TemplateDependingOnItself_LoadedWithErrors)
{
TemplateData templateData;
templateData.m_filePath = "path/to/self/dependency";
PrefabDom selfDependentPrefab = PrefabTestDomUtils::CreatePrefabDom(
{ PrefabTestDataUtils::CreateInstanceDataWithNoPatches("instance", templateData.m_filePath) }
);
AZStd::string selfDependentPrefabStr = PrefabTestDomUtils::DomToString(selfDependentPrefab);
templateData.m_id = m_prefabLoaderInterface->LoadTemplateFromString(
selfDependentPrefabStr,
templateData.m_filePath);
templateData.m_isLoadedWithErrors = true;
PrefabTestDataUtils::ValidateTemplateLoad(templateData);
}
TEST_F(PrefabLoadTemplateTest, LoadTemplate_LoadFromString_CorruptedReturnsInvalidTemplateId)
{
AZStd::string corruptPrefab = "{ Corrupted PrefabDom";
TemplateId templateId = m_prefabLoaderInterface->LoadTemplateFromString(corruptPrefab);
EXPECT_EQ(templateId, AzToolsFramework::Prefab::InvalidTemplateId);
}
}
@@ -22,6 +22,7 @@ namespace UnitTest
{
serializeContext->Class<PrefabTestComponent, AzToolsFramework::Components::EditorComponentBase>()->
Field("BoolProperty", &PrefabTestComponent::m_boolProperty)->
Field("IntProperty", &PrefabTestComponent::m_intProperty)->
Field("EntityReferenceProperty", &PrefabTestComponent::m_entityIdProperty);
}
}
@@ -28,6 +28,7 @@ namespace UnitTest
static void Reflect(AZ::ReflectContext* reflection);
bool m_boolProperty = false;
int m_intProperty = 0;
AZ::EntityId m_entityIdProperty;
};
}
@@ -12,6 +12,7 @@
#pragma once
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
@@ -27,7 +28,7 @@ namespace UnitTest
InstanceData& operator=(const InstanceData& other);
AZStd::string m_name;
AZStd::string m_source;
AZ::IO::Path m_source;
AzToolsFramework::Prefab::PrefabDom m_patches;
};
@@ -36,7 +37,7 @@ namespace UnitTest
AzToolsFramework::Prefab::TemplateId m_id = AzToolsFramework::Prefab::InvalidTemplateId;
bool m_isValid = true;
bool m_isLoadedWithErrors = false;
AZStd::string m_filePath;
AZ::IO::Path m_filePath;
AZStd::unordered_map<AZStd::string, InstanceData> m_instancesData;
};
@@ -38,7 +38,7 @@ namespace UnitTest
InstanceData CreateInstanceDataWithNoPatches(
const AZStd::string& name,
const AZStd::string& source)
AZ::IO::PathView source)
{
InstanceData newInstanceData;
newInstanceData.m_name = name;
@@ -26,7 +26,7 @@ namespace UnitTest
InstanceData CreateInstanceDataWithNoPatches(
const AZStd::string& name,
const AZStd::string& source);
AZ::IO::PathView source);
void ValidateTemplateLoad(
const TemplateData& expectedTemplateData);
@@ -24,7 +24,6 @@ namespace UnitTest
{
namespace PrefabTestDomUtils
{
void SetPrefabDomInstance(
PrefabDom& prefabDom,
const char* instanceName,
@@ -64,7 +63,8 @@ namespace UnitTest
const TemplateId& templateId,
const PrefabDomValue& expectedContent,
const PrefabDomPath& contentPath,
bool isContentAnInstance)
bool isContentAnInstance,
bool shouldCompareContainerEntities)
{
TemplateInstanceMapperInterface* templateInstanceMapper =
AZ::Interface<TemplateInstanceMapperInterface>::Get();
@@ -86,7 +86,7 @@ namespace UnitTest
if (isContentAnInstance)
{
ComparePrefabDoms(*actualContent, expectedContent, false);
ComparePrefabDoms(*actualContent, expectedContent, false, shouldCompareContainerEntities);
}
else
{
@@ -108,7 +108,8 @@ namespace UnitTest
void ValidatePrefabDomInstances(
const AZStd::vector<InstanceAlias>& instanceAliases,
const AzToolsFramework::Prefab::PrefabDom& prefabDom,
const AzToolsFramework::Prefab::PrefabDom& expectedNestedInstanceDom)
const AzToolsFramework::Prefab::PrefabDom& expectedNestedInstanceDom,
bool shouldCompareContainerEntities)
{
PrefabDomValueConstReference templateInstances = PrefabDomUtils::FindPrefabDomValue(prefabDom, "Instances");
ASSERT_TRUE(templateInstances.has_value());
@@ -116,11 +117,13 @@ namespace UnitTest
{
PrefabDomValueConstReference actualNestedInstanceDom = PrefabDomUtils::FindPrefabDomValue(templateInstances->get(), instanceAlias.c_str());
ASSERT_TRUE(actualNestedInstanceDom.has_value());
ComparePrefabDoms(actualNestedInstanceDom, expectedNestedInstanceDom, false);
ComparePrefabDoms(actualNestedInstanceDom, expectedNestedInstanceDom, false, shouldCompareContainerEntities);
}
}
void ComparePrefabDoms(PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB, bool shouldCompareLinkIds)
void ComparePrefabDoms(
PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB, bool shouldCompareLinkIds,
bool shouldCompareContainerEntities)
{
ASSERT_TRUE(valueA.has_value());
ASSERT_TRUE(valueB.has_value());
@@ -129,40 +132,52 @@ namespace UnitTest
if (shouldCompareLinkIds)
{
EXPECT_EQ(AZ::JsonSerialization::Compare(valueADom, valueBDom), AZ::JsonSerializerCompareResult::Equal);
PrefabDomValueConstReference actualNestedInstanceDomLinkId =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::LinkIdName);
PrefabDomValueConstReference expectedNestedInstanceDomLinkId =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::LinkIdName);
ComparePrefabDomValues(actualNestedInstanceDomLinkId, actualNestedInstanceDomLinkId);
}
else
if (shouldCompareContainerEntities)
{
// Compare the source values of the two DOMs.
PrefabDomValueConstReference actualNestedInstanceDomSource =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::SourceName);
PrefabDomValueConstReference expectedNestedInstanceDomSource =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::SourceName);
ComparePrefabDomValues(actualNestedInstanceDomSource, expectedNestedInstanceDomSource);
PrefabDomValueConstReference actualNestedInstanceDomContainerEntity =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::ContainerEntityName);
PrefabDomValueConstReference expectedNestedInstanceDomContainerEntity =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::ContainerEntityName);
ComparePrefabDomValues(actualNestedInstanceDomContainerEntity, expectedNestedInstanceDomContainerEntity);
}
// Compare the entities values of the two DOMs.
PrefabDomValueConstReference actualNestedInstanceDomEntities =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabTestDomUtils::EntitiesValueName);
PrefabDomValueConstReference expectedNestedInstanceDomEntities =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabTestDomUtils::EntitiesValueName);
ComparePrefabDomValues(actualNestedInstanceDomEntities, expectedNestedInstanceDomEntities);
// Compare the source values of the two DOMs.
PrefabDomValueConstReference actualNestedInstanceDomSource =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::SourceName);
PrefabDomValueConstReference expectedNestedInstanceDomSource =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::SourceName);
ComparePrefabDomValues(actualNestedInstanceDomSource, expectedNestedInstanceDomSource);
// Compare the instances values of the two DOMs, which involves iterating over each expected instance and comparing it
// with its counterpart in the actual instance.
PrefabDomValueConstReference actualNestedInstanceDomInstances =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::InstancesName);
PrefabDomValueConstReference expectedNestedInstanceDomInstances =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::InstancesName);
if (expectedNestedInstanceDomInstances.has_value())
// Compare the entities values of the two DOMs.
PrefabDomValueConstReference actualNestedInstanceDomEntities =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabTestDomUtils::EntitiesValueName);
PrefabDomValueConstReference expectedNestedInstanceDomEntities =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabTestDomUtils::EntitiesValueName);
ComparePrefabDomValues(actualNestedInstanceDomEntities, expectedNestedInstanceDomEntities);
// Compare the instances values of the two DOMs, which involves iterating over each expected instance and comparing it
// with its counterpart in the actual instance.
PrefabDomValueConstReference actualNestedInstanceDomInstances =
PrefabDomUtils::FindPrefabDomValue(valueADom, PrefabDomUtils::InstancesName);
PrefabDomValueConstReference expectedNestedInstanceDomInstances =
PrefabDomUtils::FindPrefabDomValue(valueBDom, PrefabDomUtils::InstancesName);
if (expectedNestedInstanceDomInstances.has_value())
{
ASSERT_TRUE(actualNestedInstanceDomInstances.has_value());
for (auto instanceIterator = expectedNestedInstanceDomInstances->get().MemberBegin();
instanceIterator != expectedNestedInstanceDomInstances->get().MemberEnd(); ++instanceIterator)
{
ASSERT_TRUE(actualNestedInstanceDomInstances.has_value());
for (auto instanceIterator = expectedNestedInstanceDomInstances->get().MemberBegin();
instanceIterator != expectedNestedInstanceDomInstances->get().MemberEnd(); ++instanceIterator)
{
ComparePrefabDoms(instanceIterator->value,
PrefabDomUtils::FindPrefabDomValue(actualNestedInstanceDomInstances->get(), instanceIterator->name.GetString()),
shouldCompareLinkIds);
}
ComparePrefabDoms(
instanceIterator->value,
PrefabDomUtils::FindPrefabDomValue(actualNestedInstanceDomInstances->get(), instanceIterator->name.GetString()),
shouldCompareLinkIds, shouldCompareContainerEntities);
}
}
}
@@ -180,14 +195,6 @@ namespace UnitTest
}
}
void PrintPrefabDom(const AzToolsFramework::Prefab::PrefabDomValue& prefabDom)
{
rapidjson::StringBuffer prefabBuffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(prefabBuffer);
prefabDom.Accept(writer);
std::cout << prefabBuffer.GetString() << std::endl;
}
void ValidateEntitiesOfInstances(
const AzToolsFramework::Prefab::TemplateId& templateId,
const AzToolsFramework::Prefab::PrefabDom& expectedPrefabDom,
@@ -215,8 +222,29 @@ namespace UnitTest
PrefabTestDomUtils::GetPrefabDomInstance(expectedPrefabDom, nestedInstanceAlias);
ASSERT_TRUE(nestedInstanceValue != nullptr);
PrefabTestDomUtils::ValidateInstances(templateId, *nestedInstanceValue, nestedInstancePath, true);
PrefabTestDomUtils::ValidateInstances(templateId, *nestedInstanceValue, nestedInstancePath, true, false);
}
}
void ValidateComponentsDomHasId(const PrefabDomValue& componentsDom, AZ::u64 componentId)
{
AZStd::string componentValueName = AZStd::string::format("Component_[%llu]", componentId);
PrefabDomValueConstReference entityComponentValue = PrefabDomUtils::FindPrefabDomValue(componentsDom, componentValueName.c_str());
ASSERT_TRUE(entityComponentValue);
PrefabDomValueConstReference entityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(entityComponentValue->get(), PrefabTestDomUtils::ComponentIdName);
EXPECT_EQ(componentId, entityComponentIdValue->get().GetUint64());
}
AZStd::string DomToString(const AzToolsFramework::Prefab::PrefabDom& dom)
{
rapidjson::StringBuffer prefabFileContentBuffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(prefabFileContentBuffer);
dom.Accept(writer);
return AZStd::string(prefabFileContentBuffer.GetString());
}
}
}
@@ -125,7 +125,8 @@ namespace UnitTest
const TemplateId& templateId,
const PrefabDomValue& expectedContent,
const PrefabDomPath& contentPath,
bool isContentAnInstance = false);
bool isContentAnInstance = false,
bool shouldCompareContainerEntities = true);
PrefabDom CreatePrefabDom();
PrefabDom CreatePrefabDom(const AZStd::vector<InstanceData>& instancesData);
@@ -142,16 +143,13 @@ namespace UnitTest
*/
void ValidatePrefabDomInstances(const AZStd::vector<InstanceAlias>& instanceAliases,
const PrefabDom& prefabDom,
const PrefabDom& expectedNestedInstanceDom);
const PrefabDom& expectedNestedInstanceDom,
bool shouldCompareContainerEntities = true);
void ComparePrefabDoms(PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB, bool shouldCompareLinkIds = true);
void ComparePrefabDoms(PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB, bool shouldCompareLinkIds = true,
bool shouldCompareContainerEntities = true);
void ComparePrefabDomValues(PrefabDomValueConstReference valueA, PrefabDomValueConstReference valueB);
/**
* Prints the contents of the given prefab DOM to the console in a readable format.
*/
void PrintPrefabDom(const PrefabDomValue& prefabDom);
void ValidateEntitiesOfInstances(
const AzToolsFramework::Prefab::TemplateId& templateId,
const AzToolsFramework::Prefab::PrefabDom& expectedPrefabDom,
@@ -161,7 +159,11 @@ namespace UnitTest
const AzToolsFramework::Prefab::TemplateId& templateId,
const AzToolsFramework::Prefab::PrefabDom& expectedPrefabDom,
const AZStd::vector<InstanceAlias>& nestedInstanceAliases);
void ValidateComponentsDomHasId(const PrefabDomValue& componentsDom, AZ::u64 componentId);
//! Serializes Dom into a string
AZStd::string DomToString(const AzToolsFramework::Prefab::PrefabDom& dom);
}
}
@@ -26,19 +26,15 @@ namespace UnitTest
AZ::Entity* systemEntity = GetApplication()->FindEntity(AZ::SystemEntityId);
EXPECT_TRUE(systemEntity);
// Acquire the prefab system component to gain access to its APIs for testing
m_prefabSystemComponent = systemEntity->FindComponent<AzToolsFramework::Prefab::PrefabSystemComponent>();
EXPECT_TRUE(m_prefabSystemComponent);
// Acquire the interface of PrefabLoader to gain access to its APIs for testing
m_prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
EXPECT_TRUE(m_prefabLoaderInterface);
// Acquire the interface of InstanceUpdateQueueInterface to gain access to its APIs for testing
m_instanceUpdateExecutorInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceUpdateExecutorInterface>::Get();
EXPECT_TRUE(m_instanceUpdateExecutorInterface);
// Acquire the interface of InstanceToTemplate to gain access to its APIs for testing
m_instanceToTemplateInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceToTemplateInterface>::Get();
EXPECT_TRUE(m_instanceToTemplateInterface);
@@ -60,7 +56,7 @@ namespace UnitTest
}
void PrefabTestFixture::CompareInstances(const AzToolsFramework::Prefab::Instance& instanceA,
const AzToolsFramework::Prefab::Instance& instanceB, bool shouldCompareLinkIds)
const AzToolsFramework::Prefab::Instance& instanceB, bool shouldCompareLinkIds, bool shouldCompareContainerEntities)
{
AzToolsFramework::Prefab::TemplateId templateAId = instanceA.GetTemplateId();
AzToolsFramework::Prefab::TemplateId templateBId = instanceB.GetTemplateId();
@@ -81,10 +77,11 @@ namespace UnitTest
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(instanceB, prefabDomB));
// Validate that both instances match when serialized
PrefabTestDomUtils::ComparePrefabDoms(prefabDomA, prefabDomB);
PrefabTestDomUtils::ComparePrefabDoms(prefabDomA, prefabDomB, true, shouldCompareContainerEntities);
// Validate that the serialized instances match the shared template when serialized
PrefabTestDomUtils::ComparePrefabDoms(templateA->get().GetPrefabDom(), prefabDomB, shouldCompareLinkIds);
PrefabTestDomUtils::ComparePrefabDoms(templateA->get().GetPrefabDom(), prefabDomB, shouldCompareLinkIds,
shouldCompareContainerEntities);
}
void PrefabTestFixture::DeleteInstances(const InstanceList& instancesToDelete)
@@ -96,4 +93,20 @@ namespace UnitTest
instanceToDelete = nullptr;
}
}
void PrefabTestFixture::ValidateInstanceEntitiesActive(Instance& instance)
{
AZStd::vector<AZ::EntityId> entityIdVector;
instance.GetNestedEntityIds([&entityIdVector](AZ::EntityId entityId) {
entityIdVector.push_back(entityId);
return true;
});
for (AZ::EntityId entityId : entityIdVector)
{
AZ::Entity* entityInInstance = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(entityInInstance, &AZ::ComponentApplicationBus::Events::FindEntity, entityId);
ASSERT_TRUE(entityInInstance);
EXPECT_EQ(entityInInstance->GetState(), AZ::Entity::State::Active);
}
}
}
@@ -47,11 +47,14 @@ namespace UnitTest
AZ::Entity* CreateEntity(const char* entityName, const bool shouldActivate = true);
void CompareInstances(const Instance& instanceA,
const Instance& instanceB, bool shouldCompareLinkIds = true);
void CompareInstances(const Instance& instanceA, const Instance& instanceB, bool shouldCompareLinkIds = true,
bool shouldCompareContainerEntities = true);
void DeleteInstances(const InstanceList& instancesToDelete);
//! Validates that all entities within a prefab instance are in 'Active' state.
void ValidateInstanceEntitiesActive(Instance& instance);
PrefabSystemComponent* m_prefabSystemComponent = nullptr;
PrefabLoaderInterface* m_prefabLoaderInterface = nullptr;
InstanceUpdateExecutorInterface* m_instanceUpdateExecutorInterface = nullptr;
@@ -15,11 +15,13 @@
#include <Prefab/PrefabUndo.h>
#include <Prefab/PrefabTestComponent.h>
namespace UnitTest
{
using PrefabUndoLinkTests = PrefabTestUndoFixture;
TEST_F(PrefabUndoLinkTests, PrefabUndoLinkAdd)
TEST_F(PrefabUndoLinkTests, PrefabUndoLink_Add)
{
AZStd::unique_ptr<Instance> firstInstance = nullptr;
AZStd::unique_ptr<Instance> secondInstance = nullptr;
@@ -36,6 +38,7 @@ namespace UnitTest
PrefabUndoInstanceLink undoLink("Undo Link Add Node");
undoLink.Capture(firstTemplateId, secondTemplateId, aliases[0]);
undoLink.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->InstantiatePrefab(firstTemplateId);
AZStd::vector<InstanceAlias> instances = newInstance->GetNestedInstanceAliases(secondTemplateId);
@@ -45,6 +48,7 @@ namespace UnitTest
//undo the parenting
undoLink.Undo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
newInstance = m_prefabSystemComponent->InstantiatePrefab(firstTemplateId);
instances = newInstance->GetNestedInstanceAliases(secondTemplateId);
@@ -53,10 +57,249 @@ namespace UnitTest
//undo the parenting
undoLink.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
newInstance = m_prefabSystemComponent->InstantiatePrefab(firstTemplateId);
instances = newInstance->GetNestedInstanceAliases(secondTemplateId);
ASSERT_TRUE(instances.size() == 1);
}
TEST_F(PrefabUndoLinkTests, PrefabUndoLink_InitialPatchData_ContainerTarget_PatchSucceeds)
{
//create two instances
AZStd::unique_ptr<Instance> nestedInstance = nullptr;
AZStd::unique_ptr<Instance> rootInstance = nullptr;
TemplateId nestedTemplateId = InvalidTemplateId;
TemplateId rootTemplateId = InvalidTemplateId;
SetupInstances(nestedInstance, rootInstance, nestedTemplateId, rootTemplateId);
nestedInstance->ActivateContainerEntity();
AZ::EntityId nestedContainerEntityId = nestedInstance->GetContainerEntityId();
AZ::EntityId rootContainerEntityId = rootInstance->GetContainerEntityId();
AZ::Entity* nestedContainerEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
//generate a patch to add a component to the nested instance
PrefabDom initialEntityDom;
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
nestedContainerEntity->Deactivate();
PrefabTestComponent* nestedTestComponent = nestedContainerEntity->CreateComponent<PrefabTestComponent>();
ASSERT_TRUE(nestedTestComponent);
nestedContainerEntity->Activate();
PrefabDom modifiedEntityDom;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
PrefabDom patch;
m_instanceToTemplateInterface->GeneratePatch(patch, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, nestedContainerEntityId);
//apply the patch
PrefabDom& templateDomReference = m_prefabSystemComponent->FindTemplateDom(nestedTemplateId);
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
templateDomReference.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
"Patch was not successfully applied");
//nest the second instance under the first instance
rootInstance->AddInstance(AZStd::move(nestedInstance));
AZStd::vector<InstanceAlias> aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
//create patch for nesting
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
nestedTestComponent->m_entityIdProperty = rootContainerEntityId;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
m_instanceToTemplateInterface->GeneratePatch(patch, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, nestedContainerEntityId);
//create an undo node to apply the patch and prep for undo
PrefabUndoInstanceLink undoInstanceLinkNode("Undo Link Patch");
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], patch, InvalidLinkId);
undoInstanceLinkNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//verify the application worked
InstanceOptionalReference nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
AZ::EntityId nestedContainerId = nestedInstanceRef->get().GetContainerEntityId();
AZ::Entity* nestedContainer = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(nestedContainer, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerId);
ASSERT_TRUE(nestedContainer);
PrefabTestComponent* nestedComponent = nestedContainer->FindComponent<PrefabTestComponent>();
ASSERT_EQ(nestedComponent->m_entityIdProperty, rootInstance->GetContainerEntityId());
}
TEST_F(PrefabUndoLinkTests, PrefabUndoLink_InitialPatchData_UpdateLinkEntity_PatchSucceeds)
{
//create two instance
AZStd::unique_ptr<Instance> nestedInstance = nullptr;
AZStd::unique_ptr<Instance> rootInstance = nullptr;
TemplateId nestedTemplateId = InvalidTemplateId;
TemplateId rootTemplateId = InvalidTemplateId;
SetupInstances(nestedInstance, rootInstance, nestedTemplateId, rootTemplateId);
nestedInstance->ActivateContainerEntity();
AZ::EntityId nestedContainerEntityId = nestedInstance->GetContainerEntityId();
AZ::EntityId rootContainerEntityId = rootInstance->GetContainerEntityId();
AZ::Entity* nestedContainerEntity = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
//add a component for testing to the instance that will be nested
PrefabDom initialEntityDom;
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
nestedContainerEntity->Deactivate();
PrefabTestComponent* nestedTestComponent = nestedContainerEntity->CreateComponent<PrefabTestComponent>();
ASSERT_TRUE(nestedTestComponent);
nestedContainerEntity->Activate();
PrefabDom modifiedEntityDom;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
//create patch
PrefabDom patch;
m_instanceToTemplateInterface->GeneratePatch(patch, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, nestedContainerEntityId);
m_instanceToTemplateInterface->PatchTemplate(patch, nestedTemplateId);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//instantiate a new nested instance
nestedInstance = m_prefabSystemComponent->InstantiatePrefab(nestedTemplateId);
nestedContainerEntityId = nestedInstance->GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
//nest the second instance under the first instance
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
rootInstance->AddInstance(AZStd::move(nestedInstance));
nestedTestComponent->m_entityIdProperty = rootContainerEntityId;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
//create patch
PrefabDom linkPatch;
m_instanceToTemplateInterface->GeneratePatch(linkPatch, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(linkPatch, nestedContainerEntityId);
AZStd::vector<InstanceAlias> aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
//create an undo node to apply the patch and prep for undo
PrefabUndoInstanceLink undoInstanceLinkNode("Undo Link Patch");
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], linkPatch, InvalidLinkId);
undoInstanceLinkNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
LinkId linkId = undoInstanceLinkNode.GetLinkId();
rootInstance = m_prefabSystemComponent->InstantiatePrefab(rootTemplateId);
aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
//verify the link was created
InstanceOptionalReference nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
nestedContainerEntityId = nestedInstanceRef->get().GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
//update the property on the nested component
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
nestedTestComponent = nestedContainerEntity->FindComponent<PrefabTestComponent>();
nestedTestComponent->m_boolProperty = true;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
//create patch
PrefabDom updatePatch;
m_instanceToTemplateInterface->GeneratePatch(updatePatch, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(updatePatch, nestedContainerEntityId);
//create the update link undo/redo node
PrefabUndoLinkUpdate undoLinkUpdateNode("Undo Link Update");
undoLinkUpdateNode.Capture(updatePatch, linkId);
undoLinkUpdateNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//verify the update worked
rootInstance = m_prefabSystemComponent->InstantiatePrefab(rootTemplateId);
aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
nestedContainerEntityId = nestedInstanceRef->get().GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
nestedTestComponent = nestedContainerEntity->FindComponent<PrefabTestComponent>();
ASSERT_EQ(nestedTestComponent->m_boolProperty, true);
//undo the update
undoLinkUpdateNode.Undo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//verify the undo update worked
rootInstance = m_prefabSystemComponent->InstantiatePrefab(rootTemplateId);
aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
nestedContainerEntityId = nestedInstanceRef->get().GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
nestedTestComponent = nestedContainerEntity->FindComponent<PrefabTestComponent>();
ASSERT_EQ(nestedTestComponent->m_boolProperty, false);
//redo the update so we can test if updating previously changed values matter
undoLinkUpdateNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
rootInstance = m_prefabSystemComponent->InstantiatePrefab(rootTemplateId);
aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
nestedContainerEntityId = nestedInstanceRef->get().GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
//update the property on the nested component
m_instanceToTemplateInterface->GenerateDomForEntity(initialEntityDom, *nestedContainerEntity);
nestedTestComponent = nestedContainerEntity->FindComponent<PrefabTestComponent>();
nestedTestComponent->m_intProperty = 1;
m_instanceToTemplateInterface->GenerateDomForEntity(modifiedEntityDom, *nestedContainerEntity);
//create patch
PrefabDom updatePatchIntField;
m_instanceToTemplateInterface->GeneratePatch(updatePatchIntField, initialEntityDom, modifiedEntityDom);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(updatePatchIntField, nestedContainerEntityId);
//create the update link undo/redo node
PrefabUndoLinkUpdate undoIntFieldNode("Undo Link Update");
undoIntFieldNode.Capture(updatePatchIntField, linkId);
undoIntFieldNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//verify the update worked
rootInstance = m_prefabSystemComponent->InstantiatePrefab(rootTemplateId);
aliases = rootInstance->GetNestedInstanceAliases(nestedTemplateId);
nestedInstanceRef = rootInstance->FindNestedInstance(aliases[0]);
nestedContainerEntityId = nestedInstanceRef->get().GetContainerEntityId();
AZ::ComponentApplicationBus::BroadcastResult(nestedContainerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, nestedContainerEntityId);
ASSERT_TRUE(nestedContainerEntity);
nestedTestComponent = nestedContainerEntity->FindComponent<PrefabTestComponent>();
ASSERT_EQ(nestedTestComponent->m_intProperty, 1);
}
} // namespace UnitTest
@@ -75,18 +75,18 @@ namespace UnitTest
EntityAlias entityAlias = entityAliasRef.value();
//update template
m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityAlias, templateId);
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityAlias, templateId));
//undo change
instanceEntityUndo.Undo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// verify template updated correctly
//instantiate second instance for checking if propogation works
AZStd::unique_ptr<Instance> secondInstance = m_prefabSystemComponent->InstantiatePrefab(templateId);
ASSERT_TRUE(secondInstance);
secondInstance->InitializeNestedEntities();
secondInstance->ActivateNestedEntities();
ValidateInstanceEntitiesActive(*secondInstance);
//get the values from the transform on the entity
AZ::EntityId secondNewEntity = secondInstance->GetEntityId(entityAlias);
@@ -136,6 +136,7 @@ namespace UnitTest
//undo change
instanceEntityAddUndo.Undo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//get the entity id
AZStd::vector<AZ::EntityId> entityIdVector;
@@ -188,6 +189,7 @@ namespace UnitTest
//undo change
instanceEntityRemoveUndo.Undo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
//get the entity id
AZStd::vector<AZ::EntityId> entityIdVector;
@@ -10,6 +10,7 @@
*
*/
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <Prefab/PrefabTestComponent.h>
#include <Prefab/PrefabTestDomUtils.h>
@@ -67,6 +68,8 @@ namespace UnitTest
// Create a Template from an Instance owning a single entity.
using namespace AzToolsFramework::Prefab;
AZ::Entity* entity1 = CreateEntity("Entity 1");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity1});
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity1 }, {}, PrefabMockFilePath);
TemplateId newTemplateId = newInstance->GetTemplateId();
EXPECT_TRUE(newTemplateId != InvalidTemplateId);
@@ -89,6 +92,8 @@ namespace UnitTest
// Add another entity to the Instance and use it to update the PrefabDom of Template.
AZ::Entity* entity2 = CreateEntity("Entity 2");
newInstance->AddEntity(*entity2);
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity2});
newTemplateEntityAliases = newInstance->GetEntityAliases();
EXPECT_EQ(newTemplateEntityAliases.size(), 2);
@@ -110,6 +115,8 @@ namespace UnitTest
// Create a Template with single entity.
using namespace AzToolsFramework::Prefab;
AZ::Entity* entity = CreateEntity("Entity");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity});
AZStd::unique_ptr<Instance> newNestedInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, NestedPrefabMockFilePath);
TemplateId newNestedTemplateId = newNestedInstance->GetTemplateId();
EXPECT_TRUE(newNestedTemplateId != InvalidTemplateId);
@@ -162,16 +169,20 @@ namespace UnitTest
{
// Create a Template from an Instance owning a single entity.
AZ::Entity* entity = CreateEntity("Entity", false);
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity});
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
TemplateId newTemplateId = newInstance->GetTemplateId();
PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
ASSERT_EQ(newTemplateEntityAliases.size(), 1);
// Validate that the entity doesn't have any components under it.
// Validate that the entity has 1 component under it. This is added through the scrubbing of entities in
// EditorEntityContextComponent, which gets called through HandleEntitiesAdded during loading of entities in Prefab Instances.
const PrefabDomValue* entityComponents =
PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents == nullptr);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 1);
// Instantiate Instances and validate if all Instances have the entity.
const int numberOfInstances = 3;
@@ -187,22 +198,20 @@ namespace UnitTest
// Add a component to the Instance and use it to update the PrefabDom of Template.
PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
entity->Deactivate();
entity->AddComponent(prefabTestComponent);
auto expectedComponentId = prefabTestComponent->GetId();
PrefabDom updatedDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
// Validate that the entity does have a component under it.
// Validate that the entity now has 2 components under it.
entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsArray());
EXPECT_EQ(entityComponents->GetArray().Size(), 1);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 2);
// Extract the component id of the entity in Template and verify that it matches with the component id of the Instance.
PrefabDomValueConstReference findEntityComponentIdValueResult =
PrefabDomUtils::FindPrefabDomValue(*entityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(findEntityComponentIdValueResult.has_value());
EXPECT_EQ(expectedComponentId, findEntityComponentIdValueResult->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*entityComponents, prefabTestComponent->GetId());
// Update Template's Instances and validate if all Instances have the new component under their entities.
m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
@@ -211,7 +220,6 @@ namespace UnitTest
PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityComponents,
PrefabTestDomUtils::GetPrefabDomComponentsPath(newTemplateEntityAliases.front()));
}
TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_DetachEntity_UpdateSucceeds)
@@ -220,6 +228,8 @@ namespace UnitTest
using namespace AzToolsFramework::Prefab;
AZ::Entity* entity1 = CreateEntity("Entity 1");
AZ::Entity* entity2 = CreateEntity("Entity 2");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity1, entity2});
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab(
{ entity1, entity2 },
{},
@@ -267,6 +277,8 @@ namespace UnitTest
// Create a Template with single entity.
using namespace AzToolsFramework::Prefab;
AZ::Entity* entity = CreateEntity("Entity");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity});
AZStd::unique_ptr<Instance> newNestedInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, NestedPrefabMockFilePath);
TemplateId newNestedTemplateId = newNestedInstance->GetTemplateId();
EXPECT_TRUE(newNestedTemplateId != InvalidTemplateId);
@@ -327,23 +339,22 @@ namespace UnitTest
AZ::Entity* entity = CreateEntity("Entity", false);
PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
entity->AddComponent(prefabTestComponent);
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity});
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
TemplateId newTemplateId = newInstance->GetTemplateId();
PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
ASSERT_EQ(newTemplateEntityAliases.size(), 1);
// Validate that the entity has exactly 1 component under it.
// Validate that the entity has 2 components under it. One of them is added through HandleEntitiesAdded() in EditorEntityContext.
const PrefabDomValue* entityComponents =
PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsArray());
EXPECT_EQ(entityComponents->GetArray().Size(), 1);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 2);
// Extract the component id of the entity in the Template and verify that it matches with the component id of the entity's component.
PrefabDomValueConstReference entityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*entityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(entityComponentIdValue.has_value());
EXPECT_EQ(prefabTestComponent->GetId(), entityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*entityComponents, prefabTestComponent->GetId());
// Instantiate Instances and validate if all Instances have the entity.
const int numberOfInstances = 3;
@@ -359,15 +370,18 @@ namespace UnitTest
newTemplateId, *entityComponents, PrefabTestDomUtils::GetPrefabDomComponentsPath(newTemplateEntityAliases.front()));
// Remove a component from the Instance's entity and use the Instance to update the PrefabDom of Template.
entity->Deactivate();
entity->RemoveComponent(prefabTestComponent);
delete prefabTestComponent;
entity->Activate();
PrefabDom updatedDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
// Validate that the entity does not have any component under it.
// Validate that the entity only has 1 component under it.
entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents == nullptr);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 1);
// Update Template's Instances and validate if all Instances have no component under their entities.
m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
@@ -375,7 +389,6 @@ namespace UnitTest
EXPECT_TRUE(updateResult);
PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
}
TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_ChangeComponentProperty_UpdateSucceeds)
@@ -384,23 +397,22 @@ namespace UnitTest
AZ::Entity* entity = CreateEntity("Entity", false);
PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
entity->AddComponent(prefabTestComponent);
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{entity});
AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
TemplateId newTemplateId = newInstance->GetTemplateId();
PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
ASSERT_EQ(newTemplateEntityAliases.size(), 1);
// Validate that the entity has exactly 1 component under it.
// Validate that the entity has 2 components under it. One of them is added through HandleEntitiesAdded() in EditorEntityContext.
const PrefabDomValue* entityComponents =
PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsArray());
EXPECT_EQ(entityComponents->GetArray().Size(), 1);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 2);
// Extract the component id of the entity in the Template and verify that it matches with the component id of the entity's component.
PrefabDomValueConstReference entityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*entityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(entityComponentIdValue.has_value());
EXPECT_EQ(prefabTestComponent->GetId(), entityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*entityComponents, prefabTestComponent->GetId());
// Instantiate Instances and validate if all Instances have the entity.
const int numberOfInstances = 3;
@@ -425,12 +437,16 @@ namespace UnitTest
// Validate that the prefabTestComponent in the Template's DOM doesn't have a BoolProperty.
// Even though we changed the property to false, it won't be serialized out because it's a default value.
entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsArray());
EXPECT_EQ(entityComponents->GetArray().Size(), 1);
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
EXPECT_EQ(entityComponents->MemberCount(), 2);
PrefabDomValueConstReference entityComponentBoolPropertyValue =
PrefabDomUtils::FindPrefabDomValue(*entityComponents->Begin(), PrefabTestDomUtils::BoolPropertyName);
EXPECT_FALSE(entityComponentBoolPropertyValue.has_value());
AZStd::string componentValueName = AZStd::string::format("Component_[%llu]", prefabTestComponent->GetId());
PrefabDomValueConstReference wheelEntityComponentValue = PrefabDomUtils::FindPrefabDomValue(*entityComponents, componentValueName.c_str());
ASSERT_TRUE(wheelEntityComponentValue);
PrefabDomValueConstReference wheelEntityComponentBoolPropertyValue =
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName);
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
// Update Template's Instances and validate if all Instances have no BoolProperty under their prefabTestComponents in entities.
m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
@@ -438,7 +454,6 @@ namespace UnitTest
EXPECT_TRUE(updateResult);
PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityComponents, entityComponentsPath);
}
}
@@ -11,6 +11,7 @@
*/
#include <AzCore/Component/TransformBus.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <Prefab/PrefabTestComponent.h>
#include <Prefab/PrefabTestDomUtils.h>
@@ -65,6 +66,7 @@ namespace UnitTest
PrefabDom updatedWheelInstance;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*wheelIsolatedInstance, updatedWheelInstance));
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstance);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the wheel template has the same entities(2) as the updated instance.
wheelTemplateEntityAliases = wheelIsolatedInstance->GetEntityAliases();
@@ -85,6 +87,8 @@ namespace UnitTest
{
// Create a single entity wheel instance and create a template out of it.
AZ::Entity* wheelEntity = CreateEntity("WheelEntity1");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{wheelEntity});
AZStd::unique_ptr<Instance> wheelIsolatedInstance = m_prefabSystemComponent->CreatePrefab({ wheelEntity },
{}, WheelPrefabMockFilePath);
const TemplateId wheelTemplateId = wheelIsolatedInstance->GetTemplateId();
@@ -116,13 +120,14 @@ namespace UnitTest
PrefabDom updatedAxleInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*axleInstance, updatedAxleInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(axleTemplateId, updatedAxleInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that there are 2 wheel instances under axle
wheelInstanceAliasesUnderAxle = axleInstance->GetNestedInstanceAliases(wheelTemplateId);
ASSERT_EQ(wheelInstanceAliasesUnderAxle.size(), 2);
// Validate that the wheels under the axle have the same DOM as the wheel template.
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom);
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom, false);
// Validate that the axles under the car have the same DOM as the axle template.
PrefabTestDomUtils::ValidatePrefabDomInstances(axleInstanceAliasesUnderCar, carTemplateDom, axleTemplateDom);
@@ -170,17 +175,15 @@ namespace UnitTest
PrefabDom updatedWheelInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*wheelIsolatedInstance, updatedWheelInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the wheel entity does have a component under it.
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsArray());
EXPECT_EQ(wheelEntityComponents->GetArray().Size(), 1);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
EXPECT_EQ(wheelEntityComponents->MemberCount(), 1);
// Extract the component id of the entity in wheel template and verify that it matches with the component id of the wheel instance.
PrefabDomValueReference wheelEntityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(wheelEntityComponentIdValue.has_value());
EXPECT_EQ(expectedComponentId, wheelEntityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*wheelEntityComponents, expectedComponentId);
// Validate that the wheels under the axle have the same DOM as the wheel template.
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom);
@@ -225,6 +228,7 @@ namespace UnitTest
PrefabDom updatedWheelInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*wheelIsolatedInstance, updatedWheelInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the wheel template only has 1 entity now.
wheelTemplateEntityAliases = wheelIsolatedInstance->GetEntityAliases();
@@ -242,6 +246,8 @@ namespace UnitTest
{
// Create a single entity wheel instance and create a template out of it.
AZ::Entity* wheelEntity = CreateEntity("WheelEntity1");
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{wheelEntity});
AZStd::unique_ptr<Instance> wheelIsolatedInstance = m_prefabSystemComponent->CreatePrefab({ wheelEntity },
{}, WheelPrefabMockFilePath);
const TemplateId wheelTemplateId = wheelIsolatedInstance->GetTemplateId();
@@ -275,6 +281,7 @@ namespace UnitTest
PrefabDom updatedAxleInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*axleInstance, updatedAxleInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(axleTemplateId, updatedAxleInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that there is only 1 wheel instances under axle
wheelInstanceAliasesUnderAxle = axleInstance->GetNestedInstanceAliases(wheelTemplateId);
@@ -282,7 +289,7 @@ namespace UnitTest
EXPECT_EQ(wheelInstanceAliasesUnderAxle.front(), aliasOfWheelInstanceToRetain);
// Validate that the wheels under the axle have the same DOM as the wheel template.
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom);
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom, false);
// Validate that the axles under the car have the same DOM as the axle template.
PrefabTestDomUtils::ValidatePrefabDomInstances(axleInstanceAliasesUnderCar, carTemplateDom, axleTemplateDom);
@@ -307,14 +314,11 @@ namespace UnitTest
AZStd::string entityAlias = wheelTemplateEntityAliases.front();
PrefabDomValue* wheelEntityComponents =
PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsArray());
EXPECT_EQ(wheelEntityComponents->GetArray().Size(), 1);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
EXPECT_EQ(wheelEntityComponents->MemberCount(), 1);
// Extract the component id of the entity in wheel template and verify that it matches with the component id of the wheel instance.
PrefabDomValueReference wheelEntityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(wheelEntityComponentIdValue.has_value());
EXPECT_EQ(prefabTestComponent->GetId(), wheelEntityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*wheelEntityComponents, prefabTestComponent->GetId());
// Create an axle with 0 entities and 1 wheel instance.
AZStd::unique_ptr<Instance> wheel1UnderAxle = m_prefabSystemComponent->InstantiatePrefab(wheelTemplateId);
@@ -337,6 +341,7 @@ namespace UnitTest
PrefabDom updatedWheelInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*wheelIsolatedInstance, updatedWheelInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the wheel entity does not have a component under it.
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
@@ -370,14 +375,11 @@ namespace UnitTest
AZStd::string entityAlias = wheelTemplateEntityAliases.front();
PrefabDomValue* wheelEntityComponents =
PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsArray());
EXPECT_EQ(wheelEntityComponents->GetArray().Size(), 1);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
EXPECT_EQ(wheelEntityComponents->MemberCount(), 1);
// Extract the component id of the entity in wheel template and verify that it matches with the component id of the wheel instance.
PrefabDomValueReference wheelEntityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(wheelEntityComponentIdValue.has_value());
EXPECT_EQ(prefabTestComponent->GetId(), wheelEntityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*wheelEntityComponents, prefabTestComponent->GetId());
// Create an axle with 0 entities and 1 wheel instance.
AZStd::unique_ptr<Instance> wheel1UnderAxle = m_prefabSystemComponent->InstantiatePrefab(wheelTemplateId);
@@ -400,15 +402,16 @@ namespace UnitTest
PrefabDom updatedWheelInstanceDom;
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*wheelIsolatedInstance, updatedWheelInstanceDom));
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstanceDom);
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the prefabTestComponent in the wheel template DOM doesn't have a BoolProperty.
// Even though we changed the property to false, it won't be serialized out because it's a default value.
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsArray());
EXPECT_EQ(wheelEntityComponents->GetArray().Size(), 1);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
EXPECT_EQ(wheelEntityComponents->MemberCount(), 1);
PrefabDomValueReference wheelEntityComponentBoolPropertyValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::BoolPropertyName);
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponents->MemberBegin()->value, PrefabTestDomUtils::BoolPropertyName);
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
// Validate that the wheels under the axle have the same DOM as the wheel template.
@@ -16,6 +16,7 @@
#include <Prefab/PrefabTestFixture.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
namespace UnitTest
{
@@ -34,8 +35,10 @@ namespace UnitTest
AZ::Entity* wheelEntity = CreateEntity("WheelEntity1", false);
PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
wheelEntity->AddComponent(prefabTestComponent);
wheelEntity->Init();
wheelEntity->Activate();
AZ::ComponentId prefabTestComponentId = prefabTestComponent->GetId();
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, AzToolsFramework::EntityList{wheelEntity});
AZStd::unique_ptr<Instance> wheelIsolatedInstance = m_prefabSystemComponent->CreatePrefab({ wheelEntity },
{}, WheelPrefabMockFilePath);
const TemplateId wheelTemplateId = wheelIsolatedInstance->GetTemplateId();
@@ -45,18 +48,15 @@ namespace UnitTest
// Validate that the wheel template has the same entities(1) as the instance it was created from.
ASSERT_EQ(wheelTemplateEntityAliases.size(), 1);
// Validate that the wheel entity has 1 component under it.
// Validate that the wheel entity has 2 components. One of them is added through HandleEntitiesAdded() in EditorEntityContext.
EntityAlias wheelEntityAlias = wheelTemplateEntityAliases.front();
PrefabDomValue* wheelEntityComponents =
PrefabTestDomUtils::GetPrefabDomComponentsPath(wheelEntityAlias).Get(wheelTemplateDom);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsArray());
EXPECT_EQ(wheelEntityComponents->GetArray().Size(), 1);
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
EXPECT_EQ(wheelEntityComponents->MemberCount(), 2);
// Extract the component id of the entity in wheel template and verify that it matches with the component id of the wheel instance.
PrefabDomValueReference wheelEntityComponentIdValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::ComponentIdName);
ASSERT_TRUE(wheelEntityComponentIdValue.has_value());
EXPECT_EQ(prefabTestComponent->GetId(), wheelEntityComponentIdValue->get().GetUint64());
PrefabTestDomUtils::ValidateComponentsDomHasId(*wheelEntityComponents, prefabTestComponentId);
// Create an axle with 0 entities and 1 wheel instance.
AZStd::unique_ptr<Instance> wheel1UnderAxle = m_prefabSystemComponent->InstantiatePrefab(wheelTemplateId);
@@ -77,10 +77,6 @@ namespace UnitTest
const AZStd::vector<InstanceAlias> axleInstanceAliasesUnderCar = carInstance->GetNestedInstanceAliases(axleTemplateId);
PrefabDom& carTemplateDom = m_prefabSystemComponent->FindTemplateDom(carTemplateId);
//activate the entity so we can access via transform bus
axleInstance->InitializeNestedEntities();
axleInstance->ActivateNestedEntities();
InstanceOptionalReference nestedWheelInstanceRef = axleInstance->FindNestedInstance(wheelInstanceAliasesUnderAxle[0]);
ASSERT_TRUE(nestedWheelInstanceRef);
@@ -97,7 +93,19 @@ namespace UnitTest
// Retrieve the entity pointer from the component application bus.
AZ::Entity* wheelEntityUnderAxle = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(wheelEntityUnderAxle, &AZ::ComponentApplicationBus::Events::FindEntity, wheelEntityIdUnderAxle);
axleInstance->GetNestedEntities([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr<AZ::Entity>& entity)
{
if (entity->GetId() == wheelEntityIdUnderAxle)
{
wheelEntityUnderAxle = entity.get();
return false;
}
else
{
return true;
}
});
ASSERT_NE(nullptr, wheelEntityUnderAxle);
//create document with before change snapshot
PrefabDom entityDomBefore;
@@ -117,6 +125,7 @@ namespace UnitTest
InstanceOptionalReference wheelInstanceUnderAxle = axleInstance->FindNestedInstance(wheelInstanceAliasesUnderAxle.front());
m_instanceToTemplateInterface->GeneratePatchForLink(patches, entityDomBefore, entityDomAfter, wheelInstanceUnderAxle->get().GetLinkId());
m_instanceToTemplateInterface->ApplyPatchesToInstance(wheelEntityIdUnderAxle, patches, topMostInstanceInHierarchy->get());
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Validate that the prefabTestComponent in the wheel instance under axle doesn't have a BoolProperty.
// Even though we changed the property to false, it won't be serialized out because it's a default value.
@@ -124,8 +133,13 @@ namespace UnitTest
PrefabTestDomUtils::GetPrefabDomInstancePath(wheelInstanceAliasesUnderAxle.front()).Get(axleTemplateDom);
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(wheelEntityAlias).Get(*wheelInstanceDomUnderAxle);
ASSERT_TRUE(wheelEntityComponents != nullptr);
AZStd::string componentValueName = AZStd::string::format("Component_[%llu]", prefabTestComponentId);
PrefabDomValueReference wheelEntityComponentValue = PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents, componentValueName.c_str());
ASSERT_TRUE(wheelEntityComponentValue);
PrefabDomValueReference wheelEntityComponentBoolPropertyValue =
PrefabDomUtils::FindPrefabDomValue(*wheelEntityComponents->Begin(), PrefabTestDomUtils::BoolPropertyName);
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName);
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
// Validate that the axles under the car have the same DOM as the axle template.
@@ -23,7 +23,8 @@ namespace UnitTest
{
AZStd::vector<AZ::Entity*> entitiesCreated;
AZStd::unordered_set<AZStd::string> expectedEntityNameSet;
for (int i = 0; i < 3; i++)
const int normalEntityCount = 3;
for (int i = 0; i < normalEntityCount; i++)
{
entitiesCreated.push_back(CreateEntity(AZStd::string::format("Entity_%i", i).c_str()));
expectedEntityNameSet.insert(entitiesCreated.back()->GetName());
@@ -33,17 +34,21 @@ namespace UnitTest
m_prefabSystemComponent->CreatePrefab(entitiesCreated, {}, "test/path"));
ASSERT_TRUE(instance);
ASSERT_TRUE(instance->HasContainerEntity());
auto& containerEntity = instance->GetContainerEntity()->get();
expectedEntityNameSet.insert(containerEntity.GetName());
//Create Spawnable
auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId());
auto spawnable = ::AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(prefabDom);
EXPECT_EQ(spawnable.GetEntities().size(), 3);
EXPECT_EQ(spawnable.GetEntities().size() - 1, normalEntityCount); // 1 for container entity
const auto& spawnableEntities = spawnable.GetEntities();
AZStd::unordered_set<AZStd::string> actualEntityNameSet;
for (int i = 0; i < 3; i++)
for (const auto& spawnableEntity : spawnableEntities)
{
actualEntityNameSet.insert(spawnableEntities[i]->GetName());
actualEntityNameSet.insert(spawnableEntity->GetName());
}
EXPECT_EQ(expectedEntityNameSet, actualEntityNameSet);
@@ -53,7 +58,8 @@ namespace UnitTest
{
AZStd::vector<AZ::Entity*> entitiesCreated;
AZStd::unordered_set<AZStd::string> expectedEntityNameSet;
for (int i = 0; i < 3; i++)
const int normalEntityCount = 3;
for (int i = 0; i < normalEntityCount; i++)
{
entitiesCreated.push_back(CreateEntity(AZStd::string::format("Entity_%i", i).c_str()));
expectedEntityNameSet.insert(entitiesCreated.back()->GetName());
@@ -72,17 +78,21 @@ namespace UnitTest
m_prefabSystemComponent->CreatePrefab({ entitiesCreated[2] }, MakeInstanceList(AZStd::move(secondInstance)), "test/path3"));
ASSERT_TRUE(thirdInstance);
ASSERT_TRUE(thirdInstance->HasContainerEntity());
auto& containerEntity = thirdInstance->GetContainerEntity()->get();
expectedEntityNameSet.insert(containerEntity.GetName());
//Create Spawnable
auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(thirdInstance->GetTemplateId());
auto spawnable = ::AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(prefabDom);
EXPECT_EQ(spawnable.GetEntities().size(), 3);
EXPECT_EQ(spawnable.GetEntities().size() - 1, normalEntityCount); // 1 for container entity
const auto& spawnableEntities = spawnable.GetEntities();
AZStd::unordered_set<AZStd::string> actualEntityNameSet;
for (int i = 0; i < 3; i++)
for (const auto& spawnableEntity : spawnableEntities)
{
actualEntityNameSet.insert(spawnableEntities[i]->GetName());
actualEntityNameSet.insert(spawnableEntity->GetName());
}
EXPECT_EQ(expectedEntityNameSet, actualEntityNameSet);
@@ -211,7 +211,7 @@ namespace UnitTest
EXPECT_EQ(expectedResult, actualResult);
AZStd::unique_ptr<Instance> convertedInstance(aznew Instance());
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom, false));
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom));
convertedInstance->DetachNestedEntities(
[this](AZStd::unique_ptr<AZ::Entity> entity)
@@ -117,7 +117,7 @@ namespace UnitTest
AZ::SerializeContext* m_serializeContext{ nullptr };
PrefabSystemComponent* m_prefabSystemComponent{ nullptr };
PrefabConversionUtils::EditorInfoRemover m_editorInfoRemover;
PrefabConversionUtils::PrefabProcessorContext m_prefabProcessorContext;
PrefabConversionUtils::PrefabProcessorContext m_prefabProcessorContext{ AZ::Uuid::CreateRandom() };
PrefabDom m_prefabDom;
};
}