blob: 1923992d7a40b47dfb35432b77a6051c3523b962 [file] [log] [blame]
Lei Zhang94293682016-01-27 18:27:56 -08001// 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
dsinclair488b7ad2016-10-04 11:55:50 -07005#include "core/fpdfapi/parser/cpdf_array.h"
6#include "core/fpdfapi/parser/cpdf_boolean.h"
7#include "core/fpdfapi/parser/cpdf_dictionary.h"
8#include "core/fpdfapi/parser/cpdf_name.h"
9#include "core/fpdfapi/parser/cpdf_null.h"
10#include "core/fpdfapi/parser/cpdf_number.h"
11#include "core/fpdfapi/parser/cpdf_reference.h"
12#include "core/fpdfapi/parser/cpdf_stream.h"
13#include "core/fpdfapi/parser/cpdf_string.h"
Lei Zhang94293682016-01-27 18:27:56 -080014
15#include <memory>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050016#include <string>
tsepez0e606b52016-11-18 16:22:41 -080017#include <utility>
Lei Zhang94293682016-01-27 18:27:56 -080018#include <vector>
19
dsinclair488b7ad2016-10-04 11:55:50 -070020#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
dsinclaira52ab742016-09-29 13:59:29 -070021#include "core/fxcrt/fx_basic.h"
Lei Zhang94293682016-01-27 18:27:56 -080022#include "testing/gtest/include/gtest/gtest.h"
23
Wei Libb53a5d2016-02-03 10:04:19 -080024namespace {
25
Wei Libb53a5d2016-02-03 10:04:19 -080026void TestArrayAccessors(const CPDF_Array* arr,
27 size_t index,
28 const char* str_val,
29 const char* const_str_val,
30 int int_val,
31 float float_val,
32 CPDF_Array* arr_val,
33 CPDF_Dictionary* dict_val,
34 CPDF_Stream* stream_val) {
35 EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str());
Wei Libb53a5d2016-02-03 10:04:19 -080036 EXPECT_EQ(int_val, arr->GetIntegerAt(index));
37 EXPECT_EQ(float_val, arr->GetNumberAt(index));
38 EXPECT_EQ(float_val, arr->GetFloatAt(index));
39 EXPECT_EQ(arr_val, arr->GetArrayAt(index));
40 EXPECT_EQ(dict_val, arr->GetDictAt(index));
41 EXPECT_EQ(stream_val, arr->GetStreamAt(index));
42}
43
44} // namespace
45
Lei Zhang94293682016-01-27 18:27:56 -080046class PDFObjectsTest : public testing::Test {
47 public:
48 void SetUp() override {
49 // Initialize different kinds of objects.
50 // Boolean objects.
51 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
52 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
53 // Number objects.
54 CPDF_Number* number_int_obj = new CPDF_Number(1245);
55 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
56 // String objects.
tsepez0e606b52016-11-18 16:22:41 -080057 CPDF_String* str_reg_obj = new CPDF_String(nullptr, L"A simple test");
58 CPDF_String* str_spec_obj = new CPDF_String(nullptr, L"\t\n");
Lei Zhang94293682016-01-27 18:27:56 -080059 // Name object.
tsepez5913a6c2016-11-16 17:31:18 -080060 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space");
Lei Zhang94293682016-01-27 18:27:56 -080061 // Array object.
Wei Li8f952272016-01-29 18:04:42 -080062 m_ArrayObj = new CPDF_Array;
tsepez8a3aa452016-11-16 12:26:06 -080063 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902);
64 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address");
Lei Zhang94293682016-01-27 18:27:56 -080065 // Dictionary object.
tsepezcd5bca42016-09-30 10:45:06 -070066 m_DictObj = new CPDF_Dictionary();
tsepez0e606b52016-11-18 16:22:41 -080067 m_DictObj->SetNewFor<CPDF_Boolean>("bool", false);
68 m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f);
Lei Zhang94293682016-01-27 18:27:56 -080069 // Stream object.
70 const char content[] = "abcdefghijklmnopqrstuvwxyz";
71 size_t buf_len = FX_ArraySize(content);
tsepez47fb8c02016-12-15 13:51:34 -080072 std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
73 memcpy(buf.get(), content, buf_len);
tsepez9e05ee12016-11-21 13:19:10 -080074 auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>();
75 m_StreamDictObj = pNewDict.get();
tsepez0e606b52016-11-18 16:22:41 -080076 m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict");
77 m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1);
tsepez9e05ee12016-11-21 13:19:10 -080078 CPDF_Stream* stream_obj =
tsepez47fb8c02016-12-15 13:51:34 -080079 new CPDF_Stream(std::move(buf), buf_len, std::move(pNewDict));
Lei Zhang94293682016-01-27 18:27:56 -080080 // Null Object.
81 CPDF_Null* null_obj = new CPDF_Null;
82 // All direct objects.
83 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
84 number_float_obj, str_reg_obj, str_spec_obj,
Wei Li8f952272016-01-29 18:04:42 -080085 name_obj, m_ArrayObj, m_DictObj,
Lei Zhang94293682016-01-27 18:27:56 -080086 stream_obj, null_obj};
Wei Li8f952272016-01-29 18:04:42 -080087 m_DirectObjTypes = {
88 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER,
89 CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING,
90 CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY,
91 CPDF_Object::STREAM, CPDF_Object::NULLOBJ};
92 for (size_t i = 0; i < FX_ArraySize(objs); ++i)
Lei Zhang94293682016-01-27 18:27:56 -080093 m_DirectObjs.emplace_back(objs[i]);
94
95 // Indirect references to indirect objects.
tsepez70c4afd2016-11-15 11:33:44 -080096 m_ObjHolder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
97 m_IndirectObjs = {m_ObjHolder->AddIndirectObject(boolean_true_obj->Clone()),
98 m_ObjHolder->AddIndirectObject(number_int_obj->Clone()),
99 m_ObjHolder->AddIndirectObject(str_spec_obj->Clone()),
100 m_ObjHolder->AddIndirectObject(name_obj->Clone()),
101 m_ObjHolder->AddIndirectObject(m_ArrayObj->Clone()),
102 m_ObjHolder->AddIndirectObject(m_DictObj->Clone()),
103 m_ObjHolder->AddIndirectObject(stream_obj->Clone())};
104 for (CPDF_Object* pObj : m_IndirectObjs) {
105 m_RefObjs.emplace_back(
106 new CPDF_Reference(m_ObjHolder.get(), pObj->GetObjNum()));
Lei Zhang94293682016-01-27 18:27:56 -0800107 }
108 }
109
tsepez836f7d52016-10-10 14:31:05 -0700110 bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) {
Wei Li8f952272016-01-29 18:04:42 -0800111 if (obj1 == obj2)
112 return true;
113 if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType())
114 return false;
115 switch (obj1->GetType()) {
116 case CPDF_Object::BOOLEAN:
117 return obj1->GetInteger() == obj2->GetInteger();
118 case CPDF_Object::NUMBER:
119 return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() &&
120 obj1->GetInteger() == obj2->GetInteger();
121 case CPDF_Object::STRING:
122 case CPDF_Object::NAME:
123 return obj1->GetString() == obj2->GetString();
124 case CPDF_Object::ARRAY: {
125 const CPDF_Array* array1 = obj1->AsArray();
126 const CPDF_Array* array2 = obj2->AsArray();
127 if (array1->GetCount() != array2->GetCount())
128 return false;
129 for (size_t i = 0; i < array1->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700130 if (!Equal(array1->GetObjectAt(i), array2->GetObjectAt(i)))
Wei Li8f952272016-01-29 18:04:42 -0800131 return false;
132 }
133 return true;
134 }
135 case CPDF_Object::DICTIONARY: {
136 const CPDF_Dictionary* dict1 = obj1->AsDictionary();
137 const CPDF_Dictionary* dict2 = obj2->AsDictionary();
138 if (dict1->GetCount() != dict2->GetCount())
139 return false;
140 for (CPDF_Dictionary::const_iterator it = dict1->begin();
141 it != dict1->end(); ++it) {
tsepez0e606b52016-11-18 16:22:41 -0800142 if (!Equal(it->second.get(), dict2->GetObjectFor(it->first)))
Wei Li8f952272016-01-29 18:04:42 -0800143 return false;
144 }
145 return true;
146 }
147 case CPDF_Object::NULLOBJ:
148 return true;
149 case CPDF_Object::STREAM: {
150 const CPDF_Stream* stream1 = obj1->AsStream();
151 const CPDF_Stream* stream2 = obj2->AsStream();
152 if (!stream1->GetDict() && !stream2->GetDict())
153 return true;
154 // Compare dictionaries.
155 if (!Equal(stream1->GetDict(), stream2->GetDict()))
156 return false;
157 // Compare sizes.
158 if (stream1->GetRawSize() != stream2->GetRawSize())
159 return false;
160 // Compare contents.
161 // Since this function is used for testing Clone(), only memory based
162 // streams need to be handled.
163 if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased())
164 return false;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400165 return memcmp(stream1->GetRawData(), stream2->GetRawData(),
166 stream1->GetRawSize()) == 0;
Wei Li8f952272016-01-29 18:04:42 -0800167 }
168 case CPDF_Object::REFERENCE:
169 return obj1->AsReference()->GetRefObjNum() ==
170 obj2->AsReference()->GetRefObjNum();
171 }
172 return false;
173 }
174
Lei Zhang94293682016-01-27 18:27:56 -0800175 protected:
Lei Zhang94293682016-01-27 18:27:56 -0800176 // m_ObjHolder needs to be declared first and destructed last since it also
177 // refers to some objects in m_DirectObjs.
178 std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder;
tsepez33fdebc2016-11-04 11:38:40 -0700179 std::vector<std::unique_ptr<CPDF_Object>> m_DirectObjs;
Wei Li8f952272016-01-29 18:04:42 -0800180 std::vector<int> m_DirectObjTypes;
tsepez33fdebc2016-11-04 11:38:40 -0700181 std::vector<std::unique_ptr<CPDF_Object>> m_RefObjs;
Lei Zhang94293682016-01-27 18:27:56 -0800182 CPDF_Dictionary* m_DictObj;
183 CPDF_Dictionary* m_StreamDictObj;
Wei Li8f952272016-01-29 18:04:42 -0800184 CPDF_Array* m_ArrayObj;
185 std::vector<CPDF_Object*> m_IndirectObjs;
Lei Zhang94293682016-01-27 18:27:56 -0800186};
187
188TEST_F(PDFObjectsTest, GetString) {
thestigb8bf55f2016-05-21 21:08:05 -0700189 const char* const direct_obj_results[] = {
Lei Zhang94293682016-01-27 18:27:56 -0800190 "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space",
191 "", "", "", ""};
192 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800193 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800194 EXPECT_STREQ(direct_obj_results[i], m_DirectObjs[i]->GetString().c_str());
Lei Zhang94293682016-01-27 18:27:56 -0800195
196 // Check indirect references.
thestigb8bf55f2016-05-21 21:08:05 -0700197 const char* const indirect_obj_results[] = {"true", "1245", "\t\n", "space",
198 "", "", ""};
Wei Li8f952272016-01-29 18:04:42 -0800199 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
Wei Libb53a5d2016-02-03 10:04:19 -0800200 EXPECT_STREQ(indirect_obj_results[i], m_RefObjs[i]->GetString().c_str());
Lei Zhang94293682016-01-27 18:27:56 -0800201 }
202}
203
Wei Li8f952272016-01-29 18:04:42 -0800204TEST_F(PDFObjectsTest, GetUnicodeText) {
thestigb8bf55f2016-05-21 21:08:05 -0700205 const wchar_t* const direct_obj_results[] = {
Wei Li8f952272016-01-29 18:04:42 -0800206 L"", L"", L"", L"", L"A simple test",
207 L"\t\n", L"space", L"", L"", L"abcdefghijklmnopqrstuvwxyz",
208 L""};
209 // Check for direct objects.
dsinclair685bb882016-04-20 07:32:39 -0700210 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
Wei Libb53a5d2016-02-03 10:04:19 -0800211 EXPECT_STREQ(direct_obj_results[i],
212 m_DirectObjs[i]->GetUnicodeText().c_str());
dsinclair685bb882016-04-20 07:32:39 -0700213 }
Wei Li8f952272016-01-29 18:04:42 -0800214
215 // Check indirect references.
216 for (const auto& it : m_RefObjs)
Wei Libb53a5d2016-02-03 10:04:19 -0800217 EXPECT_STREQ(L"", it->GetUnicodeText().c_str());
Wei Li8f952272016-01-29 18:04:42 -0800218}
219
Lei Zhang94293682016-01-27 18:27:56 -0800220TEST_F(PDFObjectsTest, GetNumber) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400221 const float direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0,
222 0, 0, 0, 0, 0};
Lei Zhang94293682016-01-27 18:27:56 -0800223 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800224 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800225 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber());
Lei Zhang94293682016-01-27 18:27:56 -0800226
227 // Check indirect references.
Dan Sinclair05df0752017-03-14 14:43:42 -0400228 const float indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0};
Wei Li8f952272016-01-29 18:04:42 -0800229 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800230 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber());
Lei Zhang94293682016-01-27 18:27:56 -0800231}
232
233TEST_F(PDFObjectsTest, GetInteger) {
234 const int direct_obj_results[] = {0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0};
235 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800236 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800237 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetInteger());
Lei Zhang94293682016-01-27 18:27:56 -0800238
239 // Check indirect references.
240 const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0};
Wei Li8f952272016-01-29 18:04:42 -0800241 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800242 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetInteger());
Lei Zhang94293682016-01-27 18:27:56 -0800243}
244
245TEST_F(PDFObjectsTest, GetDict) {
thestigb8bf55f2016-05-21 21:08:05 -0700246 const CPDF_Dictionary* const direct_obj_results[] = {
Lei Zhang94293682016-01-27 18:27:56 -0800247 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
248 nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr};
249 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800250 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800251 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict());
Lei Zhang94293682016-01-27 18:27:56 -0800252
253 // Check indirect references.
thestigb8bf55f2016-05-21 21:08:05 -0700254 const CPDF_Dictionary* const indirect_obj_results[] = {
Lei Zhang94293682016-01-27 18:27:56 -0800255 nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj};
Wei Li8f952272016-01-29 18:04:42 -0800256 for (size_t i = 0; i < m_RefObjs.size(); ++i)
tsepez836f7d52016-10-10 14:31:05 -0700257 EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict()));
Lei Zhang94293682016-01-27 18:27:56 -0800258}
Wei Li8f952272016-01-29 18:04:42 -0800259
260TEST_F(PDFObjectsTest, GetArray) {
thestigb8bf55f2016-05-21 21:08:05 -0700261 const CPDF_Array* const direct_obj_results[] = {
Wei Li8f952272016-01-29 18:04:42 -0800262 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
263 nullptr, m_ArrayObj, nullptr, nullptr, nullptr};
264 // Check for direct objects.
265 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
thestigb8bf55f2016-05-21 21:08:05 -0700266 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800267
268 // Check indirect references.
269 for (const auto& it : m_RefObjs)
thestigb8bf55f2016-05-21 21:08:05 -0700270 EXPECT_EQ(nullptr, it->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800271}
272
273TEST_F(PDFObjectsTest, Clone) {
274 // Check for direct objects.
275 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
tsepez335cf092016-11-09 13:28:26 -0800276 std::unique_ptr<CPDF_Object> obj = m_DirectObjs[i]->Clone();
Wei Li8f952272016-01-29 18:04:42 -0800277 EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get()));
278 }
279
280 // Check indirect references.
281 for (const auto& it : m_RefObjs) {
tsepez335cf092016-11-09 13:28:26 -0800282 std::unique_ptr<CPDF_Object> obj = it->Clone();
Wei Li8f952272016-01-29 18:04:42 -0800283 EXPECT_TRUE(Equal(it.get(), obj.get()));
284 }
285}
286
287TEST_F(PDFObjectsTest, GetType) {
288 // Check for direct objects.
289 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800290 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType());
Wei Li8f952272016-01-29 18:04:42 -0800291
292 // Check indirect references.
293 for (const auto& it : m_RefObjs)
Wei Libb53a5d2016-02-03 10:04:19 -0800294 EXPECT_EQ(CPDF_Object::REFERENCE, it->GetType());
Wei Li8f952272016-01-29 18:04:42 -0800295}
296
297TEST_F(PDFObjectsTest, GetDirect) {
298 // Check for direct objects.
299 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800300 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->GetDirect());
Wei Li8f952272016-01-29 18:04:42 -0800301
302 // Check indirect references.
303 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800304 EXPECT_EQ(m_IndirectObjs[i], m_RefObjs[i]->GetDirect());
Wei Li8f952272016-01-29 18:04:42 -0800305}
306
307TEST_F(PDFObjectsTest, SetString) {
308 // Check for direct objects.
309 const char* const set_values[] = {"true", "fake", "3.125f", "097",
310 "changed", "", "NewName"};
thestigb8bf55f2016-05-21 21:08:05 -0700311 const char* const expected[] = {"true", "false", "3.125", "97",
312 "changed", "", "NewName"};
Wei Li8f952272016-01-29 18:04:42 -0800313 for (size_t i = 0; i < FX_ArraySize(set_values); ++i) {
314 m_DirectObjs[i]->SetString(set_values[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800315 EXPECT_STREQ(expected[i], m_DirectObjs[i]->GetString().c_str());
Wei Li8f952272016-01-29 18:04:42 -0800316 }
317}
318
319TEST_F(PDFObjectsTest, IsTypeAndAsType) {
320 // Check for direct objects.
321 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
322 if (m_DirectObjTypes[i] == CPDF_Object::ARRAY) {
323 EXPECT_TRUE(m_DirectObjs[i]->IsArray());
Wei Libb53a5d2016-02-03 10:04:19 -0800324 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800325 } else {
326 EXPECT_FALSE(m_DirectObjs[i]->IsArray());
Wei Libb53a5d2016-02-03 10:04:19 -0800327 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800328 }
329
330 if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) {
331 EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
Wei Libb53a5d2016-02-03 10:04:19 -0800332 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsBoolean());
Wei Li8f952272016-01-29 18:04:42 -0800333 } else {
334 EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
Wei Libb53a5d2016-02-03 10:04:19 -0800335 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsBoolean());
Wei Li8f952272016-01-29 18:04:42 -0800336 }
337
338 if (m_DirectObjTypes[i] == CPDF_Object::NAME) {
339 EXPECT_TRUE(m_DirectObjs[i]->IsName());
Wei Libb53a5d2016-02-03 10:04:19 -0800340 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsName());
Wei Li8f952272016-01-29 18:04:42 -0800341 } else {
342 EXPECT_FALSE(m_DirectObjs[i]->IsName());
Wei Libb53a5d2016-02-03 10:04:19 -0800343 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsName());
Wei Li8f952272016-01-29 18:04:42 -0800344 }
345
346 if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) {
347 EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800348 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsNumber());
Wei Li8f952272016-01-29 18:04:42 -0800349 } else {
350 EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800351 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsNumber());
Wei Li8f952272016-01-29 18:04:42 -0800352 }
353
354 if (m_DirectObjTypes[i] == CPDF_Object::STRING) {
355 EXPECT_TRUE(m_DirectObjs[i]->IsString());
Wei Libb53a5d2016-02-03 10:04:19 -0800356 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsString());
Wei Li8f952272016-01-29 18:04:42 -0800357 } else {
358 EXPECT_FALSE(m_DirectObjs[i]->IsString());
Wei Libb53a5d2016-02-03 10:04:19 -0800359 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsString());
Wei Li8f952272016-01-29 18:04:42 -0800360 }
361
362 if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) {
363 EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
Wei Libb53a5d2016-02-03 10:04:19 -0800364 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsDictionary());
Wei Li8f952272016-01-29 18:04:42 -0800365 } else {
366 EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
Wei Libb53a5d2016-02-03 10:04:19 -0800367 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsDictionary());
Wei Li8f952272016-01-29 18:04:42 -0800368 }
369
370 if (m_DirectObjTypes[i] == CPDF_Object::STREAM) {
371 EXPECT_TRUE(m_DirectObjs[i]->IsStream());
Wei Libb53a5d2016-02-03 10:04:19 -0800372 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsStream());
Wei Li8f952272016-01-29 18:04:42 -0800373 } else {
374 EXPECT_FALSE(m_DirectObjs[i]->IsStream());
Wei Libb53a5d2016-02-03 10:04:19 -0800375 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsStream());
Wei Li8f952272016-01-29 18:04:42 -0800376 }
377
378 EXPECT_FALSE(m_DirectObjs[i]->IsReference());
Wei Libb53a5d2016-02-03 10:04:19 -0800379 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsReference());
Wei Li8f952272016-01-29 18:04:42 -0800380 }
381 // Check indirect references.
382 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
383 EXPECT_TRUE(m_RefObjs[i]->IsReference());
Wei Libb53a5d2016-02-03 10:04:19 -0800384 EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference());
385 }
386}
387
388TEST(PDFArrayTest, GetMatrix) {
389 float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
390 {1, 2, 3, 4, 5, 6},
391 {2.3f, 4.05f, 3, -2, -3, 0.0f},
392 {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}};
393 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800394 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800395 CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3],
396 elems[i][4], elems[i][5]);
397 for (size_t j = 0; j < 6; ++j)
tsepez8a3aa452016-11-16 12:26:06 -0800398 arr->AddNew<CPDF_Number>(elems[i][j]);
Wei Libb53a5d2016-02-03 10:04:19 -0800399 CFX_Matrix arr_matrix = arr->GetMatrix();
Dan Sinclair687a79c2017-02-09 14:08:53 -0500400 EXPECT_EQ(matrix.a, arr_matrix.a);
401 EXPECT_EQ(matrix.b, arr_matrix.b);
402 EXPECT_EQ(matrix.c, arr_matrix.c);
403 EXPECT_EQ(matrix.d, arr_matrix.d);
404 EXPECT_EQ(matrix.e, arr_matrix.e);
405 EXPECT_EQ(matrix.f, arr_matrix.f);
Wei Libb53a5d2016-02-03 10:04:19 -0800406 }
407}
408
409TEST(PDFArrayTest, GetRect) {
410 float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
411 {1, 2, 5, 6},
412 {2.3f, 4.05f, -3, 0.0f},
413 {0.05f, 0.1f, 1.34f, 99.9f}};
414 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800415 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800416 CFX_FloatRect rect(elems[i]);
417 for (size_t j = 0; j < 4; ++j)
tsepez8a3aa452016-11-16 12:26:06 -0800418 arr->AddNew<CPDF_Number>(elems[i][j]);
Wei Libb53a5d2016-02-03 10:04:19 -0800419 CFX_FloatRect arr_rect = arr->GetRect();
420 EXPECT_EQ(rect.left, arr_rect.left);
421 EXPECT_EQ(rect.right, arr_rect.right);
422 EXPECT_EQ(rect.bottom, arr_rect.bottom);
423 EXPECT_EQ(rect.top, arr_rect.top);
424 }
425}
426
427TEST(PDFArrayTest, GetTypeAt) {
428 {
429 // Boolean array.
thestigb8bf55f2016-05-21 21:08:05 -0700430 const bool vals[] = {true, false, false, true, true};
tsepez8a3aa452016-11-16 12:26:06 -0800431 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800432 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800433 arr->InsertNewAt<CPDF_Boolean>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800434 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
435 TestArrayAccessors(arr.get(), i, // Array and index.
436 vals[i] ? "true" : "false", // String value.
437 nullptr, // Const string value.
438 vals[i] ? 1 : 0, // Integer value.
439 0, // Float value.
440 nullptr, // Array value.
441 nullptr, // Dictionary value.
442 nullptr); // Stream value.
443 }
444 }
445 {
446 // Integer array.
thestigb8bf55f2016-05-21 21:08:05 -0700447 const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767};
tsepez8a3aa452016-11-16 12:26:06 -0800448 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800449 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800450 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800451 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
452 char buf[33];
453 TestArrayAccessors(arr.get(), i, // Array and index.
454 FXSYS_itoa(vals[i], buf, 10), // String value.
455 nullptr, // Const string value.
456 vals[i], // Integer value.
457 vals[i], // Float value.
458 nullptr, // Array value.
459 nullptr, // Dictionary value.
460 nullptr); // Stream value.
461 }
462 }
463 {
464 // Float array.
thestigb8bf55f2016-05-21 21:08:05 -0700465 const float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f,
466 897.34f, -2.5f, -1.0f, -345.0f, -0.0f};
467 const char* const expected_str[] = {
468 "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"};
tsepez8a3aa452016-11-16 12:26:06 -0800469 auto arr = pdfium::MakeUnique<CPDF_Array>();
470 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
471 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800472 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
473 TestArrayAccessors(arr.get(), i, // Array and index.
474 expected_str[i], // String value.
475 nullptr, // Const string value.
476 vals[i], // Integer value.
477 vals[i], // Float value.
478 nullptr, // Array value.
479 nullptr, // Dictionary value.
480 nullptr); // Stream value.
481 }
482 }
483 {
484 // String and name array
485 const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012",
486 ".", "EYREW", "It is a joke :)"};
Dan Sinclair0bb13332017-03-30 16:12:02 -0400487 auto string_array = pdfium::MakeUnique<CPDF_Array>();
488 auto name_array = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800489 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800490 string_array->InsertNewAt<CPDF_String>(i, vals[i], false);
491 name_array->InsertNewAt<CPDF_Name>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800492 }
493 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
494 TestArrayAccessors(string_array.get(), i, // Array and index.
495 vals[i], // String value.
496 vals[i], // Const string value.
497 0, // Integer value.
498 0, // Float value.
499 nullptr, // Array value.
500 nullptr, // Dictionary value.
501 nullptr); // Stream value.
502 TestArrayAccessors(name_array.get(), i, // Array and index.
503 vals[i], // String value.
504 vals[i], // Const string value.
505 0, // Integer value.
506 0, // Float value.
507 nullptr, // Array value.
508 nullptr, // Dictionary value.
509 nullptr); // Stream value.
510 }
511 }
512 {
513 // Null element array.
tsepez8a3aa452016-11-16 12:26:06 -0800514 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800515 for (size_t i = 0; i < 3; ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800516 arr->InsertNewAt<CPDF_Null>(i);
Wei Libb53a5d2016-02-03 10:04:19 -0800517 for (size_t i = 0; i < 3; ++i) {
518 TestArrayAccessors(arr.get(), i, // Array and index.
519 "", // String value.
520 nullptr, // Const string value.
521 0, // Integer value.
522 0, // Float value.
523 nullptr, // Array value.
524 nullptr, // Dictionary value.
525 nullptr); // Stream value.
526 }
527 }
528 {
529 // Array of array.
530 CPDF_Array* vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800531 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800532 for (size_t i = 0; i < 3; ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800533 vals[i] = arr->AddNew<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800534 for (size_t j = 0; j < 3; ++j) {
535 int value = j + 100;
tsepez8a3aa452016-11-16 12:26:06 -0800536 vals[i]->InsertNewAt<CPDF_Number>(i, value);
Wei Libb53a5d2016-02-03 10:04:19 -0800537 }
Wei Libb53a5d2016-02-03 10:04:19 -0800538 }
539 for (size_t i = 0; i < 3; ++i) {
540 TestArrayAccessors(arr.get(), i, // Array and index.
541 "", // String value.
542 nullptr, // Const string value.
543 0, // Integer value.
544 0, // Float value.
545 vals[i], // Array value.
546 nullptr, // Dictionary value.
547 nullptr); // Stream value.
548 }
549 }
550 {
551 // Dictionary array.
552 CPDF_Dictionary* vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800553 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800554 for (size_t i = 0; i < 3; ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800555 vals[i] = arr->AddNew<CPDF_Dictionary>();
Wei Libb53a5d2016-02-03 10:04:19 -0800556 for (size_t j = 0; j < 3; ++j) {
557 std::string key("key");
558 char buf[33];
559 key.append(FXSYS_itoa(j, buf, 10));
560 int value = j + 200;
tsepez0e606b52016-11-18 16:22:41 -0800561 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
Wei Libb53a5d2016-02-03 10:04:19 -0800562 }
Wei Libb53a5d2016-02-03 10:04:19 -0800563 }
564 for (size_t i = 0; i < 3; ++i) {
565 TestArrayAccessors(arr.get(), i, // Array and index.
566 "", // String value.
567 nullptr, // Const string value.
568 0, // Integer value.
569 0, // Float value.
570 nullptr, // Array value.
571 vals[i], // Dictionary value.
572 nullptr); // Stream value.
573 }
574 }
575 {
576 // Stream array.
577 CPDF_Dictionary* vals[3];
578 CPDF_Stream* stream_vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800579 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800580 for (size_t i = 0; i < 3; ++i) {
tsepezcd5bca42016-09-30 10:45:06 -0700581 vals[i] = new CPDF_Dictionary();
Wei Libb53a5d2016-02-03 10:04:19 -0800582 for (size_t j = 0; j < 3; ++j) {
583 std::string key("key");
584 char buf[33];
585 key.append(FXSYS_itoa(j, buf, 10));
586 int value = j + 200;
tsepez0e606b52016-11-18 16:22:41 -0800587 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
Wei Libb53a5d2016-02-03 10:04:19 -0800588 }
589 uint8_t content[] = "content: this is a stream";
590 size_t data_size = FX_ArraySize(content);
tsepez47fb8c02016-12-15 13:51:34 -0800591 std::unique_ptr<uint8_t, FxFreeDeleter> data(
592 FX_Alloc(uint8_t, data_size));
593 memcpy(data.get(), content, data_size);
594 stream_vals[i] = arr->AddNew<CPDF_Stream>(std::move(data), data_size,
tsepez9e05ee12016-11-21 13:19:10 -0800595 pdfium::WrapUnique(vals[i]));
Wei Libb53a5d2016-02-03 10:04:19 -0800596 }
597 for (size_t i = 0; i < 3; ++i) {
598 TestArrayAccessors(arr.get(), i, // Array and index.
599 "", // String value.
600 nullptr, // Const string value.
601 0, // Integer value.
602 0, // Float value.
603 nullptr, // Array value.
604 vals[i], // Dictionary value.
605 stream_vals[i]); // Stream value.
606 }
607 }
608 {
609 // Mixed array.
tsepez8a3aa452016-11-16 12:26:06 -0800610 auto arr = pdfium::MakeUnique<CPDF_Array>();
611 arr->InsertNewAt<CPDF_Boolean>(0, true);
612 arr->InsertNewAt<CPDF_Boolean>(1, false);
613 arr->InsertNewAt<CPDF_Number>(2, 0);
614 arr->InsertNewAt<CPDF_Number>(3, -1234);
615 arr->InsertNewAt<CPDF_Number>(4, 2345.0f);
616 arr->InsertNewAt<CPDF_Number>(5, 0.05f);
617 arr->InsertNewAt<CPDF_String>(6, "", false);
618 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false);
619 arr->InsertNewAt<CPDF_Name>(8, "NAME");
620 arr->InsertNewAt<CPDF_Name>(9, "test");
621 arr->InsertNewAt<CPDF_Null>(10);
622
623 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11);
624 arr_val->AddNew<CPDF_Number>(1);
625 arr_val->AddNew<CPDF_Number>(2);
626
627 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12);
tsepez0e606b52016-11-18 16:22:41 -0800628 dict_val->SetNewFor<CPDF_String>("key1", "Linda", false);
629 dict_val->SetNewFor<CPDF_String>("key2", "Zoe", false);
tsepez8a3aa452016-11-16 12:26:06 -0800630
tsepezcd5bca42016-09-30 10:45:06 -0700631 CPDF_Dictionary* stream_dict = new CPDF_Dictionary();
tsepez0e606b52016-11-18 16:22:41 -0800632 stream_dict->SetNewFor<CPDF_String>("key1", "John", false);
633 stream_dict->SetNewFor<CPDF_String>("key2", "King", false);
Wei Libb53a5d2016-02-03 10:04:19 -0800634 uint8_t data[] = "A stream for test";
635 // The data buffer will be owned by stream object, so it needs to be
636 // dynamically allocated.
637 size_t buf_size = sizeof(data);
tsepez47fb8c02016-12-15 13:51:34 -0800638 std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_size));
639 memcpy(buf.get(), data, buf_size);
tsepez9e05ee12016-11-21 13:19:10 -0800640 CPDF_Stream* stream_val = arr->InsertNewAt<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800641 13, std::move(buf), buf_size, pdfium::WrapUnique(stream_dict));
Wei Libb53a5d2016-02-03 10:04:19 -0800642 const char* const expected_str[] = {
643 "true", "false", "0", "-1234", "2345", "0.05", "",
644 "It is a test!", "NAME", "test", "", "", "", ""};
Wei Libb53a5d2016-02-03 10:04:19 -0800645 const int expected_int[] = {1, 0, 0, -1234, 2345, 0, 0,
646 0, 0, 0, 0, 0, 0, 0};
647 const float expected_float[] = {0, 0, 0, -1234, 2345, 0.05f, 0,
648 0, 0, 0, 0, 0, 0, 0};
649 for (size_t i = 0; i < arr->GetCount(); ++i) {
650 EXPECT_STREQ(expected_str[i], arr->GetStringAt(i).c_str());
Wei Libb53a5d2016-02-03 10:04:19 -0800651 EXPECT_EQ(expected_int[i], arr->GetIntegerAt(i));
652 EXPECT_EQ(expected_float[i], arr->GetNumberAt(i));
653 EXPECT_EQ(expected_float[i], arr->GetFloatAt(i));
654 if (i == 11)
655 EXPECT_EQ(arr_val, arr->GetArrayAt(i));
656 else
657 EXPECT_EQ(nullptr, arr->GetArrayAt(i));
658 if (i == 13) {
659 EXPECT_EQ(stream_dict, arr->GetDictAt(i));
660 EXPECT_EQ(stream_val, arr->GetStreamAt(i));
661 } else {
662 EXPECT_EQ(nullptr, arr->GetStreamAt(i));
663 if (i == 12)
664 EXPECT_EQ(dict_val, arr->GetDictAt(i));
665 else
666 EXPECT_EQ(nullptr, arr->GetDictAt(i));
667 }
668 }
669 }
670}
671
672TEST(PDFArrayTest, AddNumber) {
673 float vals[] = {1.0f, -1.0f, 0, 0.456734f,
674 12345.54321f, 0.5f, 1000, 0.000045f};
tsepez8a3aa452016-11-16 12:26:06 -0800675 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800676 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800677 arr->AddNew<CPDF_Number>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800678 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700679 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
680 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800681 }
682}
683
684TEST(PDFArrayTest, AddInteger) {
685 int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100};
tsepez8a3aa452016-11-16 12:26:06 -0800686 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800687 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800688 arr->AddNew<CPDF_Number>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800689 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700690 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
691 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800692 }
693}
694
695TEST(PDFArrayTest, AddStringAndName) {
696 const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323",
697 "$#%^&**", " ", "This is a test.\r\n"};
Dan Sinclair0bb13332017-03-30 16:12:02 -0400698 auto string_array = pdfium::MakeUnique<CPDF_Array>();
699 auto name_array = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800700 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800701 string_array->AddNew<CPDF_String>(vals[i], false);
702 name_array->AddNew<CPDF_Name>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800703 }
704 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700705 EXPECT_EQ(CPDF_Object::STRING, string_array->GetObjectAt(i)->GetType());
706 EXPECT_STREQ(vals[i], string_array->GetObjectAt(i)->GetString().c_str());
707 EXPECT_EQ(CPDF_Object::NAME, name_array->GetObjectAt(i)->GetType());
708 EXPECT_STREQ(vals[i], name_array->GetObjectAt(i)->GetString().c_str());
Wei Libb53a5d2016-02-03 10:04:19 -0800709 }
710}
711
tsepezbd567552016-03-29 14:51:50 -0700712TEST(PDFArrayTest, AddReferenceAndGetObjectAt) {
Dan Sinclair0bb13332017-03-30 16:12:02 -0400713 auto holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
Wei Libb53a5d2016-02-03 10:04:19 -0800714 CPDF_Boolean* boolean_obj = new CPDF_Boolean(true);
715 CPDF_Number* int_obj = new CPDF_Number(-1234);
716 CPDF_Number* float_obj = new CPDF_Number(2345.089f);
tsepez5913a6c2016-11-16 17:31:18 -0800717 CPDF_String* str_obj =
718 new CPDF_String(nullptr, "Adsfdsf 343434 %&&*\n", false);
719 CPDF_Name* name_obj = new CPDF_Name(nullptr, "Title:");
Wei Libb53a5d2016-02-03 10:04:19 -0800720 CPDF_Null* null_obj = new CPDF_Null();
721 CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj,
722 str_obj, name_obj, null_obj};
723 unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1};
tsepez8a3aa452016-11-16 12:26:06 -0800724 auto arr = pdfium::MakeUnique<CPDF_Array>();
Dan Sinclair0bb13332017-03-30 16:12:02 -0400725 auto arr1 = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800726 // Create two arrays of references by different AddReference() APIs.
727 for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) {
tsepez931d0872016-11-04 16:00:03 -0700728 holder->ReplaceIndirectObjectIfHigherGeneration(
729 obj_nums[i], pdfium::WrapUnique<CPDF_Object>(indirect_objs[i]));
tsepez8a3aa452016-11-16 12:26:06 -0800730 arr->AddNew<CPDF_Reference>(holder.get(), obj_nums[i]);
731 arr1->AddNew<CPDF_Reference>(holder.get(), indirect_objs[i]->GetObjNum());
Wei Libb53a5d2016-02-03 10:04:19 -0800732 }
733 // Check indirect objects.
734 for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i)
dsinclair03bd7c72016-08-23 20:13:41 -0700735 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i]));
Wei Libb53a5d2016-02-03 10:04:19 -0800736 // Check arrays.
737 EXPECT_EQ(arr->GetCount(), arr1->GetCount());
738 for (size_t i = 0; i < arr->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700739 EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetObjectAt(i)->GetType());
740 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect());
741 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i));
742 EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetObjectAt(i)->GetType());
743 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect());
744 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i));
Wei Li8f952272016-01-29 18:04:42 -0800745 }
746}
weilia470b5e2016-08-23 22:08:37 -0700747
thestig22b176d2016-08-25 11:14:21 -0700748TEST(PDFArrayTest, CloneDirectObject) {
749 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400750 auto array = pdfium::MakeUnique<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800751 array->AddNew<CPDF_Reference>(&objects_holder, 1234);
thestig22b176d2016-08-25 11:14:21 -0700752 ASSERT_EQ(1U, array->GetCount());
753 CPDF_Object* obj = array->GetObjectAt(0);
754 ASSERT_TRUE(obj);
755 EXPECT_TRUE(obj->IsReference());
756
tsepez335cf092016-11-09 13:28:26 -0800757 std::unique_ptr<CPDF_Object> cloned_array_object = array->CloneDirectObject();
thestig22b176d2016-08-25 11:14:21 -0700758 ASSERT_TRUE(cloned_array_object);
759 ASSERT_TRUE(cloned_array_object->IsArray());
760
tsepez335cf092016-11-09 13:28:26 -0800761 std::unique_ptr<CPDF_Array> cloned_array =
762 ToArray(std::move(cloned_array_object));
Wei Li6bdd8242017-03-23 09:45:04 -0700763 ASSERT_EQ(0U, cloned_array->GetCount());
thestig22b176d2016-08-25 11:14:21 -0700764 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0);
765 EXPECT_FALSE(cloned_obj);
766}
767
tsepez381fc832016-10-10 14:06:44 -0700768TEST(PDFArrayTest, ConvertIndirect) {
769 CPDF_IndirectObjectHolder objects_holder;
tsepez8a3aa452016-11-16 12:26:06 -0800770 auto array = pdfium::MakeUnique<CPDF_Array>();
771 CPDF_Object* pObj = array->AddNew<CPDF_Number>(42);
tsepez381fc832016-10-10 14:06:44 -0700772 array->ConvertToIndirectObjectAt(0, &objects_holder);
773 CPDF_Object* pRef = array->GetObjectAt(0);
774 CPDF_Object* pNum = array->GetDirectObjectAt(0);
775 EXPECT_TRUE(pRef->IsReference());
776 EXPECT_TRUE(pNum->IsNumber());
777 EXPECT_NE(pObj, pRef);
778 EXPECT_EQ(pObj, pNum);
779 EXPECT_EQ(42, array->GetIntegerAt(0));
780}
781
thestig22b176d2016-08-25 11:14:21 -0700782TEST(PDFDictionaryTest, CloneDirectObject) {
783 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400784 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800785 dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234);
thestig22b176d2016-08-25 11:14:21 -0700786 ASSERT_EQ(1U, dict->GetCount());
dsinclair38fd8442016-09-15 10:15:32 -0700787 CPDF_Object* obj = dict->GetObjectFor("foo");
thestig22b176d2016-08-25 11:14:21 -0700788 ASSERT_TRUE(obj);
789 EXPECT_TRUE(obj->IsReference());
790
tsepez335cf092016-11-09 13:28:26 -0800791 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject();
thestig22b176d2016-08-25 11:14:21 -0700792 ASSERT_TRUE(cloned_dict_object);
793 ASSERT_TRUE(cloned_dict_object->IsDictionary());
794
tsepez335cf092016-11-09 13:28:26 -0800795 std::unique_ptr<CPDF_Dictionary> cloned_dict =
796 ToDictionary(std::move(cloned_dict_object));
Wei Li6bdd8242017-03-23 09:45:04 -0700797 ASSERT_EQ(0U, cloned_dict->GetCount());
dsinclair38fd8442016-09-15 10:15:32 -0700798 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
thestig22b176d2016-08-25 11:14:21 -0700799 EXPECT_FALSE(cloned_obj);
800}
801
weilia470b5e2016-08-23 22:08:37 -0700802TEST(PDFObjectTest, CloneCheckLoop) {
803 {
tsepez0e606b52016-11-18 16:22:41 -0800804 // Create a dictionary/array pair with a reference loop. It takes
805 // some work to do this nowadays, in particular we need the
806 // anti-pattern pdfium::WrapUnique(arr.get()).
tsepez8a3aa452016-11-16 12:26:06 -0800807 auto arr_obj = pdfium::MakeUnique<CPDF_Array>();
808 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0);
tsepez0e606b52016-11-18 16:22:41 -0800809 dict_obj->SetFor("arr", pdfium::WrapUnique(arr_obj.get()));
weilia470b5e2016-08-23 22:08:37 -0700810 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800811 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone());
weilia470b5e2016-08-23 22:08:37 -0700812 // Cloned object should be the same as the original.
813 ASSERT_TRUE(cloned_array);
814 EXPECT_EQ(1u, cloned_array->GetCount());
815 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0);
816 ASSERT_TRUE(cloned_dict);
817 ASSERT_TRUE(cloned_dict->IsDictionary());
818 // Recursively referenced object is not cloned.
dsinclair38fd8442016-09-15 10:15:32 -0700819 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr"));
weilia470b5e2016-08-23 22:08:37 -0700820 }
821 {
tsepez9e05ee12016-11-21 13:19:10 -0800822 // Create a dictionary/stream pair with a reference loop. It takes
823 // some work to do this nowadays, in particular we need the
824 // anti-pattern pdfium::WrapUnique(dict.get()).
tsepez0e606b52016-11-18 16:22:41 -0800825 auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez9e05ee12016-11-21 13:19:10 -0800826 CPDF_Stream* stream_obj = dict_obj->SetNewFor<CPDF_Stream>(
827 "stream", nullptr, 0, pdfium::WrapUnique(dict_obj.get()));
tsepez836f7d52016-10-10 14:31:05 -0700828 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800829 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone());
tsepez836f7d52016-10-10 14:31:05 -0700830 // Cloned object should be the same as the original.
831 ASSERT_TRUE(cloned_stream);
832 CPDF_Object* cloned_dict = cloned_stream->GetDict();
833 ASSERT_TRUE(cloned_dict);
834 ASSERT_TRUE(cloned_dict->IsDictionary());
835 // Recursively referenced object is not cloned.
836 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream"));
837 }
838 {
thestig22b176d2016-08-25 11:14:21 -0700839 CPDF_IndirectObjectHolder objects_holder;
weilia470b5e2016-08-23 22:08:37 -0700840 // Create an object with a reference loop.
tsepez70c4afd2016-11-15 11:33:44 -0800841 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>();
842 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800843 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder,
844 dict_obj->GetObjNum());
weilia470b5e2016-08-23 22:08:37 -0700845 CPDF_Object* elem0 = arr_obj->GetObjectAt(0);
tsepez0e606b52016-11-18 16:22:41 -0800846 dict_obj->SetFor("arr", std::move(arr_obj));
tsepez70c4afd2016-11-15 11:33:44 -0800847 EXPECT_EQ(1u, dict_obj->GetObjNum());
weilia470b5e2016-08-23 22:08:37 -0700848 ASSERT_TRUE(elem0);
849 ASSERT_TRUE(elem0->IsReference());
850 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum());
851 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect());
852
853 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800854 std::unique_ptr<CPDF_Dictionary> cloned_dict =
855 ToDictionary(dict_obj->CloneDirectObject());
weilia470b5e2016-08-23 22:08:37 -0700856 // Cloned object should be the same as the original.
857 ASSERT_TRUE(cloned_dict);
dsinclair38fd8442016-09-15 10:15:32 -0700858 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr");
weilia470b5e2016-08-23 22:08:37 -0700859 ASSERT_TRUE(cloned_arr);
860 ASSERT_TRUE(cloned_arr->IsArray());
Wei Li6bdd8242017-03-23 09:45:04 -0700861 EXPECT_EQ(0U, cloned_arr->AsArray()->GetCount());
weilia470b5e2016-08-23 22:08:37 -0700862 // Recursively referenced object is not cloned.
863 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0));
864 }
865}
tsepez381fc832016-10-10 14:06:44 -0700866
867TEST(PDFDictionaryTest, ConvertIndirect) {
868 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400869 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800870 CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
tsepez381fc832016-10-10 14:06:44 -0700871 dict->ConvertToIndirectObjectFor("clams", &objects_holder);
872 CPDF_Object* pRef = dict->GetObjectFor("clams");
873 CPDF_Object* pNum = dict->GetDirectObjectFor("clams");
874 EXPECT_TRUE(pRef->IsReference());
875 EXPECT_TRUE(pNum->IsNumber());
876 EXPECT_NE(pObj, pRef);
877 EXPECT_EQ(pObj, pNum);
878 EXPECT_EQ(42, dict->GetIntegerFor("clams"));
879}