office-gobmx/test/source/xmltesttools.cxx
Noel Grandin 9b5dad13b5 loplugin:stringadd look for unnecessary temporaries
which defeat the *StringConcat optimisation.
Also make StringConcat conversions treat a nullptr as an empty string,
to match the O*String(char*) constructors.

Change-Id: If45f5b4b6a535c97bfeeacd9ec472a7603a52e5b
Reviewed-on: https://gerrit.libreoffice.org/80724
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2019-10-14 08:26:14 +02:00

278 lines
10 KiB
C++

/* -*- 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>
#include <memory>
#include <vcl/mtfxmldump.hxx>
namespace {
OUString convert(xmlChar const * string) {
OUString s;
CPPUNIT_ASSERT_MESSAGE(
"xmlChar string is not UTF-8",
rtl_convertStringToUString(
&s.pData, reinterpret_cast<char const *>(string), xmlStrlen(string),
RTL_TEXTENCODING_UTF8,
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
| RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
| RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)));
return s;
}
OString oconvert(xmlChar const * string)
{
return reinterpret_cast<char const *>(string);
}
}
XmlTestTools::XmlTestTools()
{}
XmlTestTools::~XmlTestTools()
{}
xmlDocPtr XmlTestTools::parseXml(utl::TempFile const & aTempFile)
{
SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ);
return parseXmlStream(&aFileStream);
}
xmlDocPtr XmlTestTools::parseXmlStream(SvStream* pStream)
{
std::size_t nSize = pStream->remainingSize();
std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nSize + 1]);
pStream->ReadBytes(pBuffer.get(), nSize);
pBuffer[nSize] = 0;
return xmlParseDoc(reinterpret_cast<xmlChar*>(pBuffer.get()));
}
xmlDocPtr XmlTestTools::dumpAndParse(MetafileXmlDump& rDumper, const GDIMetaFile& rGDIMetaFile)
{
SvMemoryStream aStream;
rDumper.dump(rGDIMetaFile, aStream);
aStream.Seek(STREAM_SEEK_TO_BEGIN);
return XmlTestTools::parseXmlStream(&aStream);
}
xmlXPathObjectPtr XmlTestTools::getXPathNode(xmlDocPtr pXmlDoc, const OString& rXPath)
{
xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc);
registerNamespaces(pXmlXpathCtx);
xmlXPathObjectPtr pXmlXpathObj = xmlXPathEvalExpression(BAD_CAST(rXPath.getStr()), pXmlXpathCtx);
xmlXPathFreeContext(pXmlXpathCtx);
return pXmlXpathObj;
}
void XmlTestTools::registerNamespaces(xmlXPathContextPtr& /*pXmlXpathCtx*/)
{
}
OUString XmlTestTools::getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute)
{
CPPUNIT_ASSERT(pXmlDoc);
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1, xmlXPathNodeSetGetLength(pXmlNodes));
if (rAttribute.isEmpty())
{
xmlXPathFreeObject(pXmlObj);
return OUString();
}
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
xmlChar * prop = xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr()));
OString sAttAbsent = OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath
+ "' no attribute '" + rAttribute + "' exist";
CPPUNIT_ASSERT_MESSAGE(sAttAbsent.getStr(), prop);
OUString s(convert(prop));
xmlFree(prop);
xmlXPathFreeObject(pXmlObj);
return s;
}
OUString XmlTestTools::getXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath)
{
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
switch (pXmlObj->type)
{
case XPATH_UNDEFINED:
CPPUNIT_FAIL("Undefined XPath type");
case XPATH_NODESET:
{
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_MESSAGE(
OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' not found")
.getStr(),
xmlXPathNodeSetGetLength(pXmlNodes) > 0);
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
xmlNodePtr pXmlChild = pXmlNode->children;
OUString s;
while (pXmlChild && pXmlChild->type != XML_TEXT_NODE)
pXmlChild = pXmlChild->next;
if (pXmlChild && pXmlChild->type == XML_TEXT_NODE)
s = convert(pXmlChild->content);
xmlXPathFreeObject(pXmlObj);
return s;
}
case XPATH_BOOLEAN:
{
auto boolVal = pXmlObj->boolval;
xmlXPathFreeObject(pXmlObj);
return boolVal ? OUString("true") : OUString("false");
}
case XPATH_NUMBER:
{
auto floatVal = pXmlObj->floatval;
xmlXPathFreeObject(pXmlObj);
return OUString::number(floatVal);
}
case XPATH_STRING:
{
auto convertedVal = convert(pXmlObj->stringval);
xmlXPathFreeObject(pXmlObj);
return convertedVal;
}
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
case XPATH_USERS:
case XPATH_XSLT_TREE:
xmlXPathFreeObject(pXmlObj);
CPPUNIT_FAIL("Unsupported XPath type");
}
CPPUNIT_FAIL("Invalid XPath type");
}
void XmlTestTools::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath)
{
getXPath(pXmlDoc, rXPath, ""); // it asserts that rXPath exists, and returns exactly one node
}
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(OStringLiteral("In <") + pXmlDoc->name + ">, attribute '" + rAttribute + "' of '" + rXPath + "' incorrect value.").getStr(),
rExpectedValue, aValue);
}
void XmlTestTools::assertXPathAttrs(xmlDocPtr pXmlDoc, const OString& rXPath,
const std::vector<std::pair<OString, OUString>>& aPairVector)
{
for (auto& rPair : aPairVector)
{
assertXPath(pXmlDoc, rXPath, rPair.first, rPair.second);
}
}
void XmlTestTools::assertXPath(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfNodes)
{
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
nNumberOfNodes, xmlXPathNodeSetGetLength(pXmlNodes));
xmlXPathFreeObject(pXmlObj);
}
void XmlTestTools::assertXPathContent(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rContent)
{
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath contents of child does not match").getStr(), rContent, getXPathContent(pXmlDoc, rXPath));
}
void XmlTestTools::assertXPathNSDef(xmlDocPtr pXmlDoc, const OString& rXPath,
const OUString& rNSPrefix, const OUString& rNSHref)
{
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_MESSAGE(
OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' not found").getStr(),
xmlXPathNodeSetGetLength(pXmlNodes) > 0);
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
bool bFound = false;
for (xmlNsPtr pNamespace = pXmlNode->nsDef; pNamespace; pNamespace = pNamespace->next)
{
if (!pNamespace->prefix)
continue;
CPPUNIT_ASSERT(pNamespace->href);
if (rNSPrefix == convert(pNamespace->prefix) && rNSHref == convert(pNamespace->href))
{
bFound = true;
break;
}
}
xmlXPathFreeObject(pXmlObj);
CPPUNIT_ASSERT(bFound);
}
void XmlTestTools::assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes)
{
#if LIBXML_VERSION >= 20703 /* xmlChildElementCount is only available in libxml2 >= 2.7.3 */
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of child-nodes is incorrect").getStr(),
nNumberOfChildNodes, static_cast<int>(xmlChildElementCount(pXmlNode)));
xmlXPathFreeObject(pXmlObj);
#else
(void)pXmlDoc;
(void)rXPath;
(void)nNumberOfChildNodes;
#endif
}
void XmlTestTools::assertXPathNoAttribute(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute)
{
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1, xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' unexpected '" + rAttribute + "' attribute").getStr(),
static_cast<xmlChar*>(nullptr), xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr())));
xmlXPathFreeObject(pXmlObj);
}
int XmlTestTools::getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rChildName)
{
xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath);
xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(),
1,
xmlXPathNodeSetGetLength(pXmlNodes));
xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0];
int nRet = 0;
bool bFound = false;
for (xmlNodePtr pChild = pXmlNode->children; pChild; pChild = pChild->next)
{
if (oconvert(pChild->name) == rChildName)
{
bFound = true;
break;
}
++nRet;
}
xmlXPathFreeObject(pXmlObj);
CPPUNIT_ASSERT_MESSAGE(OString(OStringLiteral("In <") + pXmlDoc->name + ">, XPath '" + rXPath
+ "' child '" + rChildName + "' not found")
.getStr(),
bFound);
return nRet;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */