xref: /aosp_15_r20/external/pdfium/fxjs/gc/gced_tree_node_mixin_unittest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2020 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "fxjs/gc/gced_tree_node_mixin.h"
6 
7 #include <map>
8 
9 #include "core/fxcrt/observed_ptr.h"
10 #include "fxjs/gc/heap.h"
11 #include "testing/fxgc_unittest.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/v8_test_environment.h"
14 #include "v8/include/cppgc/allocation.h"
15 #include "v8/include/cppgc/persistent.h"
16 
17 namespace {
18 
19 class ObservableGCedTreeNodeMixinForTest
20     : public cppgc::GarbageCollected<ObservableGCedTreeNodeMixinForTest>,
21       public GCedTreeNodeMixin<ObservableGCedTreeNodeMixinForTest>,
22       public Observable {
23  public:
24   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
25 
26   // GCedTreeNodeMixin:
Trace(cppgc::Visitor * visitor) const27   void Trace(cppgc::Visitor* visitor) const override {
28     GCedTreeNodeMixin<ObservableGCedTreeNodeMixinForTest>::Trace(visitor);
29   }
30 
31  private:
32   ObservableGCedTreeNodeMixinForTest() = default;
33 };
34 
35 }  // namespace
36 
37 class GCedTreeNodeMixinUnitTest : public FXGCUnitTest {
38  public:
39   GCedTreeNodeMixinUnitTest() = default;
40   ~GCedTreeNodeMixinUnitTest() override = default;
41 
42   // FXGCUnitTest:
TearDown()43   void TearDown() override {
44     root_ = nullptr;  // Can't (yet) outlive |FXGCUnitTest::heap_|.
45     FXGCUnitTest::TearDown();
46   }
47 
root() const48   ObservableGCedTreeNodeMixinForTest* root() const { return root_; }
CreateRoot()49   void CreateRoot() { root_ = CreateNode(); }
50 
CreateNode()51   ObservableGCedTreeNodeMixinForTest* CreateNode() {
52     return cppgc::MakeGarbageCollected<ObservableGCedTreeNodeMixinForTest>(
53         heap()->GetAllocationHandle());
54   }
55 
AddClutterToFront(ObservableGCedTreeNodeMixinForTest * parent)56   void AddClutterToFront(ObservableGCedTreeNodeMixinForTest* parent) {
57     for (int i = 0; i < 4; ++i) {
58       parent->AppendFirstChild(
59           cppgc::MakeGarbageCollected<ObservableGCedTreeNodeMixinForTest>(
60               heap()->GetAllocationHandle()));
61     }
62   }
63 
AddClutterToBack(ObservableGCedTreeNodeMixinForTest * parent)64   void AddClutterToBack(ObservableGCedTreeNodeMixinForTest* parent) {
65     for (int i = 0; i < 4; ++i) {
66       parent->AppendLastChild(
67           cppgc::MakeGarbageCollected<ObservableGCedTreeNodeMixinForTest>(
68               heap()->GetAllocationHandle()));
69     }
70   }
71 
72  private:
73   cppgc::Persistent<ObservableGCedTreeNodeMixinForTest> root_;
74 };
75 
TEST_F(GCedTreeNodeMixinUnitTest,OneRefence)76 TEST_F(GCedTreeNodeMixinUnitTest, OneRefence) {
77   CreateRoot();
78   ObservedPtr<ObservableGCedTreeNodeMixinForTest> watcher(root());
79   ForceGCAndPump();
80   EXPECT_TRUE(watcher);
81 }
82 
TEST_F(GCedTreeNodeMixinUnitTest,NoReferences)83 TEST_F(GCedTreeNodeMixinUnitTest, NoReferences) {
84   ObservedPtr<ObservableGCedTreeNodeMixinForTest> watcher(CreateNode());
85   ForceGCAndPump();
86   EXPECT_FALSE(watcher);
87 }
88 
TEST_F(GCedTreeNodeMixinUnitTest,FirstHasParent)89 TEST_F(GCedTreeNodeMixinUnitTest, FirstHasParent) {
90   CreateRoot();
91   ObservedPtr<ObservableGCedTreeNodeMixinForTest> watcher(CreateNode());
92   root()->AppendFirstChild(watcher.Get());
93   ForceGCAndPump();
94   ASSERT_TRUE(root());
95   EXPECT_TRUE(watcher);
96   root()->RemoveChild(watcher.Get());
97   ForceGCAndPump();
98   ASSERT_TRUE(root());
99   EXPECT_FALSE(watcher);
100 
101   // Now add some clutter.
102   watcher.Reset(CreateNode());
103   root()->AppendFirstChild(watcher.Get());
104   AddClutterToFront(root());
105   AddClutterToBack(root());
106   ForceGCAndPump();
107   ASSERT_TRUE(root());
108   EXPECT_TRUE(watcher);
109   root()->RemoveChild(watcher.Get());
110   ForceGCAndPump();
111   EXPECT_TRUE(root());
112   EXPECT_FALSE(watcher);
113 }
114 
TEST_F(GCedTreeNodeMixinUnitTest,RemoveSelf)115 TEST_F(GCedTreeNodeMixinUnitTest, RemoveSelf) {
116   CreateRoot();
117   ObservedPtr<ObservableGCedTreeNodeMixinForTest> watcher(CreateNode());
118   root()->AppendFirstChild(watcher.Get());
119   ForceGCAndPump();
120   EXPECT_TRUE(root());
121   ASSERT_TRUE(watcher);
122   watcher->RemoveSelfIfParented();
123   ForceGCAndPump();
124   EXPECT_TRUE(root());
125   EXPECT_FALSE(watcher);
126 }
127 
TEST_F(GCedTreeNodeMixinUnitTest,InsertBeforeAfter)128 TEST_F(GCedTreeNodeMixinUnitTest, InsertBeforeAfter) {
129   CreateRoot();
130   AddClutterToFront(root());
131   ObservedPtr<ObservableGCedTreeNodeMixinForTest> watcher(CreateNode());
132   root()->AppendFirstChild(watcher.Get());
133   root()->InsertBefore(root()->GetFirstChild(), root()->GetLastChild());
134   root()->InsertAfter(root()->GetLastChild(), root()->GetFirstChild());
135   ForceGCAndPump();
136   ASSERT_TRUE(root());
137   EXPECT_TRUE(watcher);
138   root()->RemoveChild(watcher.Get());
139   ForceGCAndPump();
140   EXPECT_TRUE(root());
141   EXPECT_FALSE(watcher);
142 }
143 
TEST_F(GCedTreeNodeMixinUnitTest,AsMapKey)144 TEST_F(GCedTreeNodeMixinUnitTest, AsMapKey) {
145   std::map<cppgc::Persistent<ObservableGCedTreeNodeMixinForTest>, int> score;
146   ObservableGCedTreeNodeMixinForTest* node = CreateNode();
147   score[node] = 100;
148   EXPECT_EQ(100, score[node]);
149 }
150