Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

170 lines
5.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "InputTestFramework.h"
#include "Misc/AutomationTest.h"
// Tests focused on binding logic for both delegates and input devices
constexpr auto BasicBindingTestFlags = EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter; // TODO: Run as Smoke/Client? No world on RunSmokeTests startup...
UControllablePlayer& ABasicBindingTest(FAutomationTestBase* Test, EInputActionValueType ForValueType)
{
// Initialise
UWorld* World =
GIVEN(AnEmptyWorld());
UControllablePlayer& Data =
AND(AControllablePlayer(World));
Test->TestTrue(TEXT("Controllable Player is valid"), Data.IsValid()); // TODO: Can we early out on a failed Test?
AND(AnInputContextIsAppliedToAPlayer(Data, TestContext, 0));
UInputAction* Action =
AND(AnInputAction(Data, TestAction, ForValueType));
AND(AnActionIsMappedToAKey(Data, TestContext, TestAction, TestKey));
return Data;
}
// ******************************
// Delegate firing (notification) tests
// ******************************
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInputBindingDigitalTest, "Input.Binding.DigitalTrigger", BasicBindingTestFlags)
bool FInputBindingDigitalTest::RunTest(const FString& Parameters)
{
UControllablePlayer& Data =
GIVEN(ABasicBindingTest(this, EInputActionValueType::Boolean));
// Unpressed shouldn't trigger
WHEN(InputIsTicked(Data));
THEN(!FInputTestHelper::TestTriggered(Data, TestAction));
// Pressing
WHEN(AKeyIsActuated(Data, TestKey));
AND(InputIsTicked(Data));
THEN(PressingKeyTriggersAction(Data, TestAction));
// Holding for multiple ticks
const int32 HoldTicks = 100;
for (int32 i = 0; i < HoldTicks; ++i)
{
WHEN(InputIsTicked(Data));
THEN(HoldingKeyTriggersAction(Data, TestAction));
}
// Releasing - does not fire canceled!
WHEN(AKeyIsReleased(Data, TestKey));
AND(InputIsTicked(Data));
THEN(ReleasingKeyTriggersCompleted(Data, TestAction));
WHEN(InputIsTicked(Data));
THEN(ReleasingKeyDoesNotTrigger(Data, TestAction));
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInputBindingAnalogTest, "Input.Binding.AnalogTrigger", BasicBindingTestFlags)
bool FInputBindingAnalogTest::RunTest(const FString& Parameters)
{
UControllablePlayer& Data =
GIVEN(ABasicBindingTest(this, EInputActionValueType::Axis1D));
// Unpressed shouldn't trigger
WHEN(AnActionIsMappedToAKey(Data, TestContext, TestAction, TestAxis));
AND(InputIsTicked(Data));
THEN(!FInputTestHelper::TestTriggered(Data, TestAction));
const TArray<float> TestValues = { 0.25f, 0.5f, 1.f, 1.f, -1.f, 0.75f, 0.5f, -0.1f};
for(float TestValue : TestValues)
{
WHEN(AKeyIsActuated(Data, TestAxis, TestValue));
AND(InputIsTicked(Data));
THEN(PressingKeyTriggersAction(Data, TestAction));
AND(TestEqual(TEXT("Trigger value"), FInputTestHelper::GetTriggered<float>(Data, TestAction), TestValue));
}
// Releasing - does not fire canceled!
WHEN(AKeyIsReleased(Data, TestAxis));
AND(InputIsTicked(Data));
THEN(ReleasingKeyTriggersCompleted(Data, TestAction));
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInputBindingMultipleKeyValuesTest, "Input.Binding.MultipleKeyValues", BasicBindingTestFlags)
bool FInputBindingMultipleKeyValuesTest::RunTest(const FString& Parameters)
{
const int32 HoldTicks = 10;
UControllablePlayer& Data =
GIVEN(ABasicBindingTest(this, EInputActionValueType::Boolean));
AND(AnActionIsMappedToAKey(Data, TestContext, TestAction, TestKey2)); // Bind second key
AND(AKeyIsActuated(Data, TestKey)); // Depress first key
// Holding for multiple ticks
for (int32 i = 0; i < HoldTicks; ++i)
{
WHEN(InputIsTicked(Data));
THEN(HoldingKeyTriggersAction(Data, TestAction));
AND(TestEqual(TEXT("Single keypress generates a consistent value over multiple ticks"), FInputTestHelper::GetTriggered<FVector>(Data, TestAction), FVector(1.f, 0.f, 0.f)));
}
// Switch keys in a single tick
WHEN(AKeyIsReleased(Data, TestKey));
AND(AKeyIsActuated(Data, TestKey2));
// Holding for multiple ticks
for (int32 i = 0; i < HoldTicks; ++i)
{
WHEN(InputIsTicked(Data));
THEN(HoldingKeyTriggersAction(Data, TestAction));
AND(TestEqual(TEXT("Switching keys in a single tick generates a consistent value"), FInputTestHelper::GetTriggered<FVector>(Data, TestAction), FVector(1.f, 0.f, 0.f)));
}
// Switch keys over 2 ticks
WHEN(AKeyIsReleased(Data, TestKey2));
AND(InputIsTicked(Data));
AND(AKeyIsActuated(Data, TestKey));
// Holding for multiple ticks
for (int32 i = 0; i < HoldTicks; ++i)
{
WHEN(InputIsTicked(Data));
THEN(HoldingKeyTriggersAction(Data, TestAction));
AND(TestEqual(TEXT("Switching keys over two ticks generates a consistent value"), FInputTestHelper::GetTriggered<FVector>(Data, TestAction), FVector(1.f, 0.f, 0.f)));
}
// Release both keys
WHEN(AKeyIsReleased(Data, TestKey));
AND(InputIsTicked(Data));
THEN(ReleasingKeyTriggersCompleted(Data, TestAction));
// Double key press on a single tick with hold
WHEN(AKeyIsActuated(Data, TestKey));
AND(AKeyIsActuated(Data, TestKey2));
for (int32 i = 0; i < HoldTicks; ++i)
{
WHEN(InputIsTicked(Data));
THEN(HoldingKeyTriggersAction(Data, TestAction));
AND(TestEqual(TEXT("Multiple key actuations on a single tick generates a consistent value"), FInputTestHelper::GetTriggered<FVector>(Data, TestAction), FVector(1.f, 0.f, 0.f)));
}
// Unpressed shouldn't trigger
WHEN(AKeyIsReleased(Data, TestKey));
AND(AKeyIsReleased(Data, TestKey2));
WHEN(InputIsTicked(Data));
THEN(!FInputTestHelper::TestTriggered(Data, TestAction));
return true;
}
// TODO: Need to check merging logic for keys generating different levels of "pressedness" activity
// TODO: Merging of multiple input mapping contexts including priority and actions of various bConsumeInput states