Files
UnrealEngine/Engine/Source/Programs/AutoRTFMTests/Private/UPackageTests.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

672 lines
20 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AutoRTFM.h"
#include "AutoRTFMTestUtils.h"
#include "AutoRTFMTesting.h"
#include "MyAutoRTFMTestObject.h"
#include "Misc/PackageName.h"
#include "UObject/LinkerInstancingContext.h"
#include "UObject/Package.h"
#include "UObject/SavePackage.h"
#include "Catch2Includes.h"
static void TrashPackage(UPackage* const Package)
{
// TODO: If we could move the trashing logic into `UPackage` we could just call that here?
const FName NewName = MakeUniqueObjectName(nullptr, UPackage::StaticClass(), NAME_TrashedPackage);
Package->Rename(*NewName.ToString(), nullptr, REN_DontCreateRedirectors | REN_NonTransactional | REN_DoNotDirty);
Package->SetFlags(RF_Transient);
}
TEST_CASE("UPackage.SetPackageFlagsTo")
{
SECTION("Commit")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_None);
AutoRTFM::Testing::Commit([&]
{
Package->SetPackageFlagsTo(PKG_TransientFlags);
});
REQUIRE(Package->GetPackageFlags() == PKG_TransientFlags);
}
SECTION("Abort")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_None);
AutoRTFM::Testing::Abort([&]
{
Package->SetPackageFlagsTo(PKG_TransientFlags);
REQUIRE(Package->GetPackageFlags() == PKG_TransientFlags);
AutoRTFM::AbortTransaction();
});
REQUIRE(Package->GetPackageFlags() == PKG_None);
}
}
TEST_CASE("UPackage.SetPackageFlags")
{
SECTION("Commit")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_RuntimeGenerated);
AutoRTFM::Testing::Commit([&]
{
Package->SetPackageFlags(PKG_TransientFlags);
});
REQUIRE(Package->GetPackageFlags() == (PKG_RuntimeGenerated | PKG_TransientFlags));
}
SECTION("Abort")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_RuntimeGenerated);
AutoRTFM::Testing::Abort([&]
{
Package->SetPackageFlags(PKG_TransientFlags);
REQUIRE(Package->GetPackageFlags() == (PKG_RuntimeGenerated | PKG_TransientFlags));
AutoRTFM::AbortTransaction();
});
REQUIRE(Package->GetPackageFlags() == PKG_RuntimeGenerated);
}
}
TEST_CASE("UPackage.ClearPackageFlags")
{
SECTION("Commit")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_RuntimeGenerated | PKG_TransientFlags);
AutoRTFM::Testing::Commit([&]
{
Package->ClearPackageFlags(PKG_TransientFlags);
});
REQUIRE(Package->GetPackageFlags() == PKG_RuntimeGenerated);
}
SECTION("Abort")
{
UPackage* Package = NewObject<UPackage>();
Package->SetPackageFlagsTo(PKG_RuntimeGenerated | PKG_TransientFlags);
AutoRTFM::Testing::Abort([&]
{
Package->ClearPackageFlags(PKG_TransientFlags);
REQUIRE(Package->GetPackageFlags() == PKG_RuntimeGenerated);
AutoRTFM::AbortTransaction();
});
REQUIRE(Package->GetPackageFlags() == (PKG_RuntimeGenerated | PKG_TransientFlags));
}
}
// Based on `Engine\Private\Tests\Loading\AsyncLoadingTests_Shared.h`, we use similar logic
// here to make a package that the loader will see and be able to actually load!
struct FPackageScopedMaker final
{
FString PackagePath;
FPackageScopedMaker(FString PackageName) : PackagePath(FPackageName::LongPackageNameToFilename(*PackageName, FPackageName::GetAssetPackageExtension()))
{
// We need to remove any previous package of the same name (could have occurred if a previous test ran segfaulted for instance).
if (FPackageName::DoesPackageExist(PackageName))
{
REQUIRE(IPlatformFile::GetPlatformPhysical().SetReadOnly(*PackagePath, false));
REQUIRE(IPlatformFile::GetPlatformPhysical().DeleteFile(*PackagePath));
}
// Ensure that async loading is done.
FlushAsyncLoading();
// Create a package.
UPackage* const Package = CreatePackage(*PackageName);
// With at least one object in it.
FString ObjectName(PackageName);
ObjectName.Append(".TestObject");
UObject* const Object = NewObject<UMyAutoRTFMTestObject>(Package, *ObjectName, RF_Public | RF_Standalone);
// Need to mark it is loaded.
Package->MarkAsFullyLoaded();
// Then wipe the standalone flag for reasons.
Object->ClearFlags(RF_Standalone);
// Save the package to the file-system.
REQUIRE(UPackage::SavePackage(Package, nullptr, *PackagePath, FSavePackageArgs()));
// Make sure the package existed in our tables before.
REQUIRE(FindObject<UObject>(nullptr, *PackageName) != nullptr);
// GC and make sure everything gets cleaned up before loading.
CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS);
// Then make sure the package is no longer loaded in our tables after.
REQUIRE(FindObject<UObject>(nullptr, *PackageName) == nullptr);
}
};
TEST_CASE("UPackage.AsyncLoading")
{
SECTION("DoesPackageExist")
{
AutoRTFM::Testing::Commit([&]
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
REQUIRE(!FPackageName::DoesPackageExist(Name));
});
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
AutoRTFM::Testing::Commit([&]
{
REQUIRE(FPackageName::DoesPackageExist(Name));
});
}
SECTION("LoadPackageAsync")
{
int32 RequestId = -1;
AutoRTFM::Testing::Commit([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
RequestId = LoadPackageAsync(Name);
});
FlushAsyncLoading(RequestId);
}
SECTION("IsAsyncLoading")
{
int32 RequestId = -1;
AutoRTFM::Testing::Commit([&]
{
REQUIRE(!IsAsyncLoading());
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
RequestId = LoadPackageAsync(Name);
REQUIRE(IsAsyncLoading());
});
FlushAsyncLoading(RequestId);
}
SECTION("FlushAsyncLoading")
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
int32 RequestId = LoadPackageAsync(Name);
AutoRTFM::Testing::Commit([&]
{
FlushAsyncLoading(RequestId);
});
}
SECTION("FlushAsyncLoading Empty")
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
int32 RequestId = LoadPackageAsync(Name);
AutoRTFM::Testing::Commit([&]
{
FlushAsyncLoading();
});
}
SECTION("FlushAsyncLoading One In One Out")
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
int32 RequestId1 = LoadPackageAsync(Name);
AutoRTFM::Testing::Commit([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
int32 RequestId2 = LoadPackageAsync(Name);
TArray<int32> RequestIds;
RequestIds.Add(RequestId1);
RequestIds.Add(RequestId2);
FlushAsyncLoading(RequestIds);
});
}
SECTION("CompletionDelegate is called closed")
{
AutoRTFM::Testing::Abort([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
FLoadPackageAsyncDelegate CompletionDelegate;
CompletionDelegate.BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type) { REQUIRE(AutoRTFM::IsClosed()); });
int RequestId = LoadPackageAsync(Name, CompletionDelegate);
FlushAsyncLoading(RequestId);
AutoRTFM::AbortTransaction();
});
}
SECTION("CompletionDelegate aborts")
{
AutoRTFM::Testing::Abort([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
FLoadPackageAsyncDelegate CompletionDelegate;
CompletionDelegate.BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type) { AutoRTFM::AbortTransaction(); });
int RequestId = LoadPackageAsync(Name, CompletionDelegate);
FlushAsyncLoading(RequestId);
FAIL("Unreachable!");
});
}
SECTION("FLoadPackageAsyncOptionalParams::CompletionDelegate is called closed")
{
AutoRTFM::Testing::Abort([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
FLoadPackageAsyncOptionalParams Params;
Params.CompletionDelegate.Reset(new FLoadPackageAsyncDelegate());
Params.CompletionDelegate->BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type) { REQUIRE(AutoRTFM::IsClosed()); });
int RequestId = LoadPackageAsync(Name, MoveTemp(Params));
FlushAsyncLoading(RequestId);
AutoRTFM::AbortTransaction();
});
}
SECTION("FLoadPackageAsyncOptionalParams::CompletionDelegate aborts")
{
AutoRTFM::Testing::Abort([&]
{
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
FLoadPackageAsyncOptionalParams Params;
Params.CompletionDelegate.Reset(new FLoadPackageAsyncDelegate());
Params.CompletionDelegate->BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type) { AutoRTFM::AbortTransaction(); });
int RequestId = LoadPackageAsync(Name, MoveTemp(Params));
FlushAsyncLoading(RequestId);
FAIL("Unreachable!");
});
}
SECTION("FLoadPackageAsyncOptionalParams::CompletionDelegate creates UObject")
{
UMyAutoRTFMTestObject* OpenObject = nullptr;
UMyAutoRTFMTestObject* ClosedObject = nullptr;
AutoRTFM::Testing::Abort([&]
{
ClosedObject = NewObject<UMyAutoRTFMTestObject>();
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
FLoadPackageAsyncOptionalParams Params;
Params.CompletionDelegate.Reset(new FLoadPackageAsyncDelegate());
Params.CompletionDelegate->BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type)
{
OpenObject = NewObject<UMyAutoRTFMTestObject>();
AutoRTFM::AbortTransaction();
});
int RequestId = LoadPackageAsync(Name, MoveTemp(Params));
FlushAsyncLoading(RequestId);
FAIL("Unreachable!");
});
REQUIRE(nullptr == ClosedObject);
REQUIRE(nullptr == OpenObject);
}
SECTION("FLoadPackageAsyncOptionalParams::CompletionDelegate calls another LoadPackageAsync")
{
AutoRTFM::Testing::Abort([&]
{
FLoadPackageAsyncOptionalParams Params;
Params.CompletionDelegate.Reset(new FLoadPackageAsyncDelegate());
Params.CompletionDelegate->BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type)
{
int RequestId = LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), MoveTemp(Params));
AutoRTFM::AbortTransaction();
});
int RequestId = LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), MoveTemp(Params));
FlushAsyncLoading(RequestId);
FAIL("Unreachable!");
});
}
SECTION("Multiple retries because of multiple loads with commit")
{
AutoRTFMTestUtils::FScopedRetry Retry(AutoRTFM::ForTheRuntime::EAutoRTFMRetryTransactionState::NoRetry);
int NumCompletionCallbacks = 0;
AutoRTFM::Testing::Commit([&]
{
FLoadPackageAsyncDelegate CompletionDelegate;
CompletionDelegate.BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type)
{
// Do this open so we can check how many retries occurred.
AutoRTFM::Open([&] { NumCompletionCallbacks++; });
});
TArray<int32> RequestIds;
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
FlushAsyncLoading(RequestIds);
REQUIRE(3 == NumCompletionCallbacks);
});
}
SECTION("Multiple retries because of multiple loads with abort")
{
AutoRTFMTestUtils::FScopedRetry Retry(AutoRTFM::ForTheRuntime::EAutoRTFMRetryTransactionState::NoRetry);
int NumCompletionCallbacks = 0;
AutoRTFM::Testing::Abort([&]
{
FLoadPackageAsyncDelegate CompletionDelegate;
CompletionDelegate.BindLambda([&](const FName&, UPackage*, EAsyncLoadingResult::Type)
{
// Do this open so we can check how many retries occurred.
AutoRTFM::Open([&] { NumCompletionCallbacks++; });
});
TArray<int32> RequestIds;
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
RequestIds.Add(LoadPackageAsync(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__), CompletionDelegate));
FlushAsyncLoading(RequestIds);
REQUIRE(3 == NumCompletionCallbacks);
AutoRTFM::AbortTransaction();
});
}
SECTION("Stack Local Linker Instancing Context")
{
int32 RequestId = -1;
AutoRTFM::Testing::Commit([&]
{
FLinkerInstancingContext Context;
FLoadPackageAsyncOptionalParams Params;
Params.InstancingContext = &Context;
FString Name(FString::Printf(TEXT("/AutoRTFMTestPackage%d"), __LINE__));
RequestId = LoadPackageAsync(Name, MoveTemp(Params));
});
FlushAsyncLoading(RequestId);
}
SECTION("Trashed Package")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
TrashPackage(Package);
AutoRTFM::Testing::Commit([&]
{
UPackage* const ReloadedPackage = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(ReloadedPackage);
REQUIRE(ReloadedPackage->GetFName() == Name);
REQUIRE(Package != ReloadedPackage);
});
}
SECTION("Find Package Loaded In Transaction")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
AutoRTFM::Testing::Commit([&]
{
// Make sure the package doesn't exist.
REQUIRE(FindObject<UObject>(nullptr, *Name) == nullptr);
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
TArray<UObject*> Objects;
REQUIRE(StaticFindAllObjects(Objects, UObject::StaticClass(), *Name));
REQUIRE(Objects.Num() == 1);
REQUIRE(Objects[0] == Package);
});
}
SECTION("Trash Package that was created in same transaction as reloaded")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
AutoRTFM::Testing::Commit([&]
{
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
TrashPackage(Package);
UPackage* const ReloadedPackage = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(ReloadedPackage);
REQUIRE(ReloadedPackage->GetFName() == Name);
REQUIRE(Package != ReloadedPackage);
});
}
SECTION("Trash Package that was found in the same transaction")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
AutoRTFM::Testing::Commit([&]
{
UPackage* const FoundPackage = FindObject<UPackage>(nullptr, *Name);
REQUIRE(Package == FoundPackage);
TrashPackage(Package);
UPackage* const ReloadedPackage = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(ReloadedPackage);
REQUIRE(ReloadedPackage->GetFName() == Name);
REQUIRE(Package != ReloadedPackage);
});
UPackage* const FoundPackage = FindObject<UPackage>(nullptr, *Name);
REQUIRE(Package != FoundPackage);
}
SECTION("Multiple retries to load multiple packages")
{
FString Name1(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _1(Name1);
FString Name2(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _2(Name2);
FString Name3(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _3(Name3);
FString Name4(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _4(Name4);
TArray<FString> PackagesToLoad({Name1, Name2, Name3, Name4});
AutoRTFM::Testing::Commit([&]
{
for (const FString& Name : PackagesToLoad)
{
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
}
});
}
SECTION("Multiple retries to load multiple packages with trashing")
{
FString Name1(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _1(Name1);
FString Name2(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _2(Name2);
FString Name3(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _3(Name3);
FString Name4(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _4(Name4);
TArray<FString> PackagesToLoad({Name1, Name2, Name3, Name4});
AutoRTFM::Testing::Commit([&]
{
for (const FString& Name : PackagesToLoad)
{
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
TrashPackage(Package);
UPackage* const ReloadedPackage = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(ReloadedPackage);
REQUIRE(ReloadedPackage->GetFName() == Name);
REQUIRE(Package != ReloadedPackage);
}
});
}
SECTION("Multiple async loads")
{
FString Name1(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _1(Name1);
FString Name2(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _2(Name2);
AutoRTFM::Testing::Commit([&]
{
REQUIRE(FindObject<UPackage>(nullptr, *Name1) == nullptr);
REQUIRE(FindObject<UPackage>(nullptr, *Name2) == nullptr);
FLoadPackageAsyncDelegate Delegate;
const int32 Id1 = LoadPackageAsync(Name1, Delegate);
const int32 Id2 = LoadPackageAsync(Name2, Delegate);
FlushAsyncLoading(Id2);
REQUIRE(FindObject<UPackage>(nullptr, *Name2) != nullptr);
});
}
SECTION("Load With Custom Name")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
AutoRTFM::Testing::Commit([&]
{
FName CustomName("Wowwee");
FLoadPackageAsyncDelegate Delegate;
Delegate.BindLambda([&](const FName& Name, UPackage* const Package, EAsyncLoadingResult::Type Result)
{
REQUIRE(EAsyncLoadingResult::Succeeded == Result);
REQUIRE(Package->GetFName() == Name);
REQUIRE(CustomName == Name);
});
FlushAsyncLoading(LoadPackageAsync(FPackagePath::FromPackageNameUnchecked(*Name), CustomName, Delegate));
});
}
SECTION("Trash And Load With Custom Name")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
bool bHit = false;
UPackage* const Package = LoadPackage(nullptr, *Name, LOAD_None);
REQUIRE(Package);
AutoRTFM::Testing::Commit([&]
{
TrashPackage(Package);
FName CustomName("Wowwee");
FLoadPackageAsyncDelegate Delegate;
Delegate.BindLambda([&](const FName& Name, UPackage* const Package, EAsyncLoadingResult::Type Result)
{
REQUIRE(AutoRTFM::IsClosed());
REQUIRE(EAsyncLoadingResult::Succeeded == Result);
REQUIRE(Package->GetFName() == Name);
REQUIRE(CustomName == Name);
bHit = true;
});
FlushAsyncLoading(LoadPackageAsync(FPackagePath::FromPackageNameUnchecked(*Name), CustomName, Delegate));
});
REQUIRE(bHit);
}
SECTION("First Time Load Package, Second Time Don't")
{
FString Name(FString::Printf(TEXT("/Game/%dAutoRTFMTestPackage%d"), FPlatformProcess::GetCurrentProcessId(), __LINE__));
FPackageScopedMaker _(Name);
bool bHit = false;
bool bFirst = true;
FName CustomName("Wowwee");
FLoadPackageAsyncDelegate Delegate;
Delegate.BindLambda([&](const FName& Name, UPackage* const Package, EAsyncLoadingResult::Type Result)
{
REQUIRE(!AutoRTFM::IsTransactional());
REQUIRE(EAsyncLoadingResult::Succeeded == Result);
REQUIRE(Package->GetFName() == Name);
REQUIRE(CustomName == Name);
bHit = true;
});
AutoRTFM::Testing::Commit([&]
{
if (!bFirst)
{
return;
}
AutoRTFM::OnComplete([&] { bFirst = false; });
FlushAsyncLoading(LoadPackageAsync(FPackagePath::FromPackageNameUnchecked(*Name), CustomName, Delegate));
});
FlushAsyncLoading(LoadPackageAsync(FPackagePath::FromPackageNameUnchecked(*Name), CustomName, Delegate));
REQUIRE(bHit);
}
}