Integrated changes from unicode branch to trunk

git-svn-id: http://pugixml.googlecode.com/svn/trunk@383 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
arseny.kapoulkine 2010-05-06 20:28:36 +00:00
parent efee7df3f4
commit f542c5ebb8
60 changed files with 5847 additions and 2882 deletions

View file

@ -28,8 +28,8 @@ if ( ! $(configuration) )
configuration = "debug" ;
}
# remove empty define
defines -= "" ;
# split defines into list
defines = [ Split $(defines) : ',' ] ;
# options
if ( $(defines) )
@ -41,23 +41,24 @@ else
BUILD = build/$(toolset)/standard/$(configuration) ;
}
if ( $(toolset:I=^mingw) )
if ( $(toolset:I=^mingw) || $(toolset) = gcc )
{
CCFLAGS = -fprofile-arcs -ftest-coverage ;
LDFLAGS = -fprofile-arcs ;
GCOVFLAGS = -n ;
if ( $(toolset) = mingw44 )
{
GCOVFLAGS += -o $(BUILD)/src ; # because stupid gcov can't find files via relative paths any more
}
GCOVFLAGS += -o $(BUILD)/src ; # because stupid gcov can't find files via relative paths
}
# rules
include "Jamrules.jam" ;
# enable dependency cache
DEPCACHE.standard = build/.depcache ;
# targets
Library pugixml : src/pugixml.cpp src/pugixpath.cpp ;
Application tests : tests/main.cpp [ Glob tests : test_*.cpp ] : pugixml ;
Application tests : [ Glob tests : *.cpp ] : pugixml ;
Test run_tests : tests ;
Coverage coverage : run_tests ;
Coverage coverage : pugixml ;
Depends coverage : run_tests ;

View file

@ -8,7 +8,7 @@ if ( $(toolset:I=^mingw) || $(toolset) = "gcc" )
}
else
{
GCCPATH = "%$(toolset)_PATH%\bin\\" ;
GCCPATH = "%$(toolset)_PATH%\\bin\\" ;
}
CCFLAGS += -D$(defines) ;
@ -39,12 +39,12 @@ if ( $(toolset:I=^mingw) || $(toolset) = "gcc" )
actions LinkAction
{
"$(GCCPATH)g++" $(>) -o $(<) -static-libgcc $(LDFLAGS)
"$(GCCPATH)g++" $(>) -o $(<) -static-libgcc -static $(LDFLAGS)
}
actions CoverageAction
actions maxtargets 1 CoverageAction
{
"$(GCCPATH)gcov" $(>:\\) $(GCOVFLAGS) | perl tests/gcov-filter.pl
"$(GCCPATH)gcov" $(>) $(GCOVFLAGS) | perl tests/gcov-filter.pl
}
}
else if ( $(toolset:I=^msvc) )
@ -69,6 +69,15 @@ else if ( $(toolset:I=^msvc) )
CCFLAGS += /W3 ; # lots of warnings at W4 in standard library
}
if ( $(toolset) = msvc7 || $(toolset) = msvc71 || $(toolset) = msvc8 )
{
CCFLAGS += "/I\"%$(toolset)_PATH%\\PlatformSDK\\include\"" ;
}
else if ( $(toolset) != msvc6 )
{
CCFLAGS += "/I\"%WINSDK_PATH%\\Include\"" ;
}
if ( ! ( PUGIXML_NO_EXCEPTIONS in $(defines) ) )
{
CCFLAGS += /EHsc ;
@ -107,7 +116,7 @@ else if ( $(toolset:I=^msvc) )
actions LinkAction
{
"%$(toolset)_PATH%\bin$(postfix)\link.exe" /SUBSYSTEM:CONSOLE /NOLOGO /OUT:$(<) $(>) /LIBPATH:"%$(toolset)_PATH%\lib$(postfix)" /LIBPATH:"%$(toolset)_PATH%\PlatformSDK\lib" /LIBPATH:"%WINSDK_PATH%\Lib$(sdk_postfix)" $(LDFLAGS)
"%$(toolset)_PATH%\bin$(postfix)\link.exe" /SUBSYSTEM:CONSOLE /NOLOGO /OUT:$(<) /PDB:$(<:S=.pdb) $(>) /LIBPATH:"%$(toolset)_PATH%\lib$(postfix)" /LIBPATH:"%$(toolset)_PATH%\PlatformSDK\lib" /LIBPATH:"%WINSDK_PATH%\Lib$(sdk_postfix)" $(LDFLAGS)
}
actions CoverageAction
@ -136,7 +145,7 @@ else if ( $(toolset) = "ic8" )
actions ObjectAction
{
"%$(toolset)_PATH%\bin\icl.exe" /W4 /WX /Wport /Qwd981,444,280,383,909,304,167,177 /I"%$(msvc)_PATH%\include" /I"%$(toolset)_PATH%\include" /c $(>) /Fo$(<) /nologo $(CCFLAGS)
"%$(toolset)_PATH%\bin\icl.exe" /W4 /WX /Wport /Qwd981,444,280,383,909,304,167,177,1419 /I"%$(msvc)_PATH%\include" /I"%$(msvc)_PATH%\PlatformSDK\Include" /I"%$(toolset)_PATH%\include" /c $(>) /Fo$(<) /nologo $(CCFLAGS)
}
actions LibraryAction
@ -183,7 +192,7 @@ else if ( $(toolset:I=^dmc) )
actions LinkAction
{
"%$(toolset)_PATH%\bin\link.exe" $(>:\\) , $(<:\\) , nul , $(LDFLAGS:\\)
"%$(toolset)_PATH%\bin\link.exe" $(>:\\) , $(<:\\) , nul , $(LDFLAGS:\\) -L/co/ma
}
actions CoverageAction
@ -400,6 +409,9 @@ rule CleanCoverage TARGET
# clean object files
local FILES = $($(SOURCE)_objects:S=.gcda) ;
# disable "independent target" warnings
NotFile $(FILES) ;
DeleteAction $(CLEAN_TARGET) : $(FILES) ;
}

View file

@ -14,6 +14,9 @@
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to disable STL
// #define PUGIXML_NO_STL

358
src/pugiutf.hpp Normal file
View file

@ -0,0 +1,358 @@
/**
* pugixml parser - version 0.5
* --------------------------------------------------------
* Copyright (C) 2006-2009, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at http://code.google.com/p/pugixml/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGIUTF_HPP
#define HEADER_PUGIUTF_HPP
namespace pugi
{
namespace impl
{
typedef unsigned char char8_t;
typedef unsigned short char16_t;
typedef unsigned int char32_t;
inline char16_t endian_swap(char16_t value)
{
return static_cast<char16_t>(((value & 0xff) << 8) | (value >> 8));
}
inline char32_t endian_swap(char32_t value)
{
return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
}
struct utf8_counter
{
typedef size_t value_type;
static value_type low(value_type result, char32_t ch)
{
// U+0000..U+007F
if (ch < 0x80) return result + 1;
// U+0080..U+07FF
else if (ch < 0x800) return result + 2;
// U+0800..U+FFFF
else return result + 3;
}
static value_type high(value_type result, char32_t)
{
// U+10000..U+10FFFF
return result + 4;
}
};
struct utf8_writer
{
typedef char8_t* value_type;
static value_type low(value_type result, char32_t ch)
{
// U+0000..U+007F
if (ch < 0x80)
{
*result = static_cast<char8_t>(ch);
return result + 1;
}
// U+0080..U+07FF
else if (ch < 0x800)
{
result[0] = static_cast<char8_t>(0xC0 | (ch >> 6));
result[1] = static_cast<char8_t>(0x80 | (ch & 0x3F));
return result + 2;
}
// U+0800..U+FFFF
else
{
result[0] = static_cast<char8_t>(0xE0 | (ch >> 12));
result[1] = static_cast<char8_t>(0x80 | ((ch >> 6) & 0x3F));
result[2] = static_cast<char8_t>(0x80 | (ch & 0x3F));
return result + 3;
}
}
static value_type high(value_type result, char32_t ch)
{
// U+10000..U+10FFFF
result[0] = static_cast<char8_t>(0xF0 | (ch >> 18));
result[1] = static_cast<char8_t>(0x80 | ((ch >> 12) & 0x3F));
result[2] = static_cast<char8_t>(0x80 | ((ch >> 6) & 0x3F));
result[3] = static_cast<char8_t>(0x80 | (ch & 0x3F));
return result + 4;
}
static value_type any(value_type result, char32_t ch)
{
return (ch < 0x10000) ? low(result, ch) : high(result, ch);
}
};
struct utf16_counter
{
typedef size_t value_type;
static value_type low(value_type result, char32_t)
{
return result + 1;
}
static value_type high(value_type result, char32_t)
{
return result + 2;
}
};
struct utf16_writer
{
typedef char16_t* value_type;
static value_type low(value_type result, char32_t ch)
{
*result = static_cast<char16_t>(ch);
return result + 1;
}
static value_type high(value_type result, char32_t ch)
{
char32_t msh = (char32_t)(ch - 0x10000) >> 10;
char32_t lsh = (char32_t)(ch - 0x10000) & 0x3ff;
result[0] = static_cast<char16_t>(0xD800 + msh);
result[1] = static_cast<char16_t>(0xDC00 + lsh);
return result + 2;
}
static value_type any(value_type result, char32_t ch)
{
return (ch < 0x10000) ? low(result, ch) : high(result, ch);
}
};
struct utf32_counter
{
typedef size_t value_type;
static value_type low(value_type result, char32_t)
{
return result + 1;
}
static value_type high(value_type result, char32_t)
{
return result + 1;
}
};
struct utf32_writer
{
typedef char32_t* value_type;
static value_type low(value_type result, char32_t ch)
{
*result = ch;
return result + 1;
}
static value_type high(value_type result, char32_t ch)
{
*result = ch;
return result + 1;
}
static value_type any(value_type result, char32_t ch)
{
*result = ch;
return result + 1;
}
};
template <size_t size> struct wchar_selector;
template <> struct wchar_selector<2>
{
typedef char16_t type;
typedef utf16_counter counter;
typedef utf16_writer writer;
};
template <> struct wchar_selector<4>
{
typedef char32_t type;
typedef utf32_counter counter;
typedef utf32_writer writer;
};
typedef wchar_selector<sizeof(wchar_t)>::counter wchar_counter;
typedef wchar_selector<sizeof(wchar_t)>::writer wchar_writer;
template <typename Traits> static inline typename Traits::value_type decode_utf8_block(const char8_t* data, size_t size, typename Traits::value_type result, Traits = Traits())
{
const char8_t utf8_byte_mask = 0x3f;
const char8_t* end = data + size;
while (data < end)
{
char8_t lead = *data;
// 0xxxxxxx -> U+0000..U+007F
if (lead < 0x80)
{
result = Traits::low(result, lead);
data += 1;
}
// 110xxxxx -> U+0080..U+07FF
else if ((unsigned)(lead - 0xC0) < 0x20 && data + 1 < end && (data[1] & 0xc0) == 0x80)
{
result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
data += 2;
}
// 1110xxxx -> U+0800-U+FFFF
else if ((unsigned)(lead - 0xE0) < 0x10 && data + 2 < end && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
{
result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
data += 3;
}
// 11110xxx -> U+10000..U+10FFFF
else if ((unsigned)(lead - 0xF0) < 0x08 && data + 3 < end && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
{
result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
data += 4;
}
// 10xxxxxx or 11111xxx -> invalid
else
{
data += 1;
}
}
return result;
}
template <typename Traits, typename opt1> static inline typename Traits::value_type decode_utf16_block(const char16_t* data, size_t size, typename Traits::value_type result, opt1, Traits = Traits())
{
const bool swap = opt1::o1;
const char16_t* end = data + size;
while (data < end)
{
char16_t lead = swap ? endian_swap(*data) : *data;
// U+0000..U+D7FF
if (lead < 0xD800)
{
result = Traits::low(result, lead);
data += 1;
}
// U+E000..U+FFFF
else if ((unsigned)(lead - 0xE000) < 0x2000)
{
result = Traits::low(result, lead);
data += 1;
}
// surrogate pair lead
else if ((unsigned)(lead - 0xD800) < 0x400 && data + 1 < end)
{
char16_t next = swap ? endian_swap(data[1]) : data[1];
if ((unsigned)(next - 0xDC00) < 0x400)
{
result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
data += 2;
}
else
{
data += 1;
}
}
else
{
data += 1;
}
}
return result;
}
template <typename Traits, typename opt1> static inline typename Traits::value_type decode_utf32_block(const char32_t* data, size_t size, typename Traits::value_type result, opt1, Traits = Traits())
{
const bool swap = opt1::o1;
const char32_t* end = data + size;
while (data < end)
{
char32_t lead = swap ? endian_swap(*data) : *data;
// U+0000..U+FFFF
if (lead < 0x10000)
{
result = Traits::low(result, lead);
data += 1;
}
// U+10000..U+10FFFF
else
{
result = Traits::high(result, lead);
data += 1;
}
}
return result;
}
template <typename T> inline void convert_utf_endian_swap(T* result, const T* data, size_t length)
{
for (size_t i = 0; i < length; ++i) result[i] = endian_swap(data[i]);
}
inline void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length)
{
for (size_t i = 0; i < length; ++i) result[i] = static_cast<wchar_t>(endian_swap(static_cast<wchar_selector<sizeof(wchar_t)>::type>(data[i])));
}
}
}
#endif
/**
* Copyright (c) 2006-2009 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

File diff suppressed because it is too large Load diff

View file

@ -17,8 +17,25 @@
#include "pugiconfig.hpp"
#ifndef PUGIXML_NO_STL
# include <string>
# include <iosfwd>
#include <exception>
namespace std
{
struct bidirectional_iterator_tag;
// Borland C++ compiler has a bug which forces template argument names in forward declarations to be the same as in actual definitions
template <class _Ty> class allocator;
template <class _Ty> struct char_traits;
template <class _Elem, class _Traits> class basic_istream;
template <class _Elem, class _Traits> class basic_ostream;
template <class _Elem, class _Traits, class _Ax> class basic_string;
// Digital Mars compiler has a bug which requires a forward declaration for explicit instantiation (otherwise type selection is messed up later, producing link errors)
// Also note that we have to declare char_traits as a class here, since it's defined that way
#ifdef __DMC__
template <> class char_traits<char>;
#endif
}
#endif
// No XPath without STL
@ -45,13 +62,39 @@
#include <stddef.h>
// Character interface macros
#ifdef PUGIXML_WCHAR_MODE
# define PUGIXML_TEXT(t) L ## t
namespace pugi
{
typedef wchar_t char_t;
#ifndef PUGIXML_NO_STL
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_t;
#endif
}
#else
# define PUGIXML_TEXT(t) t
namespace pugi
{
typedef char char_t;
# ifndef PUGIXML_NO_STL
// gcc3.4 has a bug which prevents string_t instantiation using char_t, so we have to use char type explicitly
typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > string_t;
# endif
}
#endif
// Helpers for inline implementation
namespace pugi
{
namespace impl
{
int PUGIXML_FUNCTION strcmp(const char*, const char*);
int PUGIXML_FUNCTION strcmpwild(const char*, const char*);
bool PUGIXML_FUNCTION strequal(const char_t*, const char_t*);
bool PUGIXML_FUNCTION strequalwild(const char_t*, const char_t*);
}
}
@ -199,6 +242,24 @@ namespace pugi
*/
const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol;
/**
* These flags determine the encoding of input data for XML document. Default mode is encoding_auto,
* which means that document encoding is autodetected from BOM and necessary encoding conversions are
* applied. You can override this mode by using any of the specific encodings.
*/
enum encoding_t
{
encoding_auto, //!< Auto-detect input encoding using BOM or </<? detection; use UTF8 if BOM is not found
encoding_utf8, //!< UTF8 encoding
encoding_utf16_le, //!< Little-endian UTF16
encoding_utf16_be, //!< Big-endian UTF16
encoding_utf16, //!< UTF16 with native endianness
encoding_utf32_le, //!< Little-endian UTF32
encoding_utf32_be, //!< Big-endian UTF32
encoding_utf32, //!< UTF32 with native endianness
encoding_wchar //!< The same encoding wchar_t has (either UTF16 or UTF32)
};
// Formatting flags
/**
@ -210,11 +271,11 @@ namespace pugi
const unsigned int format_indent = 0x01;
/**
* This flag determines if UTF-8 BOM is to be written to output stream.
* This flag determines if encoding-specific BOM is to be written to output stream.
*
* This flag is off by default.
*/
const unsigned int format_write_bom_utf8 = 0x02;
const unsigned int format_write_bom = 0x02;
/**
* If this flag is on, no indentation is performed and no line breaks are written to output file.
@ -281,7 +342,7 @@ namespace pugi
xpath_allocator* m_alloc;
xpath_ast_node* m_root;
void compile(const char* query);
void compile(const char_t* query);
public:
/**
@ -290,7 +351,7 @@ namespace pugi
*
* \param query - string with XPath expression
*/
explicit xpath_query(const char* query);
explicit xpath_query(const char_t* query);
/**
* Dtor
@ -335,7 +396,7 @@ namespace pugi
* \param n - context node
* \return evaluation result
*/
std::string evaluate_string(const xml_node& n) const;
string_t evaluate_string(const xml_node& n) const;
/**
* Evaluate expression as node set for the context node \a n.
@ -401,12 +462,20 @@ namespace pugi
*
* \param stream - output stream object
*/
xml_writer_stream(std::ostream& stream);
xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream);
/**
* Construct writer instance
*
* \param stream - output stream object
*/
xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream);
virtual void write(const void* data, size_t size);
private:
std::ostream* stream;
std::basic_ostream<char, std::char_traits<char> >* narrow_stream;
std::basic_ostream<wchar_t, std::char_traits<wchar_t> >* wide_stream;
};
#endif
@ -559,7 +628,7 @@ namespace pugi
* \param rhs - new attribute value
* \return self
*/
xml_attribute& operator=(const char* rhs);
xml_attribute& operator=(const char_t* rhs);
/**
* Set attribute value to \a rhs.
@ -599,7 +668,7 @@ namespace pugi
* \param rhs - new attribute name
* \return success flag (call fails if attribute is empty or there is not enough memory)
*/
bool set_name(const char* rhs);
bool set_name(const char_t* rhs);
/**
* Set attribute value to \a rhs.
@ -607,7 +676,7 @@ namespace pugi
* \param rhs - new attribute value
* \return success flag (call fails if attribute is empty or there is not enough memory)
*/
bool set_value(const char* rhs);
bool set_value(const char_t* rhs);
/**
* Set attribute value to \a rhs.
@ -655,14 +724,14 @@ namespace pugi
*
* \return attribute name, or "" if attribute is empty
*/
const char* name() const;
const char_t* name() const;
/**
* Get attribute value.
*
* \return attribute value, or "" if attribute is empty
*/
const char* value() const;
const char_t* value() const;
};
#ifdef __BORLANDC__
@ -825,14 +894,14 @@ namespace pugi
*
* \return node name, if any; "" otherwise
*/
const char* name() const;
const char_t* name() const;
/**
* Get node value (comment/PI/PCDATA/CDATA contents, depending on node type)
*
* \return node value, if any; "" otherwise
*/
const char* value() const;
const char_t* value() const;
/**
* Get child with the specified name
@ -840,7 +909,7 @@ namespace pugi
* \param name - child name
* \return child with the specified name, if any; empty node otherwise
*/
xml_node child(const char* name) const;
xml_node child(const char_t* name) const;
/**
* Get child with the name that matches specified pattern
@ -848,7 +917,7 @@ namespace pugi
* \param name - child name pattern
* \return child with the name that matches pattern, if any; empty node otherwise
*/
xml_node child_w(const char* name) const;
xml_node child_w(const char_t* name) const;
/**
* Get attribute with the specified name
@ -856,7 +925,7 @@ namespace pugi
* \param name - attribute name
* \return attribute with the specified name, if any; empty attribute otherwise
*/
xml_attribute attribute(const char* name) const;
xml_attribute attribute(const char_t* name) const;
/**
* Get attribute with the name that matches specified pattern
@ -864,7 +933,7 @@ namespace pugi
* \param name - attribute name pattern
* \return attribute with the name that matches pattern, if any; empty attribute otherwise
*/
xml_attribute attribute_w(const char* name) const;
xml_attribute attribute_w(const char_t* name) const;
/**
* Get first of following sibling nodes with the specified name
@ -872,7 +941,7 @@ namespace pugi
* \param name - sibling name
* \return node with the specified name, if any; empty node otherwise
*/
xml_node next_sibling(const char* name) const;
xml_node next_sibling(const char_t* name) const;
/**
* Get first of the following sibling nodes with the name that matches specified pattern
@ -880,7 +949,7 @@ namespace pugi
* \param name - sibling name pattern
* \return node with the name that matches pattern, if any; empty node otherwise
*/
xml_node next_sibling_w(const char* name) const;
xml_node next_sibling_w(const char_t* name) const;
/**
* Get following sibling
@ -895,7 +964,7 @@ namespace pugi
* \param name - sibling name
* \return node with the specified name, if any; empty node otherwise
*/
xml_node previous_sibling(const char* name) const;
xml_node previous_sibling(const char_t* name) const;
/**
* Get first of the preceding sibling nodes with the name that matches specified pattern
@ -903,7 +972,7 @@ namespace pugi
* \param name - sibling name pattern
* \return node with the name that matches pattern, if any; empty node otherwise
*/
xml_node previous_sibling_w(const char* name) const;
xml_node previous_sibling_w(const char_t* name) const;
/**
* Get preceding sibling
@ -931,7 +1000,7 @@ namespace pugi
*
* \return child value of current node, if any; "" otherwise
*/
const char* child_value() const;
const char_t* child_value() const;
/**
* Get child value of child with specified name. \see child_value
@ -940,7 +1009,7 @@ namespace pugi
* \param name - child name
* \return child value of specified child node, if any; "" otherwise
*/
const char* child_value(const char* name) const;
const char_t* child_value(const char_t* name) const;
/**
* Get child value of child with name that matches the specified pattern. \see child_value
@ -949,7 +1018,7 @@ namespace pugi
* \param name - child name pattern
* \return child value of specified child node, if any; "" otherwise
*/
const char* child_value_w(const char* name) const;
const char_t* child_value_w(const char_t* name) const;
public:
/**
@ -958,7 +1027,7 @@ namespace pugi
* \param rhs - new node name
* \return success flag (call fails if node is of the wrong type or there is not enough memory)
*/
bool set_name(const char* rhs);
bool set_name(const char_t* rhs);
/**
* Set node value to \a rhs (for PI/PCDATA/CDATA/comment nodes). \see value
@ -966,7 +1035,7 @@ namespace pugi
* \param rhs - new node value
* \return success flag (call fails if node is of the wrong type or there is not enough memory)
*/
bool set_value(const char* rhs);
bool set_value(const char_t* rhs);
/**
* Add attribute with specified name (for element nodes)
@ -974,7 +1043,7 @@ namespace pugi
* \param name - attribute name
* \return added attribute, or empty attribute if there was an error (wrong node type)
*/
xml_attribute append_attribute(const char* name);
xml_attribute append_attribute(const char_t* name);
/**
* Insert attribute with specified name after \a attr (for element nodes)
@ -983,7 +1052,7 @@ namespace pugi
* \param attr - attribute to insert a new one after
* \return inserted attribute, or empty attribute if there was an error (wrong node type, or attr does not belong to node)
*/
xml_attribute insert_attribute_after(const char* name, const xml_attribute& attr);
xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
/**
* Insert attribute with specified name before \a attr (for element nodes)
@ -992,7 +1061,7 @@ namespace pugi
* \param attr - attribute to insert a new one before
* \return inserted attribute, or empty attribute if there was an error (wrong node type, or attr does not belong to node)
*/
xml_attribute insert_attribute_before(const char* name, const xml_attribute& attr);
xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
/**
* Add a copy of the specified attribute (for element nodes)
@ -1084,7 +1153,7 @@ namespace pugi
*
* \param name - attribute name
*/
void remove_attribute(const char* name);
void remove_attribute(const char_t* name);
/**
* Remove specified child
@ -1098,7 +1167,7 @@ namespace pugi
*
* \param name - child name
*/
void remove_child(const char* name);
void remove_child(const char_t* name);
public:
/**
@ -1121,7 +1190,7 @@ namespace pugi
* \param name - node name
* \param it - output iterator (for example, std::back_insert_iterator (result of std::back_inserter))
*/
template <typename OutputIterator> void all_elements_by_name(const char* name, OutputIterator it) const
template <typename OutputIterator> void all_elements_by_name(const char_t* name, OutputIterator it) const
{
if (!_root) return;
@ -1129,7 +1198,7 @@ namespace pugi
{
if (node.type() == node_element)
{
if (!impl::strcmp(name, node.name()))
if (impl::strequal(name, node.name()))
{
*it = node;
++it;
@ -1146,7 +1215,7 @@ namespace pugi
* \param name - node name pattern
* \param it - output iterator (for example, std::back_insert_iterator (result of std::back_inserter))
*/
template <typename OutputIterator> void all_elements_by_name_w(const char* name, OutputIterator it) const
template <typename OutputIterator> void all_elements_by_name_w(const char_t* name, OutputIterator it) const
{
if (!_root) return;
@ -1154,7 +1223,7 @@ namespace pugi
{
if (node.type() == node_element)
{
if (!impl::strcmpwild(name, node.name()))
if (impl::strequalwild(name, node.name()))
{
*it = node;
++it;
@ -1246,7 +1315,7 @@ namespace pugi
* \param attr_value - attribute value of child node
* \return first matching child node, or empty node
*/
xml_node find_child_by_attribute(const char* name, const char* attr_name, const char* attr_value) const;
xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
/**
* Find child node with the specified name that has specified attribute (use pattern matching for node name and attribute name/value)
@ -1256,7 +1325,7 @@ namespace pugi
* \param attr_value - pattern for attribute value of child node
* \return first matching child node, or empty node
*/
xml_node find_child_by_attribute_w(const char* name, const char* attr_name, const char* attr_value) const;
xml_node find_child_by_attribute_w(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
/**
* Find child node that has specified attribute
@ -1265,7 +1334,7 @@ namespace pugi
* \param attr_value - attribute value of child node
* \return first matching child node, or empty node
*/
xml_node find_child_by_attribute(const char* attr_name, const char* attr_value) const;
xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
/**
* Find child node that has specified attribute (use pattern matching for attribute name/value)
@ -1274,7 +1343,7 @@ namespace pugi
* \param attr_value - pattern for attribute value of child node
* \return first matching child node, or empty node
*/
xml_node find_child_by_attribute_w(const char* attr_name, const char* attr_value) const;
xml_node find_child_by_attribute_w(const char_t* attr_name, const char_t* attr_value) const;
#ifndef PUGIXML_NO_STL
/**
@ -1283,7 +1352,7 @@ namespace pugi
* \param delimiter - delimiter character to insert between element names
* \return path string (e.g. '/bookstore/book/author').
*/
std::string path(char delimiter = '/') const;
string_t path(char_t delimiter = '/') const;
#endif
/**
@ -1293,7 +1362,7 @@ namespace pugi
* \param delimiter - delimiter character to use while tokenizing path
* \return matching node, if any; empty node otherwise
*/
xml_node first_element_by_path(const char* path, char delimiter = '/') const;
xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const;
/**
* Recursively traverse subtree with xml_tree_walker
@ -1313,7 +1382,7 @@ namespace pugi
* \param query - query string
* \return first node from the resulting node set by document order, or empty node if none found
*/
xpath_node select_single_node(const char* query) const;
xpath_node select_single_node(const char_t* query) const;
/**
* Select single node by evaluating XPath query
@ -1329,7 +1398,7 @@ namespace pugi
* \param query - query string
* \return resulting node set
*/
xpath_node_set select_nodes(const char* query) const;
xpath_node_set select_nodes(const char_t* query) const;
/**
* Select node set by evaluating XPath query
@ -1351,7 +1420,7 @@ namespace pugi
* \param flags - formatting flags
* \param depth - starting depth (used for indentation)
*/
void print(xml_writer& writer, const char* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, encoding_t encoding = encoding_auto, unsigned int depth = 0) const;
#ifndef PUGIXML_NO_STL
/**
@ -1363,7 +1432,18 @@ namespace pugi
* \param depth - starting depth (used for indentation)
* \deprecated Use print() with xml_writer_stream instead
*/
void print(std::ostream& os, const char* indent = "\t", unsigned int flags = format_default, unsigned int depth = 0) const;
void print(std::basic_ostream<char, std::char_traits<char> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, encoding_t encoding = encoding_auto, unsigned int depth = 0) const;
/**
* Print subtree to stream
*
* \param os - output stream
* \param indent - indentation string
* \param flags - formatting flags
* \param depth - starting depth (used for indentation)
* \deprecated Use print() with xml_writer_stream instead
*/
void print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
#endif
/**
@ -1388,17 +1468,7 @@ namespace pugi
* It's a bidirectional iterator with value type 'xml_node'.
*/
class PUGIXML_CLASS xml_node_iterator
#ifndef PUGIXML_NO_STL
: public std::iterator<std::bidirectional_iterator_tag, xml_node>
#endif
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4251 4275) // C4251 and C4275 can be ignored for _Container_base, as per MSDN
#endif
{
#ifdef _MSC_VER
# pragma warning(pop)
#endif
friend class xml_node;
private:
@ -1409,6 +1479,18 @@ namespace pugi
explicit xml_node_iterator(xml_node_struct* ref);
public:
/**
* Iterator traits
*/
typedef ptrdiff_t difference_type;
typedef xml_node value_type;
typedef xml_node* pointer;
typedef xml_node& reference;
#ifndef PUGIXML_NO_STL
typedef std::bidirectional_iterator_tag iterator_category;
#endif
/**
* Default ctor
*/
@ -1493,17 +1575,7 @@ namespace pugi
* It's a bidirectional iterator with value type 'xml_attribute'.
*/
class PUGIXML_CLASS xml_attribute_iterator
#ifndef PUGIXML_NO_STL
: public std::iterator<std::bidirectional_iterator_tag, xml_attribute>
#endif
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4251 4275) // C4251 and C4275 can be ignored for _Container_base, as per MSDN
#endif
{
#ifdef _MSC_VER
# pragma warning(pop)
#endif
friend class xml_node;
private:
@ -1514,6 +1586,18 @@ namespace pugi
explicit xml_attribute_iterator(xml_attribute_struct* ref);
public:
/**
* Iterator traits
*/
typedef ptrdiff_t difference_type;
typedef xml_attribute value_type;
typedef xml_attribute* pointer;
typedef xml_attribute& reference;
#ifndef PUGIXML_NO_STL
typedef std::bidirectional_iterator_tag iterator_category;
#endif
/**
* Default ctor
*/
@ -1657,12 +1741,6 @@ namespace pugi
char data[memory_block_size];
};
/**
* Struct used to distinguish parsing with ownership transfer from parsing without it.
* \see xml_document::parse
*/
struct transfer_ownership_tag {};
/**
* Parsing status enumeration, returned as part of xml_parse_result struct
*/
@ -1702,6 +1780,9 @@ namespace pugi
/// Line in parser source which reported this
unsigned int line;
/// Source document encoding
encoding_t encoding;
/// Cast to bool operator
operator bool() const
{
@ -1719,7 +1800,7 @@ namespace pugi
class PUGIXML_CLASS xml_document: public xml_node
{
private:
char* _buffer;
char_t* _buffer;
xml_memory_block _memory;
@ -1749,17 +1830,26 @@ namespace pugi
* \param options - parsing options
* \return parsing result
*/
xml_parse_result load(std::istream& stream, unsigned int options = parse_default);
xml_parse_result load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
/**
* Load document from stream.
*
* \param stream - stream with xml data
* \param options - parsing options
* \return parsing result
*/
xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);
#endif
/**
* Load document from string.
* Load document from string. String has to be zero-terminated. No encoding conversions are applied.
*
* \param contents - input string
* \param options - parsing options
* \return parsing result
*/
xml_parse_result load(const char* contents, unsigned int options = parse_default);
xml_parse_result load(const char_t* contents, unsigned int options = parse_default);
/**
* Load document from file
@ -1768,32 +1858,43 @@ namespace pugi
* \param options - parsing options
* \return parsing result
*/
xml_parse_result load_file(const char* name, unsigned int options = parse_default);
xml_parse_result load_file(const char* name, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
/**
* Parse the given XML string in-situ.
* The string is modified; you should ensure that string data will persist throughout the
* document's lifetime. Although, document does not gain ownership over the string, so you
* should free the memory occupied by it manually.
* Load document from buffer
*
* \param xmlstr - readwrite string with xml data
* \param contents - buffer contents
* \param size - buffer size in bytes
* \param options - parsing options
* \return parsing result
*/
xml_parse_result parse(char* xmlstr, unsigned int options = parse_default);
xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
/**
* Parse the given XML string in-situ (gains ownership).
* The string is modified; document gains ownership over the string, so you don't have to worry
* about it's lifetime.
* Call example: doc.parse(transfer_ownership_tag(), string, options);
* Load document from buffer in-situ.
* The buffer is modified; you should ensure that buffer data will persist throughout the document's
* lifetime. Document does not gain ownership over the buffer, so you should free the buffer memory manually.
*
* \param xmlstr - readwrite string with xml data
* \param contents - buffer contents
* \param size - buffer size in bytes
* \param options - parsing options
* \return parsing result
*/
xml_parse_result parse(const transfer_ownership_tag&, char* xmlstr, unsigned int options = parse_default);
xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
/**
* Load document from buffer in-situ (gains buffer ownership).
* The buffer is modified; you should ensure that buffer data will persist throughout the document's
* lifetime. Document gains ownership over the buffer, so you should allocate the buffer with pugixml
* allocation function.
*
* \param contents - buffer contents
* \param size - buffer size in bytes
* \param options - parsing options
* \return parsing result
*/
xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, encoding_t encoding = encoding_auto);
/**
* Save XML to writer
*
@ -1801,7 +1902,27 @@ namespace pugi
* \param indent - indentation string
* \param flags - formatting flags
*/
void save(xml_writer& writer, const char* indent = "\t", unsigned int flags = format_default) const;
void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, encoding_t encoding = encoding_auto) const;
#ifndef PUGIXML_NO_STL
/**
* Save XML to stream
*
* \param stream - output stream
* \param indent - indentation string
* \param flags - formatting flags
*/
void save(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, encoding_t encoding = encoding_auto) const;
/**
* Save XML to stream
*
* \param stream - output stream
* \param indent - indentation string
* \param flags - formatting flags
*/
void save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
#endif
/**
* Save XML to file
@ -1811,7 +1932,7 @@ namespace pugi
* \param flags - formatting flags
* \return success flag
*/
bool save_file(const char* name, const char* indent = "\t", unsigned int flags = format_default) const;
bool save_file(const char* name, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, encoding_t encoding = encoding_auto) const;
/**
* Compute document order for the whole tree
@ -2063,20 +2184,20 @@ namespace pugi
#ifndef PUGIXML_NO_STL
/**
* Convert utf16 to utf8
* Convert wide string to utf8
*
* \param str - input UTF16 string
* \param str - input wide string string
* \return output UTF8 string
*/
std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str);
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const wchar_t* str);
/**
* Convert utf8 to utf16
* Convert utf8 to wide string
*
* \param str - input UTF8 string
* \return output UTF16 string
* \return output wide string string
*/
std::wstring PUGIXML_FUNCTION as_utf16(const char* str);
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const char* str);
#endif
/**
@ -2104,7 +2225,7 @@ namespace pugi
* \param allocate - allocation function
* \param deallocate - deallocation function
*
* \note XPath-related allocations, as well as allocations in functions that return std::string (xml_node::path, as_utf8, as_utf16)
* \note XPath-related allocations, as well as allocations in functions that return std::string (xml_node::path, as_utf8, as_wide)
* are not performed via these functions.
* \note If you're using parse() with ownership transfer, you have to allocate the buffer you pass to parse() with allocation
* function you set via this function.
@ -2128,6 +2249,15 @@ namespace pugi
deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function();
}
#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
namespace std
{
// Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier)
std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&);
std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&);
}
#endif
#endif
/**

File diff suppressed because it is too large Load diff

89
tests/allocator.cpp Normal file
View file

@ -0,0 +1,89 @@
#include "allocator.hpp"
#include <string.h>
// Low-level allocation functions
#if defined(_WIN32) || defined(_WIN64)
# ifdef __MWERKS__
# pragma ANSI_strict off // disable ANSI strictness to include windows.h
# pragma cpp_extensions on // enable some extensions to include windows.h
# endif
# include <windows.h>
namespace
{
const size_t PAGE_SIZE = 4096;
void* allocate(size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void* ptr = VirtualAlloc(0, aligned_size + PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ptr) return 0;
void* end = (char*)ptr + aligned_size;
DWORD old_flags;
VirtualProtect(end, PAGE_SIZE, PAGE_NOACCESS, &old_flags);
return (char*)end - size;
}
void deallocate(void* ptr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void* rptr = (char*)ptr + size - aligned_size;
DWORD old_flags;
VirtualProtect(rptr, aligned_size + PAGE_SIZE, PAGE_NOACCESS, &old_flags);
}
}
#else
# include <stdlib.h>
namespace
{
void* allocate(size_t size)
{
return malloc(size);
}
void deallocate(void* ptr, size_t size)
{
(void)size;
free(ptr);
}
}
#endif
// High-level allocation functions
void* memory_allocate(size_t size)
{
void* result = allocate(size + sizeof(size_t));
if (!result) return 0;
memcpy(result, &size, sizeof(size_t));
return (size_t*)result + 1;
}
size_t memory_size(void* ptr)
{
size_t result;
memcpy(&result, (size_t*)ptr - 1, sizeof(size_t));
return result;
}
void memory_deallocate(void* ptr)
{
if (!ptr) return;
size_t size = memory_size(ptr);
deallocate((size_t*)ptr - 1, size + sizeof(size_t));
}

7
tests/allocator.hpp Normal file
View file

@ -0,0 +1,7 @@
#pragma once
#include <stddef.h>
void* memory_allocate(size_t size);
size_t memory_size(void* ptr);
void memory_deallocate(void* ptr);

141
tests/autotest.pl Normal file
View file

@ -0,0 +1,141 @@
#!/usr/bin/perl
sub permute
{
my @defines = @_;
my @result = ('');
foreach $define (@defines)
{
push @result, map { length($_) == 0 ? $define : "$_,$define" } @result;
}
@result;
}
$fast = (shift eq 'fast');
@toolsets = ($^O =~ /win/i) ? (bcc, cw, dmc, ic8, mingw34, mingw44, mingw45, msvc6, msvc7, msvc71, msvc8, msvc9, msvc9_x64, msvc10) : (gcc);
@configurations = (debug, release);
@defines = (PUGIXML_NO_XPATH, PUGIXML_NO_EXCEPTIONS, PUGIXML_NO_STL, PUGIXML_WCHAR_MODE);
@definesabbr = (noxpath, noexcept, nostl, wchar);
if ($fast)
{
@defines = (PUGIXML_WCHAR_MODE);
@definesabbr = (wchar);
}
@definesets = permute(@defines);
$fail = 0;
system("echo ### autotest begin >autotest.log");
%results = ();
foreach $toolset (@toolsets)
{
foreach $configuration (@configurations)
{
foreach $defineset (@definesets)
{
$defineabbr = $defineset;
$defineabbr =~ s/,/ /g;
for ($i = 0; $i < $#definesabbr + 1; ++$i)
{
$defineabbr =~ s/$defines[$i]/$definesabbr[$i]/;
}
if ($defineabbr !~ /noxpath/ && $defineabbr =~ /noexcept/) { next; }
if ($defineabbr !~ /noxpath/ && $defineabbr =~ /nostl/) { next; }
print "*** testing $toolset/$configuration ($defineabbr) ... ***\n";
my $cmdline = "jam toolset=$toolset configuration=$configuration defines=$defineset";
my $coverage_pugixml = 0;
my $coverage_pugixpath = 0;
system("echo ^# $cmdline run_tests >>autotest.log");
$result = system("$cmdline run_tests >>autotest.log");
# get coverage
if ($result == 0 && $toolset =~ /mingw|gcc/)
{
$coverage = `$cmdline coverage`;
$coverage_pugixml = $1 if ($coverage =~ /pugixml\.cpp' executed:([^%]+)%/);
$coverage_pugixpath = $1 if ($coverage =~ /pugixpath\.cpp' executed:([^%]+)%/);
}
# record failures
$fail = 1 if ($result != 0);
# print build report
my $report = "";
if ($result == 0)
{
my $align = ($coverage_pugixml > 0 || $coverage_pugixpath > 0) ? 'left' : 'center';
$report .= "<td bgcolor='#00ff00' align='$align'>passed";
if ($coverage_pugixml > 0 || $coverage_pugixpath > 0)
{
$report .= " <font size='-2'>$coverage_pugixml% / $coverage_pugixpath%</font>";
}
$report .= "</td>"
}
else
{
$report .= "<td bgcolor='#ff0000' align='center'>failed</td>"
}
$results{"$configuration $defineabbr"}{$toolset} = $report;
}
last if ($fast);
}
}
system("echo ### autotest end >>autotest.log");
$date = scalar localtime;
$report = <<END;
<html><head><title>pugixml autotest report</title></head><body>
<h3>pugixml autotest report</h3>
<table border=0 cellspacing=0 cellpadding=4>
<tr><td></td>
END
foreach $toolset (@toolsets)
{
$report .= "<th>$toolset</th>";
}
$report .= "</tr>\n";
foreach $k (sort {$a cmp $b} keys %results)
{
$report .= "<tr><td>$k</td>";
foreach $toolset (@toolsets)
{
$report .= $results{$k}{$toolset};
}
$report .= "</tr>\n";
}
$report .= <<END;
</table><br>
Generated on $date
</body></html>
END
open FILE, ">autotest.html";
print FILE $report;
close FILE;

0
tests/data/empty.xml Normal file
View file

3
tests/data/multiline.xml Normal file
View file

@ -0,0 +1,3 @@
<node1 />
<node2 />
<node3 />

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!DOCTYPE 週報 SYSTEM "weekly-utf-8.dtd">
<!-- 週報サンプル -->
<週報>
<English name="name" value="value">The world has many languages</English>
<Russian name="название(имя)" value="ценность">Мир имеет много языков</Russian>
<Spanish name="el nombre" value="el valor">el mundo tiene muchos idiomas</Spanish>
<SimplifiedChinese name="名字" value="价值">世界有很多语言</SimplifiedChinese>
<Русский название="name" ценность="value">&lt;имеет&gt;</Русский>
<汉语 名字="name" 价值="value">世界有很多语言𤭢</汉语>
<Heavy>&quot;Mëtæl!&quot;</Heavy>
>Umlaut Element</ä>
<年月週>
<年度>1997</年度>
<月度>1</月度>
<週>1</週>
</年月週>
<氏名>
<氏>山田</氏>
<名>太郎</名>
</氏名>
<業務報告リスト>
<業務報告>
<業務名>XMLエディターの作成</業務名>
<業務コード>X3355-23</業務コード>
<工数管理>
<見積もり工数>1600</見積もり工数>
<実績工数>320</実績工数>
<当月見積もり工数>160</当月見積もり工数>
<当月実績工数>24</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P>XMLエディターの基本仕様の作成</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>XMLエディターの基本仕様の作成</P>
</実施事項>
<実施事項>
<P>競合他社製品の機能調査</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>特になし</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>XMLとは何かわからない。</P>
</問題点対策>
</業務報告>
<業務報告>
<業務名>検索エンジンの開発</業務名>
<業務コード>S8821-76</業務コード>
<工数管理>
<見積もり工数>120</見積もり工数>
<実績工数>6</実績工数>
<当月見積もり工数>32</当月見積もり工数>
<当月実績工数>2</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P><A href="http://www.goo.ne.jp">goo</A>の機能を調べてみる</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>更に、どういう検索エンジンがあるか調査する</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>開発をするのはめんどうなので、Yahoo!を買収して下さい。</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>検索エンジンで車を走らせることができない。(要調査)</P>
</問題点対策>
</業務報告>
</業務報告リスト>
</週報>

View file

@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!DOCTYPE 週報 SYSTEM "weekly-utf-8.dtd">
<!-- 週報サンプル -->
<週報>
<English name="name" value="value">The world has many languages</English>
<Russian name="название(имя)" value="ценность">Мир имеет много языков</Russian>
<Spanish name="el nombre" value="el valor">el mundo tiene muchos idiomas</Spanish>
<SimplifiedChinese name="名字" value="价值">世界有很多语言</SimplifiedChinese>
<Русский название="name" ценность="value">&lt;имеет&gt;</Русский>
<汉语 名字="name" 价值="value">世界有很多语言𤭢</汉语>
<Heavy>&quot;Mëtæl!&quot;</Heavy>
>Umlaut Element</ä>
<年月週>
<年度>1997</年度>
<月度>1</月度>
<週>1</週>
</年月週>
<氏名>
<氏>山田</氏>
<名>太郎</名>
</氏名>
<業務報告リスト>
<業務報告>
<業務名>XMLエディターの作成</業務名>
<業務コード>X3355-23</業務コード>
<工数管理>
<見積もり工数>1600</見積もり工数>
<実績工数>320</実績工数>
<当月見積もり工数>160</当月見積もり工数>
<当月実績工数>24</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P>XMLエディターの基本仕様の作成</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>XMLエディターの基本仕様の作成</P>
</実施事項>
<実施事項>
<P>競合他社製品の機能調査</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>特になし</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>XMLとは何かわからない。</P>
</問題点対策>
</業務報告>
<業務報告>
<業務名>検索エンジンの開発</業務名>
<業務コード>S8821-76</業務コード>
<工数管理>
<見積もり工数>120</見積もり工数>
<実績工数>6</実績工数>
<当月見積もり工数>32</当月見積もり工数>
<当月実績工数>2</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P><A href="http://www.goo.ne.jp">goo</A>の機能を調べてみる</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>更に、どういう検索エンジンがあるか調査する</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>開発をするのはめんどうなので、Yahoo!を買収して下さい。</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>検索エンジンで車を走らせることができない。(要調査)</P>
</問題点対策>
</業務報告>
</業務報告リスト>
</週報>

View file

@ -0,0 +1,84 @@
<?xml version="1.0"?><!-- 週報サンプル --><週報>
<English name="name" value="value">The world has many languages</English>
<Russian name="название(имя)" value="ценность">Мир имеет много языков</Russian>
<Spanish name="el nombre" value="el valor">el mundo tiene muchos idiomas</Spanish>
<SimplifiedChinese name="名字" value="价值">世界有很多语言</SimplifiedChinese>
<Русский название="name" ценность="value">&lt;имеет&gt;</Русский>
<汉语 名字="name" 价值="value">世界有很多语言𤭢</汉语>
<Heavy>quot;Mëtæl!quot;</Heavy>
>Umlaut Element</ä>
<年月週>
<年度>1997</年度>
<月度>1</月度>
<週>1</週>
</年月週>
<氏名>
<氏>山田</氏>
<名>太郎</名>
</氏名>
<業務報告リスト>
<業務報告>
<業務名>XMLエディターの作成</業務名>
<業務コード>X3355-23</業務コード>
<工数管理>
<見積もり工数>1600</見積もり工数>
<実績工数>320</実績工数>
<当月見積もり工数>160</当月見積もり工数>
<当月実績工数>24</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P>XMLエディターの基本仕様の作成</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>XMLエディターの基本仕様の作成</P>
</実施事項>
<実施事項>
<P>競合他社製品の機能調査</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>特になし</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>XMLとは何かわからない。</P>
</問題点対策>
</業務報告>
<業務報告>
<業務名>検索エンジンの開発</業務名>
<業務コード>S8821-76</業務コード>
<工数管理>
<見積もり工数>120</見積もり工数>
<実績工数>6</実績工数>
<当月見積もり工数>32</当月見積もり工数>
<当月実績工数>2</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P><A href="http://www.goo.ne.jp">goo</A>の機能を調べてみる</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>更に、どういう検索エンジンがあるか調査する</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>開発をするのはめんどうなので、Yahoo!を買収して下さい。</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>検索エンジンで車を走らせることができない。(要調査)</P>
</問題点対策>
</業務報告>
</業務報告リスト>
</週報>

View file

@ -0,0 +1,86 @@
<!DOCTYPE 週報 SYSTEM "weekly-utf-8.dtd">
<!-- 週報サンプル -->
<週報>
<English name="name" value="value">The world has many languages</English>
<Russian name="название(имя)" value="ценность">Мир имеет много языков</Russian>
<Spanish name="el nombre" value="el valor">el mundo tiene muchos idiomas</Spanish>
<SimplifiedChinese name="名字" value="价值">世界有很多语言</SimplifiedChinese>
<Русский название="name" ценность="value">&lt;имеет&gt;</Русский>
<汉语 名字="name" 价值="value">世界有很多语言𤭢</汉语>
<Heavy>&quot;Mëtæl!&quot;</Heavy>
>Umlaut Element</ä>
<年月週>
<年度>1997</年度>
<月度>1</月度>
<週>1</週>
</年月週>
<氏名>
<氏>山田</氏>
<名>太郎</名>
</氏名>
<業務報告リスト>
<業務報告>
<業務名>XMLエディターの作成</業務名>
<業務コード>X3355-23</業務コード>
<工数管理>
<見積もり工数>1600</見積もり工数>
<実績工数>320</実績工数>
<当月見積もり工数>160</当月見積もり工数>
<当月実績工数>24</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P>XMLエディターの基本仕様の作成</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>XMLエディターの基本仕様の作成</P>
</実施事項>
<実施事項>
<P>競合他社製品の機能調査</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>特になし</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>XMLとは何かわからない。</P>
</問題点対策>
</業務報告>
<業務報告>
<業務名>検索エンジンの開発</業務名>
<業務コード>S8821-76</業務コード>
<工数管理>
<見積もり工数>120</見積もり工数>
<実績工数>6</実績工数>
<当月見積もり工数>32</当月見積もり工数>
<当月実績工数>2</当月実績工数>
</工数管理>
<予定項目リスト>
<予定項目>
<P><A href="http://www.goo.ne.jp">goo</A>の機能を調べてみる</P>
</予定項目>
</予定項目リスト>
<実施事項リスト>
<実施事項>
<P>更に、どういう検索エンジンがあるか調査する</P>
</実施事項>
</実施事項リスト>
<上長への要請事項リスト>
<上長への要請事項>
<P>開発をするのはめんどうなので、Yahoo!を買収して下さい。</P>
</上長への要請事項>
</上長への要請事項リスト>
<問題点対策>
<P>検索エンジンで車を走らせることができない。(要調査)</P>
</問題点対策>
</業務報告>
</業務報告リスト>
</週報>

View file

@ -49,7 +49,12 @@ template <typename T> static void generic_rel_ops_test(T obj1, T obj2)
T null = T();
// obj1 < obj2 (we use operator<, but there is no other choice
if (obj1 > obj2) std::swap(obj1, obj2);
if (obj1 > obj2)
{
T temp = obj1;
obj1 = obj2;
obj2 = temp;
}
// operator<
CHECK(null < obj1);

View file

@ -1,33 +1,26 @@
#include "test.hpp"
#include "allocator.hpp"
#include <exception>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <float.h>
test_runner* test_runner::_tests = 0;
size_t test_runner::_memory_fail_threshold = 0;
jmp_buf test_runner::_failure;
jmp_buf test_runner::_failure_buffer;
const char* test_runner::_failure_message;
static size_t g_memory_total_size = 0;
#ifdef __linux
size_t _msize(void* ptr)
{
return malloc_usable_size(ptr);
}
#endif
static void* custom_allocate(size_t size)
{
if (test_runner::_memory_fail_threshold > 0 && test_runner::_memory_fail_threshold < size)
return 0;
else
{
void* ptr = malloc(size);
void* ptr = memory_allocate(size);
g_memory_total_size += _msize(ptr);
g_memory_total_size += memory_size(ptr);
return ptr;
}
@ -37,9 +30,9 @@ static void custom_deallocate(void* ptr)
{
if (ptr)
{
g_memory_total_size -= _msize(ptr);
g_memory_total_size -= memory_size(ptr);
free(ptr);
memory_deallocate(ptr);
}
}
@ -48,7 +41,7 @@ static void replace_memory_management()
// create some document to touch original functions
{
pugi::xml_document doc;
doc.append_child().set_name("node");
doc.append_child().set_name(STR("node"));
}
// replace functions
@ -77,7 +70,7 @@ static bool run_test(test_runner* test)
# pragma warning(disable: 4611) // interaction between _setjmp and C++ object destruction is non-portable
#endif
volatile int result = setjmp(test_runner::_failure);
volatile int result = setjmp(test_runner::_failure_buffer);
#ifdef _MSC_VER
# pragma warning(pop)
@ -85,13 +78,17 @@ static bool run_test(test_runner* test)
if (result)
{
printf("Test %s failed: %s\n", test->_name, (const char*)(intptr_t)result);
printf("Test %s failed: %s\n", test->_name, test_runner::_failure_message);
return false;
}
test->run();
if (g_memory_total_size != 0) longjmp(test_runner::_failure, (int)(intptr_t)"Memory leaks found");
if (g_memory_total_size != 0)
{
printf("Test %s failed: memory leaks found (%u bytes)\n", test->_name, (unsigned int)g_memory_total_size);
return false;
}
return true;
#ifndef PUGIXML_NO_EXCEPTIONS

134
tests/test.cpp Normal file
View file

@ -0,0 +1,134 @@
#include "test.hpp"
#include "writer_string.hpp"
#include <math.h>
#include <float.h>
bool test_string_equal(const pugi::char_t* lhs, const pugi::char_t* rhs)
{
return (!lhs || !rhs) ? lhs == rhs : pugi::impl::strequal(lhs, rhs);
}
bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const pugi::char_t* indent, unsigned int flags)
{
xml_writer_string writer;
node.print(writer, indent, flags, get_native_encoding());
return writer.as_string() == contents;
}
#ifndef PUGIXML_NO_XPATH
bool test_xpath_string(const pugi::xml_node& node, const pugi::char_t* query, const pugi::char_t* expected)
{
pugi::xpath_query q(query);
return q.evaluate_string(node) == expected;
}
bool test_xpath_boolean(const pugi::xml_node& node, const pugi::char_t* query, bool expected)
{
pugi::xpath_query q(query);
return q.evaluate_boolean(node) == expected;
}
#include <stdio.h>
bool test_xpath_number(const pugi::xml_node& node, const pugi::char_t* query, double expected)
{
pugi::xpath_query q(query);
double value = q.evaluate_number(node);
double absolute_error = fabs(value - expected);
const double tolerance = 1e-15f;
return absolute_error < tolerance || absolute_error < fabs(expected) * tolerance;
}
bool test_xpath_number_nan(const pugi::xml_node& node, const pugi::char_t* query)
{
pugi::xpath_query q(query);
double r = q.evaluate_number(node);
#if defined(_MSC_VER) || defined(__BORLANDC__)
return _isnan(r) != 0;
#else
return r != r;
#endif
}
bool test_xpath_fail_compile(const pugi::char_t* query)
{
try
{
pugi::xpath_query q(query);
return false;
}
catch (const pugi::xpath_exception&)
{
return true;
}
}
void xpath_node_set_tester::check(bool condition)
{
if (!condition)
{
test_runner::_failure_message = message;
longjmp(test_runner::_failure_buffer, 1);
}
}
xpath_node_set_tester::xpath_node_set_tester(const pugi::xml_node& node, const pugi::char_t* query, const char* message): last(0), message(message)
{
pugi::xpath_query q(query);
result = q.evaluate_node_set(node);
}
xpath_node_set_tester::xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message): last(0), message(message)
{
result = set;
}
xpath_node_set_tester::~xpath_node_set_tester()
{
// check that we processed everything
check(last == result.size());
}
xpath_node_set_tester& xpath_node_set_tester::operator%(unsigned int expected)
{
// check element count
check(last < result.size());
// check document order
pugi::xpath_node node = result.begin()[last];
unsigned int order = node.attribute() ? node.attribute().document_order() : node.node().document_order();
check(order == expected);
// continue to the next element
last++;
return *this;
}
#endif
bool is_little_endian()
{
unsigned int ui = 1;
return *reinterpret_cast<char*>(&ui) == 1;
}
pugi::encoding_t get_native_encoding()
{
#ifdef PUGIXML_WCHAR_MODE
return pugi::encoding_wchar;
#else
return pugi::encoding_utf8;
#endif
}

View file

@ -3,21 +3,8 @@
#include "../src/pugixml.hpp"
#if (defined(_MSC_VER) && _MSC_VER==1200) || defined(__DMC__)
typedef int intptr_t;
#endif
#include <string.h>
#include <math.h>
#include <float.h>
#include <setjmp.h>
#if defined(__MWERKS__) || defined(__BORLANDC__)
#include <stdint.h> // intptr_t
#endif
#include <string>
struct test_runner
{
test_runner(const char* name)
@ -36,84 +23,25 @@ struct test_runner
static test_runner* _tests;
static size_t _memory_fail_threshold;
static jmp_buf _failure;
static jmp_buf _failure_buffer;
static const char* _failure_message;
};
inline bool test_string_equal(const char* lhs, const char* rhs)
{
return (!lhs || !rhs) ? lhs == rhs : strcmp(lhs, rhs) == 0;
}
bool test_string_equal(const pugi::char_t* lhs, const pugi::char_t* rhs);
template <typename Node> inline bool test_node_name_value(const Node& node, const char* name, const char* value)
template <typename Node> inline bool test_node_name_value(const Node& node, const pugi::char_t* name, const pugi::char_t* value)
{
return test_string_equal(node.name(), name) && test_string_equal(node.value(), value);
}
struct xml_writer_string: public pugi::xml_writer
{
std::string result;
virtual void write(const void* data, size_t size)
{
result += std::string(static_cast<const char*>(data), size);
}
};
inline bool test_node(const pugi::xml_node& node, const char* contents, const char* indent, unsigned int flags)
{
xml_writer_string writer;
node.print(writer, indent, flags);
return writer.result == contents;
}
bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const pugi::char_t* indent, unsigned int flags);
#ifndef PUGIXML_NO_XPATH
inline bool test_xpath_string(const pugi::xml_node& node, const char* query, const char* expected)
{
pugi::xpath_query q(query);
return q.evaluate_string(node) == expected;
}
inline bool test_xpath_boolean(const pugi::xml_node& node, const char* query, bool expected)
{
pugi::xpath_query q(query);
return q.evaluate_boolean(node) == expected;
}
inline bool test_xpath_number(const pugi::xml_node& node, const char* query, double expected)
{
pugi::xpath_query q(query);
return fabs(q.evaluate_number(node) - expected) < 1e-16f;
}
inline bool test_xpath_number_nan(const pugi::xml_node& node, const char* query)
{
pugi::xpath_query q(query);
double r = q.evaluate_number(node);
#if defined(_MSC_VER) || defined(__BORLANDC__)
return _isnan(r) != 0;
#else
return r != r;
#endif
}
inline bool test_xpath_fail_compile(const char* query)
{
try
{
pugi::xpath_query q(query);
return false;
}
catch (const pugi::xpath_exception&)
{
return true;
}
}
bool test_xpath_string(const pugi::xml_node& node, const pugi::char_t* query, const pugi::char_t* expected);
bool test_xpath_boolean(const pugi::xml_node& node, const pugi::char_t* query, bool expected);
bool test_xpath_number(const pugi::xml_node& node, const pugi::char_t* query, double expected);
bool test_xpath_number_nan(const pugi::xml_node& node, const pugi::char_t* query);
bool test_xpath_fail_compile(const pugi::char_t* query);
struct xpath_node_set_tester
{
@ -121,44 +49,13 @@ struct xpath_node_set_tester
unsigned int last;
const char* message;
void check(bool condition)
{
if (!condition) longjmp(test_runner::_failure, (int)(intptr_t)message);
}
void check(bool condition);
xpath_node_set_tester(const pugi::xml_node& node, const char* query, const char* message): last(0), message(message)
{
pugi::xpath_query q(query);
result = q.evaluate_node_set(node);
}
xpath_node_set_tester(const pugi::xml_node& node, const pugi::char_t* query, const char* message);
xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message);
~xpath_node_set_tester();
xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message): last(0), message(message)
{
result = set;
}
~xpath_node_set_tester()
{
// check that we processed everything
check(last == result.size());
}
xpath_node_set_tester& operator%(unsigned int expected)
{
// check element count
check(last < result.size());
// check document order
pugi::xpath_node node = result.begin()[last];
unsigned int order = node.attribute() ? node.attribute().document_order() : node.node().document_order();
check(order == expected);
// continue to the next element
last++;
return *this;
}
xpath_node_set_tester& operator%(unsigned int expected);
};
#endif
@ -191,7 +88,7 @@ struct dummy_fixture {};
\
test_fixture_##name() \
{ \
CHECK(doc.load(xml, flags)); \
CHECK(doc.load(PUGIXML_TEXT(xml), flags)); \
} \
\
private: \
@ -205,28 +102,42 @@ struct dummy_fixture {};
#define CHECK_JOIN(text, file, line) text file #line
#define CHECK_JOIN2(text, file, line) CHECK_JOIN(text, file, line)
#define CHECK_TEXT(condition, text) if (condition) ; else longjmp(test_runner::_failure, (int)(intptr_t)(CHECK_JOIN2(text, " at "__FILE__ ":", __LINE__)))
#define CHECK_TEXT(condition, text) if (condition) ; else test_runner::_failure_message = CHECK_JOIN2(text, " at "__FILE__ ":", __LINE__), longjmp(test_runner::_failure_buffer, 1)
#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__)
# define STR(value) "??" // MSVC 6.0 and CodeWarrior have troubles stringizing stuff with strings w/escaping inside
# define STRINGIZE(value) "??" // MSVC 6.0 and CodeWarrior have troubles stringizing stuff with strings w/escaping inside
#else
# define STR(value) #value
# define STRINGIZE(value) #value
#endif
#define CHECK(condition) CHECK_TEXT(condition, STR(condition) " is false")
#define CHECK_STRING(value, expected) CHECK_TEXT(test_string_equal(value, expected), STR(value) " is not equal to " STR(expected))
#define CHECK_DOUBLE(value, expected) CHECK_TEXT(fabs(value - expected) < 1e-6, STR(value) " is not equal to " STR(expected))
#define CHECK_NAME_VALUE(node, name, value) CHECK_TEXT(test_node_name_value(node, name, value), STR(node) " name/value do not match " STR(name) " and " STR(value))
#define CHECK_NODE_EX(node, expected, indent, flags) CHECK_TEXT(test_node(node, expected, indent, flags), STR(node) " contents does not match " STR(expected))
#define CHECK_NODE(node, expected) CHECK_NODE_EX(node, expected, "", pugi::format_raw)
#define CHECK(condition) CHECK_TEXT(condition, STRINGIZE(condition) " is false")
#define CHECK_STRING(value, expected) CHECK_TEXT(test_string_equal(value, expected), STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_DOUBLE(value, expected) CHECK_TEXT((value > expected ? value - expected : expected - value) < 1e-6, STRINGIZE(value) " is not equal to " STRINGIZE(expected))
#define CHECK_NAME_VALUE(node, name, value) CHECK_TEXT(test_node_name_value(node, name, value), STRINGIZE(node) " name/value do not match " STRINGIZE(name) " and " STRINGIZE(value))
#define CHECK_NODE_EX(node, expected, indent, flags) CHECK_TEXT(test_node(node, expected, indent, flags), STRINGIZE(node) " contents does not match " STRINGIZE(expected))
#define CHECK_NODE(node, expected) CHECK_NODE_EX(node, expected, PUGIXML_TEXT(""), pugi::format_raw)
#ifndef PUGIXML_NO_XPATH
#define CHECK_XPATH_STRING(node, query, expected) CHECK_TEXT(test_xpath_string(node, query, expected), STR(query) " does not evaluate to " STR(expected) " in context " STR(node))
#define CHECK_XPATH_BOOLEAN(node, query, expected) CHECK_TEXT(test_xpath_boolean(node, query, expected), STR(query) " does not evaluate to " STR(expected) " in context " STR(node))
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_TEXT(test_xpath_number(node, query, expected), STR(query) " does not evaluate to " STR(expected) " in context " STR(node))
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_TEXT(test_xpath_number_nan(node, query), STR(query) " does not evaluate to NaN in context " STR(node))
#define CHECK_XPATH_FAIL(query) CHECK_TEXT(test_xpath_fail_compile(query), STR(query) " should not compile")
#define CHECK_XPATH_NODESET(node, query) xpath_node_set_tester(node, query, CHECK_JOIN2(STR(query) " does not evaluate to expected set in context " STR(node), " at "__FILE__ ":", __LINE__))
#define CHECK_XPATH_STRING(node, query, expected) CHECK_TEXT(test_xpath_string(node, query, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_BOOLEAN(node, query, expected) CHECK_TEXT(test_xpath_boolean(node, query, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_TEXT(test_xpath_number(node, query, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_TEXT(test_xpath_number_nan(node, query), STRINGIZE(query) " does not evaluate to NaN in context " STRINGIZE(node))
#define CHECK_XPATH_FAIL(query) CHECK_TEXT(test_xpath_fail_compile(query), STRINGIZE(query) " should not compile")
#define CHECK_XPATH_NODESET(node, query) xpath_node_set_tester(node, query, CHECK_JOIN2(STRINGIZE(query) " does not evaluate to expected set in context " STRINGIZE(node), " at "__FILE__ ":", __LINE__))
#endif
#define STR(text) PUGIXML_TEXT(text)
#ifdef __DMC__
#define U_LITERALS // DMC does not understand \x01234 (it parses first three digits), but understands \u01234
#endif
inline wchar_t wchar_cast(unsigned int value)
{
return static_cast<wchar_t>(value); // to avoid C4310 on MSVC
}
bool is_little_endian();
pugi::encoding_t get_native_encoding();
#endif

View file

@ -1,10 +1,16 @@
#include <string.h> // because Borland's STL is braindead, we have to include <string.h> _before_ <string> in order to get memcpy
#include "common.hpp"
#include "writer_string.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string>
#ifdef _MSC_VER
#pragma warning(disable: 4996)
@ -13,8 +19,8 @@
TEST(document_create)
{
pugi::xml_document doc;
doc.append_child().set_name("node");
CHECK_NODE(doc, "<node />");
doc.append_child().set_name(STR("node"));
CHECK_NODE(doc, STR("<node />"));
}
#ifndef PUGIXML_NO_STL
@ -24,7 +30,29 @@ TEST(document_load_stream)
std::istringstream iss("<node/>");
CHECK(doc.load(iss));
CHECK_NODE(doc, "<node />");
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_load_stream_offset)
{
pugi::xml_document doc;
std::istringstream iss("<foobar> <node/>");
std::string s;
iss >> s;
CHECK(doc.load(iss));
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_load_stream_text)
{
pugi::xml_document doc;
std::ifstream iss("tests/data/multiline.xml");
CHECK(doc.load(iss));
CHECK_NODE(doc, STR("<node1 /><node2 /><node3 />"));
}
TEST(document_load_stream_error)
@ -39,21 +67,27 @@ TEST(document_load_stream_error)
CHECK(doc.load(fs2).status == status_io_error);
#endif
std::ifstream fs3("nul");
CHECK(doc.load(fs3).status == status_io_error);
test_runner::_memory_fail_threshold = 1;
std::istringstream iss("<node/>");
CHECK(doc.load(iss).status == status_out_of_memory);
}
TEST(document_load_stream_wide)
{
pugi::xml_document doc;
std::basic_istringstream<wchar_t> iss(L"<node/>");
CHECK(doc.load(iss));
CHECK_NODE(doc, STR("<node />"));
}
#endif
TEST(document_load_string)
{
pugi::xml_document doc;
CHECK(doc.load("<node/>"));
CHECK_NODE(doc, "<node />");
CHECK(doc.load(STR("<node/>")));
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_load_file)
@ -61,7 +95,15 @@ TEST(document_load_file)
pugi::xml_document doc;
CHECK(doc.load_file("tests/data/small.xml"));
CHECK_NODE(doc, "<node />");
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_load_file_empty)
{
pugi::xml_document doc;
CHECK(doc.load_file("tests/data/empty.xml"));
CHECK(!doc.first_child());
}
TEST(document_load_file_large)
@ -70,10 +112,10 @@ TEST(document_load_file_large)
CHECK(doc.load_file("tests/data/large.xml"));
std::string str;
str += "<node>";
for (int i = 0; i < 10000; ++i) str += "<node />";
str += "</node>";
std::basic_string<pugi::char_t> str;
str += STR("<node>");
for (int i = 0; i < 10000; ++i) str += STR("<node />");
str += STR("</node>");
CHECK_NODE(doc, str.c_str());
}
@ -84,14 +126,10 @@ TEST(document_load_file_error)
CHECK(doc.load_file("filedoesnotexist").status == status_file_not_found);
#ifdef __linux
CHECK(doc.load_file("/dev/null").status == status_io_error);
#else
#ifdef _WIN32
#ifndef __DMC__ // Digital Mars CRT does not like 'con' pseudo-file
CHECK(doc.load_file("con").status == status_io_error);
#endif
CHECK(doc.load_file("nul").status == status_io_error);
#endif
test_runner::_memory_fail_threshold = 1;
@ -102,27 +140,57 @@ TEST_XML(document_save, "<node/>")
{
xml_writer_string writer;
doc.save(writer, "", pugi::format_no_declaration | pugi::format_raw);
doc.save(writer, STR(""), pugi::format_no_declaration | pugi::format_raw, get_native_encoding());
CHECK(writer.result == "<node />");
CHECK(writer.as_string() == STR("<node />"));
}
TEST_XML(document_save_bom, "<node/>")
#ifndef PUGIXML_NO_STL
TEST_XML(document_save_stream, "<node/>")
{
xml_writer_string writer;
std::ostringstream oss;
doc.save(writer, "", pugi::format_no_declaration | pugi::format_raw | pugi::format_write_bom_utf8);
doc.save(oss, STR(""), pugi::format_no_declaration | pugi::format_raw);
CHECK(writer.result == "\xef\xbb\xbf<node />");
CHECK(oss.str() == "<node />");
}
TEST_XML(document_save_stream_wide, "<node/>")
{
std::basic_ostringstream<wchar_t> oss;
doc.save(oss, STR(""), pugi::format_no_declaration | pugi::format_raw);
CHECK(oss.str() == L"<node />");
}
#endif
TEST_XML(document_save_bom, "<n/>")
{
unsigned int flags = format_no_declaration | format_raw | format_write_bom;
// specific encodings
CHECK(test_save_narrow(doc, flags, encoding_utf8, "\xef\xbb\xbf<n />", 8));
CHECK(test_save_narrow(doc, flags, encoding_utf16_be, "\xfe\xff\x00<\x00n\x00 \x00/\x00>", 12));
CHECK(test_save_narrow(doc, flags, encoding_utf16_le, "\xff\xfe<\x00n\x00 \x00/\x00>\x00", 12));
CHECK(test_save_narrow(doc, flags, encoding_utf32_be, "\x00\x00\xfe\xff\x00\x00\x00<\x00\x00\x00n\x00\x00\x00 \x00\x00\x00/\x00\x00\x00>", 24));
CHECK(test_save_narrow(doc, flags, encoding_utf32_le, "\xff\xfe\x00\x00<\x00\x00\x00n\x00\x00\x00 \x00\x00\x00/\x00\x00\x00>\x00\x00\x00", 24));
// encodings synonyms
CHECK(save_narrow(doc, flags, encoding_utf16) == save_narrow(doc, flags, (is_little_endian() ? encoding_utf16_le : encoding_utf16_be)));
CHECK(save_narrow(doc, flags, encoding_utf32) == save_narrow(doc, flags, (is_little_endian() ? encoding_utf32_le : encoding_utf32_be)));
size_t wcharsize = sizeof(wchar_t);
CHECK(save_narrow(doc, flags, encoding_wchar) == save_narrow(doc, flags, (wcharsize == 2 ? encoding_utf16 : encoding_utf32)));
}
TEST_XML(document_save_declaration, "<node/>")
{
xml_writer_string writer;
doc.save(writer);
doc.save(writer, STR(""), pugi::format_default, get_native_encoding());
CHECK(writer.result == "<?xml version=\"1.0\"?>\n<node />\n");
CHECK(writer.as_string() == STR("<?xml version=\"1.0\"?>\n<node />\n"));
}
TEST_XML(document_save_file, "<node/>")
@ -130,34 +198,46 @@ TEST_XML(document_save_file, "<node/>")
CHECK(doc.save_file("tests/data/output.xml"));
CHECK(doc.load_file("tests/data/output.xml", pugi::parse_default | pugi::parse_declaration));
CHECK_NODE(doc, "<?xml version=\"1.0\"?><node />");
CHECK_NODE(doc, STR("<?xml version=\"1.0\"?><node />"));
unlink("tests/data/output.xml");
}
TEST(document_parse)
TEST(document_load_buffer)
{
char text[] = "<node/>";
const pugi::char_t text[] = STR("<?xml?><node/>");
pugi::xml_document doc;
CHECK(doc.parse(text));
CHECK_NODE(doc, "<node />");
CHECK(doc.load_buffer(text, sizeof(text)));
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_parse_transfer_ownership)
TEST(document_load_buffer_inplace)
{
pugi::char_t text[] = STR("<?xml?><node/>");
pugi::xml_document doc;
CHECK(doc.load_buffer_inplace(text, sizeof(text)));
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_load_buffer_inplace_own)
{
allocation_function alloc = get_memory_allocation_function();
char* text = static_cast<char*>(alloc(strlen("<node/>") + 1));
size_t size = strlen("<?xml?><node/>") * sizeof(pugi::char_t);
pugi::char_t* text = static_cast<pugi::char_t*>(alloc(size));
CHECK(text);
strcpy(text, "<node/>");
memcpy(text, STR("<?xml?><node/>"), size);
pugi::xml_document doc;
CHECK(doc.parse(transfer_ownership_tag(), text));
CHECK_NODE(doc, "<node />");
CHECK(doc.load_buffer_inplace_own(text, size));
CHECK_NODE(doc, STR("<node />"));
}
TEST(document_parse_result_bool)
@ -189,3 +269,306 @@ TEST(document_parse_result_description)
CHECK(result.description()[0] != 0);
}
}
TEST(document_load_fail)
{
xml_document doc;
CHECK(!doc.load(STR("<foo><bar/>")));
CHECK(doc.child(STR("foo")).child(STR("bar")));
}
inline void check_utftest_document(const xml_document& doc)
{
// ascii text
CHECK_STRING(doc.last_child().first_child().name(), STR("English"));
// check that we have parsed some non-ascii text
CHECK((unsigned)doc.last_child().last_child().name()[0] >= 0x80);
// check magic string
const pugi::char_t* v = doc.last_child().child(STR("Heavy")).previous_sibling().child_value();
#ifdef PUGIXML_WCHAR_MODE
CHECK(v[0] == 0x4e16 && v[1] == 0x754c && v[2] == 0x6709 && v[3] == 0x5f88 && v[4] == 0x591a && v[5] == 0x8bed && v[6] == 0x8a00);
// last character is a surrogate pair
unsigned int v7 = v[7];
size_t wcharsize = sizeof(wchar_t);
CHECK(wcharsize == 2 ? (v[7] == 0xd852 && v[8] == 0xdf62) : (v7 == 0x24b62));
#else
// unicode string
CHECK_STRING(v, "\xe4\xb8\x96\xe7\x95\x8c\xe6\x9c\x89\xe5\xbe\x88\xe5\xa4\x9a\xe8\xaf\xad\xe8\xa8\x80\xf0\xa4\xad\xa2");
#endif
}
TEST(document_load_file_convert_auto)
{
const char* files[] =
{
"tests/data/utftest_utf16_be.xml",
"tests/data/utftest_utf16_be_bom.xml",
"tests/data/utftest_utf16_be_nodecl.xml",
"tests/data/utftest_utf16_le.xml",
"tests/data/utftest_utf16_le_bom.xml",
"tests/data/utftest_utf16_le_nodecl.xml",
"tests/data/utftest_utf32_be.xml",
"tests/data/utftest_utf32_be_bom.xml",
"tests/data/utftest_utf32_be_nodecl.xml",
"tests/data/utftest_utf32_le.xml",
"tests/data/utftest_utf32_le_bom.xml",
"tests/data/utftest_utf32_le_nodecl.xml",
"tests/data/utftest_utf8.xml",
"tests/data/utftest_utf8_bom.xml",
"tests/data/utftest_utf8_nodecl.xml"
};
encoding_t encodings[] =
{
encoding_utf16_be, encoding_utf16_be, encoding_utf16_be,
encoding_utf16_le, encoding_utf16_le, encoding_utf16_le,
encoding_utf32_be, encoding_utf32_be, encoding_utf32_be,
encoding_utf32_le, encoding_utf32_le, encoding_utf32_le,
encoding_utf8, encoding_utf8, encoding_utf8
};
for (unsigned int i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
{
xml_document doc;
xml_parse_result res = doc.load_file(files[i]);
CHECK(res);
CHECK(res.encoding == encodings[i]);
check_utftest_document(doc);
}
}
TEST(document_load_file_convert_specific)
{
const char* files[] =
{
"tests/data/utftest_utf16_be.xml",
"tests/data/utftest_utf16_be_bom.xml",
"tests/data/utftest_utf16_be_nodecl.xml",
"tests/data/utftest_utf16_le.xml",
"tests/data/utftest_utf16_le_bom.xml",
"tests/data/utftest_utf16_le_nodecl.xml",
"tests/data/utftest_utf32_be.xml",
"tests/data/utftest_utf32_be_bom.xml",
"tests/data/utftest_utf32_be_nodecl.xml",
"tests/data/utftest_utf32_le.xml",
"tests/data/utftest_utf32_le_bom.xml",
"tests/data/utftest_utf32_le_nodecl.xml",
"tests/data/utftest_utf8.xml",
"tests/data/utftest_utf8_bom.xml",
"tests/data/utftest_utf8_nodecl.xml"
};
encoding_t encodings[] =
{
encoding_utf16_be, encoding_utf16_be, encoding_utf16_be,
encoding_utf16_le, encoding_utf16_le, encoding_utf16_le,
encoding_utf32_be, encoding_utf32_be, encoding_utf32_be,
encoding_utf32_le, encoding_utf32_le, encoding_utf32_le,
encoding_utf8, encoding_utf8, encoding_utf8
};
for (unsigned int i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
{
for (unsigned int j = 0; j < sizeof(files) / sizeof(files[0]); ++j)
{
encoding_t encoding = encodings[j];
xml_document doc;
xml_parse_result res = doc.load_file(files[i], parse_default, encoding);
if (encoding == encodings[i])
{
CHECK(res);
CHECK(res.encoding == encoding);
check_utftest_document(doc);
}
else
{
// should not get past first tag
CHECK(!doc.first_child());
}
}
}
}
TEST(document_load_file_convert_native_endianness)
{
const char* files[2][6] =
{
{
"tests/data/utftest_utf16_be.xml",
"tests/data/utftest_utf16_be_bom.xml",
"tests/data/utftest_utf16_be_nodecl.xml",
"tests/data/utftest_utf32_be.xml",
"tests/data/utftest_utf32_be_bom.xml",
"tests/data/utftest_utf32_be_nodecl.xml",
},
{
"tests/data/utftest_utf16_le.xml",
"tests/data/utftest_utf16_le_bom.xml",
"tests/data/utftest_utf16_le_nodecl.xml",
"tests/data/utftest_utf32_le.xml",
"tests/data/utftest_utf32_le_bom.xml",
"tests/data/utftest_utf32_le_nodecl.xml",
}
};
encoding_t encodings[] =
{
encoding_utf16, encoding_utf16, encoding_utf16,
encoding_utf32, encoding_utf32, encoding_utf32
};
for (unsigned int i = 0; i < sizeof(files[0]) / sizeof(files[0][0]); ++i)
{
const char* right_file = files[is_little_endian()][i];
const char* wrong_file = files[!is_little_endian()][i];
for (unsigned int j = 0; j < sizeof(encodings) / sizeof(encodings[0]); ++j)
{
encoding_t encoding = encodings[j];
// check file with right endianness
{
xml_document doc;
xml_parse_result res = doc.load_file(right_file, parse_default, encoding);
if (encoding == encodings[i])
{
CHECK(res);
check_utftest_document(doc);
}
else
{
// should not get past first tag
CHECK(!doc.first_child());
}
}
// check file with wrong endianness
{
xml_document doc;
doc.load_file(wrong_file, parse_default, encoding);
CHECK(!doc.first_child());
}
}
}
}
static bool load_file_in_memory(const char* path, char*& data, size_t& size)
{
FILE* file = fopen(path, "rb");
if (!file) return false;
fseek(file, 0, SEEK_END);
size = (size_t)ftell(file);
fseek(file, 0, SEEK_SET);
data = new char[size];
CHECK(fread(data, 1, size, file) == size);
fclose(file);
return true;
}
TEST(document_contents_preserve)
{
struct file_t
{
const char* path;
encoding_t encoding;
char* data;
size_t size;
};
file_t files[] =
{
{"tests/data/utftest_utf16_be_clean.xml", encoding_utf16_be, 0, 0},
{"tests/data/utftest_utf16_le_clean.xml", encoding_utf16_le, 0, 0},
{"tests/data/utftest_utf32_be_clean.xml", encoding_utf32_be, 0, 0},
{"tests/data/utftest_utf32_le_clean.xml", encoding_utf32_le, 0, 0},
{"tests/data/utftest_utf8_clean.xml", encoding_utf8, 0, 0}
};
// load files in memory
for (unsigned int i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
{
CHECK(load_file_in_memory(files[i].path, files[i].data, files[i].size));
}
// convert each file to each format and compare bitwise
for (unsigned int src = 0; src < sizeof(files) / sizeof(files[0]); ++src)
{
for (unsigned int dst = 0; dst < sizeof(files) / sizeof(files[0]); ++dst)
{
// parse into document (preserve comments, declaration and whitespace pcdata)
xml_document doc;
CHECK(doc.load_buffer(files[src].data, files[src].size, parse_default | parse_ws_pcdata | parse_declaration | parse_comments));
// compare saved document with the original (raw formatting, without extra declaration, write bom if it was in original file)
CHECK(test_save_narrow(doc, format_raw | format_no_declaration | format_write_bom, files[dst].encoding, files[dst].data, files[dst].size));
}
}
// cleanup
for (unsigned int j = 0; j < sizeof(files) / sizeof(files[0]); ++j)
{
delete[] files[j].data;
}
}
static bool test_parse_fail(const void* buffer, size_t size, encoding_t encoding = encoding_utf8)
{
// copy buffer to heap (to enable out-of-bounds checks)
void* temp = malloc(size);
memcpy(temp, buffer, size);
// check that this parses without buffer overflows (yielding an error)
xml_document doc;
bool result = doc.load_buffer_inplace(temp, size, parse_default, encoding);
free(temp);
return !result;
}
TEST(document_convert_invalid_utf8)
{
// invalid 1-byte input
CHECK(test_parse_fail("<\xb0", 2));
// invalid 2-byte input
CHECK(test_parse_fail("<\xc0", 2));
CHECK(test_parse_fail("<\xd0", 2));
// invalid 3-byte input
CHECK(test_parse_fail("<\xe2\x80", 3));
CHECK(test_parse_fail("<\xe2", 2));
// invalid 4-byte input
CHECK(test_parse_fail("<\xf2\x97\x98", 4));
CHECK(test_parse_fail("<\xf2\x97", 3));
CHECK(test_parse_fail("<\xf2", 2));
// invalid 5-byte input
CHECK(test_parse_fail("<\xf8", 2));
}
TEST(document_convert_invalid_utf16)
{
// check non-terminated degenerate handling
CHECK(test_parse_fail("\x00<\xda\x1d", 4, encoding_utf16_be));
CHECK(test_parse_fail("<\x00\x1d\xda", 4, encoding_utf16_le));
// check incorrect leading code
CHECK(test_parse_fail("\x00<\xde\x24", 4, encoding_utf16_be));
CHECK(test_parse_fail("<\x00\x24\xde", 4, encoding_utf16_le));
}

View file

@ -1,158 +1,170 @@
#include "common.hpp"
#include <float.h>
TEST_XML(dom_attr_assign, "<node attr1='' attr2='' attr3='' attr4='' attr5=''/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
node.attribute("attr1") = "v1";
xml_attribute() = "v1";
node.attribute(STR("attr1")) = STR("v1");
xml_attribute() = STR("v1");
node.attribute("attr2") = -2147483647 - 1;
node.attribute(STR("attr2")) = -2147483647 - 1;
xml_attribute() = -2147483647 - 1;
node.attribute("attr3") = 2147483647u;
node.attribute(STR("attr3")) = 2147483647u;
xml_attribute() = 2147483647;
node.attribute("attr4") = 0.5;
node.attribute(STR("attr4")) = 0.5;
xml_attribute() = 0.5;
node.attribute("attr5") = true;
node.attribute(STR("attr5")) = true;
xml_attribute() = true;
CHECK_NODE(node, "<node attr1=\"v1\" attr2=\"-2147483648\" attr3=\"2147483647\" attr4=\"0.5\" attr5=\"true\" />");
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483648\" attr3=\"2147483647\" attr4=\"0.5\" attr5=\"true\" />"));
}
TEST_XML(dom_attr_set_value, "<node attr1='' attr2='' attr3='' attr4='' attr5=''/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.attribute("attr1").set_value("v1"));
CHECK(!xml_attribute().set_value("v1"));
CHECK(node.attribute(STR("attr1")).set_value(STR("v1")));
CHECK(!xml_attribute().set_value(STR("v1")));
CHECK(node.attribute("attr2").set_value(-2147483647 - 1));
CHECK(node.attribute(STR("attr2")).set_value(-2147483647 - 1));
CHECK(!xml_attribute().set_value(-2147483647 - 1));
CHECK(node.attribute("attr3").set_value(2147483647u));
CHECK(node.attribute(STR("attr3")).set_value(2147483647u));
CHECK(!xml_attribute().set_value(2147483647));
CHECK(node.attribute("attr4").set_value(0.5));
CHECK(node.attribute(STR("attr4")).set_value(0.5));
CHECK(!xml_attribute().set_value(0.5));
CHECK(node.attribute("attr5").set_value(true));
CHECK(node.attribute(STR("attr5")).set_value(true));
CHECK(!xml_attribute().set_value(true));
CHECK_NODE(node, "<node attr1=\"v1\" attr2=\"-2147483648\" attr3=\"2147483647\" attr4=\"0.5\" attr5=\"true\" />");
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483648\" attr3=\"2147483647\" attr4=\"0.5\" attr5=\"true\" />"));
}
TEST_XML(dom_node_set_name, "<node>text</node>")
{
CHECK(doc.child("node").set_name("n"));
CHECK(!doc.child("node").first_child().set_name("n"));
CHECK(!xml_node().set_name("n"));
CHECK(doc.child(STR("node")).set_name(STR("n")));
CHECK(!doc.child(STR("node")).first_child().set_name(STR("n")));
CHECK(!xml_node().set_name(STR("n")));
CHECK_NODE(doc, "<n>text</n>");
CHECK_NODE(doc, STR("<n>text</n>"));
}
TEST_XML(dom_node_set_value, "<node>text</node>")
{
CHECK(doc.child("node").first_child().set_value("no text"));
CHECK(!doc.child("node").set_value("no text"));
CHECK(!xml_node().set_value("no text"));
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text")));
CHECK(!doc.child(STR("node")).set_value(STR("no text")));
CHECK(!xml_node().set_value(STR("no text")));
CHECK_NODE(doc, "<node>no text</node>");
CHECK_NODE(doc, STR("<node>no text</node>"));
}
TEST_XML(dom_node_set_value_allocated, "<node>text</node>")
{
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text")));
CHECK(!doc.child(STR("node")).set_value(STR("no text")));
CHECK(!xml_node().set_value(STR("no text")));
CHECK(doc.child(STR("node")).first_child().set_value(STR("no text at all")));
CHECK_NODE(doc, STR("<node>no text at all</node>"));
}
TEST_XML(dom_node_append_attribute, "<node><child/></node>")
{
CHECK(xml_node().append_attribute("a") == xml_attribute());
CHECK(doc.append_attribute("a") == xml_attribute());
CHECK(xml_node().append_attribute(STR("a")) == xml_attribute());
CHECK(doc.append_attribute(STR("a")) == xml_attribute());
xml_attribute a1 = doc.child("node").append_attribute("a1");
xml_attribute a1 = doc.child(STR("node")).append_attribute(STR("a1"));
CHECK(a1);
a1 = "v1";
a1 = STR("v1");
xml_attribute a2 = doc.child("node").append_attribute("a2");
xml_attribute a2 = doc.child(STR("node")).append_attribute(STR("a2"));
CHECK(a2 && a1 != a2);
a2 = "v2";
a2 = STR("v2");
xml_attribute a3 = doc.child("node").child("child").append_attribute("a3");
xml_attribute a3 = doc.child(STR("node")).child(STR("child")).append_attribute(STR("a3"));
CHECK(a3 && a1 != a3 && a2 != a3);
a3 = "v3";
a3 = STR("v3");
CHECK_NODE(doc, "<node a1=\"v1\" a2=\"v2\"><child a3=\"v3\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\"><child a3=\"v3\" /></node>"));
}
TEST_XML(dom_node_insert_attribute_after, "<node a1='v1'><child a2='v2'/></node>")
{
CHECK(xml_node().insert_attribute_after("a", xml_attribute()) == xml_attribute());
CHECK(xml_node().insert_attribute_after(STR("a"), xml_attribute()) == xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
xml_attribute a1 = node.attribute("a1");
xml_attribute a2 = child.attribute("a2");
xml_attribute a1 = node.attribute(STR("a1"));
xml_attribute a2 = child.attribute(STR("a2"));
CHECK(node.insert_attribute_after("a", xml_attribute()) == xml_attribute());
CHECK(node.insert_attribute_after("a", a2) == xml_attribute());
CHECK(node.insert_attribute_after(STR("a"), xml_attribute()) == xml_attribute());
CHECK(node.insert_attribute_after(STR("a"), a2) == xml_attribute());
xml_attribute a3 = node.insert_attribute_after("a3", a1);
xml_attribute a3 = node.insert_attribute_after(STR("a3"), a1);
CHECK(a3 && a3 != a2 && a3 != a1);
a3 = "v3";
a3 = STR("v3");
xml_attribute a4 = node.insert_attribute_after("a4", a1);
xml_attribute a4 = node.insert_attribute_after(STR("a4"), a1);
CHECK(a4 && a4 != a3 && a4 != a2 && a4 != a1);
a4 = "v4";
a4 = STR("v4");
xml_attribute a5 = node.insert_attribute_after("a5", a3);
xml_attribute a5 = node.insert_attribute_after(STR("a5"), a3);
CHECK(a5 && a5 != a4 && a5 != a3 && a5 != a2 && a5 != a1);
a5 = "v5";
a5 = STR("v5");
CHECK(child.insert_attribute_after("a", a4) == xml_attribute());
CHECK(child.insert_attribute_after(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, "<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\"><child a2=\"v2\" /></node>"));
}
TEST_XML(dom_node_insert_attribute_before, "<node a1='v1'><child a2='v2'/></node>")
{
CHECK(xml_node().insert_attribute_before("a", xml_attribute()) == xml_attribute());
CHECK(xml_node().insert_attribute_before(STR("a"), xml_attribute()) == xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
xml_attribute a1 = node.attribute("a1");
xml_attribute a2 = child.attribute("a2");
xml_attribute a1 = node.attribute(STR("a1"));
xml_attribute a2 = child.attribute(STR("a2"));
CHECK(node.insert_attribute_before("a", xml_attribute()) == xml_attribute());
CHECK(node.insert_attribute_before("a", a2) == xml_attribute());
CHECK(node.insert_attribute_before(STR("a"), xml_attribute()) == xml_attribute());
CHECK(node.insert_attribute_before(STR("a"), a2) == xml_attribute());
xml_attribute a3 = node.insert_attribute_before("a3", a1);
xml_attribute a3 = node.insert_attribute_before(STR("a3"), a1);
CHECK(a3 && a3 != a2 && a3 != a1);
a3 = "v3";
a3 = STR("v3");
xml_attribute a4 = node.insert_attribute_before("a4", a1);
xml_attribute a4 = node.insert_attribute_before(STR("a4"), a1);
CHECK(a4 && a4 != a3 && a4 != a2 && a4 != a1);
a4 = "v4";
a4 = STR("v4");
xml_attribute a5 = node.insert_attribute_before("a5", a3);
xml_attribute a5 = node.insert_attribute_before(STR("a5"), a3);
CHECK(a5 && a5 != a4 && a5 != a3 && a5 != a2 && a5 != a1);
a5 = "v5";
a5 = STR("v5");
CHECK(child.insert_attribute_before("a", a4) == xml_attribute());
CHECK(child.insert_attribute_before(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, "<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a1=\"v1\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a1=\"v1\"><child a2=\"v2\" /></node>"));
}
TEST_XML(dom_node_append_copy_attribute, "<node a1='v1'><child a2='v2'/><child/></node>")
{
CHECK(xml_node().append_copy(xml_attribute()) == xml_attribute());
CHECK(xml_node().append_copy(doc.child("node").attribute("a1")) == xml_attribute());
CHECK(doc.append_copy(doc.child("node").attribute("a1")) == xml_attribute());
CHECK(xml_node().append_copy(doc.child(STR("node")).attribute(STR("a1"))) == xml_attribute());
CHECK(doc.append_copy(doc.child(STR("node")).attribute(STR("a1"))) == xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
xml_attribute a1 = node.attribute("a1");
xml_attribute a2 = child.attribute("a2");
xml_attribute a1 = node.attribute(STR("a1"));
xml_attribute a2 = child.attribute(STR("a2"));
xml_attribute a3 = node.append_copy(a1);
CHECK(a3 && a3 != a2 && a3 != a1);
@ -163,29 +175,29 @@ TEST_XML(dom_node_append_copy_attribute, "<node a1='v1'><child a2='v2'/><child/>
xml_attribute a5 = node.last_child().append_copy(a1);
CHECK(a5 && a5 != a4 && a5 != a3 && a5 != a2 && a5 != a1);
CHECK_NODE(doc, "<node a1=\"v1\" a1=\"v1\" a2=\"v2\"><child a2=\"v2\" /><child a1=\"v1\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a1=\"v1\" a2=\"v2\"><child a2=\"v2\" /><child a1=\"v1\" /></node>"));
a3.set_name("a3");
a3 = "v3";
a3.set_name(STR("a3"));
a3 = STR("v3");
a4.set_name("a4");
a4 = "v4";
a4.set_name(STR("a4"));
a4 = STR("v4");
a5.set_name("a5");
a5 = "v5";
a5.set_name(STR("a5"));
a5 = STR("v5");
CHECK_NODE(doc, "<node a1=\"v1\" a3=\"v3\" a4=\"v4\"><child a2=\"v2\" /><child a5=\"v5\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a3=\"v3\" a4=\"v4\"><child a2=\"v2\" /><child a5=\"v5\" /></node>"));
}
TEST_XML(dom_node_insert_copy_after_attribute, "<node a1='v1'><child a2='v2'/></node>")
{
CHECK(xml_node().insert_copy_after(xml_attribute(), xml_attribute()) == xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
xml_attribute a1 = node.attribute("a1");
xml_attribute a2 = child.attribute("a2");
xml_attribute a1 = node.attribute(STR("a1"));
xml_attribute a2 = child.attribute(STR("a2"));
CHECK(node.insert_copy_after(a1, xml_attribute()) == xml_attribute());
CHECK(node.insert_copy_after(xml_attribute(), a1) == xml_attribute());
@ -202,29 +214,29 @@ TEST_XML(dom_node_insert_copy_after_attribute, "<node a1='v1'><child a2='v2'/></
CHECK(child.insert_copy_after(a4, a4) == xml_attribute());
CHECK_NODE(doc, "<node a1=\"v1\" a2=\"v2\" a2=\"v2\" a1=\"v1\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\" a2=\"v2\" a1=\"v1\"><child a2=\"v2\" /></node>"));
a3.set_name("a3");
a3 = "v3";
a3.set_name(STR("a3"));
a3 = STR("v3");
a4.set_name("a4");
a4 = "v4";
a4.set_name(STR("a4"));
a4 = STR("v4");
a5.set_name("a5");
a5 = "v5";
a5.set_name(STR("a5"));
a5 = STR("v5");
CHECK_NODE(doc, "<node a1=\"v1\" a5=\"v5\" a4=\"v4\" a3=\"v3\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a5=\"v5\" a4=\"v4\" a3=\"v3\"><child a2=\"v2\" /></node>"));
}
TEST_XML(dom_node_insert_copy_before_attribute, "<node a1='v1'><child a2='v2'/></node>")
{
CHECK(xml_node().insert_copy_before(xml_attribute(), xml_attribute()) == xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
xml_attribute a1 = node.attribute("a1");
xml_attribute a2 = child.attribute("a2");
xml_attribute a1 = node.attribute(STR("a1"));
xml_attribute a2 = child.attribute(STR("a2"));
CHECK(node.insert_copy_before(a1, xml_attribute()) == xml_attribute());
CHECK(node.insert_copy_before(xml_attribute(), a1) == xml_attribute());
@ -241,243 +253,254 @@ TEST_XML(dom_node_insert_copy_before_attribute, "<node a1='v1'><child a2='v2'/><
CHECK(child.insert_copy_before(a4, a4) == xml_attribute());
CHECK_NODE(doc, "<node a1=\"v1\" a2=\"v2\" a2=\"v2\" a1=\"v1\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\" a2=\"v2\" a1=\"v1\"><child a2=\"v2\" /></node>"));
a3.set_name("a3");
a3 = "v3";
a3.set_name(STR("a3"));
a3 = STR("v3");
a4.set_name("a4");
a4 = "v4";
a4.set_name(STR("a4"));
a4 = STR("v4");
a5.set_name("a5");
a5 = "v5";
a5.set_name(STR("a5"));
a5 = STR("v5");
CHECK_NODE(doc, "<node a3=\"v3\" a4=\"v4\" a5=\"v5\" a1=\"v1\"><child a2=\"v2\" /></node>");
CHECK_NODE(doc, STR("<node a3=\"v3\" a4=\"v4\" a5=\"v5\" a1=\"v1\"><child a2=\"v2\" /></node>"));
}
TEST_XML(dom_node_remove_attribute, "<node a1='v1' a2='v2' a3='v3'><child a4='v4'/></node>")
{
xml_node().remove_attribute("a");
xml_node().remove_attribute(STR("a"));
xml_node().remove_attribute(xml_attribute());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
node.remove_attribute("a");
node.remove_attribute(STR("a"));
node.remove_attribute(xml_attribute());
node.remove_attribute(child.attribute("a4"));
node.remove_attribute(child.attribute(STR("a4")));
CHECK_NODE(doc, "<node a1=\"v1\" a2=\"v2\" a3=\"v3\"><child a4=\"v4\" /></node>");
CHECK_NODE(doc, STR("<node a1=\"v1\" a2=\"v2\" a3=\"v3\"><child a4=\"v4\" /></node>"));
node.remove_attribute("a1");
node.remove_attribute(node.attribute("a3"));
child.remove_attribute("a4");
node.remove_attribute(STR("a1"));
node.remove_attribute(node.attribute(STR("a3")));
child.remove_attribute(STR("a4"));
CHECK_NODE(doc, "<node a2=\"v2\"><child /></node>");
CHECK_NODE(doc, STR("<node a2=\"v2\"><child /></node>"));
}
TEST_XML(dom_node_append_child, "<node>foo<child/></node>")
{
CHECK(xml_node().append_child() == xml_node());
CHECK(doc.child("node").first_child().append_child() == xml_node());
CHECK(doc.child(STR("node")).first_child().append_child() == xml_node());
CHECK(doc.append_child(node_document) == xml_node());
CHECK(doc.append_child(node_null) == xml_node());
xml_node n1 = doc.child("node").append_child();
xml_node n1 = doc.child(STR("node")).append_child();
CHECK(n1);
CHECK(n1.set_name("n1"));
CHECK(n1.set_name(STR("n1")));
xml_node n2 = doc.child("node").append_child();
xml_node n2 = doc.child(STR("node")).append_child();
CHECK(n2 && n1 != n2);
CHECK(n2.set_name("n2"));
CHECK(n2.set_name(STR("n2")));
xml_node n3 = doc.child("node").child("child").append_child(node_pcdata);
xml_node n3 = doc.child(STR("node")).child(STR("child")).append_child(node_pcdata);
CHECK(n3 && n1 != n3 && n2 != n3);
CHECK(n3.set_value("n3"));
CHECK(n3.set_value(STR("n3")));
xml_node n4 = doc.append_child(node_comment);
CHECK(n4 && n1 != n4 && n2 != n4 && n3 != n4);
CHECK(n4.set_value("n4"));
CHECK(n4.set_value(STR("n4")));
CHECK_NODE(doc, "<node>foo<child>n3</child><n1 /><n2 /></node><!--n4-->");
CHECK_NODE(doc, STR("<node>foo<child>n3</child><n1 /><n2 /></node><!--n4-->"));
}
TEST_XML(dom_node_insert_child_after, "<node>foo<child/></node>")
{
CHECK(xml_node().insert_child_after(node_element, xml_node()) == xml_node());
CHECK(doc.child("node").first_child().insert_child_after(node_element, xml_node()) == xml_node());
CHECK(doc.child(STR("node")).first_child().insert_child_after(node_element, xml_node()) == xml_node());
CHECK(doc.insert_child_after(node_document, xml_node()) == xml_node());
CHECK(doc.insert_child_after(node_null, xml_node()) == xml_node());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
CHECK(node.insert_child_after(node_element, node) == xml_node());
CHECK(child.insert_child_after(node_element, node) == xml_node());
xml_node n1 = node.insert_child_after(node_element, child);
CHECK(n1 && n1 != node && n1 != child);
CHECK(n1.set_name("n1"));
CHECK(n1.set_name(STR("n1")));
xml_node n2 = node.insert_child_after(node_element, child);
CHECK(n2 && n2 != node && n2 != child && n2 != n1);
CHECK(n2.set_name("n2"));
CHECK(n2.set_name(STR("n2")));
xml_node n3 = node.insert_child_after(node_pcdata, n2);
CHECK(n3 && n3 != node && n3 != child && n3 != n1 && n3 != n2);
CHECK(n3.set_value("n3"));
CHECK(n3.set_value(STR("n3")));
xml_node n4 = node.insert_child_after(node_pi, node.first_child());
CHECK(n4 && n4 != node && n4 != child && n4 != n1 && n4 != n2 && n4 != n3);
CHECK(n4.set_name("n4"));
CHECK(n4.set_name(STR("n4")));
CHECK(child.insert_child_after(node_element, n3) == xml_node());
CHECK_NODE(doc, "<node>foo<?n4?><child /><n2 />n3<n1 /></node>");
CHECK_NODE(doc, STR("<node>foo<?n4?><child /><n2 />n3<n1 /></node>"));
}
TEST_XML(dom_node_insert_child_before, "<node>foo<child/></node>")
{
CHECK(xml_node().insert_child_before(node_element, xml_node()) == xml_node());
CHECK(doc.child("node").first_child().insert_child_before(node_element, xml_node()) == xml_node());
CHECK(doc.child(STR("node")).first_child().insert_child_before(node_element, xml_node()) == xml_node());
CHECK(doc.insert_child_before(node_document, xml_node()) == xml_node());
CHECK(doc.insert_child_before(node_null, xml_node()) == xml_node());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
CHECK(node.insert_child_before(node_element, node) == xml_node());
CHECK(child.insert_child_before(node_element, node) == xml_node());
xml_node n1 = node.insert_child_before(node_element, child);
CHECK(n1 && n1 != node && n1 != child);
CHECK(n1.set_name("n1"));
CHECK(n1.set_name(STR("n1")));
xml_node n2 = node.insert_child_before(node_element, child);
CHECK(n2 && n2 != node && n2 != child && n2 != n1);
CHECK(n2.set_name("n2"));
CHECK(n2.set_name(STR("n2")));
xml_node n3 = node.insert_child_before(node_pcdata, n2);
CHECK(n3 && n3 != node && n3 != child && n3 != n1 && n3 != n2);
CHECK(n3.set_value("n3"));
CHECK(n3.set_value(STR("n3")));
xml_node n4 = node.insert_child_before(node_pi, node.first_child());
CHECK(n4 && n4 != node && n4 != child && n4 != n1 && n4 != n2 && n4 != n3);
CHECK(n4.set_name("n4"));
CHECK(n4.set_name(STR("n4")));
CHECK(child.insert_child_before(node_element, n3) == xml_node());
CHECK_NODE(doc, "<node><?n4?>foo<n1 />n3<n2 /><child /></node>");
CHECK_NODE(doc, STR("<node><?n4?>foo<n1 />n3<n2 /><child /></node>"));
}
TEST_XML(dom_node_remove_child, "<node><n1/><n2/><n3/><child><n4/></child></node>")
{
xml_node().remove_child("a");
xml_node().remove_child(STR("a"));
xml_node().remove_child(xml_node());
xml_node node = doc.child("node");
xml_node child = node.child("child");
xml_node node = doc.child(STR("node"));
xml_node child = node.child(STR("child"));
node.remove_child("a");
node.remove_child(STR("a"));
node.remove_child(xml_node());
node.remove_child(child.child("n4"));
node.remove_child(child.child(STR("n4")));
CHECK_NODE(doc, "<node><n1 /><n2 /><n3 /><child><n4 /></child></node>");
CHECK_NODE(doc, STR("<node><n1 /><n2 /><n3 /><child><n4 /></child></node>"));
node.remove_child("n1");
node.remove_child(node.child("n3"));
child.remove_child("n4");
node.remove_child(STR("n1"));
node.remove_child(node.child(STR("n3")));
child.remove_child(STR("n4"));
CHECK_NODE(doc, "<node><n2 /><child /></node>");
CHECK_NODE(doc, STR("<node><n2 /><child /></node>"));
}
TEST_XML(dom_node_append_copy, "<node>foo<child/></node>")
{
CHECK(xml_node().append_copy(xml_node()) == xml_node());
CHECK(doc.child("node").first_child().append_copy(doc.child("node")) == xml_node());
CHECK(doc.child(STR("node")).first_child().append_copy(doc.child(STR("node"))) == xml_node());
CHECK(doc.append_copy(doc) == xml_node());
CHECK(doc.append_copy(xml_node()) == xml_node());
xml_node n1 = doc.child("node").append_copy(doc.child("node").first_child());
xml_node n1 = doc.child(STR("node")).append_copy(doc.child(STR("node")).first_child());
CHECK(n1);
CHECK_STRING(n1.value(), "foo");
CHECK_NODE(doc, "<node>foo<child />foo</node>");
CHECK_STRING(n1.value(), STR("foo"));
CHECK_NODE(doc, STR("<node>foo<child />foo</node>"));
xml_node n2 = doc.child("node").append_copy(doc.child("node").child("child"));
xml_node n2 = doc.child(STR("node")).append_copy(doc.child(STR("node")).child(STR("child")));
CHECK(n2 && n2 != n1);
CHECK_STRING(n2.name(), "child");
CHECK_NODE(doc, "<node>foo<child />foo<child /></node>");
CHECK_STRING(n2.name(), STR("child"));
CHECK_NODE(doc, STR("<node>foo<child />foo<child /></node>"));
xml_node n3 = doc.child("node").child("child").append_copy(doc.child("node").first_child());
xml_node n3 = doc.child(STR("node")).child(STR("child")).append_copy(doc.child(STR("node")).first_child());
CHECK(n3 && n3 != n1 && n3 != n2);
CHECK_STRING(n3.value(), "foo");
CHECK_NODE(doc, "<node>foo<child>foo</child>foo<child /></node>");
CHECK_STRING(n3.value(), STR("foo"));
CHECK_NODE(doc, STR("<node>foo<child>foo</child>foo<child /></node>"));
}
TEST_XML(dom_node_insert_copy_after, "<node>foo<child/></node>")
{
CHECK(xml_node().insert_copy_after(xml_node(), xml_node()) == xml_node());
CHECK(doc.child("node").first_child().insert_copy_after(doc.child("node"), doc.child("node")) == xml_node());
CHECK(doc.child(STR("node")).first_child().insert_copy_after(doc.child(STR("node")), doc.child(STR("node"))) == xml_node());
CHECK(doc.insert_copy_after(doc, doc) == xml_node());
CHECK(doc.insert_copy_after(xml_node(), doc.child("node")) == xml_node());
CHECK(doc.insert_copy_after(doc.child("node"), xml_node()) == xml_node());
CHECK(doc.insert_copy_after(xml_node(), doc.child(STR("node"))) == xml_node());
CHECK(doc.insert_copy_after(doc.child(STR("node")), xml_node()) == xml_node());
xml_node n1 = doc.child("node").insert_copy_after(doc.child("node").child("child"), doc.child("node").first_child());
xml_node n1 = doc.child(STR("node")).insert_copy_after(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child());
CHECK(n1);
CHECK_STRING(n1.name(), "child");
CHECK_NODE(doc, "<node>foo<child /><child /></node>");
CHECK_STRING(n1.name(), STR("child"));
CHECK_NODE(doc, STR("<node>foo<child /><child /></node>"));
xml_node n2 = doc.child("node").insert_copy_after(doc.child("node").first_child(), doc.child("node").last_child());
xml_node n2 = doc.child(STR("node")).insert_copy_after(doc.child(STR("node")).first_child(), doc.child(STR("node")).last_child());
CHECK(n2 && n2 != n1);
CHECK_STRING(n2.value(), "foo");
CHECK_NODE(doc, "<node>foo<child /><child />foo</node>");
CHECK_STRING(n2.value(), STR("foo"));
CHECK_NODE(doc, STR("<node>foo<child /><child />foo</node>"));
xml_node n3 = doc.child("node").insert_copy_after(doc.child("node").first_child(), doc.child("node").first_child());
xml_node n3 = doc.child(STR("node")).insert_copy_after(doc.child(STR("node")).first_child(), doc.child(STR("node")).first_child());
CHECK(n3 && n3 != n1 && n3 != n2);
CHECK_STRING(n3.value(), "foo");
CHECK_NODE(doc, "<node>foofoo<child /><child />foo</node>");
CHECK_STRING(n3.value(), STR("foo"));
CHECK_NODE(doc, STR("<node>foofoo<child /><child />foo</node>"));
}
TEST_XML(dom_node_insert_copy_before, "<node>foo<child/></node>")
{
CHECK(xml_node().insert_copy_before(xml_node(), xml_node()) == xml_node());
CHECK(doc.child("node").first_child().insert_copy_before(doc.child("node"), doc.child("node")) == xml_node());
CHECK(doc.child(STR("node")).first_child().insert_copy_before(doc.child(STR("node")), doc.child(STR("node"))) == xml_node());
CHECK(doc.insert_copy_before(doc, doc) == xml_node());
CHECK(doc.insert_copy_before(xml_node(), doc.child("node")) == xml_node());
CHECK(doc.insert_copy_before(doc.child("node"), xml_node()) == xml_node());
CHECK(doc.insert_copy_before(xml_node(), doc.child(STR("node"))) == xml_node());
CHECK(doc.insert_copy_before(doc.child(STR("node")), xml_node()) == xml_node());
xml_node n1 = doc.child("node").insert_copy_before(doc.child("node").child("child"), doc.child("node").first_child());
xml_node n1 = doc.child(STR("node")).insert_copy_before(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child());
CHECK(n1);
CHECK_STRING(n1.name(), "child");
CHECK_NODE(doc, "<node><child />foo<child /></node>");
CHECK_STRING(n1.name(), STR("child"));
CHECK_NODE(doc, STR("<node><child />foo<child /></node>"));
xml_node n2 = doc.child("node").insert_copy_before(doc.child("node").first_child(), doc.child("node").last_child());
xml_node n2 = doc.child(STR("node")).insert_copy_before(doc.child(STR("node")).first_child(), doc.child(STR("node")).last_child());
CHECK(n2 && n2 != n1);
CHECK_STRING(n2.name(), "child");
CHECK_NODE(doc, "<node><child />foo<child /><child /></node>");
CHECK_STRING(n2.name(), STR("child"));
CHECK_NODE(doc, STR("<node><child />foo<child /><child /></node>"));
xml_node n3 = doc.child("node").insert_copy_before(doc.child("node").first_child().next_sibling(), doc.child("node").first_child());
xml_node n3 = doc.child(STR("node")).insert_copy_before(doc.child(STR("node")).first_child().next_sibling(), doc.child(STR("node")).first_child());
CHECK(n3 && n3 != n1 && n3 != n2);
CHECK_STRING(n3.value(), "foo");
CHECK_NODE(doc, "<node>foo<child />foo<child /><child /></node>");
CHECK_STRING(n3.value(), STR("foo"));
CHECK_NODE(doc, STR("<node>foo<child />foo<child /><child /></node>"));
}
TEST_XML(dom_node_copy_recursive, "<node>foo<child/></node>")
{
doc.child("node").append_copy(doc.child("node"));
CHECK_NODE(doc, "<node>foo<child /><node>foo<child /></node></node>");
doc.child(STR("node")).append_copy(doc.child(STR("node")));
CHECK_NODE(doc, STR("<node>foo<child /><node>foo<child /></node></node>"));
}
TEST_XML(dom_node_copy_crossdoc, "<node/>")
{
xml_document newdoc;
newdoc.append_copy(doc.child("node"));
CHECK_NODE(doc, "<node />");
CHECK_NODE(newdoc, "<node />");
newdoc.append_copy(doc.child(STR("node")));
CHECK_NODE(doc, STR("<node />"));
CHECK_NODE(newdoc, STR("<node />"));
}
TEST_XML_FLAGS(dom_node_copy_types, "<root><?xml version='1.0'?><?pi value?><!--comment--><node id='1'>pcdata<![CDATA[cdata]]></node></root>", parse_default | parse_pi | parse_comments | parse_declaration)
{
doc.append_copy(doc.child("root"));
CHECK_NODE(doc, "<root><?xml version=\"1.0\"?><?pi value?><!--comment--><node id=\"1\">pcdata<![CDATA[cdata]]></node></root><root><?xml version=\"1.0\"?><?pi value?><!--comment--><node id=\"1\">pcdata<![CDATA[cdata]]></node></root>");
doc.append_copy(doc.child(STR("root")));
CHECK_NODE(doc, STR("<root><?xml version=\"1.0\"?><?pi value?><!--comment--><node id=\"1\">pcdata<![CDATA[cdata]]></node></root><root><?xml version=\"1.0\"?><?pi value?><!--comment--><node id=\"1\">pcdata<![CDATA[cdata]]></node></root>"));
}
TEST_XML(dom_attr_assign_large, "<node attr1='' attr2='' />")
{
xml_node node = doc.child(STR("node"));
node.attribute(STR("attr1")) = FLT_MAX;
node.attribute(STR("attr2")) = DBL_MAX;
CHECK(test_node(node, STR("<node attr1=\"3.40282e+038\" attr2=\"1.79769e+308\" />"), STR(""), pugi::format_raw) ||
test_node(node, STR("<node attr1=\"3.40282e+38\" attr2=\"1.79769e+308\" />"), STR(""), pugi::format_raw));
}

View file

@ -2,9 +2,13 @@
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <utility>
#include <vector>
#include <iterator>
#include <string>
#include "helpers.hpp"
@ -37,28 +41,28 @@ template <typename T> static void generic_empty_test(const T& obj)
TEST_XML(dom_attr_bool_ops, "<node attr='1'/>")
{
generic_bool_ops_test(doc.child("node").attribute("attr"));
generic_bool_ops_test(doc.child(STR("node")).attribute(STR("attr")));
}
TEST_XML(dom_attr_eq_ops, "<node attr1='1' attr2='2'/>")
{
generic_eq_ops_test(doc.child("node").attribute("attr1"), doc.child("node").attribute("attr2"));
generic_eq_ops_test(doc.child(STR("node")).attribute(STR("attr1")), doc.child(STR("node")).attribute(STR("attr2")));
}
TEST_XML(dom_attr_rel_ops, "<node attr1='1' attr2='2'/>")
{
generic_rel_ops_test(doc.child("node").attribute("attr1"), doc.child("node").attribute("attr2"));
generic_rel_ops_test(doc.child(STR("node")).attribute(STR("attr1")), doc.child(STR("node")).attribute(STR("attr2")));
}
TEST_XML(dom_attr_empty, "<node attr='1'/>")
{
generic_empty_test(doc.child("node").attribute("attr"));
generic_empty_test(doc.child(STR("node")).attribute(STR("attr")));
}
TEST_XML(dom_attr_next_previous_attribute, "<node attr1='1' attr2='2' />")
{
xml_attribute attr1 = doc.child("node").attribute("attr1");
xml_attribute attr2 = doc.child("node").attribute("attr2");
xml_attribute attr1 = doc.child(STR("node")).attribute(STR("attr1"));
xml_attribute attr2 = doc.child(STR("node")).attribute(STR("attr2"));
CHECK(attr1.next_attribute() == attr2);
CHECK(attr2.next_attribute() == xml_attribute());
@ -72,87 +76,87 @@ TEST_XML(dom_attr_next_previous_attribute, "<node attr1='1' attr2='2' />")
TEST_XML(dom_attr_name_value, "<node attr='1'/>")
{
xml_attribute attr = doc.child("node").attribute("attr");
xml_attribute attr = doc.child(STR("node")).attribute(STR("attr"));
CHECK_NAME_VALUE(attr, "attr", "1");
CHECK_NAME_VALUE(xml_attribute(), "", "");
CHECK_NAME_VALUE(attr, STR("attr"), STR("1"));
CHECK_NAME_VALUE(xml_attribute(), STR(""), STR(""));
}
TEST_XML(dom_attr_as_int, "<node attr1='1' attr2='-1' attr3='-2147483648' attr4='2147483647'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(xml_attribute().as_int() == 0);
CHECK(node.attribute("attr1").as_int() == 1);
CHECK(node.attribute("attr2").as_int() == -1);
CHECK(node.attribute("attr3").as_int() == -2147483647 - 1);
CHECK(node.attribute("attr4").as_int() == 2147483647);
CHECK(node.attribute(STR("attr1")).as_int() == 1);
CHECK(node.attribute(STR("attr2")).as_int() == -1);
CHECK(node.attribute(STR("attr3")).as_int() == -2147483647 - 1);
CHECK(node.attribute(STR("attr4")).as_int() == 2147483647);
}
TEST_XML(dom_attr_as_uint, "<node attr1='0' attr2='1' attr3='2147483647'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(xml_attribute().as_uint() == 0);
CHECK(node.attribute("attr1").as_uint() == 0);
CHECK(node.attribute("attr2").as_uint() == 1);
CHECK(node.attribute("attr3").as_uint() == 2147483647);
CHECK(node.attribute(STR("attr1")).as_uint() == 0);
CHECK(node.attribute(STR("attr2")).as_uint() == 1);
CHECK(node.attribute(STR("attr3")).as_uint() == 2147483647);
}
TEST_XML(dom_attr_as_float, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(xml_attribute().as_float() == 0);
CHECK_DOUBLE(node.attribute("attr1").as_float(), 0);
CHECK_DOUBLE(node.attribute("attr2").as_float(), 1);
CHECK_DOUBLE(node.attribute("attr3").as_float(), 0.12);
CHECK_DOUBLE(node.attribute("attr4").as_float(), -5.1);
CHECK_DOUBLE(node.attribute("attr5").as_float(), 3e-4);
CHECK_DOUBLE(node.attribute("attr6").as_float(), 3.14159265358979323846);
CHECK_DOUBLE(node.attribute(STR("attr1")).as_float(), 0);
CHECK_DOUBLE(node.attribute(STR("attr2")).as_float(), 1);
CHECK_DOUBLE(node.attribute(STR("attr3")).as_float(), 0.12);
CHECK_DOUBLE(node.attribute(STR("attr4")).as_float(), -5.1);
CHECK_DOUBLE(node.attribute(STR("attr5")).as_float(), 3e-4);
CHECK_DOUBLE(node.attribute(STR("attr6")).as_float(), 3.14159265358979323846);
}
TEST_XML(dom_attr_as_double, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(xml_attribute().as_double() == 0);
CHECK_DOUBLE(node.attribute("attr1").as_double(), 0);
CHECK_DOUBLE(node.attribute("attr2").as_double(), 1);
CHECK_DOUBLE(node.attribute("attr3").as_double(), 0.12);
CHECK_DOUBLE(node.attribute("attr4").as_double(), -5.1);
CHECK_DOUBLE(node.attribute("attr5").as_double(), 3e-4);
CHECK_DOUBLE(node.attribute("attr6").as_double(), 3.14159265358979323846);
CHECK_DOUBLE(node.attribute(STR("attr1")).as_double(), 0);
CHECK_DOUBLE(node.attribute(STR("attr2")).as_double(), 1);
CHECK_DOUBLE(node.attribute(STR("attr3")).as_double(), 0.12);
CHECK_DOUBLE(node.attribute(STR("attr4")).as_double(), -5.1);
CHECK_DOUBLE(node.attribute(STR("attr5")).as_double(), 3e-4);
CHECK_DOUBLE(node.attribute(STR("attr6")).as_double(), 3.14159265358979323846);
}
TEST_XML(dom_attr_as_bool, "<node attr1='0' attr2='1' attr3='true' attr4='True' attr5='Yes' attr6='yes' attr7='false'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(!xml_attribute().as_bool());
CHECK(!node.attribute("attr1").as_bool());
CHECK(node.attribute("attr2").as_bool());
CHECK(node.attribute("attr3").as_bool());
CHECK(node.attribute("attr4").as_bool());
CHECK(node.attribute("attr5").as_bool());
CHECK(node.attribute("attr6").as_bool());
CHECK(!node.attribute("attr7").as_bool());
CHECK(!node.attribute(STR("attr1")).as_bool());
CHECK(node.attribute(STR("attr2")).as_bool());
CHECK(node.attribute(STR("attr3")).as_bool());
CHECK(node.attribute(STR("attr4")).as_bool());
CHECK(node.attribute(STR("attr5")).as_bool());
CHECK(node.attribute(STR("attr6")).as_bool());
CHECK(!node.attribute(STR("attr7")).as_bool());
}
TEST_XML(dom_attr_iterator, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/><node3/></node>")
{
xml_node node1 = doc.child("node").child("node1");
xml_node node2 = doc.child("node").child("node2");
xml_node node3 = doc.child("node").child("node3");
xml_node node1 = doc.child(STR("node")).child(STR("node1"));
xml_node node2 = doc.child(STR("node")).child(STR("node2"));
xml_node node3 = doc.child(STR("node")).child(STR("node3"));
CHECK(xml_node().attributes_begin() == xml_attribute_iterator());
CHECK(xml_node().attributes_end() == xml_attribute_iterator());
CHECK(node1.attributes_begin() == xml_attribute_iterator(node1.attribute("attr1")));
CHECK(node1.attributes_begin() == xml_attribute_iterator(node1.attribute(STR("attr1"))));
CHECK(move_iter(node1.attributes_begin(), 1) == node1.attributes_end());
CHECK(move_iter(node1.attributes_end(), -1) == node1.attributes_begin());
CHECK(*node1.attributes_begin() == node1.attribute("attr1"));
CHECK_STRING(node1.attributes_begin()->name(), "attr1");
CHECK(*node1.attributes_begin() == node1.attribute(STR("attr1")));
CHECK_STRING(node1.attributes_begin()->name(), STR("attr1"));
CHECK(move_iter(node2.attributes_begin(), 2) == node2.attributes_end());
CHECK(move_iter(node2.attributes_end(), -2) == node2.attributes_begin());
@ -160,7 +164,7 @@ TEST_XML(dom_attr_iterator, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/
CHECK(node3.attributes_begin() == xml_attribute_iterator());
CHECK(node3.attributes_begin() == node3.attributes_end());
xml_attribute_iterator it = node2.attribute("attr2");
xml_attribute_iterator it = node2.attribute(STR("attr2"));
xml_attribute_iterator itt = it;
CHECK(itt++ == it);
@ -180,38 +184,38 @@ TEST_XML(dom_attr_iterator, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/
TEST_XML(dom_node_bool_ops, "<node/>")
{
generic_bool_ops_test(doc.child("node"));
generic_bool_ops_test(doc.child(STR("node")));
}
TEST_XML(dom_node_eq_ops, "<node><node1/><node2/></node>")
{
generic_eq_ops_test(doc.child("node").child("node1"), doc.child("node").child("node2"));
generic_eq_ops_test(doc.child(STR("node")).child(STR("node1")), doc.child(STR("node")).child(STR("node2")));
}
TEST_XML(dom_node_rel_ops, "<node><node1/><node2/></node>")
{
generic_rel_ops_test(doc.child("node").child("node1"), doc.child("node").child("node2"));
generic_rel_ops_test(doc.child(STR("node")).child(STR("node1")), doc.child(STR("node")).child(STR("node2")));
}
TEST_XML(dom_node_empty, "<node/>")
{
generic_empty_test(doc.child("node"));
generic_empty_test(doc.child(STR("node")));
}
TEST_XML(dom_node_iterator, "<node><node1><child1/></node1><node2><child1/><child2/></node2><node3/></node>")
{
xml_node node1 = doc.child("node").child("node1");
xml_node node2 = doc.child("node").child("node2");
xml_node node3 = doc.child("node").child("node3");
xml_node node1 = doc.child(STR("node")).child(STR("node1"));
xml_node node2 = doc.child(STR("node")).child(STR("node2"));
xml_node node3 = doc.child(STR("node")).child(STR("node3"));
CHECK(xml_node().begin() == xml_node_iterator());
CHECK(xml_node().end() == xml_node_iterator());
CHECK(node1.begin() == xml_node_iterator(node1.child("child1")));
CHECK(node1.begin() == xml_node_iterator(node1.child(STR("child1"))));
CHECK(move_iter(node1.begin(), 1) == node1.end());
CHECK(move_iter(node1.end(), -1) == node1.begin());
CHECK(*node1.begin() == node1.child("child1"));
CHECK_STRING(node1.begin()->name(), "child1");
CHECK(*node1.begin() == node1.child(STR("child1")));
CHECK_STRING(node1.begin()->name(), STR("child1"));
CHECK(move_iter(node2.begin(), 2) == node2.end());
CHECK(move_iter(node2.end(), -2) == node2.begin());
@ -219,7 +223,7 @@ TEST_XML(dom_node_iterator, "<node><node1><child1/></node1><node2><child1/><chil
CHECK(node3.begin() == xml_node_iterator());
CHECK(node3.begin() == node3.end());
xml_node_iterator it = node2.child("child2");
xml_node_iterator it = node2.child(STR("child2"));
xml_node_iterator itt = it;
CHECK(itt++ == it);
@ -240,15 +244,15 @@ TEST_XML(dom_node_iterator, "<node><node1><child1/></node1><node2><child1/><chil
TEST_XML(dom_node_parent, "<node><child/></node>")
{
CHECK(xml_node().parent() == xml_node());
CHECK(doc.child("node").child("child").parent() == doc.child("node"));
CHECK(doc.child("node").parent() == doc);
CHECK(doc.child(STR("node")).child(STR("child")).parent() == doc.child(STR("node")));
CHECK(doc.child(STR("node")).parent() == doc);
}
TEST_XML(dom_node_root, "<node><child/></node>")
{
CHECK(xml_node().root() == xml_node());
CHECK(doc.child("node").child("child").root() == doc);
CHECK(doc.child("node").root() == doc);
CHECK(doc.child(STR("node")).child(STR("child")).root() == doc);
CHECK(doc.child(STR("node")).root() == doc);
}
TEST_XML_FLAGS(dom_node_type, "<?xml?><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration)
@ -263,7 +267,7 @@ TEST_XML_FLAGS(dom_node_type, "<?xml?><?pi?><!--comment--><node>pcdata<![CDATA[c
CHECK((it++)->type() == node_comment);
CHECK((it++)->type() == node_element);
xml_node_iterator cit = doc.child("node").begin();
xml_node_iterator cit = doc.child(STR("node")).begin();
CHECK((cit++)->type() == node_pcdata);
CHECK((cit++)->type() == node_cdata);
@ -271,64 +275,64 @@ TEST_XML_FLAGS(dom_node_type, "<?xml?><?pi?><!--comment--><node>pcdata<![CDATA[c
TEST_XML_FLAGS(dom_node_name_value, "<?xml?><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration)
{
CHECK_NAME_VALUE(xml_node(), "", "");
CHECK_NAME_VALUE(doc, "", "");
CHECK_NAME_VALUE(xml_node(), STR(""), STR(""));
CHECK_NAME_VALUE(doc, STR(""), STR(""));
xml_node_iterator it = doc.begin();
CHECK_NAME_VALUE(*it++, "xml", "");
CHECK_NAME_VALUE(*it++, "pi", "");
CHECK_NAME_VALUE(*it++, "", "comment");
CHECK_NAME_VALUE(*it++, "node", "");
CHECK_NAME_VALUE(*it++, STR("xml"), STR(""));
CHECK_NAME_VALUE(*it++, STR("pi"), STR(""));
CHECK_NAME_VALUE(*it++, STR(""), STR("comment"));
CHECK_NAME_VALUE(*it++, STR("node"), STR(""));
xml_node_iterator cit = doc.child("node").begin();
xml_node_iterator cit = doc.child(STR("node")).begin();
CHECK_NAME_VALUE(*cit++, "", "pcdata");
CHECK_NAME_VALUE(*cit++, "", "cdata");
CHECK_NAME_VALUE(*cit++, STR(""), STR("pcdata"));
CHECK_NAME_VALUE(*cit++, STR(""), STR("cdata"));
}
TEST_XML(dom_node_child, "<node><child1/><child2/></node>")
{
CHECK(xml_node().child("n") == xml_node());
CHECK(xml_node().child(STR("n")) == xml_node());
CHECK(doc.child("n") == xml_node());
CHECK_NAME_VALUE(doc.child("node"), "node", "");
CHECK(doc.child("node").child("child2") == doc.child("node").last_child());
CHECK(doc.child(STR("n")) == xml_node());
CHECK_NAME_VALUE(doc.child(STR("node")), STR("node"), STR(""));
CHECK(doc.child(STR("node")).child(STR("child2")) == doc.child(STR("node")).last_child());
CHECK(doc.child_w("n?de") == doc.child("node"));
CHECK(doc.child_w("n[az]de") == xml_node());
CHECK(doc.child_w("n[aoz]de") == doc.child("node"));
CHECK(doc.child_w("*e") == doc.child("node"));
CHECK(doc.child("node").child_w("*l?[23456789]*") == doc.child("node").child("child2"));
CHECK(doc.child_w(STR("n?de")) == doc.child(STR("node")));
CHECK(doc.child_w(STR("n[az]de")) == xml_node());
CHECK(doc.child_w(STR("n[aoz]de")) == doc.child(STR("node")));
CHECK(doc.child_w(STR("*e")) == doc.child(STR("node")));
CHECK(doc.child(STR("node")).child_w(STR("*l?[23456789]*")) == doc.child(STR("node")).child(STR("child2")));
}
TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().attribute("a") == xml_attribute());
CHECK(xml_node().attribute(STR("a")) == xml_attribute());
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.attribute("n") == xml_attribute());
CHECK_NAME_VALUE(node.attribute("attr1"), "attr1", "0");
CHECK(node.attribute("attr2") == node.last_attribute());
CHECK(node.attribute(STR("n")) == xml_attribute());
CHECK_NAME_VALUE(node.attribute(STR("attr1")), STR("attr1"), STR("0"));
CHECK(node.attribute(STR("attr2")) == node.last_attribute());
CHECK(node.attribute_w("*tt?[23456789]*") == node.attribute("attr2"));
CHECK(node.attribute_w("?") == xml_attribute());
CHECK(node.attribute_w(STR("*tt?[23456789]*")) == node.attribute(STR("attr2")));
CHECK(node.attribute_w(STR("?")) == xml_attribute());
}
TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></node>")
{
CHECK(xml_node().next_sibling() == xml_node());
CHECK(xml_node().next_sibling("n") == xml_node());
CHECK(xml_node().next_sibling_w("n") == xml_node());
CHECK(xml_node().next_sibling(STR("n")) == xml_node());
CHECK(xml_node().next_sibling_w(STR("n")) == xml_node());
CHECK(xml_node().previous_sibling() == xml_node());
CHECK(xml_node().previous_sibling("n") == xml_node());
CHECK(xml_node().previous_sibling_w("n") == xml_node());
CHECK(xml_node().previous_sibling(STR("n")) == xml_node());
CHECK(xml_node().previous_sibling_w(STR("n")) == xml_node());
xml_node child1 = doc.child("node").child("child1");
xml_node child2 = doc.child("node").child("child2");
xml_node child3 = doc.child("node").child("child3");
xml_node child1 = doc.child(STR("node")).child(STR("child1"));
xml_node child2 = doc.child(STR("node")).child(STR("child2"));
xml_node child3 = doc.child(STR("node")).child(STR("child3"));
CHECK(child1.next_sibling() == child2);
CHECK(child3.next_sibling() == xml_node());
@ -336,41 +340,42 @@ TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></nod
CHECK(child1.previous_sibling() == xml_node());
CHECK(child3.previous_sibling() == child2);
CHECK(child1.next_sibling("child3") == child3);
CHECK(child1.next_sibling("child") == xml_node());
CHECK(child1.next_sibling(STR("child3")) == child3);
CHECK(child1.next_sibling(STR("child")) == xml_node());
CHECK(child3.previous_sibling("child1") == child1);
CHECK(child3.previous_sibling("child") == xml_node());
CHECK(child3.previous_sibling(STR("child1")) == child1);
CHECK(child3.previous_sibling(STR("child")) == xml_node());
CHECK(child1.next_sibling_w("*[3456789]") == child3);
CHECK(child1.next_sibling_w("?") == xml_node());
CHECK(child3.previous_sibling_w("*[3456789]") == xml_node());
CHECK(child3.previous_sibling_w("?") == xml_node());
CHECK(child1.next_sibling_w(STR("*[3456789]")) == child3);
CHECK(child1.next_sibling_w(STR("?")) == xml_node());
CHECK(child3.previous_sibling_w(STR("*[3456789]")) == xml_node());
CHECK(child3.previous_sibling_w(STR("?")) == xml_node());
CHECK(child3.previous_sibling_w(STR("*1")) == child1);
}
TEST_XML(dom_node_child_value, "<node><novalue/><child1>value1</child1><child2>value2<n/></child2><child3><![CDATA[value3]]></child3>value4</node>")
{
CHECK_STRING(xml_node().child_value(), "");
CHECK_STRING(xml_node().child_value("n"), "");
CHECK_STRING(xml_node().child_value_w("n"), "");
CHECK_STRING(xml_node().child_value(), STR(""));
CHECK_STRING(xml_node().child_value(STR("n")), STR(""));
CHECK_STRING(xml_node().child_value_w(STR("n")), STR(""));
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child_value(), "value4");
CHECK_STRING(node.child("child1").child_value(), "value1");
CHECK_STRING(node.child("child2").child_value(), "value2");
CHECK_STRING(node.child("child3").child_value(), "value3");
CHECK_STRING(node.child_value("child3"), "value3");
CHECK_STRING(node.child_value_w("c*[23456789]"), "value2");
CHECK_STRING(node.child_value_w("*"), ""); // child_value(name) and child_value_w(pattern) do not continue the search if a node w/out value is found first
CHECK_STRING(node.child_value(), STR("value4"));
CHECK_STRING(node.child(STR("child1")).child_value(), STR("value1"));
CHECK_STRING(node.child(STR("child2")).child_value(), STR("value2"));
CHECK_STRING(node.child(STR("child3")).child_value(), STR("value3"));
CHECK_STRING(node.child_value(STR("child3")), STR("value3"));
CHECK_STRING(node.child_value_w(STR("c*[23456789]")), STR("value2"));
CHECK_STRING(node.child_value_w(STR("*")), STR("")); // child_value(name) and child_value_w(pattern) do not continue the search if a node w/out value is found first
}
TEST_XML(dom_node_first_last_attribute, "<node attr1='0' attr2='1'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.first_attribute() == node.attribute("attr1"));
CHECK(node.last_attribute() == node.attribute("attr2"));
CHECK(node.first_attribute() == node.attribute(STR("attr1")));
CHECK(node.last_attribute() == node.attribute(STR("attr2")));
CHECK(xml_node().first_attribute() == xml_attribute());
CHECK(xml_node().last_attribute() == xml_attribute());
@ -381,10 +386,10 @@ TEST_XML(dom_node_first_last_attribute, "<node attr1='0' attr2='1'/>")
TEST_XML(dom_node_first_last_child, "<node><child1/><child2/></node>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.first_child() == node.child("child1"));
CHECK(node.last_child() == node.child("child2"));
CHECK(node.first_child() == node.child(STR("child1")));
CHECK(node.last_child() == node.child(STR("child2")));
CHECK(xml_node().first_child() == xml_node());
CHECK(xml_node().last_child() == xml_node());
@ -395,22 +400,22 @@ TEST_XML(dom_node_first_last_child, "<node><child1/><child2/></node>")
TEST_XML(dom_node_find_child_by_attribute, "<node><child1 attr='value1'/><child2 attr='value2'/><child2 attr='value3'/></node>")
{
CHECK(xml_node().find_child_by_attribute("name", "attr", "value") == xml_node());
CHECK(xml_node().find_child_by_attribute_w("name", "attr", "value") == xml_node());
CHECK(xml_node().find_child_by_attribute("attr", "value") == xml_node());
CHECK(xml_node().find_child_by_attribute_w("attr", "value") == xml_node());
CHECK(xml_node().find_child_by_attribute(STR("name"), STR("attr"), STR("value")) == xml_node());
CHECK(xml_node().find_child_by_attribute_w(STR("name"), STR("attr"), STR("value")) == xml_node());
CHECK(xml_node().find_child_by_attribute(STR("attr"), STR("value")) == xml_node());
CHECK(xml_node().find_child_by_attribute_w(STR("attr"), STR("value")) == xml_node());
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.find_child_by_attribute("child2", "attr", "value3") == node.last_child());
CHECK(node.find_child_by_attribute("child2", "attr3", "value3") == xml_node());
CHECK(node.find_child_by_attribute("attr", "value2") == node.child("child2"));
CHECK(node.find_child_by_attribute("attr3", "value") == xml_node());
CHECK(node.find_child_by_attribute(STR("child2"), STR("attr"), STR("value3")) == node.last_child());
CHECK(node.find_child_by_attribute(STR("child2"), STR("attr3"), STR("value3")) == xml_node());
CHECK(node.find_child_by_attribute(STR("attr"), STR("value2")) == node.child(STR("child2")));
CHECK(node.find_child_by_attribute(STR("attr3"), STR("value")) == xml_node());
CHECK(node.find_child_by_attribute_w("*", "att?", "val*[0123456789]") == node.child("child1"));
CHECK(node.find_child_by_attribute_w("*", "attr3", "val*[0123456789]") == xml_node());
CHECK(node.find_child_by_attribute_w("att?", "val*[0123456789]") == node.child("child1"));
CHECK(node.find_child_by_attribute_w("attr3", "val*[0123456789]") == xml_node());
CHECK(node.find_child_by_attribute_w(STR("*"), STR("att?"), STR("val*[0123456789]")) == node.child(STR("child1")));
CHECK(node.find_child_by_attribute_w(STR("*"), STR("attr3"), STR("val*[0123456789]")) == xml_node());
CHECK(node.find_child_by_attribute_w(STR("att?"), STR("val*[0123456789]")) == node.child(STR("child1")));
CHECK(node.find_child_by_attribute_w(STR("attr3"), STR("val*[0123456789]")) == xml_node());
}
TEST_XML(dom_node_all_elements_by_name, "<node><child><child/><child/></child></node>")
@ -418,31 +423,31 @@ TEST_XML(dom_node_all_elements_by_name, "<node><child><child/><child/></child></
std::vector<xml_node> v;
v.clear();
xml_node().all_elements_by_name("node", std::back_inserter(v));
xml_node().all_elements_by_name(STR("node"), std::back_inserter(v));
CHECK(v.empty());
v.clear();
xml_node().all_elements_by_name_w("*", std::back_inserter(v));
xml_node().all_elements_by_name_w(STR("*"), std::back_inserter(v));
CHECK(v.empty());
v.clear();
doc.all_elements_by_name("node", std::back_inserter(v));
CHECK(v.size() == 1 && v[0] == doc.child("node"));
doc.all_elements_by_name(STR("node"), std::back_inserter(v));
CHECK(v.size() == 1 && v[0] == doc.child(STR("node")));
v.clear();
doc.all_elements_by_name("child", std::back_inserter(v));
doc.all_elements_by_name(STR("child"), std::back_inserter(v));
CHECK(v.size() == 3);
CHECK(v[0] == doc.child("node").child("child"));
CHECK(v[1] == doc.child("node").child("child").first_child());
CHECK(v[2] == doc.child("node").child("child").last_child());
CHECK(v[0] == doc.child(STR("node")).child(STR("child")));
CHECK(v[1] == doc.child(STR("node")).child(STR("child")).first_child());
CHECK(v[2] == doc.child(STR("node")).child(STR("child")).last_child());
v.clear();
doc.all_elements_by_name_w("*", std::back_inserter(v));
doc.all_elements_by_name_w(STR("*"), std::back_inserter(v));
CHECK(v.size() == 4);
CHECK(v[0] == doc.child("node"));
CHECK(v[1] == doc.child("node").child("child"));
CHECK(v[2] == doc.child("node").child("child").first_child());
CHECK(v[3] == doc.child("node").child("child").last_child());
CHECK(v[0] == doc.child(STR("node")));
CHECK(v[1] == doc.child(STR("node")).child(STR("child")));
CHECK(v[2] == doc.child(STR("node")).child(STR("child")).first_child());
CHECK(v[3] == doc.child(STR("node")).child(STR("child")).last_child());
}
struct find_predicate_const
@ -461,15 +466,20 @@ struct find_predicate_const
struct find_predicate_prefix
{
const char* prefix;
const pugi::char_t* prefix;
find_predicate_prefix(const char* prefix): prefix(prefix)
find_predicate_prefix(const pugi::char_t* prefix): prefix(prefix)
{
}
template <typename T> bool operator()(const T& obj) const
{
#ifdef PUGIXML_WCHAR_MODE
// can't use wcsncmp here because of a bug in DMC
return std::basic_string<pugi::char_t>(obj.name()).compare(0, wcslen(prefix), prefix) == 0;
#else
return strncmp(obj.name(), prefix, strlen(prefix)) == 0;
#endif
}
};
@ -477,86 +487,86 @@ TEST_XML(dom_node_find_attribute, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().find_attribute(find_predicate_const(true)) == xml_attribute());
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(doc.find_attribute(find_predicate_const(true)) == xml_attribute());
CHECK(node.find_attribute(find_predicate_const(true)) == node.first_attribute());
CHECK(node.find_attribute(find_predicate_const(false)) == xml_attribute());
CHECK(node.find_attribute(find_predicate_prefix("attr2")) == node.last_attribute());
CHECK(node.find_attribute(find_predicate_prefix("attr")) == node.first_attribute());
CHECK(node.find_attribute(find_predicate_prefix(STR("attr2"))) == node.last_attribute());
CHECK(node.find_attribute(find_predicate_prefix(STR("attr"))) == node.first_attribute());
}
TEST_XML(dom_node_find_child, "<node><child1/><child2/></node>")
{
CHECK(xml_node().find_child(find_predicate_const(true)) == xml_node());
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.child("node").child("child1").find_child(find_predicate_const(true)) == xml_node());
CHECK(node.child(STR("node")).child(STR("child1")).find_child(find_predicate_const(true)) == xml_node());
CHECK(node.find_child(find_predicate_const(true)) == node.first_child());
CHECK(node.find_child(find_predicate_const(false)) == xml_node());
CHECK(node.find_child(find_predicate_prefix("child2")) == node.last_child());
CHECK(node.find_child(find_predicate_prefix("child")) == node.first_child());
CHECK(node.find_child(find_predicate_prefix(STR("child2"))) == node.last_child());
CHECK(node.find_child(find_predicate_prefix(STR("child"))) == node.first_child());
}
TEST_XML(dom_node_find_node, "<node><child1/><child2/></node>")
{
CHECK(xml_node().find_node(find_predicate_const(true)) == xml_node());
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.child("node").child("child1").find_node(find_predicate_const(true)) == xml_node());
CHECK(node.child(STR("node")).child(STR("child1")).find_node(find_predicate_const(true)) == xml_node());
CHECK(node.find_node(find_predicate_const(true)) == node.first_child());
CHECK(node.find_node(find_predicate_const(false)) == xml_node());
CHECK(node.find_node(find_predicate_prefix("child2")) == node.last_child());
CHECK(node.find_node(find_predicate_prefix("child")) == node.first_child());
CHECK(doc.find_node(find_predicate_prefix("child")) == node.first_child());
CHECK(doc.find_node(find_predicate_prefix("child2")) == node.last_child());
CHECK(doc.find_node(find_predicate_prefix("child3")) == xml_node());
CHECK(node.find_node(find_predicate_prefix(STR("child2"))) == node.last_child());
CHECK(node.find_node(find_predicate_prefix(STR("child"))) == node.first_child());
CHECK(doc.find_node(find_predicate_prefix(STR("child"))) == node.first_child());
CHECK(doc.find_node(find_predicate_prefix(STR("child2"))) == node.last_child());
CHECK(doc.find_node(find_predicate_prefix(STR("child3"))) == xml_node());
}
#ifndef PUGIXML_NO_STL
TEST_XML(dom_node_path, "<node><child1>text<child2/></child1></node>")
{
CHECK(xml_node().path() == "");
CHECK(xml_node().path() == STR(""));
CHECK(doc.path() == "");
CHECK(doc.child("node").path() == "/node");
CHECK(doc.child("node").child("child1").path() == "/node/child1");
CHECK(doc.child("node").child("child1").child("child2").path() == "/node/child1/child2");
CHECK(doc.child("node").child("child1").first_child().path() == "/node/child1/");
CHECK(doc.path() == STR(""));
CHECK(doc.child(STR("node")).path() == STR("/node"));
CHECK(doc.child(STR("node")).child(STR("child1")).path() == STR("/node/child1"));
CHECK(doc.child(STR("node")).child(STR("child1")).child(STR("child2")).path() == STR("/node/child1/child2"));
CHECK(doc.child(STR("node")).child(STR("child1")).first_child().path() == STR("/node/child1/"));
CHECK(doc.child("node").child("child1").path('\\') == "\\node\\child1");
CHECK(doc.child(STR("node")).child(STR("child1")).path('\\') == STR("\\node\\child1"));
}
#endif
TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></node>")
{
CHECK(xml_node().first_element_by_path("/") == xml_node());
CHECK(xml_node().first_element_by_path(STR("/")) == xml_node());
CHECK(doc.first_element_by_path("") == doc);
CHECK(doc.first_element_by_path("/") == doc);
CHECK(doc.first_element_by_path(STR("")) == doc);
CHECK(doc.first_element_by_path(STR("/")) == doc);
CHECK(doc.first_element_by_path("/node/") == doc.child("node"));
CHECK(doc.first_element_by_path("node/") == doc.child("node"));
CHECK(doc.first_element_by_path("node") == doc.child("node"));
CHECK(doc.first_element_by_path("/node") == doc.child("node"));
CHECK(doc.first_element_by_path(STR("/node/")) == doc.child(STR("node")));
CHECK(doc.first_element_by_path(STR("node/")) == doc.child(STR("node")));
CHECK(doc.first_element_by_path(STR("node")) == doc.child(STR("node")));
CHECK(doc.first_element_by_path(STR("/node")) == doc.child(STR("node")));
#ifndef PUGIXML_NO_STL
CHECK(doc.first_element_by_path("/node/child1/child2").path() == "/node/child1/child2");
CHECK(doc.first_element_by_path(STR("/node/child1/child2")).path() == STR("/node/child1/child2"));
#endif
CHECK(doc.first_element_by_path("/node/child2") == xml_node());
CHECK(doc.first_element_by_path(STR("/node/child2")) == xml_node());
CHECK(doc.first_element_by_path("\\node\\child1", '\\') == doc.child("node").child("child1"));
CHECK(doc.first_element_by_path(STR("\\node\\child1"), '\\') == doc.child(STR("node")).child(STR("child1")));
CHECK(doc.child("node").first_element_by_path("..") == doc);
CHECK(doc.child("node").first_element_by_path(".") == doc.child("node"));
CHECK(doc.child(STR("node")).first_element_by_path(STR("..")) == doc);
CHECK(doc.child(STR("node")).first_element_by_path(STR(".")) == doc.child(STR("node")));
}
struct test_walker: xml_tree_walker
{
std::string log;
std::basic_string<pugi::char_t> log;
unsigned int call_count;
unsigned int stop_count;
@ -564,32 +574,53 @@ struct test_walker: xml_tree_walker
{
}
std::basic_string<pugi::char_t> depthstr() const
{
char buf[32];
sprintf(buf, "%d", depth());
#ifdef PUGIXML_WCHAR_MODE
wchar_t wbuf[32];
std::copy(buf, buf + strlen(buf) + 1, wbuf);
return std::basic_string<pugi::char_t>(wbuf);
#else
return std::basic_string<pugi::char_t>(buf);
#endif
}
virtual bool begin(xml_node& node)
{
char buffer[32];
sprintf(buffer, "|%d <%s=%s", depth(), node.name(), node.value());
log += buffer;
log += STR("|");
log += depthstr();
log += STR(" <");
log += node.name();
log += STR("=");
log += node.value();
return ++call_count != stop_count && xml_tree_walker::begin(node);
}
virtual bool for_each(xml_node& node)
{
char buffer[32];
sprintf(buffer, "|%d !%s=%s", depth(), node.name(), node.value());
log += buffer;
log += STR("|");
log += depthstr();
log += STR(" !");
log += node.name();
log += STR("=");
log += node.value();
return ++call_count != stop_count && xml_tree_walker::end(node);
}
virtual bool end(xml_node& node)
{
char buffer[32];
sprintf(buffer, "|%d >%s=%s", depth(), node.name(), node.value());
log += buffer;
log += STR("|");
log += depthstr();
log += STR(" >");
log += node.name();
log += STR("=");
log += node.value();
return ++call_count != stop_count;
}
@ -602,7 +633,7 @@ TEST_XML(dom_node_traverse, "<node><child>text</child></node>")
CHECK(doc.traverse(walker));
CHECK(walker.call_count == 5);
CHECK(walker.log == "|-1 <=|0 !node=|1 !child=|2 !=text|-1 >=");
CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|2 !=text|-1 >="));
}
TEST_XML(dom_node_traverse_siblings, "<node><child/><child>text</child><child/></node>")
@ -612,7 +643,7 @@ TEST_XML(dom_node_traverse_siblings, "<node><child/><child>text</child><child/><
CHECK(doc.traverse(walker));
CHECK(walker.call_count == 7);
CHECK(walker.log == "|-1 <=|0 !node=|1 !child=|1 !child=|2 !=text|1 !child=|-1 >=");
CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|1 !child=|2 !=text|1 !child=|-1 >="));
}
TEST(dom_node_traverse_empty)
@ -622,17 +653,17 @@ TEST(dom_node_traverse_empty)
CHECK(xml_node().traverse(walker));
CHECK(walker.call_count == 2);
CHECK(walker.log == "|-1 <=|-1 >=");
CHECK(walker.log == STR("|-1 <=|-1 >="));
}
TEST_XML(dom_node_traverse_child, "<node><child>text</child></node>")
{
test_walker walker;
CHECK(doc.child("node").traverse(walker));
CHECK(doc.child(STR("node")).traverse(walker));
CHECK(walker.call_count == 4);
CHECK(walker.log == "|-1 <node=|0 !child=|1 !=text|-1 >node=");
CHECK(walker.log == STR("|-1 <node=|0 !child=|1 !=text|-1 >node="));
}
TEST_XML(dom_node_traverse_stop_begin, "<node><child>text</child></node>")
@ -642,7 +673,7 @@ TEST_XML(dom_node_traverse_stop_begin, "<node><child>text</child></node>")
CHECK(!doc.traverse(walker));
CHECK(walker.call_count == 1);
CHECK(walker.log == "|-1 <=");
CHECK(walker.log == STR("|-1 <="));
}
TEST_XML(dom_node_traverse_stop_for_each, "<node><child>text</child></node>")
@ -652,7 +683,7 @@ TEST_XML(dom_node_traverse_stop_for_each, "<node><child>text</child></node>")
CHECK(!doc.traverse(walker));
CHECK(walker.call_count == 3);
CHECK(walker.log == "|-1 <=|0 !node=|1 !child=");
CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child="));
}
TEST_XML(dom_node_traverse_stop_end, "<node><child>text</child></node>")
@ -662,7 +693,7 @@ TEST_XML(dom_node_traverse_stop_end, "<node><child>text</child></node>")
CHECK(!doc.traverse(walker));
CHECK(walker.call_count == 5);
CHECK(walker.log == "|-1 <=|0 !node=|1 !child=|2 !=text|-1 >=");
CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|2 !=text|-1 >="));
}
TEST_XML_FLAGS(dom_offset_debug, "<?xml?><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration)
@ -677,7 +708,7 @@ TEST_XML_FLAGS(dom_offset_debug, "<?xml?><?pi?><!--comment--><node>pcdata<![CDAT
CHECK((it++)->offset_debug() == 17);
CHECK((it++)->offset_debug() == 28);
xml_node_iterator cit = doc.child("node").begin();
xml_node_iterator cit = doc.child(STR("node")).begin();
CHECK((cit++)->offset_debug() == 33);
CHECK((cit++)->offset_debug() == 48);
@ -685,24 +716,24 @@ TEST_XML_FLAGS(dom_offset_debug, "<?xml?><?pi?><!--comment--><node>pcdata<![CDAT
TEST_XML(dom_node_wildcard_cset, "<node c='1'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.attribute_w("[A-Z]").as_int() == 0);
CHECK(node.attribute_w("[a-z]").as_int() == 1);
CHECK(node.attribute_w("[A-z]").as_int() == 1);
CHECK(node.attribute_w("[z-a]").as_int() == 0);
CHECK(node.attribute_w("[a-zA-Z]").as_int() == 1);
CHECK(node.attribute_w("[!A-Z]").as_int() == 1);
CHECK(node.attribute_w("[!A-Za-z]").as_int() == 0);
CHECK(node.attribute_w(STR("[A-Z]")).as_int() == 0);
CHECK(node.attribute_w(STR("[a-z]")).as_int() == 1);
CHECK(node.attribute_w(STR("[A-z]")).as_int() == 1);
CHECK(node.attribute_w(STR("[z-a]")).as_int() == 0);
CHECK(node.attribute_w(STR("[a-zA-Z]")).as_int() == 1);
CHECK(node.attribute_w(STR("[!A-Z]")).as_int() == 1);
CHECK(node.attribute_w(STR("[!A-Za-z]")).as_int() == 0);
}
TEST_XML(dom_node_wildcard_star, "<node cd='1'/>")
{
xml_node node = doc.child("node");
xml_node node = doc.child(STR("node"));
CHECK(node.attribute_w("*").as_int() == 1);
CHECK(node.attribute_w("?d*").as_int() == 1);
CHECK(node.attribute_w("?c*").as_int() == 0);
CHECK(node.attribute_w("*?*c*").as_int() == 0);
CHECK(node.attribute_w("*?*d*").as_int() == 1);
CHECK(node.attribute_w(STR("*")).as_int() == 1);
CHECK(node.attribute_w(STR("?d*")).as_int() == 1);
CHECK(node.attribute_w(STR("?c*")).as_int() == 0);
CHECK(node.attribute_w(STR("*?*c*")).as_int() == 0);
CHECK(node.attribute_w(STR("*?*d*")).as_int() == 1);
}

View file

@ -0,0 +1,3 @@
// Tests header guards
#include "../src/pugixml.hpp"
#include "../src/pugixml.hpp"

View file

@ -0,0 +1,3 @@
// Tests compatibility with iosfwd
#include "../src/pugixml.hpp"
#include <iosfwd>

View file

@ -0,0 +1,3 @@
// Tests compatibility with iosfwd
#include <iosfwd>
#include "../src/pugixml.hpp"

View file

@ -0,0 +1,3 @@
// Tests compatibility with iostream
#include "../src/pugixml.hpp"
#include <iostream>

View file

@ -0,0 +1,3 @@
// Tests compatibility with iostream
#include <iostream>
#include "../src/pugixml.hpp"

View file

@ -0,0 +1,3 @@
// Tests compatibility with string
#include "../src/pugixml.hpp"
#include <string>

View file

@ -0,0 +1,3 @@
// Tests compatibility with string
#include <string>
#include "../src/pugixml.hpp"

View file

@ -2,13 +2,13 @@
namespace
{
char buffer[8];
pugi::char_t buffer[8];
int allocate_count = 0;
int deallocate_count = 0;
void* allocate(size_t size)
{
CHECK(size == 8);
CHECK(size == sizeof(pugi::char_t) * 8);
++allocate_count;
return buffer;
}
@ -32,23 +32,23 @@ TEST(custom_memory_management)
{
// parse document
xml_document doc;
CHECK(doc.load("<node/>"));
CHECK(doc.load(STR("<node />")));
CHECK(allocate_count == 1);
CHECK(deallocate_count == 0);
CHECK_STRING(buffer, "<node\0>");
CHECK_STRING(buffer, STR("<node"));
// modify document
doc.child("node").set_name("foobars");
doc.child(STR("node")).set_name(STR("foobars"));
CHECK(allocate_count == 2);
CHECK(deallocate_count == 0);
CHECK_STRING(buffer, "foobars");
CHECK_STRING(buffer, STR("foobars"));
}
CHECK(allocate_count == 2);
CHECK(deallocate_count == 2);
CHECK_STRING(buffer, "foobars");
CHECK_STRING(buffer, STR("foobars"));
// restore old functions
set_memory_management_functions(old_allocate, old_deallocate);

View file

@ -3,25 +3,25 @@
TEST(parse_pi_skip)
{
xml_document doc;
CHECK(doc.load("<?pi?><?pi value?>", parse_minimal));
CHECK(doc.load(STR("<?pi?><?pi value?>"), parse_minimal));
CHECK(!doc.first_child());
}
TEST(parse_pi_parse)
{
xml_document doc;
CHECK(doc.load("<?pi1?><?pi2 value?>", parse_minimal | parse_pi));
CHECK(doc.load(STR("<?pi1?><?pi2 value?>"), parse_minimal | parse_pi));
xml_node pi1 = doc.first_child();
xml_node pi2 = doc.last_child();
CHECK(pi1 != pi2);
CHECK(pi1.type() == node_pi);
CHECK_STRING(pi1.name(), "pi1");
CHECK_STRING(pi1.value(), "");
CHECK_STRING(pi1.name(), STR("pi1"));
CHECK_STRING(pi1.value(), STR(""));
CHECK(pi2.type() == node_pi);
CHECK_STRING(pi2.name(), "pi2");
CHECK_STRING(pi2.value(), "value");
CHECK_STRING(pi2.name(), STR("pi2"));
CHECK_STRING(pi2.value(), STR("value"));
}
TEST(parse_pi_error)
@ -34,56 +34,69 @@ TEST(parse_pi_error)
{
unsigned int flags = flag_sets[i];
CHECK(doc.load("<?", flags).status == status_bad_pi);
CHECK(doc.load("<?#?>", flags).status == status_bad_pi);
CHECK(doc.load("<?name", flags).status == status_bad_pi);
CHECK(doc.load("<?name>", flags).status == status_bad_pi);
CHECK(doc.load("<?name ?", flags).status == status_bad_pi);
CHECK(doc.load(STR("<?"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<??"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?>"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?#?>"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name>"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name ?"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name?"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name? "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name? "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name value"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name value "), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?name value "), flags).status == status_bad_pi);
}
CHECK(doc.load(STR("<?xx#?>"), parse_minimal | parse_pi).status == status_bad_pi);
}
TEST(parse_comments_skip)
{
xml_document doc;
CHECK(doc.load("<!----><!--value-->", parse_minimal));
CHECK(doc.load(STR("<!----><!--value-->"), parse_minimal));
CHECK(!doc.first_child());
}
TEST(parse_comments_parse)
{
xml_document doc;
CHECK(doc.load("<!----><!--value-->", parse_minimal | parse_comments));
CHECK(doc.load(STR("<!----><!--value-->"), parse_minimal | parse_comments));
xml_node c1 = doc.first_child();
xml_node c2 = doc.last_child();
CHECK(c1 != c2);
CHECK(c1.type() == node_comment);
CHECK_STRING(c1.name(), "");
CHECK_STRING(c1.value(), "");
CHECK_STRING(c1.name(), STR(""));
CHECK_STRING(c1.value(), STR(""));
CHECK(c2.type() == node_comment);
CHECK_STRING(c2.name(), "");
CHECK_STRING(c2.value(), "value");
CHECK_STRING(c2.name(), STR(""));
CHECK_STRING(c2.value(), STR("value"));
}
TEST(parse_comments_parse_no_eol)
{
xml_document doc;
CHECK(doc.load("<!--\r\rval1\rval2\r\nval3\nval4\r\r-->", parse_minimal | parse_comments));
CHECK(doc.load(STR("<!--\r\rval1\rval2\r\nval3\nval4\r\r-->"), parse_minimal | parse_comments));
xml_node c = doc.first_child();
CHECK(c.type() == node_comment);
CHECK_STRING(c.value(), "\r\rval1\rval2\r\nval3\nval4\r\r");
CHECK_STRING(c.value(), STR("\r\rval1\rval2\r\nval3\nval4\r\r"));
}
TEST(parse_comments_parse_eol)
{
xml_document doc;
CHECK(doc.load("<!--\r\rval1\rval2\r\nval3\nval4\r\r-->", parse_minimal | parse_comments | parse_eol));
CHECK(doc.load(STR("<!--\r\rval1\rval2\r\nval3\nval4\r\r-->"), parse_minimal | parse_comments | parse_eol));
xml_node c = doc.first_child();
CHECK(c.type() == node_comment);
CHECK_STRING(c.value(), "\n\nval1\nval2\nval3\nval4\n\n");
CHECK_STRING(c.value(), STR("\n\nval1\nval2\nval3\nval4\n\n"));
}
TEST(parse_comments_error)
@ -96,57 +109,57 @@ TEST(parse_comments_error)
{
unsigned int flags = flag_sets[i];
CHECK(doc.load("<!-", flags).status == status_bad_comment);
CHECK(doc.load("<!--", flags).status == status_bad_comment);
CHECK(doc.load("<!--v", flags).status == status_bad_comment);
CHECK(doc.load("<!-->", flags).status == status_bad_comment);
CHECK(doc.load("<!--->", flags).status == status_bad_comment);
CHECK(doc.load("<!-- <!-- --><!- -->", flags).status == status_bad_comment);
CHECK(doc.load(STR("<!-"), flags).status == status_bad_comment);
CHECK(doc.load(STR("<!--"), flags).status == status_bad_comment);
CHECK(doc.load(STR("<!--v"), flags).status == status_bad_comment);
CHECK(doc.load(STR("<!-->"), flags).status == status_bad_comment);
CHECK(doc.load(STR("<!--->"), flags).status == status_bad_comment);
CHECK(doc.load(STR("<!-- <!-- --><!- -->"), flags).status == status_bad_comment);
}
}
TEST(parse_cdata_skip)
{
xml_document doc;
CHECK(doc.load("<![CDATA[]]><![CDATA[value]]>", parse_minimal));
CHECK(doc.load(STR("<![CDATA[]]><![CDATA[value]]>"), parse_minimal));
CHECK(!doc.first_child());
}
TEST(parse_cdata_parse)
{
xml_document doc;
CHECK(doc.load("<![CDATA[]]><![CDATA[value]]>", parse_minimal | parse_cdata));
CHECK(doc.load(STR("<![CDATA[]]><![CDATA[value]]>"), parse_minimal | parse_cdata));
xml_node c1 = doc.first_child();
xml_node c2 = doc.last_child();
CHECK(c1 != c2);
CHECK(c1.type() == node_cdata);
CHECK_STRING(c1.name(), "");
CHECK_STRING(c1.value(), "");
CHECK_STRING(c1.name(), STR(""));
CHECK_STRING(c1.value(), STR(""));
CHECK(c2.type() == node_cdata);
CHECK_STRING(c2.name(), "");
CHECK_STRING(c2.value(), "value");
CHECK_STRING(c2.name(), STR(""));
CHECK_STRING(c2.value(), STR("value"));
}
TEST(parse_cdata_parse_no_eol)
{
xml_document doc;
CHECK(doc.load("<![CDATA[\r\rval1\rval2\r\nval3\nval4\r\r]]>", parse_minimal | parse_cdata));
CHECK(doc.load(STR("<![CDATA[\r\rval1\rval2\r\nval3\nval4\r\r]]>"), parse_minimal | parse_cdata));
xml_node c = doc.first_child();
CHECK(c.type() == node_cdata);
CHECK_STRING(c.value(), "\r\rval1\rval2\r\nval3\nval4\r\r");
CHECK_STRING(c.value(), STR("\r\rval1\rval2\r\nval3\nval4\r\r"));
}
TEST(parse_cdata_parse_eol)
{
xml_document doc;
CHECK(doc.load("<![CDATA[\r\rval1\rval2\r\nval3\nval4\r\r]]>", parse_minimal | parse_cdata | parse_eol));
CHECK(doc.load(STR("<![CDATA[\r\rval1\rval2\r\nval3\nval4\r\r]]>"), parse_minimal | parse_cdata | parse_eol));
xml_node c = doc.first_child();
CHECK(c.type() == node_cdata);
CHECK_STRING(c.value(), "\n\nval1\nval2\nval3\nval4\n\n");
CHECK_STRING(c.value(), STR("\n\nval1\nval2\nval3\nval4\n\n"));
}
TEST(parse_cdata_error)
@ -159,28 +172,31 @@ TEST(parse_cdata_error)
{
unsigned int flags = flag_sets[i];
CHECK(doc.load("<![", flags).status == status_bad_cdata);
CHECK(doc.load("<![C", flags).status == status_bad_cdata);
CHECK(doc.load("<![CD", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDA", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDAT", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDATA", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDATA[", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDATA[]", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDATA[>", flags).status == status_bad_cdata);
CHECK(doc.load("<![CDATA[ <![CDATA[]]><![CDATA ]]>", flags).status == status_bad_cdata);
CHECK(doc.load(STR("<!["), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![C"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CD"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDA"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDAT"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA["), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[]"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[data"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[data]"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[data]]"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[>"), flags).status == status_bad_cdata);
CHECK(doc.load(STR("<![CDATA[ <![CDATA[]]><![CDATA ]]>"), flags).status == status_bad_cdata);
}
}
TEST(parse_ws_pcdata_skip)
{
xml_document doc;
CHECK(doc.load(" ", parse_minimal));
CHECK(doc.load(STR(" "), parse_minimal));
CHECK(!doc.first_child());
CHECK(doc.load("<root> <node> </node> </root>", parse_minimal));
CHECK(doc.load(STR("<root> <node> </node> </root>"), parse_minimal));
xml_node root = doc.child("root");
xml_node root = doc.child(STR("root"));
CHECK(root.first_child() == root.last_child());
CHECK(!root.first_child().first_child());
@ -189,9 +205,9 @@ TEST(parse_ws_pcdata_skip)
TEST(parse_ws_pcdata_parse)
{
xml_document doc;
CHECK(doc.load("<root> <node> </node> </root>", parse_minimal | parse_ws_pcdata));
CHECK(doc.load(STR("<root> <node> </node> </root>"), parse_minimal | parse_ws_pcdata));
xml_node root = doc.child("root");
xml_node root = doc.child(STR("root"));
xml_node c1 = root.first_child();
xml_node c2 = c1.next_sibling();
@ -200,35 +216,35 @@ TEST(parse_ws_pcdata_parse)
CHECK(c3 == root.last_child());
CHECK(c1.type() == node_pcdata);
CHECK_STRING(c1.value(), " ");
CHECK_STRING(c1.value(), STR(" "));
CHECK(c3.type() == node_pcdata);
CHECK_STRING(c3.value(), " ");
CHECK_STRING(c3.value(), STR(" "));
CHECK(c2.first_child() == c2.last_child());
CHECK(c2.first_child().type() == node_pcdata);
CHECK_STRING(c2.first_child().value(), " ");
CHECK_STRING(c2.first_child().value(), STR(" "));
}
TEST(parse_pcdata_no_eol)
{
xml_document doc;
CHECK(doc.load("<root>\r\rval1\rval2\r\nval3\nval4\r\r</root>", parse_minimal));
CHECK(doc.load(STR("<root>\r\rval1\rval2\r\nval3\nval4\r\r</root>"), parse_minimal));
CHECK_STRING(doc.child_value("root"), "\r\rval1\rval2\r\nval3\nval4\r\r");
CHECK_STRING(doc.child_value(STR("root")), STR("\r\rval1\rval2\r\nval3\nval4\r\r"));
}
TEST(parse_pcdata_eol)
{
xml_document doc;
CHECK(doc.load("<root>\r\rval1\rval2\r\nval3\nval4\r\r</root>", parse_minimal | parse_eol));
CHECK(doc.load(STR("<root>\r\rval1\rval2\r\nval3\nval4\r\r</root>"), parse_minimal | parse_eol));
CHECK_STRING(doc.child_value("root"), "\n\nval1\nval2\nval3\nval4\n\n");
CHECK_STRING(doc.child_value(STR("root")), STR("\n\nval1\nval2\nval3\nval4\n\n"));
}
TEST(parse_pcdata_skip_ext)
{
xml_document doc;
CHECK(doc.load("pre<root/>post", parse_minimal));
CHECK(doc.load(STR("pre<root/>post"), parse_minimal));
CHECK(doc.first_child() == doc.last_child());
CHECK(doc.first_child().type() == node_element);
}
@ -236,99 +252,109 @@ TEST(parse_pcdata_skip_ext)
TEST(parse_pcdata_error)
{
xml_document doc;
CHECK(doc.load("<root>pcdata", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<root>pcdata"), parse_minimal).status == status_end_element_mismatch);
}
TEST(parse_escapes_skip)
{
xml_document doc;
CHECK(doc.load("<node id='&lt;&gt;&amp;&apos;&quot;'>&lt;&gt;&amp;&apos;&quot;</node>", parse_minimal));
CHECK_STRING(doc.child("node").attribute("id").value(), "&lt;&gt;&amp;&apos;&quot;");
CHECK(doc.load(STR("<node id='&lt;&gt;&amp;&apos;&quot;'>&lt;&gt;&amp;&apos;&quot;</node>"), parse_minimal));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR("&lt;&gt;&amp;&apos;&quot;"));
}
TEST(parse_escapes_parse)
{
xml_document doc;
CHECK(doc.load("<node id='&lt;&gt;&amp;&apos;&quot;'>&lt;&gt;&amp;&apos;&quot;</node>", parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value("node"), "<>&'\"");
CHECK_STRING(doc.child("node").attribute("id").value(), "<>&'\"");
CHECK(doc.load(STR("<node id='&lt;&gt;&amp;&apos;&quot;'>&lt;&gt;&amp;&apos;&quot;</node>"), parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value(STR("node")), STR("<>&'\""));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR("<>&'\""));
}
TEST(parse_escapes_code)
{
xml_document doc;
CHECK(doc.load("<node>&#1;&#32;&#x20;</node>", parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value("node"), "\01 ");
CHECK(doc.load(STR("<node>&#1;&#32;&#x20;</node>"), parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value(STR("node")), STR("\01 "));
}
TEST(parse_escapes_unicode)
{
xml_document doc;
CHECK(doc.load("<node>&#x03B3;&#x03b3;</node>", parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value("node"), "\xce\xb3\xce\xb3");
CHECK(doc.load(STR("<node>&#x03B3;&#x03b3;&#x24B62;</node>"), parse_minimal | parse_escapes));
#ifdef PUGIXML_WCHAR_MODE
const pugi::char_t* v = doc.child_value(STR("node"));
unsigned int v2 = v[2];
size_t wcharsize = sizeof(wchar_t);
CHECK(v[0] == 0x3b3 && v[1] == 0x3b3 && (wcharsize == 2 ? v[2] == 0xd852 && v[3] == 0xdf62 : v2 == 0x24b62));
#else
CHECK_STRING(doc.child_value(STR("node")), "\xce\xb3\xce\xb3\xf0\xa4\xad\xa2");
#endif
}
TEST(parse_escapes_error)
{
xml_document doc;
CHECK(doc.load("<node>&#x03g;&#ab;&quot</node>", parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value("node"), "&#x03g;&#ab;&quot");
CHECK(doc.load(STR("<node>&#x03g;&#ab;&quot</node>"), parse_minimal | parse_escapes));
CHECK_STRING(doc.child_value(STR("node")), STR("&#x03g;&#ab;&quot"));
CHECK(!doc.load("<node id='&#x12"));
CHECK(!doc.load("<node id='&g"));
CHECK(!doc.load("<node id='&gt"));
CHECK(!doc.load("<node id='&l"));
CHECK(!doc.load("<node id='&lt"));
CHECK(!doc.load("<node id='&a"));
CHECK(!doc.load("<node id='&amp"));
CHECK(!doc.load("<node id='&apos"));
CHECK(!doc.load(STR("<node id='&#x12")));
CHECK(!doc.load(STR("<node id='&g")));
CHECK(!doc.load(STR("<node id='&gt")));
CHECK(!doc.load(STR("<node id='&l")));
CHECK(!doc.load(STR("<node id='&lt")));
CHECK(!doc.load(STR("<node id='&a")));
CHECK(!doc.load(STR("<node id='&amp")));
CHECK(!doc.load(STR("<node id='&apos")));
}
TEST(parse_attribute_spaces)
{
xml_document doc;
CHECK(doc.load("<node id1='v1' id2 ='v2' id3= 'v3' id4 = 'v4' id5 \n\r\t = \r\t\n 'v5' />", parse_minimal));
CHECK_STRING(doc.child("node").attribute("id1").value(), "v1");
CHECK_STRING(doc.child("node").attribute("id2").value(), "v2");
CHECK_STRING(doc.child("node").attribute("id3").value(), "v3");
CHECK_STRING(doc.child("node").attribute("id4").value(), "v4");
CHECK_STRING(doc.child("node").attribute("id5").value(), "v5");
CHECK(doc.load(STR("<node id1='v1' id2 ='v2' id3= 'v3' id4 = 'v4' id5 \n\r\t = \r\t\n 'v5' />"), parse_minimal));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id1")).value(), STR("v1"));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id2")).value(), STR("v2"));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id3")).value(), STR("v3"));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id4")).value(), STR("v4"));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id5")).value(), STR("v5"));
}
TEST(parse_attribute_quot)
{
xml_document doc;
CHECK(doc.load("<node id1='v1' id2=\"v2\"/>", parse_minimal));
CHECK_STRING(doc.child("node").attribute("id1").value(), "v1");
CHECK_STRING(doc.child("node").attribute("id2").value(), "v2");
CHECK(doc.load(STR("<node id1='v1' id2=\"v2\"/>"), parse_minimal));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id1")).value(), STR("v1"));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id2")).value(), STR("v2"));
}
TEST(parse_attribute_no_eol_no_wconv)
{
xml_document doc;
CHECK(doc.load("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>", parse_minimal));
CHECK_STRING(doc.child("node").attribute("id").value(), " \t\r\rval1 \rval2\r\nval3\nval4\r\r");
CHECK(doc.load(STR("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>"), parse_minimal));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR(" \t\r\rval1 \rval2\r\nval3\nval4\r\r"));
}
TEST(parse_attribute_eol_no_wconv)
{
xml_document doc;
CHECK(doc.load("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>", parse_minimal | parse_eol));
CHECK_STRING(doc.child("node").attribute("id").value(), " \t\n\nval1 \nval2\nval3\nval4\n\n");
CHECK(doc.load(STR("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>"), parse_minimal | parse_eol));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR(" \t\n\nval1 \nval2\nval3\nval4\n\n"));
}
TEST(parse_attribute_no_eol_wconv)
{
xml_document doc;
CHECK(doc.load("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>", parse_minimal | parse_wconv_attribute));
CHECK_STRING(doc.child("node").attribute("id").value(), " val1 val2 val3 val4 ");
CHECK(doc.load(STR("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>"), parse_minimal | parse_wconv_attribute));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR(" val1 val2 val3 val4 "));
}
TEST(parse_attribute_eol_wconv)
{
xml_document doc;
CHECK(doc.load("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>", parse_minimal | parse_eol | parse_wconv_attribute));
CHECK_STRING(doc.child("node").attribute("id").value(), " val1 val2 val3 val4 ");
CHECK(doc.load(STR("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>"), parse_minimal | parse_eol | parse_wconv_attribute));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR(" val1 val2 val3 val4 "));
}
TEST(parse_attribute_wnorm)
@ -339,8 +365,8 @@ TEST(parse_attribute_wnorm)
for (int wconv = 0; wconv < 2; ++wconv)
{
unsigned int flags = parse_minimal | parse_wnorm_attribute | (eol ? parse_eol : 0) | (wconv ? parse_wconv_attribute : 0);
CHECK(doc.load("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>", flags));
CHECK_STRING(doc.child("node").attribute("id").value(), "val1 val2 val3 val4");
CHECK(doc.load(STR("<node id=' \t\r\rval1 \rval2\r\nval3\nval4\r\r'/>"), flags));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR("val1 val2 val3 val4"));
}
}
@ -360,80 +386,111 @@ TEST(parse_attribute_variations)
flags |= (wconv ? parse_wconv_attribute : 0);
flags |= (escapes ? parse_escapes : 0);
CHECK(doc.load("<node id='1'/>", flags));
CHECK_STRING(doc.child("node").attribute("id").value(), "1");
CHECK(doc.load(STR("<node id='1'/>"), flags));
CHECK_STRING(doc.child(STR("node")).attribute(STR("id")).value(), STR("1"));
}
}
TEST(parse_attribute_error)
{
xml_document doc;
CHECK(doc.load("<node id/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id=/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id='/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id=\"/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id=\"'/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id='\"/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node id='\"/>", parse_minimal).status == status_bad_attribute);
CHECK(doc.load("<node #/>", parse_minimal).status == status_bad_start_element);
CHECK(doc.load("<node#/>", parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node id"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id "), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id "), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id "), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id/"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id?/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id=/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id='/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id=\"/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id=\"'/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id='\"/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node id='\"/>"), parse_minimal).status == status_bad_attribute);
CHECK(doc.load(STR("<node #/>"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node#/>"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node id1='1'id2='2'/>"), parse_minimal).status == status_bad_attribute);
}
TEST(parse_tag_single)
{
xml_document doc;
CHECK(doc.load("<node/><node /><node\n/>", parse_minimal));
CHECK_NODE(doc, "<node /><node /><node />");
CHECK(doc.load(STR("<node/><node /><node\n/>"), parse_minimal));
CHECK_NODE(doc, STR("<node /><node /><node />"));
}
TEST(parse_tag_hierarchy)
{
xml_document doc;
CHECK(doc.load("<node><n1><n2/></n1><n3><n4><n5></n5></n4></n3 \r\n></node>", parse_minimal));
CHECK_NODE(doc, "<node><n1><n2 /></n1><n3><n4><n5 /></n4></n3></node>");
CHECK(doc.load(STR("<node><n1><n2/></n1><n3><n4><n5></n5></n4></n3 \r\n></node>"), parse_minimal));
CHECK_NODE(doc, STR("<node><n1><n2 /></n1><n3><n4><n5 /></n4></n3></node>"));
}
TEST(parse_tag_error)
{
xml_document doc;
CHECK(doc.load("<", parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load("<!", parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load("<!D", parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load("<#", parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load("<node#", parse_minimal).status == status_bad_start_element);
CHECK(doc.load("<node", parse_minimal).status == status_bad_start_element);
CHECK(doc.load("<node/", parse_minimal).status == status_bad_start_element);
CHECK(doc.load("<node/ >", parse_minimal).status == status_bad_start_element);
CHECK(doc.load("</ node>", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load("</node", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load("</node ", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load("<node></ node>", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load("<node></node", parse_minimal).status == status_bad_end_element);
CHECK(doc.load("<node></node ", parse_minimal).status == status_bad_end_element);
CHECK(doc.load("<node></nodes>", parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<"), parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load(STR("<!"), parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load(STR("<!D"), parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load(STR("<#"), parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load(STR("<node#"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node/"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node /"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node / "), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node / >"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("<node/ >"), parse_minimal).status == status_bad_start_element);
CHECK(doc.load(STR("</ node>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("</node"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("</node "), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<node></ node>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<node></node"), parse_minimal).status == status_bad_end_element);
CHECK(doc.load(STR("<node></node "), parse_minimal).status == status_bad_end_element);
CHECK(doc.load(STR("<node></nodes>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<node>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<node/><"), parse_minimal).status == status_unrecognized_tag);
CHECK(doc.load(STR("<node attr='value'>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("</></node>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("</node>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("</>"), parse_minimal).status == status_end_element_mismatch);
CHECK(doc.load(STR("<node></node v>"), parse_minimal).status == status_bad_end_element);
}
TEST(parse_declaration_cases)
{
xml_document doc;
CHECK(doc.load(STR("<?xml?><?xmL?><?xMl?><?xML?><?Xml?><?XmL?><?XMl?><?XML?>"), parse_minimal | parse_pi));
CHECK(!doc.first_child());
}
TEST(parse_declaration_attr_cases)
{
xml_document doc;
CHECK(doc.load(STR("<?xml ?><?xmL ?><?xMl ?><?xML ?><?Xml ?><?XmL ?><?XMl ?><?XML ?>"), parse_minimal | parse_pi));
CHECK(!doc.first_child());
}
TEST(parse_declaration_skip)
{
xml_document doc;
CHECK(doc.load("<?xml?><?xml version='1.0'?>", parse_minimal));
CHECK(doc.load(STR("<?xml?><?xml version='1.0'?>"), parse_minimal));
CHECK(!doc.first_child());
}
TEST(parse_declaration_parse)
{
xml_document doc;
CHECK(doc.load("<?xml?><?xml version='1.0'?>", parse_minimal | parse_declaration));
CHECK(doc.load(STR("<?xml?><?xml version='1.0'?>"), parse_minimal | parse_declaration));
xml_node d1 = doc.first_child();
xml_node d2 = doc.last_child();
CHECK(d1 != d2);
CHECK(d1.type() == node_declaration);
CHECK_STRING(d1.name(), "xml");
CHECK_STRING(d1.name(), STR("xml"));
CHECK(d2.type() == node_declaration);
CHECK_STRING(d2.name(), "xml");
CHECK_STRING(d2.attribute("version").value(), "1.0");
CHECK_STRING(d2.name(), STR("xml"));
CHECK_STRING(d2.attribute(STR("version")).value(), STR("1.0"));
}
TEST(parse_declaration_error)
@ -446,38 +503,46 @@ TEST(parse_declaration_error)
{
unsigned int flags = flag_sets[i];
CHECK(doc.load("<?xml", flags).status == status_bad_pi);
CHECK(doc.load("<?xml?", flags).status == status_bad_pi);
CHECK(doc.load("<?xml>", flags).status == status_bad_pi);
CHECK(doc.load("<?xml version='1>", flags).status == status_bad_pi);
CHECK(doc.load(STR("<?xml"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?xml?"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?xml>"), flags).status == status_bad_pi);
CHECK(doc.load(STR("<?xml version='1>"), flags).status == status_bad_pi);
}
CHECK(doc.load("<?xml version='1?>", parse_minimal | parse_declaration).status == status_bad_attribute);
CHECK(doc.load(STR("<?xml version='1?>"), parse_minimal | parse_declaration).status == status_bad_attribute);
}
TEST(parse_doctype_skip)
{
xml_document doc;
CHECK(doc.load("<!DOCTYPE doc>") && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo'>") && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc SYSTEM \"foo\">") && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc PUBLIC \"foo\" 'bar'>") && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc PUBLIC \"foo'\">") && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>]>") && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc>")) && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo'>")) && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM \"foo\">")) && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc PUBLIC \"foo\" 'bar'>")) && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc PUBLIC \"foo'\">")) && !doc.first_child());
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>]>")) && !doc.first_child());
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>]><node/>"));
CHECK_NODE(doc, "<node />");
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>]><node/>")));
CHECK_NODE(doc, STR("<node />"));
}
TEST(parse_doctype_error)
{
xml_document doc;
CHECK(doc.load("<!DOCTYPE").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc SYSTEM \"foo").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc PUBLIC \"foo\" 'bar").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc PUBLIC \"foo'\"").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY").status == status_bad_doctype);
CHECK(doc.load("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>").status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM \"foo")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc PUBLIC \"foo\" 'bar")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc PUBLIC \"foo'\"")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>]")).status == status_bad_doctype);
CHECK(doc.load(STR("<!DOCTYPE doc SYSTEM 'foo' [<!ELEMENT foo 'ANY'>] ")).status == status_bad_doctype);
}
TEST(parse_empty)
{
xml_document doc;
CHECK(doc.load(STR("")) && !doc.first_child());
}

View file

@ -1,39 +1,80 @@
#ifndef PUGIXML_NO_STL
#include "common.hpp"
#include <string>
// letters taken from http://www.utf8-chartable.de/
#ifdef __DMC__
#define U_LITERALS // DMC does not understand \x01234 (it parses first three digits), but understands \u01234
#endif
inline wchar_t wchar_cast(unsigned int value)
TEST(as_wide_empty)
{
return static_cast<wchar_t>(value); // to avoid C4310 on MSVC
CHECK(as_wide("") == L"");
}
#ifndef PUGIXML_NO_STL
TEST(as_utf16)
TEST(as_wide_valid_basic)
{
// valid 1-byte, 2-byte and 3-byte inputs
#ifdef U_LITERALS
CHECK(as_utf16("?\xd0\x80\xe2\x80\xbd") == L"?\u0400\u203D");
CHECK(as_wide("?\xd0\x80\xe2\x80\xbd") == L"?\u0400\u203D");
#else
CHECK(as_utf16("?\xd0\x80\xe2\x80\xbd") == L"?\x0400\x203D");
CHECK(as_wide("?\xd0\x80\xe2\x80\xbd") == L"?\x0400\x203D");
#endif
// invalid 1-byte input
CHECK(as_utf16("\xb0") == L" ");
// valid 4-byte input
std::wstring b4 = as_utf16("\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
CHECK(b4.size() == 3 && b4[0] == wchar_cast(0x97624) && b4[1] == L' ' && b4[2] == wchar_cast(0x1003ff));
// invalid 5-byte input
std::wstring b5 = as_utf16("\xf8\nbcd");
CHECK(b5 == L" \nbcd");
}
TEST(as_utf8)
TEST(as_wide_valid_astral)
{
// valid 4-byte input
std::wstring b4 = as_wide("\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
size_t wcharsize = sizeof(wchar_t);
if (wcharsize == 4)
{
CHECK(b4.size() == 3 && b4[0] == wchar_cast(0x97624) && b4[1] == L' ' && b4[2] == wchar_cast(0x1003ff));
}
else
{
CHECK(b4.size() == 5 && b4[0] == 0xda1d && b4[1] == 0xde24 && b4[2] == L' ' && b4[3] == 0xdbc0 && b4[4] == 0xdfff);
}
}
TEST(as_wide_invalid)
{
// invalid 1-byte input
CHECK(as_wide("a\xb0") == L"a");
CHECK(as_wide("a\xb0_") == L"a_");
// invalid 2-byte input
CHECK(as_wide("a\xc0") == L"a");
CHECK(as_wide("a\xd0") == L"a");
CHECK(as_wide("a\xc0_") == L"a_");
CHECK(as_wide("a\xd0_") == L"a_");
// invalid 3-byte input
CHECK(as_wide("a\xe2\x80") == L"a");
CHECK(as_wide("a\xe2") == L"a");
CHECK(as_wide("a\xe2\x80_") == L"a_");
CHECK(as_wide("a\xe2_") == L"a_");
// invalid 4-byte input
CHECK(as_wide("a\xf2\x97\x98") == L"a");
CHECK(as_wide("a\xf2\x97") == L"a");
CHECK(as_wide("a\xf2") == L"a");
CHECK(as_wide("a\xf2\x97\x98_") == L"a_");
CHECK(as_wide("a\xf2\x97_") == L"a_");
CHECK(as_wide("a\xf2_") == L"a_");
// invalid 5-byte input
std::wstring b5 = as_wide("\xf8\nbcd");
CHECK(b5 == L"\nbcd");
}
TEST(as_utf8_empty)
{
CHECK(as_utf8(L"") == "");
}
TEST(as_utf8_valid_basic)
{
// valid 1-byte, 2-byte and 3-byte outputs
#ifdef U_LITERALS
@ -41,16 +82,56 @@ TEST(as_utf8)
#else
CHECK(as_utf8(L"?\x0400\x203D") == "?\xd0\x80\xe2\x80\xbd");
#endif
// valid 4-byte output
#if 0
// requires 4-byte wchar_t :(
CHECK(as_utf8(L"\x97624 \x1003ff") == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
#endif
}
#endif
TEST_XML(parse_bom_utf8, "\xef\xbb\xbf<node/>")
TEST(as_utf8_valid_astral)
{
CHECK_NODE(doc, "<node />");
// valid 4-byte output
size_t wcharsize = sizeof(wchar_t);
if (wcharsize == 4)
{
std::wstring s;
s.resize(3);
s[0] = wchar_cast(0x97624);
s[1] = ' ';
s[2] = wchar_cast(0x1003ff);
CHECK(as_utf8(s.c_str()) == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
}
else
{
#ifdef U_LITERALS
CHECK(as_utf8(L"\uda1d\ude24 \udbc0\udfff") == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
#else
CHECK(as_utf8(L"\xda1d\xde24 \xdbc0\xdfff") == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
#endif
}
}
TEST(as_utf8_invalid)
{
size_t wcharsize = sizeof(wchar_t);
if (wcharsize == 2)
{
// check non-terminated degenerate handling
#ifdef U_LITERALS
CHECK(as_utf8(L"a\uda1d") == "a");
CHECK(as_utf8(L"a\uda1d_") == "a_");
#else
CHECK(as_utf8(L"a\xda1d") == "a");
CHECK(as_utf8(L"a\xda1d_") == "a_");
#endif
// check incorrect leading code
#ifdef U_LITERALS
CHECK(as_utf8(L"a\ude24") == "a");
CHECK(as_utf8(L"a\ude24_") == "a_");
#else
CHECK(as_utf8(L"a\xde24") == "a");
CHECK(as_utf8(L"a\xde24_") == "a_");
#endif
}
}
#endif

View file

@ -1,95 +1,309 @@
#include "common.hpp"
#include "writer_string.hpp"
#include <string>
#include <sstream>
TEST_XML(write_simple, "<node attr='1'><child>text</child></node>")
{
CHECK_NODE_EX(doc, "<node attr=\"1\">\n<child>text</child>\n</node>\n", "", 0);
CHECK_NODE_EX(doc, STR("<node attr=\"1\">\n<child>text</child>\n</node>\n"), STR(""), 0);
}
TEST_XML(write_raw, "<node attr='1'><child>text</child></node>")
{
CHECK_NODE_EX(doc, "<node attr=\"1\"><child>text</child></node>", "", format_raw);
CHECK_NODE_EX(doc, STR("<node attr=\"1\"><child>text</child></node>"), STR(""), format_raw);
}
TEST_XML(write_indent, "<node attr='1'><child><sub>text</sub></child></node>")
{
CHECK_NODE_EX(doc, "<node attr=\"1\">\n\t<child>\n\t\t<sub>text</sub>\n\t</child>\n</node>\n", "\t", format_indent);
CHECK_NODE_EX(doc, STR("<node attr=\"1\">\n\t<child>\n\t\t<sub>text</sub>\n\t</child>\n</node>\n"), STR("\t"), format_indent);
}
TEST_XML(write_pcdata, "<node attr='1'><child><sub/>text</child></node>")
{
CHECK_NODE_EX(doc, "<node attr=\"1\">\n\t<child>\n\t\t<sub />\n\t\ttext\n\t</child>\n</node>\n", "\t", format_indent);
CHECK_NODE_EX(doc, STR("<node attr=\"1\">\n\t<child>\n\t\t<sub />\n\t\ttext\n\t</child>\n</node>\n"), STR("\t"), format_indent);
}
TEST_XML(write_cdata, "<![CDATA[value]]>")
{
CHECK_NODE(doc, "<![CDATA[value]]>");
CHECK_NODE_EX(doc, "<![CDATA[value]]>\n", "", 0);
CHECK_NODE(doc, STR("<![CDATA[value]]>"));
CHECK_NODE_EX(doc, STR("<![CDATA[value]]>\n"), STR(""), 0);
}
TEST_XML_FLAGS(write_comment, "<!--text-->", parse_default | parse_comments)
{
CHECK_NODE(doc, "<!--text-->");
CHECK_NODE_EX(doc, "<!--text-->\n", "", 0);
CHECK_NODE(doc, STR("<!--text-->"));
CHECK_NODE_EX(doc, STR("<!--text-->\n"), STR(""), 0);
}
TEST_XML_FLAGS(write_pi, "<?name value?>", parse_default | parse_pi)
{
CHECK_NODE(doc, "<?name value?>");
CHECK_NODE_EX(doc, "<?name value?>\n", "", 0);
CHECK_NODE(doc, STR("<?name value?>"));
CHECK_NODE_EX(doc, STR("<?name value?>\n"), STR(""), 0);
}
TEST_XML_FLAGS(write_declaration, "<?xml version='2.0'?>", parse_default | parse_declaration)
{
CHECK_NODE(doc, "<?xml version=\"2.0\"?>");
CHECK_NODE_EX(doc, "<?xml version=\"2.0\"?>\n", "", 0);
CHECK_NODE(doc, STR("<?xml version=\"2.0\"?>"));
CHECK_NODE_EX(doc, STR("<?xml version=\"2.0\"?>\n"), STR(""), 0);
}
TEST_XML(write_escape, "<node attr=''>text</node>")
{
doc.child("node").attribute("attr") = "<>'\"&\x04\r\n\t";
doc.child("node").first_child().set_value("<>'\"&\x04\r\n\t");
doc.child(STR("node")).attribute(STR("attr")) = STR("<>'\"&\x04\r\n\t");
doc.child(STR("node")).first_child().set_value(STR("<>'\"&\x04\r\n\t"));
CHECK_NODE(doc, "<node attr=\"&lt;&gt;'&quot;&amp;&#4;&#13;&#10;\t\">&lt;&gt;'\"&amp;&#4;\r\n\t</node>");
CHECK_NODE(doc, STR("<node attr=\"&lt;&gt;'&quot;&amp;&#04;&#13;&#10;\t\">&lt;&gt;'\"&amp;&#04;\r\n\t</node>"));
}
TEST_XML(write_escape_unicode, "<node attr='&#x3c00;'/>")
{
#ifdef PUGIXML_WCHAR_MODE
#ifdef U_LITERALS
CHECK_NODE(doc, STR("<node attr=\"\u3c00\" />"));
#else
CHECK_NODE(doc, STR("<node attr=\"\x3c00\" />"));
#endif
#else
CHECK_NODE(doc, STR("<node attr=\"\xe3\xb0\x80\" />"));
#endif
}
struct test_writer: xml_writer
{
std::string contents;
std::basic_string<pugi::char_t> contents;
virtual void write(const void* data, size_t size)
{
contents += std::string(static_cast<const char*>(data), static_cast<const char*>(data) + size);
CHECK(size % sizeof(pugi::char_t) == 0);
contents += std::basic_string<pugi::char_t>(static_cast<const pugi::char_t*>(data), static_cast<const pugi::char_t*>(data) + size / sizeof(pugi::char_t));
}
};
TEST_XML(write_print_writer, "<node/>")
{
test_writer writer;
doc.print(writer);
doc.print(writer, STR(""), format_default, get_native_encoding());
CHECK(writer.contents == "<node />\n");
CHECK(writer.contents == STR("<node />\n"));
}
#ifndef PUGIXML_NO_STL
TEST_XML(write_print_stream, "<node/>")
{
std::ostringstream oss;
doc.print(oss);
doc.print(oss, STR(""), format_default, encoding_utf8);
CHECK(oss.str() == "<node />\n");
}
TEST_XML(write_print_stream_encode, "<n/>")
{
std::ostringstream oss;
doc.print(oss, STR(""), format_default, encoding_utf16_be);
CHECK(oss.str() == std::string("\x00<\x00n\x00 \x00/\x00>\x00\n", 12));
}
TEST_XML(write_print_stream_wide, "<node/>")
{
std::basic_ostringstream<wchar_t> oss;
doc.print(oss, STR(""), format_default, encoding_utf8);
CHECK(oss.str() == L"<node />\n");
}
#endif
TEST_XML(write_huge_chunk, "<node/>")
{
std::string name(10000, 'n');
doc.child("node").set_name(name.c_str());
std::basic_string<pugi::char_t> name(10000, STR('n'));
doc.child(STR("node")).set_name(name.c_str());
test_writer writer;
doc.print(writer);
doc.print(writer, STR(""), format_default, get_native_encoding());
CHECK(writer.contents == "<" + name + " />\n");
CHECK(writer.contents == STR("<") + name + STR(" />\n"));
}
TEST(write_encodings)
{
static char s_utf8[] = "<\x54\xC2\xA2\xE2\x82\xAC\xF0\xA4\xAD\xA2/>";
xml_document doc;
CHECK(doc.load_buffer(s_utf8, sizeof(s_utf8), parse_default, encoding_utf8));
CHECK(write_narrow(doc, format_default, encoding_utf8) == "<\x54\xC2\xA2\xE2\x82\xAC\xF0\xA4\xAD\xA2 />\n");
CHECK(test_write_narrow(doc, format_default, encoding_utf32_le, "<\x00\x00\x00\x54\x00\x00\x00\xA2\x00\x00\x00\xAC\x20\x00\x00\x62\x4B\x02\x00 \x00\x00\x00/\x00\x00\x00>\x00\x00\x00\n\x00\x00\x00", 36));
CHECK(test_write_narrow(doc, format_default, encoding_utf32_be, "\x00\x00\x00<\x00\x00\x00\x54\x00\x00\x00\xA2\x00\x00\x20\xAC\x00\x02\x4B\x62\x00\x00\x00 \x00\x00\x00/\x00\x00\x00>\x00\x00\x00\n", 36));
CHECK(write_narrow(doc, format_default, encoding_utf32) == write_narrow(doc, format_default, is_little_endian() ? encoding_utf32_le : encoding_utf32_be));
CHECK(test_write_narrow(doc, format_default, encoding_utf16_le, "<\x00\x54\x00\xA2\x00\xAC\x20\x52\xd8\x62\xdf \x00/\x00>\x00\n\x00", 20));
CHECK(test_write_narrow(doc, format_default, encoding_utf16_be, "\x00<\x00\x54\x00\xA2\x20\xAC\xd8\x52\xdf\x62\x00 \x00/\x00>\x00\n", 20));
CHECK(write_narrow(doc, format_default, encoding_utf16) == write_narrow(doc, format_default, is_little_endian() ? encoding_utf16_le : encoding_utf16_be));
size_t wcharsize = sizeof(wchar_t);
std::wstring v = write_wide(doc, format_default, encoding_wchar);
if (wcharsize == 4)
{
CHECK(v.size() == 9 && v[0] == '<' && v[1] == 0x54 && v[2] == 0xA2 && v[3] == 0x20AC && v[4] == wchar_cast(0x24B62) && v[5] == ' ' && v[6] == '/' && v[7] == '>' && v[8] == '\n');
}
else
{
CHECK(v.size() == 10 && v[0] == '<' && v[1] == 0x54 && v[2] == 0xA2 && v[3] == 0x20AC && v[4] == 0xd852 && v[5] == 0xdf62 && v[6] == ' ' && v[7] == '/' && v[8] == '>' && v[9] == '\n');
}
}
#ifdef PUGIXML_WCHAR_MODE
TEST(write_encoding_huge)
{
const unsigned int N = 16000;
// make a large utf16 name consisting of 6-byte char pairs (6 does not divide internal buffer size, so will need split correction)
std::string s_utf16 = std::string("\x00<", 2);
for (unsigned int i = 0; i < N; ++i) s_utf16 += "\x20\xAC\xd8\x52\xdf\x62";
s_utf16 += std::string("\x00/\x00>", 4);
xml_document doc;
CHECK(doc.load_buffer(&s_utf16[0], s_utf16.length(), parse_default, encoding_utf16_be));
std::string s_utf8 = "<";
for (unsigned int j = 0; j < N; ++j) s_utf8 += "\xE2\x82\xAC\xF0\xA4\xAD\xA2";
s_utf8 += " />\n";
CHECK(test_write_narrow(doc, format_default, encoding_utf8, s_utf8.c_str(), s_utf8.length()));
}
#else
TEST(write_encoding_huge)
{
const unsigned int N = 16000;
// make a large utf8 name consisting of 3-byte chars (3 does not divide internal buffer size, so will need split correction)
std::string s_utf8 = "<";
for (unsigned int i = 0; i < N; ++i) s_utf8 += "\xE2\x82\xAC";
s_utf8 += "/>";
xml_document doc;
CHECK(doc.load_buffer(&s_utf8[0], s_utf8.length(), parse_default, encoding_utf8));
std::string s_utf16 = std::string("\x00<", 2);
for (unsigned int j = 0; j < N; ++j) s_utf16 += "\x20\xAC";
s_utf16 += std::string("\x00 \x00/\x00>\x00\n", 8);
CHECK(test_write_narrow(doc, format_default, encoding_utf16_be, s_utf16.c_str(), s_utf16.length()));
}
TEST(write_encoding_huge_invalid)
{
const unsigned int N = 16000;
// make a large utf8 name consisting of non-leading chars
std::string s_utf8 = "<";
for (unsigned int i = 0; i < N; ++i) s_utf8 += "\x82";
s_utf8 += "/>";
xml_document doc;
CHECK(doc.load_buffer(&s_utf8[0], s_utf8.length(), parse_default, encoding_utf8));
std::string s_utf16 = std::string("\x00<\x00 \x00/\x00>\x00\n", 10);
CHECK(test_write_narrow(doc, format_default, encoding_utf16_be, s_utf16.c_str(), s_utf16.length()));
}
#endif
TEST(write_unicode_escape)
{
char s_utf8[] = "<\xE2\x82\xAC \xC2\xA2='\"\xF0\xA4\xAD\xA2&#x0a;\"'>&amp;\x14\xF0\xA4\xAD\xA2&lt;</\xE2\x82\xAC>";
xml_document doc;
CHECK(doc.load_buffer(s_utf8, sizeof(s_utf8), parse_default, encoding_utf8));
CHECK(write_narrow(doc, format_default, encoding_utf8) == "<\xE2\x82\xAC \xC2\xA2=\"&quot;\xF0\xA4\xAD\xA2&#10;&quot;\">&amp;&#20;\xF0\xA4\xAD\xA2&lt;</\xE2\x82\xAC>\n");
}
#ifdef PUGIXML_WCHAR_MODE
static bool test_write_unicode_invalid(const wchar_t* name, const char* expected)
{
xml_document doc;
doc.append_child(node_pcdata).set_value(name);
return write_narrow(doc, format_raw, encoding_utf8) == expected;
}
TEST(write_unicode_invalid_utf16)
{
size_t wcharsize = sizeof(wchar_t);
if (wcharsize == 2)
{
// check non-terminated degenerate handling
#ifdef U_LITERALS
CHECK(test_write_unicode_invalid(L"a\uda1d", "a"));
CHECK(test_write_unicode_invalid(L"a\uda1d_", "a_"));
#else
CHECK(test_write_unicode_invalid(L"a\xda1d", "a"));
CHECK(test_write_unicode_invalid(L"a\xda1d_", "a_"));
#endif
// check incorrect leading code
#ifdef U_LITERALS
CHECK(test_write_unicode_invalid(L"a\ude24", "a"));
CHECK(test_write_unicode_invalid(L"a\ude24_", "a_"));
#else
CHECK(test_write_unicode_invalid(L"a\xde24", "a"));
CHECK(test_write_unicode_invalid(L"a\xde24_", "a_"));
#endif
}
}
#else
static bool test_write_unicode_invalid(const char* name, const wchar_t* expected)
{
xml_document doc;
doc.append_child(node_pcdata).set_value(name);
return write_wide(doc, format_raw, encoding_wchar) == expected;
}
TEST(write_unicode_invalid_utf8)
{
// invalid 1-byte input
CHECK(test_write_unicode_invalid("a\xb0", L"a"));
CHECK(test_write_unicode_invalid("a\xb0_", L"a_"));
// invalid 2-byte input
CHECK(test_write_unicode_invalid("a\xc0", L"a"));
CHECK(test_write_unicode_invalid("a\xd0", L"a"));
CHECK(test_write_unicode_invalid("a\xc0_", L"a_"));
CHECK(test_write_unicode_invalid("a\xd0_", L"a_"));
// invalid 3-byte input
CHECK(test_write_unicode_invalid("a\xe2\x80", L"a"));
CHECK(test_write_unicode_invalid("a\xe2", L"a"));
CHECK(test_write_unicode_invalid("a\xe2\x80_", L"a_"));
CHECK(test_write_unicode_invalid("a\xe2_", L"a_"));
// invalid 4-byte input
CHECK(test_write_unicode_invalid("a\xf2\x97\x98", L"a"));
CHECK(test_write_unicode_invalid("a\xf2\x97", L"a"));
CHECK(test_write_unicode_invalid("a\xf2", L"a"));
CHECK(test_write_unicode_invalid("a\xf2\x97\x98_", L"a_"));
CHECK(test_write_unicode_invalid("a\xf2\x97_", L"a_"));
CHECK(test_write_unicode_invalid("a\xf2_", L"a_"));
// invalid 5-byte input
CHECK(test_write_unicode_invalid("a\xf8_", L"a_"));
}
#endif

View file

@ -2,46 +2,52 @@
#include "common.hpp"
#include <float.h>
#include <string.h>
#include <wchar.h>
#include <string>
TEST_XML(xpath_document_order, "<node><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2></node>")
{
CHECK(xml_node().document_order() == 0);
CHECK(doc.child("node").document_order() == 0);
CHECK(doc.child(STR("node")).document_order() == 0);
CHECK(doc.document_order() == 0);
doc.precompute_document_order();
CHECK(doc.document_order() == 1);
CHECK(doc.child("node").document_order() == 2);
CHECK(doc.child("node").child("child1").document_order() == 3);
CHECK(doc.child("node").child("child1").attribute("attr1").document_order() == 4);
CHECK(doc.child("node").child("child1").attribute("attr2").document_order() == 5);
CHECK(doc.child("node").child("child2").document_order() == 6);
CHECK(doc.child("node").child("child2").attribute("attr1").document_order() == 7);
CHECK(doc.child("node").child("child2").first_child().document_order() == 8);
CHECK(doc.child(STR("node")).document_order() == 2);
CHECK(doc.child(STR("node")).child(STR("child1")).document_order() == 3);
CHECK(doc.child(STR("node")).child(STR("child1")).attribute(STR("attr1")).document_order() == 4);
CHECK(doc.child(STR("node")).child(STR("child1")).attribute(STR("attr2")).document_order() == 5);
CHECK(doc.child(STR("node")).child(STR("child2")).document_order() == 6);
CHECK(doc.child(STR("node")).child(STR("child2")).attribute(STR("attr1")).document_order() == 7);
CHECK(doc.child(STR("node")).child(STR("child2")).first_child().document_order() == 8);
}
TEST(xpath_allocator_many_pages)
{
std::string query = "0";
pugi::string_t query = STR("0");
for (int i = 0; i < 128; ++i) query += "+string-length('abcdefgh')";
for (int i = 0; i < 128; ++i) query += STR("+string-length('abcdefgh')");
CHECK_XPATH_NUMBER(xml_node(), query.c_str(), 1024);
}
TEST(xpath_allocator_large_page)
{
std::string query;
pugi::string_t query;
for (int i = 0; i < 1024; ++i) query += "abcdefgh";
for (int i = 0; i < 1024; ++i) query += STR("abcdefgh");
CHECK_XPATH_NUMBER(xml_node(), ("string-length('" + query + "')").c_str(), 8192);
CHECK_XPATH_NUMBER(xml_node(), (STR("string-length('") + query + STR("')")).c_str(), 8192);
}
TEST_XML(xpath_sort_complex, "<node><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2></node>")
{
// just some random union order, it should not matter probably?
xpath_node_set ns = doc.child("node").select_nodes("child1 | child2 | child1/@* | . | child2/@* | child2/text()");
xpath_node_set ns = doc.child(STR("node")).select_nodes(STR("child1 | child2 | child1/@* | . | child2/@* | child2/text()"));
ns.sort(false);
xpath_node_set sorted = ns;
@ -57,7 +63,7 @@ TEST_XML(xpath_sort_complex, "<node><child1 attr1='value1' attr2='value2'/><chil
TEST_XML(xpath_sort_children, "<node><child><subchild id='1'/></child><child><subchild id='2'/></child></node>")
{
xpath_node_set ns = doc.child("node").select_nodes("child/subchild[@id=1] | child/subchild[@id=2]");
xpath_node_set ns = doc.child(STR("node")).select_nodes(STR("child/subchild[@id=1] | child/subchild[@id=2]"));
ns.sort(false);
xpath_node_set sorted = ns;
@ -73,15 +79,15 @@ TEST_XML(xpath_sort_children, "<node><child><subchild id='1'/></child><child><su
TEST_XML(xpath_sort_attributes, "<node/>")
{
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// we need to insert attributes manually since unsorted node sets are (always?) sorted via pointers because of remove_duplicates,
// so we need to have different document and pointer order to cover all comparator cases
n.append_attribute("attr2");
n.append_attribute("attr3");
n.insert_attribute_before("attr1", n.attribute("attr2"));
n.append_attribute(STR("attr2"));
n.append_attribute(STR("attr3"));
n.insert_attribute_before(STR("attr1"), n.attribute(STR("attr2")));
xpath_node_set ns = n.select_nodes("@*");
xpath_node_set ns = n.select_nodes(STR("@*"));
ns.sort(true);
xpath_node_set reverse_sorted = ns;
@ -95,4 +101,54 @@ TEST_XML(xpath_sort_attributes, "<node/>")
xpath_node_set_tester(reverse_sorted, "reverse sorted order failed") % 5 % 4 % 3;
}
TEST(xpath_long_numbers_parse)
{
const pugi::char_t* str_flt_max = STR("340282346638528860000000000000000000000");
const pugi::char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000");
const pugi::char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
const pugi::char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000");
xml_node c;
// check parsing
CHECK_XPATH_NUMBER(c, str_flt_max, FLT_MAX);
CHECK_XPATH_NUMBER(c, str_flt_max_dec, FLT_MAX);
CHECK_XPATH_NUMBER(c, str_dbl_max, DBL_MAX);
CHECK_XPATH_NUMBER(c, str_dbl_max_dec, DBL_MAX);
}
static bool test_xpath_string_prefix(const pugi::xml_node& node, const pugi::char_t* query, const pugi::char_t* expected, size_t match_length)
{
#ifdef PUGIXML_WCHAR_MODE
size_t expected_length = wcslen(expected);
#else
size_t expected_length = strlen(expected);
#endif
pugi::xpath_query q(query);
pugi::string_t value = q.evaluate_string(node);
return value.length() == expected_length && value.compare(0, match_length, expected, match_length) == 0;
}
TEST(xpath_long_numbers_stringize)
{
const pugi::char_t* str_flt_max = STR("340282346638528860000000000000000000000");
const pugi::char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000");
const pugi::char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
const pugi::char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000");
xml_node c;
CHECK(test_xpath_string_prefix(c, str_flt_max, str_flt_max, 16));
CHECK(test_xpath_string_prefix(c, str_flt_max_dec, str_flt_max, 16));
#ifndef __BORLANDC__ // printf with %f format still results in 1.xxxe+308 form
CHECK(test_xpath_string_prefix(c, str_dbl_max, str_dbl_max, 16));
CHECK(test_xpath_string_prefix(c, str_dbl_max_dec, str_dbl_max, 16));
#endif
}
#endif

View file

@ -4,13 +4,15 @@
#include "helpers.hpp"
#include <string>
TEST_XML(xpath_api_select_nodes, "<node><head/><foo/><foo/><tail/></node>")
{
doc.precompute_document_order();
xpath_node_set ns1 = doc.select_nodes("node/foo");
xpath_node_set ns1 = doc.select_nodes(STR("node/foo"));
xpath_query q("node/foo");
xpath_query q(STR("node/foo"));
xpath_node_set ns2 = doc.select_nodes(q);
CHECK(ns1.size() == 2 && ns1[0].node().document_order() == 4 && ns1[1].node().document_order() == 5);
@ -21,20 +23,20 @@ TEST_XML(xpath_api_select_single_node, "<node><head/><foo/><foo/><tail/></node>"
{
doc.precompute_document_order();
xpath_node n1 = doc.select_single_node("node/foo");
xpath_node n1 = doc.select_single_node(STR("node/foo"));
xpath_query q("node/foo");
xpath_query q(STR("node/foo"));
xpath_node n2 = doc.select_single_node(q);
CHECK(n1.node().document_order() == 4);
CHECK(n2.node().document_order() == 4);
xpath_node n3 = doc.select_single_node("node/bar");
xpath_node n3 = doc.select_single_node(STR("node/bar"));
CHECK(!n3);
xpath_node n4 = doc.select_single_node("node/head/following-sibling::foo");
xpath_node n5 = doc.select_single_node("node/tail/preceding-sibling::foo");
xpath_node n4 = doc.select_single_node(STR("node/head/following-sibling::foo"));
xpath_node n5 = doc.select_single_node(STR("node/tail/preceding-sibling::foo"));
CHECK(n4.node().document_order() == 4);
CHECK(n5.node().document_order() == 4);
@ -44,7 +46,7 @@ TEST(xpath_api_exception_what)
{
try
{
xpath_query q("");
xpath_query q(STR(""));
}
catch (const xpath_exception& e)
{
@ -54,32 +56,32 @@ TEST(xpath_api_exception_what)
TEST_XML(xpath_api_node_bool_ops, "<node attr='value'/>")
{
generic_bool_ops_test(doc.select_single_node("node"));
generic_bool_ops_test(doc.select_single_node("node/@attr"));
generic_bool_ops_test(doc.select_single_node(STR("node")));
generic_bool_ops_test(doc.select_single_node(STR("node/@attr")));
}
TEST_XML(xpath_api_node_eq_ops, "<node attr='value'/>")
{
generic_eq_ops_test(doc.select_single_node("node"), doc.select_single_node("node/@attr"));
generic_eq_ops_test(doc.select_single_node(STR("node")), doc.select_single_node(STR("node/@attr")));
}
TEST_XML(xpath_api_node_accessors, "<node attr='value'/>")
{
xpath_node null;
xpath_node node = doc.select_single_node("node");
xpath_node attr = doc.select_single_node("node/@attr");
xpath_node node = doc.select_single_node(STR("node"));
xpath_node attr = doc.select_single_node(STR("node/@attr"));
CHECK(!null.node());
CHECK(!null.attribute());
CHECK(!null.parent());
CHECK(node.node() == doc.child("node"));
CHECK(node.node() == doc.child(STR("node")));
CHECK(!node.attribute());
CHECK(node.parent() == doc);
CHECK(!attr.node());
CHECK(attr.attribute() == doc.child("node").attribute("attr"));
CHECK(attr.parent() == doc.child("node"));
CHECK(attr.attribute() == doc.child(STR("node")).attribute(STR("attr")));
CHECK(attr.parent() == doc.child(STR("node")));
}
inline void xpath_api_node_accessors_helper(const xpath_node_set& set)
@ -87,8 +89,8 @@ inline void xpath_api_node_accessors_helper(const xpath_node_set& set)
CHECK(set.size() == 2);
CHECK(set.type() == xpath_node_set::type_sorted);
CHECK(!set.empty());
CHECK_STRING(set[0].node().name(), "foo");
CHECK_STRING(set[1].node().name(), "foo");
CHECK_STRING(set[0].node().name(), STR("foo"));
CHECK_STRING(set[1].node().name(), STR("foo"));
CHECK(!set[2]);
CHECK(set.first() == set[0]);
CHECK(set.begin() + 2 == set.end());
@ -105,7 +107,7 @@ TEST_XML(xpath_api_nodeset_accessors, "<node><foo/><foo/></node>")
CHECK(!null.first());
CHECK(null.begin() == null.end());
xpath_node_set set = doc.select_nodes("node/foo");
xpath_node_set set = doc.select_nodes(STR("node/foo"));
xpath_api_node_accessors_helper(set);
xpath_node_set copy = set;
@ -120,21 +122,21 @@ TEST_XML(xpath_api_nodeset_accessors, "<node><foo/><foo/></node>")
TEST_XML(xpath_api_evaluate, "<node attr='3'/>")
{
xpath_query q("node/@attr");
xpath_query q(STR("node/@attr"));
CHECK(q.evaluate_boolean(doc));
CHECK(q.evaluate_number(doc) == 3);
CHECK(q.evaluate_string(doc) == "3");
CHECK(q.evaluate_string(doc) == STR("3"));
xpath_node_set ns = q.evaluate_node_set(doc);
CHECK(ns.size() == 1 && ns[0].attribute() == doc.child("node").attribute("attr"));
CHECK(ns.size() == 1 && ns[0].attribute() == doc.child(STR("node")).attribute(STR("attr")));
}
TEST(xpath_api_evaluate_node_set)
{
try
{
xpath_query q("1");
xpath_query q(STR("1"));
q.evaluate_node_set(xml_node());
}
@ -145,10 +147,10 @@ TEST(xpath_api_evaluate_node_set)
TEST(xpath_api_return_type)
{
CHECK(xpath_query("node").return_type() == xpath_type_node_set);
CHECK(xpath_query("1").return_type() == xpath_type_number);
CHECK(xpath_query("'s'").return_type() == xpath_type_string);
CHECK(xpath_query("true()").return_type() == xpath_type_boolean);
CHECK(xpath_query(STR("node")).return_type() == xpath_type_node_set);
CHECK(xpath_query(STR("1")).return_type() == xpath_type_number);
CHECK(xpath_query(STR("'s'")).return_type() == xpath_type_string);
CHECK(xpath_query(STR("true()")).return_type() == xpath_type_boolean);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -17,65 +17,65 @@
TEST_XML(xpath_operators_arithmetic, "<node><foo-bar>10</foo-bar><foo>2</foo><bar>3</bar></node>")
{
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// incorrect unary operator
CHECK_XPATH_FAIL("-");
CHECK_XPATH_FAIL(STR("-"));
// correct unary operator
CHECK_XPATH_NUMBER(c, "-1", -1);
CHECK_XPATH_NUMBER(c, "--1", 1);
CHECK_XPATH_NUMBER(c, "---1", -1);
CHECK_XPATH_NUMBER(c, STR("-1"), -1);
CHECK_XPATH_NUMBER(c, STR("--1"), 1);
CHECK_XPATH_NUMBER(c, STR("---1"), -1);
// incorrect binary operators
CHECK_XPATH_FAIL("5+");
CHECK_XPATH_FAIL("5-");
CHECK_XPATH_FAIL("5*");
CHECK_XPATH_FAIL("+5");
CHECK_XPATH_FAIL("*5");
CHECK_XPATH_FAIL("1div2");
CHECK_XPATH_FAIL("1mod");
CHECK_XPATH_FAIL("1div");
CHECK_XPATH_FAIL(STR("5+"));
CHECK_XPATH_FAIL(STR("5-"));
CHECK_XPATH_FAIL(STR("5*"));
CHECK_XPATH_FAIL(STR("+5"));
CHECK_XPATH_FAIL(STR("*5"));
CHECK_XPATH_FAIL(STR("1div2"));
CHECK_XPATH_FAIL(STR("1mod"));
CHECK_XPATH_FAIL(STR("1div"));
// correct trivial binary operators
CHECK_XPATH_NUMBER(c, "1 + 2", 3);
CHECK_XPATH_NUMBER(c, "1+2", 3);
CHECK_XPATH_NUMBER(c, "1 * 2", 2);
CHECK_XPATH_NUMBER(c, "1*2", 2);
CHECK_XPATH_NUMBER(c, "1 div 2", 0.5);
CHECK_XPATH_NUMBER(c, STR("1 + 2"), 3);
CHECK_XPATH_NUMBER(c, STR("1+2"), 3);
CHECK_XPATH_NUMBER(c, STR("1 * 2"), 2);
CHECK_XPATH_NUMBER(c, STR("1*2"), 2);
CHECK_XPATH_NUMBER(c, STR("1 div 2"), 0.5);
// operator precedence
CHECK_XPATH_NUMBER(c, "2 + 2 * 2 div 1 mod 3", 3);
CHECK_XPATH_NUMBER(c, "2 + 2 * 2 div (1 mod 3)", 6);
CHECK_XPATH_NUMBER(c, "(2 + 2) * 2 div (1 mod 3)", 8);
CHECK_XPATH_NUMBER(c, "(2 + 2) * (2 div 1) mod 3", 2);
CHECK_XPATH_NUMBER(c, "2 - -2", 4);
CHECK_XPATH_NUMBER(c, "2--2", 4);
CHECK_XPATH_NUMBER(c, "1-2-3", -4);
CHECK_XPATH_NUMBER(c, STR("2 + 2 * 2 div 1 mod 3"), 3);
CHECK_XPATH_NUMBER(c, STR("2 + 2 * 2 div (1 mod 3)"), 6);
CHECK_XPATH_NUMBER(c, STR("(2 + 2) * 2 div (1 mod 3)"), 8);
CHECK_XPATH_NUMBER(c, STR("(2 + 2) * (2 div 1) mod 3"), 2);
CHECK_XPATH_NUMBER(c, STR("2 - -2"), 4);
CHECK_XPATH_NUMBER(c, STR("2--2"), 4);
CHECK_XPATH_NUMBER(c, STR("1-2-3"), -4);
// infinity/nan
CHECK_XPATH_STRING(c, "1 div 0", "Infinity");
CHECK_XPATH_STRING(c, "-1 div 0", "-Infinity");
CHECK_XPATH_STRING(c, "-1 div 0 + 1 div 0", "NaN");
CHECK_XPATH_STRING(c, "0 div 0", "NaN");
CHECK_XPATH_STRING(c, "1 div 0 + 1 div 0", "Infinity");
CHECK_XPATH_STRING(c, "-1 div 0 + -1 div 0", "-Infinity");
CHECK_XPATH_STRING(c, "1 div 0 + 100", "Infinity");
CHECK_XPATH_STRING(c, "-1 div 0 + 100", "-Infinity");
CHECK_XPATH_STRING(c, "0 div 0 + 100", "NaN");
CHECK_XPATH_STRING(c, STR("1 div 0"), STR("Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div 0"), STR("-Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div 0 + 1 div 0"), STR("NaN"));
CHECK_XPATH_STRING(c, STR("0 div 0"), STR("NaN"));
CHECK_XPATH_STRING(c, STR("1 div 0 + 1 div 0"), STR("Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div 0 + -1 div 0"), STR("-Infinity"));
CHECK_XPATH_STRING(c, STR("1 div 0 + 100"), STR("Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div 0 + 100"), STR("-Infinity"));
CHECK_XPATH_STRING(c, STR("0 div 0 + 100"), STR("NaN"));
// mod, from W3C standard
CHECK_XPATH_NUMBER(c, "5 mod 2", 1);
CHECK_XPATH_NUMBER(c, "5 mod -2", 1);
CHECK_XPATH_NUMBER(c, "-5 mod 2", -1);
CHECK_XPATH_NUMBER(c, "-5 mod -2", -1);
CHECK_XPATH_NUMBER(c, STR("5 mod 2"), 1);
CHECK_XPATH_NUMBER(c, STR("5 mod -2"), 1);
CHECK_XPATH_NUMBER(c, STR("-5 mod 2"), -1);
CHECK_XPATH_NUMBER(c, STR("-5 mod -2"), -1);
// correct subtraction parsing, from W3C standard
CHECK_XPATH_NUMBER(n, "foo-bar", 10);
CHECK_XPATH_NUMBER(n, "foo -bar", -1);
CHECK_XPATH_NUMBER(n, "foo - bar", -1);
CHECK_XPATH_NUMBER(n, "-foo-bar", -10);
CHECK_XPATH_NUMBER(n, "-foo -bar", -5);
CHECK_XPATH_NUMBER(n, STR("foo-bar"), 10);
CHECK_XPATH_NUMBER(n, STR("foo -bar"), -1);
CHECK_XPATH_NUMBER(n, STR("foo - bar"), -1);
CHECK_XPATH_NUMBER(n, STR("-foo-bar"), -10);
CHECK_XPATH_NUMBER(n, STR("-foo -bar"), -5);
}
TEST(xpath_operators_logical)
@ -83,21 +83,21 @@ TEST(xpath_operators_logical)
xml_node c;
// boolean arithmetic
CHECK_XPATH_BOOLEAN(c, "true() or true()", true);
CHECK_XPATH_BOOLEAN(c, "true() or false()", true);
CHECK_XPATH_BOOLEAN(c, "false() or false()", false);
CHECK_XPATH_BOOLEAN(c, "false() or true()", true);
CHECK_XPATH_BOOLEAN(c, STR("true() or true()"), true);
CHECK_XPATH_BOOLEAN(c, STR("true() or false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("false() or false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() or true()"), true);
CHECK_XPATH_BOOLEAN(c, "true() and true()", true);
CHECK_XPATH_BOOLEAN(c, "true() and false()", false);
CHECK_XPATH_BOOLEAN(c, "false() and false()", false);
CHECK_XPATH_BOOLEAN(c, "false() and true()", false);
CHECK_XPATH_BOOLEAN(c, STR("true() and true()"), true);
CHECK_XPATH_BOOLEAN(c, STR("true() and false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() and false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() and true()"), false);
// boolean conversion
CHECK_XPATH_BOOLEAN(c, "1 or ''", true);
CHECK_XPATH_BOOLEAN(c, "1 and ''", false);
CHECK_XPATH_BOOLEAN(c, "0 or ''", false);
CHECK_XPATH_BOOLEAN(c, "0 or 'a'", true);
CHECK_XPATH_BOOLEAN(c, STR("1 or ''"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 and ''"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 or ''"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 or 'a'"), true);
}
TEST(xpath_operators_equality_primitive_boolean)
@ -105,25 +105,25 @@ TEST(xpath_operators_equality_primitive_boolean)
xml_node c;
// boolean vs boolan
CHECK_XPATH_BOOLEAN(c, "true() = true()", true);
CHECK_XPATH_BOOLEAN(c, "false() = false()", true);
CHECK_XPATH_BOOLEAN(c, "true() != false()", true);
CHECK_XPATH_BOOLEAN(c, "false() != false()", false);
CHECK_XPATH_BOOLEAN(c, STR("true() = true()"), true);
CHECK_XPATH_BOOLEAN(c, STR("false() = false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("true() != false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("false() != false()"), false);
// upcast to boolean
CHECK_XPATH_BOOLEAN(c, "true() = 2", true);
CHECK_XPATH_BOOLEAN(c, "true() != 2", false);
CHECK_XPATH_BOOLEAN(c, "false() = 2", false);
CHECK_XPATH_BOOLEAN(c, "false() != 2", true);
CHECK_XPATH_BOOLEAN(c, "false() = 0", true);
CHECK_XPATH_BOOLEAN(c, "false() != 0", false);
CHECK_XPATH_BOOLEAN(c, STR("true() = 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("true() != 2"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() = 2"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() != 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("false() = 0"), true);
CHECK_XPATH_BOOLEAN(c, STR("false() != 0"), false);
CHECK_XPATH_BOOLEAN(c, "2 = true()", true);
CHECK_XPATH_BOOLEAN(c, "2 != true()", false);
CHECK_XPATH_BOOLEAN(c, "2 = false()", false);
CHECK_XPATH_BOOLEAN(c, "2 != false()", true);
CHECK_XPATH_BOOLEAN(c, "0 = false()", true);
CHECK_XPATH_BOOLEAN(c, "0 != false()", false);
CHECK_XPATH_BOOLEAN(c, STR("2 = true()"), true);
CHECK_XPATH_BOOLEAN(c, STR("2 != true()"), false);
CHECK_XPATH_BOOLEAN(c, STR("2 = false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("2 != false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("0 = false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("0 != false()"), false);
}
TEST(xpath_operators_equality_primitive_number)
@ -131,26 +131,26 @@ TEST(xpath_operators_equality_primitive_number)
xml_node c;
// number vs number
CHECK_XPATH_BOOLEAN(c, "1 = 1", true);
CHECK_XPATH_BOOLEAN(c, "0.5 = 0.5", true);
CHECK_XPATH_BOOLEAN(c, "1 != 2", true);
CHECK_XPATH_BOOLEAN(c, "1 = -1", false);
CHECK_XPATH_BOOLEAN(c, STR("1 = 1"), true);
CHECK_XPATH_BOOLEAN(c, STR("0.5 = 0.5"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 != 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 = -1"), false);
// infinity/nan
CHECK_XPATH_BOOLEAN(c, "1 div 0 = 2 div 0", true);
CHECK_XPATH_BOOLEAN(c, "-1 div 0 != 2 div 0", true);
CHECK_XPATH_BOOLEAN(c, STR("1 div 0 = 2 div 0"), true);
CHECK_XPATH_BOOLEAN(c, STR("-1 div 0 != 2 div 0"), true);
#ifndef MSVC6_NAN_BUG
CHECK_XPATH_BOOLEAN(c, "0 div 0 = 1", false);
CHECK_XPATH_BOOLEAN(c, "0 div 0 != 1", true);
CHECK_XPATH_BOOLEAN(c, "0 div 0 = 0 div 0", false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 = 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 != 1"), true);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 = 0 div 0"), false);
#endif
// upcast to number
CHECK_XPATH_BOOLEAN(c, "2 = '2'", true);
CHECK_XPATH_BOOLEAN(c, "2 != '2'", false);
CHECK_XPATH_BOOLEAN(c, "'1' != 2", true);
CHECK_XPATH_BOOLEAN(c, "'1' = 2", false);
CHECK_XPATH_BOOLEAN(c, STR("2 = '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("2 != '2'"), false);
CHECK_XPATH_BOOLEAN(c, STR("'1' != 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("'1' = 2"), false);
}
TEST(xpath_operators_equality_primitive_string)
@ -158,104 +158,104 @@ TEST(xpath_operators_equality_primitive_string)
xml_node c;
// string vs string
CHECK_XPATH_BOOLEAN(c, "'a' = 'a'", true);
CHECK_XPATH_BOOLEAN(c, "'a' = 'b'", false);
CHECK_XPATH_BOOLEAN(c, "'ab' != 'a'", true);
CHECK_XPATH_BOOLEAN(c, "'' != 'a'", true);
CHECK_XPATH_BOOLEAN(c, "'a' != ''", true);
CHECK_XPATH_BOOLEAN(c, "'' != ''", false);
CHECK_XPATH_BOOLEAN(c, STR("'a' = 'a'"), true);
CHECK_XPATH_BOOLEAN(c, STR("'a' = 'b'"), false);
CHECK_XPATH_BOOLEAN(c, STR("'ab' != 'a'"), true);
CHECK_XPATH_BOOLEAN(c, STR("'' != 'a'"), true);
CHECK_XPATH_BOOLEAN(c, STR("'a' != ''"), true);
CHECK_XPATH_BOOLEAN(c, STR("'' != ''"), false);
}
TEST_XML(xpath_operators_equality_node_set_node_set, "<node><c1><v>a</v><v>b</v></c1><c2><v>a</v><v>c</v></c2><c3><v>b</v></c3><c4><v>d</v></c4><c5><v>a</v><v>b</v></c5><c6><v>b</v></c6></node>")
{
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// node set vs node set
CHECK_XPATH_BOOLEAN(c, "x = x", false); // empty node set compares as false with any other object via any comparison operator, as per XPath spec
CHECK_XPATH_BOOLEAN(c, "x != x", false);
CHECK_XPATH_BOOLEAN(n, "c1/v = c2/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c2/v = c3/v", false);
CHECK_XPATH_BOOLEAN(n, "c1/v = c4/v", false);
CHECK_XPATH_BOOLEAN(n, "c1/v = x", false);
CHECK_XPATH_BOOLEAN(n, "x = c1", false);
CHECK_XPATH_BOOLEAN(c, STR("x = x"), false); // empty node set compares as false with any other object via any comparison operator, as per XPath spec
CHECK_XPATH_BOOLEAN(c, STR("x != x"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v = c3/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = c4/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = x"), false);
CHECK_XPATH_BOOLEAN(n, STR("x = c1"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v != c2/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c2/v != c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != c4/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != c5/v", true); // (a, b) != (a, b), since a != b, as per XPath spec (comparison operators are so not intutive)
CHECK_XPATH_BOOLEAN(n, "c3/v != c6/v", false);
CHECK_XPATH_BOOLEAN(n, "c1/v != x", false);
CHECK_XPATH_BOOLEAN(n, "x != c1/v", false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v != c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c4/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c5/v"), true); // (a, b) != (a, b), since a != b, as per XPath spec (comparison operators are so not intutive)
CHECK_XPATH_BOOLEAN(n, STR("c3/v != c6/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != x"), false);
CHECK_XPATH_BOOLEAN(n, STR("x != c1/v"), false);
}
TEST_XML(xpath_operators_equality_node_set_primitive, "<node><c1><v>1</v><v>-1</v><v>100</v></c1><c2><v>1</v><v>nan</v></c2></node>")
{
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// node set vs number
CHECK_XPATH_BOOLEAN(c, "x = 1", false);
CHECK_XPATH_BOOLEAN(c, "x != 1", false);
CHECK_XPATH_BOOLEAN(c, "1 = x", false);
CHECK_XPATH_BOOLEAN(c, "1 != x", false);
CHECK_XPATH_BOOLEAN(c, STR("x = 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("x != 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 = x"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 != x"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v = 1", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = -1", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != 1", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = 5", false);
CHECK_XPATH_BOOLEAN(n, "c2/v = 1", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = 1"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = -1"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != 1"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = 5"), false);
CHECK_XPATH_BOOLEAN(n, STR("c2/v = 1"), true);
CHECK_XPATH_BOOLEAN(n, "1 = c1/v", true);
CHECK_XPATH_BOOLEAN(n, "-1 = c1/v", true);
CHECK_XPATH_BOOLEAN(n, "1 != c1/v", true);
CHECK_XPATH_BOOLEAN(n, "5 = c1/v", false);
CHECK_XPATH_BOOLEAN(n, "1 = c2/v", true);
CHECK_XPATH_BOOLEAN(n, STR("1 = c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("-1 = c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("1 != c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("5 = c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("1 = c2/v"), true);
#ifndef MSVC6_NAN_BUG
CHECK_XPATH_BOOLEAN(n, "c2/v != 1", true);
CHECK_XPATH_BOOLEAN(n, "1 != c2/v", true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v != 1"), true);
CHECK_XPATH_BOOLEAN(n, STR("1 != c2/v"), true);
#endif
// node set vs string
CHECK_XPATH_BOOLEAN(c, "x = '1'", false);
CHECK_XPATH_BOOLEAN(c, "x != '1'", false);
CHECK_XPATH_BOOLEAN(c, "'1' = x", false);
CHECK_XPATH_BOOLEAN(c, "'1' != x", false);
CHECK_XPATH_BOOLEAN(c, STR("x = '1'"), false);
CHECK_XPATH_BOOLEAN(c, STR("x != '1'"), false);
CHECK_XPATH_BOOLEAN(c, STR("'1' = x"), false);
CHECK_XPATH_BOOLEAN(c, STR("'1' != x"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v = '1'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = '-1'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != '1'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = '5'", false);
CHECK_XPATH_BOOLEAN(n, "c2/v = '1'", true);
CHECK_XPATH_BOOLEAN(n, "c2/v != '1'", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = '1'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = '-1'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != '1'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = '5'"), false);
CHECK_XPATH_BOOLEAN(n, STR("c2/v = '1'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v != '1'"), true);
CHECK_XPATH_BOOLEAN(n, "'1' = c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'-1' = c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'1' != c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'5' = c1/v", false);
CHECK_XPATH_BOOLEAN(n, "'1' = c2/v", true);
CHECK_XPATH_BOOLEAN(n, "'1' != c2/v", true);
CHECK_XPATH_BOOLEAN(n, STR("'1' = c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'-1' = c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'1' != c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'5' = c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("'1' = c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'1' != c2/v"), true);
// node set vs almost-numeric string just in case
CHECK_XPATH_BOOLEAN(n, "c1/v = '1.0'", false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = '1.0'"), false);
// node set vs boolean - special rules! empty sets are equal to true()
CHECK_XPATH_BOOLEAN(n, "x = true()", false);
CHECK_XPATH_BOOLEAN(n, "x != true()", true);
CHECK_XPATH_BOOLEAN(n, "x = false()", true);
CHECK_XPATH_BOOLEAN(n, "c1/v = true()", true);
CHECK_XPATH_BOOLEAN(n, "c1/v != true()", false);
CHECK_XPATH_BOOLEAN(n, "c1/v = false()", false);
CHECK_XPATH_BOOLEAN(n, STR("x = true()"), false);
CHECK_XPATH_BOOLEAN(n, STR("x != true()"), true);
CHECK_XPATH_BOOLEAN(n, STR("x = false()"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = true()"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != true()"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v = false()"), false);
CHECK_XPATH_BOOLEAN(n, "true() = x", false);
CHECK_XPATH_BOOLEAN(n, "true() != x", true);
CHECK_XPATH_BOOLEAN(n, "false() = x", true);
CHECK_XPATH_BOOLEAN(n, "true() = c1/v", true);
CHECK_XPATH_BOOLEAN(n, "true() != c1/v", false);
CHECK_XPATH_BOOLEAN(n, "false() = c1/v", false);
CHECK_XPATH_BOOLEAN(n, STR("true() = x"), false);
CHECK_XPATH_BOOLEAN(n, STR("true() != x"), true);
CHECK_XPATH_BOOLEAN(n, STR("false() = x"), true);
CHECK_XPATH_BOOLEAN(n, STR("true() = c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("true() != c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("false() = c1/v"), false);
}
TEST(xpath_operators_inequality_primitive)
@ -263,143 +263,143 @@ TEST(xpath_operators_inequality_primitive)
xml_node c;
// number vs number
CHECK_XPATH_BOOLEAN(c, "1 < 2", true);
CHECK_XPATH_BOOLEAN(c, "1 <= 2", true);
CHECK_XPATH_BOOLEAN(c, "1 > 2", false);
CHECK_XPATH_BOOLEAN(c, "1 >= 2", false);
CHECK_XPATH_BOOLEAN(c, STR("1 < 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 <= 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 > 2"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 >= 2"), false);
CHECK_XPATH_BOOLEAN(c, "1 < 1", false);
CHECK_XPATH_BOOLEAN(c, "1 <= 1", true);
CHECK_XPATH_BOOLEAN(c, "1 > 1", false);
CHECK_XPATH_BOOLEAN(c, "1 >= 1", true);
CHECK_XPATH_BOOLEAN(c, STR("1 < 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 <= 1"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 > 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 >= 1"), true);
// infinity/nan
CHECK_XPATH_BOOLEAN(c, "1 div 0 <= 2 div 0", true);
CHECK_XPATH_BOOLEAN(c, "1 div 0 < 2 div 0", false);
CHECK_XPATH_BOOLEAN(c, "-1 div 0 < 2 div 0", true);
CHECK_XPATH_BOOLEAN(c, "-1 div 0 > 2 div 0", false);
CHECK_XPATH_BOOLEAN(c, STR("1 div 0 <= 2 div 0"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 div 0 < 2 div 0"), false);
CHECK_XPATH_BOOLEAN(c, STR("-1 div 0 < 2 div 0"), true);
CHECK_XPATH_BOOLEAN(c, STR("-1 div 0 > 2 div 0"), false);
#ifndef MSVC6_NAN_BUG
CHECK_XPATH_BOOLEAN(c, "0 div 0 < 1", false);
CHECK_XPATH_BOOLEAN(c, "0 div 0 <= 1", false);
CHECK_XPATH_BOOLEAN(c, "0 div 0 > 1", false);
CHECK_XPATH_BOOLEAN(c, "0 div 0 >= 1", false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 < 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 <= 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 > 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 div 0 >= 1"), false);
#endif
// upcast to number
CHECK_XPATH_BOOLEAN(c, "2 < '2'", false);
CHECK_XPATH_BOOLEAN(c, "1 < '2'", true);
CHECK_XPATH_BOOLEAN(c, "2 <= '2'", true);
CHECK_XPATH_BOOLEAN(c, "3 <= '2'", false);
CHECK_XPATH_BOOLEAN(c, "2 > '2'", false);
CHECK_XPATH_BOOLEAN(c, "3 > '2'", true);
CHECK_XPATH_BOOLEAN(c, "2 >= '2'", true);
CHECK_XPATH_BOOLEAN(c, "3 >= '2'", true);
CHECK_XPATH_BOOLEAN(c, "1 >= true()", true);
CHECK_XPATH_BOOLEAN(c, "1 > true()", false);
CHECK_XPATH_BOOLEAN(c, STR("2 < '2'"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 < '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("2 <= '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("3 <= '2'"), false);
CHECK_XPATH_BOOLEAN(c, STR("2 > '2'"), false);
CHECK_XPATH_BOOLEAN(c, STR("3 > '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("2 >= '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("3 >= '2'"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 >= true()"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 > true()"), false);
}
TEST_XML(xpath_operators_inequality_node_set_node_set, "<node><c1><v>1</v><v>-1</v><v>-100</v></c1><c2><v>1</v><v>nan</v></c2><c3><v>1</v><v>-4</v></c3></node>")
{
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// node set vs node set
CHECK_XPATH_BOOLEAN(c, "x < x", false);
CHECK_XPATH_BOOLEAN(c, "x > x", false);
CHECK_XPATH_BOOLEAN(c, "x <= x", false);
CHECK_XPATH_BOOLEAN(c, "x >= x", false);
CHECK_XPATH_BOOLEAN(c, STR("x < x"), false);
CHECK_XPATH_BOOLEAN(c, STR("x > x"), false);
CHECK_XPATH_BOOLEAN(c, STR("x <= x"), false);
CHECK_XPATH_BOOLEAN(c, STR("x >= x"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v > x", false);
CHECK_XPATH_BOOLEAN(n, "c1/v < x", false);
CHECK_XPATH_BOOLEAN(n, "c1/v >= x", false);
CHECK_XPATH_BOOLEAN(n, "c1/v <= x", false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > x"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < x"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= x"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= x"), false);
CHECK_XPATH_BOOLEAN(n, "x > c1/v", false);
CHECK_XPATH_BOOLEAN(n, "x < c1/v", false);
CHECK_XPATH_BOOLEAN(n, "x >= c1/v", false);
CHECK_XPATH_BOOLEAN(n, "x <= c1/v", false);
CHECK_XPATH_BOOLEAN(n, STR("x > c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("x < c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("x >= c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("x <= c1/v"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v > c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v >= c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v < c3/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v <= c3/v", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c3/v"), true);
#ifndef MSVC6_NAN_BUG
CHECK_XPATH_BOOLEAN(n, "c1/v > c2/v", false);
CHECK_XPATH_BOOLEAN(n, "c1/v >= c2/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v < c2/v", true);
CHECK_XPATH_BOOLEAN(n, "c1/v <= c2/v", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > c2/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c2/v"), true);
#endif
}
TEST_XML(xpath_operators_inequality_node_set_primitive, "<node><c1><v>1</v><v>-1</v><v>-100</v></c1><c2><v>1</v><v>nan</v></c2></node>")
{
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// node set vs number
CHECK_XPATH_BOOLEAN(c, "x < 0", false);
CHECK_XPATH_BOOLEAN(c, "x > 0", false);
CHECK_XPATH_BOOLEAN(c, "x <= 0", false);
CHECK_XPATH_BOOLEAN(c, "x >= 0", false);
CHECK_XPATH_BOOLEAN(c, STR("x < 0"), false);
CHECK_XPATH_BOOLEAN(c, STR("x > 0"), false);
CHECK_XPATH_BOOLEAN(c, STR("x <= 0"), false);
CHECK_XPATH_BOOLEAN(c, STR("x >= 0"), false);
CHECK_XPATH_BOOLEAN(c, "0 < x", false);
CHECK_XPATH_BOOLEAN(c, "0 > x", false);
CHECK_XPATH_BOOLEAN(c, "0 <= x", false);
CHECK_XPATH_BOOLEAN(c, "0 >= x", false);
CHECK_XPATH_BOOLEAN(c, STR("0 < x"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 > x"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 <= x"), false);
CHECK_XPATH_BOOLEAN(c, STR("0 >= x"), false);
CHECK_XPATH_BOOLEAN(n, "c1/v > 0", true);
CHECK_XPATH_BOOLEAN(n, "c1/v > 1", false);
CHECK_XPATH_BOOLEAN(n, "c1/v >= 0", true);
CHECK_XPATH_BOOLEAN(n, "c1/v < 0", true);
CHECK_XPATH_BOOLEAN(n, "c1/v <= 0", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > 0"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > 1"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= 0"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < 0"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= 0"), true);
CHECK_XPATH_BOOLEAN(n, "0 < c1/v", true);
CHECK_XPATH_BOOLEAN(n, "1 < c1/v", false);
CHECK_XPATH_BOOLEAN(n, "0 <= c1/v", true);
CHECK_XPATH_BOOLEAN(n, "0 > c1/v", true);
CHECK_XPATH_BOOLEAN(n, "0 >= c1/v", true);
CHECK_XPATH_BOOLEAN(n, STR("0 < c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("1 < c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("0 <= c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("0 > c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("0 >= c1/v"), true);
// node set vs string
CHECK_XPATH_BOOLEAN(n, "c1/v > '0'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v > '1'", false);
CHECK_XPATH_BOOLEAN(n, "c1/v >= '0'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v < '0'", true);
CHECK_XPATH_BOOLEAN(n, "c1/v <= '0'", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > '0'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > '1'"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= '0'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < '0'"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= '0'"), true);
CHECK_XPATH_BOOLEAN(n, "'0' < c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'1' < c1/v", false);
CHECK_XPATH_BOOLEAN(n, "'0' <= c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'0' > c1/v", true);
CHECK_XPATH_BOOLEAN(n, "'0' >= c1/v", true);
CHECK_XPATH_BOOLEAN(n, STR("'0' < c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'1' < c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("'0' <= c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'0' > c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("'0' >= c1/v"), true);
// node set vs boolean
CHECK_XPATH_BOOLEAN(n, "c1/v > false()", true);
CHECK_XPATH_BOOLEAN(n, "c1/v > true()", false);
CHECK_XPATH_BOOLEAN(n, "c1/v >= false()", true);
CHECK_XPATH_BOOLEAN(n, "c1/v < false()", true);
CHECK_XPATH_BOOLEAN(n, "c1/v <= false()", true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > false()"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v > true()"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= false()"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < false()"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= false()"), true);
CHECK_XPATH_BOOLEAN(n, "false() < c1/v", true);
CHECK_XPATH_BOOLEAN(n, "true() < c1/v", false);
CHECK_XPATH_BOOLEAN(n, "false() <= c1/v", true);
CHECK_XPATH_BOOLEAN(n, "false() > c1/v", true);
CHECK_XPATH_BOOLEAN(n, "false() >= c1/v", true);
CHECK_XPATH_BOOLEAN(n, STR("false() < c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("true() < c1/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("false() <= c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("false() > c1/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("false() >= c1/v"), true);
}
TEST(xpath_operators_boolean_precedence)
{
xml_node c;
CHECK_XPATH_BOOLEAN(c, "1 = 0 or 2 = 2", true);
CHECK_XPATH_BOOLEAN(c, "1 = (0 or 2) = false()", false);
CHECK_XPATH_BOOLEAN(c, "1 < 0 or 2 > 2", false);
CHECK_XPATH_BOOLEAN(c, "2 < 1 = false()", true);
CHECK_XPATH_BOOLEAN(c, "2 < (1 = false())", false);
CHECK_XPATH_BOOLEAN(c, "3 > 2 > 1", false);
CHECK_XPATH_BOOLEAN(c, "(3 > 2) > 1", false);
CHECK_XPATH_BOOLEAN(c, "3 > (2 > 1)", true);
CHECK_XPATH_BOOLEAN(c, STR("1 = 0 or 2 = 2"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 = (0 or 2) = false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("1 < 0 or 2 > 2"), false);
CHECK_XPATH_BOOLEAN(c, STR("2 < 1 = false()"), true);
CHECK_XPATH_BOOLEAN(c, STR("2 < (1 = false())"), false);
CHECK_XPATH_BOOLEAN(c, STR("3 > 2 > 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("(3 > 2) > 1"), false);
CHECK_XPATH_BOOLEAN(c, STR("3 > (2 > 1)"), true);
}
TEST_XML(xpath_operators_union, "<node><employee/><employee secretary=''/><employee assistant=''/><employee secretary='' assistant=''/><employee assistant='' secretary=''/><tail/></node>")
@ -407,15 +407,15 @@ TEST_XML(xpath_operators_union, "<node><employee/><employee secretary=''/><emplo
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(n, "employee | .") % 2 % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@secretary] | employee[@assistant]") % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@assistant] | employee[@secretary]") % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@secretary] | employee[@nobody]") % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@nobody] | employee[@secretary]") % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, "tail/preceding-sibling::employee | .") % 2 % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, ". | tail/preceding-sibling::employee | .") % 2 % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee | .")) % 2 % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@secretary] | employee[@assistant]")) % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@assistant] | employee[@secretary]")) % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@secretary] | employee[@nobody]")) % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@nobody] | employee[@secretary]")) % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("tail/preceding-sibling::employee | .")) % 2 % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR(". | tail/preceding-sibling::employee | .")) % 2 % 3 % 4 % 6 % 8 % 11;
}
#endif

View file

@ -5,88 +5,88 @@
TEST(xpath_literal_parse)
{
xml_node c;
CHECK_XPATH_STRING(c, "'a\"b'", "a\"b");
CHECK_XPATH_STRING(c, "\"a'b\"", "a'b");
CHECK_XPATH_STRING(c, "\"\"", "");
CHECK_XPATH_STRING(c, "\'\'", "");
CHECK_XPATH_STRING(c, STR("'a\"b'"), STR("a\"b"));
CHECK_XPATH_STRING(c, STR("\"a'b\""), STR("a'b"));
CHECK_XPATH_STRING(c, STR("\"\""), STR(""));
CHECK_XPATH_STRING(c, STR("\'\'"), STR(""));
}
TEST(xpath_literal_error)
{
CHECK_XPATH_FAIL("\"");
CHECK_XPATH_FAIL("\'");
CHECK_XPATH_FAIL(STR("\""));
CHECK_XPATH_FAIL(STR("\'"));
}
TEST(xpath_number_parse)
{
xml_node c;
CHECK_XPATH_NUMBER(c, "0", 0);
CHECK_XPATH_NUMBER(c, "123", 123);
CHECK_XPATH_NUMBER(c, "123.456", 123.456);
CHECK_XPATH_NUMBER(c, ".123", 0.123);
CHECK_XPATH_NUMBER(c, "123.4567890123456789012345", 123.4567890123456789012345);
CHECK_XPATH_NUMBER(c, STR("0"), 0);
CHECK_XPATH_NUMBER(c, STR("123"), 123);
CHECK_XPATH_NUMBER(c, STR("123.456"), 123.456);
CHECK_XPATH_NUMBER(c, STR(".123"), 0.123);
CHECK_XPATH_NUMBER(c, STR("123.4567890123456789012345"), 123.4567890123456789012345);
}
TEST(xpath_number_error)
{
CHECK_XPATH_FAIL("123a");
CHECK_XPATH_FAIL("123.a");
CHECK_XPATH_FAIL(".123a");
CHECK_XPATH_FAIL(STR("123a"));
CHECK_XPATH_FAIL(STR("123.a"));
CHECK_XPATH_FAIL(STR(".123a"));
}
TEST(xpath_variables)
{
CHECK_XPATH_FAIL("$var"); // not implemented
CHECK_XPATH_FAIL("$1");
CHECK_XPATH_FAIL(STR("$var")); // not implemented
CHECK_XPATH_FAIL(STR("$1"));
}
TEST(xpath_empty_expression)
{
CHECK_XPATH_FAIL("");
CHECK_XPATH_FAIL(STR(""));
}
TEST(xpath_lexer_error)
{
CHECK_XPATH_FAIL("!");
CHECK_XPATH_FAIL("&");
CHECK_XPATH_FAIL(STR("!"));
CHECK_XPATH_FAIL(STR("&"));
}
TEST(xpath_unmatched_braces)
{
CHECK_XPATH_FAIL("node[");
CHECK_XPATH_FAIL("node[1");
CHECK_XPATH_FAIL("node[]]");
CHECK_XPATH_FAIL("node(");
CHECK_XPATH_FAIL("node(()");
CHECK_XPATH_FAIL("(node)[1");
CHECK_XPATH_FAIL("(1");
CHECK_XPATH_FAIL(STR("node["));
CHECK_XPATH_FAIL(STR("node[1"));
CHECK_XPATH_FAIL(STR("node[]]"));
CHECK_XPATH_FAIL(STR("node("));
CHECK_XPATH_FAIL(STR("node(()"));
CHECK_XPATH_FAIL(STR("(node)[1"));
CHECK_XPATH_FAIL(STR("(1"));
}
TEST(xpath_incorrect_step)
{
CHECK_XPATH_FAIL("child::1");
CHECK_XPATH_FAIL("something::*");
CHECK_XPATH_FAIL("a::*");
CHECK_XPATH_FAIL("c::*");
CHECK_XPATH_FAIL("d::*");
CHECK_XPATH_FAIL("f::*");
CHECK_XPATH_FAIL("n::*");
CHECK_XPATH_FAIL("p::*");
CHECK_XPATH_FAIL(STR("child::1"));
CHECK_XPATH_FAIL(STR("something::*"));
CHECK_XPATH_FAIL(STR("a::*"));
CHECK_XPATH_FAIL(STR("c::*"));
CHECK_XPATH_FAIL(STR("d::*"));
CHECK_XPATH_FAIL(STR("f::*"));
CHECK_XPATH_FAIL(STR("n::*"));
CHECK_XPATH_FAIL(STR("p::*"));
}
TEST(xpath_semantics_error)
{
CHECK_XPATH_FAIL("1[1]");
CHECK_XPATH_FAIL("1 | 1");
CHECK_XPATH_FAIL(STR("1[1]"));
CHECK_XPATH_FAIL(STR("1 | 1"));
}
TEST(xpath_semantics_posinv) // coverage for contains()
{
xpath_query("(node)[substring(1, 2, 3)]");
xpath_query("(node)[concat(1, 2, 3, 4)]");
xpath_query("(node)[count(foo)]");
xpath_query("(node)[local-name()]");
xpath_query("(node)[(node)[1]]");
xpath_query(STR("(node)[substring(1, 2, 3)]"));
xpath_query(STR("(node)[concat(1, 2, 3, 4)]"));
xpath_query(STR("(node)[count(foo)]"));
xpath_query(STR("(node)[local-name()]"));
xpath_query(STR("(node)[(node)[1]]"));
}
#endif

View file

@ -7,12 +7,12 @@ TEST_XML(xpath_paths_axes_child, "<node attr='value'><child attr='value'><subchi
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child:: node()");
CHECK_XPATH_NODESET(c, STR("child:: node()"));
CHECK_XPATH_NODESET(n, "child:: node()") % 4 % 7 % 8; // child, another, last
CHECK_XPATH_NODESET(n, "another/child:: node()");
CHECK_XPATH_NODESET(n, STR("child:: node()")) % 4 % 7 % 8; // child, another, last
CHECK_XPATH_NODESET(n, STR("another/child:: node()"));
}
TEST_XML(xpath_paths_axes_descendant, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -20,14 +20,14 @@ TEST_XML(xpath_paths_axes_descendant, "<node attr='value'><child attr='value'><s
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "descendant:: node()");
CHECK_XPATH_NODESET(c, STR("descendant:: node()"));
CHECK_XPATH_NODESET(n, "descendant:: node()") % 4 % 6 % 7 % 8 % 9; // child, subchild, another, subchild, last
CHECK_XPATH_NODESET(doc, "descendant:: node()") % 2 % 4 % 6 % 7 % 8 % 9; // node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(n, "another/descendant:: node()") % 8; // subchild
CHECK_XPATH_NODESET(n, "last/descendant:: node()");
CHECK_XPATH_NODESET(n, STR("descendant:: node()")) % 4 % 6 % 7 % 8 % 9; // child, subchild, another, subchild, last
CHECK_XPATH_NODESET(doc, STR("descendant:: node()")) % 2 % 4 % 6 % 7 % 8 % 9; // node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(n, STR("another/descendant:: node()")) % 8; // subchild
CHECK_XPATH_NODESET(n, STR("last/descendant:: node()"));
}
TEST_XML(xpath_paths_axes_parent, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -35,15 +35,15 @@ TEST_XML(xpath_paths_axes_parent, "<node attr='value'><child attr='value'><subch
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "parent:: node()");
CHECK_XPATH_NODESET(c, STR("parent:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "parent:: node()") % 2; // node
CHECK_XPATH_NODESET(n, "child/subchild/parent:: node()") % 4; // child
CHECK_XPATH_NODESET(n, "@attr/parent:: node()") % 2; // node
CHECK_XPATH_NODESET(n, "parent:: node()") % 1; // root
CHECK_XPATH_NODESET(doc, "parent:: node()");
CHECK_XPATH_NODESET(n.child(STR("child")), STR("parent:: node()")) % 2; // node
CHECK_XPATH_NODESET(n, STR("child/subchild/parent:: node()")) % 4; // child
CHECK_XPATH_NODESET(n, STR("@attr/parent:: node()")) % 2; // node
CHECK_XPATH_NODESET(n, STR("parent:: node()")) % 1; // root
CHECK_XPATH_NODESET(doc, STR("parent:: node()"));
}
TEST_XML(xpath_paths_axes_ancestor, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -51,15 +51,15 @@ TEST_XML(xpath_paths_axes_ancestor, "<node attr='value'><child attr='value'><sub
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "ancestor:: node()");
CHECK_XPATH_NODESET(c, STR("ancestor:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "ancestor:: node()") % 2 % 1; // node, root
CHECK_XPATH_NODESET(n, "child/subchild/ancestor:: node()") % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, "child/@attr/ancestor:: node()") % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, "ancestor:: node()") % 1; // root
CHECK_XPATH_NODESET(doc, "ancestor:: node()");
CHECK_XPATH_NODESET(n.child(STR("child")), STR("ancestor:: node()")) % 2 % 1; // node, root
CHECK_XPATH_NODESET(n, STR("child/subchild/ancestor:: node()")) % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, STR("child/@attr/ancestor:: node()")) % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, STR("ancestor:: node()")) % 1; // root
CHECK_XPATH_NODESET(doc, STR("ancestor:: node()"));
}
TEST_XML(xpath_paths_axes_following_sibling, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -67,13 +67,13 @@ TEST_XML(xpath_paths_axes_following_sibling, "<node attr1='value' attr2='value'>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "following-sibling:: node()");
CHECK_XPATH_NODESET(c, STR("following-sibling:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "following-sibling:: node()") % 8 % 10; // another, last
CHECK_XPATH_NODESET(n.child("last"), "following-sibling:: node()");
CHECK_XPATH_NODESET(n, "@attr1/following-sibling:: node()"); // attributes are not siblings
CHECK_XPATH_NODESET(n.child(STR("child")), STR("following-sibling:: node()")) % 8 % 10; // another, last
CHECK_XPATH_NODESET(n.child(STR("last")), STR("following-sibling:: node()"));
CHECK_XPATH_NODESET(n, STR("@attr1/following-sibling:: node()")); // attributes are not siblings
}
TEST_XML(xpath_paths_axes_preceding_sibling, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -81,13 +81,13 @@ TEST_XML(xpath_paths_axes_preceding_sibling, "<node attr1='value' attr2='value'>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "preceding-sibling:: node()");
CHECK_XPATH_NODESET(c, STR("preceding-sibling:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "preceding-sibling:: node()");
CHECK_XPATH_NODESET(n.child("last"), "preceding-sibling:: node()") % 8 % 5; // another, child
CHECK_XPATH_NODESET(n, "@attr2/following-sibling:: node()"); // attributes are not siblings
CHECK_XPATH_NODESET(n.child(STR("child")), STR("preceding-sibling:: node()"));
CHECK_XPATH_NODESET(n.child(STR("last")), STR("preceding-sibling:: node()")) % 8 % 5; // another, child
CHECK_XPATH_NODESET(n, STR("@attr2/following-sibling:: node()")); // attributes are not siblings
}
TEST_XML(xpath_paths_axes_following, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another><subchild/></another><almost/><last/></node>")
@ -95,14 +95,14 @@ TEST_XML(xpath_paths_axes_following, "<node attr1='value' attr2='value'><child a
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "following:: node()");
CHECK_XPATH_NODESET(c, STR("following:: node()"));
CHECK_XPATH_NODESET(n, "following:: node()"); // no descendants
CHECK_XPATH_NODESET(n.child("child"), "following:: node()") % 8 % 9 % 10 % 11; // another, subchild, almost, last
CHECK_XPATH_NODESET(n.child("child").child("subchild"), "following:: node()") % 8 % 9 % 10 % 11; // another, subchild, almost, last
CHECK_XPATH_NODESET(n.child("last"), "following:: node()");
CHECK_XPATH_NODESET(n, STR("following:: node()")); // no descendants
CHECK_XPATH_NODESET(n.child(STR("child")), STR("following:: node()")) % 8 % 9 % 10 % 11; // another, subchild, almost, last
CHECK_XPATH_NODESET(n.child(STR("child")).child(STR("subchild")), STR("following:: node()")) % 8 % 9 % 10 % 11; // another, subchild, almost, last
CHECK_XPATH_NODESET(n.child(STR("last")), STR("following:: node()"));
}
TEST_XML(xpath_paths_axes_preceding, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another><subchild/></another><almost/><last/></node>")
@ -110,14 +110,14 @@ TEST_XML(xpath_paths_axes_preceding, "<node attr1='value' attr2='value'><child a
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "preceding:: node()");
CHECK_XPATH_NODESET(c, STR("preceding:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "preceding:: node()"); // no ancestors
CHECK_XPATH_NODESET(n.child("last"), "preceding:: node()") % 10 % 9 % 8 % 7 % 5; // almost, subchild, another, subchild, child
CHECK_XPATH_NODESET(n.child("another").child("subchild"), "preceding:: node()") % 7 % 5; // subchild, child
CHECK_XPATH_NODESET(n, "preceding:: node()");
CHECK_XPATH_NODESET(n.child(STR("child")), STR("preceding:: node()")); // no ancestors
CHECK_XPATH_NODESET(n.child(STR("last")), STR("preceding:: node()")) % 10 % 9 % 8 % 7 % 5; // almost, subchild, another, subchild, child
CHECK_XPATH_NODESET(n.child(STR("another")).child(STR("subchild")), STR("preceding:: node()")) % 7 % 5; // subchild, child
CHECK_XPATH_NODESET(n, STR("preceding:: node()"));
}
TEST_XML(xpath_paths_axes_attribute, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another xmlns:foo='bar'><subchild/></another><last/></node>")
@ -125,22 +125,22 @@ TEST_XML(xpath_paths_axes_attribute, "<node attr1='value' attr2='value'><child a
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "attribute:: node()");
CHECK_XPATH_NODESET(c, STR("attribute:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "attribute:: node()") % 6; // child/@attr
CHECK_XPATH_NODESET(n.child("last"), "attribute:: node()");
CHECK_XPATH_NODESET(n, "attribute:: node()") % 3 % 4; // node/@attr1 node/@attr2
CHECK_XPATH_NODESET(doc, "descendant-or-self:: node()/attribute:: node()") % 3 % 4 % 6; // all attributes
CHECK_XPATH_NODESET(n.child("another"), "attribute:: node()"); // namespace nodes are not attributes
CHECK_XPATH_NODESET(n.child(STR("child")), STR("attribute:: node()")) % 6; // child/@attr
CHECK_XPATH_NODESET(n.child(STR("last")), STR("attribute:: node()"));
CHECK_XPATH_NODESET(n, STR("attribute:: node()")) % 3 % 4; // node/@attr1 node/@attr2
CHECK_XPATH_NODESET(doc, STR("descendant-or-self:: node()/attribute:: node()")) % 3 % 4 % 6; // all attributes
CHECK_XPATH_NODESET(n.child(STR("another")), STR("attribute:: node()")); // namespace nodes are not attributes
}
TEST_XML(xpath_paths_axes_namespace, "<node xmlns:foo='bar'/>")
{
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(n, "namespace:: node()"); // namespace nodes are not supported
CHECK_XPATH_NODESET(n, STR("namespace:: node()")); // namespace nodes are not supported
}
TEST_XML(xpath_paths_axes_self, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -148,15 +148,15 @@ TEST_XML(xpath_paths_axes_self, "<node attr='value'><child attr='value'><subchil
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "self:: node()");
CHECK_XPATH_NODESET(c, STR("self:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "self:: node()") % 4; // child
CHECK_XPATH_NODESET(n, "self:: node()") % 2; // node
CHECK_XPATH_NODESET(n, "child/self:: node()") % 4; // child
CHECK_XPATH_NODESET(n, "child/@attr/self:: node()") % 5; // @attr
CHECK_XPATH_NODESET(doc, "self:: node()") % 1; // root
CHECK_XPATH_NODESET(n.child(STR("child")), STR("self:: node()")) % 4; // child
CHECK_XPATH_NODESET(n, STR("self:: node()")) % 2; // node
CHECK_XPATH_NODESET(n, STR("child/self:: node()")) % 4; // child
CHECK_XPATH_NODESET(n, STR("child/@attr/self:: node()")) % 5; // @attr
CHECK_XPATH_NODESET(doc, STR("self:: node()")) % 1; // root
}
TEST_XML(xpath_paths_axes_descendant_or_self, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -164,14 +164,14 @@ TEST_XML(xpath_paths_axes_descendant_or_self, "<node attr='value'><child attr='v
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "descendant-or-self:: node()");
CHECK_XPATH_NODESET(c, STR("descendant-or-self:: node()"));
CHECK_XPATH_NODESET(n, "descendant-or-self:: node()") % 2 % 4 % 6 % 7 % 8 % 9; // node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(doc, "descendant-or-self:: node()") % 1 % 2 % 4 % 6 % 7 % 8 % 9; // root, node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(n, "another/descendant-or-self:: node()") % 7 % 8; // another, subchild
CHECK_XPATH_NODESET(n, "last/descendant-or-self:: node()") % 9; // last
CHECK_XPATH_NODESET(n, STR("descendant-or-self:: node()")) % 2 % 4 % 6 % 7 % 8 % 9; // node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(doc, STR("descendant-or-self:: node()")) % 1 % 2 % 4 % 6 % 7 % 8 % 9; // root, node, child, subchild, another, subchild, last
CHECK_XPATH_NODESET(n, STR("another/descendant-or-self:: node()")) % 7 % 8; // another, subchild
CHECK_XPATH_NODESET(n, STR("last/descendant-or-self:: node()")) % 9; // last
}
TEST_XML(xpath_paths_axes_ancestor_or_self, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -179,15 +179,15 @@ TEST_XML(xpath_paths_axes_ancestor_or_self, "<node attr='value'><child attr='val
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "ancestor-or-self:: node()");
CHECK_XPATH_NODESET(c, STR("ancestor-or-self:: node()"));
CHECK_XPATH_NODESET(n.child("child"), "ancestor-or-self:: node()") % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, "child/subchild/ancestor-or-self:: node()") % 6 % 4 % 2 % 1; // subchild, child, node, root
CHECK_XPATH_NODESET(n, "child/@attr/ancestor-or-self:: node()") % 5 % 4 % 2 % 1; // @attr, child, node, root
CHECK_XPATH_NODESET(n, "ancestor-or-self:: node()") % 2 % 1; // root, node
CHECK_XPATH_NODESET(doc, "ancestor-or-self:: node()") % 1; // root
CHECK_XPATH_NODESET(n.child(STR("child")), STR("ancestor-or-self:: node()")) % 4 % 2 % 1; // child, node, root
CHECK_XPATH_NODESET(n, STR("child/subchild/ancestor-or-self:: node()")) % 6 % 4 % 2 % 1; // subchild, child, node, root
CHECK_XPATH_NODESET(n, STR("child/@attr/ancestor-or-self:: node()")) % 5 % 4 % 2 % 1; // @attr, child, node, root
CHECK_XPATH_NODESET(n, STR("ancestor-or-self:: node()")) % 2 % 1; // root, node
CHECK_XPATH_NODESET(doc, STR("ancestor-or-self:: node()")) % 1; // root
}
TEST_XML(xpath_paths_axes_abbrev, "<node attr='value'><foo/></node>")
@ -195,20 +195,20 @@ TEST_XML(xpath_paths_axes_abbrev, "<node attr='value'><foo/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// @ axis
CHECK_XPATH_NODESET(c, "@attr");
CHECK_XPATH_NODESET(n, "@attr") % 3;
CHECK_XPATH_NODESET(c, STR("@attr"));
CHECK_XPATH_NODESET(n, STR("@attr")) % 3;
// no axis - child implied
CHECK_XPATH_NODESET(c, "foo");
CHECK_XPATH_NODESET(n, "foo") % 4;
CHECK_XPATH_NODESET(doc, "node()") % 2;
CHECK_XPATH_NODESET(c, STR("foo"));
CHECK_XPATH_NODESET(n, STR("foo")) % 4;
CHECK_XPATH_NODESET(doc, STR("node()")) % 2;
// @ axis should disable all other axis specifiers
CHECK_XPATH_FAIL("@child::foo");
CHECK_XPATH_FAIL("@attribute::foo");
CHECK_XPATH_FAIL(STR("@child::foo"));
CHECK_XPATH_FAIL(STR("@attribute::foo"));
}
TEST_XML(xpath_paths_nodetest_all, "<node a1='v1' x:a2='v2'><c1/><x:c2/><c3/><x:c4/></node>")
@ -216,14 +216,14 @@ TEST_XML(xpath_paths_nodetest_all, "<node a1='v1' x:a2='v2'><c1/><x:c2/><c3/><x:
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "*");
CHECK_XPATH_NODESET(c, "child::*");
CHECK_XPATH_NODESET(c, STR("*"));
CHECK_XPATH_NODESET(c, STR("child::*"));
CHECK_XPATH_NODESET(n, "*") % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(n, "child::*") % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(n, "attribute::*") % 3 % 4;
CHECK_XPATH_NODESET(n, STR("*")) % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(n, STR("child::*")) % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(n, STR("attribute::*")) % 3 % 4;
}
TEST_XML_FLAGS(xpath_paths_nodetest_name, "<node a1='v1' x:a2='v2'><c1/><x:c2/><c3/><x:c4/><?c1?></node>", parse_default | parse_pi)
@ -231,20 +231,20 @@ TEST_XML_FLAGS(xpath_paths_nodetest_name, "<node a1='v1' x:a2='v2'><c1/><x:c2/><
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "c1");
CHECK_XPATH_NODESET(c, "child::c1");
CHECK_XPATH_NODESET(c, STR("c1"));
CHECK_XPATH_NODESET(c, STR("child::c1"));
CHECK_XPATH_NODESET(n, "c1") % 5;
CHECK_XPATH_NODESET(n, "x:c2") % 6;
CHECK_XPATH_NODESET(n, STR("c1")) % 5;
CHECK_XPATH_NODESET(n, STR("x:c2")) % 6;
CHECK_XPATH_NODESET(n, "child::c1") % 5;
CHECK_XPATH_NODESET(n, "child::x:c2") % 6;
CHECK_XPATH_NODESET(n, STR("child::c1")) % 5;
CHECK_XPATH_NODESET(n, STR("child::x:c2")) % 6;
CHECK_XPATH_NODESET(n, "attribute::a1") % 3;
CHECK_XPATH_NODESET(n, "attribute::x:a2") % 4;
CHECK_XPATH_NODESET(n, "@x:a2") % 4;
CHECK_XPATH_NODESET(n, STR("attribute::a1")) % 3;
CHECK_XPATH_NODESET(n, STR("attribute::x:a2")) % 4;
CHECK_XPATH_NODESET(n, STR("@x:a2")) % 4;
}
TEST_XML(xpath_paths_nodetest_all_in_namespace, "<node a1='v1' x:a2='v2'><c1/><x:c2/><c3/><x:c4/></node>")
@ -252,19 +252,19 @@ TEST_XML(xpath_paths_nodetest_all_in_namespace, "<node a1='v1' x:a2='v2'><c1/><x
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "x:*");
CHECK_XPATH_NODESET(c, "child::x:*");
CHECK_XPATH_NODESET(c, STR("x:*"));
CHECK_XPATH_NODESET(c, STR("child::x:*"));
CHECK_XPATH_NODESET(n, "x:*") % 6 % 8;
CHECK_XPATH_NODESET(n, "child::x:*") % 6 % 8;
CHECK_XPATH_NODESET(n, STR("x:*")) % 6 % 8;
CHECK_XPATH_NODESET(n, STR("child::x:*")) % 6 % 8;
CHECK_XPATH_NODESET(n, "attribute::x:*") % 4;
CHECK_XPATH_NODESET(n, "@x:*") % 4;
CHECK_XPATH_NODESET(n, STR("attribute::x:*")) % 4;
CHECK_XPATH_NODESET(n, STR("@x:*")) % 4;
CHECK_XPATH_FAIL(":*");
CHECK_XPATH_FAIL("@:*");
CHECK_XPATH_FAIL(STR(":*"));
CHECK_XPATH_FAIL(STR("@:*"));
}
TEST_XML_FLAGS(xpath_paths_nodetest_type, "<node attr='value'>pcdata<child/><?pi1 value?><?pi2 value?><!--comment--><![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments)
@ -272,35 +272,35 @@ TEST_XML_FLAGS(xpath_paths_nodetest_type, "<node attr='value'>pcdata<child/><?pi
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
// check on empty nodes
CHECK_XPATH_NODESET(c, "node()");
CHECK_XPATH_NODESET(c, "text()");
CHECK_XPATH_NODESET(c, "comment()");
CHECK_XPATH_NODESET(c, "processing-instruction()");
CHECK_XPATH_NODESET(c, "processing-instruction('foobar')");
CHECK_XPATH_NODESET(c, STR("node()"));
CHECK_XPATH_NODESET(c, STR("text()"));
CHECK_XPATH_NODESET(c, STR("comment()"));
CHECK_XPATH_NODESET(c, STR("processing-instruction()"));
CHECK_XPATH_NODESET(c, STR("processing-instruction('foobar')"));
// child axis
CHECK_XPATH_NODESET(n, "node()") % 4 % 5 % 6 % 7 % 8 % 9;
CHECK_XPATH_NODESET(n, "text()") % 4 % 9;
CHECK_XPATH_NODESET(n, "comment()") % 8;
CHECK_XPATH_NODESET(n, "processing-instruction()") % 6 % 7;
CHECK_XPATH_NODESET(n, "processing-instruction('pi2')") % 7;
CHECK_XPATH_NODESET(n, STR("node()")) % 4 % 5 % 6 % 7 % 8 % 9;
CHECK_XPATH_NODESET(n, STR("text()")) % 4 % 9;
CHECK_XPATH_NODESET(n, STR("comment()")) % 8;
CHECK_XPATH_NODESET(n, STR("processing-instruction()")) % 6 % 7;
CHECK_XPATH_NODESET(n, STR("processing-instruction('pi2')")) % 7;
// attribute axis
CHECK_XPATH_NODESET(n, "@node()") % 3;
CHECK_XPATH_NODESET(n, "@text()");
CHECK_XPATH_NODESET(n, "@comment()");
CHECK_XPATH_NODESET(n, "@processing-instruction()");
CHECK_XPATH_NODESET(n, "@processing-instruction('pi2')");
CHECK_XPATH_NODESET(n, STR("@node()")) % 3;
CHECK_XPATH_NODESET(n, STR("@text()"));
CHECK_XPATH_NODESET(n, STR("@comment()"));
CHECK_XPATH_NODESET(n, STR("@processing-instruction()"));
CHECK_XPATH_NODESET(n, STR("@processing-instruction('pi2')"));
// incorrect 'argument' number
CHECK_XPATH_FAIL("node('')");
CHECK_XPATH_FAIL("text('')");
CHECK_XPATH_FAIL("comment('')");
CHECK_XPATH_FAIL("processing-instruction(1)");
CHECK_XPATH_FAIL("processing-instruction('', '')");
CHECK_XPATH_FAIL(STR("node('')"));
CHECK_XPATH_FAIL(STR("text('')"));
CHECK_XPATH_FAIL(STR("comment('')"));
CHECK_XPATH_FAIL(STR("processing-instruction(1)"));
CHECK_XPATH_FAIL(STR("processing-instruction('', '')"));
}
TEST_XML(xpath_paths_absolute, "<node><foo><foo/><foo/></foo></node>")
@ -308,16 +308,16 @@ TEST_XML(xpath_paths_absolute, "<node><foo><foo/><foo/></foo></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "/foo");
CHECK_XPATH_NODESET(n, "/foo");
CHECK_XPATH_NODESET(n, "/node/foo") % 3;
CHECK_XPATH_NODESET(n.child("foo"), "/node/foo") % 3;
CHECK_XPATH_NODESET(c, STR("/foo"));
CHECK_XPATH_NODESET(n, STR("/foo"));
CHECK_XPATH_NODESET(n, STR("/node/foo")) % 3;
CHECK_XPATH_NODESET(n.child(STR("foo")), STR("/node/foo")) % 3;
CHECK_XPATH_NODESET(c, "/");
CHECK_XPATH_NODESET(n, "/") % 1;
CHECK_XPATH_NODESET(n.child("foo"), "/") % 1;
CHECK_XPATH_NODESET(c, STR("/"));
CHECK_XPATH_NODESET(n, STR("/")) % 1;
CHECK_XPATH_NODESET(n.child(STR("foo")), STR("/")) % 1;
}
TEST_XML(xpath_paths_step_abbrev, "<node><foo/></node>")
@ -325,18 +325,18 @@ TEST_XML(xpath_paths_step_abbrev, "<node><foo/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, ".");
CHECK_XPATH_NODESET(c, "..");
CHECK_XPATH_NODESET(c, STR("."));
CHECK_XPATH_NODESET(c, STR(".."));
CHECK_XPATH_NODESET(n, ".") % 2;
CHECK_XPATH_NODESET(n, "..") % 1;
CHECK_XPATH_NODESET(n, "../node") % 2;
CHECK_XPATH_NODESET(n.child("foo"), "..") % 2;
CHECK_XPATH_NODESET(n, STR(".")) % 2;
CHECK_XPATH_NODESET(n, STR("..")) % 1;
CHECK_XPATH_NODESET(n, STR("../node")) % 2;
CHECK_XPATH_NODESET(n.child(STR("foo")), STR("..")) % 2;
CHECK_XPATH_FAIL(".node");
CHECK_XPATH_FAIL("..node");
CHECK_XPATH_FAIL(STR(".node"));
CHECK_XPATH_FAIL(STR("..node"));
}
TEST_XML(xpath_paths_relative_abbrev, "<node><foo><foo/><foo/></foo></node>")
@ -344,13 +344,13 @@ TEST_XML(xpath_paths_relative_abbrev, "<node><foo><foo/><foo/></foo></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "foo//bar");
CHECK_XPATH_NODESET(c, STR("foo//bar"));
CHECK_XPATH_NODESET(n, "foo/foo") % 4 % 5;
CHECK_XPATH_NODESET(n, "foo//foo") % 4 % 5;
CHECK_XPATH_NODESET(n, ".//foo") % 3 % 4 % 5;
CHECK_XPATH_NODESET(n, STR("foo/foo")) % 4 % 5;
CHECK_XPATH_NODESET(n, STR("foo//foo")) % 4 % 5;
CHECK_XPATH_NODESET(n, STR(".//foo")) % 3 % 4 % 5;
}
TEST_XML(xpath_paths_absolute_abbrev, "<node><foo><foo/><foo/></foo></node>")
@ -358,117 +358,117 @@ TEST_XML(xpath_paths_absolute_abbrev, "<node><foo><foo/><foo/></foo></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "//bar");
CHECK_XPATH_NODESET(c, STR("//bar"));
CHECK_XPATH_NODESET(n, "//foo") % 3 % 4 % 5;
CHECK_XPATH_NODESET(n.child("foo"), "//foo") % 3 % 4 % 5;
CHECK_XPATH_NODESET(doc, "//foo") % 3 % 4 % 5;
CHECK_XPATH_NODESET(n, STR("//foo")) % 3 % 4 % 5;
CHECK_XPATH_NODESET(n.child(STR("foo")), STR("//foo")) % 3 % 4 % 5;
CHECK_XPATH_NODESET(doc, STR("//foo")) % 3 % 4 % 5;
}
TEST_XML(xpath_paths_predicate_boolean, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(n, "following-sibling::chapter[position()=1]") % 6;
CHECK_XPATH_NODESET(n, "following-sibling::chapter[position()=2]") % 7;
CHECK_XPATH_NODESET(n, "preceding-sibling::chapter[position()=1]") % 4;
CHECK_XPATH_NODESET(n, "preceding-sibling::chapter[position()=2]") % 3;
CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[position()=1]")) % 6;
CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[position()=2]")) % 7;
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[position()=1]")) % 4;
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[position()=2]")) % 3;
}
TEST_XML(xpath_paths_predicate_number, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(n, "following-sibling::chapter[1]") % 6;
CHECK_XPATH_NODESET(n, "following-sibling::chapter[2]") % 7;
CHECK_XPATH_NODESET(n, "preceding-sibling::chapter[1]") % 4;
CHECK_XPATH_NODESET(n, "preceding-sibling::chapter[2]") % 3;
CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[1]")) % 6;
CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[2]")) % 7;
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[1]")) % 4;
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[2]")) % 3;
}
TEST_XML(xpath_paths_predicate_several, "<node><employee/><employee secretary=''/><employee assistant=''/><employee secretary='' assistant=''/><employee assistant='' secretary=''/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(n, "employee") % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@secretary]") % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@assistant]") % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@secretary][@assistant]") % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@assistant][@secretary]") % 8 % 11;
CHECK_XPATH_NODESET(n, "employee[@secretary and @assistant]") % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee")) % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@secretary]")) % 4 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@assistant]")) % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@secretary][@assistant]")) % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@assistant][@secretary]")) % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee[@secretary and @assistant]")) % 8 % 11;
}
TEST_XML(xpath_paths_predicate_filter_boolean, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(n, "(following-sibling::chapter)[position()=1]") % 6;
CHECK_XPATH_NODESET(n, "(following-sibling::chapter)[position()=2]") % 7;
CHECK_XPATH_NODESET(n, "(preceding-sibling::chapter)[position()=1]") % 3;
CHECK_XPATH_NODESET(n, "(preceding-sibling::chapter)[position()=2]") % 4;
CHECK_XPATH_NODESET(n, STR("(following-sibling::chapter)[position()=1]")) % 6;
CHECK_XPATH_NODESET(n, STR("(following-sibling::chapter)[position()=2]")) % 7;
CHECK_XPATH_NODESET(n, STR("(preceding-sibling::chapter)[position()=1]")) % 3;
CHECK_XPATH_NODESET(n, STR("(preceding-sibling::chapter)[position()=2]")) % 4;
}
TEST_XML(xpath_paths_predicate_filter_number, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(n, "(following-sibling::chapter)[1]") % 6;
CHECK_XPATH_NODESET(n, "(following-sibling::chapter)[2]") % 7;
CHECK_XPATH_NODESET(n, "(preceding-sibling::chapter)[1]") % 3;
CHECK_XPATH_NODESET(n, "(preceding-sibling::chapter)[2]") % 4;
CHECK_XPATH_NODESET(n, STR("(following-sibling::chapter)[1]")) % 6;
CHECK_XPATH_NODESET(n, STR("(following-sibling::chapter)[2]")) % 7;
CHECK_XPATH_NODESET(n, STR("(preceding-sibling::chapter)[1]")) % 3;
CHECK_XPATH_NODESET(n, STR("(preceding-sibling::chapter)[2]")) % 4;
}
TEST_XML(xpath_paths_predicate_filter_posinv, "<node><employee/><employee secretary=''/><employee assistant=''/><employee secretary='' assistant=''/><employee assistant='' secretary=''/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(n, "employee") % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, "(employee[@secretary])[@assistant]") % 8 % 11;
CHECK_XPATH_NODESET(n, "((employee)[@assistant])[@secretary]") % 8 % 11;
CHECK_XPATH_NODESET(n, STR("employee")) % 3 % 4 % 6 % 8 % 11;
CHECK_XPATH_NODESET(n, STR("(employee[@secretary])[@assistant]")) % 8 % 11;
CHECK_XPATH_NODESET(n, STR("((employee)[@assistant])[@secretary]")) % 8 % 11;
}
TEST_XML(xpath_paths_step_compose, "<node><foo><foo/><foo/></foo><foo/></node>")
{
doc.precompute_document_order();
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(n, "(.)/foo") % 3 % 6;
CHECK_XPATH_NODESET(n, "(.)//foo") % 3 % 4 % 5 % 6;
CHECK_XPATH_NODESET(n, "(./..)//*") % 2 % 3 % 4 % 5 % 6;
CHECK_XPATH_NODESET(n, STR("(.)/foo")) % 3 % 6;
CHECK_XPATH_NODESET(n, STR("(.)//foo")) % 3 % 4 % 5 % 6;
CHECK_XPATH_NODESET(n, STR("(./..)//*")) % 2 % 3 % 4 % 5 % 6;
CHECK_XPATH_FAIL("(1)/foo");
CHECK_XPATH_FAIL("(1)//foo");
CHECK_XPATH_FAIL(STR("(1)/foo"));
CHECK_XPATH_FAIL(STR("(1)//foo"));
}
TEST_XML(xpath_paths_descendant_double_slash_w3c, "<node><para><para/><para/><para><para/></para></para><para/></node>")
{
doc.precompute_document_order();
CHECK_XPATH_NODESET(doc, "//para") % 3 % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(doc, "/descendant::para") % 3 % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(doc, "//para[1]") % 3 % 4 % 7;
CHECK_XPATH_NODESET(doc, "/descendant::para[1]") % 3;
CHECK_XPATH_NODESET(doc, STR("//para")) % 3 % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(doc, STR("/descendant::para")) % 3 % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(doc, STR("//para[1]")) % 3 % 4 % 7;
CHECK_XPATH_NODESET(doc, STR("/descendant::para[1]")) % 3;
}
TEST_XML(xpath_paths_needs_sorting, "<node><child/><child/><child><subchild/><subchild/></child></node>")
{
doc.precompute_document_order();
CHECK_XPATH_NODESET(doc, "(node/child/subchild)[2]") % 7;
CHECK_XPATH_NODESET(doc, STR("(node/child/subchild)[2]")) % 7;
}
#endif

View file

@ -7,10 +7,10 @@ TEST_XML(xpath_paths_abbrev_w3c_1, "<node><para/><foo/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para");
CHECK_XPATH_NODESET(n, "para") % 3 % 5;
CHECK_XPATH_NODESET(c, STR("para"));
CHECK_XPATH_NODESET(n, STR("para")) % 3 % 5;
}
TEST_XML(xpath_paths_abbrev_w3c_2, "<node><para/><foo/><para/></node>")
@ -18,10 +18,10 @@ TEST_XML(xpath_paths_abbrev_w3c_2, "<node><para/><foo/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "*");
CHECK_XPATH_NODESET(n, "*") % 3 % 4 % 5;
CHECK_XPATH_NODESET(c, STR("*"));
CHECK_XPATH_NODESET(n, STR("*")) % 3 % 4 % 5;
}
TEST_XML(xpath_paths_abbrev_w3c_3, "<node>pcdata<child/><![CDATA[cdata]]></node>")
@ -29,10 +29,10 @@ TEST_XML(xpath_paths_abbrev_w3c_3, "<node>pcdata<child/><![CDATA[cdata]]></node>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "text()");
CHECK_XPATH_NODESET(n, "text()") % 3 % 5;
CHECK_XPATH_NODESET(c, STR("text()"));
CHECK_XPATH_NODESET(n, STR("text()")) % 3 % 5;
}
TEST_XML(xpath_paths_abbrev_w3c_4, "<node name='value' foo='bar' />")
@ -40,10 +40,10 @@ TEST_XML(xpath_paths_abbrev_w3c_4, "<node name='value' foo='bar' />")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "@name");
CHECK_XPATH_NODESET(n, "@name") % 3;
CHECK_XPATH_NODESET(c, STR("@name"));
CHECK_XPATH_NODESET(n, STR("@name")) % 3;
}
TEST_XML(xpath_paths_abbrev_w3c_5, "<node name='value' foo='bar' />")
@ -51,10 +51,10 @@ TEST_XML(xpath_paths_abbrev_w3c_5, "<node name='value' foo='bar' />")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "@*");
CHECK_XPATH_NODESET(n, "@*") % 3 % 4;
CHECK_XPATH_NODESET(c, STR("@*"));
CHECK_XPATH_NODESET(n, STR("@*")) % 3 % 4;
}
TEST_XML(xpath_paths_abbrev_w3c_6, "<node><para/><para/><para/><para/></node>")
@ -62,10 +62,10 @@ TEST_XML(xpath_paths_abbrev_w3c_6, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[1]");
CHECK_XPATH_NODESET(n, "para[1]") % 3;
CHECK_XPATH_NODESET(c, STR("para[1]"));
CHECK_XPATH_NODESET(n, STR("para[1]")) % 3;
}
TEST_XML(xpath_paths_abbrev_w3c_7, "<node><para/><para/><para/><para/></node>")
@ -73,10 +73,10 @@ TEST_XML(xpath_paths_abbrev_w3c_7, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[last()]");
CHECK_XPATH_NODESET(n, "para[last()]") % 6;
CHECK_XPATH_NODESET(c, STR("para[last()]"));
CHECK_XPATH_NODESET(n, STR("para[last()]")) % 6;
}
TEST_XML(xpath_paths_abbrev_w3c_8, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -85,8 +85,8 @@ TEST_XML(xpath_paths_abbrev_w3c_8, "<node><para><para/><para/><foo><para/></foo>
xml_node c;
CHECK_XPATH_NODESET(c, "*/para");
CHECK_XPATH_NODESET(doc, "*/para") % 3 % 9;
CHECK_XPATH_NODESET(c, STR("*/para"));
CHECK_XPATH_NODESET(doc, STR("*/para")) % 3 % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_9, "<doc><chapter/><chapter/><chapter/><chapter/><chapter><section/><section/><section/></chapter><chapter/></doc>")
@ -94,11 +94,11 @@ TEST_XML(xpath_paths_abbrev_w3c_9, "<doc><chapter/><chapter/><chapter/><chapter/
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("doc").child("chapter");
xml_node n = doc.child(STR("doc")).child(STR("chapter"));
CHECK_XPATH_NODESET(c, "/doc/chapter[5]/section[2]");
CHECK_XPATH_NODESET(n, "/doc/chapter[5]/section[2]") % 9;
CHECK_XPATH_NODESET(doc, "/doc/chapter[5]/section[2]") % 9;
CHECK_XPATH_NODESET(c, STR("/doc/chapter[5]/section[2]"));
CHECK_XPATH_NODESET(n, STR("/doc/chapter[5]/section[2]")) % 9;
CHECK_XPATH_NODESET(doc, STR("/doc/chapter[5]/section[2]")) % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_10, "<chapter><para><para/><para/><foo><para/></foo></para><foo/><para/></chapter>")
@ -107,8 +107,8 @@ TEST_XML(xpath_paths_abbrev_w3c_10, "<chapter><para><para/><para/><foo><para/></
xml_node c;
CHECK_XPATH_NODESET(c, "chapter//para");
CHECK_XPATH_NODESET(doc, "chapter//para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(c, STR("chapter//para"));
CHECK_XPATH_NODESET(doc, STR("chapter//para")) % 3 % 4 % 5 % 7 % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_11, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -116,11 +116,11 @@ TEST_XML(xpath_paths_abbrev_w3c_11, "<node><para><para/><para/><foo><para/></foo
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "//para");
CHECK_XPATH_NODESET(n, "//para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child("para"), "//para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(c, STR("//para"));
CHECK_XPATH_NODESET(n, STR("//para")) % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child(STR("para")), STR("//para")) % 3 % 4 % 5 % 7 % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_12, "<node><olist><item/></olist><item/><olist><olist><item/><item/></olist></olist></node>")
@ -128,11 +128,11 @@ TEST_XML(xpath_paths_abbrev_w3c_12, "<node><olist><item/></olist><item/><olist><
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "//olist/item");
CHECK_XPATH_NODESET(n, "//olist/item") % 4 % 8 % 9;
CHECK_XPATH_NODESET(n.child("olist"), "//olist/item") % 4 % 8 % 9;
CHECK_XPATH_NODESET(c, STR("//olist/item"));
CHECK_XPATH_NODESET(n, STR("//olist/item")) % 4 % 8 % 9;
CHECK_XPATH_NODESET(n.child(STR("olist")), STR("//olist/item")) % 4 % 8 % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_13, "<node><child/></node>")
@ -140,11 +140,11 @@ TEST_XML(xpath_paths_abbrev_w3c_13, "<node><child/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, ".");
CHECK_XPATH_NODESET(n, ".") % 2;
CHECK_XPATH_NODESET(n.child("child"), ".") % 3;
CHECK_XPATH_NODESET(c, STR("."));
CHECK_XPATH_NODESET(n, STR(".")) % 2;
CHECK_XPATH_NODESET(n.child(STR("child")), STR(".")) % 3;
}
TEST_XML(xpath_paths_abbrev_w3c_14, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -152,11 +152,11 @@ TEST_XML(xpath_paths_abbrev_w3c_14, "<node><para><para/><para/><foo><para/></foo
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, ".//para");
CHECK_XPATH_NODESET(n, ".//para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child("para"), ".//para") % 4 % 5 % 7;
CHECK_XPATH_NODESET(c, STR(".//para"));
CHECK_XPATH_NODESET(n, STR(".//para")) % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child(STR("para")), STR(".//para")) % 4 % 5 % 7;
}
TEST_XML(xpath_paths_abbrev_w3c_15, "<node lang='en'><child/></node>")
@ -164,11 +164,11 @@ TEST_XML(xpath_paths_abbrev_w3c_15, "<node lang='en'><child/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "..");
CHECK_XPATH_NODESET(n, "..") % 1;
CHECK_XPATH_NODESET(n.child("child"), "..") % 2;
CHECK_XPATH_NODESET(c, STR(".."));
CHECK_XPATH_NODESET(n, STR("..")) % 1;
CHECK_XPATH_NODESET(n.child(STR("child")), STR("..")) % 2;
}
TEST_XML(xpath_paths_abbrev_w3c_16, "<node lang='en'><child/></node>")
@ -176,11 +176,11 @@ TEST_XML(xpath_paths_abbrev_w3c_16, "<node lang='en'><child/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "../@lang");
CHECK_XPATH_NODESET(n, "../@lang");
CHECK_XPATH_NODESET(n.child("child"), "../@lang") % 3;
CHECK_XPATH_NODESET(c, STR("../@lang"));
CHECK_XPATH_NODESET(n, STR("../@lang"));
CHECK_XPATH_NODESET(n.child(STR("child")), STR("../@lang")) % 3;
}
TEST_XML(xpath_paths_abbrev_w3c_17, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -188,10 +188,10 @@ TEST_XML(xpath_paths_abbrev_w3c_17, "<node><para/><para type='warning'/><para ty
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[@type=\"warning\"]");
CHECK_XPATH_NODESET(n, "para[@type=\"warning\"]") % 4 % 6 % 11 % 13 % 15;
CHECK_XPATH_NODESET(c, STR("para[@type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("para[@type=\"warning\"]")) % 4 % 6 % 11 % 13 % 15;
}
TEST_XML(xpath_paths_abbrev_w3c_18, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -199,10 +199,10 @@ TEST_XML(xpath_paths_abbrev_w3c_18, "<node><para/><para type='warning'/><para ty
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[@type=\"warning\"][5]");
CHECK_XPATH_NODESET(n, "para[@type=\"warning\"][5]") % 15;
CHECK_XPATH_NODESET(c, STR("para[@type=\"warning\"][5]"));
CHECK_XPATH_NODESET(n, STR("para[@type=\"warning\"][5]")) % 15;
}
TEST_XML(xpath_paths_abbrev_w3c_19a, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -210,10 +210,10 @@ TEST_XML(xpath_paths_abbrev_w3c_19a, "<node><para/><para type='warning'/><para t
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[5][@type=\"warning\"]");
CHECK_XPATH_NODESET(n, "para[5][@type=\"warning\"]");
CHECK_XPATH_NODESET(c, STR("para[5][@type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("para[5][@type=\"warning\"]"));
}
TEST_XML(xpath_paths_abbrev_w3c_19b, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -221,10 +221,10 @@ TEST_XML(xpath_paths_abbrev_w3c_19b, "<node><para/><para type='warning'/><para t
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "para[5][@type=\"warning\"]");
CHECK_XPATH_NODESET(n, "para[5][@type=\"warning\"]") % 9;
CHECK_XPATH_NODESET(c, STR("para[5][@type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("para[5][@type=\"warning\"]")) % 9;
}
TEST_XML(xpath_paths_abbrev_w3c_20, "<node><chapter><title>foo</title></chapter><chapter><title>Introduction</title></chapter><chapter><title>introduction</title></chapter><chapter/><chapter><title>Introduction</title><title>foo</title></chapter></node>")
@ -232,10 +232,10 @@ TEST_XML(xpath_paths_abbrev_w3c_20, "<node><chapter><title>foo</title></chapter>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "chapter[title=\"Introduction\"]");
CHECK_XPATH_NODESET(n, "chapter[title=\"Introduction\"]") % 6 % 13;
CHECK_XPATH_NODESET(c, STR("chapter[title=\"Introduction\"]"));
CHECK_XPATH_NODESET(n, STR("chapter[title=\"Introduction\"]")) % 6 % 13;
}
TEST_XML(xpath_paths_abbrev_w3c_21, "<node><chapter><title>foo</title></chapter><chapter><title>Introduction</title></chapter><chapter><title>introduction</title></chapter><chapter/><chapter><title>Introduction</title><title>foo</title></chapter></node>")
@ -243,10 +243,10 @@ TEST_XML(xpath_paths_abbrev_w3c_21, "<node><chapter><title>foo</title></chapter>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "chapter[title]");
CHECK_XPATH_NODESET(n, "chapter[title]") % 3 % 6 % 9 % 13;
CHECK_XPATH_NODESET(c, STR("chapter[title]"));
CHECK_XPATH_NODESET(n, STR("chapter[title]")) % 3 % 6 % 9 % 13;
}
TEST_XML(xpath_paths_abbrev_w3c_22, "<node><employee/><employee secretary=''/><employee assistant=''/><employee secretary='' assistant=''/><employee assistant='' secretary=''/></node>")
@ -254,10 +254,10 @@ TEST_XML(xpath_paths_abbrev_w3c_22, "<node><employee/><employee secretary=''/><e
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "employee[@secretary and @assistant]");
CHECK_XPATH_NODESET(n, "employee[@secretary and @assistant]") % 8 % 11;
CHECK_XPATH_NODESET(c, STR("employee[@secretary and @assistant]"));
CHECK_XPATH_NODESET(n, STR("employee[@secretary and @assistant]")) % 8 % 11;
}
#endif

View file

@ -7,10 +7,10 @@ TEST_XML(xpath_paths_w3c_1, "<node><para/><foo/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para");
CHECK_XPATH_NODESET(n, "child::para") % 3 % 5;
CHECK_XPATH_NODESET(c, STR("child::para"));
CHECK_XPATH_NODESET(n, STR("child::para")) % 3 % 5;
}
TEST_XML(xpath_paths_w3c_2, "<node><para/><foo/><para/></node>")
@ -18,10 +18,10 @@ TEST_XML(xpath_paths_w3c_2, "<node><para/><foo/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::*");
CHECK_XPATH_NODESET(n, "child::*") % 3 % 4 % 5;
CHECK_XPATH_NODESET(c, STR("child::*"));
CHECK_XPATH_NODESET(n, STR("child::*")) % 3 % 4 % 5;
}
TEST_XML(xpath_paths_w3c_3, "<node>pcdata<child/><![CDATA[cdata]]></node>")
@ -29,10 +29,10 @@ TEST_XML(xpath_paths_w3c_3, "<node>pcdata<child/><![CDATA[cdata]]></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::text()");
CHECK_XPATH_NODESET(n, "child::text()") % 3 % 5;
CHECK_XPATH_NODESET(c, STR("child::text()"));
CHECK_XPATH_NODESET(n, STR("child::text()")) % 3 % 5;
}
TEST_XML(xpath_paths_w3c_4, "<node>pcdata<child/><![CDATA[cdata]]></node>")
@ -40,10 +40,10 @@ TEST_XML(xpath_paths_w3c_4, "<node>pcdata<child/><![CDATA[cdata]]></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::node()");
CHECK_XPATH_NODESET(n, "child::node()") % 3 % 4 % 5;
CHECK_XPATH_NODESET(c, STR("child::node()"));
CHECK_XPATH_NODESET(n, STR("child::node()")) % 3 % 4 % 5;
}
TEST_XML(xpath_paths_w3c_5, "<node name='value' foo='bar' />")
@ -51,10 +51,10 @@ TEST_XML(xpath_paths_w3c_5, "<node name='value' foo='bar' />")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "attribute::name");
CHECK_XPATH_NODESET(n, "attribute::name") % 3;
CHECK_XPATH_NODESET(c, STR("attribute::name"));
CHECK_XPATH_NODESET(n, STR("attribute::name")) % 3;
}
TEST_XML(xpath_paths_w3c_6, "<node name='value' foo='bar' />")
@ -62,10 +62,10 @@ TEST_XML(xpath_paths_w3c_6, "<node name='value' foo='bar' />")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "attribute::*");
CHECK_XPATH_NODESET(n, "attribute::*") % 3 % 4;
CHECK_XPATH_NODESET(c, STR("attribute::*"));
CHECK_XPATH_NODESET(n, STR("attribute::*")) % 3 % 4;
}
TEST_XML(xpath_paths_w3c_7, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -73,11 +73,11 @@ TEST_XML(xpath_paths_w3c_7, "<node><para><para/><para/><foo><para/></foo></para>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "descendant::para");
CHECK_XPATH_NODESET(n, "descendant::para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child("para"), "descendant::para") % 4 % 5 % 7;
CHECK_XPATH_NODESET(c, STR("descendant::para"));
CHECK_XPATH_NODESET(n, STR("descendant::para")) % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child(STR("para")), STR("descendant::para")) % 4 % 5 % 7;
}
TEST_XML(xpath_paths_w3c_8, "<node><div><font><div><div/></div></font></div></node>")
@ -85,10 +85,10 @@ TEST_XML(xpath_paths_w3c_8, "<node><div><font><div><div/></div></font></div></no
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "ancestor::div");
CHECK_XPATH_NODESET(n.child("div").child("font").child("div").child("div"), "ancestor::div") % 5 % 3;
CHECK_XPATH_NODESET(c, STR("ancestor::div"));
CHECK_XPATH_NODESET(n.child(STR("div")).child(STR("font")).child(STR("div")).child(STR("div")), STR("ancestor::div")) % 5 % 3;
}
TEST_XML(xpath_paths_w3c_9, "<node><div><font><div><div/></div></font></div></node>")
@ -96,10 +96,10 @@ TEST_XML(xpath_paths_w3c_9, "<node><div><font><div><div/></div></font></div></no
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "ancestor-or-self::div");
CHECK_XPATH_NODESET(n.child("div").child("font").child("div").child("div"), "ancestor-or-self::div") % 6 % 5 % 3;
CHECK_XPATH_NODESET(c, STR("ancestor-or-self::div"));
CHECK_XPATH_NODESET(n.child(STR("div")).child(STR("font")).child(STR("div")).child(STR("div")), STR("ancestor-or-self::div")) % 6 % 5 % 3;
}
TEST_XML(xpath_paths_w3c_10, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -107,11 +107,11 @@ TEST_XML(xpath_paths_w3c_10, "<node><para><para/><para/><foo><para/></foo></para
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "descendant-or-self::para");
CHECK_XPATH_NODESET(n, "descendant-or-self::para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child("para"), "descendant-or-self::para") % 3 % 4 % 5 % 7;
CHECK_XPATH_NODESET(c, STR("descendant-or-self::para"));
CHECK_XPATH_NODESET(n, STR("descendant-or-self::para")) % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child(STR("para")), STR("descendant-or-self::para")) % 3 % 4 % 5 % 7;
}
TEST_XML(xpath_paths_w3c_11, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -119,11 +119,11 @@ TEST_XML(xpath_paths_w3c_11, "<node><para><para/><para/><foo><para/></foo></para
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "self::para");
CHECK_XPATH_NODESET(n, "self::para");
CHECK_XPATH_NODESET(n.child("para"), "self::para") % 3;
CHECK_XPATH_NODESET(c, STR("self::para"));
CHECK_XPATH_NODESET(n, STR("self::para"));
CHECK_XPATH_NODESET(n.child(STR("para")), STR("self::para")) % 3;
}
TEST_XML(xpath_paths_w3c_12, "<chapter><para><para/><para/><foo><para/></foo></para><foo/><para/></chapter>")
@ -132,8 +132,8 @@ TEST_XML(xpath_paths_w3c_12, "<chapter><para><para/><para/><foo><para/></foo></p
xml_node c;
CHECK_XPATH_NODESET(c, "child::chapter/descendant::para");
CHECK_XPATH_NODESET(doc, "child::chapter/descendant::para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(c, STR("child::chapter/descendant::para"));
CHECK_XPATH_NODESET(doc, STR("child::chapter/descendant::para")) % 3 % 4 % 5 % 7 % 9;
}
TEST_XML(xpath_paths_w3c_13, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -142,8 +142,8 @@ TEST_XML(xpath_paths_w3c_13, "<node><para><para/><para/><foo><para/></foo></para
xml_node c;
CHECK_XPATH_NODESET(c, "child::*/child::para");
CHECK_XPATH_NODESET(doc, "child::*/child::para") % 3 % 9;
CHECK_XPATH_NODESET(c, STR("child::*/child::para"));
CHECK_XPATH_NODESET(doc, STR("child::*/child::para")) % 3 % 9;
}
TEST_XML(xpath_paths_w3c_14, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -151,13 +151,13 @@ TEST_XML(xpath_paths_w3c_14, "<node><para><para/><para/><foo><para/></foo></para
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "/");
CHECK_XPATH_NODESET(c, STR("/"));
CHECK_XPATH_NODESET(doc, "/") % 1;
CHECK_XPATH_NODESET(n, "/") % 1;
CHECK_XPATH_NODESET(n.child("para"), "/") % 1;
CHECK_XPATH_NODESET(doc, STR("/")) % 1;
CHECK_XPATH_NODESET(n, STR("/")) % 1;
CHECK_XPATH_NODESET(n.child(STR("para")), STR("/")) % 1;
}
TEST_XML(xpath_paths_w3c_15, "<node><para><para/><para/><foo><para/></foo></para><foo/><para/></node>")
@ -165,11 +165,11 @@ TEST_XML(xpath_paths_w3c_15, "<node><para><para/><para/><foo><para/></foo></para
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "/descendant::para");
CHECK_XPATH_NODESET(n, "/descendant::para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child("para"), "/descendant::para") % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(c, STR("/descendant::para"));
CHECK_XPATH_NODESET(n, STR("/descendant::para")) % 3 % 4 % 5 % 7 % 9;
CHECK_XPATH_NODESET(n.child(STR("para")), STR("/descendant::para")) % 3 % 4 % 5 % 7 % 9;
}
TEST_XML(xpath_paths_w3c_16, "<node><olist><item/></olist><item/><olist><olist><item/><item/></olist></olist></node>")
@ -177,11 +177,11 @@ TEST_XML(xpath_paths_w3c_16, "<node><olist><item/></olist><item/><olist><olist><
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "/descendant::olist/child::item");
CHECK_XPATH_NODESET(n, "/descendant::olist/child::item") % 4 % 8 % 9;
CHECK_XPATH_NODESET(n.child("olist"), "/descendant::olist/child::item") % 4 % 8 % 9;
CHECK_XPATH_NODESET(c, STR("/descendant::olist/child::item"));
CHECK_XPATH_NODESET(n, STR("/descendant::olist/child::item")) % 4 % 8 % 9;
CHECK_XPATH_NODESET(n.child(STR("olist")), STR("/descendant::olist/child::item")) % 4 % 8 % 9;
}
TEST_XML(xpath_paths_w3c_17, "<node><para/><para/><para/><para/></node>")
@ -189,10 +189,10 @@ TEST_XML(xpath_paths_w3c_17, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()=1]");
CHECK_XPATH_NODESET(n, "child::para[position()=1]") % 3;
CHECK_XPATH_NODESET(c, STR("child::para[position()=1]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()=1]")) % 3;
}
TEST_XML(xpath_paths_w3c_18, "<node><para/><para/><para/><para/></node>")
@ -200,10 +200,10 @@ TEST_XML(xpath_paths_w3c_18, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()=last()]");
CHECK_XPATH_NODESET(n, "child::para[position()=last()]") % 6;
CHECK_XPATH_NODESET(c, STR("child::para[position()=last()]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()=last()]")) % 6;
}
TEST_XML(xpath_paths_w3c_19, "<node><para/><para/><para/><para/></node>")
@ -211,10 +211,10 @@ TEST_XML(xpath_paths_w3c_19, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()=last()-1]");
CHECK_XPATH_NODESET(n, "child::para[position()=last()-1]") % 5;
CHECK_XPATH_NODESET(c, STR("child::para[position()=last()-1]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()=last()-1]")) % 5;
}
TEST_XML(xpath_paths_w3c_20, "<node><para/><para/><para/><para/></node>")
@ -222,10 +222,10 @@ TEST_XML(xpath_paths_w3c_20, "<node><para/><para/><para/><para/></node>")
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()>1]");
CHECK_XPATH_NODESET(n, "child::para[position()>1]") % 4 % 5 % 6;
CHECK_XPATH_NODESET(c, STR("child::para[position()>1]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()>1]")) % 4 % 5 % 6;
}
TEST_XML(xpath_paths_w3c_21, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
@ -233,10 +233,10 @@ TEST_XML(xpath_paths_w3c_21, "<node><chapter/><chapter/><chapter/><chapter/><cha
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(c, "following-sibling::chapter[position()=1]");
CHECK_XPATH_NODESET(n, "following-sibling::chapter[position()=1]") % 6;
CHECK_XPATH_NODESET(c, STR("following-sibling::chapter[position()=1]"));
CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[position()=1]")) % 6;
}
TEST_XML(xpath_paths_w3c_22, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
@ -244,10 +244,10 @@ TEST_XML(xpath_paths_w3c_22, "<node><chapter/><chapter/><chapter/><chapter/><cha
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node").child("chapter").next_sibling().next_sibling();
xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
CHECK_XPATH_NODESET(c, "preceding-sibling::chapter[position()=1]");
CHECK_XPATH_NODESET(n, "preceding-sibling::chapter[position()=1]") % 4;
CHECK_XPATH_NODESET(c, STR("preceding-sibling::chapter[position()=1]"));
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[position()=1]")) % 4;
}
TEST_XML(xpath_paths_w3c_23, "<node><figure><figure/><figure/><foo><figure/></foo></figure><foo/><figure/></node>")
@ -255,11 +255,11 @@ TEST_XML(xpath_paths_w3c_23, "<node><figure><figure/><figure/><foo><figure/></fo
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "/descendant::figure[position()=4]");
CHECK_XPATH_NODESET(n, "/descendant::figure[position()=4]") % 7;
CHECK_XPATH_NODESET(n.child("figure"), "/descendant::figure[position()=4]") % 7;
CHECK_XPATH_NODESET(c, STR("/descendant::figure[position()=4]"));
CHECK_XPATH_NODESET(n, STR("/descendant::figure[position()=4]")) % 7;
CHECK_XPATH_NODESET(n.child(STR("figure")), STR("/descendant::figure[position()=4]")) % 7;
}
TEST_XML(xpath_paths_w3c_24, "<doc><chapter/><chapter/><chapter/><chapter/><chapter><section/><section/><section/></chapter><chapter/></doc>")
@ -267,11 +267,11 @@ TEST_XML(xpath_paths_w3c_24, "<doc><chapter/><chapter/><chapter/><chapter/><chap
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("doc").child("chapter");
xml_node n = doc.child(STR("doc")).child(STR("chapter"));
CHECK_XPATH_NODESET(c, "/child::doc/child::chapter[position()=5]/child::section[position()=2]");
CHECK_XPATH_NODESET(n, "/child::doc/child::chapter[position()=5]/child::section[position()=2]") % 9;
CHECK_XPATH_NODESET(doc, "/child::doc/child::chapter[position()=5]/child::section[position()=2]") % 9;
CHECK_XPATH_NODESET(c, STR("/child::doc/child::chapter[position()=5]/child::section[position()=2]"));
CHECK_XPATH_NODESET(n, STR("/child::doc/child::chapter[position()=5]/child::section[position()=2]")) % 9;
CHECK_XPATH_NODESET(doc, STR("/child::doc/child::chapter[position()=5]/child::section[position()=2]")) % 9;
}
TEST_XML(xpath_paths_w3c_25, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -279,10 +279,10 @@ TEST_XML(xpath_paths_w3c_25, "<node><para/><para type='warning'/><para type='war
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[attribute::type=\"warning\"]");
CHECK_XPATH_NODESET(n, "child::para[attribute::type=\"warning\"]") % 4 % 6 % 11 % 13 % 15;
CHECK_XPATH_NODESET(c, STR("child::para[attribute::type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("child::para[attribute::type=\"warning\"]")) % 4 % 6 % 11 % 13 % 15;
}
TEST_XML(xpath_paths_w3c_26, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -290,10 +290,10 @@ TEST_XML(xpath_paths_w3c_26, "<node><para/><para type='warning'/><para type='war
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[attribute::type=\"warning\"][position()=5]");
CHECK_XPATH_NODESET(n, "child::para[attribute::type=\"warning\"][position()=5]") % 15;
CHECK_XPATH_NODESET(c, STR("child::para[attribute::type=\"warning\"][position()=5]"));
CHECK_XPATH_NODESET(n, STR("child::para[attribute::type=\"warning\"][position()=5]")) % 15;
}
TEST_XML(xpath_paths_w3c_27a, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='error'/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -301,10 +301,10 @@ TEST_XML(xpath_paths_w3c_27a, "<node><para/><para type='warning'/><para type='wa
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()=5][attribute::type=\"warning\"]");
CHECK_XPATH_NODESET(n, "child::para[position()=5][attribute::type=\"warning\"]");
CHECK_XPATH_NODESET(c, STR("child::para[position()=5][attribute::type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()=5][attribute::type=\"warning\"]"));
}
TEST_XML(xpath_paths_w3c_27b, "<node><para/><para type='warning'/><para type='warning'/><para/><para type='warning'/><para type='warning'/><para type='warning'/></node>")
@ -312,10 +312,10 @@ TEST_XML(xpath_paths_w3c_27b, "<node><para/><para type='warning'/><para type='wa
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::para[position()=5][attribute::type=\"warning\"]");
CHECK_XPATH_NODESET(n, "child::para[position()=5][attribute::type=\"warning\"]") % 9;
CHECK_XPATH_NODESET(c, STR("child::para[position()=5][attribute::type=\"warning\"]"));
CHECK_XPATH_NODESET(n, STR("child::para[position()=5][attribute::type=\"warning\"]")) % 9;
}
TEST_XML(xpath_paths_w3c_28, "<node><chapter><title>foo</title></chapter><chapter><title>Introduction</title></chapter><chapter><title>introduction</title></chapter><chapter/><chapter><title>Introduction</title><title>foo</title></chapter></node>")
@ -323,10 +323,10 @@ TEST_XML(xpath_paths_w3c_28, "<node><chapter><title>foo</title></chapter><chapte
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::chapter[child::title='Introduction']");
CHECK_XPATH_NODESET(n, "child::chapter[child::title='Introduction']") % 6 % 13;
CHECK_XPATH_NODESET(c, STR("child::chapter[child::title='Introduction']"));
CHECK_XPATH_NODESET(n, STR("child::chapter[child::title='Introduction']")) % 6 % 13;
}
TEST_XML(xpath_paths_w3c_29, "<node><chapter><title>foo</title></chapter><chapter><title>Introduction</title></chapter><chapter><title>introduction</title></chapter><chapter/><chapter><title>Introduction</title><title>foo</title></chapter></node>")
@ -334,10 +334,10 @@ TEST_XML(xpath_paths_w3c_29, "<node><chapter><title>foo</title></chapter><chapte
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::chapter[child::title]");
CHECK_XPATH_NODESET(n, "child::chapter[child::title]") % 3 % 6 % 9 % 13;
CHECK_XPATH_NODESET(c, STR("child::chapter[child::title]"));
CHECK_XPATH_NODESET(n, STR("child::chapter[child::title]")) % 3 % 6 % 9 % 13;
}
TEST_XML(xpath_paths_w3c_30, "<node><abstract/><chapter/><chapter/><references/><appendix/></node>")
@ -345,10 +345,10 @@ TEST_XML(xpath_paths_w3c_30, "<node><abstract/><chapter/><chapter/><references/>
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::*[self::chapter or self::appendix]");
CHECK_XPATH_NODESET(n, "child::*[self::chapter or self::appendix]") % 4 % 5 % 7;
CHECK_XPATH_NODESET(c, STR("child::*[self::chapter or self::appendix]"));
CHECK_XPATH_NODESET(n, STR("child::*[self::chapter or self::appendix]")) % 4 % 5 % 7;
}
TEST_XML(xpath_paths_w3c_31a, "<node><abstract/><chapter/><chapter/><references/><appendix/></node>")
@ -356,10 +356,10 @@ TEST_XML(xpath_paths_w3c_31a, "<node><abstract/><chapter/><chapter/><references/
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::*[self::chapter or self::appendix][position()=last()]");
CHECK_XPATH_NODESET(n, "child::*[self::chapter or self::appendix][position()=last()]") % 7;
CHECK_XPATH_NODESET(c, STR("child::*[self::chapter or self::appendix][position()=last()]"));
CHECK_XPATH_NODESET(n, STR("child::*[self::chapter or self::appendix][position()=last()]")) % 7;
}
TEST_XML(xpath_paths_w3c_31b, "<node><abstract/><chapter/><chapter/><references/><appendix/><chapter/></node>")
@ -367,10 +367,10 @@ TEST_XML(xpath_paths_w3c_31b, "<node><abstract/><chapter/><chapter/><references/
doc.precompute_document_order();
xml_node c;
xml_node n = doc.child("node");
xml_node n = doc.child(STR("node"));
CHECK_XPATH_NODESET(c, "child::*[self::chapter or self::appendix][position()=last()]");
CHECK_XPATH_NODESET(n, "child::*[self::chapter or self::appendix][position()=last()]") % 8;
CHECK_XPATH_NODESET(c, STR("child::*[self::chapter or self::appendix][position()=last()]"));
CHECK_XPATH_NODESET(n, STR("child::*[self::chapter or self::appendix][position()=last()]")) % 8;
}
#endif

77
tests/writer_string.cpp Normal file
View file

@ -0,0 +1,77 @@
#include "writer_string.hpp"
#include "test.hpp"
static bool test_narrow(const std::string& result, const char* expected, size_t length)
{
// check result
if (result != std::string(expected, expected + length)) return false;
// check comparison operator (incorrect implementation can theoretically early-out on zero terminators...)
if (length > 0 && result == std::string(expected, expected + length - 1) + "?") return false;
return true;
}
void xml_writer_string::write(const void* data, size_t size)
{
contents += std::string(static_cast<const char*>(data), size);
}
std::string xml_writer_string::as_narrow() const
{
return contents;
}
std::wstring xml_writer_string::as_wide() const
{
CHECK(contents.size() % sizeof(wchar_t) == 0);
return std::wstring(reinterpret_cast<const wchar_t*>(contents.data()), contents.size() / sizeof(wchar_t));
}
std::basic_string<pugi::char_t> xml_writer_string::as_string() const
{
#ifdef PUGIXML_WCHAR_MODE // to avoid "condition is always true" warning in BCC
CHECK(contents.size() % sizeof(pugi::char_t) == 0);
#endif
return std::basic_string<pugi::char_t>(reinterpret_cast<const pugi::char_t*>(contents.data()), contents.size() / sizeof(pugi::char_t));
}
std::string save_narrow(const pugi::xml_document& doc, unsigned int flags, pugi::encoding_t encoding)
{
xml_writer_string writer;
doc.save(writer, STR(""), flags, encoding);
return writer.as_narrow();
}
bool test_save_narrow(const pugi::xml_document& doc, unsigned int flags, pugi::encoding_t encoding, const char* expected, size_t length)
{
return test_narrow(save_narrow(doc, flags, encoding), expected, length);
}
std::string write_narrow(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding)
{
xml_writer_string writer;
node.print(writer, STR(""), flags, encoding);
return writer.as_narrow();
}
bool test_write_narrow(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding, const char* expected, size_t length)
{
return test_narrow(write_narrow(node, flags, encoding), expected, length);
}
std::wstring write_wide(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding)
{
xml_writer_string writer;
node.print(writer, STR(""), flags, encoding);
return writer.as_wide();
}

27
tests/writer_string.hpp Normal file
View file

@ -0,0 +1,27 @@
#ifndef HEADER_WRITER_STRING_HPP
#define HEADER_WRITER_STRING_HPP
#include "../src/pugixml.hpp"
#include <string>
struct xml_writer_string: public pugi::xml_writer
{
std::string contents;
virtual void write(const void* data, size_t size);
std::string as_narrow() const;
std::wstring as_wide() const;
std::basic_string<pugi::char_t> as_string() const;
};
std::string save_narrow(const pugi::xml_document& doc, unsigned int flags, pugi::encoding_t encoding);
bool test_save_narrow(const pugi::xml_document& doc, unsigned int flags, pugi::encoding_t encoding, const char* expected, size_t length);
std::string write_narrow(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding);
bool test_write_narrow(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding, const char* expected, size_t length);
std::wstring write_wide(pugi::xml_node node, unsigned int flags, pugi::encoding_t encoding);
#endif