1 // Copyright 2016 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/fpdfapi/parser/cpdf_array.h" 6 7 #include <memory> 8 #include <utility> 9 10 #include "core/fpdfapi/parser/cpdf_number.h" 11 #include "core/fpdfapi/parser/cpdf_reference.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "third_party/base/ptr_util.h" 14 15 TEST(cpdf_array, RemoveAt) { 16 { 17 int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 18 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); 19 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 20 arr->AddNew<CPDF_Number>(elems[i]); 21 arr->RemoveAt(3, 3); 22 int expected[] = {1, 2, 3, 7, 8, 9, 10}; 23 EXPECT_EQ(FX_ArraySize(expected), arr->GetCount()); 24 for (size_t i = 0; i < FX_ArraySize(expected); ++i) 25 EXPECT_EQ(expected[i], arr->GetIntegerAt(i)); 26 arr->RemoveAt(4, 2); 27 int expected2[] = {1, 2, 3, 7, 10}; 28 EXPECT_EQ(FX_ArraySize(expected2), arr->GetCount()); 29 for (size_t i = 0; i < FX_ArraySize(expected2); ++i) 30 EXPECT_EQ(expected2[i], arr->GetIntegerAt(i)); 31 } 32 { 33 // When the range is out of bound, RemoveAt has no effect. 34 int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 35 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); 36 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 37 arr->AddNew<CPDF_Number>(elems[i]); 38 arr->RemoveAt(8, 5); 39 EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); 40 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 41 EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); 42 arr->RemoveAt(0, 12); 43 EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); 44 arr->RemoveAt(11, 1); 45 EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); 46 } 47 } 48 49 TEST(cpdf_array, InsertAt) { 50 { 51 int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 52 auto arr = pdfium::MakeUnique<CPDF_Array>(); 53 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 54 arr->InsertNewAt<CPDF_Number>(i, elems[i]); 55 EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); 56 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 57 EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); 58 arr->InsertNewAt<CPDF_Number>(3, 33); 59 arr->InsertNewAt<CPDF_Number>(6, 55); 60 arr->InsertNewAt<CPDF_Number>(12, 12); 61 int expected[] = {1, 2, 3, 33, 4, 5, 55, 6, 7, 8, 9, 10, 12}; 62 EXPECT_EQ(FX_ArraySize(expected), arr->GetCount()); 63 for (size_t i = 0; i < FX_ArraySize(expected); ++i) 64 EXPECT_EQ(expected[i], arr->GetIntegerAt(i)); 65 } 66 { 67 // When the position to insert is beyond the upper bound, 68 // an element is inserted at that position while other unfilled 69 // positions have nullptr. 70 int elems[] = {1, 2}; 71 auto arr = pdfium::MakeUnique<CPDF_Array>(); 72 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 73 arr->InsertNewAt<CPDF_Number>(i, elems[i]); 74 arr->InsertNewAt<CPDF_Number>(10, 10); 75 EXPECT_EQ(11u, arr->GetCount()); 76 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 77 EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); 78 for (size_t i = FX_ArraySize(elems); i < 10; ++i) 79 EXPECT_EQ(nullptr, arr->GetObjectAt(i)); 80 EXPECT_EQ(10, arr->GetIntegerAt(10)); 81 } 82 } 83 84 TEST(cpdf_array, Clone) { 85 { 86 // Basic case. 87 int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 88 auto arr = pdfium::MakeUnique<CPDF_Array>(); 89 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 90 arr->InsertNewAt<CPDF_Number>(i, elems[i]); 91 std::unique_ptr<CPDF_Array> arr2 = ToArray(arr->Clone()); 92 EXPECT_EQ(arr->GetCount(), arr2->GetCount()); 93 for (size_t i = 0; i < FX_ArraySize(elems); ++i) { 94 // Clone() always create new objects. 95 EXPECT_NE(arr->GetObjectAt(i), arr2->GetObjectAt(i)); 96 EXPECT_EQ(arr->GetIntegerAt(i), arr2->GetIntegerAt(i)); 97 } 98 } 99 { 100 // Clone() with and without dereferencing reference objects. 101 static const size_t kNumOfRows = 3; 102 static const size_t kNumOfRowElems = 5; 103 int elems[kNumOfRows][kNumOfRowElems] = { 104 {1, 2, 3, 4, 5}, {10, 9, 8, 7, 6}, {11, 12, 13, 14, 15}}; 105 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); 106 // Indirect references to indirect objects. 107 std::unique_ptr<CPDF_IndirectObjectHolder> obj_holder( 108 new CPDF_IndirectObjectHolder()); 109 for (size_t i = 0; i < kNumOfRows; ++i) { 110 auto arr_elem = pdfium::MakeUnique<CPDF_Array>(); 111 for (size_t j = 0; j < kNumOfRowElems; ++j) { 112 std::unique_ptr<CPDF_Number> obj(new CPDF_Number(elems[i][j])); 113 // Starts object number from 1. 114 int obj_num = i * kNumOfRowElems + j + 1; 115 obj_holder->ReplaceIndirectObjectIfHigherGeneration(obj_num, 116 std::move(obj)); 117 arr_elem->InsertNewAt<CPDF_Reference>(j, obj_holder.get(), obj_num); 118 } 119 arr->InsertAt(i, std::move(arr_elem)); 120 } 121 ASSERT_EQ(kNumOfRows, arr->GetCount()); 122 // Not dereferencing reference objects means just creating new references 123 // instead of new copies of direct objects. 124 std::unique_ptr<CPDF_Array> arr1 = ToArray(arr->Clone()); 125 EXPECT_EQ(arr->GetCount(), arr1->GetCount()); 126 // Dereferencing reference objects creates new copies of direct objects. 127 std::unique_ptr<CPDF_Array> arr2 = ToArray(arr->CloneDirectObject()); 128 EXPECT_EQ(arr->GetCount(), arr2->GetCount()); 129 for (size_t i = 0; i < kNumOfRows; ++i) { 130 CPDF_Array* arr_elem = arr->GetObjectAt(i)->AsArray(); 131 CPDF_Array* arr1_elem = arr1->GetObjectAt(i)->AsArray(); 132 CPDF_Array* arr2_elem = arr2->GetObjectAt(i)->AsArray(); 133 EXPECT_NE(arr_elem, arr1_elem); 134 EXPECT_NE(arr_elem, arr2_elem); 135 for (size_t j = 0; j < kNumOfRowElems; ++j) { 136 auto elem_obj = arr_elem->GetObjectAt(j); 137 auto elem_obj1 = arr1_elem->GetObjectAt(j); 138 auto elem_obj2 = arr2_elem->GetObjectAt(j); 139 // Results from not deferencing reference objects. 140 EXPECT_NE(elem_obj, elem_obj1); 141 EXPECT_TRUE(elem_obj1->IsReference()); 142 EXPECT_EQ(elem_obj->GetDirect(), elem_obj1->GetDirect()); 143 EXPECT_EQ(elem_obj->GetInteger(), elem_obj1->GetInteger()); 144 // Results from deferencing reference objects. 145 EXPECT_NE(elem_obj, elem_obj2); 146 EXPECT_TRUE(elem_obj2->IsNumber()); 147 EXPECT_NE(elem_obj->GetDirect(), elem_obj2); 148 EXPECT_EQ(elem_obj->GetObjNum(), elem_obj2->GetObjNum()); 149 EXPECT_EQ(elem_obj->GetInteger(), elem_obj2->GetInteger()); 150 } 151 } 152 arr.reset(); 153 ASSERT_EQ(kNumOfRows, arr1->GetCount()); 154 for (size_t i = 0; i < kNumOfRows; ++i) { 155 for (size_t j = 0; j < kNumOfRowElems; ++j) { 156 // Results from not deferencing reference objects. 157 auto elem_obj1 = arr1->GetObjectAt(i)->AsArray()->GetObjectAt(j); 158 EXPECT_TRUE(elem_obj1->IsReference()); 159 EXPECT_EQ(elems[i][j], elem_obj1->GetInteger()); 160 // Results from deferencing reference objects. 161 EXPECT_EQ(elems[i][j], 162 arr2->GetObjectAt(i)->AsArray()->GetIntegerAt(j)); 163 } 164 } 165 } 166 } 167 168 TEST(cpdf_array, Iterator) { 169 int elems[] = {-23, -11, 3, 455, 2345877, 170 0, 7895330, -12564334, 10000, -100000}; 171 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); 172 for (size_t i = 0; i < FX_ArraySize(elems); ++i) 173 arr->InsertNewAt<CPDF_Number>(i, elems[i]); 174 size_t index = 0; 175 for (const auto& it : *arr) 176 EXPECT_EQ(elems[index++], it->AsNumber()->GetInteger()); 177 } 178