#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(&TempA); uint8* PtrB = reinterpret_cast(&TempB); uint8* PtrC = reinterpret_cast(&TempC); uint8* PtrD = reinterpret_cast(&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(Memory::SystemMalloc(sizeof(int32))); *PtrA = 0x01234567; always_check(*PtrA == 0x01234567); PtrB = reinterpret_cast(Memory::SystemRealloc(PtrA, sizeof(int64))); *PtrB = 0x0123456789ABCDEF; always_check(*PtrB == 0x0123456789ABCDEF); Memory::SystemFree(PtrB); PtrA = reinterpret_cast(Memory::Malloc(sizeof(int32), 1024)); always_check(Memory::IsAligned(PtrA, 1024)); *PtrA = 0x01234567; always_check(*PtrA == 0x01234567); PtrB = reinterpret_cast(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(Memory::Malloc(sizeof(FTracker))); FTracker* PtrB = reinterpret_cast(Memory::Malloc(sizeof(FTracker))); FTracker::Status = 0; Memory::DefaultConstruct(PtrA); always_check(FTracker::Status == -1); FTracker::Status = 1; Memory::Construct(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::bIsPointer); always_check(TPointerTraits::bIsPointer); always_check((CSameAs::PointerType, int64*>)); always_check((CSameAs::ElementType, int64>)); always_check(TPointerTraits::ToAddress(nullptr) == nullptr); always_check(TPointerTraits::bIsPointer); always_check((CSameAs::PointerType, int64(*)[]>)); always_check((CSameAs::ElementType, int64>)); always_check(TPointerTraits::ToAddress(nullptr) == nullptr); always_check(TPointerTraits>::bIsPointer); always_check((CSameAs>::PointerType, TSharedPtr>)); always_check((CSameAs>::ElementType, int64>)); always_check(TPointerTraits>::ToAddress(nullptr) == nullptr); always_check(TPointerTraits>::bIsPointer); always_check((CSameAs>::PointerType, TSharedPtr>)); always_check((CSameAs>::ElementType, int64>)); always_check(TPointerTraits>::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 Temp(new 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 TempA(PtrA); TUniqueRef TempB(PtrB); TUniqueRef TempC(PtrC, FDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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 Temp(new 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 TempA(PtrA); TUniqueRef TempB(PtrB); TUniqueRef TempC(PtrC, FArrayDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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 Temp = MakeUnique(); *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 TempA(PtrA); TUniquePtr TempB(PtrB); TUniquePtr TempC(PtrC, FDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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 TempD(MoveTemp(TempB)); TUniquePtr 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 Temp = MakeUnique(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 TempA(PtrA); TUniquePtr TempB(PtrB); TUniquePtr TempC(PtrC, FArrayDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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 TempD(MoveTemp(TempB)); TUniquePtr 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 TempA; TUniquePtr TempB = MoveTemp(TempA); TUniquePtr TempC; TempC = MoveTemp(TempA); } { TUniquePtr TempA; TUniquePtr TempB = MoveTemp(TempA); TUniquePtr 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 TempA(PtrA); TSharedRef TempB(PtrB, FDeleter()); TSharedRef TempC(PtrC, FDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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() == nullptr); always_check(TempC.GetDeleter() != nullptr); always_check(TempC.GetDeleter()->Num == 2); TSharedRef TempD(MoveTemp(TempB)); } always_check(FCounter::Num == 0); always_check(FDeleter::Num == 4); { TSharedRef Temp = MakeShared(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 TempA(PtrA); TSharedRef TempB(PtrB, FArrayDeleter()); TSharedRef TempC(PtrC, FArrayDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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() == nullptr); always_check(TempC.GetDeleter() != nullptr); always_check(TempC.GetDeleter()->Num == 2); TSharedRef 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 TempA(PtrA); TSharedPtr TempB(PtrB, FDeleter()); TSharedPtr TempC(PtrC, FDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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() == nullptr); always_check(TempC.GetDeleter() != nullptr); always_check(TempC.GetDeleter()->Num == 2); TSharedPtr TempD(MoveTemp(TempB)); TSharedPtr 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 Temp = MakeShared(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 TempA(PtrA); TSharedPtr TempB(PtrB, FArrayDeleter()); TSharedPtr TempC(PtrC, FArrayDeleter()); always_check(TempA == PtrA); always_check(TempC != TempB); always_check((TempA <=> PtrA) == strong_ordering::equal); 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() == nullptr); always_check(TempC.GetDeleter() != nullptr); always_check(TempC.GetDeleter()->Num == 2); TSharedPtr TempD(MoveTemp(TempB)); TSharedPtr 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 Temp; always_check(!Temp.IsValid()); if (Temp.Get() == nullptr) { } } { TSharedPtr Temp(new int32(123)); always_check(Temp.IsValid()); always_check(Temp.IsUnique()); const int32 DeferenceTest = *Temp; Temp.Reset(); always_check(Temp.GetSharedReferenceCount() == 0); } { TSharedPtr TempA(new bool(false)); TSharedPtr TempB(TempA); } { TSharedPtr TempA(new bool(false)); TSharedPtr TempB; TempB = TempA; } { struct FSharedTest { bool bTest; }; TSharedPtr TempA(new FSharedTest()); TempA->bTest = true; (*TempA).bTest = false; TSharedPtr TempB(TempA); TempA.Reset(); } { class FBase { bool bTest; }; class FDerived : public FBase { }; { TSharedPtr TempA(new FDerived()); TSharedPtr TempB(StaticCast(TempA)); } { TSharedPtr TempA(new FDerived()); TSharedPtr TempB(TempA); } { TSharedPtr TempA(new FDerived()); TSharedPtr TempB; TempB = TempA; } } { bool* Ptr = nullptr; TSharedPtr Temp(Ptr); always_check(!Temp.IsValid()); } { TSharedPtr Temp(new bool(true)); always_check(Temp.IsValid()); } { TWeakPtr Temp; always_check(!Temp.Lock().IsValid()); } { TSharedPtr TempShared(new int32(64)); TWeakPtr TempWeak(TempShared); always_check(TempWeak.Lock().IsValid()); } { TSharedPtr TempShared(new int32(64)); TWeakPtr TempWeak; TempWeak = TempShared; always_check(TempWeak.Lock().IsValid()); TempWeak.Reset(); always_check(!TempWeak.Lock().IsValid()); } { TSharedPtr TempShared(new int32(64)); TWeakPtr TempWeak = TempShared; TempShared.Reset(); always_check(!TempWeak.Lock().IsValid()); } { TSharedPtr TempA(new int32(64)); TSharedPtr TempB(new int32(21)); TSharedPtr TempC(TempB); always_check(!(TempA == TempB)); always_check(TempA != TempB); always_check(TempB == TempC); } { TSharedPtr TempA(new int32(64)); TSharedPtr TempB(new int32(21)); TWeakPtr WeakA(TempA); TWeakPtr WeakB(TempB); TWeakPtr WeakC(TempB); always_check(!(WeakA.Lock() == WeakB.Lock())); always_check(WeakA.Lock() != WeakB.Lock()); always_check(WeakB.Lock() == WeakC.Lock()); } { TSharedPtr TempA(new int32(10)); TSharedPtr TempB(new float32(1.0f)); TSharedPtr TempC(new float32(2.0f)); if (TempB == TempC) { } TempB = TempC; TSharedPtr TempD(new float32(123.0f)); TempB = TempD; TWeakPtr TempE = TempB; TWeakPtr TempF; TempF = ConstCast(TempC); *TempF.Lock() = 20.0f; } { TSharedPtr Temp; struct FTest { int32 Value; }; Temp = TSharedPtr(new FTest()); Temp->Value = 20; } { TSharedPtr TempA(nullptr); TSharedPtr TempB = nullptr; TWeakPtr TempD(nullptr); TWeakPtr TempE = nullptr; TempB = TSharedPtr(new float32(0.1f)); TempB = nullptr; TempB = MakeShared(30.0f); TSharedPtr TempC(MakeShared(2.0)); struct FTest { TSharedPtr Value; TSharedPtr FuncA() { return Value; } TSharedPtr FuncB() { return MakeShared(123.0f); } }; } { TSharedRef Temp(new float32(123.0f)); } { TSharedRef Temp(new float32(123.0f)); const float& RefA = *Temp; const float& RefB = *Temp.Get(); } { TSharedRef Temp = MakeShared(123.0f); } { TSharedRef TempA(new int32(1)); TSharedPtr TempB(TempA); } { TSharedPtr TempA(new int32(1)); TSharedRef TempB(TempA.ToSharedRef()); } { TSharedRef Temp(new int32(10)); Temp = TSharedRef(new int32(20)); } { TSharedRef TempA(new int32(99)); TWeakPtr TempB = TempA; always_check(TempB.Lock()); } { TSharedRef IntRef1(new int32(99)); TSharedRef IntRef2(new int32(21)); always_check(!(IntRef1 == IntRef2)); always_check(IntRef1 != IntRef2); } { TSharedRef TempA(new int32(21)); TSharedPtr TempB(TempA); TSharedPtr TempC; always_check(TempA == TempB && TempB == TempA); always_check(!(TempA != TempB || TempB != TempA)); always_check(!(TempA == TempC) && (TempA != TempC)); } { struct FTest : public TSharedFromThis { TSharedRef FuncTest() { return AsShared(); } }; TSharedPtr TempA(new FTest()); { FTest* Ptr = TempA.Get(); TSharedRef TempB(Ptr->FuncTest()); } } { TSharedRef TempA = MakeShared(); TSharedRef TempB = TempA; TSharedRef TempC = MakeShared(); TempC = TempA; } { TSharedRef TempA = MakeShared(4); TSharedRef TempB = TempA; TSharedRef TempC = MakeShared(4); TempC = TempA; } { TSharedPtr TempA; TSharedPtr TempB = TempA; TSharedPtr TempC; TempC = TempA; } { TSharedPtr TempA; TSharedPtr TempB = TempA; TSharedPtr TempC; TempC = TempA; } { TWeakPtr TempA; TWeakPtr TempB = TempA; TWeakPtr TempC; TempC = TempA; } { TWeakPtr TempA; TWeakPtr TempB = TempA; TWeakPtr TempC; TempC = TempA; } } void TestObserverPointer() { { int32 IntA; int32 IntB; TObserverPtr TempA; TObserverPtr TempB = nullptr; TObserverPtr TempC(&IntA); TObserverPtr TempD(TempC); TempA = TempC; TempB = MakeObserver(&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 TempA; TObserverPtr TempB = nullptr; TObserverPtr TempC(IntA); TObserverPtr TempD(TempC); TempA = TempC; TempB = MakeObserver(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 Temp; [](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp)); always_check(Temp.IsValid()); Temp.Reset(); [](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp, TDefaultDelete())); always_check(Temp.IsValid()); } { TUniquePtr Temp = MakeUnique(2485800585); [](int64** InPtr) { always_check(**InPtr == 2485800585); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp)); always_check(Temp.IsValid()); Temp = MakeUnique(2821859274); [](int64** InPtr) { always_check(**InPtr == 2821859274); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp, TDefaultDelete())); always_check(Temp.IsValid()); } } NAMESPACE_END(Testing) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END