From bb53a5dacba0cd7e1a2108d5efbce9b692e5cb5d Mon Sep 17 00:00:00 2001 From: Wei Li Date: Wed, 3 Feb 2016 10:04:19 -0800 Subject: Merge to XFA: Complete unit tests for CPDF_Array Also remove one unnecessary member function. TBR=thestig@chromium.org Review URL: https://codereview.chromium.org/1660523003 . (cherry picked from commit 6f358daa2e8b1639a1c3a3f07a449f8450197e8b) Review URL: https://codereview.chromium.org/1667873002 . --- core/include/fpdfapi/fpdf_objects.h | 1 - .../fpdfapi/fpdf_parser/fpdf_parser_objects.cpp | 8 +- .../fpdf_parser/fpdf_parser_objects_unittest.cpp | 473 +++++++++++++++++++-- 3 files changed, 436 insertions(+), 46 deletions(-) diff --git a/core/include/fpdfapi/fpdf_objects.h b/core/include/fpdfapi/fpdf_objects.h index 86035a86ad..ddc16d95b0 100644 --- a/core/include/fpdfapi/fpdf_objects.h +++ b/core/include/fpdfapi/fpdf_objects.h @@ -312,7 +312,6 @@ class CPDF_Array : public CPDF_Object { void AddReference(CPDF_IndirectObjectHolder* pDoc, CPDF_Object* obj) { AddReference(pDoc, obj->GetObjNum()); } - void AddNumber16(FX_FLOAT value) { AddNumber(value); } protected: ~CPDF_Array(); diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp index 813c18a4c5..5f8b075296 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp @@ -454,10 +454,10 @@ void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key, void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key, const CFX_Matrix& matrix) { CPDF_Array* pArray = new CPDF_Array; - pArray->AddNumber16(matrix.a); - pArray->AddNumber16(matrix.b); - pArray->AddNumber16(matrix.c); - pArray->AddNumber16(matrix.d); + pArray->AddNumber(matrix.a); + pArray->AddNumber(matrix.b); + pArray->AddNumber(matrix.c); + pArray->AddNumber(matrix.d); pArray->AddNumber(matrix.e); pArray->AddNumber(matrix.f); SetAt(key, pArray); 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 9de31c8673..d2c30fa6ae 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp @@ -10,6 +10,31 @@ #include "core/include/fxcrt/fx_basic.h" #include "testing/gtest/include/gtest/gtest.h" +namespace { + +using ScopedArray = std::unique_ptr>; + +void TestArrayAccessors(const CPDF_Array* arr, + size_t index, + const char* str_val, + const char* const_str_val, + int int_val, + float float_val, + CPDF_Array* arr_val, + CPDF_Dictionary* dict_val, + CPDF_Stream* stream_val) { + EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str()); + EXPECT_STREQ(const_str_val, arr->GetConstStringAt(index).GetCStr()); + EXPECT_EQ(int_val, arr->GetIntegerAt(index)); + EXPECT_EQ(float_val, arr->GetNumberAt(index)); + EXPECT_EQ(float_val, arr->GetFloatAt(index)); + EXPECT_EQ(arr_val, arr->GetArrayAt(index)); + EXPECT_EQ(dict_val, arr->GetDictAt(index)); + EXPECT_EQ(stream_val, arr->GetStreamAt(index)); +} + +} // namespace + class PDFObjectsTest : public testing::Test { public: void SetUp() override { @@ -154,13 +179,13 @@ TEST_F(PDFObjectsTest, GetString) { "", "", "", ""}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) - EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), direct_obj_results[i]); + EXPECT_STREQ(direct_obj_results[i], m_DirectObjs[i]->GetString().c_str()); // Check indirect references. const char* indirect_obj_results[] = {"true", "1245", "\t\n", "space", "", "", ""}; for (size_t i = 0; i < m_RefObjs.size(); ++i) { - EXPECT_STREQ(m_RefObjs[i]->GetString().c_str(), indirect_obj_results[i]); + EXPECT_STREQ(indirect_obj_results[i], m_RefObjs[i]->GetString().c_str()); } } @@ -171,11 +196,11 @@ TEST_F(PDFObjectsTest, GetConstString) { // Check for direct objects. 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]); + EXPECT_EQ(direct_obj_results[i], + m_DirectObjs[i]->GetConstString().GetCStr()); } else { - EXPECT_STREQ(m_DirectObjs[i]->GetConstString().GetCStr(), - direct_obj_results[i]); + EXPECT_STREQ(direct_obj_results[i], + m_DirectObjs[i]->GetConstString().GetCStr()); } } // Check indirect references. @@ -183,10 +208,10 @@ TEST_F(PDFObjectsTest, GetConstString) { nullptr, nullptr, nullptr}; for (size_t i = 0; i < m_RefObjs.size(); ++i) { if (!indirect_obj_results[i]) { - EXPECT_EQ(m_RefObjs[i]->GetConstString().GetCStr(), nullptr); + EXPECT_EQ(nullptr, m_RefObjs[i]->GetConstString().GetCStr()); } else { - EXPECT_STREQ(m_RefObjs[i]->GetConstString().GetCStr(), - indirect_obj_results[i]); + EXPECT_STREQ(indirect_obj_results[i], + m_RefObjs[i]->GetConstString().GetCStr()); } } } @@ -198,12 +223,12 @@ TEST_F(PDFObjectsTest, GetUnicodeText) { 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]); + EXPECT_STREQ(direct_obj_results[i], + m_DirectObjs[i]->GetUnicodeText().c_str()); // Check indirect references. for (const auto& it : m_RefObjs) - EXPECT_STREQ(it->GetUnicodeText().c_str(), L""); + EXPECT_STREQ(L"", it->GetUnicodeText().c_str()); } TEST_F(PDFObjectsTest, GetNumber) { @@ -211,24 +236,24 @@ TEST_F(PDFObjectsTest, GetNumber) { 0, 0, 0, 0, 0}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) - EXPECT_EQ(m_DirectObjs[i]->GetNumber(), direct_obj_results[i]); + EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber()); // Check indirect references. const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0}; for (size_t i = 0; i < m_RefObjs.size(); ++i) - EXPECT_EQ(m_RefObjs[i]->GetNumber(), indirect_obj_results[i]); + EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber()); } 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 (size_t i = 0; i < m_DirectObjs.size(); ++i) - EXPECT_EQ(m_DirectObjs[i]->GetInteger(), direct_obj_results[i]); + EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetInteger()); // Check indirect references. const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0}; for (size_t i = 0; i < m_RefObjs.size(); ++i) - EXPECT_EQ(m_RefObjs[i]->GetInteger(), indirect_obj_results[i]); + EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetInteger()); } TEST_F(PDFObjectsTest, GetDict) { @@ -237,13 +262,13 @@ TEST_F(PDFObjectsTest, GetDict) { nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) - EXPECT_EQ(m_DirectObjs[i]->GetDict(), direct_obj_results[i]); + EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict()); // Check indirect references. const CPDF_Dictionary* indirect_obj_results[] = { nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj}; for (size_t i = 0; i < m_RefObjs.size(); ++i) - EXPECT_EQ(m_RefObjs[i]->GetDict(), indirect_obj_results[i]); + EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetDict()); } TEST_F(PDFObjectsTest, GetArray) { @@ -252,11 +277,11 @@ TEST_F(PDFObjectsTest, GetArray) { 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]); + EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetArray()); // Check indirect references. for (const auto& it : m_RefObjs) - EXPECT_EQ(it->GetArray(), nullptr); + EXPECT_EQ(nullptr, it->GetArray()); } TEST_F(PDFObjectsTest, Clone) { @@ -276,21 +301,21 @@ TEST_F(PDFObjectsTest, Clone) { 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]); + EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType()); // Check indirect references. for (const auto& it : m_RefObjs) - EXPECT_EQ(it->GetType(), CPDF_Object::REFERENCE); + EXPECT_EQ(CPDF_Object::REFERENCE, it->GetType()); } 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()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->GetDirect()); // Check indirect references. for (size_t i = 0; i < m_RefObjs.size(); ++i) - EXPECT_EQ(m_RefObjs[i]->GetDirect(), m_IndirectObjs[i]); + EXPECT_EQ(m_IndirectObjs[i], m_RefObjs[i]->GetDirect()); } TEST_F(PDFObjectsTest, SetString) { @@ -301,7 +326,7 @@ TEST_F(PDFObjectsTest, SetString) { "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]); + EXPECT_STREQ(expected[i], m_DirectObjs[i]->GetString().c_str()); } } @@ -310,66 +335,432 @@ TEST_F(PDFObjectsTest, IsTypeAndAsType) { 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()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsArray()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsArray()); - EXPECT_EQ(m_DirectObjs[i]->AsArray(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsArray()); } if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) { EXPECT_TRUE(m_DirectObjs[i]->IsBoolean()); - EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsBoolean()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsBoolean()); - EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsBoolean()); } if (m_DirectObjTypes[i] == CPDF_Object::NAME) { EXPECT_TRUE(m_DirectObjs[i]->IsName()); - EXPECT_EQ(m_DirectObjs[i]->AsName(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsName()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsName()); - EXPECT_EQ(m_DirectObjs[i]->AsName(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsName()); } if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) { EXPECT_TRUE(m_DirectObjs[i]->IsNumber()); - EXPECT_EQ(m_DirectObjs[i]->AsNumber(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsNumber()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsNumber()); - EXPECT_EQ(m_DirectObjs[i]->AsNumber(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsNumber()); } if (m_DirectObjTypes[i] == CPDF_Object::STRING) { EXPECT_TRUE(m_DirectObjs[i]->IsString()); - EXPECT_EQ(m_DirectObjs[i]->AsString(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsString()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsString()); - EXPECT_EQ(m_DirectObjs[i]->AsString(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsString()); } if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) { EXPECT_TRUE(m_DirectObjs[i]->IsDictionary()); - EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsDictionary()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsDictionary()); - EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsDictionary()); } if (m_DirectObjTypes[i] == CPDF_Object::STREAM) { EXPECT_TRUE(m_DirectObjs[i]->IsStream()); - EXPECT_EQ(m_DirectObjs[i]->AsStream(), m_DirectObjs[i].get()); + EXPECT_EQ(m_DirectObjs[i].get(), m_DirectObjs[i]->AsStream()); } else { EXPECT_FALSE(m_DirectObjs[i]->IsStream()); - EXPECT_EQ(m_DirectObjs[i]->AsStream(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsStream()); } EXPECT_FALSE(m_DirectObjs[i]->IsReference()); - EXPECT_EQ(m_DirectObjs[i]->AsReference(), nullptr); + EXPECT_EQ(nullptr, m_DirectObjs[i]->AsReference()); } // 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()); + EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference()); + } +} + +TEST(PDFArrayTest, GetMatrix) { + float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, + {1, 2, 3, 4, 5, 6}, + {2.3f, 4.05f, 3, -2, -3, 0.0f}, + {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}}; + for (size_t i = 0; i < FX_ArraySize(elems); ++i) { + ScopedArray arr(new CPDF_Array); + CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3], + elems[i][4], elems[i][5]); + for (size_t j = 0; j < 6; ++j) + arr->AddNumber(elems[i][j]); + CFX_Matrix arr_matrix = arr->GetMatrix(); + EXPECT_EQ(matrix.GetA(), arr_matrix.GetA()); + EXPECT_EQ(matrix.GetB(), arr_matrix.GetB()); + EXPECT_EQ(matrix.GetC(), arr_matrix.GetC()); + EXPECT_EQ(matrix.GetD(), arr_matrix.GetD()); + EXPECT_EQ(matrix.GetE(), arr_matrix.GetE()); + EXPECT_EQ(matrix.GetF(), arr_matrix.GetF()); + } +} + +TEST(PDFArrayTest, GetRect) { + float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, + {1, 2, 5, 6}, + {2.3f, 4.05f, -3, 0.0f}, + {0.05f, 0.1f, 1.34f, 99.9f}}; + for (size_t i = 0; i < FX_ArraySize(elems); ++i) { + ScopedArray arr(new CPDF_Array); + CFX_FloatRect rect(elems[i]); + for (size_t j = 0; j < 4; ++j) + arr->AddNumber(elems[i][j]); + CFX_FloatRect arr_rect = arr->GetRect(); + EXPECT_EQ(rect.left, arr_rect.left); + EXPECT_EQ(rect.right, arr_rect.right); + EXPECT_EQ(rect.bottom, arr_rect.bottom); + EXPECT_EQ(rect.top, arr_rect.top); + } +} + +TEST(PDFArrayTest, GetTypeAt) { + { + // Boolean array. + bool vals[] = {true, false, false, true, true}; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) + arr->InsertAt(i, new CPDF_Boolean(vals[i])); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + vals[i] ? "true" : "false", // String value. + nullptr, // Const string value. + vals[i] ? 1 : 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // Integer array. + int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767}; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) + arr->InsertAt(i, new CPDF_Number(vals[i])); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + char buf[33]; + TestArrayAccessors(arr.get(), i, // Array and index. + FXSYS_itoa(vals[i], buf, 10), // String value. + nullptr, // Const string value. + vals[i], // Integer value. + vals[i], // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // Float array. + float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f, + 897.34f, -2.5f, -1.0f, -345.0f, -0.0f}; + const char* expected_str[] = {"0", "0", "10", "10", "0.0345", + "897.34", "-2.5", "-1", "-345", "0"}; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + arr->InsertAt(i, new CPDF_Number(vals[i])); + } + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + expected_str[i], // String value. + nullptr, // Const string value. + vals[i], // Integer value. + vals[i], // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // String and name array + const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012", + ".", "EYREW", "It is a joke :)"}; + ScopedArray string_array(new CPDF_Array); + ScopedArray name_array(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + string_array->InsertAt(i, new CPDF_String(vals[i], false)); + name_array->InsertAt(i, new CPDF_Name(vals[i])); + } + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + TestArrayAccessors(string_array.get(), i, // Array and index. + vals[i], // String value. + vals[i], // Const string value. + 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + TestArrayAccessors(name_array.get(), i, // Array and index. + vals[i], // String value. + vals[i], // Const string value. + 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // Null element array. + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < 3; ++i) + arr->InsertAt(i, new CPDF_Null); + for (size_t i = 0; i < 3; ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + "", // String value. + nullptr, // Const string value. + 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // Array of array. + CPDF_Array* vals[3]; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < 3; ++i) { + vals[i] = new CPDF_Array; + for (size_t j = 0; j < 3; ++j) { + int value = j + 100; + vals[i]->InsertAt(i, new CPDF_Number(value)); + } + arr->InsertAt(i, vals[i]); + } + for (size_t i = 0; i < 3; ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + "", // String value. + nullptr, // Const string value. + 0, // Integer value. + 0, // Float value. + vals[i], // Array value. + nullptr, // Dictionary value. + nullptr); // Stream value. + } + } + { + // Dictionary array. + CPDF_Dictionary* vals[3]; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < 3; ++i) { + vals[i] = new CPDF_Dictionary; + for (size_t j = 0; j < 3; ++j) { + std::string key("key"); + char buf[33]; + key.append(FXSYS_itoa(j, buf, 10)); + int value = j + 200; + vals[i]->SetAt(CFX_ByteStringC(key.c_str()), new CPDF_Number(value)); + } + arr->InsertAt(i, vals[i]); + } + for (size_t i = 0; i < 3; ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + "", // String value. + nullptr, // Const string value. + 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + vals[i], // Dictionary value. + nullptr); // Stream value. + } + } + { + // Stream array. + CPDF_Dictionary* vals[3]; + CPDF_Stream* stream_vals[3]; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < 3; ++i) { + vals[i] = new CPDF_Dictionary; + for (size_t j = 0; j < 3; ++j) { + std::string key("key"); + char buf[33]; + key.append(FXSYS_itoa(j, buf, 10)); + int value = j + 200; + vals[i]->SetAt(CFX_ByteStringC(key.c_str()), new CPDF_Number(value)); + } + uint8_t content[] = "content: this is a stream"; + size_t data_size = FX_ArraySize(content); + uint8_t* data = reinterpret_cast(malloc(data_size)); + memcpy(data, content, data_size); + stream_vals[i] = new CPDF_Stream(data, data_size, vals[i]); + arr->InsertAt(i, stream_vals[i]); + } + for (size_t i = 0; i < 3; ++i) { + TestArrayAccessors(arr.get(), i, // Array and index. + "", // String value. + nullptr, // Const string value. + 0, // Integer value. + 0, // Float value. + nullptr, // Array value. + vals[i], // Dictionary value. + stream_vals[i]); // Stream value. + } + } + { + // Mixed array. + ScopedArray arr(new CPDF_Array); + // Array arr will take ownership of all the objects inserted. + arr->InsertAt(0, new CPDF_Boolean(true)); + arr->InsertAt(1, new CPDF_Boolean(false)); + arr->InsertAt(2, new CPDF_Number(0)); + arr->InsertAt(3, new CPDF_Number(-1234)); + arr->InsertAt(4, new CPDF_Number(2345.0f)); + arr->InsertAt(5, new CPDF_Number(0.05f)); + arr->InsertAt(6, new CPDF_String("", false)); + arr->InsertAt(7, new CPDF_String("It is a test!", false)); + arr->InsertAt(8, new CPDF_Name("NAME")); + arr->InsertAt(9, new CPDF_Name("test")); + arr->InsertAt(10, new CPDF_Null()); + CPDF_Array* arr_val = new CPDF_Array; + arr_val->AddNumber(1); + arr_val->AddNumber(2); + arr->InsertAt(11, arr_val); + CPDF_Dictionary* dict_val = new CPDF_Dictionary; + dict_val->SetAt("key1", new CPDF_String("Linda", false)); + dict_val->SetAt("key2", new CPDF_String("Zoe", false)); + arr->InsertAt(12, dict_val); + CPDF_Dictionary* stream_dict = new CPDF_Dictionary; + stream_dict->SetAt("key1", new CPDF_String("John", false)); + stream_dict->SetAt("key2", new CPDF_String("King", false)); + uint8_t data[] = "A stream for test"; + // The data buffer will be owned by stream object, so it needs to be + // dynamically allocated. + size_t buf_size = sizeof(data); + uint8_t* buf = reinterpret_cast(malloc(buf_size)); + memcpy(buf, data, buf_size); + CPDF_Stream* stream_val = new CPDF_Stream(buf, buf_size, stream_dict); + arr->InsertAt(13, stream_val); + const char* const expected_str[] = { + "true", "false", "0", "-1234", "2345", "0.05", "", + "It is a test!", "NAME", "test", "", "", "", ""}; + const char* const expected_cstr[] = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + "It is a test!", "NAME", "test", nullptr, nullptr, nullptr, nullptr}; + const int expected_int[] = {1, 0, 0, -1234, 2345, 0, 0, + 0, 0, 0, 0, 0, 0, 0}; + const float expected_float[] = {0, 0, 0, -1234, 2345, 0.05f, 0, + 0, 0, 0, 0, 0, 0, 0}; + for (size_t i = 0; i < arr->GetCount(); ++i) { + EXPECT_STREQ(expected_str[i], arr->GetStringAt(i).c_str()); + EXPECT_STREQ(expected_cstr[i], arr->GetConstStringAt(i).GetCStr()); + EXPECT_EQ(expected_int[i], arr->GetIntegerAt(i)); + EXPECT_EQ(expected_float[i], arr->GetNumberAt(i)); + EXPECT_EQ(expected_float[i], arr->GetFloatAt(i)); + if (i == 11) + EXPECT_EQ(arr_val, arr->GetArrayAt(i)); + else + EXPECT_EQ(nullptr, arr->GetArrayAt(i)); + if (i == 13) { + EXPECT_EQ(stream_dict, arr->GetDictAt(i)); + EXPECT_EQ(stream_val, arr->GetStreamAt(i)); + } else { + EXPECT_EQ(nullptr, arr->GetStreamAt(i)); + if (i == 12) + EXPECT_EQ(dict_val, arr->GetDictAt(i)); + else + EXPECT_EQ(nullptr, arr->GetDictAt(i)); + } + } + } +} + +TEST(PDFArrayTest, AddNumber) { + float vals[] = {1.0f, -1.0f, 0, 0.456734f, + 12345.54321f, 0.5f, 1000, 0.000045f}; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) + arr->AddNumber(vals[i]); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + EXPECT_EQ(CPDF_Object::NUMBER, arr->GetElement(i)->GetType()); + EXPECT_EQ(vals[i], arr->GetElement(i)->GetNumber()); + } +} + +TEST(PDFArrayTest, AddInteger) { + int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100}; + ScopedArray arr(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) + arr->AddInteger(vals[i]); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + EXPECT_EQ(CPDF_Object::NUMBER, arr->GetElement(i)->GetType()); + EXPECT_EQ(vals[i], arr->GetElement(i)->GetNumber()); + } +} + +TEST(PDFArrayTest, AddStringAndName) { + const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323", + "$#%^&**", " ", "This is a test.\r\n"}; + ScopedArray string_array(new CPDF_Array); + ScopedArray name_array(new CPDF_Array); + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + string_array->AddString(vals[i]); + name_array->AddName(vals[i]); + } + for (size_t i = 0; i < FX_ArraySize(vals); ++i) { + EXPECT_EQ(CPDF_Object::STRING, string_array->GetElement(i)->GetType()); + EXPECT_STREQ(vals[i], string_array->GetElement(i)->GetString().c_str()); + EXPECT_EQ(CPDF_Object::NAME, name_array->GetElement(i)->GetType()); + EXPECT_STREQ(vals[i], name_array->GetElement(i)->GetString().c_str()); + } +} + +TEST(PDFArrayTest, AddReferenceAndGetElement) { + std::unique_ptr holder( + new CPDF_IndirectObjectHolder(nullptr)); + CPDF_Boolean* boolean_obj = new CPDF_Boolean(true); + CPDF_Number* int_obj = new CPDF_Number(-1234); + CPDF_Number* float_obj = new CPDF_Number(2345.089f); + CPDF_String* str_obj = new CPDF_String("Adsfdsf 343434 %&&*\n", false); + CPDF_Name* name_obj = new CPDF_Name("Title:"); + CPDF_Null* null_obj = new CPDF_Null(); + CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj, + str_obj, name_obj, null_obj}; + unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1}; + ScopedArray arr(new CPDF_Array); + ScopedArray arr1(new CPDF_Array); + // Create two arrays of references by different AddReference() APIs. + for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) { + // All the indirect objects inserted will be owned by holder. + holder->InsertIndirectObject(obj_nums[i], indirect_objs[i]); + arr->AddReference(holder.get(), obj_nums[i]); + arr1->AddReference(holder.get(), indirect_objs[i]); + } + // Check indirect objects. + for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i) + EXPECT_EQ(indirect_objs[i], holder->GetIndirectObject(obj_nums[i])); + // Check arrays. + EXPECT_EQ(arr->GetCount(), arr1->GetCount()); + for (size_t i = 0; i < arr->GetCount(); ++i) { + EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetElement(i)->GetType()); + EXPECT_EQ(indirect_objs[i], arr->GetElement(i)->GetDirect()); + EXPECT_EQ(indirect_objs[i], arr->GetElementValue(i)); + EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetElement(i)->GetType()); + EXPECT_EQ(indirect_objs[i], arr1->GetElement(i)->GetDirect()); + EXPECT_EQ(indirect_objs[i], arr1->GetElementValue(i)); } } -- cgit v1.2.3