Files
ProjectEleri/Plugins/DirectiveUtilities/Source/DirectiveUtilitiesTests/Private/Tests/DirectiveUtilEditorTaskLibraryTest.cpp

99 lines
4.9 KiB
C++

// Copyright (c) 2026 Unreal Directive. Licensed under the MIT License.
#include "Libraries/DirectiveUtilEditorTaskLibrary.h"
#include "Misc/AutomationTest.h"
#include "Tasks/DirectiveUtilEditorSlowTask.h"
#include <limits>
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FDirectiveUtilEditorTaskLibraryTest,
"DirectiveUtilities.EditorTaskLibraryTests",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
bool FDirectiveUtilEditorTaskLibraryTest::RunTest(const FString& Parameters)
{
TestNull("StartEditorSlowTask should reject zero work", UDirectiveUtilEditorTaskLibrary::StartEditorSlowTask(0.0f, FText::GetEmpty()));
TestNull(
"StartEditorSlowTask should reject NaN work",
UDirectiveUtilEditorTaskLibrary::StartEditorSlowTask(
std::numeric_limits<float>::quiet_NaN(),
FText::GetEmpty()));
TestNull(
"StartEditorSlowTask should reject infinite work",
UDirectiveUtilEditorTaskLibrary::StartEditorSlowTask(
std::numeric_limits<float>::infinity(),
FText::GetEmpty()));
UDirectiveUtilEditorSlowTask* PublicTask = UDirectiveUtilEditorTaskLibrary::StartEditorSlowTask(
1.0f,
FText::FromString(TEXT("Public task")));
TestNotNull("StartEditorSlowTask should create a task for positive work", PublicTask);
if (PublicTask)
{
TestNull(
"StartEditorSlowTask should reject a nested task",
UDirectiveUtilEditorTaskLibrary::StartEditorSlowTask(
1.0f,
FText::FromString(TEXT("Nested task"))));
PublicTask->Finish();
}
UDirectiveUtilEditorSlowTask* Task = NewObject<UDirectiveUtilEditorSlowTask>();
Task->Initialize(2.0f, FText::FromString(TEXT("Test task")), false, false);
TestTrue("Slow task should be active after initialization", Task->IsActive());
TestTrue("Advance should accept non-negative work", Task->Advance(1.0f, FText::FromString(TEXT("Step"))));
TestFalse("Advance should reject negative work", Task->Advance(-1.0f, FText::GetEmpty()));
TestFalse("Advance should reject NaN work", Task->Advance(std::numeric_limits<float>::quiet_NaN(), FText::GetEmpty()));
TestFalse("Advance should reject infinite work", Task->Advance(std::numeric_limits<float>::infinity(), FText::GetEmpty()));
TestFalse("A non-cancellable task should not report cancellation", Task->IsCancelRequested());
Task->Finish();
TestFalse("Slow task should be inactive after Finish", Task->IsActive());
TestFalse("Advance should fail after Finish", Task->Advance(1.0f, FText::GetEmpty()));
Task->Initialize(std::numeric_limits<float>::quiet_NaN(), FText::GetEmpty(), false, false);
TestFalse("Initialize should leave a task inactive for NaN work", Task->IsActive());
Task->Initialize(std::numeric_limits<float>::infinity(), FText::GetEmpty(), false, false);
TestFalse("Initialize should leave a task inactive for infinite work", Task->IsActive());
UDirectiveUtilEditorSlowTask* FirstTask = NewObject<UDirectiveUtilEditorSlowTask>();
UDirectiveUtilEditorSlowTask* SecondTask = NewObject<UDirectiveUtilEditorSlowTask>();
FirstTask->Initialize(1.0f, FText::FromString(TEXT("First task")), false, false);
SecondTask->Initialize(1.0f, FText::FromString(TEXT("Second task")), false, false);
TestTrue("The first slow task should remain active", FirstTask->IsActive());
TestFalse("A concurrent slow task should remain inactive", SecondTask->IsActive());
FirstTask->Finish();
SecondTask->Initialize(1.0f, FText::FromString(TEXT("Second task")), false, false);
TestTrue("A slow task should start after the active task finishes", SecondTask->IsActive());
SecondTask->Finish();
TWeakObjectPtr<UDirectiveUtilEditorSlowTask> AbandonedTask = NewObject<UDirectiveUtilEditorSlowTask>();
AbandonedTask->Initialize(1.0f, FText::FromString(TEXT("Abandoned task")), false, false);
TestTrue("An unfinished slow task should be active before collection", AbandonedTask->IsActive());
CollectGarbage(RF_NoFlags);
TestTrue("An unfinished slow task should stay alive until Finish", AbandonedTask.IsValid());
if (AbandonedTask.IsValid())
{
AbandonedTask->Finish();
}
CollectGarbage(RF_NoFlags);
TestFalse("A finished slow task should be collectable", AbandonedTask.IsValid());
UDirectiveUtilEditorSlowTask* TaskAfterCollection = NewObject<UDirectiveUtilEditorSlowTask>();
TaskAfterCollection->Initialize(1.0f, FText::FromString(TEXT("Task after collection")), false, false);
TestTrue("A slow task should start after the previous task is collected", TaskAfterCollection->IsActive());
TaskAfterCollection->Finish();
TestTrue(
"ShowEditorNotification should create a notification while Slate is active",
UDirectiveUtilEditorTaskLibrary::ShowEditorNotification(
FText::FromString(TEXT("Directive Utilities test")),
EDirectiveUtilEditorNotificationState::Success,
0.01f));
TestTrue(
"ShowEditorNotification should normalize a non-finite duration",
UDirectiveUtilEditorTaskLibrary::ShowEditorNotification(
FText::FromString(TEXT("Directive Utilities duration test")),
EDirectiveUtilEditorNotificationState::Neutral,
std::numeric_limits<float>::quiet_NaN()));
return true;
}