Files
UnrealEngineUWP/Engine/Source/Runtime/CoreUObject/Tests/ObjectRefTrackingTestBase.h
nick darnell 42c12e3776 Core - Adding support for getting the PathName from a ObjectPtr without resolving the Object*.
Core - Refactoring the Object Handle event callbacks so that we can hook and unhook them with delegates/delegatehandles.
Core - Adding support for detecting loads via object handles as a new event distinct from resolution callback.
Core - Expanding the utility functions on FObjectRef so that we can resolve it in a myraid of fashions to get the path, the class path, the full path and the export path.

[REVIEW] [at]Zousar.Shaker, [at]Joe.Pribele

[CL 22063982 by nick darnell in ue5-main branch]
2022-09-16 20:26:12 -04:00

128 lines
3.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_LOW_LEVEL_TESTS
#include "TestHarness.h"
#include "CoreMinimal.h"
#include "UObject/ObjectHandle.h"
#include "Misc/ScopeLock.h"
class FObjectRefTrackingTestBase
{
public:
uint32 GetNumResolves() const { return NumResolves; }
uint32 GetNumFailedResolves() const { return NumFailedResolves; }
uint32 GetNumReads() const { return NumReads; }
struct FSnapshotObjectRefMetrics
{
public:
FSnapshotObjectRefMetrics(FObjectRefTrackingTestBase& InTest)
: Test(InTest)
, OriginalNumResolves(Test.GetNumResolves())
, OriginalNumFailedResolves(Test.GetNumFailedResolves())
, OriginalNumReads(Test.GetNumReads())
{
Test.ConditionalInstallCallbacks();
}
bool TestNumResolves(const TCHAR* What, uint32 ExpectedDelta)
{
#if UE_WITH_OBJECT_HANDLE_TRACKING
bool bValue = OriginalNumResolves + ExpectedDelta == Test.GetNumResolves();
TEST_TRUE(What, bValue);
return bValue;
#endif
return true;
}
bool TestNumFailedResolves(const TCHAR* What, uint32 ExpectedDelta)
{
#if UE_WITH_OBJECT_HANDLE_TRACKING
bool bValue = OriginalNumFailedResolves + ExpectedDelta == Test.GetNumFailedResolves();
TEST_TRUE(What, bValue);
return bValue;
#endif
return true;
}
bool TestNumReads(const TCHAR* What, uint32 ExpectedDelta, bool bAllowAdditionalReads = false)
{
#if UE_WITH_OBJECT_HANDLE_TRACKING
bool bValue = false;
if (bAllowAdditionalReads)
{
bValue = Test.GetNumReads() >= OriginalNumReads + ExpectedDelta;
TEST_TRUE(What, bValue);
}
else
{
bValue = OriginalNumReads + ExpectedDelta == Test.GetNumReads();
TEST_TRUE(What, bValue);
}
return bValue;
#endif
return true;
}
private:
FObjectRefTrackingTestBase& Test;
uint32 OriginalNumResolves;
uint32 OriginalNumFailedResolves;
uint32 OriginalNumReads;
};
private:
#if UE_WITH_OBJECT_HANDLE_TRACKING
static void OnRefResolved(const FObjectRef& ObjectRef, UPackage* Pkg, UObject* Obj)
{
NumResolves++;
if (!IsObjectRefNull(ObjectRef) && !Obj)
{
NumFailedResolves++;
}
}
static void OnRefRead(UObject* Obj)
{
NumReads++;
}
#endif
static void ConditionalInstallCallbacks()
{
static bool bCallbacksInstalled = false;
static FCriticalSection CallbackInstallationLock;
if (bCallbacksInstalled)
{
return;
}
FScopeLock ScopeLock(&CallbackInstallationLock);
if (!bCallbacksInstalled)
{
#if UE_WITH_OBJECT_HANDLE_TRACKING
ResolvedCallbackHandle = AddObjectHandleReferenceResolvedCallback(FObjectHandleReferenceResolvedDelegate::CreateStatic(OnRefResolved));
HandleReadCallbackHandle = AddObjectHandleReadCallback(FObjectHandleReadDelegate::CreateStatic(OnRefRead));
// TODO We should unhook these handles somewhere, but i don't want to refactor the test, it's not as if they were
// being unhooked before. So...
#endif
bCallbacksInstalled = true;
}
}
#if UE_WITH_OBJECT_HANDLE_TRACKING
static FDelegateHandle ResolvedCallbackHandle;
static FDelegateHandle HandleReadCallbackHandle;
#endif
static thread_local uint32 NumResolves;
static thread_local uint32 NumFailedResolves;
static thread_local uint32 NumReads;
};
#endif