• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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 ObservableGCedTreeNodeForTest
20     : public GCedTreeNode<ObservableGCedTreeNodeForTest>,
21       public Observable {
22  public:
23   CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
24 
25  private:
26   ObservableGCedTreeNodeForTest() = default;
27 };
28 
29 }  // namespace
30 
31 class GCedTreeNodeUnitTest : public FXGCUnitTest {
32  public:
33   GCedTreeNodeUnitTest() = default;
34   ~GCedTreeNodeUnitTest() override = default;
35 
36   // FXGCUnitTest:
TearDown()37   void TearDown() override {
38     root_ = nullptr;  // Can't (yet) outlive |FXGCUnitTest::heap_|.
39     FXGCUnitTest::TearDown();
40   }
41 
root() const42   ObservableGCedTreeNodeForTest* root() const { return root_; }
CreateRoot()43   void CreateRoot() { root_ = CreateNode(); }
44 
CreateNode()45   ObservableGCedTreeNodeForTest* CreateNode() {
46     return cppgc::MakeGarbageCollected<ObservableGCedTreeNodeForTest>(
47         heap()->GetAllocationHandle());
48   }
49 
AddClutterToFront(ObservableGCedTreeNodeForTest * parent)50   void AddClutterToFront(ObservableGCedTreeNodeForTest* parent) {
51     for (int i = 0; i < 4; ++i) {
52       parent->AppendFirstChild(
53           cppgc::MakeGarbageCollected<ObservableGCedTreeNodeForTest>(
54               heap()->GetAllocationHandle()));
55     }
56   }
57 
AddClutterToBack(ObservableGCedTreeNodeForTest * parent)58   void AddClutterToBack(ObservableGCedTreeNodeForTest* parent) {
59     for (int i = 0; i < 4; ++i) {
60       parent->AppendLastChild(
61           cppgc::MakeGarbageCollected<ObservableGCedTreeNodeForTest>(
62               heap()->GetAllocationHandle()));
63     }
64   }
65 
66  private:
67   cppgc::Persistent<ObservableGCedTreeNodeForTest> root_;
68 };
69 
TEST_F(GCedTreeNodeUnitTest,OneRefence)70 TEST_F(GCedTreeNodeUnitTest, OneRefence) {
71   CreateRoot();
72   ObservedPtr<ObservableGCedTreeNodeForTest> watcher(root());
73   ForceGCAndPump();
74   EXPECT_TRUE(watcher);
75 }
76 
TEST_F(GCedTreeNodeUnitTest,NoReferences)77 TEST_F(GCedTreeNodeUnitTest, NoReferences) {
78   ObservedPtr<ObservableGCedTreeNodeForTest> watcher(CreateNode());
79   ForceGCAndPump();
80   EXPECT_FALSE(watcher);
81 }
82 
TEST_F(GCedTreeNodeUnitTest,FirstHasParent)83 TEST_F(GCedTreeNodeUnitTest, FirstHasParent) {
84   CreateRoot();
85   ObservedPtr<ObservableGCedTreeNodeForTest> watcher(CreateNode());
86   root()->AppendFirstChild(watcher.Get());
87   ForceGCAndPump();
88   ASSERT_TRUE(root());
89   EXPECT_TRUE(watcher);
90   root()->RemoveChild(watcher.Get());
91   ForceGCAndPump();
92   ASSERT_TRUE(root());
93   EXPECT_FALSE(watcher);
94 
95   // Now add some clutter.
96   watcher.Reset(CreateNode());
97   root()->AppendFirstChild(watcher.Get());
98   AddClutterToFront(root());
99   AddClutterToBack(root());
100   ForceGCAndPump();
101   ASSERT_TRUE(root());
102   EXPECT_TRUE(watcher);
103   root()->RemoveChild(watcher.Get());
104   ForceGCAndPump();
105   EXPECT_TRUE(root());
106   EXPECT_FALSE(watcher);
107 }
108 
TEST_F(GCedTreeNodeUnitTest,RemoveSelf)109 TEST_F(GCedTreeNodeUnitTest, RemoveSelf) {
110   CreateRoot();
111   ObservedPtr<ObservableGCedTreeNodeForTest> watcher(CreateNode());
112   root()->AppendFirstChild(watcher.Get());
113   ForceGCAndPump();
114   EXPECT_TRUE(root());
115   ASSERT_TRUE(watcher);
116   watcher->RemoveSelfIfParented();
117   ForceGCAndPump();
118   EXPECT_TRUE(root());
119   EXPECT_FALSE(watcher);
120 }
121 
TEST_F(GCedTreeNodeUnitTest,InsertBeforeAfter)122 TEST_F(GCedTreeNodeUnitTest, InsertBeforeAfter) {
123   CreateRoot();
124   AddClutterToFront(root());
125   ObservedPtr<ObservableGCedTreeNodeForTest> watcher(CreateNode());
126   root()->AppendFirstChild(watcher.Get());
127   root()->InsertBefore(root()->GetFirstChild(), root()->GetLastChild());
128   root()->InsertAfter(root()->GetLastChild(), root()->GetFirstChild());
129   ForceGCAndPump();
130   ASSERT_TRUE(root());
131   EXPECT_TRUE(watcher);
132   root()->RemoveChild(watcher.Get());
133   ForceGCAndPump();
134   EXPECT_TRUE(root());
135   EXPECT_FALSE(watcher);
136 }
137 
TEST_F(GCedTreeNodeUnitTest,AsMapKey)138 TEST_F(GCedTreeNodeUnitTest, AsMapKey) {
139   std::map<cppgc::Persistent<ObservableGCedTreeNodeForTest>, int> score;
140   ObservableGCedTreeNodeForTest* node = CreateNode();
141   score[node] = 100;
142   EXPECT_EQ(100, score[node]);
143 }
144