tests: add XML and HTML test tools to test module

XML and HTML parsing and XPath asserts are used by many test in
sw, sc and sd modules. This commit moves this functionallity to
test module, where it is available to all modules.

Change-Id: I53ad9c45b24f4c9bf106cb58ea619002968bfeda
This commit is contained in:
Tomaž Vajngerl 2014-04-29 15:07:54 +02:00
parent de9ebbaddc
commit dde833575e
8 changed files with 240 additions and 160 deletions

View File

@ -0,0 +1,29 @@
/* -*- 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 HTML_TEST_TOOLS_H
#define HTML_TEST_TOOLS_H
#include <sal/config.h>
#include <test/testdllapi.hxx>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <unotools/tempfile.hxx>
#include <boost/scoped_array.hpp>
class OOO_DLLPUBLIC_TEST HtmlTestTools
{
protected:
htmlDocPtr parseHtml(utl::TempFile& aTempFile);
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -0,0 +1,48 @@
/* -*- 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 XML_TEST_TOOLS_H
#define XML_TEST_TOOLS_H
#include <sal/config.h>
#include <test/testdllapi.hxx>
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include <cppunit/TestAssert.h>
class OOO_DLLPUBLIC_TEST XmlTestTools
{
protected:
XmlTestTools();
virtual ~XmlTestTools();
virtual void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx);
xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath);
OUString getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute);
OUString getXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath);
int getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rChildName);
void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath,
const OString& rAttribute = OString(),
const OUString& rExpectedValue = OUString());
void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes);
void assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent);
void assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes);
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -9,49 +9,15 @@
#include "sdmodeltestbase.hxx"
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <rtl/byteseq.hxx>
#include <boost/scoped_array.hpp>
#include <test/htmltesttools.hxx>
#include <test/xmltesttools.hxx>
using namespace css;
using namespace rtl;
class SdHTMLFilterTest : public SdModelTestBase
class SdHTMLFilterTest : public SdModelTestBase, public XmlTestTools, public HtmlTestTools
{
htmlDocPtr parseHtml(utl::TempFile& aTempFile)
{
SvFileStream aFileStream(aTempFile.GetURL(), STREAM_READ);
sal_Size nSize = aFileStream.remainingSize();
boost::scoped_array<sal_uInt8> pBuffer(new sal_uInt8[nSize + 1]);
aFileStream.Read(pBuffer.get(), nSize);
pBuffer[nSize] = 0;
printf("Content: %s\n", reinterpret_cast<char*>(pBuffer.get()));
return htmlParseDoc(reinterpret_cast<xmlChar*>(pBuffer.get()), NULL);
}
xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
{
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
return pXmlXpathObj->nodesetval;
}
void 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));
}
private:
htmlDocPtr exportAndparseHtml(sd::DrawDocShellRef& xDocShRef)
{
FileFormat* pFormat = getFormat(HTML);

View File

@ -18,12 +18,11 @@
#include <swmodule.hxx>
#include <usrpref.hxx>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <test/htmltesttools.hxx>
using namespace rtl;
class Test : public SwModelTestBase
class Test : public SwModelTestBase, public HtmlTestTools
{
private:
FieldUnit m_eUnit;
@ -34,19 +33,6 @@ public:
m_eUnit(FUNIT_NONE)
{}
protected:
htmlDocPtr parseHtml()
{
SvFileStream aFileStream(m_aTempFile.GetURL(), STREAM_READ);
sal_Size nSize = aFileStream.remainingSize();
ByteSequence aBuffer(nSize + 1);
aFileStream.Read(aBuffer.getArray(), nSize);
aBuffer[nSize] = 0;
return htmlParseDoc(reinterpret_cast<xmlChar*>(aBuffer.getArray()), NULL);
}
private:
bool mustCalcLayoutOf(const char* filename) SAL_OVERRIDE
{
@ -119,7 +105,7 @@ DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testCharacterBorder, "charborder.odt")
DECLARE_HTMLEXPORT_TEST(testExportOfImages, "textAndImage.docx")
{
htmlDocPtr pDoc = parseHtml();
htmlDocPtr pDoc = parseHtml(m_aTempFile);
if (pDoc)
{
assertXPath(pDoc, "/html/body", 1);
@ -129,7 +115,7 @@ DECLARE_HTMLEXPORT_TEST(testExportOfImages, "textAndImage.docx")
DECLARE_HTMLEXPORT_TEST(testExportOfImagesWithSkipImageEnabled, "textAndImage.docx")
{
htmlDocPtr pDoc = parseHtml();
htmlDocPtr pDoc = parseHtml(m_aTempFile);
if (pDoc)
{
assertXPath(pDoc, "/html/body", 1);

View File

@ -22,6 +22,7 @@
#include <com/sun/star/table/BorderLine2.hpp>
#include <test/bootstrapfixture.hxx>
#include <test/xmltesttools.hxx>
#include <unotest/macros_test.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <rtl/strbuf.hxx>
@ -36,11 +37,6 @@
#include <doc.hxx>
#include <rootfrm.hxx>
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
using namespace css;
#define DEFAULT_STYLE "Default Style"
@ -114,7 +110,7 @@ using namespace css;
void TestName::verify()
/// Base class for filter tests loading or roundtriping a document, then asserting the document model.
class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest
class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
{
OUString maFilterOptions;
protected:
@ -586,9 +582,8 @@ protected:
/**
* Helper method to return nodes represented by rXPath.
*/
xmlNodeSetPtr getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
virtual void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
{
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w"), BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("mc"), BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006"));
@ -604,102 +599,6 @@ protected:
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("ContentType"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("lc"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("extended-properties"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
return pXmlXpathObj->nodesetval;
}
/**
* Same as the assertXPath(), but don't assert: return the string instead.
*/
OUString 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())));
}
/**
* Same as the assertXPathContent(), but don't assert: return the string instead.
*/
OUString 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];
return OUString::createFromAscii((const char*)((pXmlNode->children[0]).content));
}
/**
* 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.
*/
void assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute = OString(), const OUString& rExpectedValue = OUString())
{
OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute);
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Attribute '" + rAttribute + "' of '" + rXPath + "' incorrect value.").getStr(),
rExpectedValue, aValue);
}
/**
* Assert that rXPath exists, and returns exactly nNumberOfNodes nodes.
* Useful for checking that we do _not_ export some node (nNumberOfNodes == 0).
*/
void 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));
}
/**
* Assert that rXPath exists, and its content equals rContent.
*/
void assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent)
{
CPPUNIT_ASSERT_EQUAL_MESSAGE("XPath contents of child does not match", rContent, getXPathContent(pXmlDoc, rXPath));
}
/**
* Assert that rXPath exists, and has exactly nNumberOfChildNodes child nodes.
* Useful for checking that we do have a no child nodes to a specific node (nNumberOfChildNodes == 0).
*/
void assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes)
{
xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of child-nodes is incorrect").getStr(),
nNumberOfChildNodes, (int)xmlChildElementCount(pXmlNode));
}
/**
* Get the position of the child named rName of the parent node specified by rXPath.
* Useful for checking relative order of elements.
*/
int getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rChildName)
{
xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1,
xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
int nRet = 0;
for (xmlNodePtr pChild = pXmlNode->children; pChild; pChild = pChild->next)
{
if (OUString::createFromAscii((const char*)pChild->name) == rChildName)
break;
++nRet;
}
return nRet;
}
uno::Reference<lang::XComponent> mxComponent;

View File

@ -45,6 +45,8 @@ endif
$(eval $(call gb_Library_add_exception_objects,test,\
test/source/bootstrapfixture \
test/source/diff/diff \
test/source/xmltesttools \
test/source/htmltesttools \
))
# vim: set noet sw=4 ts=4:

View File

@ -0,0 +1,26 @@
/* -*- 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 <test/htmltesttools.hxx>
htmlDocPtr HtmlTestTools::parseHtml(utl::TempFile& aTempFile)
{
SvFileStream aFileStream(aTempFile.GetURL(), STREAM_READ);
sal_Size nSize = aFileStream.remainingSize();
boost::scoped_array<sal_uInt8> pBuffer(new sal_uInt8[nSize + 1]);
aFileStream.Read(pBuffer.get(), nSize);
pBuffer[nSize] = 0;
return htmlParseDoc(reinterpret_cast<xmlChar*>(pBuffer.get()), NULL);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -0,0 +1,124 @@
/* -*- 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 <test/xmltesttools.hxx>
XmlTestTools::XmlTestTools()
{}
XmlTestTools::~XmlTestTools()
{}
xmlNodeSetPtr XmlTestTools::getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
{
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
registerNamespaces(pXmlXpathCtx);
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
return pXmlXpathObj->nodesetval;
}
void XmlTestTools::registerNamespaces(xmlXPathContextPtr& /*pXmlXpathCtx*/)
{
}
/**
* Same as the assertXPath(), but don't assert: return the string instead.
*/
OUString XmlTestTools::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())));
}
/**
* Same as the assertXPathContent(), but don't assert: return the string instead.
*/
OUString XmlTestTools::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];
return OUString::createFromAscii((const char*)((pXmlNode->children[0]).content));
}
/**
* 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.
*/
void XmlTestTools::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);
}
/**
* Assert that rXPath exists, and returns exactly nNumberOfNodes nodes.
* Useful for checking that we do _not_ export some node (nNumberOfNodes == 0).
*/
void XmlTestTools::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));
}
/**
* Assert that rXPath exists, and its content equals rContent.
*/
void XmlTestTools::assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent)
{
CPPUNIT_ASSERT_EQUAL_MESSAGE("XPath contents of child does not match", rContent, getXPathContent(pXmlDoc, rXPath));
}
/**
* Assert that rXPath exists, and has exactly nNumberOfChildNodes child nodes.
* Useful for checking that we do have a no child nodes to a specific node (nNumberOfChildNodes == 0).
*/
void XmlTestTools::assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes)
{
xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of child-nodes is incorrect").getStr(),
nNumberOfChildNodes, (int)xmlChildElementCount(pXmlNode));
}
/**
* Get the position of the child named rName of the parent node specified by rXPath.
* Useful for checking relative order of elements.
*/
int XmlTestTools::getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rChildName)
{
xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath);
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1,
xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
int nRet = 0;
for (xmlNodePtr pChild = pXmlNode->children; pChild; pChild = pChild->next)
{
if (OUString::createFromAscii((const char*)pChild->name) == rChildName)
break;
++nRet;
}
return nRet;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */