Write some unit tests for the input buffer
This commit is contained in:
parent
ee8dff88ea
commit
3d4c56fcd9
@ -18,14 +18,14 @@ bool UFFInputBufferComponent::CheckInputSequence(const FFFInputSequence& InputSe
|
|||||||
{
|
{
|
||||||
if(InputSequence.Sequence.IsEmpty())
|
if(InputSequence.Sequence.IsEmpty())
|
||||||
{
|
{
|
||||||
UE_LOG(LogTemp, Error,
|
UE_LOG(LogTemp, Warning,
|
||||||
TEXT("FFInputBufferComponent :: CheckInputSequence - tried to check input sequence but it was empty"));
|
TEXT("FFInputBufferComponent :: CheckInputSequence - tried to check input sequence but it was empty"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CondIdx = InputSequence.Sequence.Num() - 1;
|
int CondIdx = InputSequence.Sequence.Num() - 1;
|
||||||
int ElapsedFrames = 0;
|
int ElapsedFrames = 0;
|
||||||
for(int InpIdx = InputBuffer.Num() - 1; InpIdx > 1; InpIdx--)
|
for(int InpIdx = InputBuffer.Num() - 1; InpIdx > 0; InpIdx--)
|
||||||
{
|
{
|
||||||
int32 RequiredButtons = InputSequence.Sequence[CondIdx].RequiredButtons;
|
int32 RequiredButtons = InputSequence.Sequence[CondIdx].RequiredButtons;
|
||||||
EFFButtonState RequiredButtonState = InputSequence.Sequence[CondIdx].RequiredButtonState;
|
EFFButtonState RequiredButtonState = InputSequence.Sequence[CondIdx].RequiredButtonState;
|
||||||
@ -100,3 +100,8 @@ void UFFInputBufferComponent::DisableMostRecentInput()
|
|||||||
InputBuffer[InputBuffer.Num() - 1].DisabledButtons |= InputBuffer[InputBuffer.Num() - 1].Buttons;
|
InputBuffer[InputBuffer.Num() - 1].DisabledButtons |= InputBuffer[InputBuffer.Num() - 1].Buttons;
|
||||||
InputBuffer[InputBuffer.Num() - 2].DisabledButtons |= InputBuffer[InputBuffer.Num() - 2].Buttons;
|
InputBuffer[InputBuffer.Num() - 2].DisabledButtons |= InputBuffer[InputBuffer.Num() - 2].Buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UFFInputBufferComponent::FlushBuffer()
|
||||||
|
{
|
||||||
|
InputBuffer.Flush();
|
||||||
|
}
|
||||||
|
@ -101,6 +101,8 @@ public:
|
|||||||
|
|
||||||
void DisableMostRecentInput();
|
void DisableMostRecentInput();
|
||||||
|
|
||||||
|
void FlushBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** The underlying buffer data structure for holding past input states */
|
/** The underlying buffer data structure for holding past input states */
|
||||||
TCircleBuffer<FFFInputState, 120> InputBuffer;
|
TCircleBuffer<FFFInputState, 120> InputBuffer;
|
||||||
|
139
Source/UnrealFightingFramework/Tests/InputBufferTests.cpp
Normal file
139
Source/UnrealFightingFramework/Tests/InputBufferTests.cpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// Project Sword & Gun Copyright Kevin Poretti
|
||||||
|
|
||||||
|
// FF includes
|
||||||
|
#include "Input/FFInputBufferComponent.h"
|
||||||
|
|
||||||
|
// UE includes
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Misc/AutomationTest.h"
|
||||||
|
|
||||||
|
#if WITH_DEV_AUTOMATION_TESTS
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FInputBufferTest, "FF.Input.InputBuffer",
|
||||||
|
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)
|
||||||
|
bool FInputBufferTest::RunTest(const FString& Parameters)
|
||||||
|
{
|
||||||
|
TStrongObjectPtr<UWorld> World = TStrongObjectPtr(UWorld::CreateWorld(EWorldType::Game, false));
|
||||||
|
// Create a dummy actor
|
||||||
|
TStrongObjectPtr<AActor> InputBufferOwner = TStrongObjectPtr<AActor>(World->SpawnActor<AActor>());
|
||||||
|
TestTrue(TEXT("Create InputBufferOwner"), InputBufferOwner.IsValid());
|
||||||
|
UFFInputBufferComponent* InputBuffer =
|
||||||
|
NewObject<UFFInputBufferComponent>(InputBufferOwner.Get(),
|
||||||
|
UFFInputBufferComponent::StaticClass(), TEXT("InputBuffer"));
|
||||||
|
InputBuffer->RegisterComponent();
|
||||||
|
|
||||||
|
// InputBuffer must be able to be created as a subobject of an actor
|
||||||
|
{
|
||||||
|
TestNotNull(TEXT("Create new InputBuffer component"), InputBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputBuffer should not attempt to evaluate an input sequence if there is only one input in
|
||||||
|
// the buffer and should return false
|
||||||
|
{
|
||||||
|
FFFInputState InputDown;
|
||||||
|
InputDown.Buttons = 0x00000001;
|
||||||
|
|
||||||
|
InputBuffer->AddInput(InputDown);
|
||||||
|
|
||||||
|
FFFInputCondition PressedCondition;
|
||||||
|
PressedCondition.RequiredButtons = 0x00000001;
|
||||||
|
PressedCondition.RequiredButtonState = EFFButtonState::BTNS_Pressed;
|
||||||
|
PressedCondition.TimeoutDuration = 0;
|
||||||
|
|
||||||
|
FFFInputSequence PressedSequence;
|
||||||
|
PressedSequence.Sequence.Add(PressedCondition);
|
||||||
|
TestFalse(TEXT("Don't try to detect a sequence if only one input is present in the buffer"),
|
||||||
|
InputBuffer->CheckInputSequence(PressedSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBuffer->FlushBuffer();
|
||||||
|
|
||||||
|
// InputBuffer should not attempt to evaluate an input sequence if the sequence has no input conditions
|
||||||
|
{
|
||||||
|
FFFInputState InputUp;
|
||||||
|
InputUp.Buttons = 0x00000000;
|
||||||
|
FFFInputState InputDown;
|
||||||
|
InputDown.Buttons = 0x00000001;
|
||||||
|
|
||||||
|
InputBuffer->AddInput(InputUp);
|
||||||
|
InputBuffer->AddInput(InputDown);
|
||||||
|
|
||||||
|
FFFInputSequence EmptySequence;
|
||||||
|
TestFalse(TEXT("Don't try to detect a sequence if the sequence has no input conditions"),
|
||||||
|
InputBuffer->CheckInputSequence(EmptySequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBuffer->FlushBuffer();
|
||||||
|
|
||||||
|
// InputBuffer must detect simple button pressed condition
|
||||||
|
{
|
||||||
|
FFFInputState InputUp;
|
||||||
|
InputUp.Buttons = 0x00000000;
|
||||||
|
FFFInputState InputDown;
|
||||||
|
InputDown.Buttons = 0x00000001;
|
||||||
|
|
||||||
|
InputBuffer->AddInput(InputUp);
|
||||||
|
InputBuffer->AddInput(InputDown);
|
||||||
|
|
||||||
|
FFFInputCondition PressedCondition;
|
||||||
|
PressedCondition.RequiredButtons = 0x00000001;
|
||||||
|
PressedCondition.RequiredButtonState = EFFButtonState::BTNS_Pressed;
|
||||||
|
PressedCondition.TimeoutDuration = 0;
|
||||||
|
|
||||||
|
FFFInputSequence PressedSequence;
|
||||||
|
PressedSequence.Sequence.Add(PressedCondition);
|
||||||
|
TestTrue(TEXT("Detect a single button press in the buffer"),
|
||||||
|
InputBuffer->CheckInputSequence(PressedSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBuffer->FlushBuffer();
|
||||||
|
|
||||||
|
// InputBuffer must detect simple button released condition
|
||||||
|
{
|
||||||
|
FFFInputState InputUp;
|
||||||
|
InputUp.Buttons = 0x0000000;
|
||||||
|
FFFInputState InputDown;
|
||||||
|
InputDown.Buttons = 0x00000001;
|
||||||
|
|
||||||
|
InputBuffer->AddInput(InputDown);
|
||||||
|
InputBuffer->AddInput(InputUp);
|
||||||
|
|
||||||
|
FFFInputCondition ReleasedCondition;
|
||||||
|
ReleasedCondition.RequiredButtons = 0x00000001;
|
||||||
|
ReleasedCondition.RequiredButtonState = EFFButtonState::BTNS_Released;
|
||||||
|
ReleasedCondition.TimeoutDuration = 0;
|
||||||
|
|
||||||
|
FFFInputSequence ReleasedSequence;
|
||||||
|
ReleasedSequence.Sequence.Add(ReleasedCondition);
|
||||||
|
TestTrue(TEXT("Detect a single button release in the buffer"),
|
||||||
|
InputBuffer->CheckInputSequence(ReleasedSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBuffer->FlushBuffer();
|
||||||
|
|
||||||
|
// InputBuffer must detect simple button down condition
|
||||||
|
{
|
||||||
|
FFFInputState InputUp;
|
||||||
|
InputUp.Buttons = 0x0000000;
|
||||||
|
FFFInputState InputDown;
|
||||||
|
InputDown.Buttons = 0x00000001;
|
||||||
|
|
||||||
|
InputBuffer->AddInput(InputUp);
|
||||||
|
InputBuffer->AddInput(InputDown);
|
||||||
|
|
||||||
|
FFFInputCondition DownCondition;
|
||||||
|
DownCondition.RequiredButtons = 0x00000001;
|
||||||
|
DownCondition.RequiredButtonState = EFFButtonState::BTNS_Down;
|
||||||
|
DownCondition.TimeoutDuration = 0;
|
||||||
|
|
||||||
|
FFFInputSequence DownSequence;
|
||||||
|
DownSequence.Sequence.Add(DownCondition);
|
||||||
|
TestTrue(TEXT("Detect a single button press in the buffer"),
|
||||||
|
InputBuffer->CheckInputSequence(DownSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
World->DestroyWorld(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //WITH_DEV_AUTOMATION_TESTS
|
@ -108,6 +108,16 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes the buffer of all contents
|
||||||
|
*/
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
WriteIdx = 0;
|
||||||
|
ReadIdx = 0;
|
||||||
|
_Num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the element at an index supplied to the function.
|
* @brief Returns the element at an index supplied to the function.
|
||||||
* This function will account for write index offset and wraparound of the supplied index.
|
* This function will account for write index offset and wraparound of the supplied index.
|
||||||
|
Loading…
Reference in New Issue
Block a user