// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "xfa/fxfa/parser/xfa_utils.h" #include <memory> #include <vector> #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" #include "third_party/base/ptr_util.h" TEST(XfaUtilsImpTest, XFA_MapRotation) { struct TestCase { int input; int expected_output; } TestCases[] = {{-1000000, 80}, {-361, 359}, {-360, 0}, {-359, 1}, {-91, 269}, {-90, 270}, {-89, 271}, {-1, 359}, {0, 0}, {1, 1}, {89, 89}, {90, 90}, {91, 91}, {359, 359}, {360, 0}, {361, 1}, {100000, 280}}; for (size_t i = 0; i < FX_ArraySize(TestCases); ++i) { EXPECT_EQ(TestCases[i].expected_output, XFA_MapRotation(TestCases[i].input)); } } class XFANodeIteratorTest : 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), next_sibling_(nullptr) { if (parent) { if (!parent->children_.empty()) parent->children_.back()->next_sibling_ = this; parent->children_.push_back(this); } } private: Node* parent_; Node* next_sibling_; 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_ = pdfium::MakeUnique<Node>(nullptr); child1_ = pdfium::MakeUnique<Node>(root_.get()); child2_ = pdfium::MakeUnique<Node>(root_.get()); child3_ = pdfium::MakeUnique<Node>(child2_.get()); child4_ = pdfium::MakeUnique<Node>(child3_.get()); child5_ = pdfium::MakeUnique<Node>(child4_.get()); child6_ = pdfium::MakeUnique<Node>(child3_.get()); child7_ = pdfium::MakeUnique<Node>(child2_.get()); child8_ = pdfium::MakeUnique<Node>(child7_.get()); child9_ = pdfium::MakeUnique<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(XFANodeIteratorTest, Empty) { Iterator iter(nullptr); EXPECT_EQ(nullptr, iter.GetRoot()); EXPECT_EQ(nullptr, iter.GetCurrent()); EXPECT_EQ(nullptr, iter.MoveToNext()); EXPECT_EQ(nullptr, iter.MoveToPrev()); EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext()); } TEST_F(XFANodeIteratorTest, Root) { Iterator iter(root()); EXPECT_EQ(root(), iter.GetRoot()); EXPECT_EQ(root(), iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, Current) { Iterator iter(root()); iter.SetCurrent(child1()); EXPECT_EQ(root(), iter.GetRoot()); EXPECT_EQ(child1(), iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, CurrentOutsideRootDisallowed) { Iterator iter(child1()); iter.SetCurrent(root()); EXPECT_EQ(child1(), iter.GetRoot()); EXPECT_EQ(nullptr, iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, CurrentNull) { Iterator iter(root()); EXPECT_EQ(child1(), iter.MoveToNext()); iter.SetCurrent(nullptr); EXPECT_EQ(nullptr, iter.GetCurrent()); EXPECT_EQ(nullptr, iter.MoveToNext()); EXPECT_EQ(nullptr, iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, MoveToPrev) { Iterator iter(root()); 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_EQ(nullptr, iter.MoveToPrev()); EXPECT_EQ(root(), iter.GetCurrent()); EXPECT_EQ(nullptr, iter.MoveToPrev()); EXPECT_EQ(root(), iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, MoveToNext) { Iterator iter(root()); 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_EQ(nullptr, iter.MoveToNext()); EXPECT_EQ(nullptr, iter.GetCurrent()); EXPECT_EQ(nullptr, iter.MoveToNext()); EXPECT_EQ(nullptr, iter.GetCurrent()); } TEST_F(XFANodeIteratorTest, SkipChildrenAndMoveToNext) { Iterator iter(root()); iter.SetCurrent(child3()); EXPECT_EQ(child7(), iter.SkipChildrenAndMoveToNext()); EXPECT_EQ(child9(), iter.SkipChildrenAndMoveToNext()); EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext()); } TEST_F(XFANodeIteratorTest, 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(XFANodeIteratorTest, NextFromBeforeTheBeginning) { Iterator iter(root()); EXPECT_EQ(nullptr, iter.MoveToPrev()); EXPECT_EQ(root(), iter.GetCurrent()); EXPECT_EQ(child1(), iter.MoveToNext()); } TEST_F(XFANodeIteratorTest, PrevFromAfterTheEnd) { Iterator iter(root()); iter.SetCurrent(child9()); EXPECT_EQ(nullptr, iter.MoveToNext()); EXPECT_EQ(child9(), iter.MoveToPrev()); } TEST_F(XFANodeIteratorTest, ChildAsRootPrev) { Iterator iter(child3()); EXPECT_EQ(nullptr, iter.MoveToPrev()); iter.SetCurrent(child4()); EXPECT_EQ(child3(), iter.MoveToPrev()); EXPECT_EQ(nullptr, iter.MoveToPrev()); } TEST_F(XFANodeIteratorTest, ChildAsRootNext) { Iterator iter(child3()); iter.SetCurrent(child4()); EXPECT_EQ(child5(), iter.MoveToNext()); EXPECT_EQ(child6(), iter.MoveToNext()); EXPECT_EQ(nullptr, iter.MoveToNext()); } TEST(XFAUtilsTest, GetAttributeByName) { EXPECT_EQ(nullptr, XFA_GetAttributeByName(L"")); EXPECT_EQ(nullptr, XFA_GetAttributeByName(L"nonesuch")); EXPECT_EQ(XFA_ATTRIBUTE_H, XFA_GetAttributeByName(L"h")->eName); EXPECT_EQ(XFA_ATTRIBUTE_Short, XFA_GetAttributeByName(L"short")->eName); EXPECT_EQ(XFA_ATTRIBUTE_DecipherOnly, XFA_GetAttributeByName(L"decipherOnly")->eName); } TEST(XFAUtilsTest, GetAttributeEnumByName) { EXPECT_EQ(nullptr, XFA_GetAttributeEnumByName(L"")); EXPECT_EQ(nullptr, XFA_GetAttributeEnumByName(L"nonesuch")); EXPECT_EQ(XFA_ATTRIBUTEENUM_Asterisk, XFA_GetAttributeEnumByName(L"*")->eName); EXPECT_EQ(XFA_ATTRIBUTEENUM_Visible, XFA_GetAttributeEnumByName(L"visible")->eName); EXPECT_EQ(XFA_ATTRIBUTEENUM_Lowered, XFA_GetAttributeEnumByName(L"lowered")->eName); }