diff options
author | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-07-19 13:30:28 +0200 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-07-19 13:32:01 +0200 |
commit | 76d66256bb6825069f02e759983ef36df1404976 (patch) | |
tree | c0c07494c2de1c500b8aa398960d9ef06b5abc4f /sc | |
parent | 7c03aacb6746cc136f10acdc6ff8b146db62c8ad (diff) |
add test for fdo#79305
Change-Id: I498f272e9da8c5f988e0bf734ffcc1c04b528210
Diffstat (limited to 'sc')
-rw-r--r-- | sc/Library_scqahelper.mk | 2 | ||||
-rw-r--r-- | sc/qa/unit/data/ods/fdo79305.ods | bin | 0 -> 12995 bytes | |||
-rw-r--r-- | sc/qa/unit/helper/qahelper.cxx | 29 | ||||
-rw-r--r-- | sc/qa/unit/helper/qahelper.hxx | 4 | ||||
-rw-r--r-- | sc/qa/unit/helper/xpath.cxx | 116 | ||||
-rw-r--r-- | sc/qa/unit/helper/xpath.hxx | 77 | ||||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 17 |
7 files changed, 245 insertions, 0 deletions
diff --git a/sc/Library_scqahelper.mk b/sc/Library_scqahelper.mk index 351b1150f0ea..be7f23088749 100644 --- a/sc/Library_scqahelper.mk +++ b/sc/Library_scqahelper.mk @@ -19,6 +19,7 @@ $(eval $(call gb_Library_use_externals,scqahelper, \ boost_headers \ mdds_headers \ cppunit \ + libxml2 \ )) ifneq ($(SYSTEM_LIBORCUS),) @@ -59,6 +60,7 @@ $(eval $(call gb_Library_use_libraries,scqahelper,\ $(eval $(call gb_Library_add_exception_objects,scqahelper,\ sc/qa/unit/helper/qahelper \ + sc/qa/unit/helper/xpath \ )) # vim: set noet sw=4 ts=4: diff --git a/sc/qa/unit/data/ods/fdo79305.ods b/sc/qa/unit/data/ods/fdo79305.ods Binary files differnew file mode 100644 index 000000000000..c6f011c4fcde --- /dev/null +++ b/sc/qa/unit/data/ods/fdo79305.ods diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx index 0b19843428fe..6f02e9f167b8 100644 --- a/sc/qa/unit/helper/qahelper.cxx +++ b/sc/qa/unit/helper/qahelper.cxx @@ -647,6 +647,35 @@ ScDocShellRef ScBootstrapFixture::saveAndReload( ScDocShell* pShell, sal_Int32 n return xDocSh; } +boost::shared_ptr<utl::TempFile> ScBootstrapFixture::exportTo( ScDocShell* pShell, sal_Int32 nFormat ) +{ + OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ; + OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8); + + boost::shared_ptr<utl::TempFile> pTempFile(new utl::TempFile()); + pTempFile->EnableKillingFile(); + SfxMedium aStoreMedium( pTempFile->GetURL(), STREAM_STD_WRITE ); + sal_uInt32 nExportFormat = 0; + sal_Int32 nFormatType = aFileFormats[nFormat].nFormatType; + if (nFormatType == ODS_FORMAT_TYPE) + nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS; + SfxFilter* pExportFilter = new SfxFilter( + aFilterName, + OUString(), nFormatType, nExportFormat, aFilterType, 0, OUString(), + OUString(), OUString("private:factory/scalc*") ); + pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT); + aStoreMedium.SetFilter(pExportFilter); + pShell->DoSaveAs( aStoreMedium ); + pShell->DoClose(); + + if(nFormatType == XLSX_FORMAT_TYPE) + validate(pTempFile->GetFileName(), test::OOXML); + else if (nFormatType == ODS_FORMAT_TYPE) + validate(pTempFile->GetFileName(), test::ODF); + + return pTempFile; +} + void ScBootstrapFixture::miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems ) { for ( unsigned int index=0; index<numElems; ++index ) diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx index 8c96e360a731..30a655dc56d0 100644 --- a/sc/qa/unit/helper/qahelper.hxx +++ b/sc/qa/unit/helper/qahelper.hxx @@ -32,6 +32,8 @@ #include <sal/types.h> +#include <boost/shared_ptr.hpp> + #if defined(SCQAHELPER_DLLIMPLEMENTATION) #define SCQAHELPER_DLLPUBLIC SAL_DLLPUBLIC_EXPORT #else @@ -244,6 +246,8 @@ public: ScDocShellRef saveAndReload( ScDocShell* pShell, sal_Int32 nFormat ); + static boost::shared_ptr<utl::TempFile> exportTo( ScDocShell* pShell, sal_Int32 nFormat ); + void miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems ); }; diff --git a/sc/qa/unit/helper/xpath.cxx b/sc/qa/unit/helper/xpath.cxx new file mode 100644 index 000000000000..875b7d01ee26 --- /dev/null +++ b/sc/qa/unit/helper/xpath.cxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "xpath.hxx" + +#include <cppunit/TestAssert.h> +#include "qahelper.hxx" + +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include <com/sun/star/packages/zip/ZipFileAccess.hpp> + +xmlDocPtr XPathHelper::parseExport(ScDocShell* pShell, uno::Reference<lang::XMultiServiceFactory> xSFactory, const OUString& rFile, sal_Int32 nFormat) +{ + boost::shared_ptr<utl::TempFile> pTempFile = ScBootstrapFixture::exportTo(pShell, nFormat); + + // Read the XML stream we're interested in. + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(xSFactory), pTempFile->GetURL()); + uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(rFile), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInputStream.is()); + boost::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + sal_uInt64 const nSize = pStream->remainingSize(); + OStringBuffer aDocument(nSize); + char ch; + for (sal_Size i = 0; i < nSize; ++i) + { + pStream->ReadChar( ch ); + aDocument.append(ch); + } + CPPUNIT_ASSERT(!aDocument.isEmpty()); + + // Parse the XML. + return xmlParseMemory((const char*)aDocument.getStr(), aDocument.getLength()); +} + +xmlNodeSetPtr XPathHelper::getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath) +{ + struct { xmlChar* pPrefix; xmlChar* pURI; } aNamespaces[] = + { + { BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main") }, + { BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml") }, + { BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart") }, + { BAD_CAST("a"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main") }, + { BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006") }, + { BAD_CAST("wps"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape") }, + { BAD_CAST("wpg"), BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup") }, + { BAD_CAST("wp"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing") }, + { BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0") }, + { BAD_CAST("table"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:table:1.0") }, + { BAD_CAST("text"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:text:1.0") }, + { BAD_CAST("xlink"), BAD_CAST("http://www.w3c.org/1999/xlink") } + }; + xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc); + for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i) + { + xmlXPathRegisterNs(pXmlXpathCtx, aNamespaces[i].pPrefix, aNamespaces[i].pURI ); + } + + xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx); + return pXmlXpathObj->nodesetval; +} + +void XPathHelper::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute, const OUString& rExpectedValue) +{ + OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + OString("Attribute '" + rAttribute + "' of '" + rXPath + "' incorrect value.").getStr(), + rExpectedValue, aValue); +} + +void XPathHelper::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes) +{ + xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(), + nNumberOfNodes, xmlXPathNodeSetGetLength(pXmlNodes)); +} + +void XPathHelper::assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent) +{ + CPPUNIT_ASSERT_EQUAL_MESSAGE("XPath contents of child does not match", rContent, getXPathContent(pXmlDoc, rXPath)); +} + +OUString XPathHelper::getXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath) +{ + xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath); + + CPPUNIT_ASSERT_MESSAGE(OString("XPath '" + rXPath + "' not found").getStr(), + xmlXPathNodeSetGetLength(pXmlNodes) > 0); + + xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; + + _xmlNode *pNode = &(pXmlNode->children[0]); + return pNode ? OUString::createFromAscii((const char*)((pXmlNode->children[0]).content)) : OUString(); +} + +OUString XPathHelper::getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute) +{ + xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(), + 1, xmlXPathNodeSetGetLength(pXmlNodes)); + if (rAttribute.isEmpty()) + return OUString(); + xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; + return OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr()))); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/helper/xpath.hxx b/sc/qa/unit/helper/xpath.hxx new file mode 100644 index 000000000000..1a63401d5e59 --- /dev/null +++ b/sc/qa/unit/helper/xpath.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_SC_QA_UNIT_HELPER_XPATH_HXX +#define INCLUDED_SC_QA_UNIT_HELPER_XPATH_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <libxml/xpathInternals.h> +#include <libxml/parserInternals.h> + +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#if defined(SCQAHELPER_DLLIMPLEMENTATION) +#define SCQAHELPER_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define SCQAHELPER_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#include "docsh.hxx" +#include "scdllapi.h" + +using namespace com::sun::star; + +namespace XPathHelper +{ + /** + * Given that some problem doesn't affect the result in the importer, we + * test the resulting file directly, by opening the zip file, parsing an + * xml stream, and asserting an XPath expression. This method returns the + * xml stream, so that you can do the asserting. + */ + SCQAHELPER_DLLPUBLIC xmlDocPtr parseExport(ScDocShell* pShell, uno::Reference< lang::XMultiServiceFactory> xSFactory, + const OUString& rFile, sal_Int32 nFormat); + + /** + * Helper method to return nodes represented by rXPath. + */ + SCQAHELPER_DLLPUBLIC xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath); + + /** + * Assert that rXPath exists, and returns exactly one node. + * In case rAttribute is provided, the rXPath's attribute's value must + * equal to the rExpected value. + */ + SCQAHELPER_DLLPUBLIC void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute = OString(), const OUString& rExpectedValue = OUString()); + + /** + * Assert that rXPath exists, and returns exactly nNumberOfNodes nodes. + * Useful for checking that we do _not_ export some node (nNumberOfNodes == 0). + */ + SCQAHELPER_DLLPUBLIC void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes); + + /** + * Same as the assertXPath(), but don't assert: return the string instead. + */ + SCQAHELPER_DLLPUBLIC OUString getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute); + /** + Assert that rXPath exists, and its content equals rContent. + */ + SCQAHELPER_DLLPUBLIC void assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent); + /** + Same as the assertXPathContent(), but don't assert: return the string instead. + */ + SCQAHELPER_DLLPUBLIC OUString getXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index f91a2deee71f..951771029a49 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -18,6 +18,7 @@ #include <svl/stritem.hxx> #include "helper/qahelper.hxx" +#include "helper/xpath.hxx" #include "helper/shared_test_impl.hxx" #include "docsh.hxx" @@ -107,6 +108,8 @@ public: void testFunctionsExcel2010ODS(); #endif + void testRelativePaths(); + CPPUNIT_TEST_SUITE(ScExportTest); CPPUNIT_TEST(test); #if !defined(MACOSX) && !defined(DRAGONFLY) @@ -139,6 +142,7 @@ public: CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX); CPPUNIT_TEST(testFunctionsExcel2010XLSX); CPPUNIT_TEST(testFunctionsExcel2010XLS); + CPPUNIT_TEST(testRelativePaths); /* TODO: export to ODS currently (2014-04-28) makes the validator stumble, * probably due to a loext:fill-character attribute in a @@ -1821,6 +1825,19 @@ void ScExportTest::testFunctionsExcel2010XLS() testFunctionsExcel2010(XLS); } +void ScExportTest::testRelativePaths() +{ + ScDocShellRef xDocSh = loadDoc("fdo79305.", ODS); + CPPUNIT_ASSERT(xDocSh.Is()); + + xmlDocPtr pDoc = XPathHelper::parseExport(&(*xDocSh), m_xSFactory, "content.xml", ODS); + CPPUNIT_ASSERT(pDoc); + OUString aURL = XPathHelper::getXPath(pDoc, + "/office:document-content/office:body/office:spreadsheet/table:table/table:table-row[2]/table:table-cell[2]/text:p/text:a", "href"); + // make sure that the URL is relative + CPPUNIT_ASSERT(aURL.startsWith("..")); +} + #if 0 void ScExportTest::testFunctionsExcel2010ODS() { |