summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-07-19 13:30:28 +0200
committerMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-07-19 13:32:01 +0200
commit76d66256bb6825069f02e759983ef36df1404976 (patch)
treec0c07494c2de1c500b8aa398960d9ef06b5abc4f
parent7c03aacb6746cc136f10acdc6ff8b146db62c8ad (diff)
add test for fdo#79305
Change-Id: I498f272e9da8c5f988e0bf734ffcc1c04b528210
-rw-r--r--sc/Library_scqahelper.mk2
-rw-r--r--sc/qa/unit/data/ods/fdo79305.odsbin0 -> 12995 bytes
-rw-r--r--sc/qa/unit/helper/qahelper.cxx29
-rw-r--r--sc/qa/unit/helper/qahelper.hxx4
-rw-r--r--sc/qa/unit/helper/xpath.cxx116
-rw-r--r--sc/qa/unit/helper/xpath.hxx77
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx17
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
new file mode 100644
index 000000000000..c6f011c4fcde
--- /dev/null
+++ b/sc/qa/unit/data/ods/fdo79305.ods
Binary files differ
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()
{