#include "include/cppgc/prefinalizer.h"
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/persistent.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/heap.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cppgc {
namespace internal {
namespace {
class PrefinalizerTest : public testing::TestWithHeap { … };
class GCed : public GarbageCollected<GCed> { … };
size_t GCed::prefinalizer_callcount = …;
}
TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadObject) { … }
TEST_F(PrefinalizerTest, PrefinalizerNotCalledOnLiveObject) { … }
namespace {
class Mixin : public GarbageCollectedMixin { … };
size_t Mixin::prefinalizer_callcount = …;
class GCedWithMixin : public GarbageCollected<GCedWithMixin>, public Mixin { … };
}
TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadMixinObject) { … }
TEST_F(PrefinalizerTest, PrefinalizerNotCalledOnLiveMixinObject) { … }
namespace {
class BaseMixin : public GarbageCollectedMixin { … };
size_t BaseMixin::prefinalizer_callcount = …;
class InheritingMixin : public BaseMixin { … };
size_t InheritingMixin::prefinalizer_callcount = …;
class GCedWithMixins : public GarbageCollected<GCedWithMixins>,
public InheritingMixin { … };
size_t GCedWithMixins::prefinalizer_callcount = …;
void BaseMixin::PreFinalizer() { … }
void InheritingMixin::PreFinalizer() { … }
void GCedWithMixins::PreFinalizer() { … }
}
TEST_F(PrefinalizerTest, PrefinalizerInvocationPreservesOrder) { … }
namespace {
class LinkedNode final : public GarbageCollected<LinkedNode> { … };
class MutatingPrefinalizer final
: public GarbageCollected<MutatingPrefinalizer> { … };
}
TEST_F(PrefinalizerTest, PrefinalizerCanRewireGraphWithLiveObjects) { … }
namespace {
class PrefinalizerDeathTest : public testing::TestWithHeap { … };
class AllocatingPrefinalizer : public GarbageCollected<AllocatingPrefinalizer> { … };
}
#ifdef CPPGC_ALLOW_ALLOCATIONS_IN_PREFINALIZERS
TEST_F(PrefinalizerTest, PrefinalizerDoesNotFailOnAllcoation) {
auto* object = MakeGarbageCollected<AllocatingPrefinalizer>(
GetAllocationHandle(), GetHeap());
PreciseGC();
USE(object);
}
#else
#ifdef DEBUG
TEST_F(PrefinalizerDeathTest, PrefinalizerFailsOnAllcoation) { … }
#endif
#endif
namespace {
template <template <typename T> class RefType>
class RessurectingPrefinalizer
: public GarbageCollected<RessurectingPrefinalizer<RefType>> { … };
class GCedHolder : public GarbageCollected<GCedHolder> { … };
}
#if DEBUG
#ifdef CPPGC_VERIFY_HEAP
TEST_F(PrefinalizerDeathTest, PrefinalizerCanRewireGraphWithDeadObjects) { … }
TEST_F(PrefinalizerDeathTest, PrefinalizerCantRessurectObjectOnStack) { … }
TEST_F(PrefinalizerDeathTest, PrefinalizerCantRessurectObjectOnHeap) { … }
#endif
#endif
#ifdef CPPGC_ALLOW_ALLOCATIONS_IN_PREFINALIZERS
TEST_F(PrefinalizerTest, AllocatingPrefinalizersInMultipleGCCycles) {
auto* object = MakeGarbageCollected<AllocatingPrefinalizer>(
GetAllocationHandle(), GetHeap());
PreciseGC();
auto* other_object = MakeGarbageCollected<AllocatingPrefinalizer>(
GetAllocationHandle(), GetHeap());
PreciseGC();
USE(object);
USE(other_object);
}
#endif
class GCedBase : public GarbageCollected<GCedBase> { … };
size_t GCedBase::prefinalizer_count_ = …;
class GCedInherited : public GCedBase { … };
size_t GCedInherited::prefinalizer_count_ = …;
TEST_F(PrefinalizerTest, VirtualPrefinalizer) { … }
}
}