LCOV - code coverage report
Current view: top level - sw/qa/extras/inc - swmodeltestbase.hxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 317 325 97.5 %
Date: 2014-04-11 Functions: 93 96 96.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <com/sun/star/container/XContentEnumerationAccess.hpp>
      11             : #include <com/sun/star/frame/Desktop.hpp>
      12             : #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
      13             : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
      14             : #include <com/sun/star/style/XAutoStylesSupplier.hpp>
      15             : #include <com/sun/star/style/XAutoStyleFamily.hpp>
      16             : #include <com/sun/star/text/XPageCursor.hpp>
      17             : #include <com/sun/star/text/XTextDocument.hpp>
      18             : #include <com/sun/star/text/XTextRange.hpp>
      19             : #include <com/sun/star/text/XTextTable.hpp>
      20             : #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
      21             : #include <com/sun/star/table/XCell.hpp>
      22             : #include <com/sun/star/table/BorderLine2.hpp>
      23             : 
      24             : #include <test/bootstrapfixture.hxx>
      25             : #include <unotest/macros_test.hxx>
      26             : #include <unotools/ucbstreamhelper.hxx>
      27             : #include <rtl/strbuf.hxx>
      28             : #include <rtl/ustrbuf.hxx>
      29             : #include <rtl/byteseq.hxx>
      30             : #include <comphelper/processfactory.hxx>
      31             : #include <unotools/tempfile.hxx>
      32             : #include <unotools/mediadescriptor.hxx>
      33             : 
      34             : #include <unotxdoc.hxx>
      35             : #include <docsh.hxx>
      36             : #include <doc.hxx>
      37             : #include <rootfrm.hxx>
      38             : 
      39             : #include <libxml/xmlwriter.h>
      40             : #include <libxml/xpath.h>
      41             : #include <libxml/xpathInternals.h>
      42             : #include <libxml/parserInternals.h>
      43             : 
      44             : using namespace css;
      45             : 
      46             : #define DEFAULT_STYLE "Default Style"
      47             : #define EMU_TO_MM100(EMU) (EMU / 360)
      48             : 
      49             : /**
      50             :  * Macro to declare a new test (with full round-trip. To test
      51             :  * import only use the DECLARE_SW_IMPORT_TEST macro instead).
      52             :  * In order to add a new test, one only needs to use this macro
      53             :  * and then specify the test content, like this:
      54             :  *
      55             :  * DECLARE_SW_ROUNDTRIP_TEST(MyTest, "myfilename.docx", Test)
      56             :  * {
      57             :  *      CPPUNIT_ASSERT_EQUAL(blabla);
      58             :  * }
      59             :  *
      60             :  */
      61             : #define DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, BaseClass) \
      62             :     class TestName : public BaseClass { \
      63             :         protected:\
      64             :     virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \
      65             :         public:\
      66             :     CPPUNIT_TEST_SUITE(TestName); \
      67             :     CPPUNIT_TEST(Import); \
      68             :     CPPUNIT_TEST(Import_Export_Import); \
      69             :     CPPUNIT_TEST_SUITE_END(); \
      70             :     \
      71             :     void Import() { \
      72             :         executeImportTest(filename);\
      73             :     }\
      74             :     void Import_Export_Import() {\
      75             :         executeImportExportImportTest(filename);\
      76             :     }\
      77             :     void verify() SAL_OVERRIDE;\
      78             :     }; \
      79             :     CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
      80             :     void TestName::verify()
      81             : 
      82             : #define DECLARE_SW_IMPORT_TEST(TestName, filename, BaseClass) \
      83             :     class TestName : public BaseClass { \
      84             :         protected:\
      85             :     virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \
      86             :         public:\
      87             :     CPPUNIT_TEST_SUITE(TestName); \
      88             :     CPPUNIT_TEST(Import); \
      89             :     CPPUNIT_TEST_SUITE_END(); \
      90             :     \
      91             :     void Import() { \
      92             :         executeImportTest(filename);\
      93             :     }\
      94             :     void verify() SAL_OVERRIDE;\
      95             :     }; \
      96             :     CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
      97             :     void TestName::verify()
      98             : 
      99             : #define DECLARE_SW_EXPORT_TEST(TestName, filename, BaseClass) \
     100             :     class TestName : public BaseClass { \
     101             :         protected:\
     102             :     virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \
     103             :         public:\
     104             :     CPPUNIT_TEST_SUITE(TestName); \
     105             :     CPPUNIT_TEST(Import_Export); \
     106             :     CPPUNIT_TEST_SUITE_END(); \
     107             :     \
     108             :     void Import_Export() {\
     109             :         executeImportExport(filename);\
     110             :     }\
     111             :     void verify() SAL_OVERRIDE;\
     112             :     }; \
     113             :     CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
     114             :     void TestName::verify()
     115             : 
     116             : /// Base class for filter tests loading or roundtriping a document, then asserting the document model.
     117             : class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest
     118             : {
     119             :     OUString maFilterOptions;
     120             : protected:
     121           0 :     virtual OUString getTestName() { return OUString(); }
     122             : 
     123             : public:
     124             :     OUString& getFilterOptions()
     125             :     {
     126             :         return maFilterOptions;
     127             :     }
     128           5 :     void setFilterOptions(const OUString &rFilterOptions)
     129             :     {
     130           5 :         maFilterOptions = rFilterOptions;
     131           5 :     }
     132             : 
     133         982 :     SwModelTestBase(const char* pTestDocumentPath = "", const char* pFilter = "")
     134             :         : mpXmlBuffer(0),
     135             :         mpTestDocumentPath(pTestDocumentPath),
     136             :         mpFilter(pFilter),
     137             :         m_nStartTime(0),
     138         982 :         m_bExported(false)
     139         982 :     {}
     140             : 
     141         982 :     virtual ~SwModelTestBase()
     142         982 :     {}
     143             : 
     144         982 :     virtual void setUp() SAL_OVERRIDE
     145             :     {
     146         982 :         test::BootstrapFixture::setUp();
     147             : 
     148         982 :         mxDesktop.set( com::sun::star::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())) );
     149         982 :     }
     150             : 
     151         982 :     virtual void tearDown() SAL_OVERRIDE
     152             :     {
     153         982 :         if (mxComponent.is())
     154         935 :             mxComponent->dispose();
     155             : 
     156         982 :         test::BootstrapFixture::tearDown();
     157         982 :     }
     158             : 
     159             : protected:
     160             :     /**
     161             :      * Helper func used by each unit test to test the 'import' code.
     162             :      * (Loads the requested file and then calls 'verify' method)
     163             :      */
     164         639 :     void executeImportTest(const char* filename)
     165             :     {
     166             :         // If the testcase is stored in some other format, it's pointless to test.
     167         639 :         if (mustTestImportOf(filename))
     168             :         {
     169         592 :             header();
     170         592 :             preTest(filename);
     171         592 :             load(mpTestDocumentPath, filename);
     172         592 :             postTest(filename);
     173         592 :             verify();
     174         592 :             finish();
     175             :         }
     176         639 :     }
     177             : 
     178             :     /**
     179             :      * Helper func used by each unit test to test the 'export' code.
     180             :      * (Loads the requested file, save it to temp file, load the
     181             :      * temp file and then calls 'verify' method)
     182             :      */
     183         332 :     void executeImportExportImportTest(const char* filename)
     184             :     {
     185         332 :         header();
     186         332 :         preTest(filename);
     187         332 :         load(mpTestDocumentPath, filename);
     188         332 :         reload(mpFilter, filename);
     189         332 :         postTest(filename);
     190         332 :         verify();
     191         332 :         finish();
     192         332 :     }
     193             : 
     194             :     /**
     195             :      * Helper func used by each unit test to test the 'export' code.
     196             :      * (Loads the requested file for document base (this represents
     197             :      * the initial document condition), exports with the desired
     198             :      * export filter and then calls 'verify' method)
     199             :      */
     200           2 :     void executeImportExport(const char* filename)
     201             :     {
     202           2 :         header();
     203           2 :         preTest(filename);
     204           2 :         load(mpTestDocumentPath, filename);
     205           2 :         save(OUString::createFromAscii(mpFilter), m_aTempFile);
     206           2 :         postTest(filename);
     207           2 :         verify();
     208           2 :         finish();
     209           2 :     }
     210             : 
     211             :     /**
     212             :      * Function overloaded by unit test. See DECLARE_SW_*_TEST macros
     213             :      */
     214           0 :     virtual void verify()
     215             :     {
     216           0 :         CPPUNIT_FAIL( "verify method must be overridden" );
     217           0 :     }
     218             : 
     219             :     /**
     220             :      * Override this function if interested in skipping import test for this file
     221             :      */
     222         307 :      virtual bool mustTestImportOf(const char* /* filename */) const
     223             :      {
     224         307 :         return true;
     225             :      }
     226             :     /**
     227             :      * Override this function if some special filename-specific setup is needed
     228             :      */
     229         650 :     virtual void preTest(const char* /*filename*/)
     230             :     {
     231         650 :     }
     232             : 
     233             :     /**
     234             :      * Override this function if some special filename-specific teardown is needed
     235             :      */
     236         650 :     virtual void postTest(const char* /*filename*/)
     237             :     {
     238         650 :     }
     239             : 
     240             :     /**
     241             :      * Override this function if not calcing layout is needed
     242             :      */
     243        1260 :     virtual bool mustCalcLayoutOf(const char* /*filename*/)
     244             :     {
     245        1260 :         return true;
     246             :     }
     247             : 
     248             : private:
     249          23 :     void dumpLayout()
     250             :     {
     251             :         // create the xml writer
     252          23 :         mpXmlBuffer = xmlBufferCreate();
     253          23 :         xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(mpXmlBuffer, 0);
     254          23 :         xmlTextWriterStartDocument(pXmlWriter, NULL, NULL, NULL);
     255             : 
     256             :         // create the dump
     257          23 :         SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
     258          23 :         SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc();
     259          23 :         SwRootFrm* pLayout = pDoc->GetCurrentLayout();
     260          23 :         pLayout->dumpAsXml(pXmlWriter);
     261             : 
     262             :         // delete xml writer
     263          23 :         xmlTextWriterEndDocument(pXmlWriter);
     264          23 :         xmlFreeTextWriter(pXmlWriter);
     265          23 :     }
     266             : 
     267        1265 :     void calcLayout()
     268             :     {
     269        1265 :         SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
     270        1265 :         CPPUNIT_ASSERT(pTxtDoc);
     271        1265 :         SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc();
     272        1265 :         pDoc->GetCurrentViewShell()->CalcLayout();
     273        1265 :     }
     274             : 
     275             : protected:
     276             :     /// Get the length of the whole document.
     277          11 :     int getLength()
     278             :     {
     279          11 :         uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
     280          22 :         uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
     281          22 :         uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
     282          22 :         OUStringBuffer aBuf;
     283          34 :         while (xParaEnum->hasMoreElements())
     284             :         {
     285          12 :             uno::Reference<container::XEnumerationAccess> xRangeEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
     286          24 :             uno::Reference<container::XEnumeration> xRangeEnum = xRangeEnumAccess->createEnumeration();
     287          40 :             while (xRangeEnum->hasMoreElements())
     288             :             {
     289          16 :                 uno::Reference<text::XTextRange> xRange(xRangeEnum->nextElement(), uno::UNO_QUERY);
     290          16 :                 aBuf.append(xRange->getString());
     291          16 :             }
     292          12 :         }
     293          22 :         return aBuf.getLength();
     294             :     }
     295             : 
     296             :     /// Get a family of styles, see com.sun.star.style.StyleFamilies for possible values.
     297          78 :     uno::Reference<container::XNameAccess> getStyles(const OUString& aFamily)
     298             :     {
     299          78 :         uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent, uno::UNO_QUERY);
     300         156 :         uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY);
     301          78 :         uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName(aFamily), uno::UNO_QUERY);
     302         156 :         return xStyleFamily;
     303             :     }
     304             : 
     305             :     /// Get a family of auto styles, see com.sun.star.style.StyleFamilies for possible values.
     306           2 :     uno::Reference<style::XAutoStyleFamily> getAutoStyles(const OUString& aFamily)
     307             :     {
     308           2 :         uno::Reference< style::XAutoStylesSupplier > xAutoStylesSupplier(mxComponent, uno::UNO_QUERY);
     309           4 :         uno::Reference< style::XAutoStyles > xAutoStyles(xAutoStylesSupplier->getAutoStyles());
     310           2 :         uno::Reference< style::XAutoStyleFamily > xAutoStyleFamily(xAutoStyles->getByName(aFamily), uno::UNO_QUERY);
     311           4 :         return xAutoStyleFamily;
     312             :     }
     313             : 
     314             :     /**
     315             :      * Extract a value from the layout dump using an XPath expression and an attribute name.
     316             :      *
     317             :      * If the attribute is omitted, the text of the node is returned.
     318             :      */
     319          78 :     OUString parseDump(const OString& aXPath, const OString& aAttribute = OString())
     320             :     {
     321          78 :         if (!mpXmlBuffer)
     322          23 :             dumpLayout();
     323             : 
     324          78 :         xmlDocPtr pXmlDoc = xmlParseMemory((const char*)xmlBufferContent(mpXmlBuffer), xmlBufferLength(mpXmlBuffer));;
     325             : 
     326          78 :         xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
     327          78 :         xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(aXPath.getStr()), pXmlXpathCtx);
     328          78 :         xmlNodeSetPtr pXmlNodes = pXmlXpathObj->nodesetval;
     329          78 :         CPPUNIT_ASSERT_EQUAL_MESSAGE("parsing dump failed", 1, xmlXPathNodeSetGetLength(pXmlNodes));
     330          78 :         xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
     331          78 :         OUString aRet;
     332          78 :         if (aAttribute.getLength())
     333          15 :             aRet = OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr())));
     334             :         else
     335          63 :             aRet = OUString::createFromAscii((const char*)XML_GET_CONTENT(pXmlNode));
     336             : 
     337          78 :         xmlFreeDoc(pXmlDoc);
     338             : 
     339          78 :         return aRet;
     340             :     }
     341             : 
     342             :     template< typename T >
     343          83 :     T getProperty( const uno::Any& obj, const OUString& name ) const
     344             :     {
     345          83 :         uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY_THROW );
     346          83 :         T data = T();
     347          83 :         properties->getPropertyValue( name ) >>= data;
     348          83 :         return data;
     349             :     }
     350             : 
     351             :     template< typename T >
     352        1223 :     T getProperty( const uno::Reference< uno::XInterface >& obj, const OUString& name ) const
     353             :     {
     354        1223 :         uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY_THROW );
     355        1223 :         T data = T();
     356        1223 :         properties->getPropertyValue( name ) >>= data;
     357        1223 :         return data;
     358             :     }
     359             : 
     360           3 :     bool hasProperty(const uno::Reference<uno::XInterface>& obj, const OUString& name) const
     361             :     {
     362           3 :         uno::Reference<beans::XPropertySet> properties(obj, uno::UNO_QUERY_THROW);
     363           3 :         return properties->getPropertySetInfo()->hasPropertyByName(name);
     364             :     }
     365             : 
     366             :     /// Get number of paragraphs of the document.
     367           2 :     int getParagraphs()
     368             :     {
     369           2 :         uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
     370           4 :         uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
     371           4 :         uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
     372           2 :         int nRet = 0;
     373           7 :         while (xParaEnum->hasMoreElements())
     374             :         {
     375           3 :             xParaEnum->nextElement();
     376           3 :             nRet++;
     377             :         }
     378           4 :         return nRet;
     379             :     }
     380             : 
     381         357 :     uno::Reference<text::XTextContent> getParagraphOrTable(int number, uno::Reference<text::XText> xText = uno::Reference<text::XText>()) const
     382             :     {
     383         357 :         uno::Reference<container::XEnumerationAccess> paraEnumAccess;
     384         357 :         if (xText.is())
     385          71 :             paraEnumAccess.set(xText, uno::UNO_QUERY);
     386             :         else
     387             :         {
     388         286 :             uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
     389         286 :             paraEnumAccess.set(textDocument->getText(), uno::UNO_QUERY);
     390             :         }
     391         714 :         uno::Reference<container::XEnumeration> paraEnum = paraEnumAccess->createEnumeration();
     392         620 :         for( int i = 1;
     393             :              i < number;
     394             :              ++i )
     395         263 :             paraEnum->nextElement();
     396         357 :         uno::Reference< text::XTextContent> const xElem(paraEnum->nextElement(),
     397         357 :                 uno::UNO_QUERY_THROW);
     398         713 :         return xElem;
     399             :     }
     400             : 
     401             :     // Get paragraph (counted from 1), optionally check it contains the given text.
     402         276 :     uno::Reference< text::XTextRange > getParagraph( int number, const OUString& content = OUString() ) const
     403             :     {
     404             :         uno::Reference<text::XTextRange> const xParagraph(
     405         276 :                 getParagraphOrTable(number), uno::UNO_QUERY_THROW);
     406         275 :         if( !content.isEmpty())
     407          43 :             CPPUNIT_ASSERT_EQUAL_MESSAGE( "paragraph does not have expected content", content, xParagraph->getString());
     408         275 :         return xParagraph;
     409             :     }
     410             : 
     411          67 :     uno::Reference<text::XTextRange> getParagraphOfText(int number, uno::Reference<text::XText> xText, const OUString& content = OUString()) const
     412             :     {
     413          67 :         uno::Reference<text::XTextRange> const xParagraph(getParagraphOrTable(number, xText), uno::UNO_QUERY_THROW);
     414          67 :         if (!content.isEmpty())
     415           6 :             CPPUNIT_ASSERT_EQUAL_MESSAGE( "paragraph does not contain expected content", content, xParagraph->getString());
     416          67 :         return xParagraph;
     417             :     }
     418             : 
     419             :     /// Get run (counted from 1) of a paragraph, optionally check it contains the given text.
     420         290 :     uno::Reference<text::XTextRange> getRun(uno::Reference<text::XTextRange> xParagraph, int number, const OUString& content = OUString()) const
     421             :     {
     422         290 :         uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParagraph, uno::UNO_QUERY);
     423         580 :         uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
     424         806 :         for (int i = 1; i < number; ++i)
     425         516 :             xRunEnum->nextElement();
     426         290 :         uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
     427         290 :         if( !content.isEmpty())
     428          31 :             CPPUNIT_ASSERT_EQUAL_MESSAGE( "run does not contain expected content", content, xRun->getString());
     429         580 :         return xRun;
     430             :     }
     431             : 
     432             :     /// Get math formula string of a run.
     433         114 :     OUString getFormula(uno::Reference<text::XTextRange> xRun) const
     434             :     {
     435         114 :         uno::Reference<container::XContentEnumerationAccess> xContentEnumAccess(xRun, uno::UNO_QUERY);
     436         228 :         uno::Reference<container::XEnumeration> xContentEnum(xContentEnumAccess->createContentEnumeration(""), uno::UNO_QUERY);
     437         228 :         uno::Reference<beans::XPropertySet> xFormula(xContentEnum->nextElement(), uno::UNO_QUERY);
     438         228 :         return getProperty<OUString>(getProperty< uno::Reference<beans::XPropertySet> >(xFormula, "Model"), "Formula");
     439             :     }
     440             : 
     441             :     /// get cell of a table; table can be retrieved with getParagraphOrTable
     442           7 :     uno::Reference<table::XCell> getCell(
     443             :             uno::Reference<uno::XInterface> const& xTableIfc,
     444             :             OUString const& rCell, OUString const& rContent = OUString())
     445             :     {
     446             :         uno::Reference<text::XTextTable> const xTable(xTableIfc,
     447           7 :                 uno::UNO_QUERY_THROW);
     448             :         uno::Reference<table::XCell> const xCell(
     449           7 :                 xTable->getCellByName(rCell), uno::UNO_SET_THROW);
     450           7 :         if (!rContent.isEmpty())
     451             :         {
     452             :             uno::Reference<text::XText> const xCellText(xCell,
     453           3 :                     uno::UNO_QUERY_THROW);
     454           3 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("cell does not contain expected content", rContent, xCellText->getString());
     455             :         }
     456           7 :         return xCell;
     457             :     }
     458             : 
     459             :     /// Get shape (counted from 1)
     460         240 :     uno::Reference<drawing::XShape> getShape(int number)
     461             :     {
     462         240 :         uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
     463         480 :         uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
     464         240 :         uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(number - 1), uno::UNO_QUERY);
     465         479 :         return xShape;
     466             :     }
     467             : 
     468             :     /// Get TextFrame by name
     469          16 :     uno::Reference<drawing::XShape> getTextFrameByName(const OUString& aName)
     470             :     {
     471          16 :         uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
     472          32 :         uno::Reference<container::XNameAccess> xNameAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
     473          16 :         uno::Reference<drawing::XShape> xShape(xNameAccess->getByName(aName), uno::UNO_QUERY);
     474          32 :         return xShape;
     475             :     }
     476             : 
     477         926 :     void header()
     478             :     {
     479         926 :         std::cout << "File tested,Execution Time (ms)" << std::endl;
     480         926 :     }
     481             : 
     482         935 :     void load(const char* pDir, const char* pName)
     483             :     {
     484         935 :         if (mxComponent.is())
     485           0 :             mxComponent->dispose();
     486             :         // Output name early, so in the case of a hang, the name of the hanging input file is visible.
     487         935 :         std::cout << pName << ",";
     488         935 :         m_nStartTime = osl_getGlobalTimer();
     489         935 :         mxComponent = loadFromDesktop(getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.text.TextDocument");
     490         935 :         if (mustCalcLayoutOf(pName))
     491         934 :             calcLayout();
     492         935 :     }
     493             : 
     494         332 :     void reload(const char* pFilter, const char* filename)
     495             :     {
     496         332 :         uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
     497         664 :         OUString aFilterName = OUString::createFromAscii(pFilter);
     498         664 :         utl::MediaDescriptor aMediaDescriptor;
     499         332 :         aMediaDescriptor["FilterName"] <<= aFilterName;
     500         332 :         if (!maFilterOptions.isEmpty())
     501           0 :             aMediaDescriptor["FilterOptions"] <<= maFilterOptions;
     502         332 :         m_aTempFile.EnableKillingFile();
     503         332 :         xStorable->storeToURL(m_aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
     504         664 :         uno::Reference<lang::XComponent> xComponent(xStorable, uno::UNO_QUERY);
     505         332 :         xComponent->dispose();
     506         332 :         m_bExported = true;
     507         332 :         mxComponent = loadFromDesktop(m_aTempFile.GetURL(), "com.sun.star.text.TextDocument");
     508         332 :         if(aFilterName == "Office Open XML Text")
     509             :         {
     510             :             // too many validation errors right now
     511             :             // validate(m_aTempFile.GetFileName(), test::OOXML);
     512             :         }
     513          76 :         else if(aFilterName == "writer8")
     514             :         {
     515             :             // still a few validation errors
     516             :             // validate(m_aTempFile.GetFileName(), test::ODF);
     517             :         }
     518             : 
     519         332 :         if (mpXmlBuffer)
     520             :         {
     521           0 :             xmlBufferFree(mpXmlBuffer);
     522           0 :             mpXmlBuffer = 0;
     523             :         }
     524         332 :         if (mustCalcLayoutOf(filename))
     525         663 :             calcLayout();
     526         332 :     }
     527             : 
     528             :     /// Save the loaded document to a tempfile. Can be used to check the resulting docx/odt directly as a ZIP file.
     529           3 :     void save(const OUString& aFilterName, utl::TempFile& rTempFile)
     530             :     {
     531           3 :         rTempFile.EnableKillingFile();
     532           3 :         uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
     533           6 :         utl::MediaDescriptor aMediaDescriptor;
     534           3 :         aMediaDescriptor["FilterName"] <<= aFilterName;
     535           3 :         if (!maFilterOptions.isEmpty())
     536           1 :             aMediaDescriptor["FilterOptions"] <<= maFilterOptions;
     537           6 :         xStorable->storeToURL(rTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
     538           3 :     }
     539             : 
     540         926 :     void finish()
     541             :     {
     542         926 :         sal_uInt32 nEndTime = osl_getGlobalTimer();
     543         926 :         std::cout << (nEndTime - m_nStartTime) << std::endl;
     544         926 :         if (mpXmlBuffer)
     545             :         {
     546          23 :             xmlBufferFree(mpXmlBuffer);
     547          23 :             mpXmlBuffer = 0;
     548             :         }
     549         926 :     }
     550             : 
     551             :     /// Get page count.
     552          13 :     int getPages()
     553             :     {
     554          13 :         uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
     555          26 :         uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
     556          26 :         uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
     557          13 :         xCursor->jumpToLastPage();
     558          26 :         return xCursor->getPage();
     559             :     }
     560             : 
     561             :     /**
     562             :      * Given that some problem doesn't affect the result in the importer, we
     563             :      * test the resulting file directly, by opening the zip file, parsing an
     564             :      * xml stream, and asserting an XPath expression. This method returns the
     565             :      * xml stream, so that you can do the asserting.
     566             :      */
     567         297 :     xmlDocPtr parseExport(const OUString& rStreamName = OUString("word/document.xml"))
     568             :     {
     569         297 :         if (!m_bExported)
     570         145 :             return 0;
     571             : 
     572             :         // Read the XML stream we're interested in.
     573         152 :         uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), m_aTempFile.GetURL());
     574         304 :         uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(rStreamName), uno::UNO_QUERY);
     575             : 
     576         304 :         boost::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
     577         152 :         sal_Size nSize = pStream->remainingSize();
     578             : 
     579         304 :         rtl::ByteSequence aBuffer(nSize);
     580         152 :         pStream->Read(aBuffer.getArray(), nSize);
     581             : 
     582             :         // Parse the XML.
     583         304 :         return xmlParseMemory(reinterpret_cast<const char*>(aBuffer.getArray()), aBuffer.getLength());
     584             :     }
     585             : 
     586             :     /**
     587             :      * Helper method to return nodes represented by rXPath.
     588             :      */
     589         712 :     xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
     590             :     {
     591         712 :         xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
     592         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
     593         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml"));
     594         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006"));
     595         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape"));
     596         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"));
     597         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"));
     598         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("wp14"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"));
     599         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main"));
     600         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("pic"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/picture"));
     601         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("rels"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships"));
     602         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w14"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordml"));
     603         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("m"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/math"));
     604         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("ContentType"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types"));
     605         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("lc"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"));
     606         712 :         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("extended-properties"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
     607         712 :         xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
     608         712 :         return pXmlXpathObj->nodesetval;
     609             :     }
     610             : 
     611             :     /**
     612             :      * Same as the assertXPath(), but don't assert: return the string instead.
     613             :      */
     614         579 :     OUString getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute)
     615             :     {
     616         579 :         xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
     617        1158 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
     618         579 :                                      1, xmlXPathNodeSetGetLength(pXmlNodes));
     619         579 :         if (rAttribute.isEmpty())
     620          11 :             return OUString();
     621         568 :         xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
     622         568 :         return OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr())));
     623             :     }
     624             : 
     625             :     /**
     626             :      * Same as the assertXPathContent(), but don't assert: return the string instead.
     627             :      */
     628          30 :     OUString getXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath)
     629             :     {
     630          30 :         xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
     631             : 
     632          60 :         CPPUNIT_ASSERT_MESSAGE(OString("XPath '" + rXPath + "' not found").getStr(),
     633          30 :                 xmlXPathNodeSetGetLength(pXmlNodes) > 0);
     634             : 
     635          30 :         xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
     636          30 :         return OUString::createFromAscii((const char*)((pXmlNode->children[0]).content));
     637             :     }
     638             : 
     639             :     /**
     640             :      * Assert that rXPath exists, and returns exactly one node.
     641             :      * In case rAttribute is provided, the rXPath's attribute's value must
     642             :      * equal to the rExpected value.
     643             :      */
     644         495 :     void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute = OString(), const OUString& rExpectedValue = OUString())
     645             :     {
     646         495 :         OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute);
     647         990 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Attribute '" + rAttribute + "' of '" + rXPath + "' incorrect value.").getStr(),
     648         990 :                                      rExpectedValue, aValue);
     649         495 :     }
     650             : 
     651             :     /**
     652             :      * Assert that rXPath exists, and returns exactly nNumberOfNodes nodes.
     653             :      * Useful for checking that we do _not_ export some node (nNumberOfNodes == 0).
     654             :      */
     655          87 :     void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes)
     656             :     {
     657          87 :         xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
     658         174 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
     659          87 :                                      nNumberOfNodes, xmlXPathNodeSetGetLength(pXmlNodes));
     660          87 :     }
     661             : 
     662             :     /**
     663             :      * Assert that rXPath exists, and its content equals rContent.
     664             :      */
     665          22 :     void assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent)
     666             :     {
     667          22 :         CPPUNIT_ASSERT_EQUAL_MESSAGE("XPath contents of child does not match", rContent, getXPathContent(pXmlDoc, rXPath));
     668          22 :     }
     669             : 
     670             :     /**
     671             :      * Assert that rXPath exists, and has exactly nNumberOfChildNodes child nodes.
     672             :      * Useful for checking that we do have a no child nodes to a specific node (nNumberOfChildNodes == 0).
     673             :      */
     674           1 :     void assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes)
     675             :     {
     676           1 :         xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
     677           2 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
     678           1 :                                      1, xmlXPathNodeSetGetLength(pXmlNodes));
     679           1 :         xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
     680           2 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of child-nodes is incorrect").getStr(),
     681           1 :                                      nNumberOfChildNodes, (int)xmlChildElementCount(pXmlNode));
     682           1 :     }
     683             : 
     684             :     /**
     685             :      * Get the position of the child named rName of the parent node specified by rXPath.
     686             :      * Useful for checking relative order of elements.
     687             :      */
     688          11 :     int getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rChildName)
     689             :     {
     690          11 :         xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
     691          22 :         CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
     692             :                                      1,
     693          11 :                                      xmlXPathNodeSetGetLength(pXmlNodes));
     694          11 :         xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
     695          11 :         int nRet = 0;
     696          43 :         for (xmlNodePtr pChild = pXmlNode->children; pChild; pChild = pChild->next)
     697             :         {
     698          43 :             if (OUString::createFromAscii((const char*)pChild->name) == rChildName)
     699          11 :                 break;
     700          32 :             ++nRet;
     701             :         }
     702          11 :         return nRet;
     703             :     }
     704             : 
     705             :     uno::Reference<lang::XComponent> mxComponent;
     706             :     xmlBufferPtr mpXmlBuffer;
     707             :     const char* mpTestDocumentPath;
     708             :     const char* mpFilter;
     709             : 
     710             :     template< typename T >
     711             :     struct MethodEntry
     712             :     {
     713             :         const char* pName;
     714             :         void (T::*pMethod)();
     715             :     };
     716             :     sal_uInt32 m_nStartTime;
     717             :     utl::TempFile m_aTempFile;
     718             :     bool m_bExported; ///< Does m_aTempFile already contain something useful?
     719             : };
     720             : 
     721             : /**
     722             :  * Test whether the expected and actual borderline parameters are equal
     723             :  * and assert if not.
     724             :  *
     725             :  * @param[in]   rExpected    expected borderline object
     726             :  * @param[in]   rActual      actual borderline object
     727             :  * @param[in]   rSourceLine  line from where the assertion is called
     728             :  * Note: This method is the implementatition of CPPUNIT_ASSERT_BORDER_EQUAL, so
     729             :  *       use that macro instead.
     730             : **/
     731         126 : inline void assertBorderEqual(
     732             :     const table::BorderLine2& rExpected, const table::BorderLine2& rActual,
     733             :     const CppUnit::SourceLine& rSourceLine )
     734             : {
     735         126 :     CPPUNIT_NS::assertEquals<util::Color>( rExpected.Color, rActual.Color, rSourceLine, "different Color" );
     736         126 :     CPPUNIT_NS::assertEquals<sal_Int16>( rExpected.InnerLineWidth, rActual.InnerLineWidth, rSourceLine, "different InnerLineWidth" );
     737         126 :     CPPUNIT_NS::assertEquals<sal_Int16>( rExpected.OuterLineWidth, rActual.OuterLineWidth, rSourceLine, "different OuterLineWidth" );
     738         126 :     CPPUNIT_NS::assertEquals<sal_Int16>( rExpected.LineDistance, rActual.LineDistance, rSourceLine, "different LineDistance" );
     739         126 :     CPPUNIT_NS::assertEquals<sal_Int16>( rExpected.LineStyle, rActual.LineStyle, rSourceLine, "different LineStyle" );
     740         126 :     CPPUNIT_NS::assertEquals<sal_Int32>( rExpected.LineWidth, rActual.LineWidth, rSourceLine, "different LineWidth" );
     741         126 : }
     742             : 
     743             : #define CPPUNIT_ASSERT_BORDER_EQUAL(aExpected, aActual) \
     744             :         assertBorderEqual( aExpected, aActual, CPPUNIT_SOURCELINE() ) \
     745             : 
     746             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10