summaryrefslogtreecommitdiff
path: root/core/fpdfdoc/cpdf_nametree_unittest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfdoc/cpdf_nametree_unittest.cpp')
-rw-r--r--core/fpdfdoc/cpdf_nametree_unittest.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
index bffb496843..4842f06a8e 100644
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
@@ -9,6 +9,40 @@
#include "core/fpdfapi/parser/cpdf_string.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+void AddNameKeyValue(CPDF_Array* pNames, const char* key, const int value) {
+ pNames->AddNew<CPDF_String>(key, false);
+ pNames->AddNew<CPDF_Number>(value);
+}
+
+void CheckNameKeyValue(CPDF_Array* pNames,
+ const int index,
+ const char* key,
+ const int value) {
+ EXPECT_STREQ(key, pNames->GetStringAt(index * 2).c_str());
+ EXPECT_EQ(value, pNames->GetIntegerAt(index * 2 + 1));
+}
+
+void AddLimitsArray(CPDF_Dictionary* pNode,
+ const char* least,
+ const char* greatest) {
+ CPDF_Array* pLimits = pNode->SetNewFor<CPDF_Array>("Limits");
+ pLimits->AddNew<CPDF_String>(least, false);
+ pLimits->AddNew<CPDF_String>(greatest, false);
+}
+
+void CheckLimitsArray(CPDF_Dictionary* pNode,
+ const char* least,
+ const char* greatest) {
+ CPDF_Array* pLimits = pNode->GetArrayFor("Limits");
+ ASSERT_TRUE(pLimits);
+ EXPECT_STREQ(least, pLimits->GetStringAt(0).c_str());
+ EXPECT_STREQ(greatest, pLimits->GetStringAt(1).c_str());
+}
+
+} // namespace
+
TEST(cpdf_nametree, GetUnicodeNameWithBOM) {
// Set up the root dictionary with a Names array.
auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
@@ -34,3 +68,136 @@ TEST(cpdf_nametree, GetUnicodeNameWithBOM) {
ASSERT_TRUE(pObj->IsNumber());
EXPECT_EQ(100, pObj->AsNumber()->GetInteger());
}
+
+TEST(cpdf_nametree, AddIntoNames) {
+ // Set up a name tree with a single Names array.
+ auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ CPDF_Array* pNames = pRootDict->SetNewFor<CPDF_Array>("Names");
+ AddNameKeyValue(pNames, "2.txt", 222);
+ AddNameKeyValue(pNames, "7.txt", 777);
+
+ CPDF_NameTree nameTree(pRootDict.get());
+ pNames = nameTree.GetRoot()->GetArrayFor("Names");
+
+ // Insert a name that already exists in the names array.
+ EXPECT_FALSE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(111), L"2.txt"));
+
+ // Insert in the beginning of the names array.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(111), L"1.txt"));
+
+ // Insert in the middle of the names array.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(555), L"5.txt"));
+
+ // Insert at the end of the names array.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(999), L"9.txt"));
+
+ // Check that the names array has the expected key-value pairs.
+ CheckNameKeyValue(pNames, 0, "1.txt", 111);
+ CheckNameKeyValue(pNames, 1, "2.txt", 222);
+ CheckNameKeyValue(pNames, 2, "5.txt", 555);
+ CheckNameKeyValue(pNames, 3, "7.txt", 777);
+ CheckNameKeyValue(pNames, 4, "9.txt", 999);
+}
+
+TEST(cpdf_nametree, AddIntoKids) {
+ // Set up a name tree with five nodes of three levels.
+ auto pRootDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ CPDF_Array* pKids = pRootDict->SetNewFor<CPDF_Array>("Kids");
+ CPDF_Dictionary* pKid1 = pKids->AddNew<CPDF_Dictionary>();
+
+ AddLimitsArray(pKid1, "1.txt", "9.txt");
+ pKids = pKid1->SetNewFor<CPDF_Array>("Kids");
+ CPDF_Dictionary* pKid2 = pKids->AddNew<CPDF_Dictionary>();
+ CPDF_Dictionary* pKid3 = pKids->AddNew<CPDF_Dictionary>();
+
+ AddLimitsArray(pKid2, "1.txt", "5.txt");
+ pKids = pKid2->SetNewFor<CPDF_Array>("Kids");
+ CPDF_Dictionary* pKid4 = pKids->AddNew<CPDF_Dictionary>();
+ CPDF_Dictionary* pKid5 = pKids->AddNew<CPDF_Dictionary>();
+
+ AddLimitsArray(pKid3, "9.txt", "9.txt");
+ CPDF_Array* pNames = pKid3->SetNewFor<CPDF_Array>("Names");
+ AddNameKeyValue(pNames, "9.txt", 999);
+
+ AddLimitsArray(pKid4, "1.txt", "2.txt");
+ pNames = pKid4->SetNewFor<CPDF_Array>("Names");
+ AddNameKeyValue(pNames, "1.txt", 111);
+ AddNameKeyValue(pNames, "2.txt", 222);
+
+ AddLimitsArray(pKid5, "3.txt", "5.txt");
+ pNames = pKid5->SetNewFor<CPDF_Array>("Names");
+ AddNameKeyValue(pNames, "3.txt", 333);
+ AddNameKeyValue(pNames, "5.txt", 555);
+
+ CPDF_NameTree nameTree(pRootDict.get());
+
+ // Check that adding an existing name would fail.
+ EXPECT_FALSE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(444), L"9.txt"));
+
+ // Add a name within the limits of a leaf node.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(444), L"4.txt"));
+ ASSERT_TRUE(nameTree.LookupValue(L"4.txt"));
+ EXPECT_EQ(444, nameTree.LookupValue(L"4.txt")->GetInteger());
+
+ // Add a name that requires changing the limits of two bottom levels.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(666), L"6.txt"));
+ ASSERT_TRUE(nameTree.LookupValue(L"6.txt"));
+ EXPECT_EQ(666, nameTree.LookupValue(L"6.txt")->GetInteger());
+
+ // Add a name that requires changing the limits of two top levels.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(99), L"99.txt"));
+ ASSERT_TRUE(nameTree.LookupValue(L"99.txt"));
+ EXPECT_EQ(99, nameTree.LookupValue(L"99.txt")->GetInteger());
+
+ // Add a name that requires changing the lower limit of all levels.
+ EXPECT_TRUE(
+ nameTree.AddValueAndName(pdfium::MakeUnique<CPDF_Number>(-5), L"0.txt"));
+ ASSERT_TRUE(nameTree.LookupValue(L"0.txt"));
+ EXPECT_EQ(-5, nameTree.LookupValue(L"0.txt")->GetInteger());
+
+ // Check that the node on the first level has the expected limits.
+ pKid1 = nameTree.GetRoot()->GetArrayFor("Kids")->GetDictAt(0);
+ ASSERT_TRUE(pKid1);
+ CheckLimitsArray(pKid1, "0.txt", "99.txt");
+
+ // Check that the nodes on the second level has the expected limits and names.
+ pKid2 = pKid1->GetArrayFor("Kids")->GetDictAt(0);
+ ASSERT_TRUE(pKid2);
+ CheckLimitsArray(pKid2, "0.txt", "6.txt");
+
+ pKid3 = pKid1->GetArrayFor("Kids")->GetDictAt(1);
+ ASSERT_TRUE(pKid3);
+ CheckLimitsArray(pKid3, "9.txt", "99.txt");
+ pNames = pKid3->GetArrayFor("Names");
+ ASSERT_TRUE(pNames);
+ CheckNameKeyValue(pNames, 0, "9.txt", 999);
+ CheckNameKeyValue(pNames, 1, "99.txt", 99);
+
+ // Check that the nodes on the third level has the expected limits and names.
+ pKid4 = pKid2->GetArrayFor("Kids")->GetDictAt(0);
+ ASSERT_TRUE(pKid4);
+ CheckLimitsArray(pKid4, "0.txt", "2.txt");
+ pNames = pKid4->GetArrayFor("Names");
+ ASSERT_TRUE(pNames);
+ CheckNameKeyValue(pNames, 0, "0.txt", -5);
+ CheckNameKeyValue(pNames, 1, "1.txt", 111);
+ CheckNameKeyValue(pNames, 2, "2.txt", 222);
+
+ pKid5 = pKid2->GetArrayFor("Kids")->GetDictAt(1);
+ ASSERT_TRUE(pKid5);
+ CheckLimitsArray(pKid5, "3.txt", "6.txt");
+ pNames = pKid5->GetArrayFor("Names");
+ ASSERT_TRUE(pNames);
+ CheckNameKeyValue(pNames, 0, "3.txt", 333);
+ CheckNameKeyValue(pNames, 1, "4.txt", 444);
+ CheckNameKeyValue(pNames, 2, "5.txt", 555);
+ CheckNameKeyValue(pNames, 3, "6.txt", 666);
+}