123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /*
- * 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 <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h>
- namespace ScriptCanvas::Developer
- {
- /////////////////////////////////
- // EditorAutomationActionRunner
- /////////////////////////////////
- EditorAutomationActionRunner::~EditorAutomationActionRunner()
- {
- Reset();
- }
- void EditorAutomationActionRunner::Reset()
- {
- for (EditorAutomationAction* deleteAction : m_actionsToDelete)
- {
- delete deleteAction;
- }
- m_actionsToDelete.clear();
- while (!m_executionStack.empty())
- {
- m_executionStack.erase(m_executionStack.begin());
- }
- m_errorReports.clear();
- m_currentAction = nullptr;
- }
- bool EditorAutomationActionRunner::Tick()
- {
- if (m_currentAction == nullptr)
- {
- if (m_executionStack.empty())
- {
- return true;
- }
- else
- {
- m_currentAction = m_executionStack.front();
- while (m_currentAction->IsMissingPrecondition())
- {
- if (m_currentAction->IsAtPreconditionLimit())
- {
- ActionReport failureReport;
- failureReport = AZ::Failure<AZStd::string>("Action failed to setup its preconditions in a reasonable amount of iterations. Exiting test.");
- m_errorReports.emplace_back(failureReport);
- m_currentAction->ResetPreconditionAttempts();
- // Leak elements, then we'll just exit through normal paths next tick.
- m_executionStack.clear();
- return false;
- }
- else
- {
- EditorAutomationAction* newAction = m_currentAction->GenerationPreconditionActions();
- m_actionsToDelete.emplace(newAction);
- if (newAction)
- {
- m_currentAction = newAction;
- m_executionStack.insert(m_executionStack.begin(), newAction);
- }
- }
- }
- // Erase our current front of stack, as that is our current action.
- m_executionStack.erase(m_executionStack.begin());
- AZ_Assert(m_currentAction, "Current Action should not be null at this point.");
- if (m_currentAction == nullptr)
- {
- // Leak all the memory. We'll just exit through the normal path next tick.
- m_executionStack.clear();
- return true;
- }
- else
- {
- m_currentAction->SignalActionBegin();
- }
- }
- }
- if (m_currentAction)
- {
- if (m_currentAction->Tick())
- {
- ActionReport errorReport = m_currentAction->GenerateReport();
- if (!errorReport.IsSuccess())
- {
- m_errorReports.emplace_back(errorReport);
- }
- m_currentAction = nullptr;
- }
- }
- return false;
- }
- void EditorAutomationActionRunner::AddAction(EditorAutomationAction* actionToRun)
- {
- m_executionStack.emplace_back(actionToRun);
- }
- bool EditorAutomationActionRunner::HasActions() const
- {
- return !m_executionStack.empty();
- }
- bool EditorAutomationActionRunner::HasErrors() const
- {
- return !m_errorReports.empty();
- }
- const AZStd::vector< ActionReport >& EditorAutomationActionRunner::GetErrors() const
- {
- return m_errorReports;
- }
- ///////////////
- // StateModel
- ///////////////
- const AZStd::any* StateModel::FindStateData(const DataKey& dataId) const
- {
- auto dataIter = m_stateData.find(dataId);
- if (dataIter != m_stateData.end())
- {
- return &dataIter->second;
- }
- return nullptr;
- }
- void StateModel::ClearModelData()
- {
- m_stateData.clear();
- }
- /////////////////////////
- // EditorAutomationTest
- /////////////////////////
- EditorAutomationTest::EditorAutomationTest(QString testName)
- : m_testName(testName)
- {
- }
- EditorAutomationTest::~EditorAutomationTest()
- {
- for (const auto& statePair : m_states)
- {
- delete statePair.second;
- }
- m_states.clear();
- }
- void EditorAutomationTest::StartTest()
- {
- m_hasRun = true;
- m_testErrors.clear();
- OnTestStarting();
- m_stateId = m_initialStateId;
- m_actionRunner.Reset();
- if (SetupState(m_stateId))
- {
- AZ::SystemTickBus::Handler::BusConnect();
- }
- else
- {
- OnTestComplete();
- }
- }
- void EditorAutomationTest::OnSystemTick()
- {
- if (m_actionRunner.Tick())
- {
- if (!HasErrors())
- {
- if (m_actionRunner.HasErrors())
- {
- const AZStd::vector<ActionReport>& actionErrors = m_actionRunner.GetErrors();
- for (const ActionReport& actionErrorReport : actionErrors)
- {
- AddError(actionErrorReport.GetError());
- }
- }
- else
- {
- m_currentState->StateActionsComplete();
- if (m_currentState->HasErrors())
- {
- AddError(m_currentState->GetError());
- }
- m_currentState = nullptr;
- }
- //++m_state;
- m_actionRunner.Reset();
- if (!HasErrors())
- {
- OnStateComplete(m_stateId);
- int nextStateId = FindNextState(m_stateId);
- if (!SetupState(nextStateId))
- {
- AZ::SystemTickBus::Handler::BusDisconnect();
- OnTestComplete();
- }
- }
- else
- {
- AZ::SystemTickBus::Handler::BusDisconnect();
- OnTestComplete();
- }
- }
- else
- {
- AZ::SystemTickBus::Handler::BusDisconnect();
- OnTestComplete();
- }
- }
- }
- void EditorAutomationTest::AddState(EditorAutomationState* newState)
- {
- int stateId = newState->GetStateId();
- if (stateId == EditorAutomationState::EXIT_STATE_ID)
- {
- AZ_Error("EditorAutomationTest", false, "Trying to use reserved exit state id");
- delete newState;
- return;
- }
- auto stateIter = m_states.find(stateId);
- if (stateIter != m_states.end())
- {
- AZ_Error("EditorAutomationTest", false, "Collision on StateId %i found. Maintaining first state with id", stateId);
- delete newState;
- return;
- }
- m_registrationOrder.emplace_back(stateId);
- m_states[stateId] = newState;
- newState->SetStateModel(this);
- if (m_initialStateId == EditorAutomationState::EXIT_STATE_ID)
- {
- m_initialStateId = stateId;
- }
- }
- void EditorAutomationTest::SetHasCustomTransitions(bool hasCustomTransition)
- {
- m_hasCustomTransitions = hasCustomTransition;
- }
- bool EditorAutomationTest::HasRun() const
- {
- return m_hasRun;
- }
- bool EditorAutomationTest::IsRunning() const
- {
- return AZ::SystemTickBus::Handler::BusIsConnected();
- }
- bool EditorAutomationTest::SetupState(int stateId)
- {
- m_stateId = EditorAutomationState::EXIT_STATE_ID;
- m_currentState = nullptr;
- auto stateIter = m_states.find(stateId);
- if (stateIter != m_states.end())
- {
- m_currentState = stateIter->second;
- }
- if (m_currentState)
- {
- m_stateId = stateId;
- m_actionRunner.Reset();
- m_currentState->SetupStateActions(m_actionRunner);
- }
- return m_currentState != nullptr;
- }
- int EditorAutomationTest::FindNextState(int stateId)
- {
- int nextStateId = EditorAutomationState::EXIT_STATE_ID;
- if (m_hasCustomTransitions)
- {
- nextStateId = EvaluateTransition(stateId);
- }
- else
- {
- // Do a minus one here, so we can just blindly add 1 instead of needing to safety check it.
- // We default to EXIT so the result is the same.
- for (int i = 0; i < m_registrationOrder.size() - 1; ++i)
- {
- if (m_registrationOrder[i] == stateId)
- {
- nextStateId = m_registrationOrder[i + 1];
- }
- }
- }
- return nextStateId;
- }
- void EditorAutomationTest::AddError(AZStd::string error)
- {
- AZ_TracePrintf("EditorAutomationTestDialog", "Error in %s :: %s", m_testName.toUtf8().data(), error.c_str());
- m_testErrors.emplace_back(error);
- }
- }
|