2012-05-09 15:25:44 +02:00
|
|
|
/*
|
|
|
|
* Version: MPL 1.1 / GPLv3+ / LGPLv3+
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Miklos Vajna <vmiklos@suse.cz> (SUSE, Inc.)
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2012 the
|
|
|
|
* Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
|
|
|
|
* the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
|
|
|
|
* in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
|
|
|
|
* instead of those above.
|
|
|
|
*/
|
|
|
|
|
2012-07-26 12:54:37 +02:00
|
|
|
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
|
2012-12-14 12:58:00 +02:00
|
|
|
#include <com/sun/star/frame/Desktop.hpp>
|
2012-06-15 15:21:36 +02:00
|
|
|
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
2012-05-09 15:25:44 +02:00
|
|
|
#include <com/sun/star/text/XTextDocument.hpp>
|
2012-07-13 20:18:52 +02:00
|
|
|
#include <com/sun/star/text/XTextRange.hpp>
|
2013-02-16 20:56:21 +01:00
|
|
|
#include <com/sun/star/text/XTextTable.hpp>
|
|
|
|
#include <com/sun/star/table/XCell.hpp>
|
2012-05-09 15:25:44 +02:00
|
|
|
|
|
|
|
#include <test/bootstrapfixture.hxx>
|
|
|
|
#include <unotest/macros_test.hxx>
|
|
|
|
#include <rtl/ustrbuf.hxx>
|
2012-12-14 12:58:00 +02:00
|
|
|
#include <comphelper/processfactory.hxx>
|
2012-12-21 22:07:47 +01:00
|
|
|
#include <unotools/tempfile.hxx>
|
2012-05-09 15:25:44 +02:00
|
|
|
|
2012-06-21 17:03:23 +02:00
|
|
|
#include <unotxdoc.hxx>
|
|
|
|
#include <docsh.hxx>
|
|
|
|
#include <doc.hxx>
|
|
|
|
#include <rootfrm.hxx>
|
|
|
|
|
|
|
|
#include <libxml/xmlwriter.h>
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
|
2012-05-09 15:25:44 +02:00
|
|
|
using namespace com::sun::star;
|
|
|
|
|
2012-11-26 07:38:27 +01:00
|
|
|
#define DEFAULT_STYLE "Default Style"
|
|
|
|
|
2012-05-09 15:25:44 +02:00
|
|
|
/// Base class for filter tests loading or roundtriping a document, then asserting the document model.
|
|
|
|
class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest
|
|
|
|
{
|
|
|
|
public:
|
2012-06-21 17:03:23 +02:00
|
|
|
SwModelTestBase()
|
|
|
|
: mpXmlBuffer(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~SwModelTestBase()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-05-09 15:25:44 +02:00
|
|
|
virtual void setUp()
|
|
|
|
{
|
|
|
|
test::BootstrapFixture::setUp();
|
|
|
|
|
2012-12-14 12:58:00 +02:00
|
|
|
mxDesktop.set( com::sun::star::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())) );
|
2012-05-09 15:25:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void tearDown()
|
|
|
|
{
|
|
|
|
if (mxComponent.is())
|
|
|
|
mxComponent->dispose();
|
|
|
|
|
|
|
|
test::BootstrapFixture::tearDown();
|
|
|
|
}
|
|
|
|
|
2012-06-21 17:03:23 +02:00
|
|
|
private:
|
|
|
|
void dumpLayout()
|
|
|
|
{
|
|
|
|
// create the xml writer
|
|
|
|
mpXmlBuffer = xmlBufferCreate();
|
|
|
|
xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(mpXmlBuffer, 0);
|
|
|
|
xmlTextWriterStartDocument(pXmlWriter, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
// create the dump
|
|
|
|
SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
|
|
|
|
SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc();
|
|
|
|
SwRootFrm* pLayout = pDoc->GetCurrentLayout();
|
|
|
|
pLayout->dumpAsXml(pXmlWriter);
|
|
|
|
|
|
|
|
// delete xml writer
|
|
|
|
xmlTextWriterEndDocument(pXmlWriter);
|
|
|
|
xmlFreeTextWriter(pXmlWriter);
|
|
|
|
}
|
|
|
|
|
2013-01-16 11:11:52 +01:00
|
|
|
void calcLayout()
|
|
|
|
{
|
|
|
|
SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
|
|
|
|
SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc();
|
|
|
|
pDoc->GetCurrentViewShell()->CalcLayout();
|
|
|
|
}
|
|
|
|
|
2012-06-21 17:03:23 +02:00
|
|
|
|
2012-05-09 15:25:44 +02:00
|
|
|
protected:
|
|
|
|
/// Get the length of the whole document.
|
|
|
|
int getLength()
|
|
|
|
{
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
2012-09-26 15:37:15 +02:00
|
|
|
OUStringBuffer aBuf;
|
2012-05-09 15:25:44 +02:00
|
|
|
while (xParaEnum->hasMoreElements())
|
|
|
|
{
|
|
|
|
uno::Reference<container::XEnumerationAccess> xRangeEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xRangeEnum = xRangeEnumAccess->createEnumeration();
|
|
|
|
while (xRangeEnum->hasMoreElements())
|
|
|
|
{
|
|
|
|
uno::Reference<text::XTextRange> xRange(xRangeEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
aBuf.append(xRange->getString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aBuf.getLength();
|
|
|
|
}
|
|
|
|
|
2012-06-15 15:21:36 +02:00
|
|
|
/// Get a family of styles, see com.sun.star.style.StyleFamilies for possible values.
|
2012-09-26 15:37:15 +02:00
|
|
|
uno::Reference<container::XNameAccess> getStyles(OUString aFamily)
|
2012-06-15 15:21:36 +02:00
|
|
|
{
|
|
|
|
uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName(aFamily), uno::UNO_QUERY);
|
|
|
|
return xStyleFamily;
|
|
|
|
}
|
|
|
|
|
2012-08-28 11:46:00 +02:00
|
|
|
/**
|
|
|
|
* Extract a value from the layout dump using an XPath expression and an attribute name.
|
|
|
|
*
|
|
|
|
* If the attribute is omitted, the text of the node is returned.
|
|
|
|
*/
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString parseDump(OString aXPath, OString aAttribute = OString())
|
2012-06-21 17:03:23 +02:00
|
|
|
{
|
|
|
|
if (!mpXmlBuffer)
|
|
|
|
dumpLayout();
|
|
|
|
|
|
|
|
xmlDocPtr pXmlDoc = xmlParseMemory((const char*)xmlBufferContent(mpXmlBuffer), xmlBufferLength(mpXmlBuffer));;
|
|
|
|
|
|
|
|
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
|
|
|
|
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(aXPath.getStr()), pXmlXpathCtx);
|
|
|
|
xmlNodeSetPtr pXmlNodes = pXmlXpathObj->nodesetval;
|
2012-08-28 11:46:00 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(1, xmlXPathNodeSetGetLength(pXmlNodes));
|
2012-06-21 17:03:23 +02:00
|
|
|
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
|
2012-09-26 15:37:15 +02:00
|
|
|
OUString aRet;
|
2012-08-28 11:46:00 +02:00
|
|
|
if (aAttribute.getLength())
|
2012-09-26 15:37:15 +02:00
|
|
|
aRet = OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr())));
|
2012-08-28 11:46:00 +02:00
|
|
|
else
|
2012-09-26 15:37:15 +02:00
|
|
|
aRet = OUString::createFromAscii((const char*)XML_GET_CONTENT(pXmlNode));
|
2012-06-21 17:03:23 +02:00
|
|
|
|
|
|
|
xmlFreeDoc(pXmlDoc);
|
|
|
|
|
|
|
|
return aRet;
|
|
|
|
}
|
|
|
|
|
2012-07-13 19:57:59 +02:00
|
|
|
template< typename T >
|
2012-09-26 15:37:15 +02:00
|
|
|
T getProperty( uno::Any obj, const OUString& name ) const
|
2012-07-13 19:57:59 +02:00
|
|
|
{
|
|
|
|
uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY );
|
2012-07-14 14:07:08 +01:00
|
|
|
T data = T();
|
2012-07-13 19:57:59 +02:00
|
|
|
properties->getPropertyValue( name ) >>= data;
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T >
|
2012-09-26 15:37:15 +02:00
|
|
|
T getProperty( uno::Reference< uno::XInterface > obj, const OUString& name ) const
|
2012-07-13 19:57:59 +02:00
|
|
|
{
|
|
|
|
uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY );
|
2012-07-14 14:07:08 +01:00
|
|
|
T data = T();
|
2012-07-13 19:57:59 +02:00
|
|
|
properties->getPropertyValue( name ) >>= data;
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2012-08-13 12:23:05 +02:00
|
|
|
/// Get number of paragraphs of the document.
|
|
|
|
int getParagraphs()
|
|
|
|
{
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
|
|
|
int nRet = 0;
|
|
|
|
while (xParaEnum->hasMoreElements())
|
|
|
|
{
|
|
|
|
xParaEnum->nextElement();
|
|
|
|
nRet++;
|
|
|
|
}
|
|
|
|
return nRet;
|
|
|
|
}
|
|
|
|
|
2012-07-13 20:18:52 +02:00
|
|
|
// Get paragraph (counted from 1), optionally check it contains the given text.
|
2013-02-16 20:56:21 +01:00
|
|
|
uno::Reference<text::XTextContent> getParagraphOrTable(int number) const
|
2012-07-13 20:18:52 +02:00
|
|
|
{
|
|
|
|
uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumerationAccess> paraEnumAccess(textDocument->getText(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> paraEnum = paraEnumAccess->createEnumeration();
|
|
|
|
for( int i = 1;
|
|
|
|
i < number;
|
|
|
|
++i )
|
|
|
|
paraEnum->nextElement();
|
2013-02-16 20:56:21 +01:00
|
|
|
uno::Reference< text::XTextContent> const xElem(paraEnum->nextElement(),
|
|
|
|
uno::UNO_QUERY_THROW);
|
|
|
|
return xElem;
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< text::XTextRange > getParagraph( int number, OUString content = OUString() ) const
|
|
|
|
{
|
|
|
|
uno::Reference<text::XTextRange> const xParagraph(
|
|
|
|
getParagraphOrTable(number), uno::UNO_QUERY_THROW);
|
2012-07-13 20:18:52 +02:00
|
|
|
if( !content.isEmpty())
|
2013-02-16 20:56:21 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL( content, xParagraph->getString());
|
|
|
|
return xParagraph;
|
2012-07-13 20:18:52 +02:00
|
|
|
}
|
|
|
|
|
2012-08-07 12:46:04 +02:00
|
|
|
/// Get run (counted from 1) of a paragraph, optionally check it contains the given text.
|
|
|
|
uno::Reference<text::XTextRange> getRun(uno::Reference<text::XTextRange> xParagraph, int number, OUString content = OUString()) const
|
2012-07-26 12:54:37 +02:00
|
|
|
{
|
|
|
|
uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParagraph, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
|
|
|
|
for (int i = 1; i < number; ++i)
|
|
|
|
xRunEnum->nextElement();
|
|
|
|
uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
|
2012-08-07 12:46:04 +02:00
|
|
|
if( !content.isEmpty())
|
|
|
|
CPPUNIT_ASSERT_EQUAL( content, xRun->getString());
|
2012-07-26 12:54:37 +02:00
|
|
|
return xRun;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get math formula string of a run.
|
|
|
|
OUString getFormula(uno::Reference<text::XTextRange> xRun) const
|
|
|
|
{
|
|
|
|
uno::Reference<container::XContentEnumerationAccess> xContentEnumAccess(xRun, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xContentEnum(xContentEnumAccess->createContentEnumeration(""), uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xFormula(xContentEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
return getProperty<OUString>(getProperty< uno::Reference<beans::XPropertySet> >(xFormula, "Model"), "Formula");
|
|
|
|
}
|
|
|
|
|
2013-02-16 20:56:21 +01:00
|
|
|
/// get cell of a table; table can be retrieved with getParagraphOrTable
|
|
|
|
uno::Reference<table::XCell> getCell(
|
|
|
|
uno::Reference<uno::XInterface> const& xTableIfc,
|
|
|
|
OUString const& rCell, OUString const& rContent = OUString())
|
|
|
|
{
|
|
|
|
uno::Reference<text::XTextTable> const xTable(xTableIfc,
|
|
|
|
uno::UNO_QUERY_THROW);
|
|
|
|
uno::Reference<table::XCell> const xCell(
|
|
|
|
xTable->getCellByName(rCell), uno::UNO_SET_THROW);
|
|
|
|
if (!rContent.isEmpty())
|
|
|
|
{
|
|
|
|
uno::Reference<text::XText> const xCellText(xCell,
|
|
|
|
uno::UNO_QUERY_THROW);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(rContent, xCellText->getString());
|
|
|
|
}
|
|
|
|
return xCell;
|
|
|
|
}
|
|
|
|
|
2012-12-21 22:07:47 +01:00
|
|
|
void header()
|
|
|
|
{
|
|
|
|
fprintf(stderr, "File tested,Execution Time (ms)\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void load(const char* pDir, const char* pName)
|
|
|
|
{
|
|
|
|
// Output name early, so in the case of a hang, the name of the hanging input file is visible.
|
|
|
|
fprintf(stderr, "%s,", pName);
|
|
|
|
m_nStartTime = osl_getGlobalTimer();
|
2013-02-05 14:38:43 -05:00
|
|
|
mxComponent = loadFromDesktop(getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.text.TextDocument");
|
2013-01-16 11:11:52 +01:00
|
|
|
calcLayout();
|
2012-12-21 22:07:47 +01:00
|
|
|
}
|
2013-02-16 20:56:21 +01:00
|
|
|
|
2012-12-21 22:07:47 +01:00
|
|
|
void reload(OUString aFilter)
|
|
|
|
{
|
|
|
|
uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Sequence<beans::PropertyValue> aArgs(1);
|
|
|
|
aArgs[0].Name = "FilterName";
|
|
|
|
aArgs[0].Value <<= aFilter;
|
|
|
|
utl::TempFile aTempFile;
|
|
|
|
aTempFile.EnableKillingFile();
|
|
|
|
xStorable->storeToURL(aTempFile.GetURL(), aArgs);
|
|
|
|
uno::Reference<lang::XComponent> xComponent(xStorable, uno::UNO_QUERY);
|
|
|
|
xComponent->dispose();
|
2013-02-05 14:38:43 -05:00
|
|
|
mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
|
2013-01-10 16:29:58 +01:00
|
|
|
if (mpXmlBuffer)
|
|
|
|
{
|
|
|
|
xmlBufferFree(mpXmlBuffer);
|
|
|
|
mpXmlBuffer = 0;
|
|
|
|
}
|
2013-01-16 11:11:52 +01:00
|
|
|
calcLayout();
|
2012-12-21 22:07:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void finish()
|
|
|
|
{
|
|
|
|
sal_uInt32 nEndTime = osl_getGlobalTimer();
|
|
|
|
fprintf(stderr, "%" SAL_PRIuUINT32"\n", nEndTime - m_nStartTime);
|
2013-01-08 12:49:51 +01:00
|
|
|
if (mpXmlBuffer)
|
|
|
|
{
|
|
|
|
xmlBufferFree(mpXmlBuffer);
|
|
|
|
mpXmlBuffer = 0;
|
|
|
|
}
|
2012-12-21 22:07:47 +01:00
|
|
|
}
|
|
|
|
|
2012-05-09 15:25:44 +02:00
|
|
|
uno::Reference<lang::XComponent> mxComponent;
|
2012-06-21 17:03:23 +02:00
|
|
|
xmlBufferPtr mpXmlBuffer;
|
2012-10-20 11:42:15 +02:00
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct MethodEntry
|
|
|
|
{
|
|
|
|
const char* pName;
|
|
|
|
void (T::*pMethod)();
|
|
|
|
};
|
2012-12-21 22:07:47 +01:00
|
|
|
sal_uInt32 m_nStartTime;
|
2012-05-09 15:25:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|