[Libreoffice-commits] core.git: vcl/CppunitTest_vcl_pdfium_library_test.mk vcl/qa

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Sun Nov 22 23:51:25 UTC 2020


 vcl/CppunitTest_vcl_pdfium_library_test.mk |    1 
 vcl/qa/cppunit/PDFDocumentTest.cxx         |  588 +++++++++++++++++++++++++++++
 vcl/qa/cppunit/data/basic.pdf              |   71 +++
 vcl/qa/cppunit/data/basicSource.pdf        |   60 ++
 4 files changed, 720 insertions(+)

New commits:
commit f313e27fb7f2d42247407e26e16f264e30f87ca5
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Nov 9 19:19:19 2020 +0100
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Nov 23 00:50:46 2020 +0100

    pdf: test PDFDocument parsing
    
    basic.pdf is custom created so it covers all different parsing
    use-cases.
    
    Change-Id: I6eefa55b1cec5bf7eb91518d6a2df2cb48746dcc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105494
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/CppunitTest_vcl_pdfium_library_test.mk b/vcl/CppunitTest_vcl_pdfium_library_test.mk
index 0f4a480c8254..37acb1125506 100644
--- a/vcl/CppunitTest_vcl_pdfium_library_test.mk
+++ b/vcl/CppunitTest_vcl_pdfium_library_test.mk
@@ -11,6 +11,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,vcl_pdfium_library_test))
 
 $(eval $(call gb_CppunitTest_add_exception_objects,vcl_pdfium_library_test, \
     vcl/qa/cppunit/PDFiumLibraryTest \
+    vcl/qa/cppunit/PDFDocumentTest \
 ))
 
 $(eval $(call gb_CppunitTest_use_sdk_api,vcl_pdfium_library_test))
diff --git a/vcl/qa/cppunit/PDFDocumentTest.cxx b/vcl/qa/cppunit/PDFDocumentTest.cxx
new file mode 100644
index 000000000000..66de7dfc77d4
--- /dev/null
+++ b/vcl/qa/cppunit/PDFDocumentTest.cxx
@@ -0,0 +1,588 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <vcl/filter/pdfdocument.hxx>
+
+class PDFDocumentTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+public:
+    PDFDocumentTest() = default;
+};
+
+char const DATA_DIRECTORY[] = "/vcl/qa/cppunit/data/";
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseBasicPDF)
+{
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "basic.pdf";
+    vcl::filter::PDFDocument aDocument;
+    SvFileStream aStream(aURL, StreamMode::READ);
+    CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+    std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
+
+    vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+    CPPUNIT_ASSERT(pResources);
+
+    vcl::filter::PDFObjectElement* pTest = pResources->LookupObject("Test");
+    CPPUNIT_ASSERT(pTest);
+
+    vcl::filter::PDFObjectElement* pTestArray1 = pTest->LookupObject("TestArray1");
+    CPPUNIT_ASSERT(pTestArray1);
+    {
+        CPPUNIT_ASSERT_EQUAL(size_t(5), pTestArray1->GetArray()->GetElements().size());
+    }
+
+    vcl::filter::PDFObjectElement* pTestArray2 = pTest->LookupObject("TestArray2");
+    CPPUNIT_ASSERT(pTestArray2);
+    {
+        CPPUNIT_ASSERT_EQUAL(size_t(2), pTestArray2->GetArray()->GetElements().size());
+    }
+
+    vcl::filter::PDFObjectElement* pTestDictionary = pTest->LookupObject("TestDictionary");
+    {
+        sal_uInt64 nOffset = pTestDictionary->GetDictionaryOffset();
+        sal_uInt64 nLength = pTestDictionary->GetDictionaryLength();
+
+        aStream.Seek(nOffset);
+        std::vector<char> aBuffer(nLength + 1, 0);
+        aStream.ReadBytes(aBuffer.data(), nLength);
+        OString aString(aBuffer.data());
+
+        CPPUNIT_ASSERT_EQUAL(
+            OString("/TestReference 7 0 R/TestNumber "
+                    "123/TestName/SomeName/TestDictionary<</Key/Value>>/TestArray[1 2 3]"),
+            aString);
+    }
+
+    CPPUNIT_ASSERT(pTestDictionary);
+    {
+        auto const& rItems = pTestDictionary->GetDictionaryItems();
+        CPPUNIT_ASSERT_EQUAL(size_t(5), rItems.size());
+        auto* pReference = dynamic_cast<vcl::filter::PDFReferenceElement*>(
+            pTestDictionary->Lookup("TestReference"));
+        CPPUNIT_ASSERT(pReference);
+        CPPUNIT_ASSERT_EQUAL(7, pReference->GetObjectValue());
+
+        auto* pNumber
+            = dynamic_cast<vcl::filter::PDFNumberElement*>(pTestDictionary->Lookup("TestNumber"));
+        CPPUNIT_ASSERT(pNumber);
+        CPPUNIT_ASSERT_EQUAL(123.0, pNumber->GetValue());
+
+        auto* pName
+            = dynamic_cast<vcl::filter::PDFNameElement*>(pTestDictionary->Lookup("TestName"));
+        CPPUNIT_ASSERT(pName);
+        CPPUNIT_ASSERT_EQUAL(OString("SomeName"), pName->GetValue());
+
+        auto* pDictionary = dynamic_cast<vcl::filter::PDFDictionaryElement*>(
+            pTestDictionary->Lookup("TestDictionary"));
+        CPPUNIT_ASSERT(pDictionary);
+
+        auto* pArray
+            = dynamic_cast<vcl::filter::PDFArrayElement*>(pTestDictionary->Lookup("TestArray"));
+        CPPUNIT_ASSERT(pArray);
+
+        // Check offsets and lengths
+        {
+            sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestReference");
+            sal_uInt64 nLength
+                = pTestDictionary->GetDictionary()->GetKeyValueLength("TestReference");
+
+            aStream.Seek(nOffset);
+            std::vector<char> aBuffer(nLength + 1, 0);
+            aStream.ReadBytes(aBuffer.data(), nLength);
+            OString aString(aBuffer.data());
+
+            CPPUNIT_ASSERT_EQUAL(OString("TestReference 7 0 R"), aString);
+        }
+        {
+            sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestNumber");
+            sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestNumber");
+
+            aStream.Seek(nOffset);
+            std::vector<char> aBuffer(nLength + 1, 0);
+            aStream.ReadBytes(aBuffer.data(), nLength);
+            OString aString(aBuffer.data());
+
+            CPPUNIT_ASSERT_EQUAL(OString("TestNumber 123"), aString);
+        }
+        {
+            sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestName");
+            sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestName");
+
+            aStream.Seek(nOffset);
+            std::vector<char> aBuffer(nLength + 1, 0);
+            aStream.ReadBytes(aBuffer.data(), nLength);
+            OString aString(aBuffer.data());
+
+            CPPUNIT_ASSERT_EQUAL(OString("TestName/SomeName"), aString);
+        }
+        {
+            sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestDictionary");
+            sal_uInt64 nLength
+                = pTestDictionary->GetDictionary()->GetKeyValueLength("TestDictionary");
+
+            aStream.Seek(nOffset);
+            std::vector<char> aBuffer(nLength + 1, 0);
+            aStream.ReadBytes(aBuffer.data(), nLength);
+            OString aString(aBuffer.data());
+
+            CPPUNIT_ASSERT_EQUAL(OString("TestDictionary<</Key/Value>>"), aString);
+        }
+        {
+            sal_uInt64 nOffset = pTestDictionary->GetDictionary()->GetKeyOffset("TestArray");
+            sal_uInt64 nLength = pTestDictionary->GetDictionary()->GetKeyValueLength("TestArray");
+
+            aStream.Seek(nOffset);
+            std::vector<char> aBuffer(nLength + 1, 0);
+            aStream.ReadBytes(aBuffer.data(), nLength);
+            OString aString(aBuffer.data());
+
+            CPPUNIT_ASSERT_EQUAL(OString("TestArray[1 2 3]"), aString);
+        }
+    }
+}
+
+namespace
+{
+vcl::filter::PDFObjectElement*
+addObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+                 vcl::filter::PDFDocument& rDocument, int nObjectNumber, int nGenerationNumber)
+{
+    auto pObject = std::make_unique<vcl::filter::PDFObjectElement>(rDocument, nObjectNumber,
+                                                                   nGenerationNumber);
+    auto pObjectPtr = pObject.get();
+    rElements.push_back(std::move(pObject));
+    return pObjectPtr;
+}
+
+vcl::filter::PDFTrailerElement*
+addTrailerObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+                        vcl::filter::PDFDocument& rDocument)
+{
+    auto pTrailer = std::make_unique<vcl::filter::PDFTrailerElement>(rDocument);
+    auto pTrailerPtr = pTrailer.get();
+    rElements.push_back(std::move(pTrailer));
+    return pTrailerPtr;
+}
+void addEndObjectElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+    rElements.push_back(std::make_unique<vcl::filter::PDFEndObjectElement>());
+}
+
+void addDictionaryElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+    rElements.push_back(std::make_unique<vcl::filter::PDFDictionaryElement>());
+}
+
+void addEndDictionaryElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+    rElements.push_back(std::make_unique<vcl::filter::PDFEndDictionaryElement>());
+}
+
+void addNameElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+                    OString const& rName)
+{
+    auto pNameElement = std::make_unique<vcl::filter::PDFNameElement>();
+    pNameElement->SetValue(rName);
+    rElements.push_back(std::move(pNameElement));
+}
+
+vcl::filter::PDFNumberElement*
+addNumberElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements, double fNumber)
+{
+    auto pNumberElement = std::make_unique<vcl::filter::PDFNumberElement>();
+    auto pNumberElementPtr = pNumberElement.get();
+    pNumberElement->SetValue(fNumber);
+    rElements.push_back(std::move(pNumberElement));
+    return pNumberElementPtr;
+}
+
+void addReferenceElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+                         vcl::filter::PDFDocument& rDocument,
+                         vcl::filter::PDFNumberElement* pNumber1,
+                         vcl::filter::PDFNumberElement* pNumber2)
+{
+    auto pReferenceElement
+        = std::make_unique<vcl::filter::PDFReferenceElement>(rDocument, *pNumber1, *pNumber2);
+    rElements.push_back(std::move(pReferenceElement));
+}
+
+void addArrayElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements,
+                     vcl::filter::PDFObjectElement* pObjectPointer)
+{
+    auto pArray = std::make_unique<vcl::filter::PDFArrayElement>(pObjectPointer);
+    rElements.push_back(std::move(pArray));
+}
+
+void addEndArrayElement(std::vector<std::unique_ptr<vcl::filter::PDFElement>>& rElements)
+{
+    rElements.push_back(std::make_unique<vcl::filter::PDFEndArrayElement>());
+}
+
+} // end anonymous namespace
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseEmptyDictionary)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+    addObjectElement(aElements, aDocument, 1, 0);
+    addDictionaryElement(aElements);
+    addEndDictionaryElement(aElements);
+    addEndObjectElement(aElements);
+
+    auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+    CPPUNIT_ASSERT(pObject);
+
+    vcl::filter::PDFObjectParser aParser(aElements);
+    aParser.parse(pObject);
+
+    CPPUNIT_ASSERT(pObject->GetDictionary());
+    CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetDictionary()->GetItems().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseDictionaryWithName)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+    {
+        addObjectElement(aElements, aDocument, 1, 0);
+        addDictionaryElement(aElements);
+        addNameElement(aElements, "Test");
+        addNumberElement(aElements, 30.0);
+        addEndDictionaryElement(aElements);
+        addEndObjectElement(aElements);
+    }
+
+    auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+    CPPUNIT_ASSERT(pObject);
+
+    vcl::filter::PDFObjectParser aParser(aElements);
+    aParser.parse(pObject);
+
+    CPPUNIT_ASSERT(pObject->GetDictionary());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pObject->GetDictionary()->GetItems().size());
+    auto& rItems = pObject->GetDictionary()->GetItems();
+    auto pNumberElement = dynamic_cast<vcl::filter::PDFNumberElement*>(rItems.at("Test"));
+    CPPUNIT_ASSERT(pNumberElement);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(30.0, pNumberElement->GetValue(), 1e-4);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseDictionaryNested)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+    {
+        addObjectElement(aElements, aDocument, 1, 0);
+        addDictionaryElement(aElements);
+
+        addNameElement(aElements, "Nested1");
+        addDictionaryElement(aElements);
+        {
+            addNameElement(aElements, "Nested2");
+            addDictionaryElement(aElements);
+            {
+                addNameElement(aElements, "SomeOtherKey");
+                addNameElement(aElements, "SomeOtherValue");
+            }
+            addEndDictionaryElement(aElements);
+        }
+        addEndDictionaryElement(aElements);
+
+        addNameElement(aElements, "SomeOtherKey");
+        addNameElement(aElements, "SomeOtherValue");
+
+        addEndObjectElement(aElements);
+    }
+
+    auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+    CPPUNIT_ASSERT(pObject);
+
+    vcl::filter::PDFObjectParser aParser(aElements);
+    aParser.parse(pObject);
+
+    CPPUNIT_ASSERT(pObject->GetDictionary());
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pObject->GetDictionary()->GetItems().size());
+    CPPUNIT_ASSERT(pObject->Lookup("Nested1"));
+    CPPUNIT_ASSERT(pObject->Lookup("SomeOtherKey"));
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseEmptyArray)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+    {
+        auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+        addArrayElement(aElements, pObjectPtr);
+        addEndArrayElement(aElements);
+        addEndObjectElement(aElements);
+    }
+
+    auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+    CPPUNIT_ASSERT(pObject);
+
+    vcl::filter::PDFObjectParser aParser(aElements);
+    aParser.parse(pObject);
+
+    CPPUNIT_ASSERT(pObject->GetArray());
+    CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetArray()->GetElements().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayWithSimpleElements)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+
+    {
+        auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+        addArrayElement(aElements, pObjectPtr);
+        addNameElement(aElements, "Test");
+        addNumberElement(aElements, 30.0);
+        addEndArrayElement(aElements);
+        addEndObjectElement(aElements);
+    }
+
+    auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+    CPPUNIT_ASSERT(pObject);
+
+    vcl::filter::PDFObjectParser aParser(aElements);
+    aParser.parse(pObject);
+
+    CPPUNIT_ASSERT(pObject->GetArray());
+    CPPUNIT_ASSERT_EQUAL(size_t(2), pObject->GetArray()->GetElements().size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayNestedWithNumbers)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+
+    // [ 1 [ 10 ] 2 ]
+    {
+        auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+        addArrayElement(aElements, pObjectPtr);
+        {
+            addNumberElement(aElements, 1.0);
+            addArrayElement(aElements, pObjectPtr);
+            addNumberElement(aElements, 10.0);
+            addEndArrayElement(aElements);
+            addNumberElement(aElements, 2.0);
+        }
+        addEndArrayElement(aElements);
+        addEndObjectElement(aElements);
+    }
+
+    // Assert
+    {
+        auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+        CPPUNIT_ASSERT(pObject);
+
+        vcl::filter::PDFObjectParser aParser(aElements);
+        aParser.parse(pObject);
+
+        CPPUNIT_ASSERT(pObject->GetArray());
+        CPPUNIT_ASSERT_EQUAL(size_t(3), pObject->GetArray()->GetElements().size());
+        auto pRootArray = pObject->GetArray();
+
+        auto pNumber1 = dynamic_cast<vcl::filter::PDFNumberElement*>(pRootArray->GetElement(0));
+        CPPUNIT_ASSERT(pNumber1);
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, pNumber1->GetValue(), 1e-4);
+
+        auto pArray3 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(1));
+        CPPUNIT_ASSERT(pArray3);
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pArray3->GetElements().size());
+
+        auto pNumber2 = dynamic_cast<vcl::filter::PDFNumberElement*>(pRootArray->GetElement(2));
+        CPPUNIT_ASSERT(pNumber1);
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, pNumber2->GetValue(), 1e-4);
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseArrayNestedWithNames)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+
+    // [/Inner1/Inner2[/Inner31][/Inner41/Inner42[/Inner431/Inner432]][/Inner51[/Inner521]]]
+
+    {
+        auto pObjectPtr = addObjectElement(aElements, aDocument, 1, 0);
+        addArrayElement(aElements, pObjectPtr);
+        {
+            addNameElement(aElements, "Inner1");
+            addNameElement(aElements, "Inner2");
+
+            addArrayElement(aElements, pObjectPtr);
+            {
+                addNameElement(aElements, "Inner31");
+            }
+            addEndArrayElement(aElements);
+
+            addArrayElement(aElements, pObjectPtr);
+            {
+                addNameElement(aElements, "Inner41");
+                addNameElement(aElements, "Inner42");
+                addArrayElement(aElements, pObjectPtr);
+                {
+                    addNameElement(aElements, "Inner431");
+                    addNameElement(aElements, "Inner432");
+                }
+                addEndArrayElement(aElements);
+            }
+            addEndArrayElement(aElements);
+
+            addArrayElement(aElements, pObjectPtr);
+            {
+                addNameElement(aElements, "Inner51");
+                addArrayElement(aElements, pObjectPtr);
+                {
+                    addNameElement(aElements, "Inner521");
+                }
+                addEndArrayElement(aElements);
+            }
+            addEndArrayElement(aElements);
+        }
+        addEndArrayElement(aElements);
+        addEndObjectElement(aElements);
+    }
+
+    // Assert
+    {
+        auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElements[0].get());
+        CPPUNIT_ASSERT(pObject);
+
+        vcl::filter::PDFObjectParser aParser(aElements);
+        aParser.parse(pObject);
+
+        CPPUNIT_ASSERT(pObject->GetArray());
+        CPPUNIT_ASSERT_EQUAL(size_t(5), pObject->GetArray()->GetElements().size());
+        auto pRootArray = pObject->GetArray();
+
+        auto pName1 = dynamic_cast<vcl::filter::PDFNameElement*>(pRootArray->GetElement(0));
+        CPPUNIT_ASSERT(pName1);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner1"), pName1->GetValue());
+
+        auto pName2 = dynamic_cast<vcl::filter::PDFNameElement*>(pRootArray->GetElement(1));
+        CPPUNIT_ASSERT(pName2);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner2"), pName2->GetValue());
+
+        auto pArray3 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(2));
+        CPPUNIT_ASSERT(pArray3);
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pArray3->GetElements().size());
+
+        auto pInner31 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray3->GetElement(0));
+        CPPUNIT_ASSERT(pInner31);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner31"), pInner31->GetValue());
+
+        auto pArray4 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(3));
+        CPPUNIT_ASSERT(pArray4);
+        CPPUNIT_ASSERT_EQUAL(size_t(3), pArray4->GetElements().size());
+
+        auto pInner41 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray4->GetElement(0));
+        CPPUNIT_ASSERT(pInner41);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner41"), pInner41->GetValue());
+
+        auto pInner42 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray4->GetElement(1));
+        CPPUNIT_ASSERT(pInner42);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner42"), pInner42->GetValue());
+
+        auto pArray43 = dynamic_cast<vcl::filter::PDFArrayElement*>(pArray4->GetElement(2));
+        CPPUNIT_ASSERT(pArray43);
+        CPPUNIT_ASSERT_EQUAL(size_t(2), pArray43->GetElements().size());
+
+        auto pInner431 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray43->GetElement(0));
+        CPPUNIT_ASSERT(pInner431);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner431"), pInner431->GetValue());
+
+        auto pInner432 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray43->GetElement(1));
+        CPPUNIT_ASSERT(pInner432);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner432"), pInner432->GetValue());
+
+        auto pArray5 = dynamic_cast<vcl::filter::PDFArrayElement*>(pRootArray->GetElement(4));
+        CPPUNIT_ASSERT(pArray5);
+        CPPUNIT_ASSERT_EQUAL(size_t(2), pArray5->GetElements().size());
+
+        auto pInner51 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray5->GetElement(0));
+        CPPUNIT_ASSERT(pInner51);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner51"), pInner51->GetValue());
+
+        auto pArray52 = dynamic_cast<vcl::filter::PDFArrayElement*>(pArray5->GetElement(1));
+        CPPUNIT_ASSERT(pArray52);
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pArray52->GetElements().size());
+
+        auto pInner521 = dynamic_cast<vcl::filter::PDFNameElement*>(pArray52->GetElement(0));
+        CPPUNIT_ASSERT(pInner521);
+        CPPUNIT_ASSERT_EQUAL(OString("Inner521"), pInner521->GetValue());
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseTrailer)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+
+    {
+        addTrailerObjectElement(aElements, aDocument);
+        addDictionaryElement(aElements);
+        addNameElement(aElements, "Size");
+        addNumberElement(aElements, 11.0);
+        addEndDictionaryElement(aElements);
+    }
+    {
+        auto pTrailer = dynamic_cast<vcl::filter::PDFTrailerElement*>(aElements[0].get());
+        CPPUNIT_ASSERT(pTrailer);
+
+        vcl::filter::PDFObjectParser aParser(aElements);
+        aParser.parse(pTrailer);
+
+        CPPUNIT_ASSERT(pTrailer->GetDictionary());
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pTrailer->GetDictionary()->GetItems().size());
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(PDFDocumentTest, testParseTrailerWithReference)
+{
+    std::vector<std::unique_ptr<vcl::filter::PDFElement>> aElements;
+    vcl::filter::PDFDocument aDocument;
+
+    {
+        addTrailerObjectElement(aElements, aDocument);
+        addDictionaryElement(aElements);
+        addNameElement(aElements, "Reference");
+        auto pNumberElement1 = addNumberElement(aElements, 11.0);
+        auto pNumberElement2 = addNumberElement(aElements, 0.0);
+        addReferenceElement(aElements, aDocument, pNumberElement1, pNumberElement2);
+        addEndDictionaryElement(aElements);
+    }
+    {
+        auto pTrailer = dynamic_cast<vcl::filter::PDFTrailerElement*>(aElements[0].get());
+        CPPUNIT_ASSERT(pTrailer);
+
+        vcl::filter::PDFObjectParser aParser(aElements);
+        aParser.parse(pTrailer);
+
+        CPPUNIT_ASSERT(pTrailer->GetDictionary());
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pTrailer->GetDictionary()->GetItems().size());
+        auto pElement = pTrailer->Lookup("Reference");
+        CPPUNIT_ASSERT(pElement);
+        auto pReference = dynamic_cast<vcl::filter::PDFReferenceElement*>(pElement);
+        CPPUNIT_ASSERT(pReference);
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(11.0, pReference->GetObjectValue(), 1e-4);
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pReference->GetGenerationValue(), 1e-4);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/data/basic.pdf b/vcl/qa/cppunit/data/basic.pdf
new file mode 100644
index 000000000000..0d68be4bf5c0
--- /dev/null
+++ b/vcl/qa/cppunit/data/basic.pdf
@@ -0,0 +1,71 @@
+%PDF-1.2
+%µ¶
+
+1 0 obj
+<</Type/Page/Parent 5 0 R/Resources 3 0 R/Contents 2 0 R>>
+endobj
+
+2 0 obj
+<</Length 57>>
+stream
+BT
+/F1 24 Tf
+1 0 0 1 260 254 Tm
+0.5 g
+(Hello World)Tj
+ET
+
+endstream
+endobj
+
+3 0 obj
+<</ProcSet[/PDF/Text]/Font<</F1 4 0 R>>/Test 7 0 R>>
+endobj
+
+4 0 obj
+<</Type/Font/Subtype/Type1/Name/F1/BaseFont/Helvetica>>
+endobj
+
+5 0 obj
+<</Type/Pages/Kids[1 0 R]/Count 1/MediaBox[0 0 612 446]>>
+endobj
+
+6 0 obj
+<</Type/Catalog/Pages 5 0 R>>
+endobj
+
+7 0 obj
+<</TestArray1 8 0 R/TestArray2 9 0 R/TestDictionary 10 0 R>>
+endobj
+
+8 0 obj
+[/Inner1/Inner2[/Inner31][/Inner41/Inner42[/Inner431/Inner432]][/Inner51[/Inner521]]]
+endobj
+
+9 0 obj
+[/TestReference 7 0 R]
+endobj
+
+10 0 obj
+<</TestReference 7 0 R/TestNumber 123/TestName/SomeName/TestDictionary<</Key/Value>>/TestArray[1 2 3]>>
+endobj
+
+xref
+0 11
+0000000000 65536 f 
+0000000016 00000 n 
+0000000091 00000 n 
+0000000197 00000 n 
+0000000266 00000 n 
+0000000338 00000 n 
+0000000412 00000 n 
+0000000458 00000 n 
+0000000535 00000 n 
+0000000637 00000 n 
+0000000676 00000 n 
+
+trailer
+<</Size 11/Root 6 0 R>>
+startxref
+797
+%%EOF
diff --git a/vcl/qa/cppunit/data/basicSource.pdf b/vcl/qa/cppunit/data/basicSource.pdf
new file mode 100644
index 000000000000..2cde317fc4a8
--- /dev/null
+++ b/vcl/qa/cppunit/data/basicSource.pdf
@@ -0,0 +1,60 @@
+%PDF-1.2
+
+%Fix with "mutool clean vcl/qa/cppunit/data/basicSource.pdf vcl/qa/cppunit/data/basic.pdf"
+
+1 0 obj
+<< /Type /Page /Parent 5 0 R /Resources 3 0 R /Contents 2 0 R>>
+endobj
+
+2 0 obj
+<</Length 57>>
+stream
+BT
+/F1 24 Tf
+1 0 0 1 260 254 Tm
+0.5 g
+(Hello World)Tj
+ET
+endstream
+endobj
+
+3 0 obj
+<<
+/ProcSet [/PDF /Text ]
+/Font << /F1 4 0 R >>
+/Test 7 0 R
+>>
+endobj
+
+4 0 obj
+<< /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica >>
+endobj
+
+5 0 obj
+<< /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 612 446 ]>>
+endobj
+
+6 0 obj
+<< /Type /Catalog /Pages 5 0 R>>
+endobj
+
+7 0 obj
+<< /TestArray1 8 0 R /TestArray2 9 0 R /TestDictionary 10 0 R >>
+endobj
+
+8 0 obj
+[ /Inner1 /Inner2 [/Inner31] [/Inner41 /Inner42 [/Inner431 /Inner432] ] [ /Inner51 [/Inner521] ] ]
+endobj
+
+9 0 obj
+[ /TestReference 7 0 R ]
+endobj
+
+10 0 obj
+<< /TestReference 7 0 R /TestNumber 123 /TestName /SomeName /TestDictionary << /Key /Value >> /TestArray [1 2 3] >>
+endobj
+
+trailer
+<</Root 6 0 R>>
+
+%%EOF


More information about the Libreoffice-commits mailing list