123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- /*
- * 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 <AzCore/std/smart_ptr/unique_ptr.h>
- #include <AzTest/AzTest.h>
- #include <AzToolsFramework/Undo/UndoSystem.h>
- using namespace AZ;
- using namespace AzToolsFramework;
- using namespace AzToolsFramework::UndoSystem;
- namespace UnitTest
- {
- class SequencePointTest
- : public URSequencePoint
- {
- public:
- AZ_CLASS_ALLOCATOR(SequencePointTest, AZ::SystemAllocator)
- SequencePointTest(AZStd::string friendlyName, URCommandID id)
- : URSequencePoint(friendlyName, id)
- {}
- bool Changed() const override { return true; }
- void Redo() override { m_redoCalled = true; }
- void Undo() override { m_undoCalled = true; }
- using URSequencePoint::RemoveChild;
- bool m_redoCalled = false;
- bool m_undoCalled = false;
- };
- class DifferentTypeSequencePointTest
- : public URSequencePoint
- {
- public:
- AZ_RTTI(DifferentTypeSequencePointTest, "{D7A42B6F-DCF8-443F-B4F1-57731B1D3CB8}")
- DifferentTypeSequencePointTest(AZStd::string friendlyName, URCommandID id)
- : URSequencePoint(friendlyName, id)
- {}
- bool Changed() const override { return true; }
- };
- ///////////////////////////////////////////////////////////////////////////
- // URSequencePoint
- ///////////////////////////////////////////////////////////////////////////
- TEST(URSequencePoint, Find_IdAndTypeNotPresent_ExpectNullptr)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- auto result = parent->Find(6, AZ::Uuid::Create());
- EXPECT_FALSE(result);
- }
- TEST(URSequencePoint, Find_TypeNotPresent_ExpectNullptr)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- auto result = parent->Find(5, AZ::Uuid::Create());
- EXPECT_FALSE(result);
- }
- TEST(URSequencePoint, Find_IdNotPresent_ExpectNullptr)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew DifferentTypeSequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- auto result = parent->Find(6, AZ::Uuid("{D7A42B6F-DCF8-443F-B4F1-57731B1D3CB8}"));
- EXPECT_FALSE(result);
- }
- TEST(URSequencePoint, Find_MatchIsDirectChild_IdFound)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew DifferentTypeSequencePointTest("Child", static_cast<AZ::u64>(2));
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- auto result = parent->Find(2, AZ::AzTypeInfo<DifferentTypeSequencePointTest>::Uuid());
- EXPECT_EQ(result, child_2);
- }
- TEST(URSequencePoint, Find_IdIsIndirectChild_IdFound)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew DifferentTypeSequencePointTest("Child", static_cast<AZ::u64>(2));
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew DifferentTypeSequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- auto result = parent->Find(5, AZ::AzTypeInfo<DifferentTypeSequencePointTest>::Uuid());
- EXPECT_EQ(result, child_1_2);
- }
- TEST(URSequencePoint, RemoveChild)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_4 = aznew SequencePointTest("Child", 4);
- auto child_5 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_4->SetParent(parent.get());
- child_5->SetParent(parent.get());
- EXPECT_THAT(parent->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child_1, child_2, child_3, child_4, child_5}));
- parent->RemoveChild(child_5);
- EXPECT_THAT(parent->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child_1, child_2, child_3, child_4}));
- delete child_5;
- // The other children are owned by parent
- }
- TEST(URSequencePoint, SetParent_NotChildOfParent)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child = aznew SequencePointTest("Child", 1);
- child->SetParent(parent.get());
- EXPECT_THAT(parent->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child}));
- }
- TEST(URSequencePoint, SetParent_AlreadyChildOfParent)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_4 = aznew SequencePointTest("Child", 4);
- auto child_5 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_4->SetParent(parent.get());
- child_5->SetParent(parent.get());
- EXPECT_THAT(parent->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child_1, child_2, child_3, child_4, child_5}));
- child_5->SetParent(parent.get());
- EXPECT_THAT(parent->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child_1, child_2, child_3, child_4, child_5})) << "the parent did not de-dupe its children";
- }
- TEST(URSequencePoint, SetParent_AlreadyChildOfDifferentParent)
- {
- auto parent_1 = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto parent_2 = AZStd::make_unique<SequencePointTest>("Parent", 1);
- auto child = aznew SequencePointTest("Child", 5);
- child->SetParent(parent_1.get());
- EXPECT_THAT(parent_1->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child}));
- child->SetParent(parent_2.get());
- EXPECT_THAT(parent_1->GetChildren(), ::testing::IsEmpty()) << "the original parent did not remove the child";
- EXPECT_THAT(parent_2->GetChildren(), ::testing::Pointwise(::testing::Eq(), {child})) << "child was not added to new parent properly";
- }
- TEST(URSequencePoint, RunUndo_NoChildren_UndoIsCalled)
- {
- auto object = AZStd::make_unique<SequencePointTest>("Object", 0);
- object->m_undoCalled = false;
- object->RunUndo();
- EXPECT_TRUE(object->m_undoCalled) << "Undo was not called on the object";
- }
- TEST(URSequencePoint, RunUndo_HasChildren_UndoIsCalled)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_1_1 = aznew SequencePointTest("Child", 3);
- auto child_1_2 = aznew SequencePointTest("Child", 4);
- parent->m_undoCalled = false;
- child_1->SetParent(parent.get());
- child_1->m_undoCalled = false;
- child_2->SetParent(parent.get());
- child_2->m_undoCalled = false;
- child_1_1->SetParent(child_1);
- child_1_1->m_undoCalled = false;
- child_1_2->SetParent(child_1);
- child_1_2->m_undoCalled = false;
- parent->RunUndo();
- EXPECT_TRUE(parent->m_undoCalled) << "Undo was not called on the parent";
- EXPECT_TRUE(child_1->m_undoCalled) << "Undo was not called on the child";
- EXPECT_TRUE(child_2->m_undoCalled) << "Undo was not called on the child";
- EXPECT_TRUE(child_1_1->m_undoCalled) << "Undo was not called on the grandchild";
- EXPECT_TRUE(child_1_2->m_undoCalled) << "Undo was not called on the grandchild";
- }
- TEST(URSequencePoint, RunRedo_NoChildren_RedoIsCalled)
- {
- auto object = AZStd::make_unique<SequencePointTest>("Object", 0);
- object->m_redoCalled = false;
- object->RunRedo();
- EXPECT_TRUE(object->m_redoCalled) << "Redo was not called on the object";
- }
- TEST(URSequencePoint, RunRedo_HasChildren_RedoIsCalled)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_1_1 = aznew SequencePointTest("Child", 3);
- auto child_1_2 = aznew SequencePointTest("Child", 4);
- parent->m_redoCalled = false;
- child_1->SetParent(parent.get());
- child_1->m_redoCalled = false;
- child_2->SetParent(parent.get());
- child_2->m_redoCalled = false;
- child_1_1->SetParent(child_1);
- child_1_1->m_redoCalled = false;
- child_1_2->SetParent(child_1);
- child_1_2->m_redoCalled = false;
- parent->RunRedo();
- EXPECT_TRUE(parent->m_redoCalled) << "Redo was not called on the parent";
- EXPECT_TRUE(child_1->m_redoCalled) << "Redo was not called on the child";
- EXPECT_TRUE(child_2->m_redoCalled) << "Redo was not called on the child";
- EXPECT_TRUE(child_1_1->m_redoCalled) << "Redo was not called on the grandchild";
- EXPECT_TRUE(child_1_2->m_redoCalled) << "Redo was not called on the grandchild";
- }
- TEST(URSequencePoint, SetName)
- {
- AZStd::string test_1("Test Point");
- AZStd::string test_2("A different Test Point");
- auto testPoint = AZStd::make_unique<SequencePointTest>("Test Point", 0);
- EXPECT_EQ(testPoint->GetName(), test_1);
- testPoint->SetName("A different Test Point");
- EXPECT_EQ(testPoint->GetName(), test_2);
- }
- TEST(URSequencePoint, HasRealChildren_NoChildren_ExpectFalse)
- {
- auto testPoint = AZStd::make_unique<SequencePointTest>("Test Point", 0);
- bool result = testPoint->HasRealChildren();
- EXPECT_FALSE(result);
- }
- TEST(URSequencePoint, HasRealChildren_AllChildrenAreFake_ExpectFalse)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- bool result = parent->HasRealChildren();
- EXPECT_FALSE(result);
- }
- TEST(URSequencePoint, HasRealChildren_OneChildIsReal_ExpectTrue)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew DifferentTypeSequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew SequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- bool result = parent->HasRealChildren();
- EXPECT_TRUE(result);
- }
- TEST(URSequencePoint, HasRealChildren_OneGrandChildIsReal_ExpectTrue)
- {
- auto parent = AZStd::make_unique<SequencePointTest>("Parent", 0);
- auto child_1 = aznew SequencePointTest("Child", 1);
- auto child_2 = aznew SequencePointTest("Child", 2);
- auto child_3 = aznew SequencePointTest("Child", 3);
- auto child_1_1 = aznew SequencePointTest("Child", 4);
- auto child_1_2 = aznew DifferentTypeSequencePointTest("Child", 5);
- child_1->SetParent(parent.get());
- child_2->SetParent(parent.get());
- child_3->SetParent(parent.get());
- child_1_1->SetParent(child_1);
- child_1_2->SetParent(child_1);
- bool result = parent->HasRealChildren();
- EXPECT_TRUE(result);
- }
- ///////////////////////////////////////////////////////////////////////////
- // UndoStack
- ///////////////////////////////////////////////////////////////////////////
- class UndoDestructorTest : public URSequencePoint
- {
- public:
- AZ_CLASS_ALLOCATOR(UndoDestructorTest, AZ::SystemAllocator)
- UndoDestructorTest(bool* completedFlag)
- : URSequencePoint("UndoDestructorTest", 0)
- , m_completedFlag(completedFlag)
- {
- *m_completedFlag = false;
- }
- ~UndoDestructorTest() override
- {
- *m_completedFlag = true;
- }
- bool Changed() const override { return true; }
- private:
- bool* m_completedFlag;
- };
- TEST(UndoStack, UndoRedoMemory)
- {
- UndoStack undoStack(nullptr);
- bool flag = false;
- undoStack.Post(aznew UndoDestructorTest(&flag));
- undoStack.Undo();
- undoStack.Slice();
- EXPECT_EQ(flag, true);
- }
- class UndoIntSetter : public URSequencePoint
- {
- public:
- AZ_CLASS_ALLOCATOR(UndoIntSetter, AZ::SystemAllocator)
- UndoIntSetter(int* value, int newValue)
- : URSequencePoint("UndoIntSetter", 0)
- , m_value(value)
- , m_newValue(newValue)
- , m_oldValue(*value)
- {
- Redo();
- }
- void Undo() override
- {
- *m_value = m_oldValue;
- }
- void Redo() override
- {
- *m_value = m_newValue;
- }
- bool Changed() const override { return true; }
- private:
- int* m_value;
- int m_newValue;
- int m_oldValue;
- };
- TEST(UndoStack, UndoRedoSequence)
- {
- UndoStack undoStack(nullptr);
- int tracker = 0;
- undoStack.Post(aznew UndoIntSetter(&tracker, 1));
- EXPECT_EQ(tracker, 1);
- undoStack.Undo();
- EXPECT_EQ(tracker, 0);
- undoStack.Redo();
- EXPECT_EQ(tracker, 1);
- undoStack.Undo();
- EXPECT_EQ(tracker, 0);
- undoStack.Redo();
- EXPECT_EQ(tracker, 1);
- undoStack.Post(aznew UndoIntSetter(&tracker, 100));
- EXPECT_EQ(tracker, 100);
- undoStack.Undo();
- EXPECT_EQ(tracker, 1);
- undoStack.Undo();
- EXPECT_EQ(tracker, 0);
- undoStack.Redo();
- EXPECT_EQ(tracker, 1);
- }
- TEST(UndoStack, UndoRedoLotsOfUndos)
- {
- UndoStack undoStack(nullptr);
- int tracker = 0;
- const int numUndos = 1000;
- for (int i = 0; i < 1000; i++)
- {
- undoStack.Post(aznew UndoIntSetter(&tracker, i + 1));
- EXPECT_EQ(tracker, i + 1);
- }
- int counter = 0;
- while (undoStack.CanUndo())
- {
- undoStack.Undo();
- counter++;
- }
- EXPECT_EQ(numUndos, counter);
- EXPECT_EQ(tracker, 0);
- counter = 0;
- while (undoStack.CanRedo())
- {
- undoStack.Redo();
- counter++;
- }
- EXPECT_EQ(numUndos, counter);
- EXPECT_EQ(tracker, numUndos);
- }
- }
|