summaryrefslogtreecommitdiff
path: root/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/parser/cpdf_object_walker_unittest.cpp')
-rw-r--r--core/fpdfapi/parser/cpdf_object_walker_unittest.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
new file mode 100644
index 0000000000..66c559d3ca
--- /dev/null
+++ b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp
@@ -0,0 +1,142 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fpdfapi/parser/cpdf_object_walker.h"
+
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_boolean.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfapi/parser/cpdf_name.h"
+#include "core/fpdfapi/parser/cpdf_null.h"
+#include "core/fpdfapi/parser/cpdf_number.h"
+#include "core/fpdfapi/parser/cpdf_reference.h"
+#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fpdfapi/parser/cpdf_string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/base/ptr_util.h"
+
+namespace {
+
+std::string Walk(CPDF_Object* object) {
+ std::ostringstream result;
+ CPDF_ObjectWalker walker(object);
+ while (const CPDF_Object* obj = walker.GetNext()) {
+ if (obj->IsDictionary())
+ result << " Dict";
+ else if (obj->IsArray())
+ result << " Arr";
+ else if (obj->IsString())
+ result << " Str";
+ else if (obj->IsBoolean())
+ result << " Bool";
+ else if (obj->IsStream())
+ result << " Stream";
+ else if (obj->IsReference())
+ result << " Ref";
+ else if (obj->IsNull())
+ result << " Null";
+ else
+ result << " Unknown";
+ }
+ std::string result_str = result.str();
+ if (!result_str.empty()) {
+ result_str.erase(result_str.begin()); // remove start space
+ }
+ return result_str;
+}
+
+} // namespace
+
+TEST(CPDF_ObjectWalkerTest, Simple) {
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Null>().get()), "Null");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Dictionary>().get()), "Dict");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Array>().get()), "Arr");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_String>().get()), "Str");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Boolean>().get()), "Bool");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Stream>().get()), "Stream");
+ EXPECT_EQ(Walk(pdfium::MakeUnique<CPDF_Reference>(nullptr, 0).get()), "Ref");
+}
+
+TEST(CPDF_ObjectWalkerTest, CombinedObject) {
+ auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+ dict->SetFor("1", pdfium::MakeUnique<CPDF_String>());
+ dict->SetFor("2", pdfium::MakeUnique<CPDF_Boolean>());
+ auto array = pdfium::MakeUnique<CPDF_Array>();
+ array->Add(pdfium::MakeUnique<CPDF_Reference>(nullptr, 0));
+ array->Add(pdfium::MakeUnique<CPDF_Null>());
+ array->Add(pdfium::MakeUnique<CPDF_Stream>(
+ nullptr, 0, pdfium::MakeUnique<CPDF_Dictionary>()));
+ dict->SetFor("3", std::move(array));
+ EXPECT_EQ(Walk(dict.get()), "Dict Str Bool Arr Ref Null Stream Dict");
+}
+
+TEST(CPDF_ObjectWalkerTest, GetParent) {
+ auto level_4 = pdfium::MakeUnique<CPDF_Null>();
+ auto level_3 = pdfium::MakeUnique<CPDF_Dictionary>();
+ level_3->SetFor("AnyObj", std::move(level_4));
+ auto level_2 =
+ pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, std::move(level_3));
+ auto level_1 = pdfium::MakeUnique<CPDF_Array>();
+ level_1->Add(std::move(level_2));
+ auto level_0 = pdfium::MakeUnique<CPDF_Dictionary>();
+ level_0->SetFor("Array", std::move(level_1));
+
+ // We have <</Array [ stream( << /AnyObj null >>) ]>>
+ // In this case each step will increase depth.
+ // And on each step the prev object should be parent for current.
+ const CPDF_Object* cur_parent = nullptr;
+ CPDF_ObjectWalker walker(level_0.get());
+ while (const CPDF_Object* obj = walker.GetNext()) {
+ EXPECT_EQ(cur_parent, walker.GetParent());
+ cur_parent = obj;
+ }
+}
+
+TEST(CPDF_ObjectWalkerTest, SkipWalkIntoCurrentObject) {
+ auto root_array = pdfium::MakeUnique<CPDF_Array>();
+ // Add 2 null objects into |root_array|. [ null1, null2 ]
+ root_array->AddNew<CPDF_Null>();
+ root_array->AddNew<CPDF_Null>();
+ // |root_array| will contain 4 null objects after this.
+ // [ null1, null2, [ null3, null4 ] ]
+ root_array->Add(root_array->Clone());
+
+ int non_array_objects = 0;
+ CPDF_ObjectWalker walker(root_array.get());
+ while (const CPDF_Object* obj = walker.GetNext()) {
+ if (obj != root_array.get() && obj->IsArray()) {
+ // skip other array except root.
+ walker.SkipWalkIntoCurrentObject();
+ }
+ if (!obj->IsArray())
+ ++non_array_objects;
+ }
+ // 2 objects from child array should be skipped.
+ EXPECT_EQ(2, non_array_objects);
+}
+
+TEST(CPDF_ObjectWalkerTest, DictionaryKey) {
+ auto dict = pdfium::MakeUnique<CPDF_Dictionary>();
+ dict->SetFor("1", pdfium::MakeUnique<CPDF_Null>());
+ dict->SetFor("2", pdfium::MakeUnique<CPDF_Null>());
+ dict->SetFor("3", pdfium::MakeUnique<CPDF_Null>());
+ dict->SetFor("4", pdfium::MakeUnique<CPDF_Null>());
+ dict->SetFor("5", pdfium::MakeUnique<CPDF_Null>());
+
+ CPDF_ObjectWalker walker(dict.get());
+ while (const CPDF_Object* obj = walker.GetNext()) {
+ if (obj == dict.get()) {
+ // Ignore root dictinary object
+ continue;
+ }
+ // Test that, dictionary key is correct.
+ EXPECT_EQ(walker.GetParent()->AsDictionary()->GetObjectFor(
+ walker.dictionary_key()),
+ obj);
+ }
+}