/* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; #define DEFAULT_STYLE "Default Style" /// Base class for filter tests loading or roundtriping a document, then asserting the document model. class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest { public: SwModelTestBase() : mpXmlBuffer(0) { } ~SwModelTestBase() { } virtual void setUp() { test::BootstrapFixture::setUp(); mxDesktop.set( com::sun::star::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())) ); } virtual void tearDown() { if (mxComponent.is()) mxComponent->dispose(); test::BootstrapFixture::tearDown(); } 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(mxComponent.get()); SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc(); SwRootFrm* pLayout = pDoc->GetCurrentLayout(); pLayout->dumpAsXml(pXmlWriter); // delete xml writer xmlTextWriterEndDocument(pXmlWriter); xmlFreeTextWriter(pXmlWriter); } void calcLayout() { SwXTextDocument* pTxtDoc = dynamic_cast(mxComponent.get()); SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc(); pDoc->GetCurrentViewShell()->CalcLayout(); } protected: /// Get the length of the whole document. int getLength() { uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); uno::Reference xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); uno::Reference xParaEnum = xParaEnumAccess->createEnumeration(); OUStringBuffer aBuf; while (xParaEnum->hasMoreElements()) { uno::Reference xRangeEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); uno::Reference xRangeEnum = xRangeEnumAccess->createEnumeration(); while (xRangeEnum->hasMoreElements()) { uno::Reference xRange(xRangeEnum->nextElement(), uno::UNO_QUERY); aBuf.append(xRange->getString()); } } return aBuf.getLength(); } /// Get a family of styles, see com.sun.star.style.StyleFamilies for possible values. uno::Reference getStyles(OUString aFamily) { uno::Reference xStyleFamiliesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY); uno::Reference xStyleFamily(xStyleFamilies->getByName(aFamily), uno::UNO_QUERY); return xStyleFamily; } /** * 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. */ OUString parseDump(OString aXPath, OString aAttribute = OString()) { 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; CPPUNIT_ASSERT_EQUAL(1, xmlXPathNodeSetGetLength(pXmlNodes)); xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; OUString aRet; if (aAttribute.getLength()) aRet = OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr()))); else aRet = OUString::createFromAscii((const char*)XML_GET_CONTENT(pXmlNode)); xmlFreeDoc(pXmlDoc); return aRet; } template< typename T > T getProperty( uno::Any obj, const OUString& name ) const { uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY ); T data = T(); properties->getPropertyValue( name ) >>= data; return data; } template< typename T > T getProperty( uno::Reference< uno::XInterface > obj, const OUString& name ) const { uno::Reference< beans::XPropertySet > properties( obj, uno::UNO_QUERY ); T data = T(); properties->getPropertyValue( name ) >>= data; return data; } /// Get number of paragraphs of the document. int getParagraphs() { uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); uno::Reference xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); uno::Reference xParaEnum = xParaEnumAccess->createEnumeration(); int nRet = 0; while (xParaEnum->hasMoreElements()) { xParaEnum->nextElement(); nRet++; } return nRet; } // Get paragraph (counted from 1), optionally check it contains the given text. uno::Reference getParagraphOrTable(int number, uno::Reference xText = uno::Reference()) const { uno::Reference paraEnumAccess; if (xText.is()) paraEnumAccess.set(xText, uno::UNO_QUERY); else { uno::Reference textDocument(mxComponent, uno::UNO_QUERY); paraEnumAccess.set(textDocument->getText(), uno::UNO_QUERY); } uno::Reference paraEnum = paraEnumAccess->createEnumeration(); for( int i = 1; i < number; ++i ) paraEnum->nextElement(); 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 const xParagraph( getParagraphOrTable(number), uno::UNO_QUERY_THROW); if( !content.isEmpty()) CPPUNIT_ASSERT_EQUAL( content, xParagraph->getString()); return xParagraph; } uno::Reference getParagraphOfText(int number, uno::Reference xText) const { uno::Reference const xParagraph(getParagraphOrTable(number, xText), uno::UNO_QUERY_THROW); return xParagraph; } /// Get run (counted from 1) of a paragraph, optionally check it contains the given text. uno::Reference getRun(uno::Reference xParagraph, int number, OUString content = OUString()) const { uno::Reference xRunEnumAccess(xParagraph, uno::UNO_QUERY); uno::Reference xRunEnum = xRunEnumAccess->createEnumeration(); for (int i = 1; i < number; ++i) xRunEnum->nextElement(); uno::Reference xRun(xRunEnum->nextElement(), uno::UNO_QUERY); if( !content.isEmpty()) CPPUNIT_ASSERT_EQUAL( content, xRun->getString()); return xRun; } /// Get math formula string of a run. OUString getFormula(uno::Reference xRun) const { uno::Reference xContentEnumAccess(xRun, uno::UNO_QUERY); uno::Reference xContentEnum(xContentEnumAccess->createContentEnumeration(""), uno::UNO_QUERY); uno::Reference xFormula(xContentEnum->nextElement(), uno::UNO_QUERY); return getProperty(getProperty< uno::Reference >(xFormula, "Model"), "Formula"); } /// get cell of a table; table can be retrieved with getParagraphOrTable uno::Reference getCell( uno::Reference const& xTableIfc, OUString const& rCell, OUString const& rContent = OUString()) { uno::Reference const xTable(xTableIfc, uno::UNO_QUERY_THROW); uno::Reference const xCell( xTable->getCellByName(rCell), uno::UNO_SET_THROW); if (!rContent.isEmpty()) { uno::Reference const xCellText(xCell, uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(rContent, xCellText->getString()); } return xCell; } 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(); mxComponent = loadFromDesktop(getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.text.TextDocument"); calcLayout(); } void reload(OUString aFilter) { uno::Reference xStorable(mxComponent, uno::UNO_QUERY); uno::Sequence aArgs(1); aArgs[0].Name = "FilterName"; aArgs[0].Value <<= aFilter; utl::TempFile aTempFile; aTempFile.EnableKillingFile(); xStorable->storeToURL(aTempFile.GetURL(), aArgs); uno::Reference xComponent(xStorable, uno::UNO_QUERY); xComponent->dispose(); mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument"); if (mpXmlBuffer) { xmlBufferFree(mpXmlBuffer); mpXmlBuffer = 0; } calcLayout(); } void finish() { sal_uInt32 nEndTime = osl_getGlobalTimer(); fprintf(stderr, "%" SAL_PRIuUINT32"\n", nEndTime - m_nStartTime); if (mpXmlBuffer) { xmlBufferFree(mpXmlBuffer); mpXmlBuffer = 0; } } uno::Reference mxComponent; xmlBufferPtr mpXmlBuffer; template< typename T > struct MethodEntry { const char* pName; void (T::*pMethod)(); }; sal_uInt32 m_nStartTime; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */