1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #ifndef INCLUDED_SW_QA_EXTRAS_INC_SWMODELTESTBASE_HXX
11 #define INCLUDED_SW_QA_EXTRAS_INC_SWMODELTESTBASE_HXX
13 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
14 #include <com/sun/star/frame/Desktop.hpp>
15 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
16 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
17 #include <com/sun/star/style/XAutoStylesSupplier.hpp>
18 #include <com/sun/star/style/XAutoStyleFamily.hpp>
19 #include <com/sun/star/text/XPageCursor.hpp>
20 #include <com/sun/star/text/XTextDocument.hpp>
21 #include <com/sun/star/text/XTextRange.hpp>
22 #include <com/sun/star/text/XTextTable.hpp>
23 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
24 #include <com/sun/star/table/XCell.hpp>
25 #include <com/sun/star/table/BorderLine2.hpp>
26 #include <com/sun/star/task/XJob.hpp>
27 #include <com/sun/star/sdb/CommandType.hpp>
28 #include <com/sun/star/sdb/DatabaseContext.hpp>
29 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
31 #include <test/bootstrapfixture.hxx>
32 #include <test/xmltesttools.hxx>
33 #include <unotest/macros_test.hxx>
34 #include <unotools/ucbstreamhelper.hxx>
35 #include <rtl/strbuf.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <rtl/byteseq.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <unotools/tempfile.hxx>
40 #include <unotools/localfilehelper.hxx>
41 #include <unotools/mediadescriptor.hxx>
43 #include <unoprnms.hxx>
45 #include <unotxdoc.hxx>
48 #include <IDocumentLayoutAccess.hxx>
49 #include <rootfrm.hxx>
53 #define DEFAULT_STYLE "Default Style"
56 * Macro to declare a new test (with full round-trip. To test
57 * import only use the DECLARE_SW_IMPORT_TEST macro instead).
58 * In order to add a new test, one only needs to use this macro
59 * and then specify the test content, like this:
61 * DECLARE_SW_ROUNDTRIP_TEST(MyTest, "myfilename.docx", Test)
63 * CPPUNIT_ASSERT_EQUAL(blabla);
67 #define DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, BaseClass) \
68 class TestName : public BaseClass { \
70 virtual OUString getTestName() SAL_OVERRIDE { return OUString(#TestName); } \
72 CPPUNIT_TEST_SUITE(TestName); \
73 CPPUNIT_TEST(Import); \
74 CPPUNIT_TEST(Import_Export_Import); \
75 CPPUNIT_TEST_SUITE_END(); \
78 executeImportTest(filename);\
80 void Import_Export_Import() {\
81 executeImportExportImportTest(filename);\
83 void verify() SAL_OVERRIDE;\
85 CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
86 void TestName::verify()
88 #define DECLARE_OOXMLIMPORT_TEST(TestName, filename) DECLARE_SW_IMPORT_TEST(TestName, filename, Test)
89 #define DECLARE_OOXMLEXPORT_TEST(TestName, filename) DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
90 #define DECLARE_RTFIMPORT_TEST(TestName, filename) DECLARE_SW_IMPORT_TEST(TestName, filename, Test)
91 #define DECLARE_RTFEXPORT_TEST(TestName, filename) DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
92 #define DECLARE_ODFIMPORT_TEST(TestName, filename) DECLARE_SW_IMPORT_TEST(TestName, filename, Test)
93 #define DECLARE_ODFEXPORT_TEST(TestName, filename) DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
94 #define DECLARE_WW8EXPORT_TEST(TestName, filename) DECLARE_SW_ROUNDTRIP_TEST(TestName, filename, Test)
96 #define DECLARE_SW_IMPORT_TEST(TestName, filename, BaseClass) \
97 class TestName : public BaseClass { \
99 virtual OUString getTestName() SAL_OVERRIDE { return OUString(#TestName); } \
101 CPPUNIT_TEST_SUITE(TestName); \
102 CPPUNIT_TEST(Import); \
103 CPPUNIT_TEST_SUITE_END(); \
106 executeImportTest(filename);\
108 void verify() SAL_OVERRIDE;\
110 CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
111 void TestName::verify()
113 #define DECLARE_SW_EXPORT_TEST(TestName, filename, BaseClass) \
114 class TestName : public BaseClass { \
116 virtual OUString getTestName() SAL_OVERRIDE { return OUString(#TestName); } \
118 CPPUNIT_TEST_SUITE(TestName); \
119 CPPUNIT_TEST(Import_Export); \
120 CPPUNIT_TEST_SUITE_END(); \
122 void Import_Export() {\
123 executeImportExport(filename);\
125 void verify() SAL_OVERRIDE;\
127 CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
128 void TestName::verify()
130 /// Base class for filter tests loading or roundtriping a document, then asserting the document model.
131 class SwModelTestBase
: public test::BootstrapFixture
, public unotest::MacrosTest
, public XmlTestTools
134 OUString maFilterOptions
;
137 uno::Reference
< lang::XComponent
> mxComponent
;
139 xmlBufferPtr mpXmlBuffer
;
140 const char* mpTestDocumentPath
;
141 const char* mpFilter
;
143 sal_uInt32 mnStartTime
;
144 utl::TempFile maTempFile
;
145 bool mbExported
; ///< Does maTempFile already contain something useful?
148 virtual OUString
getTestName() { return OUString(); }
151 OUString
& getFilterOptions()
153 return maFilterOptions
;
155 void setFilterOptions(const OUString
&rFilterOptions
)
157 maFilterOptions
= rFilterOptions
;
160 SwModelTestBase(const char* pTestDocumentPath
= "", const char* pFilter
= "")
162 , mpTestDocumentPath(pTestDocumentPath
)
167 maTempFile
.EnableKillingFile();
170 virtual ~SwModelTestBase()
173 virtual void setUp() SAL_OVERRIDE
175 test::BootstrapFixture::setUp();
177 mxDesktop
.set(css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
180 virtual void tearDown() SAL_OVERRIDE
182 if (mxComponent
.is())
183 mxComponent
->dispose();
185 test::BootstrapFixture::tearDown();
190 * Helper func used by each unit test to test the 'import' code.
191 * (Loads the requested file and then calls 'verify' method)
193 void executeImportTest(const char* filename
)
195 // If the testcase is stored in some other format, it's pointless to test.
196 if (mustTestImportOf(filename
))
198 maTempFile
.EnableKillingFile(false);
201 load(mpTestDocumentPath
, filename
);
205 maTempFile
.EnableKillingFile();
210 * Helper func used by each unit test to test the 'export' code.
211 * (Loads the requested file, save it to temp file, load the
212 * temp file and then calls 'verify' method)
214 void executeImportExportImportTest(const char* filename
)
216 maTempFile
.EnableKillingFile(false);
219 load(mpTestDocumentPath
, filename
);
221 reload(mpFilter
, filename
);
225 maTempFile
.EnableKillingFile();
229 * Helper func used by each unit test to test the 'export' code.
230 * (Loads the requested file for document base (this represents
231 * the initial document condition), exports with the desired
232 * export filter and then calls 'verify' method)
234 void executeImportExport(const char* filename
)
236 maTempFile
.EnableKillingFile(false);
239 load(mpTestDocumentPath
, filename
);
240 save(OUString::createFromAscii(mpFilter
), maTempFile
);
241 maTempFile
.EnableKillingFile(false);
245 maTempFile
.EnableKillingFile();
249 * Function overridden by unit test. See DECLARE_SW_*_TEST macros
251 virtual void verify()
253 CPPUNIT_FAIL( "verify method must be overridden" );
257 * Override this function if interested in skipping import test for this file
259 virtual bool mustTestImportOf(const char* /* filename */) const
264 * Override this function if some special filename-specific setup is needed
266 virtual void preTest(const char* /*filename*/)
270 /// Override this function if some special file-specific setup is needed during export test: after load, but before save.
271 virtual void postLoad(const char* /*pFilename*/)
276 * Override this function if some special filename-specific teardown is needed
278 virtual void postTest(const char* /*filename*/)
283 * Override this function if calcing layout is not needed
285 virtual bool mustCalcLayoutOf(const char* /*filename*/)
291 * Override this function if validation is wanted
293 virtual bool mustValidate(const char* /*filename*/) const
301 // create the xml writer
302 mpXmlBuffer
= xmlBufferCreate();
303 xmlTextWriterPtr pXmlWriter
= xmlNewTextWriterMemory(mpXmlBuffer
, 0);
304 xmlTextWriterStartDocument(pXmlWriter
, NULL
, NULL
, NULL
);
307 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
308 CPPUNIT_ASSERT(pTextDoc
);
309 SwDoc
* pDoc
= pTextDoc
->GetDocShell()->GetDoc();
310 SwRootFrm
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
311 pLayout
->dumpAsXml(pXmlWriter
);
314 xmlTextWriterEndDocument(pXmlWriter
);
315 xmlFreeTextWriter(pXmlWriter
);
319 void discardDumpedLayout()
323 xmlBufferFree(mpXmlBuffer
);
330 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
331 CPPUNIT_ASSERT(pTextDoc
);
332 SwDoc
* pDoc
= pTextDoc
->GetDocShell()->GetDoc();
333 pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
336 /// Get the length of the whole document.
339 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
340 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xTextDocument
->getText(), uno::UNO_QUERY
);
341 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
343 while (xParaEnum
->hasMoreElements())
345 uno::Reference
<container::XEnumerationAccess
> xRangeEnumAccess(xParaEnum
->nextElement(), uno::UNO_QUERY
);
346 uno::Reference
<container::XEnumeration
> xRangeEnum
= xRangeEnumAccess
->createEnumeration();
347 while (xRangeEnum
->hasMoreElements())
349 uno::Reference
<text::XTextRange
> xRange(xRangeEnum
->nextElement(), uno::UNO_QUERY
);
350 aBuf
.append(xRange
->getString());
353 return aBuf
.getLength();
356 /// Get a family of styles, see com.sun.star.style.StyleFamilies for possible values.
357 uno::Reference
<container::XNameAccess
> getStyles(const OUString
& aFamily
)
359 uno::Reference
<style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier(mxComponent
, uno::UNO_QUERY
);
360 uno::Reference
<container::XNameAccess
> xStyleFamilies(xStyleFamiliesSupplier
->getStyleFamilies(), uno::UNO_QUERY
);
361 uno::Reference
<container::XNameAccess
> xStyleFamily(xStyleFamilies
->getByName(aFamily
), uno::UNO_QUERY
);
365 /// Get a family of auto styles, see com.sun.star.style.StyleFamilies for possible values.
366 uno::Reference
<style::XAutoStyleFamily
> getAutoStyles(const OUString
& aFamily
)
368 uno::Reference
< style::XAutoStylesSupplier
> xAutoStylesSupplier(mxComponent
, uno::UNO_QUERY
);
369 uno::Reference
< style::XAutoStyles
> xAutoStyles(xAutoStylesSupplier
->getAutoStyles());
370 uno::Reference
< style::XAutoStyleFamily
> xAutoStyleFamily(xAutoStyles
->getByName(aFamily
), uno::UNO_QUERY
);
371 return xAutoStyleFamily
;
374 /// Similar to parseExport(), but this gives the xmlDocPtr of the layout dump.
375 xmlDocPtr
parseLayoutDump()
380 return xmlParseMemory(reinterpret_cast<const char*>(xmlBufferContent(mpXmlBuffer
)), xmlBufferLength(mpXmlBuffer
));;
384 * Extract a value from the layout dump using an XPath expression and an attribute name.
386 * If the attribute is omitted, the text of the node is returned.
388 OUString
parseDump(const OString
& aXPath
, const OString
& aAttribute
= OString())
390 xmlDocPtr pXmlDoc
= parseLayoutDump();
392 xmlXPathContextPtr pXmlXpathCtx
= xmlXPathNewContext(pXmlDoc
);
393 xmlXPathObjectPtr pXmlXpathObj
= xmlXPathEvalExpression(BAD_CAST(aXPath
.getStr()), pXmlXpathCtx
);
394 xmlNodeSetPtr pXmlNodes
= pXmlXpathObj
->nodesetval
;
395 CPPUNIT_ASSERT_EQUAL_MESSAGE("parsing dump failed", 1, xmlXPathNodeSetGetLength(pXmlNodes
));
396 xmlNodePtr pXmlNode
= pXmlNodes
->nodeTab
[0];
398 if (aAttribute
.getLength())
399 aRet
= OUString::createFromAscii(reinterpret_cast<char*>(xmlGetProp(pXmlNode
, BAD_CAST(aAttribute
.getStr()))));
401 aRet
= OUString::createFromAscii(reinterpret_cast<char*>(xmlNodeGetContent(pXmlNode
)));
408 template< typename T
>
409 T
getProperty( const uno::Any
& obj
, const OUString
& name
) const
411 uno::Reference
< beans::XPropertySet
> properties( obj
, uno::UNO_QUERY_THROW
);
413 if (!(properties
->getPropertyValue(name
) >>= data
))
415 CPPUNIT_FAIL("the property is of unexpected type or void");
420 template< typename T
>
421 T
getProperty( const uno::Reference
< uno::XInterface
>& obj
, const OUString
& name
) const
423 uno::Reference
< beans::XPropertySet
> properties( obj
, uno::UNO_QUERY_THROW
);
425 if (!(properties
->getPropertyValue(name
) >>= data
))
427 CPPUNIT_FAIL("the property is of unexpected type or void");
432 bool hasProperty(const uno::Reference
<uno::XInterface
>& obj
, const OUString
& name
) const
434 uno::Reference
<beans::XPropertySet
> properties(obj
, uno::UNO_QUERY_THROW
);
435 return properties
->getPropertySetInfo()->hasPropertyByName(name
);
438 /// Get number of paragraphs of the document.
441 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
442 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xTextDocument
->getText(), uno::UNO_QUERY
);
443 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
445 while (xParaEnum
->hasMoreElements())
447 xParaEnum
->nextElement();
453 uno::Reference
<text::XTextContent
> getParagraphOrTable(int number
, uno::Reference
<text::XText
> xText
= uno::Reference
<text::XText
>()) const
455 uno::Reference
<container::XEnumerationAccess
> paraEnumAccess
;
457 paraEnumAccess
.set(xText
, uno::UNO_QUERY
);
460 uno::Reference
<text::XTextDocument
> textDocument(mxComponent
, uno::UNO_QUERY
);
461 paraEnumAccess
.set(textDocument
->getText(), uno::UNO_QUERY
);
463 uno::Reference
<container::XEnumeration
> paraEnum
= paraEnumAccess
->createEnumeration();
467 paraEnum
->nextElement();
468 uno::Reference
< text::XTextContent
> const xElem(paraEnum
->nextElement(),
469 uno::UNO_QUERY_THROW
);
473 // Get paragraph (counted from 1), optionally check it contains the given text.
474 uno::Reference
< text::XTextRange
> getParagraph( int number
, const OUString
& content
= OUString() ) const
476 uno::Reference
<text::XTextRange
> const xParagraph(
477 getParagraphOrTable(number
), uno::UNO_QUERY_THROW
);
478 if( !content
.isEmpty())
479 CPPUNIT_ASSERT_EQUAL_MESSAGE( "paragraph does not have expected content", content
, xParagraph
->getString());
483 uno::Reference
<text::XTextRange
> getParagraphOfText(int number
, uno::Reference
<text::XText
> xText
, const OUString
& content
= OUString()) const
485 uno::Reference
<text::XTextRange
> const xParagraph(getParagraphOrTable(number
, xText
), uno::UNO_QUERY_THROW
);
486 if (!content
.isEmpty())
487 CPPUNIT_ASSERT_EQUAL_MESSAGE( "paragraph does not contain expected content", content
, xParagraph
->getString());
491 /// Get run (counted from 1) of a paragraph, optionally check it contains the given text.
492 uno::Reference
<text::XTextRange
> getRun(uno::Reference
<text::XTextRange
> xParagraph
, int number
, const OUString
& content
= OUString()) const
494 uno::Reference
<container::XEnumerationAccess
> xRunEnumAccess(xParagraph
, uno::UNO_QUERY
);
495 uno::Reference
<container::XEnumeration
> xRunEnum
= xRunEnumAccess
->createEnumeration();
496 for (int i
= 1; i
< number
; ++i
)
497 xRunEnum
->nextElement();
498 uno::Reference
<text::XTextRange
> xRun(xRunEnum
->nextElement(), uno::UNO_QUERY
);
499 if( !content
.isEmpty())
500 CPPUNIT_ASSERT_EQUAL_MESSAGE( "run does not contain expected content", content
, xRun
->getString());
504 /// Get math formula string of a run.
505 OUString
getFormula(uno::Reference
<text::XTextRange
> xRun
) const
507 uno::Reference
<container::XContentEnumerationAccess
> xContentEnumAccess(xRun
, uno::UNO_QUERY
);
508 uno::Reference
<container::XEnumeration
> xContentEnum(xContentEnumAccess
->createContentEnumeration(""), uno::UNO_QUERY
);
509 uno::Reference
<beans::XPropertySet
> xFormula(xContentEnum
->nextElement(), uno::UNO_QUERY
);
510 return getProperty
<OUString
>(getProperty
< uno::Reference
<beans::XPropertySet
> >(xFormula
, "Model"), "Formula");
513 /// get cell of a table; table can be retrieved with getParagraphOrTable
514 uno::Reference
<table::XCell
> getCell(
515 uno::Reference
<uno::XInterface
> const& xTableIfc
,
516 OUString
const& rCell
, OUString
const& rContent
= OUString())
518 uno::Reference
<text::XTextTable
> const xTable(xTableIfc
,
519 uno::UNO_QUERY_THROW
);
520 uno::Reference
<table::XCell
> const xCell(
521 xTable
->getCellByName(rCell
), uno::UNO_SET_THROW
);
522 if (!rContent
.isEmpty())
524 uno::Reference
<text::XText
> const xCellText(xCell
,
525 uno::UNO_QUERY_THROW
);
526 CPPUNIT_ASSERT_EQUAL_MESSAGE("cell does not contain expected content", rContent
, xCellText
->getString());
531 /// Get shape (counted from 1)
532 uno::Reference
<drawing::XShape
> getShape(int number
)
534 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
535 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
536 uno::Reference
<drawing::XShape
> xShape(xDrawPage
->getByIndex(number
- 1), uno::UNO_QUERY
);
540 /// Get shape by name
541 uno::Reference
<drawing::XShape
> getShapeByName(const OUString
& aName
)
543 uno::Reference
<drawing::XShape
> xRet
;
545 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
546 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
547 for (sal_Int32 i
= 0; i
< xDrawPage
->getCount(); ++i
)
549 uno::Reference
<container::XNamed
> xShape(xDrawPage
->getByIndex(i
), uno::UNO_QUERY
);
550 if (xShape
->getName() == aName
)
552 xRet
.set(xShape
, uno::UNO_QUERY
);
559 /// Get TextFrame by name
560 uno::Reference
<drawing::XShape
> getTextFrameByName(const OUString
& aName
)
562 uno::Reference
<text::XTextFramesSupplier
> xTextFramesSupplier(mxComponent
, uno::UNO_QUERY
);
563 uno::Reference
<container::XNameAccess
> xNameAccess(xTextFramesSupplier
->getTextFrames(), uno::UNO_QUERY
);
564 uno::Reference
<drawing::XShape
> xShape(xNameAccess
->getByName(aName
), uno::UNO_QUERY
);
570 std::cout
<< "File tested,Execution Time (ms)" << std::endl
;
573 void load(const char* pDir
, const char* pName
)
575 return loadURL(getURLFromSrc(pDir
) + OUString::createFromAscii(pName
), pName
);
578 void loadURL(OUString
const& rURL
, const char* pName
)
580 if (mxComponent
.is())
581 mxComponent
->dispose();
582 // Output name early, so in the case of a hang, the name of the hanging input file is visible.
584 std::cout
<< pName
<< ",";
585 mnStartTime
= osl_getGlobalTimer();
586 mxComponent
= loadFromDesktop(rURL
, "com.sun.star.text.TextDocument");
587 discardDumpedLayout();
588 if (pName
&& mustCalcLayoutOf(pName
))
592 void reload(const char* pFilter
, const char* filename
)
594 uno::Reference
<frame::XStorable
> xStorable(mxComponent
, uno::UNO_QUERY
);
595 OUString aFilterName
= OUString::createFromAscii(pFilter
);
596 utl::MediaDescriptor aMediaDescriptor
;
597 aMediaDescriptor
["FilterName"] <<= aFilterName
;
598 if (!maFilterOptions
.isEmpty())
599 aMediaDescriptor
["FilterOptions"] <<= maFilterOptions
;
600 xStorable
->storeToURL(maTempFile
.GetURL(), aMediaDescriptor
.getAsConstPropertyValueList());
601 uno::Reference
<lang::XComponent
> xComponent(xStorable
, uno::UNO_QUERY
);
602 xComponent
->dispose();
604 mxComponent
= loadFromDesktop(maTempFile
.GetURL(), "com.sun.star.text.TextDocument");
605 if (mustValidate(filename
))
607 if(aFilterName
== "Office Open XML Text")
609 // too many validation errors right now
610 validate(maTempFile
.GetFileName(), test::OOXML
);
612 else if(aFilterName
== "writer8")
614 // still a few validation errors
615 validate(maTempFile
.GetFileName(), test::ODF
);
618 discardDumpedLayout();
619 if (mustCalcLayoutOf(filename
))
623 /// Save the loaded document to a tempfile. Can be used to check the resulting docx/odt directly as a ZIP file.
624 void save(const OUString
& aFilterName
, utl::TempFile
& rTempFile
)
626 rTempFile
.EnableKillingFile();
627 uno::Reference
<frame::XStorable
> xStorable(mxComponent
, uno::UNO_QUERY
);
628 utl::MediaDescriptor aMediaDescriptor
;
629 aMediaDescriptor
["FilterName"] <<= aFilterName
;
630 if (!maFilterOptions
.isEmpty())
631 aMediaDescriptor
["FilterOptions"] <<= maFilterOptions
;
632 xStorable
->storeToURL(rTempFile
.GetURL(), aMediaDescriptor
.getAsConstPropertyValueList());
637 sal_uInt32 nEndTime
= osl_getGlobalTimer();
638 std::cout
<< (nEndTime
- mnStartTime
) << std::endl
;
639 discardDumpedLayout();
645 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
646 uno::Reference
<text::XTextViewCursorSupplier
> xTextViewCursorSupplier(xModel
->getCurrentController(), uno::UNO_QUERY
);
647 uno::Reference
<text::XPageCursor
> xCursor(xTextViewCursorSupplier
->getViewCursor(), uno::UNO_QUERY
);
648 xCursor
->jumpToLastPage();
649 return xCursor
->getPage();
653 * Given that some problem doesn't affect the result in the importer, we
654 * test the resulting file directly, by opening the zip file, parsing an
655 * xml stream, and asserting an XPath expression. This method returns the
656 * xml stream, so that you can do the asserting.
658 xmlDocPtr
parseExport(const OUString
& rStreamName
= OUString("word/document.xml"))
663 return parseExportInternal( maTempFile
.GetURL(), rStreamName
);
666 xmlDocPtr
parseExportInternal( const OUString
& url
, const OUString
& rStreamName
)
668 // Read the XML stream we're interested in.
669 uno::Reference
<packages::zip::XZipFileAccess2
> xNameAccess
= packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory
), url
);
670 uno::Reference
<io::XInputStream
> xInputStream(xNameAccess
->getByName(rStreamName
), uno::UNO_QUERY
);
671 boost::shared_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
673 xmlDocPtr pXmlDoc
= parseXmlStream(pStream
.get());
674 pXmlDoc
->name
= reinterpret_cast<char *>(xmlStrdup(reinterpret_cast<xmlChar
const *>(OUStringToOString(maTempFile
.GetURL(), RTL_TEXTENCODING_UTF8
).getStr())));
679 * Helper method to return nodes represented by rXPath.
681 virtual void registerNamespaces(xmlXPathContextPtr
& pXmlXpathCtx
) SAL_OVERRIDE
684 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
685 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml"));
686 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006"));
687 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape"));
688 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"));
689 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"));
690 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("wp14"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"));
691 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main"));
692 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("pic"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/picture"));
693 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("rels"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships"));
694 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("w14"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordml"));
695 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("m"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/math"));
696 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("ContentType"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types"));
697 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("lc"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"));
698 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("extended-properties"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
699 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
700 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office"));
702 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0"));
703 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0"));
704 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0"));
705 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0"));
706 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("draw"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"));
707 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("fo"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"));
708 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("xlink"), BAD_CAST("http://www.w3.org/1999/xlink"));
709 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("dc"), BAD_CAST("http://purl.org/dc/elements/1.1/"));
710 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("meta"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:meta:1.0"));
711 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("number"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"));
712 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("svg"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"));
713 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("chart"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:chart:1.0"));
714 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("dr3d"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"));
715 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("math"), BAD_CAST("http://www.w3.org/1998/Math/MathML"));
716 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("form"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:form:1.0"));
717 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("script"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:script:1.0"));
718 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("ooo"), BAD_CAST("http://openoffice.org/2004/office"));
719 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("ooow"), BAD_CAST("http://openoffice.org/2004/writer"));
720 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("oooc"), BAD_CAST("http://openoffice.org/2004/calc"));
721 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("dom"), BAD_CAST("http://www.w3.org/2001/xml-events"));
722 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("xforms"), BAD_CAST("http://www.w3.org/2002/xforms"));
723 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("xsd"), BAD_CAST("http://www.w3.org/2001/XMLSchema"));
724 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("xsi"), BAD_CAST("http://www.w3.org/2001/XMLSchema-instance"));
725 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("rpt"), BAD_CAST("http://openoffice.org/2005/report"));
726 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("of"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:of:1.2"));
727 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("xhtml"), BAD_CAST("http://www.w3.org/1999/xhtml"));
728 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("grddl"), BAD_CAST("http://www.w3.org/2003/g/data-view#"));
729 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("officeooo"), BAD_CAST("http://openoffice.org/2009/office"));
730 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("tableooo"), BAD_CAST("http://openoffice.org/2009/table"));
731 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("drawooo"), BAD_CAST("http://openoffice.org/2010/draw"));
732 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("calcext"), BAD_CAST("urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"));
733 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("loext"), BAD_CAST("urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"));
734 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("field"), BAD_CAST("urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"));
735 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("formx"), BAD_CAST("urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"));
736 xmlXPathRegisterNs(pXmlXpathCtx
, BAD_CAST("css3t"), BAD_CAST("http://www.w3.org/TR/css3-text/"));
741 * Test whether the expected and actual borderline parameters are equal
744 * @param[in] rExpected expected borderline object
745 * @param[in] rActual actual borderline object
746 * @param[in] rSourceLine line from where the assertion is called
747 * Note: This method is the implementatition of CPPUNIT_ASSERT_BORDER_EQUAL, so
748 * use that macro instead.
750 inline void assertBorderEqual(
751 const table::BorderLine2
& rExpected
, const table::BorderLine2
& rActual
,
752 const CppUnit::SourceLine
& rSourceLine
)
754 CPPUNIT_NS::assertEquals
<util::Color
>( rExpected
.Color
, rActual
.Color
, rSourceLine
, "different Color" );
755 CPPUNIT_NS::assertEquals
<sal_Int16
>( rExpected
.InnerLineWidth
, rActual
.InnerLineWidth
, rSourceLine
, "different InnerLineWidth" );
756 CPPUNIT_NS::assertEquals
<sal_Int16
>( rExpected
.OuterLineWidth
, rActual
.OuterLineWidth
, rSourceLine
, "different OuterLineWidth" );
757 CPPUNIT_NS::assertEquals
<sal_Int16
>( rExpected
.LineDistance
, rActual
.LineDistance
, rSourceLine
, "different LineDistance" );
758 CPPUNIT_NS::assertEquals
<sal_Int16
>( rExpected
.LineStyle
, rActual
.LineStyle
, rSourceLine
, "different LineStyle" );
759 CPPUNIT_NS::assertEquals
<sal_Int32
>( rExpected
.LineWidth
, rActual
.LineWidth
, rSourceLine
, "different LineWidth" );
762 #define CPPUNIT_ASSERT_BORDER_EQUAL(aExpected, aActual) \
763 assertBorderEqual( aExpected, aActual, CPPUNIT_SOURCELINE() ) \
765 #endif // INCLUDED_SW_QA_EXTRAS_INC_SWMODELTESTBASE_HXX
767 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */