Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,76 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzTest/AzTest.h>
namespace ScriptCanvasTests
{
class EntityRefTestEvents : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = AZ::EntityId;
virtual void TestEvent(AZ::EntityId, bool) = 0;
};
using EntityRefTestEventBus = AZ::EBus<EntityRefTestEvents>;
class TestComponent : public AZ::Component
, EntityRefTestEventBus::Handler
{
public:
AZ_COMPONENT(TestComponent, "{527680AE-BF46-4BC8-A923-A39B458A3B53}", AZ::Component);
void Init() override {}
void Activate() override
{
EntityRefTestEventBus::Handler::BusConnect(GetEntityId());
}
void Deactivate() override
{
EntityRefTestEventBus::Handler::BusDisconnect();
}
void TestEvent(AZ::EntityId referencedEntity, bool shouldBeSelf) override
{
// validate entity
if (shouldBeSelf)
{
EXPECT_TRUE(GetEntity()->GetId() == referencedEntity);
}
AZ_TracePrintf("Script Canvas", "TestEvent handled by: %s\n", GetEntity()->GetName().c_str());
}
static void Reflect(AZ::ReflectContext* reflection)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
if (serializeContext)
{
serializeContext->Class<TestComponent, AZ::Component>()
->Version(0)
;
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflection);
if (behaviorContext)
{
behaviorContext->EBus<EntityRefTestEventBus>("EntityRefTestEventBus")
->Event("TestEvent", &EntityRefTestEvents::TestEvent)
;
}
}
};
}
@@ -0,0 +1,48 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Editor/Framework/ScriptCanvasGraphUtilities.h>
#include "EntityRefTests.h"
#include <Asset/EditorAssetSystemComponent.h>
#include <AzFramework/Application/Application.h>
#include <ScriptCanvas/SystemComponent.h>
namespace ScriptCanvasTests
{
class Application
: public AzFramework::Application
{
public:
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
AZ::ComponentTypeList components = AzFramework::Application::GetRequiredSystemComponents();
components.insert(components.end(),
{
azrtti_typeid<ScriptCanvasTests::TestComponent>(),
azrtti_typeid<ScriptCanvasEditor::TraceMessageComponent>(),
});
return components;
}
void CreateReflectionManager() override
{
AzFramework::Application::CreateReflectionManager();
RegisterComponentDescriptor(ScriptCanvasTests::TestComponent::CreateDescriptor());
RegisterComponentDescriptor(ScriptCanvasEditor::TraceMessageComponent::CreateDescriptor());
}
};
}
@@ -0,0 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ScriptCanvasTestFixture.h"
namespace ScriptCanvasTests
{
Application* ScriptCanvasTestFixture::s_application = nullptr;
UnitTest::AllocatorsBase ScriptCanvasTestFixture::s_allocatorSetup = {};
AZStd::atomic_bool ScriptCanvasTestFixture::s_asyncOperationActive = {};
bool ScriptCanvasTestFixture::s_setupSucceeded = false;
}
@@ -0,0 +1,416 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "ScriptCanvasTestApplication.h"
#include "ScriptCanvasTestNodes.h"
#include "EntityRefTests.h"
#include "ScriptCanvasTestUtilities.h"
#include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Core/SlotConfigurationDefaults.h>
#include <AzTest/AzTest.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Driller/Driller.h>
#include <AzCore/Memory/MemoryDriller.h>
#include <ScriptCanvas/ScriptCanvasGem.h>
#include <AzCore/Memory/MemoryComponent.h>
#include <AzCore/Asset/AssetManagerComponent.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <ScriptCanvas/SystemComponent.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#define SC_EXPECT_DOUBLE_EQ(candidate, reference) EXPECT_NEAR(candidate, reference, 0.001)
#define SC_EXPECT_FLOAT_EQ(candidate, reference) EXPECT_NEAR(candidate, reference, 0.001f)
namespace ScriptCanvasTests
{
class ScriptCanvasTestFixture
: public ::testing::Test
, protected NodeAccessor
{
public:
static AZStd::atomic_bool s_asyncOperationActive;
protected:
static ScriptCanvasTests::Application* s_application;
static void SetUpTestCase()
{
s_allocatorSetup.SetupAllocator();
s_asyncOperationActive = false;
if (s_application == nullptr)
{
AZ::ComponentApplication::StartupParameters appStartup;
s_application = aznew ScriptCanvasTests::Application();
{
ScriptCanvasEditor::TraceSuppressionBus::Broadcast(&ScriptCanvasEditor::TraceSuppressionRequests::SuppressPrintf, true);
AZ::ComponentApplication::Descriptor descriptor;
descriptor.m_enableDrilling = false;
descriptor.m_useExistingAllocator = true;
AZ::DynamicModuleDescriptor dynamicModuleDescriptor;
dynamicModuleDescriptor.m_dynamicLibraryPath = "Gem.GraphCanvas.Editor.875b6fcbdeea44deaae7984ad9bb6cdc.v0.1.0";
descriptor.m_modules.push_back(dynamicModuleDescriptor);
dynamicModuleDescriptor.m_dynamicLibraryPath = "Gem.ScriptCanvasGem.Editor.869a0d0ec11a45c299917d45c81555e6.v0.1.0";
descriptor.m_modules.push_back(dynamicModuleDescriptor);
s_application->Start(descriptor, appStartup);
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
ScriptCanvasEditor::TraceSuppressionBus::Broadcast(&ScriptCanvasEditor::TraceSuppressionRequests::SuppressPrintf, false);
}
}
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "SC unit tests require filehandling");
if (!fileIO->GetAlias("@engroot@"))
{
const char* engineRoot = nullptr;
AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
AZ_Assert(engineRoot, "null engine root");
fileIO->SetAlias("@engroot@", engineRoot);
}
s_setupSucceeded = fileIO->GetAlias("@engroot@") != nullptr;
AZ::TickBus::AllowFunctionQueuing(true);
}
static void TearDownTestCase()
{
// don't hang on to dangling assets
AZ::Data::AssetManager::Instance().DispatchEvents();
if (AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance())
{
fileIO->DestroyPath(k_tempCoreAssetDir);
}
if (s_application)
{
s_application->Stop();
delete s_application;
s_application = nullptr;
}
s_allocatorSetup.TeardownAllocator();
}
template<class T>
void RegisterComponentDescriptor()
{
AZ::ComponentDescriptor* descriptor = T::CreateDescriptor();
auto insertResult = m_descriptors.insert(descriptor);
if (insertResult.second)
{
GetApplication()->RegisterComponentDescriptor(descriptor);
}
}
void SetUp() override
{
ASSERT_TRUE(s_setupSucceeded) << "ScriptCanvasTestFixture set up failed, unit tests can't work properly";
m_serializeContext = s_application->GetSerializeContext();
m_behaviorContext = s_application->GetBehaviorContext();
AZ_Assert(AZ::IO::FileIOBase::GetInstance(), "File IO was not properly installed");
RegisterComponentDescriptor<TestNodes::TestResult>();
RegisterComponentDescriptor<TestNodes::ConfigurableUnitTestNode>();
m_numericVectorType = ScriptCanvas::Data::Type::BehaviorContextObject(azrtti_typeid<AZStd::vector<ScriptCanvas::Data::NumberType>>());
m_stringToNumberMapType = ScriptCanvas::Data::Type::BehaviorContextObject(azrtti_typeid<AZStd::unordered_map<ScriptCanvas::Data::StringType, ScriptCanvas::Data::NumberType>>());
m_dataSlotConfigurationType = ScriptCanvas::Data::Type::BehaviorContextObject(azrtti_typeid<ScriptCanvas::DataSlotConfiguration>());
ScriptUnitTestEventHandler::Reflect(m_serializeContext);
ScriptUnitTestEventHandler::Reflect(m_behaviorContext);
}
void TearDown() override
{
ASSERT_TRUE(s_setupSucceeded) << "ScriptCanvasTestFixture set up failed, unit tests can't work properly";
m_serializeContext->EnableRemoveReflection();
m_behaviorContext->EnableRemoveReflection();
ScriptUnitTestEventHandler::Reflect(m_serializeContext);
ScriptUnitTestEventHandler::Reflect(m_behaviorContext);
m_serializeContext->DisableRemoveReflection();
m_behaviorContext->DisableRemoveReflection();
for (AZ::ComponentDescriptor* componentDescriptor : m_descriptors)
{
GetApplication()->UnregisterComponentDescriptor(componentDescriptor);
}
m_descriptors.clear();
delete m_graph;
m_graph = nullptr;
}
ScriptCanvas::Graph* CreateGraph()
{
if (m_graph == nullptr)
{
m_graph = aznew ScriptCanvas::Graph();
m_graph->Init();
}
return m_graph;
}
TestNodes::ConfigurableUnitTestNode* CreateConfigurableNode(AZStd::string entityName = "ConfigurableNodeEntity")
{
AZ::Entity* configurableNodeEntity = new AZ::Entity(entityName.c_str());
auto configurableNode = configurableNodeEntity->CreateComponent<TestNodes::ConfigurableUnitTestNode>();
if (m_graph == nullptr)
{
CreateGraph();
}
configurableNodeEntity->Init();
m_graph->AddNode(configurableNodeEntity->GetId());
return configurableNode;
}
void ReportErrors(ScriptCanvas::Graph* graph, bool expectErrors = false, bool expectIrrecoverableErrors = false)
{
EXPECT_EQ(graph->IsInErrorState(), expectErrors);
EXPECT_EQ(graph->IsInIrrecoverableErrorState(), expectIrrecoverableErrors);
if (graph->IsInErrorState())
{
AZ_TracePrintf("UnitTest", "%s\n", AZStd::string(graph->GetLastErrorDescription()).c_str());
}
}
void TestConnectionBetween(ScriptCanvas::Endpoint sourceEndpoint, ScriptCanvas::Endpoint targetEndpoint, bool isValid = true)
{
EXPECT_EQ(m_graph->CanConnectionExistBetween(sourceEndpoint, targetEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanConnectionExistBetween(targetEndpoint, sourceEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanCreateConnectionBetween(sourceEndpoint, targetEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanCreateConnectionBetween(targetEndpoint, sourceEndpoint).IsSuccess(), isValid);
if (isValid)
{
EXPECT_TRUE(m_graph->ConnectByEndpoint(sourceEndpoint, targetEndpoint));
}
}
void TestIsConnectionPossible(ScriptCanvas::Endpoint sourceEndpoint, ScriptCanvas::Endpoint targetEndpoint, bool isValid = true)
{
EXPECT_EQ(m_graph->CanConnectionExistBetween(sourceEndpoint, targetEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanConnectionExistBetween(targetEndpoint, sourceEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanCreateConnectionBetween(sourceEndpoint, targetEndpoint).IsSuccess(), isValid);
EXPECT_EQ(m_graph->CanCreateConnectionBetween(targetEndpoint, sourceEndpoint).IsSuccess(), isValid);
}
void CreateExecutionFlowBetween(AZStd::vector<TestNodes::ConfigurableUnitTestNode*> unitTestNodes)
{
ScriptCanvas::Slot* previousOutSlot = nullptr;
for (TestNodes::ConfigurableUnitTestNode* testNode : unitTestNodes)
{
{
ScriptCanvas::ExecutionSlotConfiguration inputSlot = ScriptCanvas::CommonSlots::GeneralInSlot();
ScriptCanvas::Slot* slot = testNode->AddTestingSlot(inputSlot);
if (slot && previousOutSlot)
{
TestConnectionBetween(previousOutSlot->GetEndpoint(), slot->GetEndpoint());
}
}
{
ScriptCanvas::ExecutionSlotConfiguration outputSlot = ScriptCanvas::CommonSlots::GeneralOutSlot();
previousOutSlot = testNode->AddTestingSlot(outputSlot);
}
}
}
AZStd::vector< ScriptCanvas::Data::Type > GetContainerDataTypes() const
{
return { m_numericVectorType, m_stringToNumberMapType };
}
ScriptCanvas::Data::Type GetRandomContainerType() const
{
AZStd::vector< ScriptCanvas::Data::Type > containerTypes = GetContainerDataTypes();
// We have no types to randomize. Just return.
if (containerTypes.empty())
{
return m_numericVectorType;
}
int randomIndex = rand() % containerTypes.size();
ScriptCanvas::Data::Type randomType = containerTypes[randomIndex];
AZ_TracePrintf("ScriptCanvasTestFixture", "RandomContainerType: %s\n", randomType.GetAZType().ToString<AZStd::string>().c_str());
return randomType;
}
AZStd::vector< ScriptCanvas::Data::Type > GetPrimitiveTypes() const
{
return{
ScriptCanvas::Data::Type::AABB(),
ScriptCanvas::Data::Type::Boolean(),
ScriptCanvas::Data::Type::Color(),
ScriptCanvas::Data::Type::CRC(),
ScriptCanvas::Data::Type::EntityID(),
ScriptCanvas::Data::Type::Matrix3x3(),
ScriptCanvas::Data::Type::Matrix4x4(),
ScriptCanvas::Data::Type::Number(),
ScriptCanvas::Data::Type::OBB(),
ScriptCanvas::Data::Type::Plane(),
ScriptCanvas::Data::Type::Quaternion(),
ScriptCanvas::Data::Type::String(),
ScriptCanvas::Data::Type::Transform(),
ScriptCanvas::Data::Type::Vector2(),
ScriptCanvas::Data::Type::Vector3(),
ScriptCanvas::Data::Type::Vector4()
};
}
ScriptCanvas::Data::Type GetRandomPrimitiveType() const
{
AZStd::vector< ScriptCanvas::Data::Type > primitiveTypes = GetPrimitiveTypes();
// We have no types to randomize. Just return.
if (primitiveTypes.empty())
{
return ScriptCanvas::Data::Type::Number();
}
int randomIndex = rand() % primitiveTypes.size();
ScriptCanvas::Data::Type randomType = primitiveTypes[randomIndex];
AZ_TracePrintf("ScriptCanvasTestFixture", "RandomPrimitiveType: %s\n", randomType.GetAZType().ToString<AZStd::string>().c_str());
return randomType;
}
AZStd::vector< ScriptCanvas::Data::Type > GetBehaviorObjectTypes() const
{
return {
m_dataSlotConfigurationType
};
}
ScriptCanvas::Data::Type GetRandomObjectType() const
{
AZStd::vector< ScriptCanvas::Data::Type > objectTypes = GetBehaviorObjectTypes();
// We have no types to randomize. Just return.
if (objectTypes.empty())
{
return m_dataSlotConfigurationType;
}
int randomIndex = rand() % objectTypes.size();
ScriptCanvas::Data::Type randomType = objectTypes[randomIndex];
AZ_TracePrintf("ScriptCanvasTestFixture", "RandomObjectType: %s\n", randomType.GetAZType().ToString<AZStd::string>().c_str());
return randomType;
}
AZStd::vector< ScriptCanvas::Data::Type > GetTypes() const
{
auto primitives = GetPrimitiveTypes();
auto containers = GetContainerDataTypes();
auto objects = GetBehaviorObjectTypes();
primitives.reserve(containers.size() + objects.size());
primitives.insert(primitives.end(), containers.begin(), containers.end());
primitives.insert(primitives.end(), objects.begin(), objects.end());
return primitives;
}
ScriptCanvas::Data::Type GetRandomType() const
{
AZStd::vector< ScriptCanvas::Data::Type > types = GetTypes();
// We have no types to randomize. Just return.
if (types.empty())
{
return m_dataSlotConfigurationType;
}
int randomIndex = rand() % types.size();
ScriptCanvas::Data::Type randomType = types[randomIndex];
AZ_TracePrintf("ScriptCanvasTestFixture", "RandomType: %s\n", randomType.GetAZType().ToString<AZStd::string>().c_str());
return randomType;
}
AZStd::string GenerateSlotName()
{
AZStd::string slotName = AZStd::string::format("Slot %i", m_slotCounter);
++m_slotCounter;
return slotName;
}
AZ::SerializeContext* m_serializeContext;
AZ::BehaviorContext* m_behaviorContext;
UnitTestEntityContext m_entityContext;
// Really big(visually) data types just storing here for ease of use in situations.
ScriptCanvas::Data::Type m_numericVectorType;
ScriptCanvas::Data::Type m_stringToNumberMapType;
ScriptCanvas::Data::Type m_dataSlotConfigurationType;
ScriptCanvas::Graph* m_graph = nullptr;
int m_slotCounter = 0;
AZStd::unordered_map< AZ::EntityId, AZ::Entity* > m_entityMap;
protected:
static ScriptCanvasTests::Application* GetApplication() { return s_application; }
private:
static UnitTest::AllocatorsBase s_allocatorSetup;
static bool s_setupSucceeded;
AZStd::unordered_set< AZ::ComponentDescriptor* > m_descriptors;
};
}
@@ -0,0 +1,452 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ScriptCanvasTestNodes.h"
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Core/SlotConfigurationDefaults.h>
#include <gtest/gtest.h>
namespace TestNodes
{
//////////////////////////////////////////////////////////////////////////////
void TestResult::OnInit()
{
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
ScriptCanvas::DynamicDataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = "Value";
slotConfiguration.m_dynamicDataType = ScriptCanvas::DynamicDataType::Any;
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Input);
AddSlot(slotConfiguration);
}
void TestResult::OnInputSignal(const ScriptCanvas::SlotId&)
{
auto valueDatum = FindDatum(GetSlotId("Value"));
if (!valueDatum)
{
return;
}
valueDatum->ToString(m_string);
// technically, I should remove this, make it an object that holds a string, with an untyped slot, and this could be a local value
if (!m_string.empty())
{
AZ_TracePrintf("Script Canvas", "%s\n", m_string.c_str());
}
SignalOutput(GetSlotId(ScriptCanvas::CommonSlots::GeneralOutSlot::GetName()));
}
void TestResult::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<TestResult, Node>()
->Version(5)
->Field("m_string", &TestResult::m_string)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<TestResult>("TestResult", "Development node, will be replaced by a Log node")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/ScriptCanvas/TestResult.png")
->DataElement(AZ::Edit::UIHandlers::Default, &TestResult::m_string, "String", "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
}
}
//////////////////////////////////////////////////////////////////////////////
void ContractNode::Reflect(AZ::ReflectContext* reflection)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
if (serializeContext)
{
serializeContext->Class<ContractNode, Node>()
->Version(1)
;
}
}
void ContractNode::OnInit()
{
using namespace ScriptCanvas;
SlotId inSlotId = Node::AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
auto func = []() { return aznew DisallowReentrantExecutionContract{}; };
ContractDescriptor descriptor{ AZStd::move(func) };
GetSlot(inSlotId)->AddContract(descriptor);
AddSlot(ScriptCanvas::DataSlotConfiguration(Data::Type::String(), "Set String", ScriptCanvas::ConnectionType::Input));
AddSlot(ScriptCanvas::DataSlotConfiguration(Data::Type::String(), "Get String", ScriptCanvas::ConnectionType::Output));
AddSlot(ScriptCanvas::DataSlotConfiguration(Data::Type::Number(), "Set Number", ScriptCanvas::ConnectionType::Input));
AddSlot(ScriptCanvas::DataSlotConfiguration(Data::Type::Number(), "Get Number", ScriptCanvas::ConnectionType::Output));
}
void ContractNode::OnInputSignal(const ScriptCanvas::SlotId&)
{
SignalOutput(GetSlotId(ScriptCanvas::CommonSlots::GeneralOutSlot::GetName()));
}
//////////////////////////////////////////////////////////////////////////////
void InfiniteLoopNode::Reflect(AZ::ReflectContext* reflection)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<InfiniteLoopNode, Node>()
->Version(0)
;
}
}
void InfiniteLoopNode::OnInputSignal(const ScriptCanvas::SlotId&)
{
SignalOutput(GetSlotId("Before Infinity"));
}
void InfiniteLoopNode::OnInit()
{
AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
AddSlot(ScriptCanvas::ExecutionSlotConfiguration("Before Infinity", ScriptCanvas::ConnectionType::Output));
AddSlot(ScriptCanvas::ExecutionSlotConfiguration("After Infinity", ScriptCanvas::ConnectionType::Output));
}
//////////////////////////////////////////////////////////////////////////////
void UnitTestErrorNode::Reflect(AZ::ReflectContext* reflection)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<UnitTestErrorNode, Node>()
->Version(0)
;
}
}
void UnitTestErrorNode::OnInit()
{
AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
ScriptCanvas::DynamicDataSlotConfiguration slotConfiguration;
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Output);
slotConfiguration.m_name = "This";
slotConfiguration.m_dynamicDataType = ScriptCanvas::DynamicDataType::Any;
AddSlot(slotConfiguration);
}
void UnitTestErrorNode::OnInputSignal(const ScriptCanvas::SlotId&)
{
SCRIPTCANVAS_REPORT_ERROR((*this), "Unit test error!");
SignalOutput(GetSlotId("Out"));
}
//////////////////////////////////////////////////////////////////////////////
void AddNodeWithRemoveSlot::Reflect(AZ::ReflectContext* reflection)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<AddNodeWithRemoveSlot, ScriptCanvas::Node>()
->Version(0)
->Field("m_dynamicSlotIds", &AddNodeWithRemoveSlot::m_dynamicSlotIds)
;
}
}
ScriptCanvas::SlotId AddNodeWithRemoveSlot::AddSlot(AZStd::string_view slotName)
{
ScriptCanvas::SlotId addedSlotId = FindSlotIdForDescriptor(slotName, ScriptCanvas::SlotDescriptors::DataIn());
if (!addedSlotId.IsValid())
{
ScriptCanvas::DataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = slotName;
slotConfiguration.SetDefaultValue(0.0);
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Input);
addedSlotId = Node::AddSlot(slotConfiguration);
m_dynamicSlotIds.push_back(addedSlotId);
}
return addedSlotId;
}
bool AddNodeWithRemoveSlot::RemoveSlot(const ScriptCanvas::SlotId& slotId)
{
auto dynamicSlotIt = AZStd::find(m_dynamicSlotIds.begin(), m_dynamicSlotIds.end(), slotId);
if (dynamicSlotIt != m_dynamicSlotIds.end())
{
m_dynamicSlotIds.erase(dynamicSlotIt);
}
return Node::RemoveSlot(slotId);
}
void AddNodeWithRemoveSlot::OnInputSignal(const ScriptCanvas::SlotId& slotId)
{
if (slotId == GetSlotId("In"))
{
ScriptCanvas::Data::NumberType result{};
for (const ScriptCanvas::SlotId& dynamicSlotId : m_dynamicSlotIds)
{
if (auto numberInput = FindDatum(dynamicSlotId))
{
if (auto argValue = numberInput->GetAs<ScriptCanvas::Data::NumberType>())
{
result += *argValue;
}
}
}
auto resultType = GetSlotDataType(m_resultSlotId);
EXPECT_TRUE(resultType.IsValid());
ScriptCanvas::Datum output(result);;
PushOutput(output, *GetSlot(m_resultSlotId));
SignalOutput(GetSlotId("Out"));
}
}
void AddNodeWithRemoveSlot::OnInit()
{
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
for (AZStd::string slotName : {"A", "B", "C"})
{
ScriptCanvas::SlotId slotId = FindSlotIdForDescriptor(slotName, ScriptCanvas::SlotDescriptors::DataIn());
if (!slotId.IsValid())
{
ScriptCanvas::DataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = slotName;
slotConfiguration.SetDefaultValue(0);
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Input);
m_dynamicSlotIds.push_back(Node::AddSlot(slotConfiguration));
}
}
{
ScriptCanvas::DataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = "Result";
slotConfiguration.SetType(ScriptCanvas::Data::Type::Number());
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Output);
m_resultSlotId = Node::AddSlot(slotConfiguration);
}
}
void StringView::OnInit()
{
AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
{
ScriptCanvas::DataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = "View";
slotConfiguration.m_toolTip = "Input string_view object";
slotConfiguration.ConfigureDatum(AZStd::move(ScriptCanvas::Datum(ScriptCanvas::Data::Type::String(), ScriptCanvas::Datum::eOriginality::Copy)));
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Input);
AddSlot(slotConfiguration);
}
{
ScriptCanvas::DataSlotConfiguration slotConfiguration;
slotConfiguration.m_name = "Result";
slotConfiguration.m_toolTip = "Output string object";
slotConfiguration.SetAZType<AZStd::string>();
slotConfiguration.SetConnectionType(ScriptCanvas::ConnectionType::Output);
m_resultSlotId = AddSlot(slotConfiguration);
}
}
//////////////////////////////////////////////////////////////////////////////
void StringView::OnInputSignal(const ScriptCanvas::SlotId&)
{
auto viewDatum = FindDatum(GetSlotId("View"));
if (!viewDatum)
{
return;
}
ScriptCanvas::Data::StringType result;
viewDatum->ToString(result);
ScriptCanvas::Datum output(result);
auto resultSlot = GetSlot(m_resultSlotId);
if (resultSlot)
{
PushOutput(output, *resultSlot);
}
SignalOutput(GetSlotId("Out"));
}
void StringView::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<StringView, Node>()
->Version(0)
;
}
}
//////////////////////////////////////////////////////////////////////////////
void InsertSlotConcatNode::Reflect(AZ::ReflectContext* reflection)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<InsertSlotConcatNode, ScriptCanvas::Node>()
->Version(0)
;
}
}
ScriptCanvas::SlotId InsertSlotConcatNode::InsertSlot(AZ::s64 index, AZStd::string_view slotName)
{
using namespace ScriptCanvas;
SlotId addedSlotId = FindSlotIdForDescriptor(slotName, ScriptCanvas::SlotDescriptors::DataIn());
if (!addedSlotId.IsValid())
{
DataSlotConfiguration dataConfig;
dataConfig.m_name = slotName;
dataConfig.m_toolTip = "";
dataConfig.SetConnectionType(ScriptCanvas::ConnectionType::Input);
dataConfig.SetDefaultValue(Data::StringType());
addedSlotId = Node::InsertSlot(index, dataConfig);
}
return addedSlotId;
}
void InsertSlotConcatNode::OnInputSignal(const ScriptCanvas::SlotId& slotId)
{
if (slotId == GetSlotId(ScriptCanvas::CommonSlots::GeneralInSlot::GetName()))
{
ScriptCanvas::Data::StringType result{};
for (const ScriptCanvas::Slot* concatSlot : GetAllSlotsByDescriptor(ScriptCanvas::SlotDescriptors::DataIn()))
{
if (auto inputDatum = FindDatum(concatSlot->GetId()))
{
ScriptCanvas::Data::StringType stringArg;
if (inputDatum->ToString(stringArg))
{
result += stringArg;
}
}
}
auto resultSlotId = GetSlotId("Result");
auto resultType = GetSlotDataType(resultSlotId);
EXPECT_TRUE(resultType.IsValid());
if (auto resultSlot = GetSlot(resultSlotId))
{
PushOutput(ScriptCanvas::Datum(result), *resultSlot);
}
SignalOutput(GetSlotId("Out"));
}
}
void InsertSlotConcatNode::OnInit()
{
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralInSlot());
Node::AddSlot(ScriptCanvas::CommonSlots::GeneralOutSlot());
Node::AddSlot(ScriptCanvas::DataSlotConfiguration(ScriptCanvas::Data::Type::String(), "Result", ScriptCanvas::ConnectionType::Output));
}
/////////////////////////////
// ConfigurableUnitTestNode
/////////////////////////////
void ConfigurableUnitTestNode::Reflect(AZ::ReflectContext* reflection)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<ConfigurableUnitTestNode, ScriptCanvas::Node>()
->Version(0)
;
}
}
ScriptCanvas::Slot* ConfigurableUnitTestNode::AddTestingSlot(const ScriptCanvas::SlotConfiguration& slotConfiguration)
{
ScriptCanvas::SlotId slotId = AddSlot(slotConfiguration);
return GetSlot(slotId);
}
ScriptCanvas::Slot* ConfigurableUnitTestNode::InsertTestingSlot(int index, const ScriptCanvas::SlotConfiguration& slotConfiguration)
{
ScriptCanvas::SlotId slotId = InsertSlot(index, slotConfiguration);
return GetSlot(slotId);
}
AZStd::vector< const ScriptCanvas::Slot* > ConfigurableUnitTestNode::FindSlotsByDescriptor(const ScriptCanvas::SlotDescriptor& slotDescriptor) const
{
return GetAllSlotsByDescriptor(slotDescriptor);
}
void ConfigurableUnitTestNode::TestClearDisplayType(const AZ::Crc32& dynamicGroup)
{
ClearDisplayType(dynamicGroup);
}
void ConfigurableUnitTestNode::TestSetDisplayType(const AZ::Crc32& dynamicGroup, const ScriptCanvas::Data::Type& dataType)
{
SetDisplayType(dynamicGroup, dataType);
}
bool ConfigurableUnitTestNode::TestHasConcreteDisplayType(const AZ::Crc32& dynamicGroup) const
{
return HasConcreteDisplayType(dynamicGroup);
}
bool ConfigurableUnitTestNode::TestIsSlotConnectedToConcreteDisplayType(const ScriptCanvas::Slot& slot, ExploredDynamicGroupCache& exploredGroupCache) const
{
return IsSlotConnectedToConcreteDisplayType(slot, exploredGroupCache);
}
}
@@ -0,0 +1,175 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Core/Contracts/DisallowReentrantExecutionContract.h>
namespace TestNodes
{
//////////////////////////////////////////////////////////////////////////////
// TestResult node, prints a string to the console.
class TestResult
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(TestResult, "{085CBDD3-D4E0-44D4-BF68-8732E35B9DF1}", ScriptCanvas::Node);
static void Reflect(AZ::ReflectContext* context);
// really only used for unit testing
AZ_INLINE void SetText(const ScriptCanvas::Data::StringType& text) { m_string = text; }
AZ_INLINE const ScriptCanvas::Data::StringType& GetText() const { return m_string; }
void MarkDefaultableInput() override {}
protected:
void OnInit() override;
void OnInputSignal(const ScriptCanvas::SlotId&) override;
private:
ScriptCanvas::Data::StringType m_string;
};
//////////////////////////////////////////////////////////////////////////////
// ContractNode - used to test contract evaluation.
class ContractNode : public ScriptCanvas::Node
{
public:
AZ_COMPONENT(ContractNode, "{76A17F4F-F508-4C20-83A0-0125468946C7}", ScriptCanvas::Node);
static void Reflect(AZ::ReflectContext* reflection);
void OnInit() override;
protected:
void OnInputSignal(const ScriptCanvas::SlotId&) override;
};
//////////////////////////////////////////////////////////////////////////////
class InfiniteLoopNode
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(InfiniteLoopNode, "{709A78D5-3449-4E94-B751-C68AC6385749}", Node);
static void Reflect(AZ::ReflectContext* reflection);
protected:
void OnInputSignal(const ScriptCanvas::SlotId&) override;
void OnInit() override;
};
//////////////////////////////////////////////////////////////////////////////
class UnitTestErrorNode
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(UnitTestErrorNode, "{6A3E9EAD-F84B-4474-90B6-C3334DA669C2}", Node);
static void Reflect(AZ::ReflectContext* reflection);
protected:
void OnInit() override;
void OnInputSignal(const ScriptCanvas::SlotId&) override;
};
//////////////////////////////////////////////////////////////////////////////
class AddNodeWithRemoveSlot
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(AddNodeWithRemoveSlot, "{DE04D042-745F-4384-8B62-D6EE36321EFC}", ScriptCanvas::Node);
static void Reflect(AZ::ReflectContext* reflection);
ScriptCanvas::SlotId AddSlot(AZStd::string_view slotName);
bool RemoveSlot(const ScriptCanvas::SlotId& slotId);
protected:
void OnInputSignal(const ScriptCanvas::SlotId& slotId) override;
void OnInit() override;
AZStd::vector<ScriptCanvas::SlotId> m_dynamicSlotIds;
ScriptCanvas::SlotId m_resultSlotId;
};
//////////////////////////////////////////////////////////////////////////////
class StringView
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(StringView, "{F47ACD24-79EB-4DBE-B325-8B9DB0839A75}", ScriptCanvas::Node);
protected:
void OnInit() override;
void OnInputSignal(const ScriptCanvas::SlotId&) override;
public:
static void Reflect(AZ::ReflectContext* context);
private:
ScriptCanvas::SlotId m_resultSlotId;
};
//////////////////////////////////////////////////////////////////////////////
class InsertSlotConcatNode
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(InsertSlotConcatNode, "{445313E7-D0A5-4D73-B674-6FA37EFFF5C8}", ScriptCanvas::Node);
static void Reflect(AZ::ReflectContext* reflection);
ScriptCanvas::SlotId InsertSlot(AZ::s64 index, AZStd::string_view slotName);
protected:
void OnInputSignal(const ScriptCanvas::SlotId& slotId) override;
void OnInit() override;
};
//////////////////////////////////////////////////////////////////////////////
class ConfigurableUnitTestNode
: public ScriptCanvas::Node
{
public:
AZ_COMPONENT(ConfigurableUnitTestNode, "{61BF3D66-809A-4AAE-B20A-DFA2B51BE4EE}", ScriptCanvas::Node);
static void Reflect(AZ::ReflectContext* reflection);
ScriptCanvas::Slot* AddTestingSlot(const ScriptCanvas::SlotConfiguration& slotConfiguration);
ScriptCanvas::Slot* InsertTestingSlot(int index, const ScriptCanvas::SlotConfiguration& slotConfiguration);
AZStd::vector< const ScriptCanvas::Slot* > FindSlotsByDescriptor(const ScriptCanvas::SlotDescriptor& slotDescriptor) const;
void TestClearDisplayType(const AZ::Crc32& dynamicGroup);
void TestSetDisplayType(const AZ::Crc32& dynamicGroup, const ScriptCanvas::Data::Type& dataType);
bool TestHasConcreteDisplayType(const AZ::Crc32& dynamicGroup) const;
bool TestIsSlotConnectedToConcreteDisplayType(const ScriptCanvas::Slot& slot, ExploredDynamicGroupCache& exploredGroupCache) const;
protected:
};
}
@@ -0,0 +1,666 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
#include <Framework/ScriptCanvasTestUtilities.h>
#include <Framework/ScriptCanvasTestNodes.h>
#include <Editor/Framework/ScriptCanvasGraphUtilities.h>
#include <Asset/EditorAssetSystemComponent.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
namespace ScriptCanvasTestUtilitiesCPP
{
const char* k_defaultExtension = "scriptcanvas";
const char* k_unitTestDirPathRelative = "@engroot@/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests";
} // namespace ScriptCanvasTestUtilitiesCPP
namespace ScriptCanvasTests
{
using namespace ScriptCanvas;
#define SC_CORE_UNIT_TEST_DIR "@exefolder@/LY_SC_UnitTest_ScriptCanvas_CoreCPP_Temporary"
#define SC_CORE_UNIT_TEST_NAME "serializationTest.scriptcanvas_compiled"
const char* k_tempCoreAssetDir = SC_CORE_UNIT_TEST_DIR;
const char* k_tempCoreAssetName = SC_CORE_UNIT_TEST_NAME;
const char* k_tempCoreAssetPath = SC_CORE_UNIT_TEST_DIR "/" SC_CORE_UNIT_TEST_NAME;
#undef SC_CORE_UNIT_TEST_DIR
#undef SC_CORE_UNIT_TEST_NAME
AZStd::string_view GetGraphNameFromPath(AZStd::string_view graphPath)
{
graphPath.remove_prefix(AZStd::min(graphPath.find_last_of("\\/") + 1, graphPath.size()));
return graphPath;
}
void VerifyReporter(const ScriptCanvasEditor::Reporter& reporter)
{
if (!reporter.GetScriptCanvasId().IsValid())
{
ADD_FAILURE() << "Graph is not valid";
}
else if (reporter.IsReportFinished())
{
bool reportCheckpoints = false;
const auto& successes = reporter.GetSuccess();
for (const auto& success : successes)
{
SUCCEED() << success.data();
}
if (!reporter.IsActivated())
{
ADD_FAILURE() << "Graph did not activate";
}
if (!reporter.IsDeactivated())
{
ADD_FAILURE() << "Graph did not deactivate";
reportCheckpoints = true;
}
if (!reporter.IsErrorFree())
{
ADD_FAILURE() << "Graph had errors";
reportCheckpoints = true;
}
const auto& failures = reporter.GetFailure();
for (const auto& failure : failures)
{
ADD_FAILURE() << failure.data();
}
if (!reporter.IsComplete())
{
ADD_FAILURE() << "Graph was not marked complete";
reportCheckpoints = true;
}
if (reportCheckpoints)
{
const auto& checkpoints = reporter.GetCheckpoints();
if (checkpoints.empty())
{
ADD_FAILURE() << "No checkpoints or other unit test nodes found, using them can help parse graph test failures";
}
else
{
AZStd::string checkpointPath = "Checkpoint Path:\n";
int i = 0;
for (const auto& checkpoint : checkpoints)
{
checkpointPath += AZStd::string::format("%2d: %s\n", ++i, checkpoint.data()).data();
}
ADD_FAILURE() << checkpointPath.data();
}
}
}
else
{
ADD_FAILURE() << "Graph report did not finish";
}
}
void RunUnitTestGraph(AZStd::string_view graphPath, ExecutionMode execution, const ScriptCanvasEditor::DurationSpec& duration)
{
const AZStd::string filePath = AZStd::string::format("%s/%s.%s", ScriptCanvasTestUtilitiesCPP::k_unitTestDirPathRelative, graphPath.data(), ScriptCanvasTestUtilitiesCPP::k_defaultExtension);
const ScriptCanvasEditor::Reporter reporter = ScriptCanvasEditor::RunGraph(filePath, execution, duration);
ScriptCanvasTests::VerifyReporter(reporter);
}
void RunUnitTestGraph(AZStd::string_view graphPath, const ScriptCanvasEditor::DurationSpec& duration)
{
ScriptCanvasTests::RunUnitTestGraph(graphPath, ExecutionMode::Interpreted, duration);
}
void RunUnitTestGraph(AZStd::string_view graphPath, ExecutionMode execution)
{
ScriptCanvasTests::RunUnitTestGraph(graphPath, execution, ScriptCanvasEditor::DurationSpec());
}
void RunUnitTestGraph(AZStd::string_view graphPath)
{
ScriptCanvasTests::RunUnitTestGraph(graphPath, ScriptCanvasEditor::DurationSpec());
}
void RunUnitTestGraphMixed(AZStd::string_view graphPath, const ScriptCanvasEditor::DurationSpec& duration)
{
const ScriptCanvasEditor::Reporter reporterIterpreted0 = RunGraph(graphPath, ExecutionMode::Interpreted, duration);
const ScriptCanvasEditor::Reporter reporterNative0 = RunGraph(graphPath, ExecutionMode::Native, duration);
const ScriptCanvasEditor::Reporter reporterIterpreted1 = RunGraph(graphPath, ExecutionMode::Interpreted, duration);
const ScriptCanvasEditor::Reporter reporterNative1 = RunGraph(graphPath, ExecutionMode::Native, duration);
VerifyReporter(reporterIterpreted0);
VerifyReporter(reporterNative0);
EXPECT_TRUE(reporterIterpreted0.IsActivated());
EXPECT_TRUE(reporterIterpreted1.IsComplete());
EXPECT_TRUE(reporterIterpreted0.IsErrorFree());
EXPECT_EQ(reporterNative0, reporterIterpreted0);
EXPECT_EQ(reporterNative0, reporterIterpreted1);
EXPECT_EQ(reporterNative1, reporterIterpreted0);
EXPECT_EQ(reporterNative1, reporterIterpreted1);
EXPECT_EQ(reporterNative0, reporterNative1);
EXPECT_EQ(reporterIterpreted0, reporterIterpreted1);
}
ScriptCanvasEditor::LoadTestGraphResult LoadTestGraph(AZStd::string_view graphPath)
{
const AZStd::string filePath = AZStd::string::format("%s/%s.%s", ScriptCanvasTestUtilitiesCPP::k_unitTestDirPathRelative, graphPath.data(), ScriptCanvasTestUtilitiesCPP::k_defaultExtension);
AZ::Outcome< AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome = AZ::Failure(AZStd::string("asset creation failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, filePath);
if (assetOutcome.IsSuccess())
{
ScriptCanvasEditor::LoadTestGraphResult result;
result.m_asset = assetOutcome.GetValue();
result.m_graphEntity = AZStd::make_unique<AZ::Entity>("Loaded Graph");
result.m_graph = result.m_graphEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(result.m_asset);
return result;
}
return {};
}
void RunUnitTestGraphMixed(AZStd::string_view graphPath)
{
RunUnitTestGraphMixed(graphPath, ScriptCanvasEditor::DurationSpec());
}
TestBehaviorContextObject TestBehaviorContextObject::MaxReturnByValue(TestBehaviorContextObject lhs, TestBehaviorContextObject rhs)
{
return lhs.GetValue() >= rhs.GetValue() ? lhs : rhs;
}
const TestBehaviorContextObject* TestBehaviorContextObject::MaxReturnByPointer(const TestBehaviorContextObject* lhs, const TestBehaviorContextObject* rhs)
{
return (lhs && rhs && lhs->GetValue() >= rhs->GetValue()) ? lhs : rhs;
}
const TestBehaviorContextObject& TestBehaviorContextObject::MaxReturnByReference(const TestBehaviorContextObject& lhs, const TestBehaviorContextObject& rhs)
{
return lhs.GetValue() >= rhs.GetValue() ? lhs : rhs;
}
int TestBehaviorContextObject::MaxReturnByValueInteger(int lhs, int rhs)
{
return lhs >= rhs ? lhs : rhs;
}
const int* TestBehaviorContextObject::MaxReturnByPointerInteger(const int* lhs, const int* rhs)
{
return (lhs && rhs && (*lhs) >= (*rhs)) ? lhs : rhs;
}
const int& TestBehaviorContextObject::MaxReturnByReferenceInteger(const int& lhs, const int& rhs)
{
return lhs >= rhs ? lhs : rhs;
}
static void TestBehaviorContextObjectGenericConstructor(TestBehaviorContextObject* thisPtr)
{
new (thisPtr) TestBehaviorContextObject();
thisPtr->SetValue(0);
}
void TestBehaviorContextObject::Reflect(AZ::ReflectContext* reflectContext)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<TestBehaviorContextObject>()
->Version(0)
->Field("m_value", &TestBehaviorContextObject::m_value)
->Field("isNormalized", &TestBehaviorContextObject::m_isNormalized)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
{
behaviorContext->Class<TestBehaviorContextObject>("TestBehaviorContextObject")
->Attribute(AZ::Script::Attributes::ConstructorOverride, &TestBehaviorContextObjectGenericConstructor)
->Attribute(AZ::Script::Attributes::GenericConstructorOverride, &TestBehaviorContextObjectGenericConstructor)
->Method("In", &TestBehaviorContextObject::GetValue)
->Method("Out", &TestBehaviorContextObject::SetValue)
->Method("Normalize", &TestBehaviorContextObject::Normalize)
->Method("IsNormalized", &TestBehaviorContextObject::IsNormalized)
->Method("Denormalize", &TestBehaviorContextObject::Denormalize)
->Method("MaxReturnByValue", &TestBehaviorContextObject::MaxReturnByValue)
->Method("MaxReturnByPointer", &TestBehaviorContextObject::MaxReturnByPointer)
->Method("MaxReturnByReference", &TestBehaviorContextObject::MaxReturnByReference)
->Method("MaxReturnByValueInteger", &TestBehaviorContextObject::MaxReturnByValueInteger)
->Method("MaxReturnByPointerInteger", &TestBehaviorContextObject::MaxReturnByPointerInteger)
->Method("MaxReturnByReferenceInteger", &TestBehaviorContextObject::MaxReturnByReferenceInteger)
->Method<bool (TestBehaviorContextObject::*)(const TestBehaviorContextObject&) const>("LessThan", &TestBehaviorContextObject::operator<)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::LessThan)
->Method<bool (TestBehaviorContextObject::*)(const TestBehaviorContextObject&) const>("LessEqualThan", &TestBehaviorContextObject::operator<=)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::LessEqualThan)
->Method<bool (TestBehaviorContextObject::*)(const TestBehaviorContextObject&) const>("Equal", &TestBehaviorContextObject::operator==)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
;
}
}
TestBehaviorContextObject MaxReturnByValue(TestBehaviorContextObject lhs, TestBehaviorContextObject rhs)
{
return lhs.GetValue() >= rhs.GetValue() ? lhs : rhs;
}
const TestBehaviorContextObject* MaxReturnByPointer(const TestBehaviorContextObject* lhs, const TestBehaviorContextObject* rhs)
{
return (lhs && rhs && (lhs->GetValue() >= rhs->GetValue())) ? lhs : rhs;
}
const TestBehaviorContextObject& MaxReturnByReference(const TestBehaviorContextObject& lhs, const TestBehaviorContextObject& rhs)
{
return lhs.GetValue() >= rhs.GetValue() ? lhs : rhs;
}
AZ::u32 TestBehaviorContextObject::s_createdCount = 0;
AZ::u32 TestBehaviorContextObject::s_destroyedCount = 0;
ScriptCanvas::Nodes::Core::BehaviorContextObjectNode* CreateTestObjectNode(const AZ::EntityId& graphUniqueId, AZ::EntityId& entityOut, const AZ::Uuid& objectTypeID)
{
ScriptCanvas::Nodes::Core::BehaviorContextObjectNode* node = CreateTestNode<ScriptCanvas::Nodes::Core::BehaviorContextObjectNode>(graphUniqueId, entityOut);
EXPECT_TRUE(node != nullptr);
node->InitializeObject(objectTypeID);
return node;
}
AZ::EntityId CreateClassFunctionNode(const ScriptCanvasId& scriptCanvasId, AZStd::string_view className, AZStd::string_view methodName)
{
using namespace ScriptCanvas;
ScriptCanvas::Namespaces emptyNamespaces;
AZ::Entity* splitEntity{ aznew AZ::Entity };
splitEntity->Init();
AZ::EntityId methodNodeID{ splitEntity->GetId() };
SystemRequestBus::Broadcast(&SystemRequests::CreateNodeOnEntity, methodNodeID, scriptCanvasId, Nodes::Core::Method::RTTI_Type());
Nodes::Core::Method* methodNode(nullptr);
SystemRequestBus::BroadcastResult(methodNode, &SystemRequests::GetNode<Nodes::Core::Method>, methodNodeID);
EXPECT_TRUE(methodNode != nullptr);
methodNode->InitializeClassOrBus(emptyNamespaces, className, methodName);
return methodNodeID;
}
ScriptCanvas::Node* CreateDataNodeByType(const ScriptCanvasId& scriptCanvasId, const ScriptCanvas::Data::Type& type, AZ::EntityId& nodeIDout)
{
using namespace ScriptCanvas;
Node* node(nullptr);
switch (type.GetType())
{
case Data::eType::AABB:
node = CreateTestNode<Nodes::Math::AABB>(scriptCanvasId, nodeIDout);
break;
case Data::eType::BehaviorContextObject:
{
auto objectNode = CreateTestNode<Nodes::Core::BehaviorContextObjectNode>(scriptCanvasId, nodeIDout);
objectNode->InitializeObject(type);
node = objectNode;
}
break;
case Data::eType::Boolean:
node = CreateTestNode<Nodes::Logic::Boolean>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Color:
node = CreateTestNode<Nodes::Math::Color>(scriptCanvasId, nodeIDout);
break;
case Data::eType::CRC:
node = CreateTestNode<Nodes::Math::CRC>(scriptCanvasId, nodeIDout);
break;
case Data::eType::EntityID:
node = CreateTestNode<Nodes::Entity::EntityRef>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Matrix3x3:
node = CreateTestNode<Nodes::Math::Matrix3x3>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Matrix4x4:
node = CreateTestNode<Nodes::Math::Matrix4x4>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Number:
node = CreateTestNode<Nodes::Math::Number>(scriptCanvasId, nodeIDout);
break;
case Data::eType::OBB:
node = CreateTestNode<Nodes::Math::OBB>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Plane:
node = CreateTestNode<Nodes::Math::Plane>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Quaternion:
node = CreateTestNode<Nodes::Math::Quaternion>(scriptCanvasId, nodeIDout);
break;
case Data::eType::String:
node = CreateTestNode<Nodes::Core::String>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Transform:
node = CreateTestNode<Nodes::Math::Transform>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Vector2:
node = CreateTestNode<Nodes::Math::Vector2>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Vector3:
node = CreateTestNode<Nodes::Math::Vector3>(scriptCanvasId, nodeIDout);
break;
case Data::eType::Vector4:
node = CreateTestNode<Nodes::Math::Vector4>(scriptCanvasId, nodeIDout);
break;
default:
AZ_Error("ScriptCanvas", false, "unsupported data type");
}
node->SetExecutionType(ExecutionType::Runtime);
return node;
}
AZStd::string SlotDescriptorToString(ScriptCanvas::SlotDescriptor descriptor)
{
AZStd::string name;
switch (descriptor.m_slotType)
{
case SlotTypeDescriptor::Data:
name.append("Data");
break;
case SlotTypeDescriptor::Execution:
name.append("Execution");
break;
default:
break;
}
switch (descriptor.m_connectionType)
{
case ConnectionType::Input:
name.append("In");
break;
case ConnectionType::Output:
name.append("Out");
break;
default:
break;
}
return name;
}
void DumpSlots(const ScriptCanvas::Node& node)
{
const auto& nodeslots = node.GetSlots();
for (const auto& nodeslot : nodeslots)
{
AZ_TracePrintf("ScriptCanvasTest", "'%s':%s\n", nodeslot.GetName().data(), SlotDescriptorToString(nodeslot.GetDescriptor()).c_str());
}
}
bool Connect(ScriptCanvas::Graph& graph, const AZ::EntityId& fromNodeID, const char* fromSlotName, const AZ::EntityId& toNodeID, const char* toSlotName, bool dumpSlotsOnFailure /*= true*/)
{
using namespace ScriptCanvas;
AZ::Entity* fromNode{};
AZ::ComponentApplicationBus::BroadcastResult(fromNode, &AZ::ComponentApplicationBus::Events::FindEntity, fromNodeID);
AZ::Entity* toNode{};
AZ::ComponentApplicationBus::BroadcastResult(toNode, &AZ::ComponentApplicationBus::Events::FindEntity, toNodeID);
if (fromNode && toNode)
{
Node* from = AZ::EntityUtils::FindFirstDerivedComponent<Node>(fromNode);
Node* to = AZ::EntityUtils::FindFirstDerivedComponent<Node>(toNode);
auto fromSlotId = from->GetSlotId(fromSlotName);
auto toSlotId = to->GetSlotId(toSlotName);
if (graph.Connect(fromNodeID, fromSlotId, toNodeID, toSlotId))
{
return true;
}
else if (dumpSlotsOnFailure)
{
AZ_TracePrintf("ScriptCanvasTest", "Slots from:\n");
DumpSlots(*from);
AZ_TracePrintf("ScriptCanvasTest", "\nSlots to:\n");
DumpSlots(*to);
}
}
return false;
}
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> CreateRuntimeAsset(ScriptCanvas::Graph* graph)
{
using namespace ScriptCanvas;
RuntimeAssetHandler runtimeAssetHandler;
AZ::Data::Asset<RuntimeAsset> runtimeAsset;
runtimeAsset.Create(AZ::Uuid::CreateRandom());
AZ::SerializeContext* serializeContext = AZ::EntityUtils::GetApplicationSerializeContext();
serializeContext->CloneObjectInplace(runtimeAsset.Get()->GetData().m_graphData, graph->GetGraphDataConst());
AZStd::unordered_map<AZ::EntityId, AZ::EntityId> graphToAssetEntityIdMap{ { graph->GetScriptCanvasId(), ScriptCanvas::UniqueId } };
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(&runtimeAsset.Get()->GetData().m_graphData, graphToAssetEntityIdMap, serializeContext);
return runtimeAsset;
}
AZ::Entity* UnitTestEntityContext::CreateEntity(const char* name)
{
auto entity = aznew AZ::Entity(name);
AddEntity(entity);
return entity;
}
void UnitTestEntityContext::AddEntity(AZ::Entity* entity)
{
AddEntity(entity->GetId());
}
void UnitTestEntityContext::AddEntity(AZ::EntityId entityId)
{
AZ_Assert(!AzFramework::EntityIdContextQueryBus::FindFirstHandler(entityId), "Entity already belongs to a context.");
m_unitTestEntityIdMap.emplace(entityId, entityId);
AzFramework::EntityIdContextQueryBus::MultiHandler::BusConnect(entityId);
}
void UnitTestEntityContext::RemoveEntity(AZ::EntityId entityId)
{
auto foundIt = m_unitTestEntityIdMap.find(entityId);
if (foundIt != m_unitTestEntityIdMap.end())
{
AzFramework::EntityIdContextQueryBus::MultiHandler::BusDisconnect(entityId);
m_unitTestEntityIdMap.erase(foundIt);
}
}
void UnitTestEntityContext::ActivateEntity(AZ::EntityId entityId)
{
if (IsOwnedByThisContext(entityId))
{
AZ::Entity* entity{};
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
if (entity)
{
if (entity->GetState() == AZ::Entity::State::Constructed)
{
entity->Init();
}
if (entity->GetState() == AZ::Entity::State::Init)
{
entity->Activate();
}
}
}
}
void UnitTestEntityContext::DeactivateEntity(AZ::EntityId entityId)
{
if (IsOwnedByThisContext(entityId))
{
AZ::Entity* entity{};
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
if (entity)
{
if (entity->GetState() == AZ::Entity::State::Active)
{
entity->Deactivate();
}
else if (entity->GetState() == AZ::Entity::State::Activating)
{
// Queue Deactivation to next frame
AZ::SystemTickBus::QueueFunction(&AZ::Entity::Activate, entity);
}
}
}
}
bool UnitTestEntityContext::DestroyEntity(AZ::Entity* entity)
{
if (entity)
{
auto foundIt = m_unitTestEntityIdMap.find(entity->GetId());
if (foundIt != m_unitTestEntityIdMap.end())
{
AzFramework::EntityIdContextQueryBus::MultiHandler::BusDisconnect(entity->GetId());
m_unitTestEntityIdMap.erase(foundIt);
delete entity;
return true;
}
}
return false;
}
bool UnitTestEntityContext::DestroyEntityById(AZ::EntityId entityId)
{
AZ::Entity* entity{};
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
return DestroyEntity(entity);
}
void UnitTestEntityContext::ResetContext()
{
AzFramework::EntityIdContextQueryBus::MultiHandler::BusDisconnect();
m_unitTestEntityIdMap.clear();
}
AZ::EntityId UnitTestEntityContext::FindLoadedEntityIdMapping(const AZ::EntityId& staticId) const
{
auto idIter = m_unitTestEntityIdMap.find(staticId);
if (idIter != m_unitTestEntityIdMap.end())
{
return idIter->second;
}
return AZ::EntityId();
}
AZ::Entity* UnitTestEntityContext::CloneEntity(const AZ::Entity& sourceEntity)
{
if (!IsOwnedByThisContext(sourceEntity.GetId()))
{
AZ_Warning("Script Canvas", false, "Entity %s does not belong to the unit test entity context.", sourceEntity.GetName().data());
return {};
}
AZ::SerializeContext* serializeContext{};
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
AZ::Entity* cloneEntity = serializeContext->CloneObject(&sourceEntity);
if (cloneEntity)
{
cloneEntity->SetId(AZ::Entity::MakeId());
AddEntity(cloneEntity);
}
return cloneEntity;
}
AZ::Data::AssetId UnitTestEntityContext::CurrentlyInstantiatingSlice()
{
return AZ::Data::AssetId();
}
bool UnitTestEntityContext::HandleRootEntityReloadedFromStream(AZ::Entity*, bool, AZ::SliceComponent::EntityIdToEntityIdMap*)
{
return true;
}
AZ::SliceComponent* UnitTestEntityContext::GetRootSlice()
{
return {};
}
const AZStd::unordered_map<AZ::EntityId, AZ::EntityId>& UnitTestEntityContext::GetLoadedEntityIdMap()
{
return m_unitTestEntityIdMap;
}
AzFramework::SliceInstantiationTicket UnitTestEntityContext::InstantiateSlice(const AZ::Data::Asset<AZ::Data::AssetData>&,
const AZ::IdUtils::Remapper<AZ::EntityId>::IdMapper&, const AZ::Data::AssetFilterCB&)
{
return AzFramework::SliceInstantiationTicket();
}
AZ::SliceComponent::SliceInstanceAddress UnitTestEntityContext::CloneSliceInstance(
AZ::SliceComponent::SliceInstanceAddress, AZ::SliceComponent::EntityIdToEntityIdMap&)
{
return AZ::SliceComponent::SliceInstanceAddress();
}
void UnitTestEntityContext::CancelSliceInstantiation(const AzFramework::SliceInstantiationTicket&)
{
}
AzFramework::SliceInstantiationTicket UnitTestEntityContext::GenerateSliceInstantiationTicket()
{
return AzFramework::SliceInstantiationTicket();
}
void UnitTestEntityContext::SetIsDynamic(bool)
{
}
const AzFramework::RootSliceAsset& UnitTestEntityContext::GetRootAsset() const
{
return m_unitTestRootAsset;
}
} // ScriptCanvasTests
@@ -0,0 +1,869 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
#include <Editor/Framework/ScriptCanvasReporter.h>
#include <Framework/ScriptCanvasTestNodes.h>
#include <AzTest/AzTest.h>
namespace ScriptCanvasTests
{
extern const char* k_tempCoreAssetDir;
extern const char* k_tempCoreAssetName;
extern const char* k_tempCoreAssetPath;
AZStd::string_view GetGraphNameFromPath(AZStd::string_view graphPath);
void VerifyReporter(const ScriptCanvasEditor::Reporter& reporter);
void RunUnitTestGraph(AZStd::string_view graphPath, ScriptCanvas::ExecutionMode execution, const ScriptCanvasEditor::DurationSpec& duration);
void RunUnitTestGraph(AZStd::string_view graphPath, const ScriptCanvasEditor::DurationSpec& duration);
void RunUnitTestGraph(AZStd::string_view graphPath, ScriptCanvas::ExecutionMode execution);
void RunUnitTestGraph(AZStd::string_view graphPath);
void RunUnitTestGraphMixed(AZStd::string_view graphPath, const ScriptCanvasEditor::DurationSpec& duration);
void RunUnitTestGraphMixed(AZStd::string_view graphPath);
class NodeAccessor
{
public:
template<typename t_Value>
static const t_Value* GetInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName)
{
return GetInput_UNIT_TEST<t_Value>(node, node->GetSlotId(slotName));
}
template<typename t_Value>
static t_Value* ModInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName)
{
return ModInput_UNIT_TEST<t_Value>(node, node->GetSlotId(slotName));
}
template<typename t_Value>
static const t_Value* GetInput_UNIT_TEST(ScriptCanvas::Node* node, const ScriptCanvas::SlotId& slotId)
{
const ScriptCanvas::Datum* input = node->FindDatum(slotId);
return input ? input->GetAs<t_Value>() : nullptr;
}
template<typename t_Value>
static t_Value* ModInput_UNIT_TEST(ScriptCanvas::Node* node, const ScriptCanvas::SlotId& slotId)
{
auto slotIter = node->m_slotIdIteratorCache.find(slotId);
if (slotIter != node->m_slotIdIteratorCache.end())
{
ScriptCanvas::Slot* slot = &(*slotIter->second.m_slotIterator);
if (slot->IsVariableReference())
{
AZ_Assert(false, "Variable references are not supported in Unit Test methods.");
}
else
{
return slotIter->second.GetDatumIter()->ModAs<t_Value>();
}
}
return nullptr;
}
static const ScriptCanvas::Datum* GetInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName)
{
return GetInput_UNIT_TEST(node, node->GetSlotId(slotName));
}
static const ScriptCanvas::Datum* GetInput_UNIT_TEST(ScriptCanvas::Node* node, const ScriptCanvas::SlotId& slotId)
{
return node->FindDatum(slotId);
}
// initializes the node input to the value passed in, not a pointer to it
template<typename t_Value>
static void SetInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName, const t_Value& value)
{
SetInput_UNIT_TEST<t_Value>(node, node->GetSlotId(slotName), value);
}
template<typename t_Value>
static void SetInput_UNIT_TEST(ScriptCanvas::Node* node, const ScriptCanvas::SlotId& slotId, const t_Value& value)
{
node->SetInput(ScriptCanvas::Datum(value), slotId);
}
static void SetInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName, const ScriptCanvas::Datum& value)
{
SetInput_UNIT_TEST(node, node->GetSlotId(slotName), value);
}
static void SetInput_UNIT_TEST(ScriptCanvas::Node* node, AZStd::string_view slotName, ScriptCanvas::Datum&& value)
{
SetInput_UNIT_TEST(node, node->GetSlotId(slotName), AZStd::move(value));
}
static void SetInput_UNIT_TEST(ScriptCanvas::Node* node, const ScriptCanvas::SlotId& slotId, ScriptCanvas::Datum&& value)
{
node->SetInput(AZStd::move(value), slotId);
}
};
template<typename t_NodeType>
t_NodeType* GetTestNode([[maybe_unused]] const ScriptCanvas::ScriptCanvasId& scriptCanvasId, const AZ::EntityId& nodeID)
{
using namespace ScriptCanvas;
t_NodeType* node{};
SystemRequestBus::BroadcastResult(node, &SystemRequests::GetNode<t_NodeType>, nodeID);
EXPECT_TRUE(node != nullptr);
node->SetExecutionType(ExecutionType::Runtime);
return node;
}
template<typename t_NodeType>
t_NodeType* CreateTestNode(const ScriptCanvas::ScriptCanvasId& scriptCanvasId, AZ::EntityId& entityOut)
{
using namespace ScriptCanvas;
AZ::Entity* entity{ aznew AZ::Entity };
entity->Init();
entityOut = entity->GetId();
EXPECT_TRUE(entityOut.IsValid());
SystemRequestBus::Broadcast(&SystemRequests::CreateNodeOnEntity, entityOut, scriptCanvasId, azrtti_typeid<t_NodeType>());
return GetTestNode<t_NodeType>(scriptCanvasId, entityOut);
}
ScriptCanvas::Node* CreateDataNodeByType(const ScriptCanvas::ScriptCanvasId& scriptCanvasId, const ScriptCanvas::Data::Type& type, AZ::EntityId& nodeIDout);
template<typename t_Value>
ScriptCanvas::Node* CreateDataNode(const ScriptCanvas::ScriptCanvasId& scriptCanvasId, const t_Value& value, AZ::EntityId& nodeIDout)
{
using namespace ScriptCanvas;
const Data::Type operandType = Data::FromAZType(azrtti_typeid<t_Value>());
Node* node = CreateDataNodeByType(scriptCanvasId, operandType, nodeIDout);
EXPECT_NE(node, nullptr);
if (node)
{
NodeAccessor::SetInput_UNIT_TEST(node, "Set", value);
}
return node;
}
template<typename t_Value>
ScriptCanvas::VariableId CreateVariable(ScriptCanvas::ScriptCanvasId scriptCanvasId, const t_Value& value, AZStd::string_view variableName)
{
using namespace ScriptCanvas;
AZ::Outcome<VariableId, AZStd::string> addVariableOutcome = AZ::Failure(AZStd::string());
GraphVariableManagerRequestBus::EventResult(addVariableOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, variableName, Datum(value));
if (!addVariableOutcome)
{
AZ_Warning("Script Canvas Test", false, "%s", addVariableOutcome.GetError().data());
return {};
}
return addVariableOutcome.TakeValue();
}
ScriptCanvas::Nodes::Core::BehaviorContextObjectNode* CreateTestObjectNode(const ScriptCanvas::ScriptCanvasId& scriptCanvasId, AZ::EntityId& entityOut, const AZ::Uuid& objectTypeID);
AZ::EntityId CreateClassFunctionNode(const ScriptCanvas::ScriptCanvasId& scriptCanvasId, AZStd::string_view className, AZStd::string_view methodName);
AZStd::string SlotDescriptorToString(ScriptCanvas::SlotDescriptor type);
void DumpSlots(const ScriptCanvas::Node& node);
bool Connect(ScriptCanvas::Graph& graph, const AZ::EntityId& fromNodeID, const char* fromSlotName, const AZ::EntityId& toNodeID, const char* toSlotName, bool dumpSlotsOnFailure = true);
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> CreateRuntimeAsset(ScriptCanvas::Graph* graph);
class UnitTestEvents
: public AZ::EBusTraits
{
public:
virtual void Failed(AZStd::string description) = 0;
virtual AZStd::string Result(AZStd::string description) = 0;
virtual void SideEffect(AZStd::string description) = 0;
virtual void Succeeded(AZStd::string description) = 0;
};
using UnitTestEventsBus = AZ::EBus<UnitTestEvents>;
class UnitTestEventsHandler
: public UnitTestEventsBus::Handler
{
public:
~UnitTestEventsHandler()
{
Clear();
}
void Clear()
{
for (auto iter : m_failures)
{
ADD_FAILURE() << iter.first.c_str();
}
for (auto iter : m_successes)
{
GTEST_SUCCEED();
}
m_failures.clear();
m_results.clear();
m_successes.clear();
m_results.clear();
}
void Failed(AZStd::string description) override
{
auto iter = m_failures.find(description);
if (iter != m_failures.end())
{
++iter->second;
}
else
{
m_failures.insert(AZStd::make_pair(description, 1));
}
}
int FailureCount(AZStd::string_view description) const
{
auto iter = m_failures.find(description);
return iter != m_failures.end() ? iter->second : 0;
}
bool IsFailed() const
{
return !m_failures.empty();
}
bool IsSucceeded() const
{
return !m_successes.empty();
}
void SideEffect(AZStd::string description) override
{
auto iter = m_sideEffects.find(description);
if (iter != m_sideEffects.end())
{
++iter->second;
}
else
{
m_sideEffects.insert(AZStd::make_pair(description, 1));
}
}
int SideEffectCount() const
{
int count(0);
for (auto iter : m_sideEffects)
{
count += iter.second;
}
return count;
}
int SideEffectCount(AZStd::string_view description) const
{
auto iter = m_sideEffects.find(description);
return iter != m_sideEffects.end() ? iter->second : 0;
}
void Succeeded(AZStd::string description) override
{
auto iter = m_successes.find(description);
if (iter != m_successes.end())
{
++iter->second;
}
else
{
m_successes.insert(AZStd::make_pair(description, 1));
}
}
int SuccessCount(AZStd::string_view description) const
{
auto iter = m_successes.find(description);
return iter != m_successes.end() ? iter->second : 0;
}
AZStd::string Result(AZStd::string description) override
{
auto iter = m_results.find(description);
if (iter != m_results.end())
{
++iter->second;
}
else
{
m_results.insert(AZStd::make_pair(description, 1));
}
return description;
}
int ResultCount(AZStd::string_view description) const
{
auto iter = m_results.find(description);
return iter != m_results.end() ? iter->second : 0;
}
private:
AZStd::unordered_map<AZStd::string, int> m_failures;
AZStd::unordered_map<AZStd::string, int> m_sideEffects;
AZStd::unordered_map<AZStd::string, int> m_successes;
AZStd::unordered_map<AZStd::string, int> m_results;
};
struct TestBehaviorContextProperties
{
AZ_TYPE_INFO(TestBehaviorContextProperties, "{13ECCA93-9A62-4A46-846C-ABFEEA215C48}");
static void Reflect(AZ::ReflectContext* reflectContext)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<TestBehaviorContextProperties>()
->Version(0)
;
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
{
behaviorContext->Class<TestBehaviorContextProperties>("TestBehaviorContextProperties")
->Property("boolean", BehaviorValueGetter(&TestBehaviorContextProperties::m_booleanProp), BehaviorValueSetter(&TestBehaviorContextProperties::m_booleanProp))
->Property("number", BehaviorValueGetter(&TestBehaviorContextProperties::m_numberProp), BehaviorValueSetter(&TestBehaviorContextProperties::m_numberProp))
->Property("string", BehaviorValueGetter(&TestBehaviorContextProperties::m_stringProp), BehaviorValueSetter(&TestBehaviorContextProperties::m_stringProp))
->Property("getterOnlyNumber", BehaviorValueGetter(&TestBehaviorContextProperties::m_getterOnlyProp), nullptr)
->Property("setterOnlyNumber", nullptr, BehaviorValueSetter(&TestBehaviorContextProperties::m_setterOnlyProp))
;
}
}
ScriptCanvas::Data::BooleanType m_booleanProp = false;
ScriptCanvas::Data::NumberType m_numberProp = 0.0f;
ScriptCanvas::Data::StringType m_stringProp;
ScriptCanvas::Data::NumberType m_getterOnlyProp = 0.0f;
ScriptCanvas::Data::NumberType m_setterOnlyProp = 0.0f;
};
class TestBehaviorContextObject
{
public:
AZ_TYPE_INFO(TestBehaviorContextObject, "{52DA0875-8EF6-4D39-9CF6-9F83BAA59A1D}");
static TestBehaviorContextObject MaxReturnByValue(TestBehaviorContextObject lhs, TestBehaviorContextObject rhs);
static const TestBehaviorContextObject* MaxReturnByPointer(const TestBehaviorContextObject* lhs, const TestBehaviorContextObject* rhs);
static const TestBehaviorContextObject& MaxReturnByReference(const TestBehaviorContextObject& lhs, const TestBehaviorContextObject& rhs);
static int MaxReturnByValueInteger(int lhs, int rhs);
static const int* MaxReturnByPointerInteger(const int* lhs, const int* rhs);
static const int& MaxReturnByReferenceInteger(const int& lhs, const int& rhs);
static void Reflect(AZ::ReflectContext* reflectContext);
static AZ::u32 GetCreatedCount() { return s_createdCount; }
static AZ::u32 GetDestroyedCount() { return s_destroyedCount; }
static void ResetCounts() { s_createdCount = s_destroyedCount = 0; }
TestBehaviorContextObject()
{
++s_createdCount;
}
TestBehaviorContextObject(const TestBehaviorContextObject& src)
: m_value(src.m_value)
{
++s_createdCount;
}
TestBehaviorContextObject(TestBehaviorContextObject&& src)
: m_value(src.m_value)
{
++s_createdCount;
}
TestBehaviorContextObject(int value)
: m_value(value)
{
++s_createdCount;
}
~TestBehaviorContextObject()
{
AZ::u32 destroyedCount = ++s_destroyedCount;
AZ::u32 createdCount = s_createdCount;
AZ_Assert(destroyedCount <= createdCount, "ScriptCanvas execution error");
}
TestBehaviorContextObject& operator=(const TestBehaviorContextObject& source)
{
m_value = source.m_value;
return *this;
}
// make a to string
int GetValue() const { return m_value; }
void SetValue(int value) { m_value = value; }
bool IsNormalized() const { return m_isNormalized; }
void Normalize() { m_isNormalized = true; }
void Denormalize() { m_isNormalized = false; }
bool operator>(const TestBehaviorContextObject& other) const
{
return m_value > other.m_value;
}
bool operator>=(const TestBehaviorContextObject& other) const
{
return m_value >= other.m_value;
}
bool operator==(const TestBehaviorContextObject& other) const
{
return m_value == other.m_value;
}
bool operator!=(const TestBehaviorContextObject& other) const
{
return m_value != other.m_value;
}
bool operator<=(const TestBehaviorContextObject& other) const
{
return m_value <= other.m_value;
}
bool operator<(const TestBehaviorContextObject& other) const
{
return m_value < other.m_value;
}
private:
int m_value = -1;
bool m_isNormalized = false;
static AZ::u32 s_createdCount;
static AZ::u32 s_destroyedCount;
};
TestBehaviorContextObject MaxReturnByValue(TestBehaviorContextObject lhs, TestBehaviorContextObject rhs);
const TestBehaviorContextObject* MaxReturnByPointer(const TestBehaviorContextObject* lhs, const TestBehaviorContextObject* rhs);
const TestBehaviorContextObject& MaxReturnByReference(const TestBehaviorContextObject& lhs, const TestBehaviorContextObject& rhs);
class EventTest
: public AZ::ComponentBus
{
public:
virtual void Event() = 0;
virtual int Number(int number) = 0;
virtual AZStd::string String(AZStd::string_view string) = 0;
virtual TestBehaviorContextObject Object(const TestBehaviorContextObject& vector) = 0;
};
using EventTestBus = AZ::EBus<EventTest>;
class EventTestHandler
: public EventTestBus::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER
(EventTestHandler
, "{29E7F7EE-0867-467A-8389-68B07C184109}"
, AZ::SystemAllocator
, Event
, Number
, String
, Object);
static void Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EventTestHandler>()
->Version(0)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<EventTestBus>("EventTestHandler")
->Handler<EventTestHandler>()
;
}
}
void Event() override
{
Call(FN_Event);
}
int Number(int input) override
{
int output;
CallResult(output, FN_Number, input);
return output;
}
AZStd::string String(AZStd::string_view input) override
{
AZStd::string output;
CallResult(output, FN_String, input);
return output;
}
TestBehaviorContextObject Object(const TestBehaviorContextObject& input) override
{
TestBehaviorContextObject output;
CallResult(output, FN_Object, input);
return output;
}
}; // EventTestHandler
class ConvertibleToString
{
public:
AZ_TYPE_INFO(StringView, "{DBF947E7-4097-4C5D-AF0D-E2DB311E8958}");
static AZStd::string ConstCharPtrToString(const char* inputStr)
{
return AZStd::string_view(inputStr);
}
static AZStd::string StringViewToString(AZStd::string_view inputView)
{
return inputView;
}
static void Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ConvertibleToString>()
->Version(0)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<ConvertibleToString>("ConvertibleToString")
->Method("ConstCharPtrToString", &ConvertibleToString::ConstCharPtrToString)
->Method("StringViewToString", &ConvertibleToString::StringViewToString)
;
}
}
};
class UnitTestEntityContext
: public AzFramework::EntityIdContextQueryBus::MultiHandler
, public AzFramework::EntityContextRequestBus::Handler
, public AzFramework::SliceEntityOwnershipServiceRequestBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(UnitTestEntityContext, AZ::SystemAllocator, 0);
UnitTestEntityContext()
{
AzFramework::EntityContextRequestBus::Handler::BusConnect(GetOwningContextId());
AzFramework::SliceEntityOwnershipServiceRequestBus::Handler::BusConnect(GetOwningContextId());
}
//// EntityIdContextQueryBus::MultiHandler
// Returns a generate Uuid which represents the UnitTest EntityContext
AzFramework::EntityContextId GetOwningContextId() override { return AzFramework::EntityContextId("{36591268-5CE9-4BC1-8277-0AB9AD528447}"); }
////
//////////////////////////////////////////////////////////////////////////
// SliceEntityOwnershipServiceRequestBus
AZ::Data::AssetId CurrentlyInstantiatingSlice() override;
bool HandleRootEntityReloadedFromStream(AZ::Entity* rootEntity, bool remapIds,
AZ::SliceComponent::EntityIdToEntityIdMap* idRemapTable) override;
AZ::SliceComponent* GetRootSlice() override;
AZ::EntityId FindLoadedEntityIdMapping(const AZ::EntityId& staticId) const;
const AZStd::unordered_map<AZ::EntityId, AZ::EntityId>& GetLoadedEntityIdMap() override;
AzFramework::SliceInstantiationTicket InstantiateSlice(const AZ::Data::Asset<AZ::Data::AssetData>& asset,
const AZ::IdUtils::Remapper<AZ::EntityId>::IdMapper& customIdMapper, const AZ::Data::AssetFilterCB& assetLoadFilter) override;
AZ::SliceComponent::SliceInstanceAddress CloneSliceInstance(AZ::SliceComponent::SliceInstanceAddress sourceInstance,
AZ::SliceComponent::EntityIdToEntityIdMap& sourceToCloneEntityIdMap) override;
void CancelSliceInstantiation(const AzFramework::SliceInstantiationTicket& ticket) override;
AzFramework::SliceInstantiationTicket GenerateSliceInstantiationTicket() override;
void SetIsDynamic(bool isDynamic) override;
const AzFramework::RootSliceAsset& GetRootAsset() const override;
//////////////////////////////////////////////////////////////////////////
AZ::Entity* CreateEntity(const char* name) override;
void AddEntity(AZ::Entity* entity) override;
void ActivateEntity(AZ::EntityId entityId) override;
void DeactivateEntity(AZ::EntityId entityId) override;
bool DestroyEntity(AZ::Entity* entity) override;
bool DestroyEntityById(AZ::EntityId entityId) override;
AZ::Entity* CloneEntity(const AZ::Entity& sourceEntity) override;
void ResetContext() override;
////
void AddEntity(AZ::EntityId entityId);
void RemoveEntity(AZ::EntityId entityId);
bool IsOwnedByThisContext(AZ::EntityId entityId) { return m_unitTestEntityIdMap.count(entityId) != 0; }
AZStd::unordered_map<AZ::EntityId, AZ::EntityId> m_unitTestEntityIdMap;
AzFramework::RootSliceAsset m_unitTestRootAsset;
};
template<typename t_Operator, typename t_Operand, typename t_Value>
void BinaryOpTest(const t_Operand& lhs, const t_Operand& rhs, const t_Value& expectedResult, bool forceGraphError = false)
{
using namespace ScriptCanvas;
using namespace Nodes;
AZ::Entity graphEntity("Graph");
graphEntity.Init();
SystemRequestBus::Broadcast(&SystemRequests::CreateGraphOnEntity, &graphEntity);
auto graph = graphEntity.FindComponent<Graph>();
EXPECT_NE(nullptr, graph);
const AZ::EntityId& graphEntityId = graph->GetEntityId();
const ScriptCanvasId& graphUniqueId = graph->GetScriptCanvasId();
AZ::EntityId startID;
CreateTestNode<Nodes::Core::Start>(graphUniqueId, startID);
AZ::EntityId operatorID;
CreateTestNode<t_Operator>(graphUniqueId, operatorID);
AZ::EntityId lhsID;
CreateDataNode(graphUniqueId, lhs, lhsID);
AZ::EntityId rhsID;
CreateDataNode(graphUniqueId, rhs, rhsID);
AZ::EntityId printID;
auto printNode = CreateTestNode<TestNodes::TestResult>(graphUniqueId, printID);
EXPECT_TRUE(Connect(*graph, lhsID, "Get", operatorID, BinaryOperator::k_lhsName));
if (!forceGraphError)
{
EXPECT_TRUE(Connect(*graph, rhsID, "Get", operatorID, BinaryOperator::k_rhsName));
}
EXPECT_TRUE(Connect(*graph, operatorID, BinaryOperator::k_resultName, printID, "Value"));
EXPECT_TRUE(Connect(*graph, startID, "Out", operatorID, BinaryOperator::k_evaluateName));
bool isArithmetic = AZStd::is_base_of<ScriptCanvas::Nodes::ArithmeticExpression, t_Operator>::value;
if (isArithmetic)
{
EXPECT_TRUE(Connect(*graph, operatorID, BinaryOperator::k_outName, printID, "In"));
}
else
{
EXPECT_TRUE(Connect(*graph, operatorID, BinaryOperator::k_onTrue, printID, "In"));
EXPECT_TRUE(Connect(*graph, operatorID, BinaryOperator::k_onFalse, printID, "In"));
}
{
ScriptCanvasEditor::ScopedOutputSuppression suppressOutput;
graph->GetEntity()->Activate();
EXPECT_EQ(graph->IsInErrorState(), forceGraphError);
}
if (!forceGraphError)
{
if (auto result = NodeAccessor::GetInput_UNIT_TEST<t_Value>(printNode, "Value"))
{
EXPECT_EQ(*result, expectedResult);
}
else
{
ADD_FAILURE();
}
}
graph->GetEntity()->Deactivate();
delete graph;
}
template<typename TBusIdType>
class TemplateEventTest
: public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = TBusIdType;
virtual void GenericEvent() = 0;
virtual AZStd::string UpdateNameEvent(AZStd::string_view) = 0;
virtual AZ::Vector3 VectorCreatedEvent(const AZ::Vector3&) = 0;
};
template<typename TBusIdType>
using TemplateEventTestBus = AZ::EBus<TemplateEventTest<TBusIdType>>;
template<typename TBusIdType>
class TemplateEventTestHandler
: public TemplateEventTestBus<TBusIdType>::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER_TEMPLATE(TemplateEventTestHandler, (TemplateEventTestHandler, "{AADA0906-C216-4D98-BD51-76BB0C2F7FAF}", TBusIdType), AZ::SystemAllocator
, GenericEvent
, UpdateNameEvent
, VectorCreatedEvent
);
static void Reflect(AZ::ReflectContext* context)
{
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
const AZStd::string ebusName(AZ::AzTypeInfo<TemplateEventTestHandler>::Name());
behaviorContext->EBus<TemplateEventTestBus<TBusIdType>>(ebusName.data())
->template Handler<TemplateEventTestHandler>()
->Event("Update Name", &TemplateEventTestBus<TBusIdType>::Events::UpdateNameEvent)
;
}
}
void GenericEvent() override
{
Call(FN_GenericEvent);
}
AZStd::string UpdateNameEvent(AZStd::string_view name) override
{
AZStd::string result;
CallResult(result, FN_UpdateNameEvent, name);
return result;
}
AZ::Vector3 VectorCreatedEvent(const AZ::Vector3& newVector) override
{
AZ::Vector3 result;
CallResult(result, FN_VectorCreatedEvent, newVector);
return result;
}
};
class ScriptUnitTestEventHandler
: public UnitTestEventsBus::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER
(ScriptUnitTestEventHandler
, "{3FC89358-837D-43D5-8C4F-61B672A751B2}"
, AZ::SystemAllocator
, Failed
, Result
, SideEffect
, Succeeded);
static void Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ScriptUnitTestEventHandler>()
->Version(0)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<UnitTestEventsBus>("UnitTestEventsBus")
->Handler<ScriptUnitTestEventHandler>()
->Event("Failed", &UnitTestEventsBus::Events::Failed)
->Event("Result", &UnitTestEventsBus::Events::Result)
->Event("SideEffect", &UnitTestEventsBus::Events::SideEffect)
->Event("Succeeded", &UnitTestEventsBus::Events::Succeeded)
;
}
}
void Failed(AZStd::string description) override
{
Call(FN_Failed, description);
}
AZStd::string Result(AZStd::string description) override
{
AZStd::string output;
CallResult(output, FN_Result, description);
return output;
}
void SideEffect(AZStd::string description) override
{
Call(FN_SideEffect, description);
}
void Succeeded(AZStd::string description) override
{
Call(FN_Succeeded, description);
}
}; // ScriptUnitTestEventHandler
class ScriptUnitTestNodeNotificationHandler
: private ScriptCanvas::NodeNotificationsBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(ScriptUnitTestNodeNotificationHandler, AZ::SystemAllocator, 0);
ScriptUnitTestNodeNotificationHandler(AZ::EntityId nodeId)
{
ScriptCanvas::NodeNotificationsBus::Handler::BusConnect(nodeId);
}
~ScriptUnitTestNodeNotificationHandler()
{
ScriptCanvas::NodeNotificationsBus::Handler::BusDisconnect();
}
AZ::u32 GetSlotsAdded() const
{
return m_slotsAdded;
}
AZ::u32 GetSlotsRemoved() const
{
return m_slotsRemoved;
}
private:
void OnSlotAdded([[maybe_unused]] const ScriptCanvas::SlotId& slotId) override
{
++m_slotsAdded;
}
void OnSlotRemoved([[maybe_unused]] const ScriptCanvas::SlotId& slotId) override
{
++m_slotsRemoved;
}
AZ::u32 m_slotsAdded = 0;
AZ::u32 m_slotsRemoved = 0;
};
} // ScriptCanvasTests
@@ -0,0 +1,97 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Source/Framework/ScriptCanvasTestVerify.h>
namespace ScriptCanvasTests
{
ScriptCanvasEditor::UnitTestResult VerifyReporterEditor(const ScriptCanvasEditor::Reporter& reporter)
{
ScriptCanvasEditor::UnitTestResult result = ScriptCanvasEditor::UnitTestResult(false, true, "");
if (!reporter.GetScriptCanvasId().IsValid())
{
result.m_consoleOutput += "Graph is not valid\n";
}
else if (reporter.IsReportFinished())
{
const auto& successes = reporter.GetSuccess();
for (const auto& success : successes)
{
result.m_consoleOutput += "SUCCESS - ";
result.m_consoleOutput += success.data();
result.m_consoleOutput += "\n";
}
if (!reporter.IsActivated())
{
result.m_consoleOutput += "Graph did not activate\n";
}
if (!reporter.IsDeactivated())
{
result.m_consoleOutput += "Graph did not deactivate\n";
}
if (!reporter.IsErrorFree())
{
result.m_consoleOutput += "Graph had errors\n";
}
const auto& failures = reporter.GetFailure();
for (const auto& failure : failures)
{
result.m_consoleOutput += "FAILURE - ";
result.m_consoleOutput += failure.data();
result.m_consoleOutput += "\n";
}
if (!reporter.IsComplete())
{
result.m_consoleOutput += "Graph was not marked complete\n";
}
const auto& checkpoints = reporter.GetCheckpoints();
if (!checkpoints.empty())
{
AZStd::string checkpointPath = "Checkpoint Path:\n";
int i = 0;
for (const auto& checkpoint : checkpoints)
{
checkpointPath += AZStd::string::format("%2d: %s\n", ++i, checkpoint.data());
}
result.m_consoleOutput += checkpointPath.data();
}
if (reporter.IsComplete() && failures.empty())
{
result.m_consoleOutput += "COMPLETE!\n";
result.m_success = true;
return result;
}
}
else
{
result.m_consoleOutput += "Graph report did not finish\n";
}
result.m_consoleOutput += "FAILED!\n";
result.m_success = false;
return result;
}
} // namespace ScriptCanvasTests
@@ -0,0 +1,23 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Editor/Framework/ScriptCanvasReporter.h>
#include <ScriptCanvas/Bus/UnitTestVerificationBus.h>
namespace ScriptCanvasTests
{
ScriptCanvasEditor::UnitTestResult VerifyReporterEditor(const ScriptCanvasEditor::Reporter& reporter);
} // ScriptCanvasTests
@@ -0,0 +1,257 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "UnitTestingReporter.h"
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <AzTest/AzTest.h>
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_EQ(LHS, RHS)\
EXPECT_EQ(LHS, RHS) << report.data();
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_NE(LHS, RHS)\
EXPECT_NE(LHS, RHS) << report.data();
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GT(LHS, RHS)\
EXPECT_GT(LHS, RHS) << report.data();
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GE(LHS, RHS)\
EXPECT_GE(LHS, RHS) << report.data();
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LT(LHS, RHS)\
EXPECT_LT(LHS, RHS) << report.data();
#define SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LE(LHS, RHS)\
EXPECT_LE(LHS, RHS) << report.data();
namespace ScriptCanvas
{
namespace UnitTesting
{
Reporter::Reporter()
: m_graphId{}
, m_entityId{}
{}
Reporter::Reporter(const RuntimeComponent& graph)
{
SetGraph(graph);
}
Reporter::~Reporter()
{
Reset();
}
void Reporter::Checkpoint(const Report& report)
{
if (m_isReportFinished)
return;
m_checkpoints.push_back(report);
}
const AZStd::vector<Report>& Reporter::GetCheckpoints() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_checkpoints;
}
const AZStd::vector<Report>& Reporter::GetFailure() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_failures;
}
const AZ::EntityId& Reporter::GetGraphId() const
{
return m_graphId;
}
const AZStd::vector<Report>& Reporter::GetSuccess() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_successes;
}
bool Reporter::IsActivated() const
{
return m_graphIsActivated;
}
bool Reporter::IsComplete() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_graphIsComplete;
}
bool Reporter::IsDeactivated() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_graphIsDeactivated;
}
bool Reporter::IsErrorFree() const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_graphIsErrorFree;
}
bool Reporter::IsReportFinished() const
{
return m_isReportFinished;
}
void Reporter::FinishReport()
{
AZ_Assert(!m_isReportFinished, "the report is already finished");
m_isReportFinished = true;
}
void Reporter::FinishReport(const RuntimeComponent& graph)
{
AZ_Assert(!m_isReportFinished, "the report is already finished");
Bus::Handler::BusDisconnect(m_graphId);
AZ::EntityBus::Handler::BusDisconnect(m_entityId);
m_graphIsErrorFree = !graph.IsInErrorState();
m_isReportFinished = true;
}
bool Reporter::operator==(const Reporter& other) const
{
AZ_Assert(m_isReportFinished, "the report must be finished before evaluation");
return m_graphIsActivated == other.m_graphIsActivated
&& m_graphIsDeactivated == other.m_graphIsDeactivated
&& m_graphIsComplete == other.m_graphIsComplete
&& m_graphIsErrorFree == other.m_graphIsErrorFree
&& m_isReportFinished == other.m_isReportFinished
&& m_failures == other.m_failures
&& m_successes == other.m_successes;
}
void Reporter::OnEntityActivated(const AZ::EntityId& entity)
{
AZ_Assert(m_entityId == entity, "this reporter is listening to the wrong entity");
if (m_isReportFinished)
return;
m_graphIsActivated = true;
}
void Reporter::OnEntityDeactivated(const AZ::EntityId& entity)
{
AZ_Assert(m_entityId == entity, "this reporter is listening to the wrong entity");
if (m_isReportFinished)
return;
m_graphIsDeactivated = true;
}
void Reporter::Reset()
{
if (m_graphId.IsValid())
{
Bus::Handler::BusDisconnect();
}
if (m_entityId.IsValid())
{
AZ::EntityBus::Handler::BusDisconnect();
}
m_graphIsActivated = false;
m_graphIsComplete = false;
m_graphIsErrorFree = false;
m_isReportFinished = false;
m_graphId = AZ::EntityId{};
m_failures.clear();
m_failures.clear();
}
void Reporter::SetGraph(const RuntimeComponent& graph)
{
Reset();
m_graphId = graph.GetUniqueId();
m_entityId = graph.GetEntityId();
Bus::Handler::BusConnect(m_graphId);
AZ::EntityBus::Handler::BusConnect(m_entityId);
}
// Handler
void Reporter::MarkComplete(const Report& report)
{
if (m_isReportFinished)
return;
if (m_graphIsComplete)
{
AddFailure(AZStd::string::format("MarkComplete was called twice. %s", report.data()));
}
else
{
m_graphIsComplete = true;
}
}
void Reporter::AddFailure(const Report& report)
{
if (m_isReportFinished)
return;
m_failures.push_back(report);
Checkpoint(AZStd::string::format("AddFailure: %s", report.data()));
}
void Reporter::AddSuccess(const Report& report)
{
if (m_isReportFinished)
return;
m_successes.push_back(report);
Checkpoint(AZStd::string::format("AddSuccess: %s", report.data()));
}
void Reporter::ExpectFalse(const bool value, const Report& report)
{
EXPECT_FALSE(value) << report.data();
Checkpoint(AZStd::string::format("ExpectFalse: %s", report.data()));
}
void Reporter::ExpectTrue(const bool value, const Report& report)
{
EXPECT_TRUE(value) << report.data();
Checkpoint(AZStd::string::format("ExpectTrue: %s", report.data()));
}
void Reporter::ExpectEqualNumber(const Data::NumberType lhs, const Data::NumberType rhs, const Report& report)
{
EXPECT_NEAR(lhs, rhs, 0.001) << report.data();
Checkpoint(AZStd::string::format("ExpectEqualNumber: %s", report.data()));
}
void Reporter::ExpectNotEqualNumber(const Data::NumberType lhs, const Data::NumberType rhs, const Report& report)
{
EXPECT_NE(lhs, rhs) << report.data();
Checkpoint(AZStd::string::format("ExpectNotEqualNumber: %s", report.data()));
}
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_EQ)
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectNotEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_NE)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectGreaterThan, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GT)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectGreaterThanEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_GE)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectLessThan, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LT)
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_IMPLEMENTATIONS(Reporter, ExpectLessThanEqual, SCRIPT_CANVAS_UNIT_TEST_REPORTER_EXPECT_LE)
} // namespace UnitTesting
} // namespace ScriptCanvas
@@ -0,0 +1,109 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/EntityBus.h>
#include <AzCore/Component/EntityId.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Libraries/UnitTesting/UnitTestBus.h>
namespace ScriptCanvas
{
class RuntimeComponent;
namespace UnitTesting
{
class Reporter
: public Bus::Handler
, public AZ::EntityBus::Handler
{
public:
Reporter();
Reporter(const RuntimeComponent& graph);
~Reporter();
void FinishReport();
void FinishReport(const RuntimeComponent& graph);
const AZStd::vector<Report>& GetCheckpoints() const;
const AZStd::vector<Report>& GetFailure() const;
const AZ::EntityId& GetGraphId() const;
const AZStd::vector<Report>& GetSuccess() const;
bool IsActivated() const;
bool IsComplete() const;
bool IsDeactivated() const;
bool IsErrorFree() const;
bool IsReportFinished() const;
bool operator==(const Reporter& other) const;
void Reset();
void SetGraph(const RuntimeComponent& graph);
// Bus::Handler
void AddFailure(const Report& report) override;
void AddSuccess(const Report& report) override;
void Checkpoint(const Report& report) override;
void ExpectFalse(const bool value, const Report& report) override;
void ExpectTrue(const bool value, const Report& report) override;
void MarkComplete(const Report& report) override;
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_OVERRIDES(ExpectEqual);
SCRIPT_CANVAS_UNIT_TEST_EQUALITY_OVERLOAD_OVERRIDES(ExpectNotEqual);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectGreaterThan);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectGreaterThanEqual);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectLessThan);
SCRIPT_CANVAS_UNIT_TEST_COMPARE_OVERLOAD_OVERRIDES(ExpectLessThanEqual);
protected:
void OnEntityActivated(const AZ::EntityId&) override;
void OnEntityDeactivated(const AZ::EntityId&) override;
private:
bool m_graphIsActivated = false;
bool m_graphIsDeactivated = false;
bool m_graphIsComplete = false;
bool m_graphIsErrorFree = false;
bool m_isReportFinished = false;
AZ::EntityId m_graphId;
AZ::EntityId m_entityId;
AZStd::vector<Report> m_checkpoints;
AZStd::vector<Report> m_failures;
AZStd::vector<Report> m_successes;
}; // class Reporter/
} // namespace UnitTesting
} // namespace ScriptCanvas
@@ -0,0 +1,80 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <ScriptCanvas/Core/Attributes.h>
namespace ScriptCanvasTestingNodes
{
//! This object is used to test the use of BehaviorContext classes
class BehaviorContextObjectTest
{
public:
AZ_RTTI(BehaviorContextObjectTest, "{FF687BD7-42AA-44C4-B3AB-79353E8C6CCF}");
AZ_CLASS_ALLOCATOR(BehaviorContextObjectTest, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<BehaviorContextObjectTest>()
->Version(0)
->Field("StringName", &BehaviorContextObjectTest::m_string)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<BehaviorContextObjectTest>("Behavior Context Object Test", "An Object that lives within Behavior Context exclusively for testing")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Tests/Behavior Context")
->Attribute(AZ::Edit::Attributes::CategoryStyle, ".method")
->Attribute(ScriptCanvas::Attributes::Node::TitlePaletteOverride, "TestingNodeTitlePalette")
->DataElement(AZ::Edit::UIHandlers::Default, &BehaviorContextObjectTest::m_string, "String", "")
;
}
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<BehaviorContextObjectTest>()
->Attribute(AZ::Script::Attributes::Category, "Tests/Behavior Context")
->Method("SetString", &BehaviorContextObjectTest::SetString)
->Method("GetString", &BehaviorContextObjectTest::GetString)
;
}
}
BehaviorContextObjectTest()
{
}
virtual ~BehaviorContextObjectTest() {}
void SetString(AZStd::string string)
{
m_string = string;
}
AZStd::string GetString() const
{
return m_string;
}
private:
AZStd::string m_string;
};
}
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Module/Module.h>
#include <ScriptCanvasTestingSystemComponent.h>
#include <Editor/Framework/ScriptCanvasTraceUtilities.h>
namespace ScriptCanvasTesting
{
using namespace ScriptCanvasEditor;
class ScriptCanvasTestingModule
: public AZ::Module
{
public:
AZ_RTTI(ScriptCanvasTestingModule, "{AF32BC51-C4E5-48C4-B5E4-D7877C303D43}", AZ::Module);
AZ_CLASS_ALLOCATOR(ScriptCanvasTestingModule, AZ::SystemAllocator, 0);
ScriptCanvasTestingModule()
{
m_descriptors.insert(m_descriptors.end(), {
ScriptCanvasTestingSystemComponent::CreateDescriptor(),
TraceMessageComponent::CreateDescriptor(),
});
}
/**
* Add required SystemComponents to the SystemEntity.
*/
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<ScriptCanvasTestingSystemComponent>(),
azrtti_typeid<TraceMessageComponent>(),
};
}
};
}
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(Gem_ScriptCanvasTesting, ScriptCanvasTesting::ScriptCanvasTestingModule)
@@ -0,0 +1,49 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Module/Module.h>
#include "ScriptCanvasTestingSystemComponent.h"
namespace ScriptCanvasTesting
{
class ScriptCanvasTestingModule
: public AZ::Module
{
public:
AZ_RTTI(ScriptCanvasTestingModule, "{AF32BC51-C4E5-48C4-B5E4-D7877C303D43}", AZ::Module);
AZ_CLASS_ALLOCATOR(ScriptCanvasTestingModule, AZ::SystemAllocator, 0);
ScriptCanvasTestingModule()
{
m_descriptors.insert(m_descriptors.end(), {
ScriptCanvasTestingSystemComponent::CreateDescriptor(),
});
}
/**
* Add required SystemComponents to the SystemEntity.
*/
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<ScriptCanvasTestingSystemComponent>(),
};
}
};
}
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(Gem_ScriptCanvasTesting, ScriptCanvasTesting::ScriptCanvasTestingModule)
@@ -0,0 +1,82 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <Framework/ScriptCanvasTestVerify.h>
#include "ScriptCanvasTestingSystemComponent.h"
#include <Nodes/BehaviorContextObjectTestNode.h>
namespace ScriptCanvasTesting
{
void ScriptCanvasTestingSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<ScriptCanvasTestingSystemComponent, AZ::Component>()
->Version(0)
;
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<ScriptCanvasTestingSystemComponent>("ScriptCanvasTesting", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
}
}
ScriptCanvasTestingNodes::BehaviorContextObjectTest::Reflect(context);
}
void ScriptCanvasTestingSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("ScriptCanvasTestingService", 0xd2b424fc));
}
void ScriptCanvasTestingSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("ScriptCanvasTestingService", 0xd2b424fc));
}
void ScriptCanvasTestingSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
(void)required;
}
void ScriptCanvasTestingSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
(void)dependent;
}
void ScriptCanvasTestingSystemComponent::Init()
{
}
void ScriptCanvasTestingSystemComponent::Activate()
{
ScriptCanvasEditor::UnitTestVerificationBus::Handler::BusConnect();
}
void ScriptCanvasTestingSystemComponent::Deactivate()
{
ScriptCanvasEditor::UnitTestVerificationBus::Handler::BusDisconnect();
}
ScriptCanvasEditor::UnitTestResult ScriptCanvasTestingSystemComponent::Verify(ScriptCanvasEditor::Reporter reporter)
{
return ScriptCanvasTests::VerifyReporterEditor(reporter);
}
}
@@ -0,0 +1,46 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright EntityRef license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <ScriptCanvas/Bus/ScriptCanvasExecutionBus.h>
#include <ScriptCanvas/Bus/UnitTestVerificationBus.h>
namespace ScriptCanvasTesting
{
class ScriptCanvasTestingSystemComponent
: public AZ::Component
, public ScriptCanvasEditor::UnitTestVerificationBus::Handler
{
public:
AZ_COMPONENT(ScriptCanvasTestingSystemComponent, "{4D0AA0FD-8451-4AA3-883E-82ADB1C44568}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
ScriptCanvasEditor::UnitTestResult Verify(ScriptCanvasEditor::Reporter reporter) override;
protected:
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
};
}