1111 lines
27 KiB
C++
1111 lines
27 KiB
C++
#include "Testing/MemoryTesting.h"
|
|
|
|
#include "Memory/Memory.h"
|
|
#include "Memory/Alignment.h"
|
|
#include "Memory/PointerTraits.h"
|
|
#include "Memory/UniquePointer.h"
|
|
#include "Memory/SharedPointer.h"
|
|
#include "Memory/MemoryOperator.h"
|
|
#include "Memory/ObserverPointer.h"
|
|
#include "Memory/InOutPointer.h"
|
|
#include "Miscellaneous/AssertionMacros.h"
|
|
|
|
NAMESPACE_REDCRAFT_BEGIN
|
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
|
NAMESPACE_MODULE_BEGIN(Utility)
|
|
|
|
NAMESPACE_BEGIN(Testing)
|
|
|
|
void TestMemory()
|
|
{
|
|
TestAlignment();
|
|
TestMemoryBuffer();
|
|
TestMemoryMalloc();
|
|
TestMemoryOperator();
|
|
TestPointerTraits();
|
|
TestUniquePointer();
|
|
TestSharedPointer();
|
|
TestObserverPointer();
|
|
TestInOutPointer();
|
|
}
|
|
|
|
void TestAlignment()
|
|
{
|
|
int32 Unaligned = 0xAAAA;
|
|
|
|
int32 Aligned8 = Memory::Align(Unaligned, 8);
|
|
int32 Aligned16 = Memory::Align(Unaligned, 16);
|
|
int32 Aligned32 = Memory::Align(Unaligned, 32);
|
|
int32 Aligned64 = Memory::Align(Unaligned, 64);
|
|
|
|
int32 AlignedDown8 = Memory::AlignDown(Unaligned, 8);
|
|
int32 AlignedDown16 = Memory::AlignDown(Unaligned, 16);
|
|
int32 AlignedDown32 = Memory::AlignDown(Unaligned, 32);
|
|
int32 AlignedDown64 = Memory::AlignDown(Unaligned, 64);
|
|
|
|
int32 AlignedArbitrary8 = Memory::AlignArbitrary(Unaligned, 8);
|
|
int32 AlignedArbitrary16 = Memory::AlignArbitrary(Unaligned, 16);
|
|
int32 AlignedArbitrary32 = Memory::AlignArbitrary(Unaligned, 32);
|
|
int32 AlignedArbitrary64 = Memory::AlignArbitrary(Unaligned, 64);
|
|
|
|
always_check((Memory::IsAligned(Aligned8, 8) && Aligned8 > Unaligned));
|
|
always_check((Memory::IsAligned(Aligned16, 16) && Aligned16 > Unaligned));
|
|
always_check((Memory::IsAligned(Aligned32, 32) && Aligned32 > Unaligned));
|
|
always_check((Memory::IsAligned(Aligned64, 64) && Aligned64 > Unaligned));
|
|
|
|
always_check((Memory::IsAligned(Aligned8, 8) && AlignedDown8 < Unaligned));
|
|
always_check((Memory::IsAligned(Aligned16, 16) && AlignedDown16 < Unaligned));
|
|
always_check((Memory::IsAligned(Aligned32, 32) && AlignedDown32 < Unaligned));
|
|
always_check((Memory::IsAligned(Aligned64, 64) && AlignedDown64 < Unaligned));
|
|
|
|
always_check((Memory::IsAligned(AlignedArbitrary8, 8)));
|
|
always_check((Memory::IsAligned(AlignedArbitrary16, 16)));
|
|
always_check((Memory::IsAligned(AlignedArbitrary32, 32)));
|
|
always_check((Memory::IsAligned(AlignedArbitrary64, 64)));
|
|
|
|
}
|
|
|
|
void TestMemoryBuffer()
|
|
{
|
|
int64 TempA;
|
|
int64 TempB;
|
|
int64 TempC;
|
|
int64 TempD;
|
|
uint8* PtrA = reinterpret_cast<uint8*>(&TempA);
|
|
uint8* PtrB = reinterpret_cast<uint8*>(&TempB);
|
|
uint8* PtrC = reinterpret_cast<uint8*>(&TempC);
|
|
uint8* PtrD = reinterpret_cast<uint8*>(&TempD);
|
|
|
|
TempA = 0x0123456789ABCDEF;
|
|
TempB = 0x0123456789AB0000;
|
|
Memory::Memmove(PtrA, PtrA + 2, 6);
|
|
always_check((TempA << 16) == TempB);
|
|
|
|
TempA = 0x0123456789ABCDEF;
|
|
Memory::Memmove(TempB, TempA);
|
|
always_check(TempB == TempA);
|
|
|
|
TempA = 1004;
|
|
TempB = 1005;
|
|
TempC = 1005;
|
|
TempD = 1006;
|
|
int32 ResultA = Memory::Memcmp(PtrA, PtrB, sizeof(int64));
|
|
int32 ResultB = Memory::Memcmp(PtrB, PtrC, sizeof(int64));
|
|
int32 ResultC = Memory::Memcmp(PtrC, PtrD, sizeof(int64));
|
|
always_check((ResultA < 0) == (ResultC < 0));
|
|
always_check(ResultB == 0);
|
|
int32 ResultD = Memory::Memcmp(TempA, TempB);
|
|
int32 ResultE = Memory::Memcmp(TempB, TempC);
|
|
int32 ResultF = Memory::Memcmp(TempC, TempD);
|
|
always_check((ResultD < 0) == (ResultF < 0));
|
|
always_check(ResultE == 0);
|
|
|
|
Memory::Memset(PtrA, 0x3F, sizeof(int64));
|
|
always_check(TempA == 0x3F3F3F3F3F3F3F3F);
|
|
Memory::Memset(TempB, 0x3F);
|
|
always_check(TempB == 0x3F3F3F3F3F3F3F3F);
|
|
|
|
Memory::Memzero(PtrA, sizeof(int64));
|
|
always_check(TempA == 0);
|
|
Memory::Memzero(TempB);
|
|
always_check(TempB == 0);
|
|
|
|
TempA = 0x0123456789ABCDEF;
|
|
Memory::Memcpy(PtrC, PtrA, sizeof(int64));
|
|
always_check(TempA == TempC);
|
|
TempB = 0xDEDCBA9876543210;
|
|
Memory::Memcpy(TempD, TempB);
|
|
always_check(TempB == TempD);
|
|
|
|
}
|
|
|
|
void TestMemoryMalloc()
|
|
{
|
|
int32* PtrA;
|
|
int64* PtrB;
|
|
|
|
PtrA = reinterpret_cast<int32*>(Memory::SystemMalloc(sizeof(int32)));
|
|
*PtrA = 0x01234567;
|
|
always_check(*PtrA == 0x01234567);
|
|
PtrB = reinterpret_cast<int64*>(Memory::SystemRealloc(PtrA, sizeof(int64)));
|
|
*PtrB = 0x0123456789ABCDEF;
|
|
always_check(*PtrB == 0x0123456789ABCDEF);
|
|
Memory::SystemFree(PtrB);
|
|
|
|
PtrA = reinterpret_cast<int32*>(Memory::Malloc(sizeof(int32), 1024));
|
|
always_check(Memory::IsAligned(PtrA, 1024));
|
|
*PtrA = 0x01234567;
|
|
always_check(*PtrA == 0x01234567);
|
|
PtrB = reinterpret_cast<int64*>(Memory::Realloc(PtrA, sizeof(int64), 1024));
|
|
always_check(Memory::IsAligned(PtrB, 1024));
|
|
*PtrB = 0x0123456789ABCDEF;
|
|
always_check(*PtrB == 0x0123456789ABCDEF);
|
|
Memory::Free(PtrB);
|
|
|
|
PtrA = new int32;
|
|
PtrB = new int64;
|
|
*PtrA = 0x01234567;
|
|
always_check(*PtrA == 0x01234567);
|
|
*PtrB = 0x0123456789ABCDEF;
|
|
always_check(*PtrB == 0x0123456789ABCDEF);
|
|
delete PtrA;
|
|
delete PtrB;
|
|
|
|
struct alignas(1024) FTest { int32 A; };
|
|
FTest* PtrC = new FTest[4];
|
|
always_check(Memory::IsAligned(PtrC, 1024));
|
|
PtrC->A = 0x01234567;
|
|
always_check(PtrC->A == 0x01234567);
|
|
delete [] PtrC;
|
|
|
|
Memory::Free(Memory::Realloc(Memory::Malloc(0), 0));
|
|
}
|
|
|
|
NAMESPACE_UNNAMED_BEGIN
|
|
|
|
struct FTracker
|
|
{
|
|
static int32 Status;
|
|
FTracker() { always_check(Status == 0); Status = -1; }
|
|
FTracker(const FTracker&) { always_check(Status == 1); Status = -1; }
|
|
FTracker(FTracker&&) { always_check(Status == 2); Status = -1; }
|
|
~FTracker() { always_check(Status == 3); Status = -1; }
|
|
FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; }
|
|
FTracker& operator=(FTracker&&) { always_check(Status == 5); Status = -1; return *this; }
|
|
};
|
|
|
|
int32 FTracker::Status = -1;
|
|
|
|
NAMESPACE_UNNAMED_END
|
|
|
|
void TestMemoryOperator()
|
|
{
|
|
|
|
FTracker* PtrA = reinterpret_cast<FTracker*>(Memory::Malloc(sizeof(FTracker)));
|
|
FTracker* PtrB = reinterpret_cast<FTracker*>(Memory::Malloc(sizeof(FTracker)));
|
|
|
|
FTracker::Status = 0;
|
|
Memory::DefaultConstruct<FTracker>(PtrA);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 1;
|
|
Memory::Construct<FTracker>(PtrA, PtrB);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 1;
|
|
Memory::CopyConstruct(PtrA, PtrB);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 2;
|
|
Memory::MoveConstruct(PtrA, PtrB);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 3;
|
|
Memory::Destruct(PtrA);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 4;
|
|
Memory::CopyAssign(PtrA, PtrB);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
FTracker::Status = 5;
|
|
Memory::MoveAssign(PtrA, PtrB);
|
|
always_check(FTracker::Status == -1);
|
|
|
|
Memory::Free(PtrA);
|
|
Memory::Free(PtrB);
|
|
}
|
|
|
|
void TestPointerTraits()
|
|
{
|
|
always_check(!TPointerTraits<int64>::bIsPointer);
|
|
|
|
always_check(TPointerTraits<int64*>::bIsPointer);
|
|
always_check((CSameAs<TPointerTraits<int64*>::PointerType, int64*>));
|
|
always_check((CSameAs<TPointerTraits<int64*>::ElementType, int64>));
|
|
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
|
|
|
always_check(TPointerTraits<int64(*)[]>::bIsPointer);
|
|
always_check((CSameAs<TPointerTraits<int64(*)[]>::PointerType, int64(*)[]>));
|
|
always_check((CSameAs<TPointerTraits<int64(*)[]>::ElementType, int64>));
|
|
always_check(TPointerTraits<int64*>::ToAddress(nullptr) == nullptr);
|
|
|
|
always_check(TPointerTraits<TSharedPtr<int64>>::bIsPointer);
|
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::PointerType, TSharedPtr<int64>>));
|
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64>>::ElementType, int64>));
|
|
always_check(TPointerTraits<TSharedPtr<int64>>::ToAddress(nullptr) == nullptr);
|
|
|
|
always_check(TPointerTraits<TSharedPtr<int64[]>>::bIsPointer);
|
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::PointerType, TSharedPtr<int64[]>>));
|
|
always_check((CSameAs<TPointerTraits<TSharedPtr<int64[]>>::ElementType, int64>));
|
|
always_check(TPointerTraits<TSharedPtr<int64[]>>::ToAddress(nullptr) == nullptr);
|
|
|
|
}
|
|
|
|
NAMESPACE_UNNAMED_BEGIN
|
|
|
|
struct FCounter
|
|
{
|
|
static int32 Num;
|
|
FCounter() { ++Num; }
|
|
~FCounter() { --Num; }
|
|
};
|
|
|
|
int32 FCounter::Num = 0;
|
|
|
|
struct FDeleter
|
|
{
|
|
static int32 Num;
|
|
void operator()(FCounter* Ptr) { delete Ptr; ++Num; }
|
|
};
|
|
|
|
int32 FDeleter::Num = 0;
|
|
|
|
struct FArrayDeleter
|
|
{
|
|
static int32 Num;
|
|
void operator()(FCounter* Ptr) { delete [] Ptr; ++Num; }
|
|
};
|
|
|
|
int32 FArrayDeleter::Num = 0;
|
|
|
|
NAMESPACE_UNNAMED_END
|
|
|
|
void TestUniquePointer()
|
|
{
|
|
{
|
|
TUniqueRef<int32> Temp = MakeUnique<int32>();
|
|
*Temp = 15;
|
|
always_check(*Temp.Get() = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter;
|
|
FCounter* PtrB = new FCounter;
|
|
FCounter* PtrC = new FCounter;
|
|
|
|
TUniqueRef<FCounter> TempA(PtrA);
|
|
TUniqueRef<FCounter, FDeleter> TempB(PtrB);
|
|
TUniqueRef<FCounter, FDeleter> TempC(PtrC, FDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter);
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrX = TempB.ReleaseAndReset(new FCounter);
|
|
always_check(FCounter::Num == TempNum + 1);
|
|
delete PtrX;
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrY = TempB.ReleaseAndReset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum + 1);
|
|
delete PtrY;
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempC.GetDeleter().Num == 2);
|
|
}
|
|
|
|
always_check(FCounter::Num == 0);
|
|
always_check(FDeleter::Num == 4);
|
|
|
|
{
|
|
TUniqueRef<int32[]> Temp = MakeUnique<int32[]>(4);
|
|
Temp[0] = 15;
|
|
always_check(Temp.Get()[0] = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FArrayDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter[4];
|
|
FCounter* PtrB = new FCounter[4];
|
|
FCounter* PtrC = new FCounter[4];
|
|
|
|
TUniqueRef<FCounter[]> TempA(PtrA);
|
|
TUniqueRef<FCounter[], FArrayDeleter> TempB(PtrB);
|
|
TUniqueRef<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4]);
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrX = TempB.ReleaseAndReset(new FCounter[4]);
|
|
always_check(FCounter::Num == TempNum + 4);
|
|
delete [] PtrX;
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrY = TempB.ReleaseAndReset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum + 4);
|
|
delete [] PtrY;
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempC.GetDeleter().Num == 2);
|
|
}
|
|
|
|
always_check( FCounter::Num == 0);
|
|
always_check(FArrayDeleter::Num == 4);
|
|
|
|
{
|
|
TUniquePtr<int32> Temp = MakeUnique<int32>();
|
|
*Temp = 15;
|
|
always_check(*Temp.Get() = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter;
|
|
FCounter* PtrB = new FCounter;
|
|
FCounter* PtrC = new FCounter;
|
|
|
|
TUniquePtr<FCounter> TempA(PtrA);
|
|
TUniquePtr<FCounter, FDeleter> TempB(PtrB);
|
|
TUniquePtr<FCounter, FDeleter> TempC(PtrC, FDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter);
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrX = TempB.ReleaseAndReset(new FCounter);
|
|
always_check(FCounter::Num == TempNum + 1);
|
|
delete PtrX;
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrY = TempB.ReleaseAndReset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum + 1);
|
|
delete PtrY;
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempC.GetDeleter().Num == 2);
|
|
|
|
TUniquePtr<FCounter, FDeleter> TempD(MoveTemp(TempB));
|
|
|
|
TUniquePtr<FCounter, FDeleter> TempE;
|
|
TempE = MoveTemp(TempC);
|
|
TempE = nullptr;
|
|
|
|
TempB.Reset(new FCounter);
|
|
always_check(!!TempB);
|
|
always_check(TempB.IsValid());
|
|
delete TempB.Release();
|
|
|
|
}
|
|
|
|
always_check(FCounter::Num == 0);
|
|
always_check(FDeleter::Num == 4);
|
|
|
|
{
|
|
TUniquePtr<int32[]> Temp = MakeUnique<int32[]>(4);
|
|
Temp[0] = 15;
|
|
always_check(Temp.Get()[0] = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FArrayDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter[4];
|
|
FCounter* PtrB = new FCounter[4];
|
|
FCounter* PtrC = new FCounter[4];
|
|
|
|
TUniquePtr<FCounter[]> TempA(PtrA);
|
|
TUniquePtr<FCounter[], FArrayDeleter> TempB(PtrB);
|
|
TUniquePtr<FCounter[], FArrayDeleter> TempC(PtrC, FArrayDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4]);
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrX = TempB.ReleaseAndReset(new FCounter[4]);
|
|
always_check(FCounter::Num == TempNum + 4);
|
|
delete [] PtrX;
|
|
|
|
TempNum = FCounter::Num;
|
|
FCounter* PtrY = TempB.ReleaseAndReset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum + 4);
|
|
delete [] PtrY;
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempC.GetDeleter().Num == 2);
|
|
|
|
TUniquePtr<FCounter[], FArrayDeleter> TempD(MoveTemp(TempB));
|
|
|
|
TUniquePtr<FCounter[], FArrayDeleter> TempE;
|
|
TempE = MoveTemp(TempC);
|
|
TempE = nullptr;
|
|
|
|
TempB.Reset(new FCounter[4]);
|
|
always_check(!!TempB);
|
|
always_check(TempB.IsValid());
|
|
delete [] TempB.Release();
|
|
|
|
}
|
|
|
|
always_check( FCounter::Num == 0);
|
|
always_check(FArrayDeleter::Num == 4);
|
|
|
|
{
|
|
TUniquePtr<int32> TempA;
|
|
TUniquePtr<const int32> TempB = MoveTemp(TempA);
|
|
TUniquePtr<const int32> TempC;
|
|
TempC = MoveTemp(TempA);
|
|
}
|
|
|
|
{
|
|
TUniquePtr<int32[]> TempA;
|
|
TUniquePtr<const int32[]> TempB = MoveTemp(TempA);
|
|
TUniquePtr<const int32[]> TempC;
|
|
TempC = MoveTemp(TempA);
|
|
}
|
|
|
|
}
|
|
|
|
void TestSharedPointer()
|
|
{
|
|
|
|
FCounter::Num = 0;
|
|
FDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter;
|
|
FCounter* PtrB = new FCounter;
|
|
FCounter* PtrC = new FCounter;
|
|
|
|
TSharedRef<FCounter> TempA(PtrA);
|
|
TSharedRef<FCounter> TempB(PtrB, FDeleter());
|
|
TSharedRef<FCounter> TempC(PtrC, FDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempC.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempA.GetDeleter<FDeleter>() == nullptr);
|
|
always_check(TempC.GetDeleter<FDeleter>() != nullptr);
|
|
always_check(TempC.GetDeleter<FDeleter>()->Num == 2);
|
|
|
|
TSharedRef<FCounter> TempD(MoveTemp(TempB));
|
|
}
|
|
|
|
always_check(FCounter::Num == 0);
|
|
always_check(FDeleter::Num == 4);
|
|
|
|
{
|
|
TSharedRef<int32[]> Temp = MakeShared<int32[]>(4);
|
|
Temp[0] = 15;
|
|
always_check(Temp.Get()[0] = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FArrayDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter[4];
|
|
FCounter* PtrB = new FCounter[4];
|
|
FCounter* PtrC = new FCounter[4];
|
|
|
|
TSharedRef<FCounter[]> TempA(PtrA);
|
|
TSharedRef<FCounter[]> TempB(PtrB, FArrayDeleter());
|
|
TSharedRef<FCounter[]> TempC(PtrC, FArrayDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempA.GetDeleter<FArrayDeleter>() == nullptr);
|
|
always_check(TempC.GetDeleter<FArrayDeleter>() != nullptr);
|
|
always_check(TempC.GetDeleter<FArrayDeleter>()->Num == 2);
|
|
|
|
TSharedRef<FCounter[]> TempD(MoveTemp(TempB));
|
|
}
|
|
|
|
always_check( FCounter::Num == 0);
|
|
always_check(FArrayDeleter::Num == 4);
|
|
|
|
FCounter::Num = 0;
|
|
FDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter;
|
|
FCounter* PtrB = new FCounter;
|
|
FCounter* PtrC = new FCounter;
|
|
|
|
TSharedPtr<FCounter> TempA(PtrA);
|
|
TSharedPtr<FCounter> TempB(PtrB, FDeleter());
|
|
TSharedPtr<FCounter> TempC(PtrC, FDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempA.GetDeleter<FDeleter>() == nullptr);
|
|
always_check(TempC.GetDeleter<FDeleter>() != nullptr);
|
|
always_check(TempC.GetDeleter<FDeleter>()->Num == 2);
|
|
|
|
TSharedPtr<FCounter> TempD(MoveTemp(TempB));
|
|
|
|
TSharedPtr<FCounter> TempE;
|
|
TempE = MoveTemp(TempC);
|
|
TempE = nullptr;
|
|
|
|
TempB.Reset(new FCounter, FDeleter());
|
|
always_check(!!TempB);
|
|
always_check(TempB.IsValid());
|
|
|
|
}
|
|
|
|
always_check(FCounter::Num == 0);
|
|
always_check(FDeleter::Num == 5);
|
|
|
|
{
|
|
TSharedPtr<int32[]> Temp = MakeShared<int32[]>(4);
|
|
Temp[0] = 15;
|
|
always_check(Temp.Get()[0] = 15);
|
|
}
|
|
|
|
FCounter::Num = 0;
|
|
FArrayDeleter::Num = 0;
|
|
|
|
{
|
|
FCounter* PtrA = new FCounter[4];
|
|
FCounter* PtrB = new FCounter[4];
|
|
FCounter* PtrC = new FCounter[4];
|
|
|
|
TSharedPtr<FCounter[]> TempA(PtrA);
|
|
TSharedPtr<FCounter[]> TempB(PtrB, FArrayDeleter());
|
|
TSharedPtr<FCounter[]> TempC(PtrC, FArrayDeleter());
|
|
|
|
always_check(TempA != nullptr);
|
|
always_check(TempC != TempB);
|
|
always_check((TempA <=> nullptr) == strong_ordering::greater);
|
|
always_check((TempC <=> TempB) != strong_ordering::equal);
|
|
|
|
int32 TempNum;
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
TempNum = FCounter::Num;
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(FCounter::Num == TempNum);
|
|
|
|
always_check(GetTypeHash(TempB) == GetTypeHash(TempB.Get()));
|
|
|
|
Swap(TempB, TempC);
|
|
|
|
always_check(TempA.GetDeleter<FArrayDeleter>() == nullptr);
|
|
always_check(TempC.GetDeleter<FArrayDeleter>() != nullptr);
|
|
always_check(TempC.GetDeleter<FArrayDeleter>()->Num == 2);
|
|
|
|
TSharedPtr<FCounter[]> TempD(MoveTemp(TempB));
|
|
|
|
TSharedPtr<FCounter[]> TempE;
|
|
TempE = MoveTemp(TempC);
|
|
TempE = nullptr;
|
|
|
|
TempB.Reset(new FCounter[4], FArrayDeleter());
|
|
always_check(!!TempB);
|
|
always_check(TempB.IsValid());
|
|
|
|
}
|
|
|
|
always_check( FCounter::Num == 0);
|
|
always_check(FArrayDeleter::Num == 5);
|
|
|
|
{
|
|
TSharedPtr<bool> Temp;
|
|
always_check(!Temp.IsValid());
|
|
if (Temp.Get() == nullptr) { }
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> Temp(new int32(123));
|
|
|
|
always_check(Temp.IsValid());
|
|
always_check(Temp.IsUnique());
|
|
|
|
const int32 DeferenceTest = *Temp;
|
|
|
|
Temp.Reset();
|
|
|
|
always_check(Temp.GetSharedReferenceCount() == 0);
|
|
}
|
|
|
|
{
|
|
TSharedPtr<bool> TempA(new bool(false));
|
|
TSharedPtr<bool> TempB(TempA);
|
|
}
|
|
|
|
{
|
|
TSharedPtr<bool> TempA(new bool(false));
|
|
TSharedPtr<bool> TempB;
|
|
TempB = TempA;
|
|
}
|
|
|
|
{
|
|
struct FSharedTest { bool bTest; };
|
|
|
|
TSharedPtr<FSharedTest> TempA(new FSharedTest());
|
|
|
|
TempA->bTest = true;
|
|
|
|
(*TempA).bTest = false;
|
|
|
|
TSharedPtr<FSharedTest> TempB(TempA);
|
|
|
|
TempA.Reset();
|
|
}
|
|
|
|
{
|
|
class FBase { bool bTest; };
|
|
|
|
class FDerived : public FBase { };
|
|
|
|
{
|
|
TSharedPtr<FBase> TempA(new FDerived());
|
|
TSharedPtr<FDerived> TempB(StaticCast<FDerived>(TempA));
|
|
}
|
|
|
|
{
|
|
TSharedPtr<FDerived> TempA(new FDerived());
|
|
TSharedPtr<FBase> TempB(TempA);
|
|
}
|
|
|
|
{
|
|
TSharedPtr<FDerived> TempA(new FDerived());
|
|
TSharedPtr<FBase> TempB;
|
|
TempB = TempA;
|
|
}
|
|
}
|
|
|
|
{
|
|
bool* Ptr = nullptr;
|
|
TSharedPtr<bool> Temp(Ptr);
|
|
always_check(!Temp.IsValid());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<bool> Temp(new bool(true));
|
|
always_check(Temp.IsValid());
|
|
}
|
|
|
|
{
|
|
TWeakPtr<bool> Temp;
|
|
always_check(!Temp.Lock().IsValid());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempShared(new int32(64));
|
|
TWeakPtr<int32> TempWeak(TempShared);
|
|
always_check(TempWeak.Lock().IsValid());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempShared(new int32(64));
|
|
TWeakPtr<int32> TempWeak;
|
|
TempWeak = TempShared;
|
|
|
|
always_check(TempWeak.Lock().IsValid());
|
|
|
|
TempWeak.Reset();
|
|
always_check(!TempWeak.Lock().IsValid());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempShared(new int32(64));
|
|
TWeakPtr<int32> TempWeak = TempShared;
|
|
TempShared.Reset();
|
|
always_check(!TempWeak.Lock().IsValid());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempA(new int32(64));
|
|
TSharedPtr<int32> TempB(new int32(21));
|
|
TSharedPtr<int32> TempC(TempB);
|
|
|
|
always_check(!(TempA == TempB));
|
|
always_check(TempA != TempB);
|
|
always_check(TempB == TempC);
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempA(new int32(64));
|
|
TSharedPtr<int32> TempB(new int32(21));
|
|
|
|
TWeakPtr<int32> WeakA(TempA);
|
|
TWeakPtr<int32> WeakB(TempB);
|
|
TWeakPtr<int32> WeakC(TempB);
|
|
|
|
always_check(!(WeakA.Lock() == WeakB.Lock()));
|
|
always_check(WeakA.Lock() != WeakB.Lock());
|
|
always_check(WeakB.Lock() == WeakC.Lock());
|
|
}
|
|
|
|
{
|
|
TSharedPtr<const int32> TempA(new int32(10));
|
|
TSharedPtr<const float32> TempB(new float32(1.0f));
|
|
TSharedPtr<const float32> TempC(new float32(2.0f));
|
|
|
|
if (TempB == TempC) { }
|
|
|
|
TempB = TempC;
|
|
|
|
TSharedPtr<float32> TempD(new float32(123.0f));
|
|
|
|
TempB = TempD;
|
|
|
|
TWeakPtr<const float32> TempE = TempB;
|
|
TWeakPtr<float32> TempF;
|
|
|
|
TempF = ConstCast<float32>(TempC);
|
|
*TempF.Lock() = 20.0f;
|
|
}
|
|
|
|
{
|
|
TSharedPtr<struct FTest> Temp;
|
|
struct FTest { int32 Value; };
|
|
Temp = TSharedPtr<FTest>(new FTest());
|
|
Temp->Value = 20;
|
|
}
|
|
|
|
{
|
|
TSharedPtr<bool> TempA(nullptr);
|
|
TSharedPtr<float32> TempB = nullptr;
|
|
|
|
TWeakPtr<bool> TempD(nullptr);
|
|
TWeakPtr<float32> TempE = nullptr;
|
|
|
|
TempB = TSharedPtr<float32>(new float32(0.1f));
|
|
TempB = nullptr;
|
|
|
|
TempB = MakeShared<float32>(30.0f);
|
|
TSharedPtr<float64> TempC(MakeShared<float64>(2.0));
|
|
|
|
struct FTest
|
|
{
|
|
TSharedPtr<float32> Value;
|
|
|
|
TSharedPtr<float32> FuncA() { return Value; }
|
|
|
|
TSharedPtr<float32> FuncB() { return MakeShared<float32>(123.0f); }
|
|
};
|
|
}
|
|
|
|
{
|
|
TSharedRef<float32> Temp(new float32(123.0f));
|
|
}
|
|
|
|
{
|
|
TSharedRef<float32> Temp(new float32(123.0f));
|
|
const float& RefA = *Temp;
|
|
const float& RefB = *Temp.Get();
|
|
}
|
|
|
|
{
|
|
TSharedRef<float32> Temp = MakeShared<float32>(123.0f);
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> TempA(new int32(1));
|
|
TSharedPtr<int32> TempB(TempA);
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempA(new int32(1));
|
|
TSharedRef<int32> TempB(TempA.ToSharedRef());
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> Temp(new int32(10));
|
|
Temp = TSharedRef<int32>(new int32(20));
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> TempA(new int32(99));
|
|
TWeakPtr<int32> TempB = TempA;
|
|
always_check(TempB.Lock());
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> IntRef1(new int32(99));
|
|
TSharedRef<int32> IntRef2(new int32(21));
|
|
always_check(!(IntRef1 == IntRef2));
|
|
always_check(IntRef1 != IntRef2);
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> TempA(new int32(21));
|
|
TSharedPtr<int32> TempB(TempA);
|
|
TSharedPtr<int32> TempC;
|
|
|
|
always_check(TempA == TempB && TempB == TempA);
|
|
always_check(!(TempA != TempB || TempB != TempA));
|
|
always_check(!(TempA == TempC) && (TempA != TempC));
|
|
}
|
|
|
|
{
|
|
struct FTest : public TSharedFromThis<FTest>
|
|
{
|
|
TSharedRef<FTest> FuncTest() { return AsShared(); }
|
|
};
|
|
|
|
TSharedPtr<FTest> TempA(new FTest());
|
|
|
|
{
|
|
FTest* Ptr = TempA.Get();
|
|
TSharedRef<FTest> TempB(Ptr->FuncTest());
|
|
}
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32> TempA = MakeShared<int32>();
|
|
TSharedRef<const int32> TempB = TempA;
|
|
TSharedRef<const int32> TempC = MakeShared<int32>();
|
|
TempC = TempA;
|
|
}
|
|
|
|
{
|
|
TSharedRef<int32[]> TempA = MakeShared<int32[]>(4);
|
|
TSharedRef<const int32[]> TempB = TempA;
|
|
TSharedRef<const int32[]> TempC = MakeShared<int32[]>(4);
|
|
TempC = TempA;
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32> TempA;
|
|
TSharedPtr<const int32> TempB = TempA;
|
|
TSharedPtr<const int32> TempC;
|
|
TempC = TempA;
|
|
}
|
|
|
|
{
|
|
TSharedPtr<int32[]> TempA;
|
|
TSharedPtr<const int32[]> TempB = TempA;
|
|
TSharedPtr<const int32[]> TempC;
|
|
TempC = TempA;
|
|
}
|
|
|
|
{
|
|
TWeakPtr<int32> TempA;
|
|
TWeakPtr<const int32> TempB = TempA;
|
|
TWeakPtr<const int32> TempC;
|
|
TempC = TempA;
|
|
}
|
|
|
|
{
|
|
TWeakPtr<int32[]> TempA;
|
|
TWeakPtr<const int32[]> TempB = TempA;
|
|
TWeakPtr<const int32[]> TempC;
|
|
TempC = TempA;
|
|
}
|
|
|
|
}
|
|
|
|
void TestObserverPointer()
|
|
{
|
|
{
|
|
int32 IntA;
|
|
int32 IntB;
|
|
|
|
TObserverPtr<int32> TempA;
|
|
TObserverPtr<int32> TempB = nullptr;
|
|
TObserverPtr<int32> TempC(&IntA);
|
|
TObserverPtr<int32> TempD(TempC);
|
|
|
|
TempA = TempC;
|
|
TempB = MakeObserver<int32>(&IntB);
|
|
|
|
always_check(TempA == TempC);
|
|
always_check(TempB == &IntB);
|
|
always_check(TempB.IsValid());
|
|
|
|
always_check(TempA.Release() == &IntA);
|
|
always_check(!TempA.IsValid());
|
|
|
|
TempA.Reset(&IntA);
|
|
|
|
always_check(TempA == &IntA);
|
|
|
|
always_check(GetTypeHash(TempA) == GetTypeHash(&IntA));
|
|
|
|
Swap(TempA, TempB);
|
|
|
|
always_check(TempA == &IntB);
|
|
always_check(TempB == &IntA);
|
|
}
|
|
|
|
{
|
|
int32 IntA[4];
|
|
int32 IntB[4];
|
|
|
|
TObserverPtr<int32[]> TempA;
|
|
TObserverPtr<int32[]> TempB = nullptr;
|
|
TObserverPtr<int32[]> TempC(IntA);
|
|
TObserverPtr<int32[]> TempD(TempC);
|
|
|
|
TempA = TempC;
|
|
TempB = MakeObserver<int32[]>(IntB);
|
|
|
|
always_check(TempA == TempC);
|
|
always_check(TempB == IntB);
|
|
always_check(TempB.IsValid());
|
|
|
|
always_check(TempA.Release() == IntA);
|
|
always_check(!TempA.IsValid());
|
|
|
|
TempA.Reset(IntA);
|
|
|
|
always_check(TempA == IntA);
|
|
|
|
always_check(GetTypeHash(TempA) == GetTypeHash(&IntA));
|
|
|
|
Swap(TempA, TempB);
|
|
|
|
always_check(TempA == IntB);
|
|
always_check(TempB == IntA);
|
|
}
|
|
}
|
|
|
|
void TestInOutPointer()
|
|
{
|
|
{
|
|
TUniquePtr<int64> Temp;
|
|
|
|
[](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp));
|
|
always_check(Temp.IsValid());
|
|
|
|
Temp.Reset();
|
|
|
|
[](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp, TDefaultDelete<int64>()));
|
|
always_check(Temp.IsValid());
|
|
}
|
|
|
|
{
|
|
TUniquePtr<int64> Temp = MakeUnique<int64>(2485800585);
|
|
|
|
[](int64** InPtr) { always_check(**InPtr == 2485800585); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp));
|
|
always_check(Temp.IsValid());
|
|
|
|
Temp = MakeUnique<int64>(2821859274);
|
|
|
|
[](int64** InPtr) { always_check(**InPtr == 2821859274); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp, TDefaultDelete<int64>()));
|
|
always_check(Temp.IsValid());
|
|
}
|
|
}
|
|
|
|
NAMESPACE_END(Testing)
|
|
|
|
NAMESPACE_MODULE_END(Utility)
|
|
NAMESPACE_MODULE_END(Redcraft)
|
|
NAMESPACE_REDCRAFT_END
|