Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: core/fpdfapi/fpdf_parser/cpdf_object_unittest.cpp

Issue 2392603004: Move core/fpdfapi/fpdf_parser to core/fpdfapi/parser (Closed)
Patch Set: Rebase to master Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfapi/fpdf_parser/cpdf_object.cpp ('k') | core/fpdfapi/fpdf_parser/cpdf_parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/fpdfapi/fpdf_parser/cpdf_array.h"
6 #include "core/fpdfapi/fpdf_parser/cpdf_boolean.h"
7 #include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h"
8 #include "core/fpdfapi/fpdf_parser/cpdf_name.h"
9 #include "core/fpdfapi/fpdf_parser/cpdf_null.h"
10 #include "core/fpdfapi/fpdf_parser/cpdf_number.h"
11 #include "core/fpdfapi/fpdf_parser/cpdf_reference.h"
12 #include "core/fpdfapi/fpdf_parser/cpdf_stream.h"
13 #include "core/fpdfapi/fpdf_parser/cpdf_string.h"
14
15 #include <memory>
16 #include <string>
17 #include <vector>
18
19 #include "core/fpdfapi/fpdf_parser/cpdf_indirect_object_holder.h"
20 #include "core/fxcrt/fx_basic.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace {
24
25 using ScopedArray = std::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>>;
26 using ScopedDict =
27 std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>>;
28
29 void TestArrayAccessors(const CPDF_Array* arr,
30 size_t index,
31 const char* str_val,
32 const char* const_str_val,
33 int int_val,
34 float float_val,
35 CPDF_Array* arr_val,
36 CPDF_Dictionary* dict_val,
37 CPDF_Stream* stream_val) {
38 EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str());
39 EXPECT_EQ(int_val, arr->GetIntegerAt(index));
40 EXPECT_EQ(float_val, arr->GetNumberAt(index));
41 EXPECT_EQ(float_val, arr->GetFloatAt(index));
42 EXPECT_EQ(arr_val, arr->GetArrayAt(index));
43 EXPECT_EQ(dict_val, arr->GetDictAt(index));
44 EXPECT_EQ(stream_val, arr->GetStreamAt(index));
45 }
46
47 } // namespace
48
49 class PDFObjectsTest : public testing::Test {
50 public:
51 void SetUp() override {
52 // Initialize different kinds of objects.
53 // Boolean objects.
54 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
55 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
56 // Number objects.
57 CPDF_Number* number_int_obj = new CPDF_Number(1245);
58 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
59 // String objects.
60 CPDF_String* str_reg_obj = new CPDF_String(L"A simple test");
61 CPDF_String* str_spec_obj = new CPDF_String(L"\t\n");
62 // Name object.
63 CPDF_Name* name_obj = new CPDF_Name("space");
64 // Array object.
65 m_ArrayObj = new CPDF_Array;
66 m_ArrayObj->InsertAt(0, new CPDF_Number(8902));
67 m_ArrayObj->InsertAt(1, new CPDF_Name("address"));
68 // Dictionary object.
69 m_DictObj = new CPDF_Dictionary();
70 m_DictObj->SetFor("bool", new CPDF_Boolean(false));
71 m_DictObj->SetFor("num", new CPDF_Number(0.23f));
72 // Stream object.
73 const char content[] = "abcdefghijklmnopqrstuvwxyz";
74 size_t buf_len = FX_ArraySize(content);
75 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len));
76 memcpy(buf, content, buf_len);
77 m_StreamDictObj = new CPDF_Dictionary();
78 m_StreamDictObj->SetFor("key1", new CPDF_String(L" test dict"));
79 m_StreamDictObj->SetFor("key2", new CPDF_Number(-1));
80 CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj);
81 // Null Object.
82 CPDF_Null* null_obj = new CPDF_Null;
83 // All direct objects.
84 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
85 number_float_obj, str_reg_obj, str_spec_obj,
86 name_obj, m_ArrayObj, m_DictObj,
87 stream_obj, null_obj};
88 m_DirectObjTypes = {
89 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER,
90 CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING,
91 CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY,
92 CPDF_Object::STREAM, CPDF_Object::NULLOBJ};
93 for (size_t i = 0; i < FX_ArraySize(objs); ++i)
94 m_DirectObjs.emplace_back(objs[i]);
95
96 // Indirect references to indirect objects.
97 m_ObjHolder.reset(new CPDF_IndirectObjectHolder());
98 m_IndirectObjs = {boolean_true_obj, number_int_obj, str_spec_obj, name_obj,
99 m_ArrayObj, m_DictObj, stream_obj};
100 for (size_t i = 0; i < m_IndirectObjs.size(); ++i) {
101 m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]);
102 m_RefObjs.emplace_back(new CPDF_Reference(
103 m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum()));
104 }
105 }
106
107 bool Equal(CPDF_Object* obj1, CPDF_Object* obj2) {
108 if (obj1 == obj2)
109 return true;
110 if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType())
111 return false;
112 switch (obj1->GetType()) {
113 case CPDF_Object::BOOLEAN:
114 return obj1->GetInteger() == obj2->GetInteger();
115 case CPDF_Object::NUMBER:
116 return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() &&
117 obj1->GetInteger() == obj2->GetInteger();
118 case CPDF_Object::STRING:
119 case CPDF_Object::NAME:
120 return obj1->GetString() == obj2->GetString();
121 case CPDF_Object::ARRAY: {
122 const CPDF_Array* array1 = obj1->AsArray();
123 const CPDF_Array* array2 = obj2->AsArray();
124 if (array1->GetCount() != array2->GetCount())
125 return false;
126 for (size_t i = 0; i < array1->GetCount(); ++i) {
127 if (!Equal(array1->GetObjectAt(i), array2->GetObjectAt(i)))
128 return false;
129 }
130 return true;
131 }
132 case CPDF_Object::DICTIONARY: {
133 const CPDF_Dictionary* dict1 = obj1->AsDictionary();
134 const CPDF_Dictionary* dict2 = obj2->AsDictionary();
135 if (dict1->GetCount() != dict2->GetCount())
136 return false;
137 for (CPDF_Dictionary::const_iterator it = dict1->begin();
138 it != dict1->end(); ++it) {
139 if (!Equal(it->second, dict2->GetObjectFor(it->first)))
140 return false;
141 }
142 return true;
143 }
144 case CPDF_Object::NULLOBJ:
145 return true;
146 case CPDF_Object::STREAM: {
147 const CPDF_Stream* stream1 = obj1->AsStream();
148 const CPDF_Stream* stream2 = obj2->AsStream();
149 if (!stream1->GetDict() && !stream2->GetDict())
150 return true;
151 // Compare dictionaries.
152 if (!Equal(stream1->GetDict(), stream2->GetDict()))
153 return false;
154 // Compare sizes.
155 if (stream1->GetRawSize() != stream2->GetRawSize())
156 return false;
157 // Compare contents.
158 // Since this function is used for testing Clone(), only memory based
159 // streams need to be handled.
160 if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased())
161 return false;
162 return FXSYS_memcmp(stream1->GetRawData(), stream2->GetRawData(),
163 stream1->GetRawSize()) == 0;
164 }
165 case CPDF_Object::REFERENCE:
166 return obj1->AsReference()->GetRefObjNum() ==
167 obj2->AsReference()->GetRefObjNum();
168 }
169 return false;
170 }
171
172 protected:
173 using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>;
174
175 // 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;
178 std::vector<ScopedObj> m_DirectObjs;
179 std::vector<int> m_DirectObjTypes;
180 std::vector<ScopedObj> m_RefObjs;
181 CPDF_Dictionary* m_DictObj;
182 CPDF_Dictionary* m_StreamDictObj;
183 CPDF_Array* m_ArrayObj;
184 std::vector<CPDF_Object*> m_IndirectObjs;
185 };
186
187 TEST_F(PDFObjectsTest, GetString) {
188 const char* const direct_obj_results[] = {
189 "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space",
190 "", "", "", ""};
191 // Check for direct objects.
192 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
193 EXPECT_STREQ(direct_obj_results[i], m_DirectObjs[i]->GetString().c_str());
194
195 // Check indirect references.
196 const char* const indirect_obj_results[] = {"true", "1245", "\t\n", "space",
197 "", "", ""};
198 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
199 EXPECT_STREQ(indirect_obj_results[i], m_RefObjs[i]->GetString().c_str());
200 }
201 }
202
203 TEST_F(PDFObjectsTest, GetUnicodeText) {
204 const wchar_t* const direct_obj_results[] = {
205 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.
209 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
210 EXPECT_STREQ(direct_obj_results[i],
211 m_DirectObjs[i]->GetUnicodeText().c_str());
212 }
213
214 // Check indirect references.
215 for (const auto& it : m_RefObjs)
216 EXPECT_STREQ(L"", it->GetUnicodeText().c_str());
217 }
218
219 TEST_F(PDFObjectsTest, GetNumber) {
220 const FX_FLOAT direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0,
221 0, 0, 0, 0, 0};
222 // Check for direct objects.
223 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
224 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber());
225
226 // Check indirect references.
227 const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0};
228 for (size_t i = 0; i < m_RefObjs.size(); ++i)
229 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber());
230 }
231
232 TEST_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.
235 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
236 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetInteger());
237
238 // Check indirect references.
239 const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0};
240 for (size_t i = 0; i < m_RefObjs.size(); ++i)
241 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetInteger());
242 }
243
244 TEST_F(PDFObjectsTest, GetDict) {
245 const CPDF_Dictionary* const direct_obj_results[] = {
246 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
247 nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr};
248 // Check for direct objects.
249 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
250 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict());
251
252 // Check indirect references.
253 const CPDF_Dictionary* const indirect_obj_results[] = {
254 nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj};
255 for (size_t i = 0; i < m_RefObjs.size(); ++i)
256 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetDict());
257 }
258
259 TEST_F(PDFObjectsTest, GetArray) {
260 const CPDF_Array* const direct_obj_results[] = {
261 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
262 nullptr, m_ArrayObj, nullptr, nullptr, nullptr};
263 // Check for direct objects.
264 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
265 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray());
266
267 // Check indirect references.
268 for (const auto& it : m_RefObjs)
269 EXPECT_EQ(nullptr, it->AsArray());
270 }
271
272 TEST_F(PDFObjectsTest, Clone) {
273 // Check for direct objects.
274 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
275 ScopedObj obj(m_DirectObjs[i]->Clone());
276 EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get()));
277 }
278
279 // Check indirect references.
280 for (const auto& it : m_RefObjs) {
281 ScopedObj obj(it->Clone());
282 EXPECT_TRUE(Equal(it.get(), obj.get()));
283 }
284 }
285
286 TEST_F(PDFObjectsTest, GetType) {
287 // Check for direct objects.
288 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
289 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType());
290
291 // Check indirect references.
292 for (const auto& it : m_RefObjs)
293 EXPECT_EQ(CPDF_Object::REFERENCE, it->GetType());
294 }
295
296 TEST_F(PDFObjectsTest, GetDirect) {
297 // Check for direct objects.
298 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
299 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->GetDirect());
300
301 // Check indirect references.
302 for (size_t i = 0; i < m_RefObjs.size(); ++i)
303 EXPECT_EQ(m_IndirectObjs[i], m_RefObjs[i]->GetDirect());
304 }
305
306 TEST_F(PDFObjectsTest, SetString) {
307 // Check for direct objects.
308 const char* const set_values[] = {"true", "fake", "3.125f", "097",
309 "changed", "", "NewName"};
310 const char* const expected[] = {"true", "false", "3.125", "97",
311 "changed", "", "NewName"};
312 for (size_t i = 0; i < FX_ArraySize(set_values); ++i) {
313 m_DirectObjs[i]->SetString(set_values[i]);
314 EXPECT_STREQ(expected[i], m_DirectObjs[i]->GetString().c_str());
315 }
316 }
317
318 TEST_F(PDFObjectsTest, IsTypeAndAsType) {
319 // Check for direct objects.
320 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
321 if (m_DirectObjTypes[i] == CPDF_Object::ARRAY) {
322 EXPECT_TRUE(m_DirectObjs[i]->IsArray());
323 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsArray());
324 } else {
325 EXPECT_FALSE(m_DirectObjs[i]->IsArray());
326 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsArray());
327 }
328
329 if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) {
330 EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
331 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsBoolean());
332 } else {
333 EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
334 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsBoolean());
335 }
336
337 if (m_DirectObjTypes[i] == CPDF_Object::NAME) {
338 EXPECT_TRUE(m_DirectObjs[i]->IsName());
339 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsName());
340 } else {
341 EXPECT_FALSE(m_DirectObjs[i]->IsName());
342 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsName());
343 }
344
345 if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) {
346 EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
347 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsNumber());
348 } else {
349 EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
350 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsNumber());
351 }
352
353 if (m_DirectObjTypes[i] == CPDF_Object::STRING) {
354 EXPECT_TRUE(m_DirectObjs[i]->IsString());
355 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsString());
356 } else {
357 EXPECT_FALSE(m_DirectObjs[i]->IsString());
358 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsString());
359 }
360
361 if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) {
362 EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
363 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsDictionary());
364 } else {
365 EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
366 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsDictionary());
367 }
368
369 if (m_DirectObjTypes[i] == CPDF_Object::STREAM) {
370 EXPECT_TRUE(m_DirectObjs[i]->IsStream());
371 EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsStream());
372 } else {
373 EXPECT_FALSE(m_DirectObjs[i]->IsStream());
374 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsStream());
375 }
376
377 EXPECT_FALSE(m_DirectObjs[i]->IsReference());
378 EXPECT_EQ(nullptr, m_DirectObjs[i]->AsReference());
379 }
380 // Check indirect references.
381 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
382 EXPECT_TRUE(m_RefObjs[i]->IsReference());
383 EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference());
384 }
385 }
386
387 TEST(PDFArrayTest, GetMatrix) {
388 float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
389 {1, 2, 3, 4, 5, 6},
390 {2.3f, 4.05f, 3, -2, -3, 0.0f},
391 {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}};
392 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
393 ScopedArray arr(new CPDF_Array);
394 CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3],
395 elems[i][4], elems[i][5]);
396 for (size_t j = 0; j < 6; ++j)
397 arr->AddNumber(elems[i][j]);
398 CFX_Matrix arr_matrix = arr->GetMatrix();
399 EXPECT_EQ(matrix.GetA(), arr_matrix.GetA());
400 EXPECT_EQ(matrix.GetB(), arr_matrix.GetB());
401 EXPECT_EQ(matrix.GetC(), arr_matrix.GetC());
402 EXPECT_EQ(matrix.GetD(), arr_matrix.GetD());
403 EXPECT_EQ(matrix.GetE(), arr_matrix.GetE());
404 EXPECT_EQ(matrix.GetF(), arr_matrix.GetF());
405 }
406 }
407
408 TEST(PDFArrayTest, GetRect) {
409 float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
410 {1, 2, 5, 6},
411 {2.3f, 4.05f, -3, 0.0f},
412 {0.05f, 0.1f, 1.34f, 99.9f}};
413 for (size_t i = 0; i < FX_ArraySize(elems); ++i) {
414 ScopedArray arr(new CPDF_Array);
415 CFX_FloatRect rect(elems[i]);
416 for (size_t j = 0; j < 4; ++j)
417 arr->AddNumber(elems[i][j]);
418 CFX_FloatRect arr_rect = arr->GetRect();
419 EXPECT_EQ(rect.left, arr_rect.left);
420 EXPECT_EQ(rect.right, arr_rect.right);
421 EXPECT_EQ(rect.bottom, arr_rect.bottom);
422 EXPECT_EQ(rect.top, arr_rect.top);
423 }
424 }
425
426 TEST(PDFArrayTest, GetTypeAt) {
427 {
428 // Boolean array.
429 const bool vals[] = {true, false, false, true, true};
430 ScopedArray arr(new CPDF_Array);
431 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
432 arr->InsertAt(i, new CPDF_Boolean(vals[i]));
433 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
434 TestArrayAccessors(arr.get(), i, // Array and index.
435 vals[i] ? "true" : "false", // String value.
436 nullptr, // Const string value.
437 vals[i] ? 1 : 0, // Integer value.
438 0, // Float value.
439 nullptr, // Array value.
440 nullptr, // Dictionary value.
441 nullptr); // Stream value.
442 }
443 }
444 {
445 // Integer array.
446 const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767};
447 ScopedArray arr(new CPDF_Array);
448 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
449 arr->InsertAt(i, new CPDF_Number(vals[i]));
450 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
451 char buf[33];
452 TestArrayAccessors(arr.get(), i, // Array and index.
453 FXSYS_itoa(vals[i], buf, 10), // String value.
454 nullptr, // Const string value.
455 vals[i], // Integer value.
456 vals[i], // Float value.
457 nullptr, // Array value.
458 nullptr, // Dictionary value.
459 nullptr); // Stream value.
460 }
461 }
462 {
463 // Float array.
464 const float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f,
465 897.34f, -2.5f, -1.0f, -345.0f, -0.0f};
466 const char* const expected_str[] = {
467 "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"};
468 ScopedArray arr(new CPDF_Array);
469 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
470 arr->InsertAt(i, new CPDF_Number(vals[i]));
471 }
472 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 :)"};
487 ScopedArray string_array(new CPDF_Array);
488 ScopedArray name_array(new CPDF_Array);
489 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
490 string_array->InsertAt(i, new CPDF_String(vals[i], false));
491 name_array->InsertAt(i, new CPDF_Name(vals[i]));
492 }
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.
514 ScopedArray arr(new CPDF_Array);
515 for (size_t i = 0; i < 3; ++i)
516 arr->InsertAt(i, new CPDF_Null);
517 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];
531 ScopedArray arr(new CPDF_Array);
532 for (size_t i = 0; i < 3; ++i) {
533 vals[i] = new CPDF_Array;
534 for (size_t j = 0; j < 3; ++j) {
535 int value = j + 100;
536 vals[i]->InsertAt(i, new CPDF_Number(value));
537 }
538 arr->InsertAt(i, vals[i]);
539 }
540 for (size_t i = 0; i < 3; ++i) {
541 TestArrayAccessors(arr.get(), i, // Array and index.
542 "", // String value.
543 nullptr, // Const string value.
544 0, // Integer value.
545 0, // Float value.
546 vals[i], // Array value.
547 nullptr, // Dictionary value.
548 nullptr); // Stream value.
549 }
550 }
551 {
552 // Dictionary array.
553 CPDF_Dictionary* vals[3];
554 ScopedArray arr(new CPDF_Array);
555 for (size_t i = 0; i < 3; ++i) {
556 vals[i] = new CPDF_Dictionary();
557 for (size_t j = 0; j < 3; ++j) {
558 std::string key("key");
559 char buf[33];
560 key.append(FXSYS_itoa(j, buf, 10));
561 int value = j + 200;
562 vals[i]->SetFor(key.c_str(), new CPDF_Number(value));
563 }
564 arr->InsertAt(i, vals[i]);
565 }
566 for (size_t i = 0; i < 3; ++i) {
567 TestArrayAccessors(arr.get(), i, // Array and index.
568 "", // String value.
569 nullptr, // Const string value.
570 0, // Integer value.
571 0, // Float value.
572 nullptr, // Array value.
573 vals[i], // Dictionary value.
574 nullptr); // Stream value.
575 }
576 }
577 {
578 // Stream array.
579 CPDF_Dictionary* vals[3];
580 CPDF_Stream* stream_vals[3];
581 ScopedArray arr(new CPDF_Array);
582 for (size_t i = 0; i < 3; ++i) {
583 vals[i] = new CPDF_Dictionary();
584 for (size_t j = 0; j < 3; ++j) {
585 std::string key("key");
586 char buf[33];
587 key.append(FXSYS_itoa(j, buf, 10));
588 int value = j + 200;
589 vals[i]->SetFor(key.c_str(), new CPDF_Number(value));
590 }
591 uint8_t content[] = "content: this is a stream";
592 size_t data_size = FX_ArraySize(content);
593 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size));
594 memcpy(data, content, data_size);
595 stream_vals[i] = new CPDF_Stream(data, data_size, vals[i]);
596 arr->InsertAt(i, stream_vals[i]);
597 }
598 for (size_t i = 0; i < 3; ++i) {
599 TestArrayAccessors(arr.get(), i, // Array and index.
600 "", // String value.
601 nullptr, // Const string value.
602 0, // Integer value.
603 0, // Float value.
604 nullptr, // Array value.
605 vals[i], // Dictionary value.
606 stream_vals[i]); // Stream value.
607 }
608 }
609 {
610 // Mixed array.
611 ScopedArray arr(new CPDF_Array);
612 // Array arr will take ownership of all the objects inserted.
613 arr->InsertAt(0, new CPDF_Boolean(true));
614 arr->InsertAt(1, new CPDF_Boolean(false));
615 arr->InsertAt(2, new CPDF_Number(0));
616 arr->InsertAt(3, new CPDF_Number(-1234));
617 arr->InsertAt(4, new CPDF_Number(2345.0f));
618 arr->InsertAt(5, new CPDF_Number(0.05f));
619 arr->InsertAt(6, new CPDF_String("", false));
620 arr->InsertAt(7, new CPDF_String("It is a test!", false));
621 arr->InsertAt(8, new CPDF_Name("NAME"));
622 arr->InsertAt(9, new CPDF_Name("test"));
623 arr->InsertAt(10, new CPDF_Null());
624 CPDF_Array* arr_val = new CPDF_Array;
625 arr_val->AddNumber(1);
626 arr_val->AddNumber(2);
627 arr->InsertAt(11, arr_val);
628 CPDF_Dictionary* dict_val = new CPDF_Dictionary();
629 dict_val->SetFor("key1", new CPDF_String("Linda", false));
630 dict_val->SetFor("key2", new CPDF_String("Zoe", false));
631 arr->InsertAt(12, dict_val);
632 CPDF_Dictionary* stream_dict = new CPDF_Dictionary();
633 stream_dict->SetFor("key1", new CPDF_String("John", false));
634 stream_dict->SetFor("key2", new CPDF_String("King", false));
635 uint8_t data[] = "A stream for test";
636 // The data buffer will be owned by stream object, so it needs to be
637 // dynamically allocated.
638 size_t buf_size = sizeof(data);
639 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_size));
640 memcpy(buf, data, buf_size);
641 CPDF_Stream* stream_val = new CPDF_Stream(buf, buf_size, stream_dict);
642 arr->InsertAt(13, stream_val);
643 const char* const expected_str[] = {
644 "true", "false", "0", "-1234", "2345", "0.05", "",
645 "It is a test!", "NAME", "test", "", "", "", ""};
646 const int expected_int[] = {1, 0, 0, -1234, 2345, 0, 0,
647 0, 0, 0, 0, 0, 0, 0};
648 const float expected_float[] = {0, 0, 0, -1234, 2345, 0.05f, 0,
649 0, 0, 0, 0, 0, 0, 0};
650 for (size_t i = 0; i < arr->GetCount(); ++i) {
651 EXPECT_STREQ(expected_str[i], arr->GetStringAt(i).c_str());
652 EXPECT_EQ(expected_int[i], arr->GetIntegerAt(i));
653 EXPECT_EQ(expected_float[i], arr->GetNumberAt(i));
654 EXPECT_EQ(expected_float[i], arr->GetFloatAt(i));
655 if (i == 11)
656 EXPECT_EQ(arr_val, arr->GetArrayAt(i));
657 else
658 EXPECT_EQ(nullptr, arr->GetArrayAt(i));
659 if (i == 13) {
660 EXPECT_EQ(stream_dict, arr->GetDictAt(i));
661 EXPECT_EQ(stream_val, arr->GetStreamAt(i));
662 } else {
663 EXPECT_EQ(nullptr, arr->GetStreamAt(i));
664 if (i == 12)
665 EXPECT_EQ(dict_val, arr->GetDictAt(i));
666 else
667 EXPECT_EQ(nullptr, arr->GetDictAt(i));
668 }
669 }
670 }
671 }
672
673 TEST(PDFArrayTest, AddNumber) {
674 float vals[] = {1.0f, -1.0f, 0, 0.456734f,
675 12345.54321f, 0.5f, 1000, 0.000045f};
676 ScopedArray arr(new CPDF_Array);
677 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
678 arr->AddNumber(vals[i]);
679 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
680 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
681 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
682 }
683 }
684
685 TEST(PDFArrayTest, AddInteger) {
686 int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100};
687 ScopedArray arr(new CPDF_Array);
688 for (size_t i = 0; i < FX_ArraySize(vals); ++i)
689 arr->AddInteger(vals[i]);
690 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
691 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType());
692 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
693 }
694 }
695
696 TEST(PDFArrayTest, AddStringAndName) {
697 const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323",
698 "$#%^&**", " ", "This is a test.\r\n"};
699 ScopedArray string_array(new CPDF_Array);
700 ScopedArray name_array(new CPDF_Array);
701 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
702 string_array->AddString(vals[i]);
703 name_array->AddName(vals[i]);
704 }
705 for (size_t i = 0; i < FX_ArraySize(vals); ++i) {
706 EXPECT_EQ(CPDF_Object::STRING, string_array->GetObjectAt(i)->GetType());
707 EXPECT_STREQ(vals[i], string_array->GetObjectAt(i)->GetString().c_str());
708 EXPECT_EQ(CPDF_Object::NAME, name_array->GetObjectAt(i)->GetType());
709 EXPECT_STREQ(vals[i], name_array->GetObjectAt(i)->GetString().c_str());
710 }
711 }
712
713 TEST(PDFArrayTest, AddReferenceAndGetObjectAt) {
714 std::unique_ptr<CPDF_IndirectObjectHolder> holder(
715 new CPDF_IndirectObjectHolder());
716 CPDF_Boolean* boolean_obj = new CPDF_Boolean(true);
717 CPDF_Number* int_obj = new CPDF_Number(-1234);
718 CPDF_Number* float_obj = new CPDF_Number(2345.089f);
719 CPDF_String* str_obj = new CPDF_String("Adsfdsf 343434 %&&*\n", false);
720 CPDF_Name* name_obj = new CPDF_Name("Title:");
721 CPDF_Null* null_obj = new CPDF_Null();
722 CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj,
723 str_obj, name_obj, null_obj};
724 unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1};
725 ScopedArray arr(new CPDF_Array);
726 ScopedArray arr1(new CPDF_Array);
727 // Create two arrays of references by different AddReference() APIs.
728 for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) {
729 // All the indirect objects inserted will be owned by holder.
730 holder->ReplaceIndirectObjectIfHigherGeneration(obj_nums[i],
731 indirect_objs[i]);
732 arr->AddReference(holder.get(), obj_nums[i]);
733 arr1->AddReference(holder.get(), indirect_objs[i]->GetObjNum());
734 }
735 // Check indirect objects.
736 for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i)
737 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i]));
738 // Check arrays.
739 EXPECT_EQ(arr->GetCount(), arr1->GetCount());
740 for (size_t i = 0; i < arr->GetCount(); ++i) {
741 EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetObjectAt(i)->GetType());
742 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect());
743 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i));
744 EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetObjectAt(i)->GetType());
745 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect());
746 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i));
747 }
748 }
749
750 TEST(PDFArrayTest, CloneDirectObject) {
751 CPDF_IndirectObjectHolder objects_holder;
752 ScopedArray array(new CPDF_Array);
753 array->AddReference(&objects_holder, 1234);
754 ASSERT_EQ(1U, array->GetCount());
755 CPDF_Object* obj = array->GetObjectAt(0);
756 ASSERT_TRUE(obj);
757 EXPECT_TRUE(obj->IsReference());
758
759 CPDF_Object* cloned_array_object = array->CloneDirectObject();
760 ASSERT_TRUE(cloned_array_object);
761 ASSERT_TRUE(cloned_array_object->IsArray());
762
763 ScopedArray cloned_array(cloned_array_object->AsArray());
764 ASSERT_EQ(1U, cloned_array->GetCount());
765 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0);
766 EXPECT_FALSE(cloned_obj);
767 }
768
769 TEST(PDFDictionaryTest, CloneDirectObject) {
770 CPDF_IndirectObjectHolder objects_holder;
771 ScopedDict dict(new CPDF_Dictionary());
772 dict->SetReferenceFor("foo", &objects_holder, 1234);
773 ASSERT_EQ(1U, dict->GetCount());
774 CPDF_Object* obj = dict->GetObjectFor("foo");
775 ASSERT_TRUE(obj);
776 EXPECT_TRUE(obj->IsReference());
777
778 CPDF_Object* cloned_dict_object = dict->CloneDirectObject();
779 ASSERT_TRUE(cloned_dict_object);
780 ASSERT_TRUE(cloned_dict_object->IsDictionary());
781
782 ScopedDict cloned_dict(cloned_dict_object->AsDictionary());
783 ASSERT_EQ(1U, cloned_dict->GetCount());
784 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo");
785 EXPECT_FALSE(cloned_obj);
786 }
787
788 TEST(PDFObjectTest, CloneCheckLoop) {
789 {
790 // Create an object with a reference loop.
791 ScopedArray arr_obj(new CPDF_Array);
792 // Dictionary object.
793 CPDF_Dictionary* dict_obj = new CPDF_Dictionary();
794 dict_obj->SetFor("arr", arr_obj.get());
795 arr_obj->InsertAt(0, dict_obj);
796
797 // Clone this object to see whether stack overflow will be triggered.
798 ScopedArray cloned_array(arr_obj->Clone()->AsArray());
799 // Cloned object should be the same as the original.
800 ASSERT_TRUE(cloned_array);
801 EXPECT_EQ(1u, cloned_array->GetCount());
802 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0);
803 ASSERT_TRUE(cloned_dict);
804 ASSERT_TRUE(cloned_dict->IsDictionary());
805 // Recursively referenced object is not cloned.
806 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr"));
807 }
808 {
809 CPDF_IndirectObjectHolder objects_holder;
810 // Create an object with a reference loop.
811 CPDF_Dictionary* dict_obj = new CPDF_Dictionary();
812 CPDF_Array* arr_obj = new CPDF_Array;
813 objects_holder.AddIndirectObject(dict_obj);
814 EXPECT_EQ(1u, dict_obj->GetObjNum());
815 dict_obj->SetFor("arr", arr_obj);
816 arr_obj->InsertAt(
817 0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum()));
818 CPDF_Object* elem0 = arr_obj->GetObjectAt(0);
819 ASSERT_TRUE(elem0);
820 ASSERT_TRUE(elem0->IsReference());
821 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum());
822 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect());
823
824 // Clone this object to see whether stack overflow will be triggered.
825 ScopedDict cloned_dict(ToDictionary(dict_obj->CloneDirectObject()));
826 // Cloned object should be the same as the original.
827 ASSERT_TRUE(cloned_dict);
828 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr");
829 ASSERT_TRUE(cloned_arr);
830 ASSERT_TRUE(cloned_arr->IsArray());
831 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount());
832 // Recursively referenced object is not cloned.
833 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0));
834 }
835 }
OLDNEW
« no previous file with comments | « core/fpdfapi/fpdf_parser/cpdf_object.cpp ('k') | core/fpdfapi/fpdf_parser/cpdf_parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698