Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Arseny Kapoulkine
c237489a6c Fix access modifier offset 2018-10-17 21:14:43 -07:00
Arseny Kapoulkine
3c75d4d612 Fix compilation by setting clang-format standard to C++03 2018-10-17 20:57:34 -07:00
Arseny Kapoulkine
e61dbc5e88 Reformat 2018-10-17 20:53:02 -07:00
Arseny Kapoulkine
7d6901bff2 Add .clang-format and Makefile rule for formatting 2018-10-17 20:52:58 -07:00
40 changed files with 14703 additions and 13713 deletions

12
.clang-format Normal file
View file

@ -0,0 +1,12 @@
Standard: Cpp03
UseTab: ForIndentation
TabWidth: 4
IndentWidth: 4
AccessModifierOffset: -4
BreakBeforeBraces: Allman
IndentCaseLabels: false
ColumnLimit: 0
PointerAlignment: Left
BreakConstructorInitializersBeforeComma: true
NamespaceIndentation: None
AlignEscapedNewlines: DontAlign

View file

@ -74,6 +74,9 @@ release: build/pugixml-$(VERSION).tar.gz build/pugixml-$(VERSION).zip
docs: docs/quickstart.html docs/manual.html
format:
clang-format -i src/*.cpp src/*.hpp tests/*.cpp tests/*.hpp
build/pugixml-%: .FORCE | $(RELEASE)
@mkdir -p $(BUILD)
TIMESTAMP=`git show v$(VERSION) -s --format=%ct` && python scripts/archive.py $@ pugixml-$(VERSION) $$TIMESTAMP $|

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,144 +1,146 @@
#include "allocator.hpp"
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
// Address sanitizer
#if defined(__has_feature)
# define ADDRESS_SANITIZER __has_feature(address_sanitizer)
#define ADDRESS_SANITIZER __has_feature(address_sanitizer)
#else
# if defined(__SANITIZE_ADDRESS__)
# define ADDRESS_SANITIZER 1
# else
# define ADDRESS_SANITIZER 0
# endif
#if defined(__SANITIZE_ADDRESS__)
#define ADDRESS_SANITIZER 1
#else
#define ADDRESS_SANITIZER 0
#endif
#endif
// 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
#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
# if defined(_MSC_VER)
# pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
# endif
#if defined(_MSC_VER)
#pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
#endif
# ifdef _XBOX_VER
# define NOD3D
# include <xtl.h>
# else
# include <windows.h>
# endif
#ifdef _XBOX_VER
#define NOD3D
#include <xtl.h>
#else
#include <windows.h>
#endif
namespace
{
const size_t page_size = 4096;
const size_t page_size = 4096;
size_t align_to_page(size_t value)
{
return (value + page_size - 1) & ~(page_size - 1);
}
void* allocate_page_aligned(size_t size)
{
// We can't use VirtualAlloc because it has 64Kb granularity so we run out of address space quickly
// We can't use malloc because of occasional problems with CW on CRT termination
static HANDLE heap = HeapCreate(0, 0, 0);
void* result = HeapAlloc(heap, 0, size + page_size);
return reinterpret_cast<void*>(align_to_page(reinterpret_cast<size_t>(result)));
}
void* allocate(size_t size)
{
size_t aligned_size = align_to_page(size);
void* ptr = allocate_page_aligned(aligned_size + page_size);
if (!ptr) return 0;
char* end = static_cast<char*>(ptr) + aligned_size;
DWORD old_flags;
VirtualProtect(end, page_size, PAGE_NOACCESS, &old_flags);
return end - size;
}
void deallocate(void* ptr, size_t size)
{
size_t aligned_size = align_to_page(size);
void* rptr = static_cast<char*>(ptr) + size - aligned_size;
DWORD old_flags;
VirtualProtect(rptr, aligned_size + page_size, PAGE_NOACCESS, &old_flags);
}
size_t align_to_page(size_t value)
{
return (value + page_size - 1) & ~(page_size - 1);
}
void* allocate_page_aligned(size_t size)
{
// We can't use VirtualAlloc because it has 64Kb granularity so we run out of address space quickly
// We can't use malloc because of occasional problems with CW on CRT termination
static HANDLE heap = HeapCreate(0, 0, 0);
void* result = HeapAlloc(heap, 0, size + page_size);
return reinterpret_cast<void*>(align_to_page(reinterpret_cast<size_t>(result)));
}
void* allocate(size_t size)
{
size_t aligned_size = align_to_page(size);
void* ptr = allocate_page_aligned(aligned_size + page_size);
if (!ptr)
return 0;
char* end = static_cast<char*>(ptr) + aligned_size;
DWORD old_flags;
VirtualProtect(end, page_size, PAGE_NOACCESS, &old_flags);
return end - size;
}
void deallocate(void* ptr, size_t size)
{
size_t aligned_size = align_to_page(size);
void* rptr = static_cast<char*>(ptr) + size - aligned_size;
DWORD old_flags;
VirtualProtect(rptr, aligned_size + page_size, PAGE_NOACCESS, &old_flags);
}
} // namespace
#elif (defined(__APPLE__) || defined(__linux__)) && (defined(__i386) || defined(__x86_64)) && !ADDRESS_SANITIZER
# include <sys/mman.h>
#include <sys/mman.h>
namespace
{
const size_t page_size = 4096;
const size_t page_size = 4096;
size_t align_to_page(size_t value)
{
return (value + page_size - 1) & ~(page_size - 1);
}
void* allocate_page_aligned(size_t size)
{
void* result = malloc(size + page_size);
return reinterpret_cast<void*>(align_to_page(reinterpret_cast<size_t>(result)));
}
void* allocate(size_t size)
{
size_t aligned_size = align_to_page(size);
void* ptr = allocate_page_aligned(aligned_size + page_size);
if (!ptr) return 0;
char* end = static_cast<char*>(ptr) + aligned_size;
int res = mprotect(end, page_size, PROT_NONE);
assert(res == 0);
(void)!res;
return end - size;
}
void deallocate(void* ptr, size_t size)
{
size_t aligned_size = align_to_page(size);
void* rptr = static_cast<char*>(ptr) + size - aligned_size;
int res = mprotect(rptr, aligned_size + page_size, PROT_NONE);
assert(res == 0);
(void)!res;
}
size_t align_to_page(size_t value)
{
return (value + page_size - 1) & ~(page_size - 1);
}
void* allocate_page_aligned(size_t size)
{
void* result = malloc(size + page_size);
return reinterpret_cast<void*>(align_to_page(reinterpret_cast<size_t>(result)));
}
void* allocate(size_t size)
{
size_t aligned_size = align_to_page(size);
void* ptr = allocate_page_aligned(aligned_size + page_size);
if (!ptr)
return 0;
char* end = static_cast<char*>(ptr) + aligned_size;
int res = mprotect(end, page_size, PROT_NONE);
assert(res == 0);
(void)!res;
return end - size;
}
void deallocate(void* ptr, size_t size)
{
size_t aligned_size = align_to_page(size);
void* rptr = static_cast<char*>(ptr) + size - aligned_size;
int res = mprotect(rptr, aligned_size + page_size, PROT_NONE);
assert(res == 0);
(void)!res;
}
} // namespace
#else
namespace
{
void* allocate(size_t size)
{
return malloc(size);
}
void deallocate(void* ptr, size_t size)
{
(void)size;
free(ptr);
}
void* allocate(size_t size)
{
return malloc(size);
}
void deallocate(void* ptr, size_t size)
{
(void)size;
free(ptr);
}
} // namespace
#endif
// High-level allocation functions
@ -147,7 +149,8 @@ const size_t memory_alignment = sizeof(double) > sizeof(void*) ? sizeof(double)
void* memory_allocate(size_t size)
{
void* result = allocate(size + memory_alignment);
if (!result) return 0;
if (!result)
return 0;
memcpy(result, &size, sizeof(size_t));
@ -166,10 +169,10 @@ size_t memory_size(void* ptr)
void memory_deallocate(void* ptr)
{
if (!ptr) return;
if (!ptr)
return;
size_t size = memory_size(ptr);
deallocate(static_cast<char*>(ptr) - memory_alignment, size + memory_alignment);
}

View file

@ -2,9 +2,9 @@
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
{
pugi::xml_document doc;
pugi::xml_document doc;
doc.load_buffer(Data, Size);
doc.load_buffer(Data, Size, pugi::parse_minimal);

View file

@ -3,7 +3,7 @@
#include <stdint.h>
#include <string.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
{
char* text = new char[Size + 1];
memcpy(text, Data, Size);

View file

@ -5,7 +5,8 @@
#include <utility>
template <typename T> static void generic_bool_ops_test(const T& obj)
template <typename T>
static void generic_bool_ops_test(const T& obj)
{
T null;
@ -14,14 +15,14 @@ template <typename T> static void generic_bool_ops_test(const T& obj)
CHECK(!!obj);
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning) - we really want to just cast to bool instead of !!
#pragma warning(push)
#pragma warning(disable : 4800) // forcing value to bool 'true' or 'false' (performance warning) - we really want to just cast to bool instead of !!
#endif
bool b1 = null, b2 = obj;
#ifdef _MSC_VER
# pragma warning(pop)
#pragma warning(pop)
#endif
CHECK(!b1);
@ -33,7 +34,8 @@ template <typename T> static void generic_bool_ops_test(const T& obj)
CHECK(obj || obj);
}
template <typename T> static void generic_eq_ops_test(const T& obj1, const T& obj2)
template <typename T>
static void generic_eq_ops_test(const T& obj1, const T& obj2)
{
T null = T();
@ -54,7 +56,8 @@ template <typename T> static void generic_eq_ops_test(const T& obj1, const T& ob
CHECK(!(T(obj1) != obj1));
}
template <typename T> static void generic_rel_ops_test(T obj1, T obj2)
template <typename T>
static void generic_rel_ops_test(T obj1, T obj2)
{
T null = T();
@ -103,7 +106,8 @@ template <typename T> static void generic_rel_ops_test(T obj1, T obj2)
CHECK(!(obj1 >= obj2));
}
template <typename T> static void generic_empty_test(const T& obj)
template <typename T>
static void generic_empty_test(const T& obj)
{
T null;

View file

@ -1,21 +1,21 @@
#include "test.hpp"
#include "allocator.hpp"
#include "test.hpp"
#include <assert.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <assert.h>
#include <string>
#ifndef PUGIXML_NO_EXCEPTIONS
# include <exception>
#include <exception>
#endif
#ifdef _WIN32_WCE
# undef DebugBreak
# pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
# include <windows.h>
#undef DebugBreak
#pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
#include <windows.h>
#endif
test_runner* test_runner::_tests = 0;
@ -41,7 +41,8 @@ static void* custom_allocate(size_t size)
else
{
void* ptr = memory_allocate(size);
if (!ptr) return 0;
if (!ptr)
return 0;
g_memory_total_size += memory_size(ptr);
g_memory_total_count++;
@ -89,9 +90,9 @@ static void replace_memory_management()
namespace std
{
_CRTIMP2 _Prhand _Raise_handler;
_CRTIMP2 void __cdecl _Throw(const exception&) {}
}
_CRTIMP2 _Prhand _Raise_handler;
_CRTIMP2 void __cdecl _Throw(const exception&) {}
} // namespace std
#endif
static bool run_test(test_runner* test, const char* test_name, pugi::allocation_function allocate)
@ -109,15 +110,15 @@ static bool run_test(test_runner* test, const char* test_name, pugi::allocation_
pugi::set_memory_management_functions(allocate, custom_deallocate);
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4611) // interaction between _setjmp and C++ object destruction is non-portable
# pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged
#pragma warning(push)
#pragma warning(disable : 4611) // interaction between _setjmp and C++ object destruction is non-portable
#pragma warning(disable : 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged
#endif
volatile int result = setjmp(test_runner::_failure_buffer);
#ifdef _MSC_VER
# pragma warning(pop)
#pragma warning(pop)
#endif
if (result)
@ -193,10 +194,10 @@ int main(int, char** argv)
if (g_memory_fail_triggered)
{
// run tests that trigger memory failures twice - with an allocator that returns NULL and with an allocator that throws
#ifndef PUGIXML_NO_EXCEPTIONS
#ifndef PUGIXML_NO_EXCEPTIONS
total++;
passed += run_test(test, (test->_name + std::string(" (throw)")).c_str(), custom_allocate_throw);
#endif
#endif
}
}

View file

@ -5,8 +5,8 @@
#include "writer_string.hpp"
#include <math.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <wchar.h>
@ -33,10 +33,12 @@ static void build_document_order(std::vector<pugi::xpath_node>& result, pugi::xm
cur = cur.next_sibling();
else
{
while (cur && !cur.next_sibling()) cur = cur.parent();
while (cur && !cur.next_sibling())
cur = cur.parent();
cur = cur.next_sibling();
if (!cur) break;
if (!cur)
break;
}
}
}
@ -45,11 +47,11 @@ static void build_document_order(std::vector<pugi::xpath_node>& result, pugi::xm
bool test_string_equal(const pugi::char_t* lhs, const pugi::char_t* rhs)
{
return (!lhs || !rhs) ? lhs == rhs :
#ifdef PUGIXML_WCHAR_MODE
wcscmp(lhs, rhs) == 0;
#else
strcmp(lhs, rhs) == 0;
#endif
#ifdef PUGIXML_WCHAR_MODE
wcscmp(lhs, rhs) == 0;
#else
strcmp(lhs, rhs) == 0;
#endif
}
bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const pugi::char_t* indent, unsigned int flags)
@ -83,7 +85,8 @@ static size_t strlength(const pugi::char_t* s)
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, const pugi::char_t* expected)
{
pugi::xpath_query q(query, variables);
if (!q) return false;
if (!q)
return false;
const size_t capacity = 64;
pugi::char_t result[capacity];
@ -104,7 +107,8 @@ bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query,
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, bool expected)
{
pugi::xpath_query q(query, variables);
if (!q) return false;
if (!q)
return false;
return q.evaluate_boolean(node) == expected;
}
@ -112,7 +116,8 @@ bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query,
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, double expected)
{
pugi::xpath_query q(query, variables);
if (!q) return false;
if (!q)
return false;
double value = q.evaluate_number(node);
double absolute_error = fabs(value - expected);
@ -124,7 +129,8 @@ bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query,
bool test_xpath_number_nan(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables)
{
pugi::xpath_query q(query, variables);
if (!q) return false;
if (!q)
return false;
return test_double_nan(q.evaluate_number(node));
}
@ -155,12 +161,15 @@ void xpath_node_set_tester::check(bool condition)
}
}
xpath_node_set_tester::xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message_): last(0), message(message_)
xpath_node_set_tester::xpath_node_set_tester(const pugi::xpath_node_set& set, const char* message_)
: last(0)
, message(message_)
{
result = set;
// only sort unsorted sets so that we're able to verify reverse order for some axes
if (result.type() == pugi::xpath_node_set::type_unsorted) result.sort();
if (result.type() == pugi::xpath_node_set::type_unsorted)
result.sort();
if (result.empty())
{

View file

@ -36,7 +36,8 @@ struct test_runner
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 pugi::char_t* name, const pugi::char_t* 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);
}
@ -71,17 +72,22 @@ struct xpath_node_set_tester
#endif
struct dummy_fixture {};
struct dummy_fixture
{
};
#define TEST_FIXTURE(name, fixture) \
struct test_runner_helper_##name: fixture \
struct test_runner_helper_##name : fixture \
{ \
void run(); \
}; \
static struct test_runner_##name: test_runner \
static struct test_runner_##name : test_runner \
{ \
test_runner_##name(): test_runner(#name) {} \
\
test_runner_##name() \
: test_runner(#name) \
{ \
} \
\
virtual void run() PUGIXML_OVERRIDE \
{ \
test_runner_helper_##name helper; \
@ -96,30 +102,34 @@ struct dummy_fixture {};
struct test_fixture_##name \
{ \
pugi::xml_document doc; \
\
\
test_fixture_##name() \
{ \
CHECK(doc.load_string(PUGIXML_TEXT(xml), flags)); \
} \
\
\
private: \
test_fixture_##name(const test_fixture_##name&); \
test_fixture_##name& operator=(const test_fixture_##name&); \
}; \
\
\
TEST_FIXTURE(name, test_fixture_##name)
#define TEST_XML(name, xml) TEST_XML_FLAGS(name, xml, pugi::parse_default)
#define CHECK_JOIN(text, file, line) text " at " file ":" #line
#define CHECK_JOIN2(text, file, line) CHECK_JOIN(text, file, line)
#define CHECK_TEXT(condition, text) if (condition) ; else test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)
#define CHECK_TEXT(condition, text) \
if (condition) \
; \
else \
test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)
#define CHECK_FORCE_FAIL(text) test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1)
#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__) || (defined(__BORLANDC__) && __BORLANDC__ <= 0x540)
# define STRINGIZE(value) "??" // Some compilers have issues with stringizing expressions that contain strings w/escaping inside
#define STRINGIZE(value) "??" // Some compilers have issues with stringizing expressions that contain strings w/escaping inside
#else
# define STRINGIZE(value) #value
#define STRINGIZE(value) #value
#endif
#define CHECK(condition) CHECK_TEXT(condition, STRINGIZE(condition) " is false")
@ -147,9 +157,29 @@ struct dummy_fixture {};
#endif
#ifdef PUGIXML_NO_EXCEPTIONS
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); code; CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#define CHECK_ALLOC_FAIL(code) \
do \
{ \
CHECK(!test_runner::_memory_fail_triggered); \
code; \
CHECK(test_runner::_memory_fail_triggered); \
test_runner::_memory_fail_triggered = false; \
} while (test_runner::_memory_fail_triggered)
#else
#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); try { code; } catch (std::bad_alloc&) {} CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered)
#define CHECK_ALLOC_FAIL(code) \
do \
{ \
CHECK(!test_runner::_memory_fail_triggered); \
try \
{ \
code; \
} \
catch (std::bad_alloc&) \
{ \
} \
CHECK(test_runner::_memory_fail_triggered); \
test_runner::_memory_fail_triggered = false; \
} while (test_runner::_memory_fail_triggered)
#endif
#define STR(text) PUGIXML_TEXT(text)
@ -161,7 +191,7 @@ struct dummy_fixture {};
#if (defined(_MSC_VER) && _MSC_VER == 1200) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 800) || defined(__BORLANDC__)
// NaN comparison on MSVC6 is incorrect, see http://www.nabble.com/assertDoubleEquals,-NaN---Microsoft-Visual-Studio-6-td9137859.html
// IC8 and BCC are also affected by the same bug
# define MSVC6_NAN_BUG
#define MSVC6_NAN_BUG
#endif
inline wchar_t wchar_cast(unsigned int value)

View file

@ -15,19 +15,19 @@
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <string>
#ifndef PUGIXML_NO_EXCEPTIONS
# include <stdexcept>
#include <stdexcept>
#endif
#ifdef __MINGW32__
# include <io.h> // for unlink in C++0x mode
#include <io.h> // for unlink in C++0x mode
#endif
#if defined(__CELLOS_LV2__) || defined(ANDROID) || defined(_GLIBCXX_HAVE_UNISTD_H) || defined(__APPLE__)
# include <unistd.h> // for unlink
#include <unistd.h> // for unlink
#endif
using namespace pugi;
@ -35,7 +35,8 @@ using namespace pugi;
static bool load_file_in_memory(const char* path, char*& data, size_t& size)
{
FILE* file = fopen(path, "rb");
if (!file) return false;
if (!file)
return false;
fseek(file, 0, SEEK_END);
long length = ftell(file);
@ -53,15 +54,16 @@ static bool load_file_in_memory(const char* path, char*& data, size_t& size)
static bool test_file_contents(const char* path, const char* data, size_t size)
{
char* fdata;
size_t fsize;
if (!load_file_in_memory(path, fdata, fsize)) return false;
char* fdata;
size_t fsize;
if (!load_file_in_memory(path, fdata, fsize))
return false;
bool result = (size == fsize && memcmp(data, fdata, size) == 0);
bool result = (size == fsize && memcmp(data, fdata, size) == 0);
delete[] fdata;
delete[] fdata;
return result;
return result;
}
TEST(document_create_empty)
@ -199,114 +201,120 @@ TEST(document_load_stream_wide_error_previous)
CHECK(!doc.first_child());
}
template <typename T> class char_array_buffer: public std::basic_streambuf<T>
template <typename T>
class char_array_buffer : public std::basic_streambuf<T>
{
public:
char_array_buffer(T* begin, T* end)
{
this->setg(begin, begin, end);
}
char_array_buffer(T* begin, T* end)
{
this->setg(begin, begin, end);
}
};
TEST(document_load_stream_nonseekable)
{
char contents[] = "<node />";
char_array_buffer<char> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::istream in(&buffer);
char contents[] = "<node />";
char_array_buffer<char> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::istream in(&buffer);
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, STR("<node/>"));
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, STR("<node/>"));
}
TEST(document_load_stream_wide_nonseekable)
{
wchar_t contents[] = L"<node />";
char_array_buffer<wchar_t> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::basic_istream<wchar_t> in(&buffer);
wchar_t contents[] = L"<node />";
char_array_buffer<wchar_t> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::basic_istream<wchar_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, STR("<node/>"));
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, STR("<node/>"));
}
TEST(document_load_stream_nonseekable_large)
{
std::basic_string<char_t> str;
str += STR("<node>");
for (int i = 0; i < 10000; ++i) str += STR("<node/>");
for (int i = 0; i < 10000; ++i)
str += STR("<node/>");
str += STR("</node>");
char_array_buffer<char_t> buffer(&str[0], &str[0] + str.length());
std::basic_istream<char_t> in(&buffer);
char_array_buffer<char_t> buffer(&str[0], &str[0] + str.length());
std::basic_istream<char_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, str.c_str());
xml_document doc;
CHECK(doc.load(in));
CHECK_NODE(doc, str.c_str());
}
TEST(document_load_stream_nonseekable_out_of_memory)
{
char contents[] = "<node />";
char_array_buffer<char> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::istream in(&buffer);
char contents[] = "<node />";
char_array_buffer<char> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::istream in(&buffer);
test_runner::_memory_fail_threshold = 1;
test_runner::_memory_fail_threshold = 1;
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
}
TEST(document_load_stream_wide_nonseekable_out_of_memory)
{
wchar_t contents[] = L"<node />";
char_array_buffer<wchar_t> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::basic_istream<wchar_t> in(&buffer);
wchar_t contents[] = L"<node />";
char_array_buffer<wchar_t> buffer(contents, contents + sizeof(contents) / sizeof(contents[0]));
std::basic_istream<wchar_t> in(&buffer);
test_runner::_memory_fail_threshold = 1;
test_runner::_memory_fail_threshold = 1;
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
}
TEST(document_load_stream_nonseekable_out_of_memory_large)
{
std::basic_string<char> str;
str += "<node>";
for (int i = 0; i < 10000; ++i) str += "<node />";
for (int i = 0; i < 10000; ++i)
str += "<node />";
str += "</node>";
char_array_buffer<char> buffer(&str[0], &str[0] + str.length());
std::basic_istream<char> in(&buffer);
char_array_buffer<char> buffer(&str[0], &str[0] + str.length());
std::basic_istream<char> in(&buffer);
test_runner::_memory_fail_threshold = 32768 * 3 + 4096;
test_runner::_memory_fail_threshold = 32768 * 3 + 4096;
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
}
TEST(document_load_stream_wide_nonseekable_out_of_memory_large)
{
std::basic_string<wchar_t> str;
str += L"<node>";
for (int i = 0; i < 10000; ++i) str += L"<node />";
for (int i = 0; i < 10000; ++i)
str += L"<node />";
str += L"</node>";
char_array_buffer<wchar_t> buffer(&str[0], &str[0] + str.length());
std::basic_istream<wchar_t> in(&buffer);
char_array_buffer<wchar_t> buffer(&str[0], &str[0] + str.length());
std::basic_istream<wchar_t> in(&buffer);
test_runner::_memory_fail_threshold = 32768 * 3 * sizeof(wchar_t) + 4096;
test_runner::_memory_fail_threshold = 32768 * 3 * sizeof(wchar_t) + 4096;
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory));
}
template <typename T> class seek_fail_buffer: public std::basic_streambuf<T>
template <typename T>
class seek_fail_buffer : public std::basic_streambuf<T>
{
public:
int seeks;
seek_fail_buffer(): seeks(0)
seek_fail_buffer()
: seeks(0)
{
}
@ -321,28 +329,30 @@ public:
TEST(document_load_stream_seekable_fail_seek)
{
seek_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
seek_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
TEST(document_load_stream_wide_seekable_fail_seek)
{
seek_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
seek_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
template <typename T> class tell_fail_buffer: public std::basic_streambuf<T>
template <typename T>
class tell_fail_buffer : public std::basic_streambuf<T>
{
public:
int seeks;
tell_fail_buffer(): seeks(0)
tell_fail_buffer()
: seeks(0)
{
}
@ -361,80 +371,89 @@ public:
TEST(document_load_stream_seekable_fail_tell)
{
tell_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
tell_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
TEST(document_load_stream_wide_seekable_fail_tell)
{
tell_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
tell_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
#ifndef PUGIXML_NO_EXCEPTIONS
template <typename T> class read_fail_buffer: public std::basic_streambuf<T>
template <typename T>
class read_fail_buffer : public std::basic_streambuf<T>
{
public:
typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE
typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE
{
throw std::runtime_error("underflow failed");
#ifdef __DMC__
#ifdef __DMC__
return 0;
#endif
#endif
}
};
TEST(document_load_stream_nonseekable_fail_read)
{
read_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
read_fail_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
TEST(document_load_stream_wide_nonseekable_fail_read)
{
read_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
read_fail_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
template <typename T> class read_fail_seekable_buffer: public std::basic_streambuf<T>
template <typename T>
class read_fail_seekable_buffer : public std::basic_streambuf<T>
{
public:
typename std::basic_streambuf<T>::pos_type offset;
read_fail_seekable_buffer(): offset(0)
{
}
read_fail_seekable_buffer()
: offset(0)
{
}
typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE
typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE
{
throw std::runtime_error("underflow failed");
#ifdef __DMC__
#ifdef __DMC__
return 0;
#endif
#endif
}
typename std::basic_streambuf<T>::pos_type seekoff(typename std::basic_streambuf<T>::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode) PUGIXML_OVERRIDE
{
switch (dir)
{
case std::ios_base::beg: offset = off; break;
case std::ios_base::cur: offset += off; break;
case std::ios_base::end: offset = 16 + off; break;
default: ;
case std::ios_base::beg:
offset = off;
break;
case std::ios_base::cur:
offset += off;
break;
case std::ios_base::end:
offset = 16 + off;
break;
default:;
}
return offset;
}
@ -448,20 +467,20 @@ public:
TEST(document_load_stream_seekable_fail_read)
{
read_fail_seekable_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
read_fail_seekable_buffer<char> buffer;
std::basic_istream<char> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
TEST(document_load_stream_wide_seekable_fail_read)
{
read_fail_seekable_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
read_fail_seekable_buffer<wchar_t> buffer;
std::basic_istream<wchar_t> in(&buffer);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
xml_document doc;
CHECK(doc.load(in).status == status_io_error);
}
#endif
#endif
@ -498,7 +517,8 @@ TEST(document_load_file_large)
std::basic_string<char_t> str;
str += STR("<node>");
for (int i = 0; i < 10000; ++i) str += STR("<node/>");
for (int i = 0; i < 10000; ++i)
str += STR("<node/>");
str += STR("</node>");
CHECK_NODE(doc, str.c_str());
@ -744,9 +764,9 @@ struct temp_file
~temp_file()
{
#ifndef _WIN32_WCE
#ifndef _WIN32_WCE
CHECK(unlink(path) == 0);
#endif
#endif
}
};
@ -784,10 +804,10 @@ TEST_XML(document_save_file_text, "<node/>")
temp_file f;
CHECK(doc.save_file(f.path, STR(""), format_no_declaration | format_save_file_text));
CHECK(test_file_contents(f.path, "<node />\n", 9) || test_file_contents(f.path, "<node />\r\n", 10));
CHECK(test_file_contents(f.path, "<node />\n", 9) || test_file_contents(f.path, "<node />\r\n", 10));
CHECK(doc.save_file(f.path, STR(""), format_no_declaration));
CHECK(test_file_contents(f.path, "<node />\n", 9));
CHECK(test_file_contents(f.path, "<node />\n", 9));
}
TEST_XML(document_save_file_wide_text, "<node/>")
@ -799,10 +819,10 @@ TEST_XML(document_save_file_wide_text, "<node/>")
std::copy(f.path, f.path + strlen(f.path) + 1, wpath + 0);
CHECK(doc.save_file(wpath, STR(""), format_no_declaration | format_save_file_text));
CHECK(test_file_contents(f.path, "<node />\n", 9) || test_file_contents(f.path, "<node />\r\n", 10));
CHECK(test_file_contents(f.path, "<node />\n", 9) || test_file_contents(f.path, "<node />\r\n", 10));
CHECK(doc.save_file(wpath, STR(""), format_no_declaration));
CHECK(test_file_contents(f.path, "<node />\n", 9));
CHECK(test_file_contents(f.path, "<node />\n", 9));
}
TEST_XML(document_save_file_leak, "<node/>")
@ -926,32 +946,30 @@ inline void check_utftest_document(const xml_document& doc)
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"
};
{
"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"};
xml_encoding 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
};
{
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)
{
@ -967,32 +985,30 @@ TEST(document_load_file_convert_auto)
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"
};
{
"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"};
xml_encoding 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
};
{
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)
{
@ -1021,30 +1037,28 @@ TEST(document_load_file_convert_specific)
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",
}
};
{
{
"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",
}};
xml_encoding encodings[] =
{
encoding_utf16, encoding_utf16, encoding_utf16,
encoding_utf32, encoding_utf32, encoding_utf32
};
{
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)
{
@ -1084,24 +1098,22 @@ TEST(document_load_file_convert_native_endianness)
struct file_data_t
{
const char* path;
xml_encoding encoding;
const char* path;
xml_encoding encoding;
char* data;
size_t size;
char* data;
size_t size;
};
TEST(document_contents_preserve)
{
file_data_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}
};
{
{"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)
@ -1133,10 +1145,9 @@ TEST(document_contents_preserve)
TEST(document_contents_preserve_latin1)
{
file_data_t files[] =
{
{"tests/data/latintest_utf8.xml", encoding_utf8, 0, 0},
{"tests/data/latintest_latin1.xml", encoding_latin1, 0, 0}
};
{
{"tests/data/latintest_utf8.xml", encoding_utf8, 0, 0},
{"tests/data/latintest_latin1.xml", encoding_latin1, 0, 0}};
// load files in memory
for (unsigned int i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
@ -1216,18 +1227,17 @@ TEST(document_convert_invalid_utf16)
TEST(document_load_buffer_empty)
{
xml_encoding encodings[] =
{
encoding_auto,
encoding_utf8,
encoding_utf16_le,
encoding_utf16_be,
encoding_utf16,
encoding_utf32_le,
encoding_utf32_be,
encoding_utf32,
encoding_wchar,
encoding_latin1
};
{
encoding_auto,
encoding_utf8,
encoding_utf16_le,
encoding_utf16_be,
encoding_utf16,
encoding_utf32_le,
encoding_utf32_be,
encoding_utf32,
encoding_wchar,
encoding_latin1};
char buffer[1];
@ -1252,18 +1262,17 @@ TEST(document_load_buffer_empty)
TEST(document_load_buffer_empty_fragment)
{
xml_encoding encodings[] =
{
encoding_auto,
encoding_utf8,
encoding_utf16_le,
encoding_utf16_be,
encoding_utf16,
encoding_utf32_le,
encoding_utf32_be,
encoding_utf32,
encoding_wchar,
encoding_latin1
};
{
encoding_auto,
encoding_utf8,
encoding_utf16_le,
encoding_utf16_be,
encoding_utf16,
encoding_utf32_le,
encoding_utf32_be,
encoding_utf32,
encoding_wchar,
encoding_latin1};
char buffer[1];
@ -1390,91 +1399,92 @@ TEST(document_load_buffer_inplace_short)
#ifndef PUGIXML_NO_EXCEPTIONS
TEST(document_load_exceptions)
{
bool thrown = false;
bool thrown = false;
try
{
xml_document doc;
if (!doc.load_string(STR("<node attribute='value"))) throw std::bad_alloc();
try
{
xml_document doc;
if (!doc.load_string(STR("<node attribute='value")))
throw std::bad_alloc();
CHECK_FORCE_FAIL("Expected parsing failure");
}
catch (const std::bad_alloc&)
{
thrown = true;
}
CHECK_FORCE_FAIL("Expected parsing failure");
}
catch (const std::bad_alloc&)
{
thrown = true;
}
CHECK(thrown);
CHECK(thrown);
}
#endif
TEST_XML_FLAGS(document_element, "<?xml version='1.0'?><node><child/></node><!---->", parse_default | parse_declaration | parse_comments)
{
CHECK(doc.document_element() == doc.child(STR("node")));
CHECK(doc.document_element() == doc.child(STR("node")));
}
TEST_XML_FLAGS(document_element_absent, "<!---->", parse_comments | parse_fragment)
{
CHECK(doc.document_element() == xml_node());
CHECK(doc.document_element() == xml_node());
}
TEST_XML(document_reset, "<node><child/></node>")
{
CHECK(doc.first_child());
CHECK(doc.first_child());
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
CHECK(doc.load_string(STR("<node/>")));
CHECK(doc.first_child());
CHECK_NODE(doc, STR("<node/>"));
CHECK(doc.load_string(STR("<node/>")));
CHECK(doc.first_child());
CHECK_NODE(doc, STR("<node/>"));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
}
TEST(document_reset_empty)
{
xml_document doc;
xml_document doc;
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
doc.reset();
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
}
TEST_XML(document_reset_copy, "<node><child/></node>")
{
xml_document doc2;
xml_document doc2;
CHECK_NODE(doc2, STR(""));
CHECK_NODE(doc2, STR(""));
doc2.reset(doc);
doc2.reset(doc);
CHECK_NODE(doc2, STR("<node><child/></node>"));
CHECK(doc.first_child() != doc2.first_child());
CHECK_NODE(doc2, STR("<node><child/></node>"));
CHECK(doc.first_child() != doc2.first_child());
doc.reset(doc2);
doc.reset(doc2);
CHECK_NODE(doc, STR("<node><child/></node>"));
CHECK(doc.first_child() != doc2.first_child());
CHECK_NODE(doc, STR("<node><child/></node>"));
CHECK(doc.first_child() != doc2.first_child());
CHECK(doc.first_child().offset_debug() == -1);
CHECK(doc.first_child().offset_debug() == -1);
}
TEST_XML(document_reset_copy_self, "<node><child/></node>")
{
CHECK_NODE(doc, STR("<node><child/></node>"));
CHECK_NODE(doc, STR("<node><child/></node>"));
doc.reset(doc);
doc.reset(doc);
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
CHECK(!doc.first_child());
CHECK_NODE(doc, STR(""));
}
TEST(document_load_buffer_utf_truncated)
@ -1487,20 +1497,20 @@ TEST(document_load_buffer_utf_truncated)
struct document_data_t
{
xml_encoding encoding;
xml_encoding encoding;
const unsigned char* data;
size_t size;
const unsigned char* data;
size_t size;
};
const document_data_t data[] =
{
{ encoding_utf8, utf8, sizeof(utf8) },
{ encoding_utf16_be, utf16_be, sizeof(utf16_be) },
{ encoding_utf16_le, utf16_le, sizeof(utf16_le) },
{ encoding_utf32_be, utf32_be, sizeof(utf32_be) },
{ encoding_utf32_le, utf32_le, sizeof(utf32_le) },
};
{
{encoding_utf8, utf8, sizeof(utf8)},
{encoding_utf16_be, utf16_be, sizeof(utf16_be)},
{encoding_utf16_le, utf16_le, sizeof(utf16_le)},
{encoding_utf32_be, utf32_be, sizeof(utf32_be)},
{encoding_utf32_le, utf32_le, sizeof(utf32_le)},
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{
@ -1520,11 +1530,11 @@ TEST(document_load_buffer_utf_truncated)
const char_t* name = doc.first_child().name();
#ifdef PUGIXML_WCHAR_MODE
#ifdef PUGIXML_WCHAR_MODE
CHECK(name[0] == 0x20ac && name[1] == 0);
#else
#else
CHECK_STRING(name, "\xe2\x82\xac");
#endif
#endif
}
else
{
@ -1565,11 +1575,11 @@ TEST(document_load_stream_truncated)
{
const char_t* name = doc.first_child().name();
#ifdef PUGIXML_WCHAR_MODE
#ifdef PUGIXML_WCHAR_MODE
CHECK(name[0] == 0x20ac && name[1] == 0);
#else
#else
CHECK_STRING(name, "\xe2\x82\xac");
#endif
#endif
}
}
}
@ -1594,14 +1604,13 @@ TEST(document_alignment)
TEST(document_convert_out_of_memory)
{
file_data_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},
{"tests/data/latintest_latin1.xml", encoding_latin1, 0, 0}
};
{
{"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},
{"tests/data/latintest_latin1.xml", encoding_latin1, 0, 0}};
// load files in memory
for (unsigned int i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
@ -1761,7 +1770,7 @@ TEST(document_move_empty_zero_alloc)
test_runner::_memory_fail_threshold = 1;
for (int i = 1; i < 32; ++i)
docs[i] = std::move(docs[i-1]);
docs[i] = std::move(docs[i - 1]);
delete[] docs;
}
@ -1776,7 +1785,7 @@ TEST(document_move_repeated_zero_alloc)
test_runner::_memory_fail_threshold = 1;
for (int i = 1; i < 32; ++i)
docs[i] = std::move(docs[i-1]);
docs[i] = std::move(docs[i - 1]);
for (int i = 0; i < 31; ++i)
CHECK(!docs[i].first_child());
@ -1797,15 +1806,15 @@ TEST(document_move_compact_fail)
int safe_count = 21;
for (int i = 1; i <= safe_count; ++i)
docs[i] = std::move(docs[i-1]);
docs[i] = std::move(docs[i - 1]);
CHECK_ALLOC_FAIL(docs[safe_count+1] = std::move(docs[safe_count]));
CHECK_ALLOC_FAIL(docs[safe_count + 1] = std::move(docs[safe_count]));
for (int i = 0; i < safe_count; ++i)
CHECK(!docs[i].first_child());
CHECK_NODE(docs[safe_count], STR("<node><child/></node>"));
CHECK(!docs[safe_count+1].first_child());
CHECK(!docs[safe_count + 1].first_child());
}
#endif
#endif

View file

@ -3,9 +3,9 @@
#include <limits>
#include <string>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <limits.h>
using namespace pugi;
@ -174,7 +174,7 @@ TEST_XML(dom_attr_assign_large_number_float, "<node attr='' />")
node.attribute(STR("attr")) = std::numeric_limits<float>::max();
CHECK(test_node(node, STR("<node attr=\"3.40282347e+038\"/>"), STR(""), format_raw) ||
test_node(node, STR("<node attr=\"3.40282347e+38\"/>"), STR(""), format_raw));
test_node(node, STR("<node attr=\"3.40282347e+38\"/>"), STR(""), format_raw));
}
TEST_XML(dom_attr_assign_large_number_double, "<node attr='' />")
@ -880,12 +880,12 @@ TEST(dom_node_declaration_name)
TEST(dom_node_declaration_attributes)
{
xml_document doc;
xml_node node = doc.append_child(node_declaration);
node.append_attribute(STR("version")) = STR("1.0");
node.append_attribute(STR("encoding")) = STR("utf-8");
xml_document doc;
xml_node node = doc.append_child(node_declaration);
node.append_attribute(STR("version")) = STR("1.0");
node.append_attribute(STR("encoding")) = STR("utf-8");
CHECK_NODE(doc, STR("<?xml version=\"1.0\" encoding=\"utf-8\"?>"));
CHECK_NODE(doc, STR("<?xml version=\"1.0\" encoding=\"utf-8\"?>"));
}
TEST(dom_node_declaration_top_level)
@ -926,7 +926,8 @@ TEST(dom_string_out_of_memory)
const unsigned int length = 65536;
static char_t string[length + 1];
for (unsigned int i = 0; i < length; ++i) string[i] = 'a';
for (unsigned int i = 0; i < length; ++i)
string[i] = 'a';
string[length] = 0;
xml_document doc;
@ -976,8 +977,8 @@ TEST(dom_node_out_of_memory)
xml_attribute a = n.append_attribute(STR("a"));
CHECK(a);
CHECK_ALLOC_FAIL(while (n.append_child(node_comment)) { /* nop */ });
CHECK_ALLOC_FAIL(while (n.append_attribute(STR("b"))) { /* nop */ });
CHECK_ALLOC_FAIL(while (n.append_child(node_comment)){/* nop */});
CHECK_ALLOC_FAIL(while (n.append_attribute(STR("b"))){/* nop */});
// verify all node modification operations
CHECK_ALLOC_FAIL(CHECK(!n.append_child()));
@ -1005,7 +1006,8 @@ TEST(dom_node_memory_limit)
const unsigned int length = 65536;
static char_t string[length + 1];
for (unsigned int i = 0; i < length; ++i) string[i] = 'a';
for (unsigned int i = 0; i < length; ++i)
string[i] = 'a';
string[length] = 0;
test_runner::_memory_fail_threshold = 32768 * 2 + sizeof(string);
@ -1024,7 +1026,8 @@ TEST(dom_node_memory_limit_pi)
const unsigned int length = 65536;
static char_t string[length + 1];
for (unsigned int i = 0; i < length; ++i) string[i] = 'a';
for (unsigned int i = 0; i < length; ++i)
string[i] = 'a';
string[length] = 0;
test_runner::_memory_fail_threshold = 32768 * 2 + sizeof(string);
@ -1073,15 +1076,15 @@ TEST(dom_node_doctype_copy)
TEST(dom_node_doctype_value)
{
xml_document doc;
xml_node node = doc.append_child(node_doctype);
xml_document doc;
xml_node node = doc.append_child(node_doctype);
CHECK(node.type() == node_doctype);
CHECK_STRING(node.value(), STR(""));
CHECK_NODE(node, STR("<!DOCTYPE>"));
CHECK(node.type() == node_doctype);
CHECK_STRING(node.value(), STR(""));
CHECK_NODE(node, STR("<!DOCTYPE>"));
CHECK(node.set_value(STR("id [ foo ]")));
CHECK_NODE(node, STR("<!DOCTYPE id [ foo ]>"));
CHECK(node.set_value(STR("id [ foo ]")));
CHECK_NODE(node, STR("<!DOCTYPE id [ foo ]>"));
}
TEST_XML(dom_node_append_buffer_native, "<node>test</node>")
@ -1112,7 +1115,6 @@ TEST_XML(dom_node_append_buffer_convert, "<node>test</node>")
CHECK_NODE(doc, STR("<node>test<n/><n/></node>"));
}
TEST_XML(dom_node_append_buffer_remove, "<node>test</node>")
{
xml_node node = doc.child(STR("node"));
@ -1127,15 +1129,21 @@ TEST_XML(dom_node_append_buffer_remove, "<node>test</node>")
CHECK_NODE(doc, STR("<node>test<child1 id=\"1\"/><child2>text</child2><child3/><child1 id=\"1\"/><child2>text</child2><child3/></node>"));
while (node.remove_child(STR("child2"))) {}
while (node.remove_child(STR("child2")))
{
}
CHECK_NODE(doc, STR("<node>test<child1 id=\"1\"/><child3/><child1 id=\"1\"/><child3/></node>"));
while (node.remove_child(STR("child1"))) {}
while (node.remove_child(STR("child1")))
{
}
CHECK_NODE(doc, STR("<node>test<child3/><child3/></node>"));
while (node.remove_child(STR("child3"))) {}
while (node.remove_child(STR("child3")))
{
}
CHECK_NODE(doc, STR("<node>test</node>"));
@ -1665,7 +1673,8 @@ TEST(dom_node_copy_declaration_empty_name)
CHECK_STRING(decl2.name(), STR(""));
}
template <typename T> bool fp_equal(T lhs, T rhs)
template <typename T>
bool fp_equal(T lhs, T rhs)
{
// Several compilers compare float/double values on x87 stack without proper rounding
// This causes roundtrip tests to fail, although they correctly preserve the data.
@ -1703,13 +1712,13 @@ TEST(dom_fp_roundtrip_min_max_double)
}
const double fp_roundtrip_base[] =
{
0.31830988618379067154,
0.43429448190325182765,
0.57721566490153286061,
0.69314718055994530942,
0.70710678118654752440,
0.78539816339744830962,
{
0.31830988618379067154,
0.43429448190325182765,
0.57721566490153286061,
0.69314718055994530942,
0.70710678118654752440,
0.78539816339744830962,
};
TEST(dom_fp_roundtrip_float)
@ -1738,17 +1747,17 @@ TEST(dom_fp_roundtrip_double)
{
for (size_t i = 0; i < sizeof(fp_roundtrip_base) / sizeof(fp_roundtrip_base[0]); ++i)
{
#if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(__MWERKS__)
#if (defined(_MSC_VER) && _MSC_VER < 1400) || defined(__MWERKS__)
// Not all runtime libraries guarantee roundtripping for denormals
if (e == -1021 && fp_roundtrip_base[i] < 0.5)
continue;
#endif
#endif
#ifdef __DMC__
#ifdef __DMC__
// Digital Mars C does not roundtrip on exactly one combination
if (e == -12 && i == 1)
continue;
#endif
#endif
double value = ldexp(fp_roundtrip_base[i], e);

View file

@ -8,57 +8,57 @@ using namespace pugi;
TEST_XML_FLAGS(dom_text_empty, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text());
CHECK(node.child(STR("b")).text());
CHECK(!node.child(STR("c")).text());
CHECK(!node.child(STR("d")).text());
CHECK(!xml_node().text());
CHECK(!xml_text());
CHECK(node.child(STR("a")).text());
CHECK(node.child(STR("b")).text());
CHECK(!node.child(STR("c")).text());
CHECK(!node.child(STR("d")).text());
CHECK(!xml_node().text());
CHECK(!xml_text());
generic_empty_test(node.child(STR("a")).text());
generic_empty_test(node.child(STR("a")).text());
}
TEST_XML(dom_text_bool_ops, "<node>foo</node>")
{
generic_bool_ops_test(doc.child(STR("node")).text());
generic_bool_ops_test(doc.child(STR("node")).text());
}
TEST_XML_FLAGS(dom_text_get, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().get(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo"));
CHECK_STRING(node.child(STR("a")).text().get(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().get(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar"));
CHECK_STRING(node.child(STR("b")).text().get(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().get(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR(""));
CHECK_STRING(node.child(STR("c")).text().get(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR(""));
CHECK_STRING(node.child(STR("d")).text().get(), STR(""));
CHECK_STRING(node.child(STR("d")).text().get(), STR(""));
CHECK_STRING(xml_node().text().get(), STR(""));
CHECK_STRING(xml_node().text().get(), STR(""));
}
TEST_XML_FLAGS(dom_text_as_string, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().as_string(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR(""));
CHECK_STRING(node.child(STR("c")).text().as_string(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR(""));
CHECK_STRING(node.child(STR("d")).text().as_string(), STR(""));
CHECK_STRING(node.child(STR("d")).text().as_string(), STR(""));
CHECK_STRING(xml_node().text().as_string(), STR(""));
CHECK_STRING(xml_node().text().as_string(), STR(""));
}
TEST_XML(dom_text_as_int, "<node><text1>1</text1><text2>-1</text2><text3>-2147483648</text3><text4>2147483647</text4><text5>0</text5></node>")
@ -70,19 +70,19 @@ TEST_XML(dom_text_as_int, "<node><text1>1</text1><text2>-1</text2><text3>-214748
CHECK(node.child(STR("text2")).text().as_int() == -1);
CHECK(node.child(STR("text3")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text4")).text().as_int() == 2147483647);
CHECK(node.child(STR("text5")).text().as_int() == 0);
CHECK(node.child(STR("text5")).text().as_int() == 0);
}
TEST_XML(dom_text_as_int_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>-0x20</text4><text5>-0x80000000</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_int() == 1451);
CHECK(node.child(STR("text3")).text().as_int() == 255);
CHECK(node.child(STR("text4")).text().as_int() == -32);
CHECK(node.child(STR("text5")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text6")).text().as_int() == 0);
CHECK(node.child(STR("text1")).text().as_int() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_int() == 1451);
CHECK(node.child(STR("text3")).text().as_int() == 255);
CHECK(node.child(STR("text4")).text().as_int() == -32);
CHECK(node.child(STR("text5")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text6")).text().as_int() == 0);
}
TEST_XML(dom_text_as_uint, "<node><text1>0</text1><text2>1</text2><text3>2147483647</text3><text4>4294967295</text4><text5>0</text5></node>")
@ -94,29 +94,29 @@ TEST_XML(dom_text_as_uint, "<node><text1>0</text1><text2>1</text2><text3>2147483
CHECK(node.child(STR("text2")).text().as_uint() == 1);
CHECK(node.child(STR("text3")).text().as_uint() == 2147483647);
CHECK(node.child(STR("text4")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text5")).text().as_uint() == 0);
CHECK(node.child(STR("text5")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_uint_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>0x20</text4><text5>0xFFFFFFFF</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_uint() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_uint() == 1451);
CHECK(node.child(STR("text3")).text().as_uint() == 255);
CHECK(node.child(STR("text4")).text().as_uint() == 32);
CHECK(node.child(STR("text5")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text6")).text().as_uint() == 0);
CHECK(node.child(STR("text1")).text().as_uint() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_uint() == 1451);
CHECK(node.child(STR("text3")).text().as_uint() == 255);
CHECK(node.child(STR("text4")).text().as_uint() == 32);
CHECK(node.child(STR("text5")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text6")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_integer_space, "<node><text1> \t\n1234</text1><text2>\n\t 0x123</text2><text3>- 16</text3><text4>- 0x10</text4></node>")
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 1234);
CHECK(node.child(STR("text2")).text().as_int() == 291);
CHECK(node.child(STR("text3")).text().as_int() == 0);
CHECK(node.child(STR("text4")).text().as_int() == 0);
CHECK(node.child(STR("text1")).text().as_int() == 1234);
CHECK(node.child(STR("text2")).text().as_int() == 291);
CHECK(node.child(STR("text3")).text().as_int() == 0);
CHECK(node.child(STR("text4")).text().as_int() == 0);
}
TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
@ -211,42 +211,42 @@ TEST_XML(dom_text_as_ullong_hex, "<node><text1>0777</text1><text2>0x5ab</text2><
TEST_XML(dom_text_get_no_state, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK(!t);
CHECK(t.get() && *t.get() == 0);
CHECK(!node.first_child());
CHECK(!t);
CHECK(t.get() && *t.get() == 0);
CHECK(!node.first_child());
node.append_child(node_pcdata);
node.append_child(node_pcdata);
CHECK(t);
CHECK_STRING(t.get(), STR(""));
CHECK(t);
CHECK_STRING(t.get(), STR(""));
node.first_child().set_value(STR("test"));
node.first_child().set_value(STR("test"));
CHECK(t);
CHECK_STRING(t.get(), STR("test"));
CHECK(t);
CHECK_STRING(t.get(), STR("test"));
}
TEST_XML(dom_text_set, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR("boo"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("boo"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
t.set(STR("foobarfoobar"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
}
TEST_XML(dom_text_assign, "<node/>")
@ -399,49 +399,49 @@ TEST_XML(dom_text_set_value_llong, "<node/>")
TEST_XML(dom_text_middle, "<node><c1>notthisone</c1>text<c2/></node>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK_STRING(t.get(), STR("text"));
t.set(STR("notext"));
CHECK_STRING(t.get(), STR("text"));
t.set(STR("notext"));
CHECK_NODE(node, STR("<node><c1>notthisone</c1>notext<c2/></node>"));
CHECK(node.remove_child(t.data()));
CHECK_NODE(node, STR("<node><c1>notthisone</c1>notext<c2/></node>"));
CHECK(node.remove_child(t.data()));
CHECK(!t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/></node>"));
CHECK(!t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/></node>"));
t.set(STR("yestext"));
t.set(STR("yestext"));
CHECK(t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/>yestext</node>"));
CHECK(t.data() == node.last_child());
CHECK(t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/>yestext</node>"));
CHECK(t.data() == node.last_child());
}
TEST_XML_FLAGS(dom_text_data, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child());
CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child());
CHECK(!node.child(STR("c")).text().data());
CHECK(!node.child(STR("d")).text().data());
CHECK(!xml_text().data());
CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child());
CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child());
CHECK(!node.child(STR("c")).text().data());
CHECK(!node.child(STR("d")).text().data());
CHECK(!xml_text().data());
}
TEST(dom_text_defaults)
{
xml_text text;
xml_text text;
CHECK_STRING(text.as_string(STR("foo")), STR("foo"));
CHECK(text.as_int(42) == 42);
CHECK(text.as_uint(42) == 42);
CHECK(text.as_double(42) == 42);
CHECK(text.as_float(42) == 42);
CHECK(text.as_bool(true) == true);
CHECK_STRING(text.as_string(STR("foo")), STR("foo"));
CHECK(text.as_int(42) == 42);
CHECK(text.as_uint(42) == 42);
CHECK(text.as_double(42) == 42);
CHECK(text.as_float(42) == 42);
CHECK(text.as_bool(true) == true);
#ifdef PUGIXML_HAS_LONG_LONG
CHECK(text.as_llong(42) == 42);
CHECK(text.as_ullong(42) == 42);
CHECK(text.as_llong(42) == 42);
CHECK(text.as_ullong(42) == 42);
#endif
}

View file

@ -4,28 +4,34 @@
#include "test.hpp"
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <utility>
#include <vector>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
#include "helpers.hpp"
using namespace pugi;
#ifdef PUGIXML_NO_STL
template <typename I> static I move_iter(I base, int n)
template <typename I>
static I move_iter(I base, int n)
{
if (n > 0) while (n--) ++base;
else while (n++) --base;
if (n > 0)
while (n--)
++base;
else
while (n++)
--base;
return base;
}
#else
template <typename I> static I move_iter(I base, int n)
template <typename I>
static I move_iter(I base, int n)
{
std::advance(base, n);
return base;
@ -237,18 +243,18 @@ TEST_XML(dom_attr_as_ullong_hex, "<node attr1='0777' attr2='0x5ab' attr3='0XFf'
TEST(dom_attr_defaults)
{
xml_attribute attr;
xml_attribute attr;
CHECK_STRING(attr.as_string(STR("foo")), STR("foo"));
CHECK(attr.as_int(42) == 42);
CHECK(attr.as_uint(42) == 42);
CHECK(attr.as_double(42) == 42);
CHECK(attr.as_float(42) == 42);
CHECK(attr.as_bool(true) == true);
CHECK_STRING(attr.as_string(STR("foo")), STR("foo"));
CHECK(attr.as_int(42) == 42);
CHECK(attr.as_uint(42) == 42);
CHECK(attr.as_double(42) == 42);
CHECK(attr.as_float(42) == 42);
CHECK(attr.as_bool(true) == true);
#ifdef PUGIXML_HAS_LONG_LONG
CHECK(attr.as_llong(42) == 42);
CHECK(attr.as_ullong(42) == 42);
CHECK(attr.as_llong(42) == 42);
CHECK(attr.as_ullong(42) == 42);
#endif
}
@ -339,18 +345,18 @@ TEST_XML(dom_attr_iterator_invalidate, "<node><node1 attr1='0'/><node2 attr1='0'
TEST_XML(dom_attr_iterator_const, "<node attr1='0' attr2='1'/>")
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
const xml_attribute_iterator i1 = node.attributes_begin();
const xml_attribute_iterator i2 = ++xml_attribute_iterator(i1);
const xml_attribute_iterator i3 = ++xml_attribute_iterator(i2);
const xml_attribute_iterator i1 = node.attributes_begin();
const xml_attribute_iterator i2 = ++xml_attribute_iterator(i1);
const xml_attribute_iterator i3 = ++xml_attribute_iterator(i2);
CHECK(*i1 == node.attribute(STR("attr1")));
CHECK(*i2 == node.attribute(STR("attr2")));
CHECK(i3 == node.attributes_end());
CHECK(*i1 == node.attribute(STR("attr1")));
CHECK(*i2 == node.attribute(STR("attr2")));
CHECK(i3 == node.attributes_end());
CHECK_STRING(i1->name(), STR("attr1"));
CHECK_STRING(i2->name(), STR("attr2"));
CHECK_STRING(i1->name(), STR("attr1"));
CHECK_STRING(i2->name(), STR("attr2"));
}
TEST_XML(dom_node_bool_ops, "<node/>")
@ -461,18 +467,18 @@ TEST_XML(dom_node_iterator_invalidate, "<node><node1><child1/></node1><node2><ch
TEST_XML(dom_node_iterator_const, "<node><child1/><child2/></node>")
{
xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
const xml_node_iterator i1 = node.begin();
const xml_node_iterator i2 = ++xml_node_iterator(i1);
const xml_node_iterator i3 = ++xml_node_iterator(i2);
const xml_node_iterator i1 = node.begin();
const xml_node_iterator i2 = ++xml_node_iterator(i1);
const xml_node_iterator i3 = ++xml_node_iterator(i2);
CHECK(*i1 == node.child(STR("child1")));
CHECK(*i2 == node.child(STR("child2")));
CHECK(i3 == node.end());
CHECK(*i1 == node.child(STR("child1")));
CHECK(*i2 == node.child(STR("child2")));
CHECK(i3 == node.end());
CHECK_STRING(i1->name(), STR("child1"));
CHECK_STRING(i2->name(), STR("child2"));
CHECK_STRING(i1->name(), STR("child1"));
CHECK_STRING(i2->name(), STR("child2"));
}
TEST_XML(dom_node_parent, "<node><child/></node>")
@ -659,11 +665,13 @@ struct find_predicate_const
{
bool result;
find_predicate_const(bool result_): result(result_)
find_predicate_const(bool result_)
: result(result_)
{
}
template <typename T> bool operator()(const T&) const
template <typename T>
bool operator()(const T&) const
{
return result;
}
@ -673,18 +681,20 @@ struct find_predicate_prefix
{
const char_t* prefix;
find_predicate_prefix(const char_t* prefix_): prefix(prefix_)
find_predicate_prefix(const char_t* prefix_)
: prefix(prefix_)
{
}
template <typename T> bool operator()(const T& obj) const
template <typename T>
bool operator()(const T& obj) const
{
#ifdef PUGIXML_WCHAR_MODE
#ifdef PUGIXML_WCHAR_MODE
// can't use wcsncmp here because of a bug in DMC
return std::basic_string<char_t>(obj.name()).compare(0, wcslen(prefix), prefix) == 0;
#else
#else
return strncmp(obj.name(), prefix, strlen(prefix)) == 0;
#endif
#endif
}
};
@ -782,13 +792,15 @@ TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></
CHECK(doc.first_element_by_path(STR("//node")) == doc.child(STR("node")));
}
struct test_walker: xml_tree_walker
struct test_walker : xml_tree_walker
{
std::basic_string<char_t> log;
unsigned int call_count;
unsigned int stop_count;
test_walker(unsigned int stop_count_ = 0): call_count(0), stop_count(stop_count_)
test_walker(unsigned int stop_count_ = 0)
: call_count(0)
, stop_count(stop_count_)
{
}
@ -797,14 +809,14 @@ struct test_walker: xml_tree_walker
char buf[32];
sprintf(buf, "%d", depth());
#ifdef PUGIXML_WCHAR_MODE
#ifdef PUGIXML_WCHAR_MODE
wchar_t wbuf[32];
std::copy(buf, buf + strlen(buf) + 1, &wbuf[0]);
return std::basic_string<char_t>(wbuf);
#else
#else
return std::basic_string<char_t>(buf);
#endif
#endif
}
virtual bool begin(xml_node& node) PUGIXML_OVERRIDE
@ -935,7 +947,7 @@ TEST_XML_FLAGS(dom_offset_debug, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>pcd
TEST(dom_offset_debug_encoding)
{
char buf[] = { 0, '<', 0, 'n', 0, '/', 0, '>' };
char buf[] = {0, '<', 0, 'n', 0, '/', 0, '>'};
xml_document doc;
CHECK(doc.load_buffer(buf, sizeof(buf)));
@ -979,17 +991,17 @@ TEST_XML(dom_internal_object, "<node attr='value'>value</node>")
CHECK(xml_node().internal_object() == 0);
CHECK(xml_attribute().internal_object() == 0);
CHECK(node.internal_object() != 0);
CHECK(value.internal_object() != 0);
CHECK(node.internal_object() != value.internal_object());
CHECK(node.internal_object() != 0);
CHECK(value.internal_object() != 0);
CHECK(node.internal_object() != value.internal_object());
CHECK(attr.internal_object() != 0);
CHECK(attr.internal_object() != 0);
xml_node node_copy = node;
CHECK(node_copy.internal_object() == node.internal_object());
xml_node node_copy = node;
CHECK(node_copy.internal_object() == node.internal_object());
xml_attribute attr_copy = attr;
CHECK(attr_copy.internal_object() == attr.internal_object());
xml_attribute attr_copy = attr;
CHECK(attr_copy.internal_object() == attr.internal_object());
}
TEST_XML(dom_hash_value, "<node attr='value'>value</node>")
@ -1001,17 +1013,17 @@ TEST_XML(dom_hash_value, "<node attr='value'>value</node>")
CHECK(xml_node().hash_value() == 0);
CHECK(xml_attribute().hash_value() == 0);
CHECK(node.hash_value() != 0);
CHECK(value.hash_value() != 0);
CHECK(node.hash_value() != value.hash_value());
CHECK(node.hash_value() != 0);
CHECK(value.hash_value() != 0);
CHECK(node.hash_value() != value.hash_value());
CHECK(attr.hash_value() != 0);
CHECK(attr.hash_value() != 0);
xml_node node_copy = node;
CHECK(node_copy.hash_value() == node.hash_value());
xml_node node_copy = node;
CHECK(node_copy.hash_value() == node.hash_value());
xml_attribute attr_copy = attr;
CHECK(attr_copy.hash_value() == attr.hash_value());
xml_attribute attr_copy = attr;
CHECK(attr_copy.hash_value() == attr.hash_value());
}
TEST_XML(dom_node_named_iterator, "<node><node1><child/></node1><node2><child/><child/></node2><node3/><node4><child/><x/></node4></node>")
@ -1121,15 +1133,15 @@ TEST_XML(dom_ranged_for, "<node attr1='1' attr2='2'><test>3</test><fake>5</fake>
{
int index = 1;
for (xml_node n: doc.children())
for (xml_node n : doc.children())
{
for (xml_attribute a: n.attributes())
for (xml_attribute a : n.attributes())
{
CHECK(a.as_int() == index);
index++;
}
for (xml_node c: n.children(STR("test")))
for (xml_node c : n.children(STR("test")))
{
CHECK(c.text().as_int() == index);
index++;

View file

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

View file

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

View file

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

View file

@ -5,7 +5,6 @@
// Check header guards
#include "../src/pugixml.hpp"
#include "../src/pugixml.hpp"
using namespace pugi;

View file

@ -5,7 +5,6 @@
// Check header guards
#include "../src/pugixml.hpp"
#include "../src/pugixml.hpp"
using namespace pugi;

View file

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

View file

@ -1,5 +1,5 @@
// Tests compatibility with string/iostream
#include <string>
#include "../src/pugixml.hpp"
#include <istream>
#include <ostream>
#include <string>

View file

@ -1,7 +1,7 @@
#include "test.hpp"
#include "writer_string.hpp"
#include "allocator.hpp"
#include "writer_string.hpp"
#include <string>
#include <vector>
@ -10,28 +10,28 @@ using namespace pugi;
namespace
{
int page_allocs = 0;
int page_deallocs = 0;
int page_allocs = 0;
int page_deallocs = 0;
bool is_page(size_t size)
{
return size >= 16384;
}
void* allocate(size_t size)
{
void* ptr = memory_allocate(size);
page_allocs += is_page(memory_size(ptr));
return ptr;
}
void deallocate(void* ptr)
{
page_deallocs += is_page(memory_size(ptr));
memory_deallocate(ptr);
}
bool is_page(size_t size)
{
return size >= 16384;
}
void* allocate(size_t size)
{
void* ptr = memory_allocate(size);
page_allocs += is_page(memory_size(ptr));
return ptr;
}
void deallocate(void* ptr)
{
page_deallocs += is_page(memory_size(ptr));
memory_deallocate(ptr);
}
} // namespace
TEST(memory_custom_memory_management)
{
page_allocs = page_deallocs = 0;
@ -116,7 +116,7 @@ TEST(memory_large_allocations)
}
// prune
for (node = doc.first_child(); node; )
for (node = doc.first_child(); node;)
{
xml_node next = node.next_sibling().next_sibling();
@ -229,7 +229,8 @@ TEST(memory_string_allocate_decreasing)
std::basic_string<char_t> s = STR("ab");
for (int i = 0; i < 17; ++i) s += s;
for (int i = 0; i < 17; ++i)
s += s;
for (int j = 0; j < 17; ++j)
{
@ -286,7 +287,8 @@ TEST(memory_string_allocate_decreasing_inplace)
std::basic_string<char_t> s = STR("ab");
for (int i = 0; i < 17; ++i) s += s;
for (int i = 0; i < 17; ++i)
s += s;
for (int j = 0; j < 17; ++j)
{

View file

@ -279,132 +279,132 @@ TEST(parse_ws_pcdata_parse)
static int get_tree_node_count(xml_node n)
{
int result = 1;
int result = 1;
for (xml_node c = n.first_child(); c; c = c.next_sibling())
result += get_tree_node_count(c);
for (xml_node c = n.first_child(); c; c = c.next_sibling())
result += get_tree_node_count(c);
return result;
return result;
}
TEST(parse_ws_pcdata_permutations)
{
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
test_data_t test_data[] =
{
// external pcdata should be discarded (whitespace or not)
{7, STR("ext1<node/>"), STR("<node/>"), 2},
{7, STR("ext1<node/>ext2"), STR("<node/>"), 2},
{7, STR(" <node/>"), STR("<node/>"), 2},
{7, STR("<node/> "), STR("<node/>"), 2},
{7, STR(" <node/> "), STR("<node/>"), 2},
// inner pcdata should be preserved
{7, STR("<node>inner</node>"), STR("<node>inner</node>"), 3},
{7, STR("<node>inner1<child/>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node>inner1<child>deep</child>inner2</node>"), STR("<node>inner1<child>deep</child>inner2</node>"), 6},
// empty pcdata nodes should never be created
{7, STR("<node>inner1<child></child>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node><child></child>inner2</node>"), STR("<node><child/>inner2</node>"), 4},
{7, STR("<node>inner1<child></child></node>"), STR("<node>inner1<child/></node>"), 4},
{7, STR("<node><child></child></node>"), STR("<node><child/></node>"), 3},
// comments, pi or other nodes should not cause pcdata creation either
{7, STR("<node><!----><child><?pi?></child><![CDATA[x]]></node>"), STR("<node><child/><![CDATA[x]]></node>"), 4},
// leading/trailing pcdata whitespace should be preserved (note: this will change if parse_ws_pcdata_trim is introduced)
{7, STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), 6},
// whitespace-only pcdata preservation depends on the parsing mode
{1, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child/><child><deep/></child></node>"), 5},
{2, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t\n\t</node>"), 13},
{4, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child> </child><child><deep> </deep></child></node>"), 7},
// current implementation of parse_ws_pcdata_single has an unfortunate bug; reproduce it here
{4, STR("<node>\t\t<!---->\n\n</node>"), STR("<node>\n\n</node>"), 3},
// error case: terminate PCDATA in the middle
{7, STR("<node>abcdef"), STR("<node>abcdef</node>"), -3},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
// error case: terminate PCDATA as early as possible
{7, STR("<node>"), STR("<node/>"), -2},
{7, STR("<node>a"), STR("<node>a</node>"), -3},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
};
test_data_t test_data[] =
{
// external pcdata should be discarded (whitespace or not)
{7, STR("ext1<node/>"), STR("<node/>"), 2},
{7, STR("ext1<node/>ext2"), STR("<node/>"), 2},
{7, STR(" <node/>"), STR("<node/>"), 2},
{7, STR("<node/> "), STR("<node/>"), 2},
{7, STR(" <node/> "), STR("<node/>"), 2},
// inner pcdata should be preserved
{7, STR("<node>inner</node>"), STR("<node>inner</node>"), 3},
{7, STR("<node>inner1<child/>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node>inner1<child>deep</child>inner2</node>"), STR("<node>inner1<child>deep</child>inner2</node>"), 6},
// empty pcdata nodes should never be created
{7, STR("<node>inner1<child></child>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node><child></child>inner2</node>"), STR("<node><child/>inner2</node>"), 4},
{7, STR("<node>inner1<child></child></node>"), STR("<node>inner1<child/></node>"), 4},
{7, STR("<node><child></child></node>"), STR("<node><child/></node>"), 3},
// comments, pi or other nodes should not cause pcdata creation either
{7, STR("<node><!----><child><?pi?></child><![CDATA[x]]></node>"), STR("<node><child/><![CDATA[x]]></node>"), 4},
// leading/trailing pcdata whitespace should be preserved (note: this will change if parse_ws_pcdata_trim is introduced)
{7, STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), 6},
// whitespace-only pcdata preservation depends on the parsing mode
{1, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child/><child><deep/></child></node>"), 5},
{2, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t\n\t</node>"), 13},
{4, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child> </child><child><deep> </deep></child></node>"), 7},
// current implementation of parse_ws_pcdata_single has an unfortunate bug; reproduce it here
{4, STR("<node>\t\t<!---->\n\n</node>"), STR("<node>\n\n</node>"), 3},
// error case: terminate PCDATA in the middle
{7, STR("<node>abcdef"), STR("<node>abcdef</node>"), -3},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
// error case: terminate PCDATA as early as possible
{7, STR("<node>"), STR("<node/>"), -2},
{7, STR("<node>a"), STR("<node>a</node>"), -3},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
};
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
for (int flag = 0; flag < 3; ++flag)
{
if (td.mask & (1 << flag))
{
unsigned int flags[] = {parse_default, parse_default | parse_ws_pcdata, parse_default | parse_ws_pcdata_single};
for (int flag = 0; flag < 3; ++flag)
{
if (td.mask & (1 << flag))
{
unsigned int flags[] = {parse_default, parse_default | parse_ws_pcdata, parse_default | parse_ws_pcdata_single};
xml_document doc;
CHECK((td.nodes > 0) == doc.load_string(td.source, flags[flag]));
CHECK_NODE(doc, td.result);
xml_document doc;
CHECK((td.nodes > 0) == doc.load_string(td.source, flags[flag]));
CHECK_NODE(doc, td.result);
int nodes = get_tree_node_count(doc);
CHECK((td.nodes < 0 ? -td.nodes : td.nodes) == nodes);
}
}
}
int nodes = get_tree_node_count(doc);
CHECK((td.nodes < 0 ? -td.nodes : td.nodes) == nodes);
}
}
}
}
TEST(parse_ws_pcdata_fragment_permutations)
{
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
test_data_t test_data[] =
{
// external pcdata should be preserved
{7, STR("ext1"), STR("ext1"), 2},
{5, STR(" "), STR(""), 1},
{2, STR(" "), STR(" "), 2},
{7, STR("ext1<node/>"), STR("ext1<node/>"), 3},
{7, STR("<node/>ext2"), STR("<node/>ext2"), 3},
{7, STR("ext1<node/>ext2"), STR("ext1<node/>ext2"), 4},
{7, STR("ext1<node1/>ext2<node2/>ext3"), STR("ext1<node1/>ext2<node2/>ext3"), 6},
{5, STR(" <node/>"), STR("<node/>"), 2},
{2, STR(" <node/>"), STR(" <node/>"), 3},
{5, STR("<node/> "), STR("<node/>"), 2},
{2, STR("<node/> "), STR("<node/> "), 3},
{5, STR(" <node/> "), STR("<node/>"), 2},
{2, STR(" <node/> "), STR(" <node/> "), 4},
{5, STR(" <node1/> <node2/> "), STR("<node1/><node2/>"), 3},
{2, STR(" <node1/> <node2/> "), STR(" <node1/> <node2/> "), 6},
};
test_data_t test_data[] =
{
// external pcdata should be preserved
{7, STR("ext1"), STR("ext1"), 2},
{5, STR(" "), STR(""), 1},
{2, STR(" "), STR(" "), 2},
{7, STR("ext1<node/>"), STR("ext1<node/>"), 3},
{7, STR("<node/>ext2"), STR("<node/>ext2"), 3},
{7, STR("ext1<node/>ext2"), STR("ext1<node/>ext2"), 4},
{7, STR("ext1<node1/>ext2<node2/>ext3"), STR("ext1<node1/>ext2<node2/>ext3"), 6},
{5, STR(" <node/>"), STR("<node/>"), 2},
{2, STR(" <node/>"), STR(" <node/>"), 3},
{5, STR("<node/> "), STR("<node/>"), 2},
{2, STR("<node/> "), STR("<node/> "), 3},
{5, STR(" <node/> "), STR("<node/>"), 2},
{2, STR(" <node/> "), STR(" <node/> "), 4},
{5, STR(" <node1/> <node2/> "), STR("<node1/><node2/>"), 3},
{2, STR(" <node1/> <node2/> "), STR(" <node1/> <node2/> "), 6},
};
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
for (int flag = 0; flag < 3; ++flag)
{
if (td.mask & (1 << flag))
{
unsigned int flags[] = {parse_default, parse_default | parse_ws_pcdata, parse_default | parse_ws_pcdata_single};
for (int flag = 0; flag < 3; ++flag)
{
if (td.mask & (1 << flag))
{
unsigned int flags[] = {parse_default, parse_default | parse_ws_pcdata, parse_default | parse_ws_pcdata_single};
xml_document doc;
CHECK((td.nodes > 0) == doc.load_string(td.source, flags[flag] | parse_fragment));
CHECK_NODE(doc, td.result);
xml_document doc;
CHECK((td.nodes > 0) == doc.load_string(td.source, flags[flag] | parse_fragment));
CHECK_NODE(doc, td.result);
int nodes = get_tree_node_count(doc);
CHECK((td.nodes < 0 ? -td.nodes : td.nodes) == nodes);
}
}
}
int nodes = get_tree_node_count(doc);
CHECK((td.nodes < 0 ? -td.nodes : td.nodes) == nodes);
}
}
}
}
TEST(parse_pcdata_no_eol)
@ -439,49 +439,48 @@ TEST(parse_pcdata_error)
TEST(parse_pcdata_trim)
{
struct test_data_t
{
const char_t* source;
const char_t* result;
unsigned int flags;
};
struct test_data_t
{
const char_t* source;
const char_t* result;
unsigned int flags;
};
test_data_t test_data[] =
{
{ STR("<node> text</node>"), STR("text"), 0 },
{ STR("<node>\t\n text</node>"), STR("text"), 0 },
{ STR("<node>text </node>"), STR("text"), 0 },
{ STR("<node>text \t\n</node>"), STR("text"), 0 },
{ STR("<node>\r\n\t text \t\n\r</node>"), STR("text"), 0 },
{ STR(" text"), STR("text"), parse_fragment },
{ STR("\t\n text"), STR("text"), parse_fragment },
{ STR("text "), STR("text"), parse_fragment },
{ STR("text \t\n"), STR("text"), parse_fragment },
{ STR("\r\n\t text \t\n\r"), STR("text"), parse_fragment },
{ STR("<node>\r\n\t text \t\n\r more \r\n\t</node>"), STR("text \t\n\r more"), 0 },
{ STR("<node>\r\n\t text \t\n\r more \r\n\t</node>"), STR("text \t\n\n more"), parse_eol },
{ STR("<node>\r\n\t text \r\n\r\n\r\n\r\n\r\n\r\n\r\n more \r\n\t</node>"), STR("text \n\n\n\n\n\n\n more"), parse_eol },
{ STR("<node> test&amp;&amp;&amp;&amp;&amp;&amp;&amp; </node>"), STR("test&amp;&amp;&amp;&amp;&amp;&amp;&amp;"), 0 },
{ STR("<node> test&amp;&amp;&amp;&amp;&amp;&amp;&amp; </node>"), STR("test&&&&&&&"), parse_escapes },
{ STR(" test&amp;&amp;&amp;&amp;&amp;&amp;&amp; "), STR("test&&&&&&&"), parse_fragment | parse_escapes },
{ STR("<node>\r\n\t text \t\n\r m&amp;&amp;e \r\n\t</node>"), STR("text \t\n\n m&&e"), parse_eol | parse_escapes }
};
test_data_t test_data[] =
{
{STR("<node> text</node>"), STR("text"), 0},
{STR("<node>\t\n text</node>"), STR("text"), 0},
{STR("<node>text </node>"), STR("text"), 0},
{STR("<node>text \t\n</node>"), STR("text"), 0},
{STR("<node>\r\n\t text \t\n\r</node>"), STR("text"), 0},
{STR(" text"), STR("text"), parse_fragment},
{STR("\t\n text"), STR("text"), parse_fragment},
{STR("text "), STR("text"), parse_fragment},
{STR("text \t\n"), STR("text"), parse_fragment},
{STR("\r\n\t text \t\n\r"), STR("text"), parse_fragment},
{STR("<node>\r\n\t text \t\n\r more \r\n\t</node>"), STR("text \t\n\r more"), 0},
{STR("<node>\r\n\t text \t\n\r more \r\n\t</node>"), STR("text \t\n\n more"), parse_eol},
{STR("<node>\r\n\t text \r\n\r\n\r\n\r\n\r\n\r\n\r\n more \r\n\t</node>"), STR("text \n\n\n\n\n\n\n more"), parse_eol},
{STR("<node> test&amp;&amp;&amp;&amp;&amp;&amp;&amp; </node>"), STR("test&amp;&amp;&amp;&amp;&amp;&amp;&amp;"), 0},
{STR("<node> test&amp;&amp;&amp;&amp;&amp;&amp;&amp; </node>"), STR("test&&&&&&&"), parse_escapes},
{STR(" test&amp;&amp;&amp;&amp;&amp;&amp;&amp; "), STR("test&&&&&&&"), parse_fragment | parse_escapes},
{STR("<node>\r\n\t text \t\n\r m&amp;&amp;e \r\n\t</node>"), STR("text \t\n\n m&&e"), parse_eol | parse_escapes}};
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
{
const test_data_t& td = test_data[i];
xml_document doc;
CHECK(doc.load_string(td.source, td.flags | parse_trim_pcdata));
xml_document doc;
CHECK(doc.load_string(td.source, td.flags | parse_trim_pcdata));
const char_t* value = doc.child(STR("node")) ? doc.child_value(STR("node")) : doc.text().get();
CHECK_STRING(value, td.result);
}
const char_t* value = doc.child(STR("node")) ? doc.child_value(STR("node")) : doc.text().get();
CHECK_STRING(value, td.result);
}
}
TEST(parse_pcdata_trim_empty)
{
unsigned int flags[] = { 0, parse_ws_pcdata, parse_ws_pcdata_single, parse_ws_pcdata | parse_ws_pcdata_single };
unsigned int flags[] = {0, parse_ws_pcdata, parse_ws_pcdata_single, parse_ws_pcdata | parse_ws_pcdata_single};
for (size_t i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i)
{
@ -696,7 +695,6 @@ TEST(parse_attribute_variations)
}
}
TEST(parse_attribute_error)
{
xml_document doc;
@ -926,10 +924,10 @@ TEST(parse_out_of_memory_halfway_node)
for (unsigned int i = 0; i < count; ++i)
{
text[4*i + 0] = '<';
text[4*i + 1] = 'n';
text[4*i + 2] = '/';
text[4*i + 3] = '>';
text[4 * i + 0] = '<';
text[4 * i + 1] = 'n';
text[4 * i + 2] = '/';
text[4 * i + 3] = '>';
}
test_runner::_memory_fail_threshold = 65536;
@ -949,11 +947,11 @@ TEST(parse_out_of_memory_halfway_attr)
for (unsigned int i = 0; i < count; ++i)
{
text[5*i + 2] = ' ';
text[5*i + 3] = 'a';
text[5*i + 4] = '=';
text[5*i + 5] = '"';
text[5*i + 6] = '"';
text[5 * i + 2] = ' ';
text[5 * i + 3] = 'a';
text[5 * i + 4] = '=';
text[5 * i + 5] = '"';
text[5 * i + 6] = '"';
}
text[5 * count + 2] = '/';
@ -984,10 +982,10 @@ TEST(parse_out_of_memory_allocator_state_sync)
for (unsigned int i = 0; i < count; ++i)
{
text[4*i + 0] = '<';
text[4*i + 1] = 'n';
text[4*i + 2] = '/';
text[4*i + 3] = '>';
text[4 * i + 0] = '<';
text[4 * i + 1] = 'n';
text[4 * i + 2] = '/';
text[4 * i + 3] = '>';
}
test_runner::_memory_fail_threshold = 65536;
@ -1072,18 +1070,18 @@ TEST(parse_bom_fragment)
};
const test_data_t data[] =
{
{ encoding_utf8, "\xef\xbb\xbf", 3, STR("") },
{ encoding_utf8, "\xef\xbb\xbftest", 7, STR("test") },
{ encoding_utf16_be, "\xfe\xff", 2, STR("") },
{ encoding_utf16_be, "\xfe\xff\x00t\x00o\x00s\x00t", 10, STR("tost") },
{ encoding_utf16_le, "\xff\xfe", 2, STR("") },
{ encoding_utf16_le, "\xff\xfet\x00o\x00s\x00t\x00", 10, STR("tost") },
{ encoding_utf32_be, "\x00\x00\xfe\xff", 4, STR("") },
{ encoding_utf32_be, "\x00\x00\xfe\xff\x00\x00\x00t\x00\x00\x00o\x00\x00\x00s\x00\x00\x00t", 20, STR("tost") },
{ encoding_utf32_le, "\xff\xfe\x00\x00", 4, STR("") },
{ encoding_utf32_le, "\xff\xfe\x00\x00t\x00\x00\x00o\x00\x00\x00s\x00\x00\x00t\x00\x00\x00", 20, STR("tost") },
};
{
{encoding_utf8, "\xef\xbb\xbf", 3, STR("")},
{encoding_utf8, "\xef\xbb\xbftest", 7, STR("test")},
{encoding_utf16_be, "\xfe\xff", 2, STR("")},
{encoding_utf16_be, "\xfe\xff\x00t\x00o\x00s\x00t", 10, STR("tost")},
{encoding_utf16_le, "\xff\xfe", 2, STR("")},
{encoding_utf16_le, "\xff\xfet\x00o\x00s\x00t\x00", 10, STR("tost")},
{encoding_utf32_be, "\x00\x00\xfe\xff", 4, STR("")},
{encoding_utf32_be, "\x00\x00\xfe\xff\x00\x00\x00t\x00\x00\x00o\x00\x00\x00s\x00\x00\x00t", 20, STR("tost")},
{encoding_utf32_le, "\xff\xfe\x00\x00", 4, STR("")},
{encoding_utf32_le, "\xff\xfe\x00\x00t\x00\x00\x00o\x00\x00\x00s\x00\x00\x00t\x00\x00\x00", 20, STR("tost")},
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{
@ -1171,12 +1169,11 @@ TEST(parse_close_tag_eof)
TEST(parse_fuzz_doctype)
{
unsigned char data[] =
{
0x3b, 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0xef, 0xbb, 0xbf, 0x3c, 0x3f, 0x78,
0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22,
0x3f, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0xe9, 0x80, 0xb1, 0xe5, 0xa0, 0xb1, 0xe3, 0x82, 0xb4,
0xe3, 0x83, 0xb3, 0x20, 0xef, 0x83, 0x97, 0xe3, 0xa9, 0x2a, 0x20, 0x2d, 0x2d, 0x3e
};
{
0x3b, 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0xef, 0xbb, 0xbf, 0x3c, 0x3f, 0x78,
0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22,
0x3f, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0xe9, 0x80, 0xb1, 0xe5, 0xa0, 0xb1, 0xe3, 0x82, 0xb4,
0xe3, 0x83, 0xb3, 0x20, 0xef, 0x83, 0x97, 0xe3, 0xa9, 0x2a, 0x20, 0x2d, 0x2d, 0x3e};
xml_document doc;
CHECK(doc.load_buffer(data, sizeof(data)).status == status_bad_doctype);
@ -1215,9 +1212,9 @@ TEST(parse_embed_pcdata)
CHECK_STRING(child.child_value(), STR("outer"));
CHECK_STRING(child.child_value(STR("inner2")), STR("value2"));
#ifndef PUGIXML_NO_XPATH
#ifndef PUGIXML_NO_XPATH
CHECK_XPATH_NUMBER(doc, STR("count(node/child/*[starts-with(., 'value')])"), 2);
#endif
#endif
CHECK_NODE(doc, STR("<node><key>value</key><child><inner1>value1</inner1><inner2>value2</inner2>outer</child><two>text<data/></two></node>"));
CHECK_NODE_EX(doc, STR("<node>\n<key>value</key>\n<child>\n<inner1>value1</inner1>\n<inner2>value2</inner2>outer</child>\n<two>text<data />\n</two>\n</node>\n"), STR("\t"), 0);
@ -1286,23 +1283,23 @@ TEST(parse_encoding_detect_auto)
};
const data_t data[] =
{
// BOM
{ "\x00\x00\xfe\xff", 4, encoding_utf32_be },
{ "\xff\xfe\x00\x00", 4, encoding_utf32_le },
{ "\xfe\xff ", 4, encoding_utf16_be },
{ "\xff\xfe ", 4, encoding_utf16_le },
{ "\xef\xbb\xbf ", 4, encoding_utf8 },
// automatic tag detection for < or <?
{ "\x00\x00\x00<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>", 16, encoding_utf32_be },
{ "<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>\x00\x00\x00", 16, encoding_utf32_le },
{ "\x00<\x00?\x00n\x00?\x00>", 10, encoding_utf16_be },
{ "<\x00?\x00n\x00?\x00>\x00", 10, encoding_utf16_le },
{ "\x00<\x00n\x00/\x00>", 8, encoding_utf16_be },
{ "<\x00n\x00/\x00>\x00", 8, encoding_utf16_le },
// <?xml encoding
{ "<?xml encoding='latin1'?>", 25, encoding_latin1 },
};
{
// BOM
{"\x00\x00\xfe\xff", 4, encoding_utf32_be},
{"\xff\xfe\x00\x00", 4, encoding_utf32_le},
{"\xfe\xff ", 4, encoding_utf16_be},
{"\xff\xfe ", 4, encoding_utf16_le},
{"\xef\xbb\xbf ", 4, encoding_utf8},
// automatic tag detection for < or <?
{"\x00\x00\x00<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>", 16, encoding_utf32_be},
{"<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>\x00\x00\x00", 16, encoding_utf32_le},
{"\x00<\x00?\x00n\x00?\x00>", 10, encoding_utf16_be},
{"<\x00?\x00n\x00?\x00>\x00", 10, encoding_utf16_le},
{"\x00<\x00n\x00/\x00>", 8, encoding_utf16_be},
{"<\x00n\x00/\x00>\x00", 8, encoding_utf16_le},
// <?xml encoding
{"<?xml encoding='latin1'?>", 25, encoding_latin1},
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{
@ -1324,27 +1321,27 @@ TEST(parse_encoding_detect_auto_incomplete)
};
const data_t data[] =
{
// BOM
{ "\x00\x00\xfe ", 4, encoding_utf8 },
{ "\x00\x00 ", 4, encoding_utf8 },
{ "\xff\xfe\x00 ", 4, encoding_utf16_le },
{ "\xfe ", 4, encoding_utf8 },
{ "\xff ", 4, encoding_utf8 },
{ "\xef\xbb ", 4, encoding_utf8 },
{ "\xef ", 4, encoding_utf8 },
// automatic tag detection for < or <?
{ "\x00\x00\x00 ", 4, encoding_utf8 },
{ "<\x00\x00n/\x00>\x00", 8, encoding_utf16_le },
{ "\x00<n\x00\x00/\x00>", 8, encoding_utf16_be },
{ "<\x00?n/\x00>\x00", 8, encoding_utf16_le },
{ "\x00 ", 2, encoding_utf8 },
// <?xml encoding
{ "<?xmC encoding='latin1'?>", 25, encoding_utf8 },
{ "<?xBC encoding='latin1'?>", 25, encoding_utf8 },
{ "<?ABC encoding='latin1'?>", 25, encoding_utf8 },
{ "<_ABC encoding='latin1'/>", 25, encoding_utf8 },
};
{
// BOM
{"\x00\x00\xfe ", 4, encoding_utf8},
{"\x00\x00 ", 4, encoding_utf8},
{"\xff\xfe\x00 ", 4, encoding_utf16_le},
{"\xfe ", 4, encoding_utf8},
{"\xff ", 4, encoding_utf8},
{"\xef\xbb ", 4, encoding_utf8},
{"\xef ", 4, encoding_utf8},
// automatic tag detection for < or <?
{"\x00\x00\x00 ", 4, encoding_utf8},
{"<\x00\x00n/\x00>\x00", 8, encoding_utf16_le},
{"\x00<n\x00\x00/\x00>", 8, encoding_utf16_be},
{"<\x00?n/\x00>\x00", 8, encoding_utf16_le},
{"\x00 ", 2, encoding_utf8},
// <?xml encoding
{"<?xmC encoding='latin1'?>", 25, encoding_utf8},
{"<?xBC encoding='latin1'?>", 25, encoding_utf8},
{"<?ABC encoding='latin1'?>", 25, encoding_utf8},
{"<_ABC encoding='latin1'/>", 25, encoding_utf8},
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{

View file

@ -3,8 +3,8 @@
#include "test.hpp"
#include <string.h>
#include <wchar.h>
#include <string>
#include <wchar.h>
using namespace pugi;
@ -30,21 +30,28 @@ static bool test_doctype_wf(const char_t* decl)
xml_document doc;
// standalone
if (!load_concat(doc, decl) || !doc.first_child().empty()) return false;
if (!load_concat(doc, decl) || !doc.first_child().empty())
return false;
// pcdata pre/postfix
if (!load_concat(doc, STR("a"), decl) || !test_node(doc, STR("a"), STR(""), format_raw)) return false;
if (!load_concat(doc, decl, STR("b")) || !test_node(doc, STR("b"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("a"), decl, STR("b")) || !test_node(doc, STR("ab"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("a"), decl) || !test_node(doc, STR("a"), STR(""), format_raw))
return false;
if (!load_concat(doc, decl, STR("b")) || !test_node(doc, STR("b"), STR(""), format_raw))
return false;
if (!load_concat(doc, STR("a"), decl, STR("b")) || !test_node(doc, STR("ab"), STR(""), format_raw))
return false;
// node pre/postfix
if (!load_concat(doc, STR("<nodea/>"), decl) || !test_node(doc, STR("<nodea/>"), STR(""), format_raw)) return false;
if (!load_concat(doc, decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodeb/>"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("<nodea/>"), decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodea/><nodeb/>"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("<nodea/>"), decl) || !test_node(doc, STR("<nodea/>"), STR(""), format_raw))
return false;
if (!load_concat(doc, decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodeb/>"), STR(""), format_raw))
return false;
if (!load_concat(doc, STR("<nodea/>"), decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodea/><nodeb/>"), STR(""), format_raw))
return false;
// check load-store contents preservation
CHECK(doc.load_string(decl, parse_doctype | parse_fragment));
CHECK_NODE(doc, decl);
// check load-store contents preservation
CHECK(doc.load_string(decl, parse_doctype | parse_fragment));
CHECK_NODE(doc, decl);
return true;
}
@ -54,13 +61,16 @@ static bool test_doctype_nwf(const char_t* decl)
xml_document doc;
// standalone
if (load_concat(doc, decl).status != status_bad_doctype) return false;
if (load_concat(doc, decl).status != status_bad_doctype)
return false;
// pcdata postfix
if (load_concat(doc, decl, STR("b")).status != status_bad_doctype) return false;
if (load_concat(doc, decl, STR("b")).status != status_bad_doctype)
return false;
// node postfix
if (load_concat(doc, decl, STR("<nodeb/>")).status != status_bad_doctype) return false;
if (load_concat(doc, decl, STR("<nodeb/>")).status != status_bad_doctype)
return false;
return true;
}
@ -281,9 +291,9 @@ TEST(parse_doctype_xmlconf_oasis_1)
TEST_DOCTYPE_WF("<!DOCTYPE doc [ <!ELEMENT doc EMPTY> <!NOTATION not1 PUBLIC \"a b cdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"> <!NOTATION not2 PUBLIC '0123456789-()+,./:=?;!*#@$_%'> <!NOTATION not3 PUBLIC \"0123456789-()+,.'/:=?;!*#@$_%\"> ]>");
TEST_DOCTYPE_WF("<!DOCTYPE doc SYSTEM \"p31pass1.dtd\" [<!ELEMENT doc EMPTY>]>");
// not actually a doctype :)
xml_document doc;
CHECK(doc.load_string(STR("<!--a <!DOCTYPE <?- ]]>-<[ CDATA [ \"- -'- -<doc>--> <!---->"), parse_full | parse_fragment) && doc.first_child().type() == node_comment && doc.last_child().type() == node_comment && doc.first_child().next_sibling() == doc.last_child());
// not actually a doctype :)
xml_document doc;
CHECK(doc.load_string(STR("<!--a <!DOCTYPE <?- ]]>-<[ CDATA [ \"- -'- -<doc>--> <!---->"), parse_full | parse_fragment) && doc.first_child().type() == node_comment && doc.last_child().type() == node_comment && doc.first_child().next_sibling() == doc.last_child());
CHECK(doc.load_string(STR("<?xmla <!DOCTYPE <[ CDATA [</doc> &a%b&#c?>"), parse_full | parse_fragment) && doc.first_child().type() == node_pi && doc.first_child() == doc.last_child());
}
@ -303,22 +313,22 @@ TEST(parse_doctype_xmlconf_xmltest_1)
TEST_XML_FLAGS(parse_doctype_value, "<!DOCTYPE doc [ <!ELEMENT doc (#PCDATA)> <!ENTITY e \"<![CDATA[Tim & Michael]]>\"> ]>", parse_fragment | parse_doctype)
{
xml_node n = doc.first_child();
xml_node n = doc.first_child();
CHECK(n.type() == node_doctype);
CHECK_STRING(n.value(), STR("doc [ <!ELEMENT doc (#PCDATA)> <!ENTITY e \"<![CDATA[Tim & Michael]]>\"> ]"));
CHECK(n.type() == node_doctype);
CHECK_STRING(n.value(), STR("doc [ <!ELEMENT doc (#PCDATA)> <!ENTITY e \"<![CDATA[Tim & Michael]]>\"> ]"));
}
TEST(parse_doctype_error_toplevel)
{
xml_document doc;
CHECK(doc.load_string(STR("<node><!DOCTYPE></node>")).status == status_bad_doctype);
CHECK(doc.load_string(STR("<node><!DOCTYPE></node>"), parse_doctype).status == status_bad_doctype);
xml_document doc;
CHECK(doc.load_string(STR("<node><!DOCTYPE></node>")).status == status_bad_doctype);
CHECK(doc.load_string(STR("<node><!DOCTYPE></node>"), parse_doctype).status == status_bad_doctype);
}
TEST(parse_doctype_error_ignore)
{
xml_document doc;
xml_document doc;
CHECK(doc.load_string(STR("<!DOCTYPE root [ <![IGNORE[ ")).status == status_bad_doctype);
CHECK(doc.load_string(STR("<!DOCTYPE root [ <![IGNORE[ "), parse_doctype).status == status_bad_doctype);
CHECK(doc.load_string(STR("<!DOCTYPE root [ <![IGNORE[ <![INCLUDE[")).status == status_bad_doctype);

View file

@ -73,9 +73,9 @@ TEST(as_wide_invalid)
TEST(as_wide_string)
{
std::string s = "abcd";
std::string s = "abcd";
CHECK(as_wide(s) == L"abcd");
CHECK(as_wide(s) == L"abcd");
}
TEST(as_utf8_empty)
@ -110,11 +110,11 @@ TEST(as_utf8_valid_astral)
}
else
{
#ifdef U_LITERALS
#ifdef U_LITERALS
CHECK(as_utf8(L"\uda1d\ude24 \udbc0\udfff") == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
#else
#else
CHECK(as_utf8(L"\xda1d\xde24 \xdbc0\xdfff") == "\xf2\x97\x98\xa4 \xf4\x80\x8f\xbf");
#endif
#endif
}
}
@ -125,29 +125,29 @@ TEST(as_utf8_invalid)
if (wcharsize == 2)
{
// check non-terminated degenerate handling
#ifdef U_LITERALS
#ifdef U_LITERALS
CHECK(as_utf8(L"a\uda1d") == "a");
CHECK(as_utf8(L"a\uda1d_") == "a_");
#else
#else
CHECK(as_utf8(L"a\xda1d") == "a");
CHECK(as_utf8(L"a\xda1d_") == "a_");
#endif
#endif
// check incorrect leading code
#ifdef U_LITERALS
#ifdef U_LITERALS
CHECK(as_utf8(L"a\ude24") == "a");
CHECK(as_utf8(L"a\ude24_") == "a_");
#else
#else
CHECK(as_utf8(L"a\xde24") == "a");
CHECK(as_utf8(L"a\xde24_") == "a_");
#endif
#endif
}
}
TEST(as_utf8_string)
{
std::basic_string<wchar_t> s = L"abcd";
std::basic_string<wchar_t> s = L"abcd";
CHECK(as_utf8(s) == "abcd");
CHECK(as_utf8(s) == "abcd");
}
#endif

View file

@ -2,9 +2,9 @@
#include "writer_string.hpp"
#include <string>
#include <sstream>
#include <stdexcept>
#include <string>
using namespace pugi;
@ -199,11 +199,11 @@ TEST_XML(write_escape, "<node attr=''>text</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
#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
@ -217,7 +217,7 @@ TEST_XML(write_no_escapes, "<node attr=''>text</node>")
CHECK_NODE_EX(doc, STR("<node attr=\"<>'\"&\x04\r\n\t\"><>'\"&\x04\r\n\t</node>"), STR(""), format_raw | format_no_escapes);
}
struct test_writer: xml_writer
struct test_writer : xml_writer
{
std::basic_string<char_t> contents;
@ -302,7 +302,7 @@ TEST(write_encodings)
CHECK(v.size() == 10 && v[0] == '<' && v[1] == 0x54 && v[2] == 0xA2 && v[3] == 0x20AC && v[4] == wchar_cast(0xd852) && v[5] == wchar_cast(0xdf62) && v[6] == ' ' && v[7] == '/' && v[8] == '>' && v[9] == '\n');
}
CHECK(test_write_narrow(doc, format_default, encoding_latin1, "<\x54\xA2?? />\n", 9));
CHECK(test_write_narrow(doc, format_default, encoding_latin1, "<\x54\xA2?? />\n", 9));
}
#ifdef PUGIXML_WCHAR_MODE
@ -313,7 +313,8 @@ TEST(write_encoding_huge)
// 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";
for (unsigned int i = 0; i < N; ++i)
s_utf16 += "\x20\xAC\xd8\x52\xdf\x62";
s_utf16 += std::string("\x00/\x00>", 4);
@ -322,7 +323,8 @@ TEST(write_encoding_huge)
std::string s_utf8 = "<";
for (unsigned int j = 0; j < N; ++j) s_utf8 += "\xE2\x82\xAC\xF0\xA4\xAD\xA2";
for (unsigned int j = 0; j < N; ++j)
s_utf8 += "\xE2\x82\xAC\xF0\xA4\xAD\xA2";
s_utf8 += " />\n";
@ -340,7 +342,8 @@ TEST(write_encoding_huge_invalid)
// make a large utf16 name consisting of leading surrogate chars
std::basic_string<wchar_t> s_utf16;
for (unsigned int i = 0; i < N; ++i) s_utf16 += static_cast<wchar_t>(0xd852);
for (unsigned int i = 0; i < N; ++i)
s_utf16 += static_cast<wchar_t>(0xd852);
xml_document doc;
doc.append_child().set_name(s_utf16.c_str());
@ -356,7 +359,8 @@ TEST(write_encoding_huge)
// 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";
for (unsigned int i = 0; i < N; ++i)
s_utf8 += "\xE2\x82\xAC";
s_utf8 += "/>";
@ -365,7 +369,8 @@ TEST(write_encoding_huge)
std::string s_utf16 = std::string("\x00<", 2);
for (unsigned int j = 0; j < N; ++j) s_utf16 += "\x20\xAC";
for (unsigned int j = 0; j < N; ++j)
s_utf16 += "\x20\xAC";
s_utf16 += std::string("\x00 \x00/\x00>\x00\n", 8);
@ -379,7 +384,8 @@ TEST(write_encoding_huge_invalid)
// 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";
for (unsigned int i = 0; i < N; ++i)
s_utf8 += "\x82";
xml_document doc;
doc.append_child().set_name(s_utf8.c_str());
@ -416,22 +422,22 @@ TEST(write_unicode_invalid_utf16)
if (wcharsize == 2)
{
// check non-terminated degenerate handling
#ifdef U_LITERALS
#ifdef U_LITERALS
CHECK(test_write_unicode_invalid(L"a\uda1d", "a"));
CHECK(test_write_unicode_invalid(L"a\uda1d_", "a_"));
#else
#else
CHECK(test_write_unicode_invalid(L"a\xda1d", "a"));
CHECK(test_write_unicode_invalid(L"a\xda1d_", "a_"));
#endif
#endif
// check incorrect leading code
#ifdef U_LITERALS
#ifdef U_LITERALS
CHECK(test_write_unicode_invalid(L"a\ude24", "a"));
CHECK(test_write_unicode_invalid(L"a\ude24_", "a_"));
#else
#else
CHECK(test_write_unicode_invalid(L"a\xde24", "a"));
CHECK(test_write_unicode_invalid(L"a\xde24_", "a_"));
#endif
#endif
}
}
#else
@ -569,19 +575,17 @@ TEST(write_pcdata_whitespace_fixedpoint)
const char_t* data = STR("<node> test <child>\n <sub/>\n </child>\n</node>");
static const unsigned int flags_parse[] =
{
0,
parse_ws_pcdata,
parse_ws_pcdata_single,
parse_trim_pcdata
};
{
0,
parse_ws_pcdata,
parse_ws_pcdata_single,
parse_trim_pcdata};
static const unsigned int flags_format[] =
{
0,
format_raw,
format_indent
};
{
0,
format_raw,
format_indent};
for (unsigned int i = 0; i < sizeof(flags_parse) / sizeof(flags_parse[0]); ++i)
{
@ -618,7 +622,7 @@ TEST_XML(write_no_empty_element_tags, "<node><child1/><child2>text</child2><chil
TEST_XML_FLAGS(write_roundtrip, "<node><child1 attr1='value1' attr2='value2'/><child2 attr='value'>pre<![CDATA[data]]>mid&lt;text&amp;escape<!--comment--><test/>post<?pi value?>fin</child2><child3/></node>", parse_full)
{
const unsigned int flagset[] = { format_indent, format_raw, format_no_declaration, format_indent_attributes, format_no_empty_element_tags };
const unsigned int flagset[] = {format_indent, format_raw, format_no_declaration, format_indent_attributes, format_no_empty_element_tags};
size_t flagcount = sizeof(flagset) / sizeof(flagset[0]);
for (size_t i = 0; i < (size_t(1) << flagcount); ++i)
@ -669,7 +673,7 @@ TEST(write_flush_coverage)
}
#ifndef PUGIXML_NO_EXCEPTIONS
struct throwing_writer: xml_writer
struct throwing_writer : xml_writer
{
virtual void write(const void*, size_t) PUGIXML_OVERRIDE
{

View file

@ -5,10 +5,10 @@
#include <string.h>
#include <wchar.h>
#include <string>
#include <vector>
#include <algorithm>
#include <limits>
#include <string>
#include <vector>
using namespace pugi;
@ -24,7 +24,8 @@ TEST(xpath_allocator_many_pages)
{
std::basic_string<char_t> query = STR("0");
for (int i = 0; i < 128; ++i) query += STR("+string-length('abcdefgh')");
for (int i = 0; i < 128; ++i)
query += STR("+string-length('abcdefgh')");
CHECK_XPATH_NUMBER(xml_node(), query.c_str(), 1024);
}
@ -33,7 +34,8 @@ TEST(xpath_allocator_large_page)
{
std::basic_string<char_t> query;
for (int i = 0; i < 1024; ++i) query += STR("abcdefgh");
for (int i = 0; i < 1024; ++i)
query += STR("abcdefgh");
CHECK_XPATH_NUMBER(xml_node(), (STR("string-length('") + query + STR("')")).c_str(), 8192);
}
@ -147,10 +149,10 @@ TEST(xpath_sort_random_medium)
{
xml_document doc;
load_document_copy(doc, STR("<node>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("</node>"));
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("</node>"));
xpath_node_set ns = doc.select_nodes(STR("//node() | //@*"));
@ -162,24 +164,25 @@ TEST(xpath_sort_random_medium)
xpath_node_set_tester tester(copy, "sorted order failed");
for (unsigned int i = 2; i < 39; ++i) tester % i;
for (unsigned int i = 2; i < 39; ++i)
tester % i;
}
TEST(xpath_sort_random_large)
{
xml_document doc;
load_document_copy(doc, STR("<node>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2></node>"));
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2>")
STR("<child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2></node>"));
xpath_node_set ns = doc.select_nodes(STR("//node() | //@*"));
@ -191,7 +194,8 @@ TEST(xpath_sort_random_large)
xpath_node_set_tester tester(copy, "sorted order failed");
for (unsigned int i = 2; i < 129; ++i) tester % i;
for (unsigned int i = 2; i < 129; ++i)
tester % i;
}
TEST(xpath_long_numbers_parse)
@ -247,7 +251,8 @@ TEST(xpath_denorm_numbers)
// 10^-318 - double denormal
for (int i = 0; i < 106; ++i)
{
if (i != 0) query += STR(" * ");
if (i != 0)
query += STR(" * ");
query += STR("0.001");
}
@ -282,7 +287,7 @@ TEST_XML(xpath_rexml_2, "<a:x xmlns:a='1'><a:y p='p' q='q'><a:z>zzz</a:z></a:y><
TEST_XML(xpath_rexml_3, "<article><section role='subdivision' id='1'><para>free flowing text.</para></section><section role='division'><section role='subdivision' id='2'><para>free flowing text.</para></section><section role='division'><para>free flowing text.</para></section></section></article>")
{
CHECK_XPATH_NODESET(doc, STR("//section[../self::section[@role=\"division\"]]")) % 10 % 15;
CHECK_XPATH_NODESET(doc, STR("//section[@role=\"subdivision\" and not(../self::section[@role=\"division\"])]")) % 3;
CHECK_XPATH_NODESET(doc, STR("//section[@role=\"subdivision\" and not(../self::section[@role=\"division\"])]")) % 3;
CHECK_XPATH_NODESET(doc, STR("//section[@role=\"subdivision\"][not(../self::section[@role=\"division\"])]")) % 3;
}
@ -716,7 +721,7 @@ TEST(xpath_sort_crossdoc_different_depth)
TEST_XML(xpath_sort_empty_node, "<node><child1/><child2/></node>")
{
xml_node n = doc.child(STR("node"));
xpath_node nodes[] = { n.child(STR("child2")), xml_node(), n.child(STR("child1")), xml_node() };
xpath_node nodes[] = {n.child(STR("child2")), xml_node(), n.child(STR("child1")), xml_node()};
xpath_node_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]));
ns.sort();
@ -728,9 +733,10 @@ TEST(xpath_allocate_string_out_of_memory)
{
std::basic_string<char_t> query;
for (int i = 0; i < 1024; ++i) query += STR("abcdefgh");
for (int i = 0; i < 1024; ++i)
query += STR("abcdefgh");
test_runner::_memory_fail_threshold = 8*1024;
test_runner::_memory_fail_threshold = 8 * 1024;
#ifndef __DMC__ // DigitalMars exception handling crashes instead of catching the exception...
CHECK_ALLOC_FAIL(CHECK(!xpath_query(query.c_str())));

View file

@ -141,10 +141,10 @@ TEST_XML(xpath_api_nodeset_copy, "<node><foo/><foo/></node>")
TEST(xpath_api_nodeset_copy_empty)
{
xpath_node_set set;
xpath_node_set set2 = set;
xpath_node_set set3;
set3 = set;
xpath_node_set set;
xpath_node_set set2 = set;
xpath_node_set set3;
set3 = set;
}
TEST_XML(xpath_api_evaluate, "<node attr='3'/>")
@ -430,7 +430,6 @@ TEST_XML(xpath_api_nodeset_move_ctor, "<node><foo/><foo/><bar/></node>")
CHECK(move[1] == doc.first_child().first_child());
}
TEST_XML(xpath_api_nodeset_move_ctor_single, "<node><foo/><foo/><bar/></node>")
{
xpath_node_set set = doc.select_nodes(STR("node/bar"));

View file

@ -57,7 +57,7 @@ TEST_XML(xpath_number_sum, "<node>123<child>789</child></node><node/>")
CHECK_XPATH_NUMBER(n, STR("sum(.)"), 123789); // 123 .. 789
CHECK_XPATH_NUMBER(n, STR("sum(./descendant-or-self::node())"), 125490); // node + 123 + child + 789 = 123789 + 123 + 789 + 789 = 125490
CHECK_XPATH_NUMBER(n, STR("sum(.//node())"), 1701); // 123 + child + 789 = 123 + 789 + 789
CHECK_XPATH_NUMBER(n, STR("sum(.//node())"), 1701); // 123 + child + 789 = 123 + 789 + 789
CHECK_XPATH_NUMBER_NAN(doc.last_child(), STR("sum(.)"));
// sum with 2 arguments
@ -423,9 +423,9 @@ TEST(xpath_string_substring_after)
TEST_XML(xpath_string_substring_after_heap, "<node>foo<child/>bar</node>")
{
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'fo')"), STR("obar"));
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'fooba')"), STR("r"));
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'foobar')"), STR(""));
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'fo')"), STR("obar"));
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'fooba')"), STR("r"));
CHECK_XPATH_STRING(doc, STR("substring-after(node, 'foobar')"), STR(""));
}
TEST(xpath_string_substring)
@ -452,7 +452,7 @@ TEST(xpath_string_substring)
CHECK_XPATH_STRING(c, STR("substring('abcd', 0 div 0)"), STR(""));
CHECK_XPATH_STRING(c, STR("substring('', 1)"), STR(""));
CHECK_XPATH_STRING(c, STR("substring('', 0)"), STR(""));
CHECK_XPATH_STRING(c, STR("substring(substring('internalexternalcorrect substring',9),9)"), STR("correct substring"));
CHECK_XPATH_STRING(c, STR("substring(substring('internalexternalcorrect substring',9),9)"), STR("correct substring"));
// substring with 3 arguments
CHECK_XPATH_STRING(c, STR("substring('abcd', 2, 1)"), STR("b"));
@ -490,9 +490,9 @@ TEST(xpath_string_substring)
TEST_XML(xpath_string_substring_heap, "<node>foo<child/>bar</node>")
{
CHECK_XPATH_STRING(doc, STR("substring(node, 3)"), STR("obar"));
CHECK_XPATH_STRING(doc, STR("substring(node, 6)"), STR("r"));
CHECK_XPATH_STRING(doc, STR("substring(node, 7)"), STR(""));
CHECK_XPATH_STRING(doc, STR("substring(node, 3)"), STR("obar"));
CHECK_XPATH_STRING(doc, STR("substring(node, 6)"), STR("r"));
CHECK_XPATH_STRING(doc, STR("substring(node, 7)"), STR(""));
}
TEST_XML(xpath_string_string_length, "<node>123</node>")
@ -590,7 +590,7 @@ TEST_XML(xpath_nodeset_last, "<node><c1/><c1/><c2/><c3/><c3/><c3/><c3/></node>")
// last with 0 arguments
CHECK_XPATH_NUMBER(n, STR("last()"), 1);
CHECK_XPATH_NODESET(n, STR("c1[last() = 1]"));
CHECK_XPATH_NODESET(n, STR("c1[last() = 2]")) % 3 % 4; // c1, c1
CHECK_XPATH_NODESET(n, STR("c1[last() = 2]")) % 3 % 4; // c1, c1
CHECK_XPATH_NODESET(n, STR("c2/preceding-sibling::node()[last() = 2]")) % 4 % 3; // c1, c1
// last with 1 argument
@ -829,7 +829,8 @@ TEST(xpath_string_translate_table_out_of_memory)
for (size_t i = 0; i < count; ++i)
{
if (i != 0) query += STR(",");
if (i != 0)
query += STR(",");
query += STR("translate('a','a','A')");
}

View file

@ -99,82 +99,80 @@ TEST(xpath_semantics_posinv) // coverage for contains()
TEST(xpath_parse_paths_valid)
{
const char_t* paths[] =
{
// From Jaxen tests
STR("foo[.='bar']"), STR("foo[.!='bar']"), STR("/"), STR("*"), STR("//foo"), STR("/*"), STR("/."), STR("/foo[/bar[/baz]]"),
STR("/foo/bar/baz[(1 or 2) + 3 * 4 + 8 and 9]"), STR("/foo/bar/baz"), STR("(.)[1]"), STR("self::node()"), STR("."), STR("count(/)"),
STR("foo[1]"), STR("/baz[(1 or 2) + 3 * 4 + 8 and 9]"), STR("foo/bar[/baz[(1 or 2) - 3 mod 4 + 8 and 9 div 8]]"),
STR("foo/bar/yeah:baz[a/b/c and toast]"), STR("/foo/bar[../x='123']"), STR("/foo[@bar='1234']"), STR("foo|bar"),
STR("/foo|/bar[@id='1234']"), STR("count(//author/attribute::*)"), STR("/child::node()/child::node()[@id='_13563275']"),
STR("10 + (count(descendant::author) * 5)"), STR("10 + count(descendant::author) * 5"), STR("2 + (2 * 5)"), STR("//foo:bar"),
STR("count(//author)+5"), STR("count(//author)+count(//author/attribute::*)"), STR("/foo/bar[@a='1' and @c!='2']"),
STR("12 + (count(//author)+count(//author/attribute::*)) div 2"), STR("text()[.='foo']"), STR("/*/*[@id='123']")
STR("/foo/bar[@a='1' and @b='2']"), STR("/foo/bar[@a='1' and @b!='2']"), STR("//attribute::*[.!='crunchy']"),
STR("'//*[contains(string(text()),\"yada yada\")]'"),
const char_t* paths[] =
{
// From Jaxen tests
STR("foo[.='bar']"), STR("foo[.!='bar']"), STR("/"), STR("*"), STR("//foo"), STR("/*"), STR("/."), STR("/foo[/bar[/baz]]"),
STR("/foo/bar/baz[(1 or 2) + 3 * 4 + 8 and 9]"), STR("/foo/bar/baz"), STR("(.)[1]"), STR("self::node()"), STR("."), STR("count(/)"),
STR("foo[1]"), STR("/baz[(1 or 2) + 3 * 4 + 8 and 9]"), STR("foo/bar[/baz[(1 or 2) - 3 mod 4 + 8 and 9 div 8]]"),
STR("foo/bar/yeah:baz[a/b/c and toast]"), STR("/foo/bar[../x='123']"), STR("/foo[@bar='1234']"), STR("foo|bar"),
STR("/foo|/bar[@id='1234']"), STR("count(//author/attribute::*)"), STR("/child::node()/child::node()[@id='_13563275']"),
STR("10 + (count(descendant::author) * 5)"), STR("10 + count(descendant::author) * 5"), STR("2 + (2 * 5)"), STR("//foo:bar"),
STR("count(//author)+5"), STR("count(//author)+count(//author/attribute::*)"), STR("/foo/bar[@a='1' and @c!='2']"),
STR("12 + (count(//author)+count(//author/attribute::*)) div 2"), STR("text()[.='foo']"), STR("/*/*[@id='123']") STR("/foo/bar[@a='1' and @b='2']"), STR("/foo/bar[@a='1' and @b!='2']"), STR("//attribute::*[.!='crunchy']"),
STR("'//*[contains(string(text()),\"yada yada\")]'"),
// From ajaxslt tests
STR("@*"), STR("@*|node()"), STR("/descendant-or-self::div"), STR("/div"), STR("//div"), STR("/descendant-or-self::node()/child::para"),
STR("substring('12345', 0, 3)"), STR("//title | //link"), STR("x//title"), STR("x/title"), STR("id('a')//title"), STR("//*[@about]"),
STR("count(descendant::*)"), STR("count(descendant::*) + count(ancestor::*)"), STR("@*|text()"), STR("*|/"), STR("source|destination"),
STR("page != 'to' and page != 'from'"), STR("substring-after(icon/@image, '/mapfiles/marker')"), STR("substring-before(str, c)"), STR("page = 'from'"),
STR("segments/@time"), STR("child::para"), STR("child::*"), STR("child::text()"), STR("child::node()"), STR("attribute::name"), STR("attribute::*"),
STR("descendant::para"), STR("ancestor::div"), STR("ancestor-or-self::div"), STR("descendant-or-self::para"), STR("self::para"), STR("child::*/child::para"),
STR("concat(substring-before(@image,'marker'),'icon',substring-after(@image,'marker'))"), STR("/"), STR("/descendant::para"), STR("/descendant::olist/child::item"),
STR("child::para[position()=1]"), STR("child::para[position()=last()]"), STR("child::para[position()=last()-1]"), STR("child::para[position()>1]"),
STR("following-sibling::chapter[position()=1]"), STR("preceding-sibling::chapter[position()=1]"), STR("/descendant::figure[position()=42]"),
STR("/child::doc/child::chapter[position()=5]/child::section[position()=2]"), STR("child::chapter/descendant::para"), STR("child::para[attribute::type='warning']"),
STR("child::para[attribute::type='warning'][position()=5]"), STR("child::para[position()=5][attribute::type='warning']"), STR("child::chapter[child::title='Introduction']"),
STR("child::chapter[child::title]"), STR("child::*[self::chapter or self::appendix]"), STR("child::*[self::chapter or self::appendix][position()=last()]"),
STR("count(//*[id='u1']|//*[id='u2'])"), STR("count(//*[id='u1']|//*[class='u'])"), STR("count(//*[class='u']|//*[class='u'])"), STR("count(//*[class='u']|//*[id='u1'])"),
STR("count(//*[@id='self']/ancestor-or-self::*)"), STR("count(//*[@id='self']/ancestor::*)"), STR("count(//*[@id='self']/attribute::*)"), STR("count(//*[@id='self']/child::*)"),
STR("count(//*[@id='self']/descendant-or-self::*)"), STR("count(//*[@id='self']/descendant::*)"), STR("count(//*[@id='self']/following-sibling::*)"),
STR("count(//*[@id='self']/following::*)"), STR("//*[@id='self']/parent::*/@id"), STR("count(//*[@id='self']/preceding-sibling::*)"),
STR("count(//*[@id='self']/preceding::*)"), STR("//*[@id='self']/self::*/@id"), STR("id('nested1')/div[1]//input[2]"), STR("id('foo')//div[contains(@id, 'useful')]//input"),
STR("(//table[@class='stylee'])//th[text()='theHeaderText']/../td"), STR("address"), STR("address=string(/page/user/defaultlocation)"), STR("count-of-snippet-of-url = 0"),
STR("daddr"), STR("form"), STR("form = 'from'"), STR("form = 'to'"), STR("form='near'"), STR("home"), STR("i"), STR("i > page and i < page + range"),
STR("i < page and i >= page - range"), STR("i < @max"), STR("i <= page"), STR("i + 1"), STR("i = page"), STR("i = 1"), STR("info = position() or (not(info) and position() = 1)"),
STR("is-first-order"), STR("is-first-order and snippets-exist"), STR("more"), STR("more > 0"), STR("near-point"), STR("page"), STR("page != 'from'"), STR("page != 'to'"),
STR("page != 'to' and page != 'from'"), STR("page > 1"), STR("page = 'basics'"), STR("page = 'details'"), STR("page = 'from'"), STR("page = 'to'"), STR("page='from'"),
STR("page='to'"), STR("r >= 0.5"), STR("r >= 1"), STR("r - 0"), STR("r - 1"), STR("r - 2"), STR("r - 3"), STR("r - 4"), STR("saddr"), STR("sources"), STR("sources[position() < details]"),
STR("src"), STR("str"), STR("\"'\""), STR("(//location[string(info/references/reference[1]/url)=string(current-url)]/info/references/reference[1])[1]"),
STR("(not(count-of-snippet-of-url = 0) and (position() = 1) or not(current-url = //locations/location[position() = last-pos]//reference[1]/url))"),
STR("(not(info) and position() = 1) or info = position()"), STR("."), STR("../@arg0"), STR("../@filterpng"), STR("/page/@filterpng"), STR("4"), STR("@attribution"),
STR("@id"), STR("@max > @num"), STR("@meters > 16093"), STR("@name"), STR("@start div @num + 1"), STR("@url"), STR("ad"), STR("address/line"), STR("adsmessage"),
STR("attr"), STR("boolean(location[@id='near'][icon/@image])"), STR("bubble/node()"), STR("calltoaction/node()"), STR("category"), STR("contains(str, c)"),
STR("count(//location[string(info/references/reference[1]/url)=string(current-url)]//snippet)"), STR("count(//snippet)"), STR("count(attr)"), STR("count(location)"),
STR("count(structured/source) > 1"), STR("description/node()"), STR("destination"), STR("destinationAddress"), STR("domain"), STR("false()"), STR("icon/@class != 'noicon'"),
STR("icon/@image"), STR("info"), STR("info/address/line"), STR("info/distance"), STR("info/distance and near-point"), STR("info/distance and info/phone and near-point"),
STR("info/distance or info/phone"), STR("info/panel/node()"), STR("info/phone"), STR("info/references/reference[1]"), STR("info/references/reference[1]/snippet"),
STR("info/references/reference[1]/url"), STR("info/title"), STR("info/title/node()"), STR("line"), STR("location"), STR("location[@id!='near']"), STR("location[@id='near'][icon/@image]"),
STR("location[position() > umlocations div 2]"), STR("location[position() <= numlocations div 2]"), STR("locations"), STR("locations/location"), STR("near"), STR("node()"),
STR("not(count-of-snippets = 0)"), STR("not(form = 'from')"), STR("not(form = 'near')"), STR("not(form = 'to')"), STR("not(../@page)"), STR("not(structured/source)"), STR("notice"),
STR("number(../@info)"), STR("number(../@items)"), STR("number(/page/@linewidth)"), STR("page/ads"), STR("page/directions"), STR("page/error"), STR("page/overlay"),
STR("page/overlay/locations/location"), STR("page/refinements"), STR("page/request/canonicalnear"), STR("page/request/near"), STR("page/request/query"), STR("page/spelling/suggestion"),
STR("page/user/defaultlocation"), STR("phone"), STR("position()"), STR("position() != 1"), STR("position() != last()"), STR("position() > 1"), STR("position() < details"),
STR("position()-1"), STR("query"), STR("references/@total"), STR("references/reference"), STR("references/reference/domain"), STR("references/reference/url"),
STR("reviews/@positive div (reviews/@positive + reviews/@negative) * 5"), STR("reviews/@positive div (reviews/@positive + reviews/@negative) * (5)"), STR("reviews/@total"),
STR("reviews/@total > 1"), STR("reviews/@total > 5"), STR("reviews/@total = 1"), STR("segments/@distance"), STR("segments/@time"), STR("segments/segment"), STR("shorttitle/node()"),
STR("snippet"), STR("snippet/node()"), STR("source"), STR("sourceAddress"), STR("sourceAddress and destinationAddress"), STR("string(../@daddr)"), STR("string(../@form)"),
STR("string(../@page)"), STR("string(../@saddr)"), STR("string(info/title)"), STR("string(page/request/canonicalnear) != ''"), STR("string(page/request/near) != ''"),
STR("string-length(address) > linewidth"), STR("structured/@total - details"), STR("structured/source"), STR("structured/source[@name]"), STR("substring(address, 1, linewidth - 3)"),
STR("substring-after(str, c)"), STR("substring-after(icon/@image, '/mapfiles/marker')"), STR("substring-before(str, c)"), STR("tagline/node()"), STR("targetedlocation"),
STR("title"), STR("title/node()"), STR("true()"), STR("url"), STR("visibleurl"), STR("id(\"level10\")/ancestor::SPAN"), STR("id(\"level10\")/ancestor-or-self::SPAN"), STR("//attribute::*"),
STR("child::HTML/child::BODY/child::H1"), STR("descendant::node()"), STR("descendant-or-self::SPAN"), STR("id(\"first\")/following::text()"), STR("id(\"first\")/following-sibling::node()"),
STR("id(\"level10\")/parent::node()"), STR("id(\"last\")/preceding::text()"), STR("id(\"last\")/preceding-sibling::node()"), STR("/HTML/BODY/H1/self::node()"), STR("//*[@name]"),
STR("id(\"pet\")/SELECT[@name=\"species\"]/OPTION[@selected]/@value"), STR("descendant::INPUT[@name=\"name\"]/@value"), STR("id(\"pet\")/INPUT[@name=\"gender\" and @checked]/@value"),
STR("//TEXTAREA[@name=\"description\"]/text()"), STR("id(\"div1\")|id(\"div2\")|id(\"div3 div4 div5\")"), STR("//LI[1]"), STR("//LI[last()]/text()"), STR("//LI[position() mod 2]/@class"),
STR("//text()[.=\"foo\"]"), STR("descendant-or-self::SPAN[position() > 2]"), STR("descendant::*[contains(@class,\" fruit \")]"),
// From ajaxslt tests
STR("@*"), STR("@*|node()"), STR("/descendant-or-self::div"), STR("/div"), STR("//div"), STR("/descendant-or-self::node()/child::para"),
STR("substring('12345', 0, 3)"), STR("//title | //link"), STR("x//title"), STR("x/title"), STR("id('a')//title"), STR("//*[@about]"),
STR("count(descendant::*)"), STR("count(descendant::*) + count(ancestor::*)"), STR("@*|text()"), STR("*|/"), STR("source|destination"),
STR("page != 'to' and page != 'from'"), STR("substring-after(icon/@image, '/mapfiles/marker')"), STR("substring-before(str, c)"), STR("page = 'from'"),
STR("segments/@time"), STR("child::para"), STR("child::*"), STR("child::text()"), STR("child::node()"), STR("attribute::name"), STR("attribute::*"),
STR("descendant::para"), STR("ancestor::div"), STR("ancestor-or-self::div"), STR("descendant-or-self::para"), STR("self::para"), STR("child::*/child::para"),
STR("concat(substring-before(@image,'marker'),'icon',substring-after(@image,'marker'))"), STR("/"), STR("/descendant::para"), STR("/descendant::olist/child::item"),
STR("child::para[position()=1]"), STR("child::para[position()=last()]"), STR("child::para[position()=last()-1]"), STR("child::para[position()>1]"),
STR("following-sibling::chapter[position()=1]"), STR("preceding-sibling::chapter[position()=1]"), STR("/descendant::figure[position()=42]"),
STR("/child::doc/child::chapter[position()=5]/child::section[position()=2]"), STR("child::chapter/descendant::para"), STR("child::para[attribute::type='warning']"),
STR("child::para[attribute::type='warning'][position()=5]"), STR("child::para[position()=5][attribute::type='warning']"), STR("child::chapter[child::title='Introduction']"),
STR("child::chapter[child::title]"), STR("child::*[self::chapter or self::appendix]"), STR("child::*[self::chapter or self::appendix][position()=last()]"),
STR("count(//*[id='u1']|//*[id='u2'])"), STR("count(//*[id='u1']|//*[class='u'])"), STR("count(//*[class='u']|//*[class='u'])"), STR("count(//*[class='u']|//*[id='u1'])"),
STR("count(//*[@id='self']/ancestor-or-self::*)"), STR("count(//*[@id='self']/ancestor::*)"), STR("count(//*[@id='self']/attribute::*)"), STR("count(//*[@id='self']/child::*)"),
STR("count(//*[@id='self']/descendant-or-self::*)"), STR("count(//*[@id='self']/descendant::*)"), STR("count(//*[@id='self']/following-sibling::*)"),
STR("count(//*[@id='self']/following::*)"), STR("//*[@id='self']/parent::*/@id"), STR("count(//*[@id='self']/preceding-sibling::*)"),
STR("count(//*[@id='self']/preceding::*)"), STR("//*[@id='self']/self::*/@id"), STR("id('nested1')/div[1]//input[2]"), STR("id('foo')//div[contains(@id, 'useful')]//input"),
STR("(//table[@class='stylee'])//th[text()='theHeaderText']/../td"), STR("address"), STR("address=string(/page/user/defaultlocation)"), STR("count-of-snippet-of-url = 0"),
STR("daddr"), STR("form"), STR("form = 'from'"), STR("form = 'to'"), STR("form='near'"), STR("home"), STR("i"), STR("i > page and i < page + range"),
STR("i < page and i >= page - range"), STR("i < @max"), STR("i <= page"), STR("i + 1"), STR("i = page"), STR("i = 1"), STR("info = position() or (not(info) and position() = 1)"),
STR("is-first-order"), STR("is-first-order and snippets-exist"), STR("more"), STR("more > 0"), STR("near-point"), STR("page"), STR("page != 'from'"), STR("page != 'to'"),
STR("page != 'to' and page != 'from'"), STR("page > 1"), STR("page = 'basics'"), STR("page = 'details'"), STR("page = 'from'"), STR("page = 'to'"), STR("page='from'"),
STR("page='to'"), STR("r >= 0.5"), STR("r >= 1"), STR("r - 0"), STR("r - 1"), STR("r - 2"), STR("r - 3"), STR("r - 4"), STR("saddr"), STR("sources"), STR("sources[position() < details]"),
STR("src"), STR("str"), STR("\"'\""), STR("(//location[string(info/references/reference[1]/url)=string(current-url)]/info/references/reference[1])[1]"),
STR("(not(count-of-snippet-of-url = 0) and (position() = 1) or not(current-url = //locations/location[position() = last-pos]//reference[1]/url))"),
STR("(not(info) and position() = 1) or info = position()"), STR("."), STR("../@arg0"), STR("../@filterpng"), STR("/page/@filterpng"), STR("4"), STR("@attribution"),
STR("@id"), STR("@max > @num"), STR("@meters > 16093"), STR("@name"), STR("@start div @num + 1"), STR("@url"), STR("ad"), STR("address/line"), STR("adsmessage"),
STR("attr"), STR("boolean(location[@id='near'][icon/@image])"), STR("bubble/node()"), STR("calltoaction/node()"), STR("category"), STR("contains(str, c)"),
STR("count(//location[string(info/references/reference[1]/url)=string(current-url)]//snippet)"), STR("count(//snippet)"), STR("count(attr)"), STR("count(location)"),
STR("count(structured/source) > 1"), STR("description/node()"), STR("destination"), STR("destinationAddress"), STR("domain"), STR("false()"), STR("icon/@class != 'noicon'"),
STR("icon/@image"), STR("info"), STR("info/address/line"), STR("info/distance"), STR("info/distance and near-point"), STR("info/distance and info/phone and near-point"),
STR("info/distance or info/phone"), STR("info/panel/node()"), STR("info/phone"), STR("info/references/reference[1]"), STR("info/references/reference[1]/snippet"),
STR("info/references/reference[1]/url"), STR("info/title"), STR("info/title/node()"), STR("line"), STR("location"), STR("location[@id!='near']"), STR("location[@id='near'][icon/@image]"),
STR("location[position() > umlocations div 2]"), STR("location[position() <= numlocations div 2]"), STR("locations"), STR("locations/location"), STR("near"), STR("node()"),
STR("not(count-of-snippets = 0)"), STR("not(form = 'from')"), STR("not(form = 'near')"), STR("not(form = 'to')"), STR("not(../@page)"), STR("not(structured/source)"), STR("notice"),
STR("number(../@info)"), STR("number(../@items)"), STR("number(/page/@linewidth)"), STR("page/ads"), STR("page/directions"), STR("page/error"), STR("page/overlay"),
STR("page/overlay/locations/location"), STR("page/refinements"), STR("page/request/canonicalnear"), STR("page/request/near"), STR("page/request/query"), STR("page/spelling/suggestion"),
STR("page/user/defaultlocation"), STR("phone"), STR("position()"), STR("position() != 1"), STR("position() != last()"), STR("position() > 1"), STR("position() < details"),
STR("position()-1"), STR("query"), STR("references/@total"), STR("references/reference"), STR("references/reference/domain"), STR("references/reference/url"),
STR("reviews/@positive div (reviews/@positive + reviews/@negative) * 5"), STR("reviews/@positive div (reviews/@positive + reviews/@negative) * (5)"), STR("reviews/@total"),
STR("reviews/@total > 1"), STR("reviews/@total > 5"), STR("reviews/@total = 1"), STR("segments/@distance"), STR("segments/@time"), STR("segments/segment"), STR("shorttitle/node()"),
STR("snippet"), STR("snippet/node()"), STR("source"), STR("sourceAddress"), STR("sourceAddress and destinationAddress"), STR("string(../@daddr)"), STR("string(../@form)"),
STR("string(../@page)"), STR("string(../@saddr)"), STR("string(info/title)"), STR("string(page/request/canonicalnear) != ''"), STR("string(page/request/near) != ''"),
STR("string-length(address) > linewidth"), STR("structured/@total - details"), STR("structured/source"), STR("structured/source[@name]"), STR("substring(address, 1, linewidth - 3)"),
STR("substring-after(str, c)"), STR("substring-after(icon/@image, '/mapfiles/marker')"), STR("substring-before(str, c)"), STR("tagline/node()"), STR("targetedlocation"),
STR("title"), STR("title/node()"), STR("true()"), STR("url"), STR("visibleurl"), STR("id(\"level10\")/ancestor::SPAN"), STR("id(\"level10\")/ancestor-or-self::SPAN"), STR("//attribute::*"),
STR("child::HTML/child::BODY/child::H1"), STR("descendant::node()"), STR("descendant-or-self::SPAN"), STR("id(\"first\")/following::text()"), STR("id(\"first\")/following-sibling::node()"),
STR("id(\"level10\")/parent::node()"), STR("id(\"last\")/preceding::text()"), STR("id(\"last\")/preceding-sibling::node()"), STR("/HTML/BODY/H1/self::node()"), STR("//*[@name]"),
STR("id(\"pet\")/SELECT[@name=\"species\"]/OPTION[@selected]/@value"), STR("descendant::INPUT[@name=\"name\"]/@value"), STR("id(\"pet\")/INPUT[@name=\"gender\" and @checked]/@value"),
STR("//TEXTAREA[@name=\"description\"]/text()"), STR("id(\"div1\")|id(\"div2\")|id(\"div3 div4 div5\")"), STR("//LI[1]"), STR("//LI[last()]/text()"), STR("//LI[position() mod 2]/@class"),
STR("//text()[.=\"foo\"]"), STR("descendant-or-self::SPAN[position() > 2]"), STR("descendant::*[contains(@class,\" fruit \")]"),
// ajaxslt considers this path invalid, however I believe it's valid as per spec
STR("***"),
// ajaxslt considers this path invalid, however I believe it's valid as per spec
STR("***"),
// Oasis MSFT considers this path invalid, however I believe it's valid as per spec
STR("**..**"),
// Oasis MSFT considers this path invalid, however I believe it's valid as per spec
STR("**..**"),
// Miscellaneous
STR("..***..***.***.***..***..***..")
};
// Miscellaneous
STR("..***..***.***.***..***..***..")};
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i)
{
@ -185,73 +183,125 @@ TEST(xpath_parse_paths_valid)
#if defined(PUGIXML_WCHAR_MODE) || !defined(PUGIXML_NO_STL)
TEST(xpath_parse_paths_valid_unicode)
{
// From ajaxslt
// From ajaxslt
const wchar_t* paths[] =
{
#ifdef U_LITERALS
L"/descendant-or-self::\u90e8\u5206", L"//\u90e8\u5206", L"substring('\uff11\uff12\uff13\uff14\uff15', 0, 3)", L"//\u30bf\u30a4\u30c8\u30eb | //\u30ea\u30f3\u30af",
L"\u8b0e//\u30bf\u30a4\u30c8\u30eb", L"//*[@\u30c7\u30b9\u30c6\u30a3\u30cd\u30a4\u30b7\u30e7\u30f3]", L"\u30da\u30fc\u30b8 = '\u304b\u3089'",
L"concat(substring-before(@\u30a4\u30e1\u30fc\u30b8,'\u76ee\u5370'),'\u30a2\u30a4\u30b3\u30f3',substring-after(@\u30a4\u30e1\u30fc\u30b8,'\u76ee\u5370'))",
L"\u30bd\u30fc\u30b9|\u30c7\u30b9\u30c6\u30a3\u30cd\u30a4\u30b7\u30e7\u30f3", L"\u30da\u30fc\u30b8 != '\u307e\u3067' and \u30da\u30fc\u30b8 != '\u304b\u3089'",
L"substring-after(\u30a2\u30a4\u30b3\u30f3/@\u30a4\u30e1\u30fc\u30b8, '/\u5730\u56f3\u30d5\u30a1\u30a4\u30eb/\u76ee\u5370')", L"child::\u6bb5\u843d",
L"substring-before(\u6587\u5b57\u5217, \u6587\u5b57)", L"\u30bb\u30b0\u30e1\u30f3\u30c8/@\u6642\u523b", L"attribute::\u540d\u524d", L"descendant::\u6bb5\u843d",
L"ancestor::\u90e8\u5206", L"ancestor-or-self::\u90e8\u5206", L"descendant-or-self::\u6bb5\u843d", L"self::\u6bb5\u843d", L"child::\u7ae0/descendant::\u6bb5\u843d",
L"child::*/child::\u6bb5\u843d", L"/descendant::\u6bb5\u843d", L"/descendant::\u9806\u5e8f\u30ea\u30b9\u30c8/child::\u9805\u76ee", L"child::\u6bb5\u843d[position()=1]",
L"child::\u6bb5\u843d[position()=last()]", L"child::\u6bb5\u843d[position()=last()-1]", L"child::\u6bb5\u843d[position()>1]", L"following-sibling::\u7ae0[position()=1]",
L"preceding-sibling::\u7ae0[position()=1]", L"/descendant::\u56f3\u8868[position()=42]", L"/child::\u6587\u66f8/child::\u7ae0[position()=5]/child::\u7bc0[position()=2]",
L"child::\u6bb5\u843d[attribute::\u30bf\u30a4\u30d7='\u8b66\u544a']", L"child::\u6bb5\u843d[attribute::\u30bf\u30a4\u30d7='\u8b66\u544a'][position()=5]",
L"child::\u6bb5\u843d[position()=5][attribute::\u30bf\u30a4\u30d7='\u8b66\u544a']", L"child::\u7ae0[child::\u30bf\u30a4\u30c8\u30eb='\u306f\u3058\u3081\u306b']",
L"child::\u7ae0[child::\u30bf\u30a4\u30c8\u30eb]", L"child::*[self::\u7ae0 or self::\u4ed8\u9332]", L"child::*[self::\u7ae0 or self::\u4ed8\u9332][position()=last()]",
#else
L"/descendant-or-self::\x90e8\x5206", L"//\x90e8\x5206", L"substring('\xff11\xff12\xff13\xff14\xff15', 0, 3)", L"//\x30bf\x30a4\x30c8\x30eb | //\x30ea\x30f3\x30af",
L"\x8b0e//\x30bf\x30a4\x30c8\x30eb", L"//*[@\x30c7\x30b9\x30c6\x30a3\x30cd\x30a4\x30b7\x30e7\x30f3]", L"\x30da\x30fc\x30b8 = '\x304b\x3089'",
L"concat(substring-before(@\x30a4\x30e1\x30fc\x30b8,'\x76ee\x5370'),'\x30a2\x30a4\x30b3\x30f3',substring-after(@\x30a4\x30e1\x30fc\x30b8,'\x76ee\x5370'))",
L"\x30bd\x30fc\x30b9|\x30c7\x30b9\x30c6\x30a3\x30cd\x30a4\x30b7\x30e7\x30f3", L"\x30da\x30fc\x30b8 != '\x307e\x3067' and \x30da\x30fc\x30b8 != '\x304b\x3089'",
L"substring-after(\x30a2\x30a4\x30b3\x30f3/@\x30a4\x30e1\x30fc\x30b8, '/\x5730\x56f3\x30d5\x30a1\x30a4\x30eb/\x76ee\x5370')", L"child::\x6bb5\x843d",
L"substring-before(\x6587\x5b57\x5217, \x6587\x5b57)", L"\x30bb\x30b0\x30e1\x30f3\x30c8/@\x6642\x523b", L"attribute::\x540d\x524d", L"descendant::\x6bb5\x843d",
L"ancestor::\x90e8\x5206", L"ancestor-or-self::\x90e8\x5206", L"descendant-or-self::\x6bb5\x843d", L"self::\x6bb5\x843d", L"child::\x7ae0/descendant::\x6bb5\x843d",
L"child::*/child::\x6bb5\x843d", L"/descendant::\x6bb5\x843d", L"/descendant::\x9806\x5e8f\x30ea\x30b9\x30c8/child::\x9805\x76ee", L"child::\x6bb5\x843d[position()=1]",
L"child::\x6bb5\x843d[position()=last()]", L"child::\x6bb5\x843d[position()=last()-1]", L"child::\x6bb5\x843d[position()>1]", L"following-sibling::\x7ae0[position()=1]",
L"preceding-sibling::\x7ae0[position()=1]", L"/descendant::\x56f3\x8868[position()=42]", L"/child::\x6587\x66f8/child::\x7ae0[position()=5]/child::\x7bc0[position()=2]",
L"child::\x6bb5\x843d[attribute::\x30bf\x30a4\x30d7='\x8b66\x544a']", L"child::\x6bb5\x843d[attribute::\x30bf\x30a4\x30d7='\x8b66\x544a'][position()=5]",
L"child::\x6bb5\x843d[position()=5][attribute::\x30bf\x30a4\x30d7='\x8b66\x544a']", L"child::\x7ae0[child::\x30bf\x30a4\x30c8\x30eb='\x306f\x3058\x3081\x306b']",
L"child::\x7ae0[child::\x30bf\x30a4\x30c8\x30eb]", L"child::*[self::\x7ae0 or self::\x4ed8\x9332]", L"child::*[self::\x7ae0 or self::\x4ed8\x9332][position()=last()]",
#endif
};
{
#ifdef U_LITERALS
L"/descendant-or-self::\u90e8\u5206",
L"//\u90e8\u5206",
L"substring('\uff11\uff12\uff13\uff14\uff15', 0, 3)",
L"//\u30bf\u30a4\u30c8\u30eb | //\u30ea\u30f3\u30af",
L"\u8b0e//\u30bf\u30a4\u30c8\u30eb",
L"//*[@\u30c7\u30b9\u30c6\u30a3\u30cd\u30a4\u30b7\u30e7\u30f3]",
L"\u30da\u30fc\u30b8 = '\u304b\u3089'",
L"concat(substring-before(@\u30a4\u30e1\u30fc\u30b8,'\u76ee\u5370'),'\u30a2\u30a4\u30b3\u30f3',substring-after(@\u30a4\u30e1\u30fc\u30b8,'\u76ee\u5370'))",
L"\u30bd\u30fc\u30b9|\u30c7\u30b9\u30c6\u30a3\u30cd\u30a4\u30b7\u30e7\u30f3",
L"\u30da\u30fc\u30b8 != '\u307e\u3067' and \u30da\u30fc\u30b8 != '\u304b\u3089'",
L"substring-after(\u30a2\u30a4\u30b3\u30f3/@\u30a4\u30e1\u30fc\u30b8, '/\u5730\u56f3\u30d5\u30a1\u30a4\u30eb/\u76ee\u5370')",
L"child::\u6bb5\u843d",
L"substring-before(\u6587\u5b57\u5217, \u6587\u5b57)",
L"\u30bb\u30b0\u30e1\u30f3\u30c8/@\u6642\u523b",
L"attribute::\u540d\u524d",
L"descendant::\u6bb5\u843d",
L"ancestor::\u90e8\u5206",
L"ancestor-or-self::\u90e8\u5206",
L"descendant-or-self::\u6bb5\u843d",
L"self::\u6bb5\u843d",
L"child::\u7ae0/descendant::\u6bb5\u843d",
L"child::*/child::\u6bb5\u843d",
L"/descendant::\u6bb5\u843d",
L"/descendant::\u9806\u5e8f\u30ea\u30b9\u30c8/child::\u9805\u76ee",
L"child::\u6bb5\u843d[position()=1]",
L"child::\u6bb5\u843d[position()=last()]",
L"child::\u6bb5\u843d[position()=last()-1]",
L"child::\u6bb5\u843d[position()>1]",
L"following-sibling::\u7ae0[position()=1]",
L"preceding-sibling::\u7ae0[position()=1]",
L"/descendant::\u56f3\u8868[position()=42]",
L"/child::\u6587\u66f8/child::\u7ae0[position()=5]/child::\u7bc0[position()=2]",
L"child::\u6bb5\u843d[attribute::\u30bf\u30a4\u30d7='\u8b66\u544a']",
L"child::\u6bb5\u843d[attribute::\u30bf\u30a4\u30d7='\u8b66\u544a'][position()=5]",
L"child::\u6bb5\u843d[position()=5][attribute::\u30bf\u30a4\u30d7='\u8b66\u544a']",
L"child::\u7ae0[child::\u30bf\u30a4\u30c8\u30eb='\u306f\u3058\u3081\u306b']",
L"child::\u7ae0[child::\u30bf\u30a4\u30c8\u30eb]",
L"child::*[self::\u7ae0 or self::\u4ed8\u9332]",
L"child::*[self::\u7ae0 or self::\u4ed8\u9332][position()=last()]",
#else
L"/descendant-or-self::\x90e8\x5206",
L"//\x90e8\x5206",
L"substring('\xff11\xff12\xff13\xff14\xff15', 0, 3)",
L"//\x30bf\x30a4\x30c8\x30eb | //\x30ea\x30f3\x30af",
L"\x8b0e//\x30bf\x30a4\x30c8\x30eb",
L"//*[@\x30c7\x30b9\x30c6\x30a3\x30cd\x30a4\x30b7\x30e7\x30f3]",
L"\x30da\x30fc\x30b8 = '\x304b\x3089'",
L"concat(substring-before(@\x30a4\x30e1\x30fc\x30b8,'\x76ee\x5370'),'\x30a2\x30a4\x30b3\x30f3',substring-after(@\x30a4\x30e1\x30fc\x30b8,'\x76ee\x5370'))",
L"\x30bd\x30fc\x30b9|\x30c7\x30b9\x30c6\x30a3\x30cd\x30a4\x30b7\x30e7\x30f3",
L"\x30da\x30fc\x30b8 != '\x307e\x3067' and \x30da\x30fc\x30b8 != '\x304b\x3089'",
L"substring-after(\x30a2\x30a4\x30b3\x30f3/@\x30a4\x30e1\x30fc\x30b8, '/\x5730\x56f3\x30d5\x30a1\x30a4\x30eb/\x76ee\x5370')",
L"child::\x6bb5\x843d",
L"substring-before(\x6587\x5b57\x5217, \x6587\x5b57)",
L"\x30bb\x30b0\x30e1\x30f3\x30c8/@\x6642\x523b",
L"attribute::\x540d\x524d",
L"descendant::\x6bb5\x843d",
L"ancestor::\x90e8\x5206",
L"ancestor-or-self::\x90e8\x5206",
L"descendant-or-self::\x6bb5\x843d",
L"self::\x6bb5\x843d",
L"child::\x7ae0/descendant::\x6bb5\x843d",
L"child::*/child::\x6bb5\x843d",
L"/descendant::\x6bb5\x843d",
L"/descendant::\x9806\x5e8f\x30ea\x30b9\x30c8/child::\x9805\x76ee",
L"child::\x6bb5\x843d[position()=1]",
L"child::\x6bb5\x843d[position()=last()]",
L"child::\x6bb5\x843d[position()=last()-1]",
L"child::\x6bb5\x843d[position()>1]",
L"following-sibling::\x7ae0[position()=1]",
L"preceding-sibling::\x7ae0[position()=1]",
L"/descendant::\x56f3\x8868[position()=42]",
L"/child::\x6587\x66f8/child::\x7ae0[position()=5]/child::\x7bc0[position()=2]",
L"child::\x6bb5\x843d[attribute::\x30bf\x30a4\x30d7='\x8b66\x544a']",
L"child::\x6bb5\x843d[attribute::\x30bf\x30a4\x30d7='\x8b66\x544a'][position()=5]",
L"child::\x6bb5\x843d[position()=5][attribute::\x30bf\x30a4\x30d7='\x8b66\x544a']",
L"child::\x7ae0[child::\x30bf\x30a4\x30c8\x30eb='\x306f\x3058\x3081\x306b']",
L"child::\x7ae0[child::\x30bf\x30a4\x30c8\x30eb]",
L"child::*[self::\x7ae0 or self::\x4ed8\x9332]",
L"child::*[self::\x7ae0 or self::\x4ed8\x9332][position()=last()]",
#endif
};
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i)
{
#if defined(PUGIXML_WCHAR_MODE)
#if defined(PUGIXML_WCHAR_MODE)
xpath_query q(paths[i]);
#elif !defined(PUGIXML_NO_STL)
#elif !defined(PUGIXML_NO_STL)
std::basic_string<char> path_utf8 = as_utf8(paths[i]);
xpath_query q(path_utf8.c_str());
#endif
#endif
}
}
#endif
TEST(xpath_parse_invalid)
{
const char_t* paths[] =
{
// From Jaxen tests
STR("//:p"), STR("/foo/bar/"), STR("12 + (count(//author)+count(//author/attribute::*)) / 2"), STR("id()/2"), STR("+"),
STR("///triple slash"), STR("/numbers numbers"), STR("/a/b[c > d]efg"), STR("/inv/child::"), STR("/invoice/@test[abcd"),
STR("/invoice/@test[abcd > x"), STR("string-length('a"), STR("/descendant::()"), STR("(1 + 1"), STR("!false()"),
STR("$author"), STR("10 + $foo"), STR("$foo:bar"), STR("$varname[@a='1']"), STR("foo/$variable/foo"),
STR(".[1]"), STR("chyld::foo"), STR("foo/tacos()"), STR("foo/tacos()"), STR("/foo/bar[baz"), STR("//"), STR("*:foo"),
STR("/cracker/cheese[(mold > 1) and (sense/taste"),
const char_t* paths[] =
{
// From Jaxen tests
STR("//:p"), STR("/foo/bar/"), STR("12 + (count(//author)+count(//author/attribute::*)) / 2"), STR("id()/2"), STR("+"),
STR("///triple slash"), STR("/numbers numbers"), STR("/a/b[c > d]efg"), STR("/inv/child::"), STR("/invoice/@test[abcd"),
STR("/invoice/@test[abcd > x"), STR("string-length('a"), STR("/descendant::()"), STR("(1 + 1"), STR("!false()"),
STR("$author"), STR("10 + $foo"), STR("$foo:bar"), STR("$varname[@a='1']"), STR("foo/$variable/foo"),
STR(".[1]"), STR("chyld::foo"), STR("foo/tacos()"), STR("foo/tacos()"), STR("/foo/bar[baz"), STR("//"), STR("*:foo"),
STR("/cracker/cheese[(mold > 1) and (sense/taste"),
// From xpath-as3 tests
STR("a b"), STR("//self::node())"), STR("/x/y[contains(self::node())"), STR("/x/y[contains(self::node()]"), STR("///"), STR("text::a"),
// From xpath-as3 tests
STR("a b"), STR("//self::node())"), STR("/x/y[contains(self::node())"), STR("/x/y[contains(self::node()]"), STR("///"), STR("text::a"),
// From haXe-xpath tests
STR("|/gjs"), STR("+3"), STR("/html/body/p != ---'div'/a"), STR(""), STR("@"), STR("#akf"), STR(",")
// From haXe-xpath tests
STR("|/gjs"), STR("+3"), STR("/html/body/p != ---'div'/a"), STR(""), STR("@"), STR("#akf"), STR(",")
// Miscellaneous
STR("..."), STR("...."), STR("**"), STR("****"), STR("******"), STR("..***..***.***.***..***..***..*"), STR("/[1]")
};
// Miscellaneous
STR("..."),
STR("...."), STR("**"), STR("****"), STR("******"), STR("..***..***.***.***..***..***..*"), STR("/[1]")};
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i)
{
@ -376,7 +426,7 @@ TEST(xpath_parse_oom_propagation)
{
std::basic_string<char_t> literal(i, 'a');
std::basic_string<char_t> query = STR("processing-instruction('") + literal + STR("') | ") + query_base;
CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(query.c_str()));
}
}

View file

@ -27,9 +27,9 @@ TEST_XML(xpath_paths_axes_descendant, "<node attr='value'><child attr='value'><s
CHECK_XPATH_NODESET(c, STR("descendant:: node()"));
CHECK_XPATH_NODESET(n, STR("descendant:: node()")) % 4 % 6 % 7 % 8 % 9; // child, subchild, another, subchild, last
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("another/descendant:: node()")) % 8; // subchild
CHECK_XPATH_NODESET(n, STR("last/descendant:: node()"));
CHECK_XPATH_NODESET(n, STR("@attr/descendant::node()"));
@ -45,9 +45,9 @@ TEST_XML(xpath_paths_axes_parent, "<node attr='value'><child attr='value'><subch
CHECK_XPATH_NODESET(c, STR("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(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()"));
CHECK_XPATH_NODESET(na, STR("parent:: node()")) % 2; // node
@ -62,9 +62,9 @@ TEST_XML(xpath_paths_axes_ancestor, "<node attr='value'><child attr='value'><sub
CHECK_XPATH_NODESET(c, STR("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(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()"));
CHECK_XPATH_NODESET(na, STR("ancestor:: node()")) % 4 % 2 % 1; // child, node, root
@ -82,7 +82,7 @@ TEST_XML(xpath_paths_axes_following_sibling, "<node attr1='value' attr2='value'>
CHECK_XPATH_NODESET(n.child(STR("last")), STR("following-sibling:: node()"));
CHECK_XPATH_NODESET(n, STR("@attr1/following-sibling:: node()")); // attributes are not siblings
CHECK_XPATH_NODESET(na, STR("following-sibling:: node()")); // attributes are not siblings
CHECK_XPATH_NODESET(na, STR("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>")
@ -97,7 +97,7 @@ TEST_XML(xpath_paths_axes_preceding_sibling, "<node attr1='value' attr2='value'>
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
CHECK_XPATH_NODESET(na, STR("following-sibling:: node()")); // attributes are not siblings
CHECK_XPATH_NODESET(na, STR("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>")
@ -108,14 +108,14 @@ TEST_XML(xpath_paths_axes_following, "<node attr1='value' attr2='value'><child a
CHECK_XPATH_NODESET(c, STR("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, 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()"));
CHECK_XPATH_NODESET(n, STR("@attr1/following::node()")) % 5 % 7 % 8 % 9 % 10 % 11; // child, subchild, another, subchild, almost, last - because @/following
CHECK_XPATH_NODESET(n, STR("@attr1/following::node()")) % 5 % 7 % 8 % 9 % 10 % 11; // child, subchild, another, subchild, almost, last - because @/following
CHECK_XPATH_NODESET(n, STR("child/@attr/following::node()")) % 7 % 8 % 9 % 10 % 11; // subchild, another, subchild, almost, last
CHECK_XPATH_NODESET(na, STR("following::node()")) % 5 % 7 % 8 % 9 % 10 % 11; // child, subchild, another, subchild, almost, last - because @/following
CHECK_XPATH_NODESET(na, STR("following::node()")) % 5 % 7 % 8 % 9 % 10 % 11; // child, subchild, another, subchild, almost, last - because @/following
}
TEST_XML(xpath_paths_axes_preceding, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another><subchild id='1'/></another><almost/><last/></node>")
@ -126,14 +126,14 @@ TEST_XML(xpath_paths_axes_preceding, "<node attr1='value' attr2='value'><child a
CHECK_XPATH_NODESET(c, STR("preceding:: node()"));
CHECK_XPATH_NODESET(n.child(STR("child")), STR("preceding:: node()")); // no ancestors
CHECK_XPATH_NODESET(n.child(STR("last")), STR("preceding:: node()")) % 11 % 9 % 8 % 7 % 5; // almost, subchild, another, subchild, child
CHECK_XPATH_NODESET(n.child(STR("child")), STR("preceding:: node()")); // no ancestors
CHECK_XPATH_NODESET(n.child(STR("last")), STR("preceding:: node()")) % 11 % 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()"));
CHECK_XPATH_NODESET(n, STR("child/@attr/preceding::node()")); // no ancestors
CHECK_XPATH_NODESET(n, STR("child/@attr/preceding::node()")); // no ancestors
CHECK_XPATH_NODESET(n, STR("//subchild[@id]/@id/preceding::node()")) % 7 % 5; // subchild, child
CHECK_XPATH_NODESET(na, STR("preceding::node()")); // no ancestors
CHECK_XPATH_NODESET(na, STR("preceding::node()")); // no ancestors
}
TEST_XML(xpath_paths_axes_attribute, "<node attr1='value' attr2='value'><child attr='value'><subchild/></child><another xmlns:foo='bar'><subchild/></another><last/></node>")
@ -146,9 +146,9 @@ TEST_XML(xpath_paths_axes_attribute, "<node attr1='value' attr2='value'><child a
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(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
CHECK_XPATH_NODESET(n.child(STR("another")), STR("attribute:: node()")); // namespace nodes are not attributes
CHECK_XPATH_NODESET(n, STR("@attr1/attribute::node()"));
CHECK_XPATH_NODESET(na, STR("attribute::node()"));
@ -174,11 +174,11 @@ TEST_XML(xpath_paths_axes_self, "<node attr='value'><child attr='value'><subchil
CHECK_XPATH_NODESET(c, STR("self:: node()"));
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
CHECK_XPATH_NODESET(na, STR("self:: node()")) % 3; // @attr
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
CHECK_XPATH_NODESET(na, STR("self:: node()")) % 3; // @attr
}
TEST_XML(xpath_paths_axes_descendant_or_self, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -189,13 +189,13 @@ TEST_XML(xpath_paths_axes_descendant_or_self, "<node attr='value'><child attr='v
CHECK_XPATH_NODESET(c, STR("descendant-or-self:: node()"));
CHECK_XPATH_NODESET(n, STR("descendant-or-self:: node()")) % 2 % 4 % 6 % 7 % 8 % 9; // node, child, subchild, another, subchild, 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
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
CHECK_XPATH_NODESET(n, STR("child/@attr/descendant-or-self::node()")) % 5; // @attr
CHECK_XPATH_NODESET(na, STR("descendant-or-self::node()")) % 5; // @attr
CHECK_XPATH_NODESET(na, STR("descendant-or-self::node()")) % 5; // @attr
}
TEST_XML(xpath_paths_axes_ancestor_or_self, "<node attr='value'><child attr='value'><subchild/></child><another><subchild/></another><last/></node>")
@ -207,13 +207,13 @@ TEST_XML(xpath_paths_axes_ancestor_or_self, "<node attr='value'><child attr='val
CHECK_XPATH_NODESET(c, STR("ancestor-or-self:: node()"));
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
CHECK_XPATH_NODESET(n, STR("ancestor-or-self:: node()")) % 2 % 1; // root, node
CHECK_XPATH_NODESET(n, STR("last/ancestor-or-self::node()")) % 9 % 2 % 1; // root, node, last
CHECK_XPATH_NODESET(na, STR("ancestor-or-self:: node()")) % 5 % 4 % 2 % 1; // @attr, 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
CHECK_XPATH_NODESET(n, STR("ancestor-or-self:: node()")) % 2 % 1; // root, node
CHECK_XPATH_NODESET(n, STR("last/ancestor-or-self::node()")) % 9 % 2 % 1; // root, node, last
CHECK_XPATH_NODESET(na, STR("ancestor-or-self:: node()")) % 5 % 4 % 2 % 1; // @attr, child, node, root
}
TEST_XML(xpath_paths_axes_abbrev, "<node attr='value'><foo/></node>")
@ -561,7 +561,7 @@ TEST_XML(xpath_paths_descendant_double_slash_w3c, "<node><para><para/><para/><pa
TEST_XML(xpath_paths_needs_sorting, "<node><child/><child/><child><subchild/><subchild/></child></node>")
{
CHECK_XPATH_NODESET(doc, STR("(node/child/subchild)[2]")) % 7;
CHECK_XPATH_NODESET(doc, STR("(node/child/subchild)[2]")) % 7;
}
TEST_XML(xpath_paths_descendant_filters, "<node><para><para/><para/><para><para/></para></para><para/></node>")
@ -657,53 +657,53 @@ TEST_XML(xpath_paths_optimize_compare_attribute, "<node id='1' /><node id='2' />
TEST_XML(xpath_paths_optimize_step_once, "<node><para1><para2/><para3/><para4><para5 attr5=''/></para4></para1><para6/></node>")
{
CHECK_XPATH_BOOLEAN(doc, STR("node//para2/following::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/following::*"), false);
CHECK_XPATH_BOOLEAN(doc, STR("node//para2/following::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/following::*"), false);
CHECK_XPATH_STRING(doc, STR("name(node//para2/following::*)"), STR("para3"));
CHECK_XPATH_STRING(doc, STR("name(node//para6/following::*)"), STR(""));
CHECK_XPATH_STRING(doc, STR("name(node//para2/following::*)"), STR("para3"));
CHECK_XPATH_STRING(doc, STR("name(node//para6/following::*)"), STR(""));
CHECK_XPATH_BOOLEAN(doc, STR("node//para1/preceding::*"), false);
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/preceding::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("node//para1/preceding::*"), false);
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/preceding::*"), true);
CHECK_XPATH_STRING(doc, STR("name(node//para1/preceding::*)"), STR(""));
CHECK_XPATH_STRING(doc, STR("name(node//para6/preceding::*)"), STR("para1"));
CHECK_XPATH_STRING(doc, STR("name(node//para1/preceding::*)"), STR(""));
CHECK_XPATH_STRING(doc, STR("name(node//para6/preceding::*)"), STR("para1"));
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/preceding::para4"), true);
CHECK_XPATH_BOOLEAN(doc, STR("node//para6/preceding::para4"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor-or-self::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor-or-self::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/following::para6"), true);
CHECK_XPATH_STRING(doc, STR("name(//@attr5/following::para6)"), STR("para6"));
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/following::para6"), true);
CHECK_XPATH_STRING(doc, STR("name(//@attr5/following::para6)"), STR("para6"));
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor-or-self::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor-or-self::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor::*"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor-or-self::node()"), true);
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor-or-self::node()"), true);
}
TEST_XML(xpath_paths_null_nodeset_entries, "<node attr='value'/>")
{
xpath_node nodes[] =
{
xpath_node(doc.first_child()),
xpath_node(xml_node()),
xpath_node(doc.first_child().first_attribute(), doc.first_child()),
xpath_node(xml_attribute(), doc.first_child()),
xpath_node(xml_attribute(), xml_node()),
};
xpath_node nodes[] =
{
xpath_node(doc.first_child()),
xpath_node(xml_node()),
xpath_node(doc.first_child().first_attribute(), doc.first_child()),
xpath_node(xml_attribute(), doc.first_child()),
xpath_node(xml_attribute(), xml_node()),
};
xpath_node_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]));
xpath_node_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]));
xpath_variable_set vars;
vars.set(STR("x"), ns);
xpath_variable_set vars;
vars.set(STR("x"), ns);
xpath_node_set rs = xpath_query(STR("$x/."), &vars).evaluate_node_set(xml_node());
xpath_node_set rs = xpath_query(STR("$x/."), &vars).evaluate_node_set(xml_node());
CHECK(rs.size() == 2);
CHECK(rs[0] == nodes[0]);
CHECK(rs[1] == nodes[2]);
CHECK(rs.size() == 2);
CHECK(rs[0] == nodes[0]);
CHECK(rs[1] == nodes[2]);
}
TEST_XML(xpath_paths_step_leaf_coverage, "<n><n1/><n2 a='v'><child/></n2><n3/></n>")

View file

@ -404,11 +404,11 @@ TEST(xpath_variables_name_case)
TEST(xpath_variables_name_unicode)
{
#ifdef PUGIXML_WCHAR_MODE
#ifdef U_LITERALS
const char_t* name = L"\u0400\u203D";
#else
const char_t* name = L"\x0400\x203D";
#endif
#ifdef U_LITERALS
const char_t* name = L"\u0400\u203D";
#else
const char_t* name = L"\x0400\x203D";
#endif
#else
const char_t* name = "\xd0\x80\xe2\x80\xbd";
#endif

View file

@ -322,16 +322,16 @@ TEST(xpath_xalan_math_5)
CHECK_XPATH_NUMBER(c, STR("10+5+25+20+15+50+35+40"), 200);
CHECK_XPATH_NUMBER(c, STR("100-9-7-4-17-18-5"), 40);
CHECK_XPATH_NUMBER(c, STR("3*2+5*4-4*2-1"), 17);
CHECK_XPATH_NUMBER(c, STR("6*5-8*2+5*2"), 24);
CHECK_XPATH_NUMBER(c, STR("10*5-4*2+6*1 -3*3"), 39);
CHECK_XPATH_NUMBER(c, STR("6*5-8*2+5*2"), 24);
CHECK_XPATH_NUMBER(c, STR("10*5-4*2+6*1 -3*3"), 39);
CHECK_XPATH_NUMBER(c, STR("(24 div 3 +2) div (40 div 8 -3)"), 5);
CHECK_XPATH_NUMBER(c, STR("80 div 2 + 12 div 2 - 4 div 2"), 44);
CHECK_XPATH_NUMBER(c, STR("70 div 10 - 18 div 6 + 10 div 2"), 9);
CHECK_XPATH_NUMBER(c, STR("(24 div 3 +2) div (40 div 8 -3)"), 5);
CHECK_XPATH_NUMBER(c, STR("80 div 2 + 12 div 2 - 4 div 2"), 44);
CHECK_XPATH_NUMBER(c, STR("70 div 10 - 18 div 6 + 10 div 2"), 9);
CHECK_XPATH_NUMBER(c, STR("48 mod 17 - 2 mod 9 + 13 mod 5"), 15);
CHECK_XPATH_NUMBER(c, STR("56 mod round(5*2+1.444) - 6 mod 4 + 7 mod 4"), 2);
CHECK_XPATH_NUMBER(c, STR("(77 mod 10 + 5 mod 8) mod 10"), 2);
CHECK_XPATH_NUMBER(c, STR("48 mod 17 - 2 mod 9 + 13 mod 5"), 15);
CHECK_XPATH_NUMBER(c, STR("56 mod round(5*2+1.444) - 6 mod 4 + 7 mod 4"), 2);
CHECK_XPATH_NUMBER(c, STR("(77 mod 10 + 5 mod 8) mod 10"), 2);
}
TEST_XML(xpath_xalan_math_6, "<doc><n1>3</n1><n2>7</n2><n3>x</n3></doc>")

View file

@ -4,8 +4,8 @@
#include "test.hpp"
#include <string>
#include <algorithm>
#include <string>
using namespace pugi;

View file

@ -193,7 +193,7 @@ TEST_XML(xpath_xalan_axes_9, "<doc><foo att1='c'><foo att1='b'><foo att1='a'><ba
xml_node baz = doc.select_node(STR("//baz")).node();
CHECK_XPATH_NODESET(baz, STR("ancestor-or-self::*[@att1][1]/@att1")) % 8;
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*)[@att1][1]/@att1")) % 4;
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*)[@att1][1]/@att1")) % 4;
CHECK_XPATH_NODESET(baz, STR("ancestor::foo[1]/@att1")) % 8;
CHECK_XPATH_NODESET(baz, STR("(ancestor::foo[1])/@att1")) % 8;
@ -203,7 +203,7 @@ TEST_XML(xpath_xalan_axes_9, "<doc><foo att1='c'><foo att1='b'><foo att1='a'><ba
xml_node bar = doc.child(STR("doc")).child(STR("bar"));
CHECK_XPATH_NODESET(bar, STR("preceding::foo[1]/@att1")) % 8;
CHECK_XPATH_NODESET(bar, STR("preceding::foo[1]/@att1")) % 8;
CHECK_XPATH_NODESET(bar, STR("(preceding::foo)[1]/@att1")) % 4;
}
@ -211,7 +211,7 @@ TEST_XML(xpath_xalan_axes_10, "<doc><foo att1='c'/><foo att1='b'/><foo att1='a'/
{
xml_node baz = doc.child(STR("doc")).child(STR("baz"));
CHECK_XPATH_NODESET(baz, STR("preceding-sibling::foo[1]/@att1")) % 8;
CHECK_XPATH_NODESET(baz, STR("preceding-sibling::foo[1]/@att1")) % 8;
CHECK_XPATH_NODESET(baz, STR("(preceding-sibling::foo)[1]/@att1")) % 4;
}
@ -219,10 +219,10 @@ TEST_XML(xpath_xalan_axes_11, "<chapter title='A' x='0'><section title='A1' x='1
{
xml_node chapter = doc.child(STR("chapter"));
CHECK_XPATH_NUMBER(doc, STR("count(//@*)"), 16);
CHECK_XPATH_NUMBER(doc, STR("count(//@title)"), 12);
CHECK_XPATH_NUMBER(doc, STR("count(//section//@*)"), 14);
CHECK_XPATH_NUMBER(doc, STR("count(//section//@title)"), 11);
CHECK_XPATH_NUMBER(doc, STR("count(//@*)"), 16);
CHECK_XPATH_NUMBER(doc, STR("count(//@title)"), 12);
CHECK_XPATH_NUMBER(doc, STR("count(//section//@*)"), 14);
CHECK_XPATH_NUMBER(doc, STR("count(//section//@title)"), 11);
CHECK_XPATH_NUMBER(chapter, STR("count(.//@*)"), 16);
CHECK_XPATH_NUMBER(chapter, STR("count(.//@title)"), 12);
@ -254,13 +254,13 @@ TEST_XML(xpath_xalan_axes_13, "<doc att1='e'><foo att1='d'><foo att1='c'><foo at
CHECK_XPATH_NODESET(d, STR("(descendant-or-self::*/@att1)[last()]")) % 11;
CHECK_XPATH_NUMBER(baz, STR("count(ancestor-or-self::*/@att1)"), 5);
CHECK_XPATH_NODESET(baz, STR("ancestor-or-self::*/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string(ancestor-or-self::*/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*)/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string((ancestor-or-self::*)/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*/@att1)[last()]")) % 11;
CHECK_XPATH_NODESET(baz, STR("(ancestor::*|self::*)/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string((ancestor::*|self::*)/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("ancestor-or-self::*/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string(ancestor-or-self::*/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*)/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string((ancestor-or-self::*)/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("(ancestor-or-self::*/@att1)[last()]")) % 11;
CHECK_XPATH_NODESET(baz, STR("(ancestor::*|self::*)/@att1[last()]")) % 3 % 5 % 7 % 9 % 11;
CHECK_XPATH_STRING(baz, STR("string((ancestor::*|self::*)/@att1[last()])"), STR("e"));
CHECK_XPATH_NODESET(baz, STR("((ancestor::*|self::*)/@att1)[last()]")) % 11;
}

View file

@ -52,12 +52,12 @@ TEST_XML_FLAGS(xpath_xalan_position_2, "<doc><a test='true'><num>1</num></a><a><
CHECK_XPATH_NODESET(c, STR("processing-instruction()[2]")) % 34;
CHECK_XPATH_NODESET(c, STR("processing-instruction('pi')[2]")) % 34;
CHECK_XPATH_NODESET(c, STR("comment()[2]")) % 36;
CHECK_XPATH_NODESET(c, STR("a/*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/child::*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/descendant::*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 31;
CHECK_XPATH_NODESET(c, STR("a/child::node()[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/descendant::text()[last()]")) % 6 % 9 % 12 % 16 % 19 % 22 % 26 % 32;
CHECK_XPATH_NODESET(c, STR("child::comment()[last()]")) % 36;
CHECK_XPATH_NODESET(c, STR("a/*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/child::*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/descendant::*[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 31;
CHECK_XPATH_NODESET(c, STR("a/child::node()[last()]")) % 5 % 8 % 11 % 15 % 18 % 21 % 25 % 29;
CHECK_XPATH_NODESET(c, STR("a/descendant::text()[last()]")) % 6 % 9 % 12 % 16 % 19 % 22 % 26 % 32;
CHECK_XPATH_NODESET(c, STR("child::comment()[last()]")) % 36;
}
TEST_XML(xpath_xalan_position_3, "<article class='whitepaper' status='Note'><articleinfo><title>AAA</title><section id='info'><title>BBB</title><para>About this article</para><section revisionflag='added'><title>CCC</title><para>This is the section titled 'ZZZ'.</para><ednote who='KKK'><title>DDD</title><para>Don't worry.</para><section revisionflag='added'><title>EEE</title><para>This is the deep subsection.</para></section></ednote></section></section></articleinfo></article>")
@ -111,7 +111,6 @@ TEST_XML(xpath_xalan_match_1, "<root><x spot='a' num='1'/><x spot='b' num='2'/><
CHECK_XPATH_NODESET(c, STR("x[(((((2*10)-4)+9) div 5) mod 3)]")) % 6;
}
TEST_XML(xpath_xalan_match_2, "<doc><l1><v2>doc-l1-v2</v2><x2>doc-l1-x2</x2><l2><v3>doc-l1-l2-v3</v3><w3>doc-l1-l2-w3</w3><x3>doc-l1-l2-x3</x3><y3>doc-l1-l2-y3</y3><l3><v4>doc-l1-l2-l3-v4</v4><x4>doc-l1-l2-l3-x4</x4></l3></l2></l1></doc>")
{
CHECK_XPATH_STRING(doc, STR("doc/l1/v2"), STR("doc-l1-v2"));

View file

@ -111,7 +111,7 @@ TEST_XML(xpath_xalan_select_11, "<doc><sub1 pos='1'><child1>descendant number 1<
TEST_XML(xpath_xalan_select_12, "<doc><sub pos='1'><child>child number 1</child><sub-sub pos='1sub'><child>grandchild number 1</child></sub-sub></sub><sub0 pos='2-no'><child>child number 2</child><sub pos='2.5'><child>grandchild number 2</child></sub></sub0><sub pos='3'><child>child number 3</child><subno pos='3.5-no'><child>grandchild number 3</child></subno></sub><sub0 pos='4-no'><child>child number 4</child><sub-sub pos='4sub'><child>grandchild number 4</child></sub-sub></sub0></doc>")
{
CHECK_XPATH_NODESET(doc, STR("//child/ancestor-or-self::sub | //child/ancestor-or-self::sub-sub")) % 3 % 7 % 15 % 19 % 31;
CHECK_XPATH_NODESET(doc, STR("//child/ancestor-or-self::sub | //child/ancestor-or-self::sub-sub")) % 3 % 7 % 15 % 19 % 31;
}
TEST_XML(xpath_xalan_select_13, "<doc><book><author><name real='no'>Carmelo Montanez</name><chapters>Nine</chapters><bibliography></bibliography></author></book><book><author><name real='na'>David Marston</name><chapters>Seven</chapters><bibliography></bibliography></author></book><book><author><name real='yes'>Mary Brady</name><chapters>Ten</chapters><bibliography><author><name>Lynne Rosenthal</name><chapters>Five</chapters></author></bibliography></author></book></doc>")
@ -154,17 +154,17 @@ TEST_XML(xpath_xalan_select_17, "<directions><north><dup1/><dup2/><south/><east/
{
xml_node c = doc.child(STR("directions"));
CHECK_XPATH_NODESET(c, STR("north/* | north/dup1 | north/dup2")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("north/dup2 | north/dup1 | north/*")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("//north/dup2 | south/preceding-sibling::*[4]/* | north/dup1 | north/*")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("north/dup2 | south/preceding-sibling::*[4]/* | north/*")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("north/* | north/dup1 | north/dup2")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("north/dup2 | north/dup1 | north/*")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("//north/dup2 | south/preceding-sibling::*[4]/* | north/dup1 | north/*")) % 4 % 5 % 6 % 7 % 8;
CHECK_XPATH_NODESET(c, STR("north/dup2 | south/preceding-sibling::*[4]/* | north/*")) % 4 % 5 % 6 % 7 % 8;
}
TEST_XML(xpath_xalan_select_18, "<para><font color='red'>Hello</font><font color='green'>There</font><font color='blue'>World</font></para>")
{
CHECK_XPATH_NODESET(doc, STR("/para/font[@color='green']")) % 6;
CHECK_XPATH_NODESET(doc.child(STR("para")), STR("/para/font[@color='green']")) % 6;
CHECK_XPATH_NODESET(doc.child(STR("para")).last_child(), STR("/para/font[@color='green']")) % 6;
CHECK_XPATH_NODESET(doc, STR("/para/font[@color='green']")) % 6;
CHECK_XPATH_NODESET(doc.child(STR("para")), STR("/para/font[@color='green']")) % 6;
CHECK_XPATH_NODESET(doc.child(STR("para")).last_child(), STR("/para/font[@color='green']")) % 6;
}
TEST_XML_FLAGS(xpath_xalan_select_19, "<doc>1<a>in-a</a>2<!-- upper comment --><b>3<bb>4<bbb>5</bbb>6</bb>7</b><!-- lower comment -->8<c>in-c</c>9<?pi?></doc>", parse_default | parse_comments | parse_pi)

View file

@ -5,10 +5,12 @@
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;
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;
if (length > 0 && result == std::string(expected, expected + length - 1) + "?")
return false;
return true;
}
@ -27,7 +29,7 @@ std::basic_string<wchar_t> xml_writer_string::as_wide() const
{
CHECK(contents.size() % sizeof(wchar_t) == 0);
// round-trip pointer through void* to avoid pointer alignment warnings; contents data should be heap allocated => safe to cast
// round-trip pointer through void* to avoid pointer alignment warnings; contents data should be heap allocated => safe to cast
return std::basic_string<wchar_t>(static_cast<const wchar_t*>(static_cast<const void*>(contents.data())), contents.size() / sizeof(wchar_t));
}
@ -37,7 +39,7 @@ std::basic_string<pugi::char_t> xml_writer_string::as_string() const
CHECK(contents.size() % sizeof(pugi::char_t) == 0);
#endif
// round-trip pointer through void* to avoid pointer alignment warnings; contents data should be heap allocated => safe to cast
// round-trip pointer through void* to avoid pointer alignment warnings; contents data should be heap allocated => safe to cast
return std::basic_string<pugi::char_t>(static_cast<const pugi::char_t*>(static_cast<const void*>(contents.data())), contents.size() / sizeof(pugi::char_t));
}

View file

@ -5,7 +5,7 @@
#include <string>
struct xml_writer_string: public pugi::xml_writer
struct xml_writer_string : public pugi::xml_writer
{
std::string contents;