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