| // Copyright 2017 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" | |
| #include <memory> | |
| #include <vector> | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| class CXFANodeIteratorTemplateTest : public testing::Test { | |
| public: | |
| class Node { | |
| public: | |
| class Strategy { | |
| public: | |
| static Node* GetFirstChild(Node* pNode) { | |
| return pNode && !pNode->children_.empty() ? pNode->children_.front() | |
| : nullptr; | |
| } | |
| static Node* GetNextSibling(Node* pNode) { | |
| return pNode ? pNode->next_sibling_ : nullptr; | |
| } | |
| static Node* GetParent(Node* pNode) { | |
| return pNode ? pNode->parent_ : nullptr; | |
| } | |
| }; | |
| explicit Node(Node* parent) : parent_(parent) { | |
| if (parent) { | |
| if (!parent->children_.empty()) { | |
| parent->children_.back()->next_sibling_ = this; | |
| } | |
| parent->children_.push_back(this); | |
| } | |
| } | |
| private: | |
| Node* const parent_; | |
| Node* next_sibling_ = nullptr; | |
| std::vector<Node*> children_; | |
| }; | |
| using Iterator = CXFA_NodeIteratorTemplate<Node, Node::Strategy>; | |
| // Builds a tree along the lines of: | |
| // | |
| // root | |
| // | | |
| // child1--child2 | |
| // | | |
| // child3------------child7--child9 | |
| // | | | |
| // child4--child6 child8 | |
| // | | |
| // child5 | |
| // | |
| void SetUp() override { | |
| root_ = std::make_unique<Node>(nullptr); | |
| child1_ = std::make_unique<Node>(root_.get()); | |
| child2_ = std::make_unique<Node>(root_.get()); | |
| child3_ = std::make_unique<Node>(child2_.get()); | |
| child4_ = std::make_unique<Node>(child3_.get()); | |
| child5_ = std::make_unique<Node>(child4_.get()); | |
| child6_ = std::make_unique<Node>(child3_.get()); | |
| child7_ = std::make_unique<Node>(child2_.get()); | |
| child8_ = std::make_unique<Node>(child7_.get()); | |
| child9_ = std::make_unique<Node>(child2_.get()); | |
| } | |
| Node* root() const { return root_.get(); } | |
| Node* child1() const { return child1_.get(); } | |
| Node* child2() const { return child2_.get(); } | |
| Node* child3() const { return child3_.get(); } | |
| Node* child4() const { return child4_.get(); } | |
| Node* child5() const { return child5_.get(); } | |
| Node* child6() const { return child6_.get(); } | |
| Node* child7() const { return child7_.get(); } | |
| Node* child8() const { return child8_.get(); } | |
| Node* child9() const { return child9_.get(); } | |
| protected: | |
| std::unique_ptr<Node> root_; | |
| std::unique_ptr<Node> child1_; | |
| std::unique_ptr<Node> child2_; | |
| std::unique_ptr<Node> child3_; | |
| std::unique_ptr<Node> child4_; | |
| std::unique_ptr<Node> child5_; | |
| std::unique_ptr<Node> child6_; | |
| std::unique_ptr<Node> child7_; | |
| std::unique_ptr<Node> child8_; | |
| std::unique_ptr<Node> child9_; | |
| }; | |
| TEST_F(CXFANodeIteratorTemplateTest, Empty) { | |
| Iterator iter(nullptr); | |
| EXPECT_FALSE(iter.GetRoot()); | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| EXPECT_FALSE(iter.SkipChildrenAndMoveToNext()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, Root) { | |
| Iterator iter(root()); | |
| EXPECT_EQ(root(), iter.GetRoot()); | |
| EXPECT_EQ(root(), iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, Current) { | |
| Iterator iter(root()); | |
| EXPECT_TRUE(iter.SetCurrent(child1())); | |
| EXPECT_EQ(root(), iter.GetRoot()); | |
| EXPECT_EQ(child1(), iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, CurrentOutsideRootDisallowed) { | |
| Iterator iter(child1()); | |
| EXPECT_FALSE(iter.SetCurrent(root())); | |
| EXPECT_EQ(child1(), iter.GetRoot()); | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, CurrentNull) { | |
| Iterator iter(root()); | |
| EXPECT_EQ(child1(), iter.MoveToNext()); | |
| EXPECT_FALSE(iter.SetCurrent(nullptr)); // ??? | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, MoveToPrev) { | |
| Iterator iter(root()); | |
| EXPECT_TRUE(iter.SetCurrent(child9())); | |
| EXPECT_EQ(child8(), iter.MoveToPrev()); | |
| EXPECT_EQ(child8(), iter.GetCurrent()); | |
| EXPECT_EQ(child7(), iter.MoveToPrev()); | |
| EXPECT_EQ(child7(), iter.GetCurrent()); | |
| EXPECT_EQ(child6(), iter.MoveToPrev()); | |
| EXPECT_EQ(child6(), iter.GetCurrent()); | |
| EXPECT_EQ(child5(), iter.MoveToPrev()); | |
| EXPECT_EQ(child5(), iter.GetCurrent()); | |
| EXPECT_EQ(child4(), iter.MoveToPrev()); | |
| EXPECT_EQ(child4(), iter.GetCurrent()); | |
| EXPECT_EQ(child3(), iter.MoveToPrev()); | |
| EXPECT_EQ(child3(), iter.GetCurrent()); | |
| EXPECT_EQ(child2(), iter.MoveToPrev()); | |
| EXPECT_EQ(child2(), iter.GetCurrent()); | |
| EXPECT_EQ(child1(), iter.MoveToPrev()); | |
| EXPECT_EQ(child1(), iter.GetCurrent()); | |
| EXPECT_EQ(root(), iter.MoveToPrev()); | |
| EXPECT_EQ(root(), iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| EXPECT_EQ(root(), iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| EXPECT_EQ(root(), iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, MoveToNext) { | |
| Iterator iter(root()); | |
| EXPECT_TRUE(iter.SetCurrent(child2())); | |
| EXPECT_EQ(child3(), iter.MoveToNext()); | |
| EXPECT_EQ(child3(), iter.GetCurrent()); | |
| EXPECT_EQ(child4(), iter.MoveToNext()); | |
| EXPECT_EQ(child4(), iter.GetCurrent()); | |
| EXPECT_EQ(child5(), iter.MoveToNext()); | |
| EXPECT_EQ(child5(), iter.GetCurrent()); | |
| EXPECT_EQ(child6(), iter.MoveToNext()); | |
| EXPECT_EQ(child6(), iter.GetCurrent()); | |
| EXPECT_EQ(child7(), iter.MoveToNext()); | |
| EXPECT_EQ(child7(), iter.GetCurrent()); | |
| EXPECT_EQ(child8(), iter.MoveToNext()); | |
| EXPECT_EQ(child8(), iter.GetCurrent()); | |
| EXPECT_EQ(child9(), iter.MoveToNext()); | |
| EXPECT_EQ(child9(), iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| EXPECT_FALSE(iter.GetCurrent()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, SkipChildrenAndMoveToNext) { | |
| Iterator iter(root()); | |
| EXPECT_TRUE(iter.SetCurrent(child3())); | |
| EXPECT_EQ(child7(), iter.SkipChildrenAndMoveToNext()); | |
| EXPECT_EQ(child9(), iter.SkipChildrenAndMoveToNext()); | |
| EXPECT_FALSE(iter.SkipChildrenAndMoveToNext()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, BackAndForth) { | |
| Iterator iter(root()); | |
| EXPECT_EQ(child1(), iter.MoveToNext()); | |
| EXPECT_EQ(child2(), iter.MoveToNext()); | |
| EXPECT_EQ(child3(), iter.MoveToNext()); | |
| EXPECT_EQ(child4(), iter.MoveToNext()); | |
| EXPECT_EQ(child5(), iter.MoveToNext()); | |
| EXPECT_EQ(child4(), iter.MoveToPrev()); | |
| EXPECT_EQ(child3(), iter.MoveToPrev()); | |
| EXPECT_EQ(child2(), iter.MoveToPrev()); | |
| EXPECT_EQ(child1(), iter.MoveToPrev()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, NextFromBeforeTheBeginning) { | |
| Iterator iter(root()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| EXPECT_EQ(root(), iter.GetCurrent()); | |
| EXPECT_EQ(child1(), iter.MoveToNext()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, PrevFromAfterTheEnd) { | |
| Iterator iter(root()); | |
| EXPECT_TRUE(iter.SetCurrent(child9())); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| EXPECT_EQ(child9(), iter.MoveToPrev()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, ChildAsRootPrev) { | |
| Iterator iter(child3()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| EXPECT_TRUE(iter.SetCurrent(child4())); | |
| EXPECT_EQ(child3(), iter.MoveToPrev()); | |
| EXPECT_FALSE(iter.MoveToPrev()); | |
| } | |
| TEST_F(CXFANodeIteratorTemplateTest, ChildAsRootNext) { | |
| Iterator iter(child3()); | |
| EXPECT_TRUE(iter.SetCurrent(child4())); | |
| EXPECT_EQ(child5(), iter.MoveToNext()); | |
| EXPECT_EQ(child6(), iter.MoveToNext()); | |
| EXPECT_FALSE(iter.MoveToNext()); | |
| } |