• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 PDFium Authors. All rights reserved.
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 "core/fxcrt/retained_tree_node.h"
6 
7 #include "core/fxcrt/observed_ptr.h"
8 #include "core/fxcrt/retain_ptr.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 namespace fxcrt {
12 namespace {
13 
14 class ObservableRetainedTreeNodeForTest
15     : public RetainedTreeNode<ObservableRetainedTreeNodeForTest>,
16       public Observable {
17  public:
18   template <typename T, typename... Args>
19   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
20 
21  private:
22   ObservableRetainedTreeNodeForTest() = default;
23 };
24 
AddClutterToFront(const RetainPtr<ObservableRetainedTreeNodeForTest> & parent)25 void AddClutterToFront(
26     const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
27   for (int i = 0; i < 4; ++i) {
28     parent->AppendFirstChild(
29         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
30   }
31 }
32 
AddClutterToBack(const RetainPtr<ObservableRetainedTreeNodeForTest> & parent)33 void AddClutterToBack(
34     const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
35   for (int i = 0; i < 4; ++i) {
36     parent->AppendLastChild(
37         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
38   }
39 }
40 
41 }  // namespace
42 
TEST(RetainedTreeNode,NoParent)43 TEST(RetainedTreeNode, NoParent) {
44   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
45   {
46     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
47         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
48     EXPECT_FALSE(ptr->HasChild(ptr.Get()));
49     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
50     EXPECT_TRUE(watcher.Get());
51   }
52   EXPECT_FALSE(watcher.Get());
53 }
54 
TEST(RetainedTreeNode,FirstHasParent)55 TEST(RetainedTreeNode, FirstHasParent) {
56   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
57   RetainPtr<ObservableRetainedTreeNodeForTest> parent =
58       pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
59   {
60     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
61         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
62     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
63     parent->AppendFirstChild(ptr);
64     EXPECT_FALSE(parent->HasChild(parent.Get()));
65     EXPECT_TRUE(parent->HasChild(ptr.Get()));
66     EXPECT_TRUE(watcher.Get());
67   }
68   EXPECT_TRUE(watcher.Get());
69   parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
70   EXPECT_FALSE(watcher.Get());
71   // Now add some clutter.
72   {
73     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
74         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
75     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
76     parent->AppendFirstChild(ptr);
77     AddClutterToFront(parent);
78     AddClutterToBack(parent);
79     EXPECT_TRUE(watcher.Get());
80   }
81   EXPECT_TRUE(watcher.Get());
82   parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
83   EXPECT_FALSE(watcher.Get());
84 }
85 
TEST(RetainedTreeNode,LastHasParent)86 TEST(RetainedTreeNode, LastHasParent) {
87   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
88   RetainPtr<ObservableRetainedTreeNodeForTest> parent =
89       pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
90   {
91     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
92         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
93     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
94     parent->AppendLastChild(ptr);
95     EXPECT_FALSE(parent->HasChild(parent.Get()));
96     EXPECT_TRUE(parent->HasChild(ptr.Get()));
97     EXPECT_TRUE(watcher.Get());
98   }
99   {
100     // Now add some clutter.
101     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
102         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
103     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
104     parent->AppendLastChild(ptr);
105     AddClutterToFront(parent);
106     AddClutterToBack(parent);
107     EXPECT_TRUE(watcher.Get());
108   }
109   EXPECT_TRUE(watcher.Get());
110   parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
111   EXPECT_FALSE(watcher.Get());
112 }
113 
TEST(RetainedTreeNode,GrandChildCleanedUp)114 TEST(RetainedTreeNode, GrandChildCleanedUp) {
115   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
116   RetainPtr<ObservableRetainedTreeNodeForTest> grandparent =
117       pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
118   {
119     RetainPtr<ObservableRetainedTreeNodeForTest> parent =
120         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
121     grandparent->AppendFirstChild(parent);
122     {
123       RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
124           pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
125       watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
126       parent->AppendFirstChild(ptr);
127       EXPECT_TRUE(watcher.Get());
128     }
129     grandparent->RemoveChild(parent);
130     EXPECT_TRUE(watcher.Get());
131   }
132   EXPECT_FALSE(watcher.Get());
133 }
134 
TEST(RetainedTreeNode,RemoveSelf)135 TEST(RetainedTreeNode, RemoveSelf) {
136   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
137   auto parent = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
138   {
139     auto child = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
140     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(child.Get());
141     parent->AppendFirstChild(child);
142   }
143   EXPECT_TRUE(watcher.Get());
144   watcher->RemoveSelfIfParented();
145   EXPECT_FALSE(watcher.Get());
146 }
147 
TEST(RetainedTreeNode,InsertBeforeAfter)148 TEST(RetainedTreeNode, InsertBeforeAfter) {
149   ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
150   RetainPtr<ObservableRetainedTreeNodeForTest> parent =
151       pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
152 
153   AddClutterToFront(parent);
154   {
155     RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
156         pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
157     watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
158     parent->AppendFirstChild(ptr);
159     parent->InsertBefore(pdfium::WrapRetain(parent->GetFirstChild()),
160                          parent->GetLastChild());
161     parent->InsertAfter(pdfium::WrapRetain(parent->GetLastChild()),
162                         parent->GetFirstChild());
163     EXPECT_TRUE(watcher.Get());
164   }
165   parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
166   EXPECT_FALSE(watcher.Get());
167 }
168 
TEST(RetainedTreeNode,Traversal)169 TEST(RetainedTreeNode, Traversal) {
170   RetainPtr<ObservableRetainedTreeNodeForTest> parent =
171       pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
172 
173   AddClutterToFront(parent);
174   int count = 0;
175   for (ObservableRetainedTreeNodeForTest* pNode = parent->GetFirstChild();
176        pNode; pNode = pNode->GetNextSibling()) {
177     ++count;
178   }
179   EXPECT_EQ(4, count);
180   count = 0;
181   for (ObservableRetainedTreeNodeForTest* pNode = parent->GetLastChild(); pNode;
182        pNode = pNode->GetPrevSibling()) {
183     ++count;
184   }
185   EXPECT_EQ(4, count);
186 }
187 
188 }  // namespace fxcrt
189