diff options
Diffstat (limited to 'core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp')
-rw-r--r-- | core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp | 263 |
1 files changed, 239 insertions, 24 deletions
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp index 3965399254..9de31c8673 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp @@ -26,9 +26,9 @@ class PDFObjectsTest : public testing::Test { // Name object. CPDF_Name* name_obj = new CPDF_Name("space"); // Array object. - CPDF_Array* array_obj = new CPDF_Array; - array_obj->InsertAt(0, new CPDF_Number(8902)); - array_obj->InsertAt(1, new CPDF_Name("address")); + m_ArrayObj = new CPDF_Array; + m_ArrayObj->InsertAt(0, new CPDF_Number(8902)); + m_ArrayObj->InsertAt(1, new CPDF_Name("address")); // Dictionary object. m_DictObj = new CPDF_Dictionary; m_DictObj->SetAt("bool", new CPDF_Boolean(false)); @@ -47,23 +47,92 @@ class PDFObjectsTest : public testing::Test { // All direct objects. CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, number_float_obj, str_reg_obj, str_spec_obj, - name_obj, array_obj, m_DictObj, + name_obj, m_ArrayObj, m_DictObj, stream_obj, null_obj}; - for (int i = 0; i < FX_ArraySize(objs); ++i) + m_DirectObjTypes = { + CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, + CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING, + CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY, + CPDF_Object::STREAM, CPDF_Object::NULLOBJ}; + for (size_t i = 0; i < FX_ArraySize(objs); ++i) m_DirectObjs.emplace_back(objs[i]); // Indirect references to indirect objects. m_ObjHolder.reset(new CPDF_IndirectObjectHolder(nullptr)); - CPDF_Object* referred_objs[] = { - boolean_true_obj, number_int_obj, str_spec_obj, name_obj, - array_obj, m_DictObj, stream_obj}; - for (int i = 0; i < FX_ArraySize(referred_objs); ++i) { - m_ObjHolder->AddIndirectObject(referred_objs[i]); - m_RefObjs.emplace_back( - new CPDF_Reference(m_ObjHolder.get(), referred_objs[i]->GetObjNum())); + m_IndirectObjs = {boolean_true_obj, number_int_obj, str_spec_obj, name_obj, + m_ArrayObj, m_DictObj, stream_obj}; + for (size_t i = 0; i < m_IndirectObjs.size(); ++i) { + m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]); + m_RefObjs.emplace_back(new CPDF_Reference( + m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum())); } } + bool Equal(CPDF_Object* obj1, CPDF_Object* obj2) { + if (obj1 == obj2) + return true; + if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType()) + return false; + switch (obj1->GetType()) { + case CPDF_Object::BOOLEAN: + return obj1->GetInteger() == obj2->GetInteger(); + case CPDF_Object::NUMBER: + return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() && + obj1->GetInteger() == obj2->GetInteger(); + case CPDF_Object::STRING: + case CPDF_Object::NAME: + return obj1->GetString() == obj2->GetString(); + case CPDF_Object::ARRAY: { + const CPDF_Array* array1 = obj1->AsArray(); + const CPDF_Array* array2 = obj2->AsArray(); + if (array1->GetCount() != array2->GetCount()) + return false; + for (size_t i = 0; i < array1->GetCount(); ++i) { + if (!Equal(array1->GetElement(i), array2->GetElement(i))) + return false; + } + return true; + } + case CPDF_Object::DICTIONARY: { + const CPDF_Dictionary* dict1 = obj1->AsDictionary(); + const CPDF_Dictionary* dict2 = obj2->AsDictionary(); + if (dict1->GetCount() != dict2->GetCount()) + return false; + for (CPDF_Dictionary::const_iterator it = dict1->begin(); + it != dict1->end(); ++it) { + if (!Equal(it->second, dict2->GetElement(it->first))) + return false; + } + return true; + } + case CPDF_Object::NULLOBJ: + return true; + case CPDF_Object::STREAM: { + const CPDF_Stream* stream1 = obj1->AsStream(); + const CPDF_Stream* stream2 = obj2->AsStream(); + if (!stream1->GetDict() && !stream2->GetDict()) + return true; + // Compare dictionaries. + if (!Equal(stream1->GetDict(), stream2->GetDict())) + return false; + // Compare sizes. + if (stream1->GetRawSize() != stream2->GetRawSize()) + return false; + // Compare contents. + // Since this function is used for testing Clone(), only memory based + // streams need to be handled. + if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased()) + return false; + return FXSYS_memcmp(stream1->GetRawData(), stream2->GetRawData(), + stream1->GetRawSize()) == 0; + } + case CPDF_Object::REFERENCE: + return obj1->AsReference()->GetRefObjNum() == + obj2->AsReference()->GetRefObjNum(); + } + return false; + } + protected: using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>; @@ -71,9 +140,12 @@ class PDFObjectsTest : public testing::Test { // refers to some objects in m_DirectObjs. std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder; std::vector<ScopedObj> m_DirectObjs; + std::vector<int> m_DirectObjTypes; std::vector<ScopedObj> m_RefObjs; CPDF_Dictionary* m_DictObj; CPDF_Dictionary* m_StreamDictObj; + CPDF_Array* m_ArrayObj; + std::vector<CPDF_Object*> m_IndirectObjs; }; TEST_F(PDFObjectsTest, GetString) { @@ -81,13 +153,13 @@ TEST_F(PDFObjectsTest, GetString) { "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space", "", "", "", ""}; // Check for direct objects. - for (int i = 0; i < m_DirectObjs.size(); ++i) + for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), direct_obj_results[i]); // Check indirect references. const char* indirect_obj_results[] = {"true", "1245", "\t\n", "space", "", "", ""}; - for (int i = 0; i < m_RefObjs.size(); ++i) { + for (size_t i = 0; i < m_RefObjs.size(); ++i) { EXPECT_STREQ(m_RefObjs[i]->GetString().c_str(), indirect_obj_results[i]); } } @@ -97,7 +169,7 @@ TEST_F(PDFObjectsTest, GetConstString) { nullptr, nullptr, nullptr, nullptr, "A simple test", "\t\n", "space", nullptr, nullptr, nullptr, nullptr}; // Check for direct objects. - for (int i = 0; i < m_DirectObjs.size(); ++i) { + for (size_t i = 0; i < m_DirectObjs.size(); ++i) { if (!direct_obj_results[i]) { EXPECT_EQ(m_DirectObjs[i]->GetConstString().GetCStr(), direct_obj_results[i]); @@ -109,38 +181,53 @@ TEST_F(PDFObjectsTest, GetConstString) { // Check indirect references. const char* indirect_obj_results[] = {nullptr, nullptr, "\t\n", "space", nullptr, nullptr, nullptr}; - for (int i = 0; i < m_RefObjs.size(); ++i) { - if (!indirect_obj_results[i]) + for (size_t i = 0; i < m_RefObjs.size(); ++i) { + if (!indirect_obj_results[i]) { EXPECT_EQ(m_RefObjs[i]->GetConstString().GetCStr(), nullptr); - else { + } else { EXPECT_STREQ(m_RefObjs[i]->GetConstString().GetCStr(), indirect_obj_results[i]); } } } +TEST_F(PDFObjectsTest, GetUnicodeText) { + const wchar_t* direct_obj_results[] = { + L"", L"", L"", L"", L"A simple test", + L"\t\n", L"space", L"", L"", L"abcdefghijklmnopqrstuvwxyz", + L""}; + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) + EXPECT_STREQ(m_DirectObjs[i]->GetUnicodeText().c_str(), + direct_obj_results[i]); + + // Check indirect references. + for (const auto& it : m_RefObjs) + EXPECT_STREQ(it->GetUnicodeText().c_str(), L""); +} + TEST_F(PDFObjectsTest, GetNumber) { const FX_FLOAT direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0, 0, 0, 0, 0, 0}; // Check for direct objects. - for (int i = 0; i < m_DirectObjs.size(); ++i) + for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(m_DirectObjs[i]->GetNumber(), direct_obj_results[i]); // Check indirect references. const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0}; - for (int i = 0; i < m_RefObjs.size(); ++i) + for (size_t i = 0; i < m_RefObjs.size(); ++i) EXPECT_EQ(m_RefObjs[i]->GetNumber(), indirect_obj_results[i]); } TEST_F(PDFObjectsTest, GetInteger) { const int direct_obj_results[] = {0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0}; // Check for direct objects. - for (int i = 0; i < m_DirectObjs.size(); ++i) + for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(m_DirectObjs[i]->GetInteger(), direct_obj_results[i]); // Check indirect references. const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0}; - for (int i = 0; i < m_RefObjs.size(); ++i) + for (size_t i = 0; i < m_RefObjs.size(); ++i) EXPECT_EQ(m_RefObjs[i]->GetInteger(), indirect_obj_results[i]); } @@ -149,12 +236,140 @@ TEST_F(PDFObjectsTest, GetDict) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr}; // Check for direct objects. - for (int i = 0; i < m_DirectObjs.size(); ++i) + for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(m_DirectObjs[i]->GetDict(), direct_obj_results[i]); // Check indirect references. const CPDF_Dictionary* indirect_obj_results[] = { nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj}; - for (int i = 0; i < m_RefObjs.size(); ++i) + for (size_t i = 0; i < m_RefObjs.size(); ++i) EXPECT_EQ(m_RefObjs[i]->GetDict(), indirect_obj_results[i]); } + +TEST_F(PDFObjectsTest, GetArray) { + const CPDF_Array* direct_obj_results[] = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, m_ArrayObj, nullptr, nullptr, nullptr}; + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) + EXPECT_EQ(m_DirectObjs[i]->GetArray(), direct_obj_results[i]); + + // Check indirect references. + for (const auto& it : m_RefObjs) + EXPECT_EQ(it->GetArray(), nullptr); +} + +TEST_F(PDFObjectsTest, Clone) { + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) { + ScopedObj obj(m_DirectObjs[i]->Clone()); + EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get())); + } + + // Check indirect references. + for (const auto& it : m_RefObjs) { + ScopedObj obj(it->Clone()); + EXPECT_TRUE(Equal(it.get(), obj.get())); + } +} + +TEST_F(PDFObjectsTest, GetType) { + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) + EXPECT_EQ(m_DirectObjs[i]->GetType(), m_DirectObjTypes[i]); + + // Check indirect references. + for (const auto& it : m_RefObjs) + EXPECT_EQ(it->GetType(), CPDF_Object::REFERENCE); +} + +TEST_F(PDFObjectsTest, GetDirect) { + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) + EXPECT_EQ(m_DirectObjs[i]->GetDirect(), m_DirectObjs[i].get()); + + // Check indirect references. + for (size_t i = 0; i < m_RefObjs.size(); ++i) + EXPECT_EQ(m_RefObjs[i]->GetDirect(), m_IndirectObjs[i]); +} + +TEST_F(PDFObjectsTest, SetString) { + // Check for direct objects. + const char* const set_values[] = {"true", "fake", "3.125f", "097", + "changed", "", "NewName"}; + const char* expected[] = {"true", "false", "3.125", "97", + "changed", "", "NewName"}; + for (size_t i = 0; i < FX_ArraySize(set_values); ++i) { + m_DirectObjs[i]->SetString(set_values[i]); + EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), expected[i]); + } +} + +TEST_F(PDFObjectsTest, IsTypeAndAsType) { + // Check for direct objects. + for (size_t i = 0; i < m_DirectObjs.size(); ++i) { + if (m_DirectObjTypes[i] == CPDF_Object::ARRAY) { + EXPECT_TRUE(m_DirectObjs[i]->IsArray()); + EXPECT_EQ(m_DirectObjs[i]->AsArray(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsArray()); + EXPECT_EQ(m_DirectObjs[i]->AsArray(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) { + EXPECT_TRUE(m_DirectObjs[i]->IsBoolean()); + EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsBoolean()); + EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::NAME) { + EXPECT_TRUE(m_DirectObjs[i]->IsName()); + EXPECT_EQ(m_DirectObjs[i]->AsName(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsName()); + EXPECT_EQ(m_DirectObjs[i]->AsName(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) { + EXPECT_TRUE(m_DirectObjs[i]->IsNumber()); + EXPECT_EQ(m_DirectObjs[i]->AsNumber(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsNumber()); + EXPECT_EQ(m_DirectObjs[i]->AsNumber(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::STRING) { + EXPECT_TRUE(m_DirectObjs[i]->IsString()); + EXPECT_EQ(m_DirectObjs[i]->AsString(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsString()); + EXPECT_EQ(m_DirectObjs[i]->AsString(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) { + EXPECT_TRUE(m_DirectObjs[i]->IsDictionary()); + EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsDictionary()); + EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), nullptr); + } + + if (m_DirectObjTypes[i] == CPDF_Object::STREAM) { + EXPECT_TRUE(m_DirectObjs[i]->IsStream()); + EXPECT_EQ(m_DirectObjs[i]->AsStream(), m_DirectObjs[i].get()); + } else { + EXPECT_FALSE(m_DirectObjs[i]->IsStream()); + EXPECT_EQ(m_DirectObjs[i]->AsStream(), nullptr); + } + + EXPECT_FALSE(m_DirectObjs[i]->IsReference()); + EXPECT_EQ(m_DirectObjs[i]->AsReference(), nullptr); + } + // Check indirect references. + for (size_t i = 0; i < m_RefObjs.size(); ++i) { + EXPECT_TRUE(m_RefObjs[i]->IsReference()); + EXPECT_EQ(m_RefObjs[i]->AsReference(), m_RefObjs[i].get()); + } +} |