blob: 4780e87bc0e07eda295c18774e42bcd7e4f27a0e [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
Dan Sinclairbcd1e702017-08-31 13:19:18 -04005#include <memory>
6#include <string>
7#include <utility>
8#include <vector>
9
Lei Zhang26170562018-04-17 17:01:52 +000010#include "constants/stream_dict_common.h"
dsinclair488b7ad2016-10-04 11:55:50 -070011#include "core/fpdfapi/parser/cpdf_array.h"
12#include "core/fpdfapi/parser/cpdf_boolean.h"
13#include "core/fpdfapi/parser/cpdf_dictionary.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040014#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
dsinclair488b7ad2016-10-04 11:55:50 -070015#include "core/fpdfapi/parser/cpdf_name.h"
16#include "core/fpdfapi/parser/cpdf_null.h"
17#include "core/fpdfapi/parser/cpdf_number.h"
18#include "core/fpdfapi/parser/cpdf_reference.h"
19#include "core/fpdfapi/parser/cpdf_stream.h"
20#include "core/fpdfapi/parser/cpdf_string.h"
Lei Zhang94293682016-01-27 18:27:56 -080021#include "testing/gtest/include/gtest/gtest.h"
22
Wei Libb53a5d2016-02-03 10:04:19 -080023namespace {
24
Wei Libb53a5d2016-02-03 10:04:19 -080025void TestArrayAccessors(const CPDF_Array* arr,
26 size_t index,
27 const char* str_val,
28 const char* const_str_val,
29 int int_val,
30 float float_val,
31 CPDF_Array* arr_val,
32 CPDF_Dictionary* dict_val,
33 CPDF_Stream* stream_val) {
34 EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str());
Wei Libb53a5d2016-02-03 10:04:19 -080035 EXPECT_EQ(int_val, arr->GetIntegerAt(index));
36 EXPECT_EQ(float_val, arr->GetNumberAt(index));
37 EXPECT_EQ(float_val, arr->GetFloatAt(index));
38 EXPECT_EQ(arr_val, arr->GetArrayAt(index));
39 EXPECT_EQ(dict_val, arr->GetDictAt(index));
40 EXPECT_EQ(stream_val, arr->GetStreamAt(index));
41}
42
43} // namespace
44
Lei Zhang94293682016-01-27 18:27:56 -080045class PDFObjectsTest : public testing::Test {
46 public:
47 void SetUp() override {
48 // Initialize different kinds of objects.
49 // Boolean objects.
50 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
51 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
52 // Number objects.
53 CPDF_Number* number_int_obj = new CPDF_Number(1245);
54 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
55 // String objects.
tsepez0e606b52016-11-18 16:22:41 -080056 CPDF_String* str_reg_obj = new CPDF_String(nullptr, L"A simple test");
57 CPDF_String* str_spec_obj = new CPDF_String(nullptr, L"\t\n");
Lei Zhang94293682016-01-27 18:27:56 -080058 // Name object.
tsepez5913a6c2016-11-16 17:31:18 -080059 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space");
Lei Zhang94293682016-01-27 18:27:56 -080060 // Array object.
Wei Li8f952272016-01-29 18:04:42 -080061 m_ArrayObj = new CPDF_Array;
tsepez8a3aa452016-11-16 12:26:06 -080062 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902);
63 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address");
Lei Zhang94293682016-01-27 18:27:56 -080064 // Dictionary object.
tsepezcd5bca42016-09-30 10:45:06 -070065 m_DictObj = new CPDF_Dictionary();
tsepez0e606b52016-11-18 16:22:41 -080066 m_DictObj->SetNewFor<CPDF_Boolean>("bool", false);
67 m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f);
Lei Zhang94293682016-01-27 18:27:56 -080068 // Stream object.
69 const char content[] = "abcdefghijklmnopqrstuvwxyz";
70 size_t buf_len = FX_ArraySize(content);
tsepez47fb8c02016-12-15 13:51:34 -080071 std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
72 memcpy(buf.get(), content, buf_len);
tsepez9e05ee12016-11-21 13:19:10 -080073 auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>();
74 m_StreamDictObj = pNewDict.get();
tsepez0e606b52016-11-18 16:22:41 -080075 m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict");
76 m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1);
tsepez9e05ee12016-11-21 13:19:10 -080077 CPDF_Stream* stream_obj =
tsepez47fb8c02016-12-15 13:51:34 -080078 new CPDF_Stream(std::move(buf), buf_len, std::move(pNewDict));
Lei Zhang94293682016-01-27 18:27:56 -080079 // Null Object.
80 CPDF_Null* null_obj = new CPDF_Null;
81 // All direct objects.
82 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
83 number_float_obj, str_reg_obj, str_spec_obj,
Tom Sepezd0409af2017-05-25 15:53:57 -070084 name_obj, m_ArrayObj.Get(), m_DictObj.Get(),
Lei Zhang94293682016-01-27 18:27:56 -080085 stream_obj, null_obj};
Wei Li8f952272016-01-29 18:04:42 -080086 m_DirectObjTypes = {
87 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER,
88 CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING,
89 CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY,
90 CPDF_Object::STREAM, CPDF_Object::NULLOBJ};
91 for (size_t i = 0; i < FX_ArraySize(objs); ++i)
Lei Zhang94293682016-01-27 18:27:56 -080092 m_DirectObjs.emplace_back(objs[i]);
93
94 // Indirect references to indirect objects.
tsepez70c4afd2016-11-15 11:33:44 -080095 m_ObjHolder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
96 m_IndirectObjs = {m_ObjHolder->AddIndirectObject(boolean_true_obj->Clone()),
97 m_ObjHolder->AddIndirectObject(number_int_obj->Clone()),
98 m_ObjHolder->AddIndirectObject(str_spec_obj->Clone()),
99 m_ObjHolder->AddIndirectObject(name_obj->Clone()),
100 m_ObjHolder->AddIndirectObject(m_ArrayObj->Clone()),
101 m_ObjHolder->AddIndirectObject(m_DictObj->Clone()),
102 m_ObjHolder->AddIndirectObject(stream_obj->Clone())};
103 for (CPDF_Object* pObj : m_IndirectObjs) {
104 m_RefObjs.emplace_back(
105 new CPDF_Reference(m_ObjHolder.get(), pObj->GetObjNum()));
Lei Zhang94293682016-01-27 18:27:56 -0800106 }
107 }
108
tsepez836f7d52016-10-10 14:31:05 -0700109 bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) {
Wei Li8f952272016-01-29 18:04:42 -0800110 if (obj1 == obj2)
111 return true;
112 if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType())
113 return false;
114 switch (obj1->GetType()) {
115 case CPDF_Object::BOOLEAN:
116 return obj1->GetInteger() == obj2->GetInteger();
117 case CPDF_Object::NUMBER:
118 return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() &&
119 obj1->GetInteger() == obj2->GetInteger();
120 case CPDF_Object::STRING:
121 case CPDF_Object::NAME:
122 return obj1->GetString() == obj2->GetString();
123 case CPDF_Object::ARRAY: {
124 const CPDF_Array* array1 = obj1->AsArray();
125 const CPDF_Array* array2 = obj2->AsArray();
126 if (array1->GetCount() != array2->GetCount())
127 return false;
128 for (size_t i = 0; i < array1->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700129 if (!Equal(array1->GetObjectAt(i), array2->GetObjectAt(i)))
Wei Li8f952272016-01-29 18:04:42 -0800130 return false;
131 }
132 return true;
133 }
134 case CPDF_Object::DICTIONARY: {
135 const CPDF_Dictionary* dict1 = obj1->AsDictionary();
136 const CPDF_Dictionary* dict2 = obj2->AsDictionary();
137 if (dict1->GetCount() != dict2->GetCount())
138 return false;
139 for (CPDF_Dictionary::const_iterator it = dict1->begin();
140 it != dict1->end(); ++it) {
tsepez0e606b52016-11-18 16:22:41 -0800141 if (!Equal(it->second.get(), dict2->GetObjectFor(it->first)))
Wei Li8f952272016-01-29 18:04:42 -0800142 return false;
143 }
144 return true;
145 }
146 case CPDF_Object::NULLOBJ:
147 return true;
148 case CPDF_Object::STREAM: {
149 const CPDF_Stream* stream1 = obj1->AsStream();
150 const CPDF_Stream* stream2 = obj2->AsStream();
151 if (!stream1->GetDict() && !stream2->GetDict())
152 return true;
153 // Compare dictionaries.
154 if (!Equal(stream1->GetDict(), stream2->GetDict()))
155 return false;
156 // Compare sizes.
157 if (stream1->GetRawSize() != stream2->GetRawSize())
158 return false;
159 // Compare contents.
160 // Since this function is used for testing Clone(), only memory based
161 // streams need to be handled.
162 if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased())
163 return false;
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400164 return memcmp(stream1->GetRawData(), stream2->GetRawData(),
165 stream1->GetRawSize()) == 0;
Wei Li8f952272016-01-29 18:04:42 -0800166 }
167 case CPDF_Object::REFERENCE:
168 return obj1->AsReference()->GetRefObjNum() ==
169 obj2->AsReference()->GetRefObjNum();
170 }
171 return false;
172 }
173
Lei Zhang94293682016-01-27 18:27:56 -0800174 protected:
Lei Zhang94293682016-01-27 18:27:56 -0800175 // m_ObjHolder needs to be declared first and destructed last since it also
176 // refers to some objects in m_DirectObjs.
177 std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder;
tsepez33fdebc2016-11-04 11:38:40 -0700178 std::vector<std::unique_ptr<CPDF_Object>> m_DirectObjs;
Wei Li8f952272016-01-29 18:04:42 -0800179 std::vector<int> m_DirectObjTypes;
tsepez33fdebc2016-11-04 11:38:40 -0700180 std::vector<std::unique_ptr<CPDF_Object>> m_RefObjs;
Dan Sinclairaee0db02017-09-21 16:53:58 -0400181 UnownedPtr<CPDF_Dictionary> m_DictObj;
182 UnownedPtr<CPDF_Dictionary> m_StreamDictObj;
183 UnownedPtr<CPDF_Array> m_ArrayObj;
Wei Li8f952272016-01-29 18:04:42 -0800184 std::vector<CPDF_Object*> m_IndirectObjs;
Lei Zhang94293682016-01-27 18:27:56 -0800185};
186
187TEST_F(PDFObjectsTest, GetString) {
thestigb8bf55f2016-05-21 21:08:05 -0700188 const char* const direct_obj_results[] = {
Lei Zhang94293682016-01-27 18:27:56 -0800189 "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space",
190 "", "", "", ""};
191 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800192 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800193 EXPECT_STREQ(direct_obj_results[i], m_DirectObjs[i]->GetString().c_str());
Lei Zhang94293682016-01-27 18:27:56 -0800194
195 // Check indirect references.
thestigb8bf55f2016-05-21 21:08:05 -0700196 const char* const indirect_obj_results[] = {"true", "1245", "\t\n", "space",
197 "", "", ""};
Wei Li8f952272016-01-29 18:04:42 -0800198 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
Wei Libb53a5d2016-02-03 10:04:19 -0800199 EXPECT_STREQ(indirect_obj_results[i], m_RefObjs[i]->GetString().c_str());
Lei Zhang94293682016-01-27 18:27:56 -0800200 }
201}
202
Wei Li8f952272016-01-29 18:04:42 -0800203TEST_F(PDFObjectsTest, GetUnicodeText) {
thestigb8bf55f2016-05-21 21:08:05 -0700204 const wchar_t* const direct_obj_results[] = {
Wei Li8f952272016-01-29 18:04:42 -0800205 L"", L"", L"", L"", L"A simple test",
206 L"\t\n", L"space", L"", L"", L"abcdefghijklmnopqrstuvwxyz",
207 L""};
208 // Check for direct objects.
dsinclair685bb882016-04-20 07:32:39 -0700209 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
Wei Libb53a5d2016-02-03 10:04:19 -0800210 EXPECT_STREQ(direct_obj_results[i],
211 m_DirectObjs[i]->GetUnicodeText().c_str());
dsinclair685bb882016-04-20 07:32:39 -0700212 }
Wei Li8f952272016-01-29 18:04:42 -0800213
214 // Check indirect references.
215 for (const auto& it : m_RefObjs)
Wei Libb53a5d2016-02-03 10:04:19 -0800216 EXPECT_STREQ(L"", it->GetUnicodeText().c_str());
Wei Li8f952272016-01-29 18:04:42 -0800217}
218
Lei Zhang94293682016-01-27 18:27:56 -0800219TEST_F(PDFObjectsTest, GetNumber) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400220 const float direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0,
221 0, 0, 0, 0, 0};
Lei Zhang94293682016-01-27 18:27:56 -0800222 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800223 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800224 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber());
Lei Zhang94293682016-01-27 18:27:56 -0800225
226 // Check indirect references.
Dan Sinclair05df0752017-03-14 14:43:42 -0400227 const float indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0};
Wei Li8f952272016-01-29 18:04:42 -0800228 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800229 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber());
Lei Zhang94293682016-01-27 18:27:56 -0800230}
231
232TEST_F(PDFObjectsTest, GetInteger) {
233 const int direct_obj_results[] = {0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0};
234 // Check for direct objects.
Wei Li8f952272016-01-29 18:04:42 -0800235 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800236 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetInteger());
Lei Zhang94293682016-01-27 18:27:56 -0800237
238 // Check indirect references.
239 const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0};
Wei Li8f952272016-01-29 18:04:42 -0800240 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800241 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetInteger());
Lei Zhang94293682016-01-27 18:27:56 -0800242}
243
244TEST_F(PDFObjectsTest, GetDict) {
thestigb8bf55f2016-05-21 21:08:05 -0700245 const CPDF_Dictionary* const direct_obj_results[] = {
Tom Sepezd0409af2017-05-25 15:53:57 -0700246 nullptr, nullptr, nullptr, nullptr, nullptr,
247 nullptr, nullptr, nullptr, m_DictObj.Get(), m_StreamDictObj.Get(),
248 nullptr};
Lei Zhang94293682016-01-27 18:27:56 -0800249 // 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.
Tom Sepezd0409af2017-05-25 15:53:57 -0700254 const CPDF_Dictionary* const indirect_obj_results[] = {nullptr,
255 nullptr,
256 nullptr,
257 nullptr,
258 nullptr,
259 m_DictObj.Get(),
260 m_StreamDictObj.Get()};
Wei Li8f952272016-01-29 18:04:42 -0800261 for (size_t i = 0; i < m_RefObjs.size(); ++i)
tsepez836f7d52016-10-10 14:31:05 -0700262 EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict()));
Lei Zhang94293682016-01-27 18:27:56 -0800263}
Wei Li8f952272016-01-29 18:04:42 -0800264
265TEST_F(PDFObjectsTest, GetArray) {
thestigb8bf55f2016-05-21 21:08:05 -0700266 const CPDF_Array* const direct_obj_results[] = {
Tom Sepezd0409af2017-05-25 15:53:57 -0700267 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
268 nullptr, m_ArrayObj.Get(), nullptr, nullptr, nullptr};
Wei Li8f952272016-01-29 18:04:42 -0800269 // Check for direct objects.
270 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
thestigb8bf55f2016-05-21 21:08:05 -0700271 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800272
273 // Check indirect references.
274 for (const auto& it : m_RefObjs)
thestigb8bf55f2016-05-21 21:08:05 -0700275 EXPECT_EQ(nullptr, it->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800276}
277
278TEST_F(PDFObjectsTest, Clone) {
279 // Check for direct objects.
280 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
tsepez335cf092016-11-09 13:28:26 -0800281 std::unique_ptr<CPDF_Object> obj = m_DirectObjs[i]->Clone();
Wei Li8f952272016-01-29 18:04:42 -0800282 EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get()));
283 }
284
285 // Check indirect references.
286 for (const auto& it : m_RefObjs) {
tsepez335cf092016-11-09 13:28:26 -0800287 std::unique_ptr<CPDF_Object> obj = it->Clone();
Wei Li8f952272016-01-29 18:04:42 -0800288 EXPECT_TRUE(Equal(it.get(), obj.get()));
289 }
290}
291
292TEST_F(PDFObjectsTest, GetType) {
293 // Check for direct objects.
294 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800295 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType());
Wei Li8f952272016-01-29 18:04:42 -0800296
297 // Check indirect references.
298 for (const auto& it : m_RefObjs)
Wei Libb53a5d2016-02-03 10:04:19 -0800299 EXPECT_EQ(CPDF_Object::REFERENCE, it->GetType());
Wei Li8f952272016-01-29 18:04:42 -0800300}
301
302TEST_F(PDFObjectsTest, GetDirect) {
303 // Check for direct objects.
304 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800305 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->GetDirect());
Wei Li8f952272016-01-29 18:04:42 -0800306
307 // Check indirect references.
308 for (size_t i = 0; i < m_RefObjs.size(); ++i)
Wei Libb53a5d2016-02-03 10:04:19 -0800309 EXPECT_EQ(m_IndirectObjs[i], m_RefObjs[i]->GetDirect());
Wei Li8f952272016-01-29 18:04:42 -0800310}
311
312TEST_F(PDFObjectsTest, SetString) {
313 // Check for direct objects.
314 const char* const set_values[] = {"true", "fake", "3.125f", "097",
315 "changed", "", "NewName"};
thestigb8bf55f2016-05-21 21:08:05 -0700316 const char* const expected[] = {"true", "false", "3.125", "97",
317 "changed", "", "NewName"};
Wei Li8f952272016-01-29 18:04:42 -0800318 for (size_t i = 0; i < FX_ArraySize(set_values); ++i) {
319 m_DirectObjs[i]->SetString(set_values[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800320 EXPECT_STREQ(expected[i], m_DirectObjs[i]->GetString().c_str());
Wei Li8f952272016-01-29 18:04:42 -0800321 }
322}
323
324TEST_F(PDFObjectsTest, IsTypeAndAsType) {
325 // Check for direct objects.
326 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
327 if (m_DirectObjTypes[i] == CPDF_Object::ARRAY) {
328 EXPECT_TRUE(m_DirectObjs[i]->IsArray());
Wei Libb53a5d2016-02-03 10:04:19 -0800329 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800330 } else {
331 EXPECT_FALSE(m_DirectObjs[i]->IsArray());
Wei Libb53a5d2016-02-03 10:04:19 -0800332 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsArray());
Wei Li8f952272016-01-29 18:04:42 -0800333 }
334
335 if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) {
336 EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
Wei Libb53a5d2016-02-03 10:04:19 -0800337 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsBoolean());
Wei Li8f952272016-01-29 18:04:42 -0800338 } else {
339 EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
Wei Libb53a5d2016-02-03 10:04:19 -0800340 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsBoolean());
Wei Li8f952272016-01-29 18:04:42 -0800341 }
342
343 if (m_DirectObjTypes[i] == CPDF_Object::NAME) {
344 EXPECT_TRUE(m_DirectObjs[i]->IsName());
Wei Libb53a5d2016-02-03 10:04:19 -0800345 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsName());
Wei Li8f952272016-01-29 18:04:42 -0800346 } else {
347 EXPECT_FALSE(m_DirectObjs[i]->IsName());
Wei Libb53a5d2016-02-03 10:04:19 -0800348 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsName());
Wei Li8f952272016-01-29 18:04:42 -0800349 }
350
351 if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) {
352 EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800353 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsNumber());
Wei Li8f952272016-01-29 18:04:42 -0800354 } else {
355 EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800356 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsNumber());
Wei Li8f952272016-01-29 18:04:42 -0800357 }
358
359 if (m_DirectObjTypes[i] == CPDF_Object::STRING) {
360 EXPECT_TRUE(m_DirectObjs[i]->IsString());
Wei Libb53a5d2016-02-03 10:04:19 -0800361 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsString());
Wei Li8f952272016-01-29 18:04:42 -0800362 } else {
363 EXPECT_FALSE(m_DirectObjs[i]->IsString());
Wei Libb53a5d2016-02-03 10:04:19 -0800364 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsString());
Wei Li8f952272016-01-29 18:04:42 -0800365 }
366
367 if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) {
368 EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
Wei Libb53a5d2016-02-03 10:04:19 -0800369 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsDictionary());
Wei Li8f952272016-01-29 18:04:42 -0800370 } else {
371 EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
Wei Libb53a5d2016-02-03 10:04:19 -0800372 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsDictionary());
Wei Li8f952272016-01-29 18:04:42 -0800373 }
374
375 if (m_DirectObjTypes[i] == CPDF_Object::STREAM) {
376 EXPECT_TRUE(m_DirectObjs[i]->IsStream());
Wei Libb53a5d2016-02-03 10:04:19 -0800377 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsStream());
Wei Li8f952272016-01-29 18:04:42 -0800378 } else {
379 EXPECT_FALSE(m_DirectObjs[i]->IsStream());
Wei Libb53a5d2016-02-03 10:04:19 -0800380 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsStream());
Wei Li8f952272016-01-29 18:04:42 -0800381 }
382
383 EXPECT_FALSE(m_DirectObjs[i]->IsReference());
Wei Libb53a5d2016-02-03 10:04:19 -0800384 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsReference());
Wei Li8f952272016-01-29 18:04:42 -0800385 }
386 // Check indirect references.
387 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
388 EXPECT_TRUE(m_RefObjs[i]->IsReference());
Wei Libb53a5d2016-02-03 10:04:19 -0800389 EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference());
390 }
391}
392
393TEST(PDFArrayTest, GetMatrix) {
394 float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
395 {1, 2, 3, 4, 5, 6},
396 {2.3f, 4.05f, 3, -2, -3, 0.0f},
397 {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}};
398 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800399 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800400 CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3],
401 elems[i][4], elems[i][5]);
402 for (size_t j = 0; j < 6; ++j)
tsepez8a3aa452016-11-16 12:26:06 -0800403 arr->AddNew<CPDF_Number>(elems[i][j]);
Wei Libb53a5d2016-02-03 10:04:19 -0800404 CFX_Matrix arr_matrix = arr->GetMatrix();
Dan Sinclair687a79c2017-02-09 14:08:53 -0500405 EXPECT_EQ(matrix.a, arr_matrix.a);
406 EXPECT_EQ(matrix.b, arr_matrix.b);
407 EXPECT_EQ(matrix.c, arr_matrix.c);
408 EXPECT_EQ(matrix.d, arr_matrix.d);
409 EXPECT_EQ(matrix.e, arr_matrix.e);
410 EXPECT_EQ(matrix.f, arr_matrix.f);
Wei Libb53a5d2016-02-03 10:04:19 -0800411 }
412}
413
414TEST(PDFArrayTest, GetRect) {
415 float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
416 {1, 2, 5, 6},
417 {2.3f, 4.05f, -3, 0.0f},
418 {0.05f, 0.1f, 1.34f, 99.9f}};
419 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800420 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800421 CFX_FloatRect rect(elems[i]);
422 for (size_t j = 0; j < 4; ++j)
tsepez8a3aa452016-11-16 12:26:06 -0800423 arr->AddNew<CPDF_Number>(elems[i][j]);
Wei Libb53a5d2016-02-03 10:04:19 -0800424 CFX_FloatRect arr_rect = arr->GetRect();
425 EXPECT_EQ(rect.left, arr_rect.left);
426 EXPECT_EQ(rect.right, arr_rect.right);
427 EXPECT_EQ(rect.bottom, arr_rect.bottom);
428 EXPECT_EQ(rect.top, arr_rect.top);
429 }
430}
431
432TEST(PDFArrayTest, GetTypeAt) {
433 {
434 // Boolean array.
thestigb8bf55f2016-05-21 21:08:05 -0700435 const bool vals[] = {true, false, false, true, true};
tsepez8a3aa452016-11-16 12:26:06 -0800436 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800437 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800438 arr->InsertNewAt<CPDF_Boolean>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800439 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
440 TestArrayAccessors(arr.get(), i, // Array and index.
441 vals[i] ? "true" : "false", // String value.
442 nullptr, // Const string value.
443 vals[i] ? 1 : 0, // Integer value.
444 0, // Float value.
445 nullptr, // Array value.
446 nullptr, // Dictionary value.
447 nullptr); // Stream value.
448 }
449 }
450 {
451 // Integer array.
thestigb8bf55f2016-05-21 21:08:05 -0700452 const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767};
tsepez8a3aa452016-11-16 12:26:06 -0800453 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800454 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800455 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800456 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
457 char buf[33];
458 TestArrayAccessors(arr.get(), i, // Array and index.
459 FXSYS_itoa(vals[i], buf, 10), // String value.
460 nullptr, // Const string value.
461 vals[i], // Integer value.
462 vals[i], // Float value.
463 nullptr, // Array value.
464 nullptr, // Dictionary value.
465 nullptr); // Stream value.
466 }
467 }
468 {
469 // Float array.
thestigb8bf55f2016-05-21 21:08:05 -0700470 const float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f,
471 897.34f, -2.5f, -1.0f, -345.0f, -0.0f};
472 const char* const expected_str[] = {
473 "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"};
tsepez8a3aa452016-11-16 12:26:06 -0800474 auto arr = pdfium::MakeUnique<CPDF_Array>();
475 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
476 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800477 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
478 TestArrayAccessors(arr.get(), i, // Array and index.
479 expected_str[i], // String value.
480 nullptr, // Const string value.
481 vals[i], // Integer value.
482 vals[i], // Float value.
483 nullptr, // Array value.
484 nullptr, // Dictionary value.
485 nullptr); // Stream value.
486 }
487 }
488 {
489 // String and name array
490 const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012",
491 ".", "EYREW", "It is a joke :)"};
Dan Sinclair0bb13332017-03-30 16:12:02 -0400492 auto string_array = pdfium::MakeUnique<CPDF_Array>();
493 auto name_array = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800494 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800495 string_array->InsertNewAt<CPDF_String>(i, vals[i], false);
496 name_array->InsertNewAt<CPDF_Name>(i, vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800497 }
498 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
499 TestArrayAccessors(string_array.get(), i, // Array and index.
500 vals[i], // String value.
501 vals[i], // Const string value.
502 0, // Integer value.
503 0, // Float value.
504 nullptr, // Array value.
505 nullptr, // Dictionary value.
506 nullptr); // Stream value.
507 TestArrayAccessors(name_array.get(), i, // Array and index.
508 vals[i], // String value.
509 vals[i], // Const string value.
510 0, // Integer value.
511 0, // Float value.
512 nullptr, // Array value.
513 nullptr, // Dictionary value.
514 nullptr); // Stream value.
515 }
516 }
517 {
518 // Null element array.
tsepez8a3aa452016-11-16 12:26:06 -0800519 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800520 for (size_t i = 0; i < 3; ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800521 arr->InsertNewAt<CPDF_Null>(i);
Wei Libb53a5d2016-02-03 10:04:19 -0800522 for (size_t i = 0; i < 3; ++i) {
523 TestArrayAccessors(arr.get(), i, // Array and index.
524 "", // String value.
525 nullptr, // Const string value.
526 0, // Integer value.
527 0, // Float value.
528 nullptr, // Array value.
529 nullptr, // Dictionary value.
530 nullptr); // Stream value.
531 }
532 }
533 {
534 // Array of array.
535 CPDF_Array* vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800536 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800537 for (size_t i = 0; i < 3; ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800538 vals[i] = arr->AddNew<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800539 for (size_t j = 0; j < 3; ++j) {
540 int value = j + 100;
tsepez8a3aa452016-11-16 12:26:06 -0800541 vals[i]->InsertNewAt<CPDF_Number>(i, value);
Wei Libb53a5d2016-02-03 10:04:19 -0800542 }
Wei Libb53a5d2016-02-03 10:04:19 -0800543 }
544 for (size_t i = 0; i < 3; ++i) {
545 TestArrayAccessors(arr.get(), i, // Array and index.
546 "", // String value.
547 nullptr, // Const string value.
548 0, // Integer value.
549 0, // Float value.
550 vals[i], // Array value.
551 nullptr, // Dictionary value.
552 nullptr); // Stream value.
553 }
554 }
555 {
556 // Dictionary array.
557 CPDF_Dictionary* vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800558 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800559 for (size_t i = 0; i < 3; ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800560 vals[i] = arr->AddNew<CPDF_Dictionary>();
Wei Libb53a5d2016-02-03 10:04:19 -0800561 for (size_t j = 0; j < 3; ++j) {
562 std::string key("key");
563 char buf[33];
564 key.append(FXSYS_itoa(j, buf, 10));
565 int value = j + 200;
tsepez0e606b52016-11-18 16:22:41 -0800566 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
Wei Libb53a5d2016-02-03 10:04:19 -0800567 }
Wei Libb53a5d2016-02-03 10:04:19 -0800568 }
569 for (size_t i = 0; i < 3; ++i) {
570 TestArrayAccessors(arr.get(), i, // Array and index.
571 "", // String value.
572 nullptr, // Const string value.
573 0, // Integer value.
574 0, // Float value.
575 nullptr, // Array value.
576 vals[i], // Dictionary value.
577 nullptr); // Stream value.
578 }
579 }
580 {
581 // Stream array.
582 CPDF_Dictionary* vals[3];
583 CPDF_Stream* stream_vals[3];
tsepez8a3aa452016-11-16 12:26:06 -0800584 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800585 for (size_t i = 0; i < 3; ++i) {
tsepezcd5bca42016-09-30 10:45:06 -0700586 vals[i] = new CPDF_Dictionary();
Wei Libb53a5d2016-02-03 10:04:19 -0800587 for (size_t j = 0; j < 3; ++j) {
588 std::string key("key");
589 char buf[33];
590 key.append(FXSYS_itoa(j, buf, 10));
591 int value = j + 200;
tsepez0e606b52016-11-18 16:22:41 -0800592 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
Wei Libb53a5d2016-02-03 10:04:19 -0800593 }
594 uint8_t content[] = "content: this is a stream";
595 size_t data_size = FX_ArraySize(content);
tsepez47fb8c02016-12-15 13:51:34 -0800596 std::unique_ptr<uint8_t, FxFreeDeleter> data(
597 FX_Alloc(uint8_t, data_size));
598 memcpy(data.get(), content, data_size);
599 stream_vals[i] = arr->AddNew<CPDF_Stream>(std::move(data), data_size,
tsepez9e05ee12016-11-21 13:19:10 -0800600 pdfium::WrapUnique(vals[i]));
Wei Libb53a5d2016-02-03 10:04:19 -0800601 }
602 for (size_t i = 0; i < 3; ++i) {
603 TestArrayAccessors(arr.get(), i, // Array and index.
604 "", // String value.
605 nullptr, // Const string value.
606 0, // Integer value.
607 0, // Float value.
608 nullptr, // Array value.
609 vals[i], // Dictionary value.
610 stream_vals[i]); // Stream value.
611 }
612 }
613 {
614 // Mixed array.
tsepez8a3aa452016-11-16 12:26:06 -0800615 auto arr = pdfium::MakeUnique<CPDF_Array>();
616 arr->InsertNewAt<CPDF_Boolean>(0, true);
617 arr->InsertNewAt<CPDF_Boolean>(1, false);
618 arr->InsertNewAt<CPDF_Number>(2, 0);
619 arr->InsertNewAt<CPDF_Number>(3, -1234);
620 arr->InsertNewAt<CPDF_Number>(4, 2345.0f);
621 arr->InsertNewAt<CPDF_Number>(5, 0.05f);
622 arr->InsertNewAt<CPDF_String>(6, "", false);
623 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false);
624 arr->InsertNewAt<CPDF_Name>(8, "NAME");
625 arr->InsertNewAt<CPDF_Name>(9, "test");
626 arr->InsertNewAt<CPDF_Null>(10);
627
628 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11);
629 arr_val->AddNew<CPDF_Number>(1);
630 arr_val->AddNew<CPDF_Number>(2);
631
632 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12);
tsepez0e606b52016-11-18 16:22:41 -0800633 dict_val->SetNewFor<CPDF_String>("key1", "Linda", false);
634 dict_val->SetNewFor<CPDF_String>("key2", "Zoe", false);
tsepez8a3aa452016-11-16 12:26:06 -0800635
tsepezcd5bca42016-09-30 10:45:06 -0700636 CPDF_Dictionary* stream_dict = new CPDF_Dictionary();
tsepez0e606b52016-11-18 16:22:41 -0800637 stream_dict->SetNewFor<CPDF_String>("key1", "John", false);
638 stream_dict->SetNewFor<CPDF_String>("key2", "King", false);
Wei Libb53a5d2016-02-03 10:04:19 -0800639 uint8_t data[] = "A stream for test";
640 // The data buffer will be owned by stream object, so it needs to be
641 // dynamically allocated.
642 size_t buf_size = sizeof(data);
tsepez47fb8c02016-12-15 13:51:34 -0800643 std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_size));
644 memcpy(buf.get(), data, buf_size);
tsepez9e05ee12016-11-21 13:19:10 -0800645 CPDF_Stream* stream_val = arr->InsertNewAt<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800646 13, std::move(buf), buf_size, pdfium::WrapUnique(stream_dict));
Wei Libb53a5d2016-02-03 10:04:19 -0800647 const char* const expected_str[] = {
648 "true", "false", "0", "-1234", "2345", "0.05", "",
649 "It is a test!", "NAME", "test", "", "", "", ""};
Wei Libb53a5d2016-02-03 10:04:19 -0800650 const int expected_int[] = {1, 0, 0, -1234, 2345, 0, 0,
651 0, 0, 0, 0, 0, 0, 0};
652 const float expected_float[] = {0, 0, 0, -1234, 2345, 0.05f, 0,
653 0, 0, 0, 0, 0, 0, 0};
654 for (size_t i = 0; i < arr->GetCount(); ++i) {
655 EXPECT_STREQ(expected_str[i], arr->GetStringAt(i).c_str());
Wei Libb53a5d2016-02-03 10:04:19 -0800656 EXPECT_EQ(expected_int[i], arr->GetIntegerAt(i));
657 EXPECT_EQ(expected_float[i], arr->GetNumberAt(i));
658 EXPECT_EQ(expected_float[i], arr->GetFloatAt(i));
659 if (i == 11)
660 EXPECT_EQ(arr_val, arr->GetArrayAt(i));
661 else
662 EXPECT_EQ(nullptr, arr->GetArrayAt(i));
663 if (i == 13) {
664 EXPECT_EQ(stream_dict, arr->GetDictAt(i));
665 EXPECT_EQ(stream_val, arr->GetStreamAt(i));
666 } else {
667 EXPECT_EQ(nullptr, arr->GetStreamAt(i));
668 if (i == 12)
669 EXPECT_EQ(dict_val, arr->GetDictAt(i));
670 else
671 EXPECT_EQ(nullptr, arr->GetDictAt(i));
672 }
673 }
674 }
675}
676
677TEST(PDFArrayTest, AddNumber) {
678 float vals[] = {1.0f, -1.0f, 0, 0.456734f,
679 12345.54321f, 0.5f, 1000, 0.000045f};
tsepez8a3aa452016-11-16 12:26:06 -0800680 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800681 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800682 arr->AddNew<CPDF_Number>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800683 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700684 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
685 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800686 }
687}
688
689TEST(PDFArrayTest, AddInteger) {
690 int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100};
tsepez8a3aa452016-11-16 12:26:06 -0800691 auto arr = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800692 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
tsepez8a3aa452016-11-16 12:26:06 -0800693 arr->AddNew<CPDF_Number>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800694 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700695 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
696 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
Wei Libb53a5d2016-02-03 10:04:19 -0800697 }
698}
699
700TEST(PDFArrayTest, AddStringAndName) {
Lei Zhang69fe7112017-09-14 18:26:26 -0700701 static constexpr const char* vals[] = {
702 "", "a", "ehjhRIOYTTFdfcdnv", "122323",
703 "$#%^&**", " ", "This is a test.\r\n"};
Dan Sinclair0bb13332017-03-30 16:12:02 -0400704 auto string_array = pdfium::MakeUnique<CPDF_Array>();
705 auto name_array = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800706 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepez8a3aa452016-11-16 12:26:06 -0800707 string_array->AddNew<CPDF_String>(vals[i], false);
708 name_array->AddNew<CPDF_Name>(vals[i]);
Wei Libb53a5d2016-02-03 10:04:19 -0800709 }
710 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700711 EXPECT_EQ(CPDF_Object::STRING, string_array->GetObjectAt(i)->GetType());
712 EXPECT_STREQ(vals[i], string_array->GetObjectAt(i)->GetString().c_str());
713 EXPECT_EQ(CPDF_Object::NAME, name_array->GetObjectAt(i)->GetType());
714 EXPECT_STREQ(vals[i], name_array->GetObjectAt(i)->GetString().c_str());
Wei Libb53a5d2016-02-03 10:04:19 -0800715 }
716}
717
tsepezbd567552016-03-29 14:51:50 -0700718TEST(PDFArrayTest, AddReferenceAndGetObjectAt) {
Dan Sinclair0bb13332017-03-30 16:12:02 -0400719 auto holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
Wei Libb53a5d2016-02-03 10:04:19 -0800720 CPDF_Boolean* boolean_obj = new CPDF_Boolean(true);
721 CPDF_Number* int_obj = new CPDF_Number(-1234);
722 CPDF_Number* float_obj = new CPDF_Number(2345.089f);
tsepez5913a6c2016-11-16 17:31:18 -0800723 CPDF_String* str_obj =
724 new CPDF_String(nullptr, "Adsfdsf 343434 %&&*\n", false);
725 CPDF_Name* name_obj = new CPDF_Name(nullptr, "Title:");
Wei Libb53a5d2016-02-03 10:04:19 -0800726 CPDF_Null* null_obj = new CPDF_Null();
727 CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj,
728 str_obj, name_obj, null_obj};
729 unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1};
tsepez8a3aa452016-11-16 12:26:06 -0800730 auto arr = pdfium::MakeUnique<CPDF_Array>();
Dan Sinclair0bb13332017-03-30 16:12:02 -0400731 auto arr1 = pdfium::MakeUnique<CPDF_Array>();
Wei Libb53a5d2016-02-03 10:04:19 -0800732 // Create two arrays of references by different AddReference() APIs.
733 for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) {
tsepez931d0872016-11-04 16:00:03 -0700734 holder->ReplaceIndirectObjectIfHigherGeneration(
735 obj_nums[i], pdfium::WrapUnique<CPDF_Object>(indirect_objs[i]));
tsepez8a3aa452016-11-16 12:26:06 -0800736 arr->AddNew<CPDF_Reference>(holder.get(), obj_nums[i]);
737 arr1->AddNew<CPDF_Reference>(holder.get(), indirect_objs[i]->GetObjNum());
Wei Libb53a5d2016-02-03 10:04:19 -0800738 }
739 // Check indirect objects.
740 for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i)
dsinclair03bd7c72016-08-23 20:13:41 -0700741 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i]));
Wei Libb53a5d2016-02-03 10:04:19 -0800742 // Check arrays.
743 EXPECT_EQ(arr->GetCount(), arr1->GetCount());
744 for (size_t i = 0; i < arr->GetCount(); ++i) {
tsepezbd567552016-03-29 14:51:50 -0700745 EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetObjectAt(i)->GetType());
746 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect());
747 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i));
748 EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetObjectAt(i)->GetType());
749 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect());
750 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i));
Wei Li8f952272016-01-29 18:04:42 -0800751 }
752}
weilia470b5e2016-08-23 22:08:37 -0700753
thestig22b176d2016-08-25 11:14:21 -0700754TEST(PDFArrayTest, CloneDirectObject) {
755 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400756 auto array = pdfium::MakeUnique<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800757 array->AddNew<CPDF_Reference>(&objects_holder, 1234);
thestig22b176d2016-08-25 11:14:21 -0700758 ASSERT_EQ(1U, array->GetCount());
759 CPDF_Object* obj = array->GetObjectAt(0);
760 ASSERT_TRUE(obj);
761 EXPECT_TRUE(obj->IsReference());
762
tsepez335cf092016-11-09 13:28:26 -0800763 std::unique_ptr<CPDF_Object> cloned_array_object = array->CloneDirectObject();
thestig22b176d2016-08-25 11:14:21 -0700764 ASSERT_TRUE(cloned_array_object);
765 ASSERT_TRUE(cloned_array_object->IsArray());
766
tsepez335cf092016-11-09 13:28:26 -0800767 std::unique_ptr<CPDF_Array> cloned_array =
768 ToArray(std::move(cloned_array_object));
Wei Li6bdd8242017-03-23 09:45:04 -0700769 ASSERT_EQ(0U, cloned_array->GetCount());
thestig22b176d2016-08-25 11:14:21 -0700770 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0);
771 EXPECT_FALSE(cloned_obj);
772}
773
tsepez381fc832016-10-10 14:06:44 -0700774TEST(PDFArrayTest, ConvertIndirect) {
775 CPDF_IndirectObjectHolder objects_holder;
tsepez8a3aa452016-11-16 12:26:06 -0800776 auto array = pdfium::MakeUnique<CPDF_Array>();
777 CPDF_Object* pObj = array->AddNew<CPDF_Number>(42);
tsepez381fc832016-10-10 14:06:44 -0700778 array->ConvertToIndirectObjectAt(0, &objects_holder);
779 CPDF_Object* pRef = array->GetObjectAt(0);
780 CPDF_Object* pNum = array->GetDirectObjectAt(0);
781 EXPECT_TRUE(pRef->IsReference());
782 EXPECT_TRUE(pNum->IsNumber());
783 EXPECT_NE(pObj, pRef);
784 EXPECT_EQ(pObj, pNum);
785 EXPECT_EQ(42, array->GetIntegerAt(0));
786}
787
Artem Strygin90555e02017-07-28 19:41:59 +0300788TEST(PDFStreamTest, SetData) {
789 std::vector<uint8_t> data(100);
790 auto stream = pdfium::MakeUnique<CPDF_Stream>();
791 stream->InitStream(data.data(), data.size(),
792 pdfium::MakeUnique<CPDF_Dictionary>());
793 EXPECT_EQ(static_cast<int>(data.size()),
Lei Zhang26170562018-04-17 17:01:52 +0000794 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin90555e02017-07-28 19:41:59 +0300795
Lei Zhang26170562018-04-17 17:01:52 +0000796 stream->GetDict()->SetNewFor<CPDF_String>(pdfium::stream::kFilter,
797 L"SomeFilter");
798 stream->GetDict()->SetNewFor<CPDF_String>(pdfium::stream::kDecodeParms,
799 L"SomeParams");
Artem Strygin90555e02017-07-28 19:41:59 +0300800
801 std::vector<uint8_t> new_data(data.size() * 2);
802 stream->SetData(new_data.data(), new_data.size());
803
804 // The "Length" field should be updated for new data size.
805 EXPECT_EQ(static_cast<int>(new_data.size()),
Lei Zhang26170562018-04-17 17:01:52 +0000806 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin90555e02017-07-28 19:41:59 +0300807
808 // The "Filter" and "DecodeParms" fields should not be changed.
Lei Zhang26170562018-04-17 17:01:52 +0000809 EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor(pdfium::stream::kFilter),
810 L"SomeFilter");
811 EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor(pdfium::stream::kDecodeParms),
812 L"SomeParams");
Artem Strygin90555e02017-07-28 19:41:59 +0300813}
814
815TEST(PDFStreamTest, SetDataAndRemoveFilter) {
816 std::vector<uint8_t> data(100);
817 auto stream = pdfium::MakeUnique<CPDF_Stream>();
818 stream->InitStream(data.data(), data.size(),
819 pdfium::MakeUnique<CPDF_Dictionary>());
820 EXPECT_EQ(static_cast<int>(data.size()),
Lei Zhang26170562018-04-17 17:01:52 +0000821 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin90555e02017-07-28 19:41:59 +0300822
Lei Zhang26170562018-04-17 17:01:52 +0000823 stream->GetDict()->SetNewFor<CPDF_String>(pdfium::stream::kFilter,
824 L"SomeFilter");
825 stream->GetDict()->SetNewFor<CPDF_String>(pdfium::stream::kDecodeParms,
826 L"SomeParams");
Artem Strygin90555e02017-07-28 19:41:59 +0300827
828 std::vector<uint8_t> new_data(data.size() * 2);
829 stream->SetDataAndRemoveFilter(new_data.data(), new_data.size());
830 // The "Length" field should be updated for new data size.
831 EXPECT_EQ(static_cast<int>(new_data.size()),
Lei Zhang26170562018-04-17 17:01:52 +0000832 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin90555e02017-07-28 19:41:59 +0300833
834 // The "Filter" and "DecodeParms" should be removed.
Lei Zhang26170562018-04-17 17:01:52 +0000835 EXPECT_FALSE(stream->GetDict()->KeyExist(pdfium::stream::kFilter));
836 EXPECT_FALSE(stream->GetDict()->KeyExist(pdfium::stream::kDecodeParms));
Artem Strygin90555e02017-07-28 19:41:59 +0300837}
838
Artem Strygin4fde70e2017-09-04 17:01:41 +0300839TEST(PDFStreamTest, LengthInDictionaryOnCreate) {
840 static constexpr uint32_t kBufSize = 100;
841 // The length field should be created on stream create.
842 {
843 std::unique_ptr<uint8_t, FxFreeDeleter> data;
844 data.reset(FX_Alloc(uint8_t, kBufSize));
845 auto stream = pdfium::MakeUnique<CPDF_Stream>(
846 std::move(data), kBufSize, pdfium::MakeUnique<CPDF_Dictionary>());
847 EXPECT_EQ(static_cast<int>(kBufSize),
Lei Zhang26170562018-04-17 17:01:52 +0000848 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin4fde70e2017-09-04 17:01:41 +0300849 }
850 // The length field should be corrected on stream create.
851 {
852 std::unique_ptr<uint8_t, FxFreeDeleter> data;
853 data.reset(FX_Alloc(uint8_t, kBufSize));
854 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
Lei Zhang26170562018-04-17 17:01:52 +0000855 dict->SetNewFor<CPDF_Number>(pdfium::stream::kLength, 30000);
Artem Strygin4fde70e2017-09-04 17:01:41 +0300856 auto stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), kBufSize,
857 std::move(dict));
858 EXPECT_EQ(static_cast<int>(kBufSize),
Lei Zhang26170562018-04-17 17:01:52 +0000859 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
Artem Strygin4fde70e2017-09-04 17:01:41 +0300860 }
861}
862
thestig22b176d2016-08-25 11:14:21 -0700863TEST(PDFDictionaryTest, CloneDirectObject) {
864 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400865 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800866 dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234);
thestig22b176d2016-08-25 11:14:21 -0700867 ASSERT_EQ(1U, dict->GetCount());
dsinclair38fd8442016-09-15 10:15:32 -0700868 CPDF_Object* obj = dict->GetObjectFor("foo");
thestig22b176d2016-08-25 11:14:21 -0700869 ASSERT_TRUE(obj);
870 EXPECT_TRUE(obj->IsReference());
871
tsepez335cf092016-11-09 13:28:26 -0800872 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject();
thestig22b176d2016-08-25 11:14:21 -0700873 ASSERT_TRUE(cloned_dict_object);
874 ASSERT_TRUE(cloned_dict_object->IsDictionary());
875
tsepez335cf092016-11-09 13:28:26 -0800876 std::unique_ptr<CPDF_Dictionary> cloned_dict =
877 ToDictionary(std::move(cloned_dict_object));
Wei Li6bdd8242017-03-23 09:45:04 -0700878 ASSERT_EQ(0U, cloned_dict->GetCount());
dsinclair38fd8442016-09-15 10:15:32 -0700879 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
thestig22b176d2016-08-25 11:14:21 -0700880 EXPECT_FALSE(cloned_obj);
881}
882
weilia470b5e2016-08-23 22:08:37 -0700883TEST(PDFObjectTest, CloneCheckLoop) {
884 {
tsepez0e606b52016-11-18 16:22:41 -0800885 // Create a dictionary/array pair with a reference loop. It takes
886 // some work to do this nowadays, in particular we need the
887 // anti-pattern pdfium::WrapUnique(arr.get()).
tsepez8a3aa452016-11-16 12:26:06 -0800888 auto arr_obj = pdfium::MakeUnique<CPDF_Array>();
889 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0);
tsepez0e606b52016-11-18 16:22:41 -0800890 dict_obj->SetFor("arr", pdfium::WrapUnique(arr_obj.get()));
weilia470b5e2016-08-23 22:08:37 -0700891 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800892 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone());
weilia470b5e2016-08-23 22:08:37 -0700893 // Cloned object should be the same as the original.
894 ASSERT_TRUE(cloned_array);
895 EXPECT_EQ(1u, cloned_array->GetCount());
896 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0);
897 ASSERT_TRUE(cloned_dict);
898 ASSERT_TRUE(cloned_dict->IsDictionary());
899 // Recursively referenced object is not cloned.
dsinclair38fd8442016-09-15 10:15:32 -0700900 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr"));
weilia470b5e2016-08-23 22:08:37 -0700901 }
902 {
tsepez9e05ee12016-11-21 13:19:10 -0800903 // Create a dictionary/stream pair with a reference loop. It takes
904 // some work to do this nowadays, in particular we need the
905 // anti-pattern pdfium::WrapUnique(dict.get()).
tsepez0e606b52016-11-18 16:22:41 -0800906 auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez9e05ee12016-11-21 13:19:10 -0800907 CPDF_Stream* stream_obj = dict_obj->SetNewFor<CPDF_Stream>(
908 "stream", nullptr, 0, pdfium::WrapUnique(dict_obj.get()));
tsepez836f7d52016-10-10 14:31:05 -0700909 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800910 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone());
tsepez836f7d52016-10-10 14:31:05 -0700911 // Cloned object should be the same as the original.
912 ASSERT_TRUE(cloned_stream);
913 CPDF_Object* cloned_dict = cloned_stream->GetDict();
914 ASSERT_TRUE(cloned_dict);
915 ASSERT_TRUE(cloned_dict->IsDictionary());
916 // Recursively referenced object is not cloned.
917 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream"));
918 }
919 {
thestig22b176d2016-08-25 11:14:21 -0700920 CPDF_IndirectObjectHolder objects_holder;
weilia470b5e2016-08-23 22:08:37 -0700921 // Create an object with a reference loop.
tsepez70c4afd2016-11-15 11:33:44 -0800922 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>();
923 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800924 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder,
925 dict_obj->GetObjNum());
weilia470b5e2016-08-23 22:08:37 -0700926 CPDF_Object* elem0 = arr_obj->GetObjectAt(0);
tsepez0e606b52016-11-18 16:22:41 -0800927 dict_obj->SetFor("arr", std::move(arr_obj));
tsepez70c4afd2016-11-15 11:33:44 -0800928 EXPECT_EQ(1u, dict_obj->GetObjNum());
weilia470b5e2016-08-23 22:08:37 -0700929 ASSERT_TRUE(elem0);
930 ASSERT_TRUE(elem0->IsReference());
931 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum());
932 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect());
933
934 // Clone this object to see whether stack overflow will be triggered.
tsepez335cf092016-11-09 13:28:26 -0800935 std::unique_ptr<CPDF_Dictionary> cloned_dict =
936 ToDictionary(dict_obj->CloneDirectObject());
weilia470b5e2016-08-23 22:08:37 -0700937 // Cloned object should be the same as the original.
938 ASSERT_TRUE(cloned_dict);
dsinclair38fd8442016-09-15 10:15:32 -0700939 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr");
weilia470b5e2016-08-23 22:08:37 -0700940 ASSERT_TRUE(cloned_arr);
941 ASSERT_TRUE(cloned_arr->IsArray());
Wei Li6bdd8242017-03-23 09:45:04 -0700942 EXPECT_EQ(0U, cloned_arr->AsArray()->GetCount());
weilia470b5e2016-08-23 22:08:37 -0700943 // Recursively referenced object is not cloned.
944 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0));
945 }
946}
tsepez381fc832016-10-10 14:06:44 -0700947
948TEST(PDFDictionaryTest, ConvertIndirect) {
949 CPDF_IndirectObjectHolder objects_holder;
Dan Sinclair0bb13332017-03-30 16:12:02 -0400950 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800951 CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
tsepez381fc832016-10-10 14:06:44 -0700952 dict->ConvertToIndirectObjectFor("clams", &objects_holder);
953 CPDF_Object* pRef = dict->GetObjectFor("clams");
954 CPDF_Object* pNum = dict->GetDirectObjectFor("clams");
955 EXPECT_TRUE(pRef->IsReference());
956 EXPECT_TRUE(pNum->IsNumber());
957 EXPECT_NE(pObj, pRef);
958 EXPECT_EQ(pObj, pNum);
959 EXPECT_EQ(42, dict->GetIntegerFor("clams"));
960}
Artem Strygin106eecd2017-07-28 14:34:37 +0300961
962TEST(PDFDictionaryTest, ExtractObjectOnRemove) {
963 auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
964 CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("child", 42);
965 auto extracted_object = dict->RemoveFor("child");
966 EXPECT_EQ(pObj, extracted_object.get());
967
968 extracted_object = dict->RemoveFor("non_exists_object");
969 EXPECT_FALSE(extracted_object);
970}