1 // Copyright 2017 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 "xfa/fxfa/parser/cxfa_node.h"
6
7 #include "fxjs/gc/heap.h"
8 #include "fxjs/xfa/cjx_node.h"
9 #include "testing/fxgc_unittest.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "v8/include/cppgc/allocation.h"
12 #include "v8/include/cppgc/persistent.h"
13 #include "xfa/fxfa/parser/cxfa_document.h"
14
15 namespace {
16
17 class TestNode final : public CXFA_Node {
18 public:
19 CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
20 ~TestNode() override = default;
21
22 private:
TestNode(CXFA_Document * doc)23 explicit TestNode(CXFA_Document* doc)
24 : CXFA_Node(doc,
25 XFA_PacketType::Form,
26 {XFA_XDPPACKET::kTemplate, XFA_XDPPACKET::kForm},
27 XFA_ObjectType::Node,
28 XFA_Element::Node,
29 {},
30 {},
31 cppgc::MakeGarbageCollected<CJX_Node>(
32 doc->GetHeap()->GetAllocationHandle(),
33 this)) {}
34 };
35
36 } // namespace
37
38 class CXFANodeTest : public FXGCUnitTest {
39 public:
SetUp()40 void SetUp() override {
41 FXGCUnitTest::SetUp();
42 doc_ = cppgc::MakeGarbageCollected<CXFA_Document>(
43 heap()->GetAllocationHandle(), nullptr, heap(), nullptr);
44 node_ = cppgc::MakeGarbageCollected<TestNode>(heap()->GetAllocationHandle(),
45 doc_);
46 }
47
TearDown()48 void TearDown() override {
49 node_.Clear();
50 doc_.Clear();
51 FXGCUnitTest::TearDown();
52 }
53
GetDoc() const54 CXFA_Document* GetDoc() const { return doc_; }
GetNode() const55 CXFA_Node* GetNode() const { return node_; }
56
57 private:
58 cppgc::Persistent<CXFA_Document> doc_;
59 cppgc::Persistent<TestNode> node_;
60 };
61
TEST_F(CXFANodeTest,InsertFirstChild)62 TEST_F(CXFANodeTest, InsertFirstChild) {
63 EXPECT_FALSE(GetNode()->GetFirstChild());
64 EXPECT_FALSE(GetNode()->GetLastChild());
65
66 CXFA_Node* child =
67 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
68 GetNode()->InsertChildAndNotify(-1, child);
69
70 EXPECT_EQ(GetNode(), child->GetParent());
71 EXPECT_EQ(child, GetNode()->GetFirstChild());
72 EXPECT_EQ(child, GetNode()->GetLastChild());
73 EXPECT_FALSE(child->GetPrevSibling());
74 EXPECT_FALSE(child->GetNextSibling());
75 }
76
TEST_F(CXFANodeTest,InsertChildByNegativeIndex)77 TEST_F(CXFANodeTest, InsertChildByNegativeIndex) {
78 CXFA_Node* child0 =
79 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
80 GetNode()->InsertChildAndNotify(-1, child0);
81
82 CXFA_Node* child =
83 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
84 GetNode()->InsertChildAndNotify(-1, child);
85
86 EXPECT_EQ(GetNode(), child->GetParent());
87 EXPECT_FALSE(child->GetNextSibling());
88 EXPECT_EQ(child0, child->GetPrevSibling());
89 EXPECT_EQ(child, child0->GetNextSibling());
90 EXPECT_FALSE(child0->GetPrevSibling());
91
92 EXPECT_EQ(child0, GetNode()->GetFirstChild());
93 EXPECT_EQ(child, GetNode()->GetLastChild());
94 }
95
TEST_F(CXFANodeTest,InsertChildByIndex)96 TEST_F(CXFANodeTest, InsertChildByIndex) {
97 CXFA_Node* child0 =
98 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
99 GetNode()->InsertChildAndNotify(-1, child0);
100
101 CXFA_Node* child1 =
102 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
103 GetNode()->InsertChildAndNotify(-1, child1);
104
105 CXFA_Node* child2 =
106 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
107 GetNode()->InsertChildAndNotify(-1, child2);
108
109 CXFA_Node* child3 =
110 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
111 GetNode()->InsertChildAndNotify(-1, child3);
112
113 CXFA_Node* child =
114 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
115 GetNode()->InsertChildAndNotify(2, child);
116
117 EXPECT_EQ(GetNode(), child->GetParent());
118
119 EXPECT_EQ(child0, GetNode()->GetFirstChild());
120 EXPECT_EQ(child1, child0->GetNextSibling());
121 EXPECT_EQ(child, child1->GetNextSibling());
122 EXPECT_EQ(child2, child->GetNextSibling());
123 EXPECT_EQ(child3, child2->GetNextSibling());
124 EXPECT_FALSE(child3->GetNextSibling());
125
126 EXPECT_EQ(child3, GetNode()->GetLastChild());
127 EXPECT_EQ(child2, child3->GetPrevSibling());
128 EXPECT_EQ(child, child2->GetPrevSibling());
129 EXPECT_EQ(child1, child->GetPrevSibling());
130 EXPECT_EQ(child0, child1->GetPrevSibling());
131 EXPECT_FALSE(child0->GetPrevSibling());
132 }
133
TEST_F(CXFANodeTest,InsertChildIndexPastEnd)134 TEST_F(CXFANodeTest, InsertChildIndexPastEnd) {
135 CXFA_Node* child0 =
136 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
137 GetNode()->InsertChildAndNotify(-1, child0);
138
139 CXFA_Node* child1 =
140 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
141 GetNode()->InsertChildAndNotify(-1, child1);
142
143 CXFA_Node* child =
144 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
145 GetNode()->InsertChildAndNotify(20, child);
146
147 EXPECT_EQ(GetNode(), child->GetParent());
148 EXPECT_FALSE(child->GetNextSibling());
149 EXPECT_EQ(child1, child->GetPrevSibling());
150 EXPECT_EQ(child, child1->GetNextSibling());
151
152 EXPECT_EQ(child0, GetNode()->GetFirstChild());
153 EXPECT_EQ(child, GetNode()->GetLastChild());
154 }
155
TEST_F(CXFANodeTest,InsertFirstChildBeforeNullptr)156 TEST_F(CXFANodeTest, InsertFirstChildBeforeNullptr) {
157 EXPECT_FALSE(GetNode()->GetFirstChild());
158 EXPECT_FALSE(GetNode()->GetLastChild());
159
160 CXFA_Node* child =
161 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
162 GetNode()->InsertChildAndNotify(child, nullptr);
163 EXPECT_EQ(child, GetNode()->GetFirstChild());
164 EXPECT_EQ(child, GetNode()->GetLastChild());
165 }
166
TEST_F(CXFANodeTest,InsertBeforeWithNullBefore)167 TEST_F(CXFANodeTest, InsertBeforeWithNullBefore) {
168 CXFA_Node* child0 =
169 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
170 GetNode()->InsertChildAndNotify(-1, child0);
171
172 CXFA_Node* child1 =
173 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
174 GetNode()->InsertChildAndNotify(-1, child1);
175
176 CXFA_Node* child =
177 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
178 GetNode()->InsertChildAndNotify(child, nullptr);
179
180 EXPECT_EQ(GetNode(), child->GetParent());
181 EXPECT_FALSE(child->GetNextSibling());
182 EXPECT_EQ(child1, child->GetPrevSibling());
183 EXPECT_EQ(child, child1->GetNextSibling());
184
185 EXPECT_EQ(child0, GetNode()->GetFirstChild());
186 EXPECT_EQ(child, GetNode()->GetLastChild());
187 }
188
TEST_F(CXFANodeTest,InsertBeforeFirstChild)189 TEST_F(CXFANodeTest, InsertBeforeFirstChild) {
190 CXFA_Node* child0 =
191 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
192 GetNode()->InsertChildAndNotify(-1, child0);
193
194 CXFA_Node* child1 =
195 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
196 GetNode()->InsertChildAndNotify(-1, child1);
197
198 CXFA_Node* child =
199 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
200 GetNode()->InsertChildAndNotify(child, child0);
201
202 EXPECT_EQ(GetNode(), child->GetParent());
203 EXPECT_EQ(child0, child->GetNextSibling());
204 EXPECT_FALSE(child->GetPrevSibling());
205 EXPECT_EQ(child, child0->GetPrevSibling());
206
207 EXPECT_EQ(child, GetNode()->GetFirstChild());
208 EXPECT_EQ(child1, GetNode()->GetLastChild());
209 }
210
TEST_F(CXFANodeTest,InsertBefore)211 TEST_F(CXFANodeTest, InsertBefore) {
212 CXFA_Node* child0 =
213 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
214 GetNode()->InsertChildAndNotify(-1, child0);
215
216 CXFA_Node* child1 =
217 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
218 GetNode()->InsertChildAndNotify(-1, child1);
219
220 CXFA_Node* child2 =
221 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
222 GetNode()->InsertChildAndNotify(-1, child2);
223
224 CXFA_Node* child3 =
225 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
226 GetNode()->InsertChildAndNotify(-1, child3);
227
228 CXFA_Node* child =
229 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
230 GetNode()->InsertChildAndNotify(child, child2);
231
232 EXPECT_EQ(GetNode(), child->GetParent());
233 EXPECT_EQ(child2, child->GetNextSibling());
234 EXPECT_EQ(child1, child->GetPrevSibling());
235 EXPECT_EQ(child, child1->GetNextSibling());
236 EXPECT_EQ(child, child2->GetPrevSibling());
237
238 EXPECT_EQ(child0, GetNode()->GetFirstChild());
239 EXPECT_EQ(child3, GetNode()->GetLastChild());
240 }
241
TEST_F(CXFANodeTest,RemoveOnlyChild)242 TEST_F(CXFANodeTest, RemoveOnlyChild) {
243 CXFA_Node* child0 =
244 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
245 GetNode()->InsertChildAndNotify(-1, child0);
246 EXPECT_EQ(child0, GetNode()->GetFirstChild());
247 EXPECT_EQ(child0, GetNode()->GetLastChild());
248
249 GetNode()->RemoveChildAndNotify(child0, false);
250 EXPECT_FALSE(GetNode()->GetFirstChild());
251 EXPECT_FALSE(GetNode()->GetLastChild());
252 EXPECT_FALSE(child0->GetParent());
253 EXPECT_FALSE(child0->GetNextSibling());
254 EXPECT_FALSE(child0->GetPrevSibling());
255 }
256
TEST_F(CXFANodeTest,RemoveFirstChild)257 TEST_F(CXFANodeTest, RemoveFirstChild) {
258 CXFA_Node* child0 =
259 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
260 GetNode()->InsertChildAndNotify(-1, child0);
261
262 CXFA_Node* child1 =
263 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
264 GetNode()->InsertChildAndNotify(-1, child1);
265
266 CXFA_Node* child2 =
267 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
268 GetNode()->InsertChildAndNotify(-1, child2);
269 EXPECT_EQ(child0, GetNode()->GetFirstChild());
270 EXPECT_EQ(child2, GetNode()->GetLastChild());
271
272 GetNode()->RemoveChildAndNotify(child0, false);
273 EXPECT_EQ(child1, GetNode()->GetFirstChild());
274 EXPECT_EQ(child2, GetNode()->GetLastChild());
275 EXPECT_FALSE(child1->GetPrevSibling());
276 EXPECT_FALSE(child0->GetParent());
277 EXPECT_FALSE(child0->GetNextSibling());
278 EXPECT_FALSE(child0->GetPrevSibling());
279 }
280
TEST_F(CXFANodeTest,RemoveLastChild)281 TEST_F(CXFANodeTest, RemoveLastChild) {
282 CXFA_Node* child0 =
283 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
284 GetNode()->InsertChildAndNotify(-1, child0);
285
286 CXFA_Node* child1 =
287 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
288 GetNode()->InsertChildAndNotify(-1, child1);
289
290 CXFA_Node* child2 =
291 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
292 GetNode()->InsertChildAndNotify(-1, child2);
293 EXPECT_EQ(child0, GetNode()->GetFirstChild());
294 EXPECT_EQ(child2, GetNode()->GetLastChild());
295
296 GetNode()->RemoveChildAndNotify(child2, false);
297 EXPECT_EQ(child0, GetNode()->GetFirstChild());
298 EXPECT_EQ(child1, GetNode()->GetLastChild());
299 EXPECT_FALSE(child1->GetNextSibling());
300 EXPECT_FALSE(child2->GetParent());
301 EXPECT_FALSE(child2->GetNextSibling());
302 EXPECT_FALSE(child2->GetPrevSibling());
303 }
304
TEST_F(CXFANodeTest,RemoveChild)305 TEST_F(CXFANodeTest, RemoveChild) {
306 CXFA_Node* child0 =
307 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
308 GetNode()->InsertChildAndNotify(-1, child0);
309
310 CXFA_Node* child1 =
311 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
312 GetNode()->InsertChildAndNotify(-1, child1);
313
314 CXFA_Node* child2 =
315 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
316 GetNode()->InsertChildAndNotify(-1, child2);
317 EXPECT_EQ(child0, GetNode()->GetFirstChild());
318 EXPECT_EQ(child2, GetNode()->GetLastChild());
319
320 GetNode()->RemoveChildAndNotify(child1, false);
321 EXPECT_EQ(child0, GetNode()->GetFirstChild());
322 EXPECT_EQ(child2, GetNode()->GetLastChild());
323 EXPECT_EQ(child2, child0->GetNextSibling());
324 EXPECT_EQ(child0, child2->GetPrevSibling());
325 EXPECT_FALSE(child1->GetParent());
326 EXPECT_FALSE(child1->GetNextSibling());
327 EXPECT_FALSE(child1->GetPrevSibling());
328 }
329
TEST_F(CXFANodeTest,InsertChildWithParent)330 TEST_F(CXFANodeTest, InsertChildWithParent) {
331 CXFA_Node* child0 =
332 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
333 CXFA_Node* child1 =
334 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
335 child0->InsertChildAndNotify(-1, child1);
336
337 EXPECT_DEATH_IF_SUPPORTED(GetNode()->InsertChildAndNotify(0, child1), "");
338 }
339
TEST_F(CXFANodeTest,InsertNullChild)340 TEST_F(CXFANodeTest, InsertNullChild) {
341 EXPECT_DEATH_IF_SUPPORTED(GetNode()->InsertChildAndNotify(0, nullptr), "");
342 }
343
TEST_F(CXFANodeTest,InsertBeforeWithNullChild)344 TEST_F(CXFANodeTest, InsertBeforeWithNullChild) {
345 EXPECT_DEATH_IF_SUPPORTED(GetNode()->InsertChildAndNotify(nullptr, nullptr),
346 "");
347 }
348
TEST_F(CXFANodeTest,InsertBeforeWithBeforeInAnotherParent)349 TEST_F(CXFANodeTest, InsertBeforeWithBeforeInAnotherParent) {
350 CXFA_Node* child0 =
351 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
352 GetNode()->InsertChildAndNotify(-1, child0);
353
354 CXFA_Node* child1 =
355 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
356 child0->InsertChildAndNotify(-1, child1);
357
358 CXFA_Node* child =
359 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
360 EXPECT_DEATH_IF_SUPPORTED(GetNode()->InsertChildAndNotify(child, child1), "");
361 }
362
TEST_F(CXFANodeTest,InsertBeforeWithNodeInAnotherParent)363 TEST_F(CXFANodeTest, InsertBeforeWithNodeInAnotherParent) {
364 CXFA_Node* child0 =
365 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
366 GetNode()->InsertChildAndNotify(-1, child0);
367
368 CXFA_Node* child1 =
369 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
370 child0->InsertChildAndNotify(-1, child1);
371
372 EXPECT_DEATH_IF_SUPPORTED(GetNode()->InsertChildAndNotify(child1, nullptr),
373 "");
374 }
375
TEST_F(CXFANodeTest,RemoveChildNullptr)376 TEST_F(CXFANodeTest, RemoveChildNullptr) {
377 EXPECT_DEATH_IF_SUPPORTED(GetNode()->RemoveChildAndNotify(nullptr, false),
378 "");
379 }
380
TEST_F(CXFANodeTest,RemoveChildAnotherParent)381 TEST_F(CXFANodeTest, RemoveChildAnotherParent) {
382 CXFA_Node* child0 =
383 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
384 GetNode()->InsertChildAndNotify(-1, child0);
385
386 CXFA_Node* child1 =
387 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
388 child0->InsertChildAndNotify(-1, child1);
389
390 GetNode()->RemoveChildAndNotify(child1, false);
391 EXPECT_EQ(child0, child1->GetParent());
392 }
393
TEST_F(CXFANodeTest,AncestorOf)394 TEST_F(CXFANodeTest, AncestorOf) {
395 CXFA_Node* child0 =
396 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
397 GetNode()->InsertChildAndNotify(-1, child0);
398
399 CXFA_Node* child1 =
400 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
401 GetNode()->InsertChildAndNotify(-1, child1);
402
403 CXFA_Node* grandchild =
404 GetDoc()->CreateNode(XFA_PacketType::Form, XFA_Element::Ui);
405 child0->InsertChildAndNotify(-1, grandchild);
406
407 EXPECT_TRUE(GetNode()->IsAncestorOf(child0));
408 EXPECT_TRUE(GetNode()->IsAncestorOf(child1));
409 EXPECT_FALSE(child1->IsAncestorOf(child0));
410 EXPECT_TRUE(child0->IsAncestorOf(grandchild));
411 EXPECT_TRUE(GetNode()->IsAncestorOf(grandchild));
412 EXPECT_FALSE(child1->IsAncestorOf(grandchild));
413 }
414
TEST_F(CXFANodeTest,DeltaObjectIsNode)415 TEST_F(CXFANodeTest, DeltaObjectIsNode) {
416 CXFA_Node* delta =
417 CXFA_Node::Create(GetDoc(), XFA_Element::Delta, XFA_PacketType::Form);
418 ASSERT_TRUE(delta);
419 ASSERT_TRUE(delta->IsNode());
420
421 // This call should not crash, like in crbug.com/1465239.
422 delta->JSObject()->SetAttributeByEnum(XFA_Attribute::Name, L"delta",
423 /*bNotify=*/false);
424 }
425