#include "RootedObject.h" #if WITH_DEV_AUTOMATION_TESTS template struct TIsAssignableFrom { struct TrueType {}; template static T DeclVal(); // intentionally not implemented enum { Value = TIsSame() = DeclVal(), DeclVal()), TrueType>::Value }; }; static_assert(TIsConstructible>::Value, "TRootedObject should be default constructible"); static_assert(TIsConstructible, TRootedObject&&>::Value, "TRootedObject should be move constructible"); static_assert(TIsAssignableFrom, TRootedObject&&>::Value, "TRootedObject should be move assignable"); static_assert(TIsAssignableFrom>::Value, "TRootedObject should implicitly castable to its inner type"); BEGIN_DEFINE_SPEC(TRootedObjectSpec, "Workshop.RootedObject", EAutomationTestFlags::ProductFilter | EAutomationTestFlags::ApplicationContextMask) UObject* TheInnerObject; END_DEFINE_SPEC(TRootedObjectSpec) void TRootedObjectSpec::Define() { BeforeEach([this]() { TheInnerObject = NewObject(); }); Describe("Construct", [this]() { It("Should add the rooted object to the root", [this]() { TRootedObject RootedObject(TheInnerObject); TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted()); }); It("Should move correctly", [this]() { TRootedObject RootedObject(TheInnerObject); TRootedObject OtherRootedObject; OtherRootedObject = MoveTemp(RootedObject); TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted()); TestFalse("RootedObject.IsValid()", RootedObject.IsValid()); TestTrue("OtherRootedObject.IsValid()", OtherRootedObject.IsValid()); }); }); Describe("Destruct", [this]() { It("Should remove the rooted object from the root", [this]() { { TRootedObject RootedObject(TheInnerObject); TestTrue("TheInnerObject->IsRooted()", TheInnerObject->IsRooted()); } TestFalse("TheInnerObject->IsRooted()", TheInnerObject->IsRooted()); }); }); Describe("RetrieveObject", [this]() { It("Should invalidate the rooted object", [this]() { TRootedObject RootedObject(TheInnerObject); RootedObject.RetrieveObject(); TestFalse("RootedObject.IsValid()", RootedObject.IsValid()); }); It("Should return the inner object", [this]() { TRootedObject RootedObject(TheInnerObject); UObject* RetrievedObject = RootedObject.RetrieveObject(); TestEqual("RootedObject.IsValid()", TheInnerObject, RetrievedObject); }); It("Should remove the inner object from root", [this]() { TRootedObject RootedObject(TheInnerObject); UObject* RetrievedObject = RootedObject.RetrieveObject(); TestFalse("RetrievedObject->IsRooted()", RetrievedObject->IsRooted()); }); It("Implicit Retrieve is same as explicit retrieve", [this]() { TRootedObject RootedObject(TheInnerObject); UObject* RetrievedObject = RootedObject; TestEqual("RootedObject.IsValid()", TheInnerObject, RetrievedObject); TestFalse("RetrievedObject->IsRooted()", RetrievedObject->IsRooted()); }); }); } #endif