Add Oilpan cppgc object allocation tests. Creates an object and tracks that it is destroyed by GC. Change-Id: I573787d0e413a40d2b0816f3bb2b93c5b1bdd6a9 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70570 Commit-Queue: Tom Sepez <tsepez@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/gc/heap_embeddertest.cpp b/fxjs/gc/heap_embeddertest.cpp index 2696a91..381bd13 100644 --- a/fxjs/gc/heap_embeddertest.cpp +++ b/fxjs/gc/heap_embeddertest.cpp
@@ -5,11 +5,82 @@ #include "fxjs/gc/heap.h" #include <memory> +#include <set> #include "testing/embedder_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/stl_util.h" +#include "v8/include/cppgc/allocation.h" +#include "v8/include/cppgc/persistent.h" +#include "v8/include/v8.h" -TEST_F(EmbedderTest, SeveralHeaps) { +namespace { + +class PseudoCollectible : public cppgc::GarbageCollected<PseudoCollectible> { + public: + static cppgc::Persistent<PseudoCollectible> s_persistent_; + + static void Clear() { + s_live_.clear(); + s_dead_.clear(); + s_persistent_ = nullptr; + } + static size_t LiveCount() { return s_live_.size(); } + static size_t DeadCount() { return s_dead_.size(); } + + PseudoCollectible() { s_live_.insert(this); } + virtual ~PseudoCollectible() { + s_live_.erase(this); + s_dead_.insert(this); + } + + bool IsLive() const { return pdfium::Contains(s_live_, this); } + + virtual void Trace(cppgc::Visitor* visitor) const {} + + private: + static std::set<const PseudoCollectible*> s_live_; + static std::set<const PseudoCollectible*> s_dead_; +}; + +std::set<const PseudoCollectible*> PseudoCollectible::s_live_; +std::set<const PseudoCollectible*> PseudoCollectible::s_dead_; +cppgc::Persistent<PseudoCollectible> PseudoCollectible::s_persistent_; + +struct V8IsolateDeleter { + inline void operator()(v8::Isolate* ptr) { ptr->Dispose(); } +}; + +} // namespace + +class HeapEmbedderTest : public EmbedderTest { + public: + void SetUp() override { + v8::Isolate::CreateParams params; + params.array_buffer_allocator = static_cast<v8::ArrayBuffer::Allocator*>( + FPDF_GetArrayBufferAllocatorSharedInstance()); + isolate_.reset(v8::Isolate::New(params)); + EmbedderTest::SetExternalIsolate(isolate_.get()); + EmbedderTest::SetUp(); + } + + void TearDown() override { + EmbedderTest::TearDown(); + isolate_.reset(); + } + + void PumpPlatformMessageLoop() { + while (v8::platform::PumpMessageLoop( + EmbedderTestEnvironment::GetInstance()->platform(), isolate_.get())) { + continue; + } + } + + private: + std::unique_ptr<v8::Isolate, V8IsolateDeleter> isolate_; +}; + +TEST_F(HeapEmbedderTest, SeveralHeaps) { FXGCScopedHeap heap1 = FXGC_CreateHeap(); EXPECT_TRUE(heap1); @@ -19,3 +90,41 @@ FXGCScopedHeap heap3 = FXGC_CreateHeap(); EXPECT_TRUE(heap2); } + +TEST_F(HeapEmbedderTest, NoReferences) { + FXGCScopedHeap heap1 = FXGC_CreateHeap(); + ASSERT_TRUE(heap1); + + PseudoCollectible::s_persistent_ = + cppgc::MakeGarbageCollected<PseudoCollectible>(heap1.get()); + EXPECT_TRUE(PseudoCollectible::s_persistent_->IsLive()); + EXPECT_EQ(1u, PseudoCollectible::LiveCount()); + EXPECT_EQ(0u, PseudoCollectible::DeadCount()); + + PseudoCollectible::s_persistent_ = nullptr; + heap1->ForceGarbageCollectionSlow("NoReferences", "test", + cppgc::Heap::StackState::kNoHeapPointers); + PumpPlatformMessageLoop(); + EXPECT_EQ(0u, PseudoCollectible::LiveCount()); + EXPECT_EQ(1u, PseudoCollectible::DeadCount()); + PseudoCollectible::Clear(); +} + +TEST_F(HeapEmbedderTest, HasReferences) { + FXGCScopedHeap heap1 = FXGC_CreateHeap(); + ASSERT_TRUE(heap1); + + PseudoCollectible::s_persistent_ = + cppgc::MakeGarbageCollected<PseudoCollectible>(heap1.get()); + EXPECT_TRUE(PseudoCollectible::s_persistent_->IsLive()); + EXPECT_EQ(1u, PseudoCollectible::LiveCount()); + EXPECT_EQ(0u, PseudoCollectible::DeadCount()); + + heap1->ForceGarbageCollectionSlow("HasReferences", "test", + cppgc::Heap::StackState::kNoHeapPointers); + PumpPlatformMessageLoop(); + EXPECT_TRUE(PseudoCollectible::s_persistent_->IsLive()); + EXPECT_EQ(1u, PseudoCollectible::LiveCount()); + EXPECT_EQ(0u, PseudoCollectible::DeadCount()); + PseudoCollectible::Clear(); +}