mirror of
https://github.com/zeux/pugixml.git
synced 2024-12-27 13:33:17 +08:00
tests: Added more XPath variable tests
git-svn-id: http://pugixml.googlecode.com/svn/trunk@681 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
23d84cdf7c
commit
61ceb10baf
@ -70,55 +70,75 @@ bool test_double_nan(double value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PUGIXML_NO_XPATH
|
#ifndef PUGIXML_NO_XPATH
|
||||||
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, const pugi::char_t* expected)
|
bool test_xpath_string(const pugi::xpath_node& node, const pugi::xpath_query& query, const pugi::char_t* expected)
|
||||||
{
|
{
|
||||||
pugi::xpath_query q(query);
|
|
||||||
|
|
||||||
const size_t capacity = 64;
|
const size_t capacity = 64;
|
||||||
pugi::char_t result[capacity];
|
pugi::char_t result[capacity];
|
||||||
|
|
||||||
size_t size = q.evaluate_string(result, capacity, node);
|
size_t size = query.evaluate_string(result, capacity, node);
|
||||||
|
|
||||||
if (size <= capacity) return test_string_equal(result, expected);
|
if (size <= capacity) return test_string_equal(result, expected);
|
||||||
|
|
||||||
std::basic_string<pugi::char_t> buffer(size, ' ');
|
std::basic_string<pugi::char_t> buffer(size, ' ');
|
||||||
|
|
||||||
return q.evaluate_string(&buffer[0], size, node) == size && test_string_equal(buffer.c_str(), expected);
|
return query.evaluate_string(&buffer[0], size, node) == size && test_string_equal(buffer.c_str(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, bool expected)
|
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::xpath_query& query, bool expected)
|
||||||
{
|
{
|
||||||
pugi::xpath_query q(query);
|
return query.evaluate_boolean(node) == expected;
|
||||||
|
|
||||||
return q.evaluate_boolean(node) == expected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, double expected)
|
bool test_xpath_number(const pugi::xpath_node& node, const pugi::xpath_query& query, double expected)
|
||||||
{
|
{
|
||||||
pugi::xpath_query q(query);
|
double value = query.evaluate_number(node);
|
||||||
|
|
||||||
double value = q.evaluate_number(node);
|
|
||||||
double absolute_error = fabs(value - expected);
|
double absolute_error = fabs(value - expected);
|
||||||
|
|
||||||
const double tolerance = 1e-15f;
|
const double tolerance = 1e-15f;
|
||||||
return absolute_error < tolerance || absolute_error < fabs(expected) * tolerance;
|
return absolute_error < tolerance || absolute_error < fabs(expected) * tolerance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_xpath_number_nan(const pugi::xpath_node& node, const pugi::xpath_query& query)
|
||||||
|
{
|
||||||
|
return test_double_nan(query.evaluate_number(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, const pugi::char_t* expected)
|
||||||
|
{
|
||||||
|
pugi::xpath_query q(query);
|
||||||
|
|
||||||
|
return q && test_xpath_string(node, q, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, bool expected)
|
||||||
|
{
|
||||||
|
pugi::xpath_query q(query);
|
||||||
|
|
||||||
|
return q && test_xpath_boolean(node, q, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, double expected)
|
||||||
|
{
|
||||||
|
pugi::xpath_query q(query);
|
||||||
|
|
||||||
|
return q && test_xpath_number(node, q, expected);
|
||||||
|
}
|
||||||
|
|
||||||
bool test_xpath_number_nan(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_query q(query);
|
pugi::xpath_query q(query);
|
||||||
|
|
||||||
return test_double_nan(q.evaluate_number(node));
|
return q && test_xpath_number_nan(node, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_xpath_fail_compile(const pugi::char_t* query)
|
bool test_xpath_fail_compile(const pugi::char_t* query, pugi::xpath_variable_set* variables)
|
||||||
{
|
{
|
||||||
#ifdef PUGIXML_NO_EXCEPTIONS
|
#ifdef PUGIXML_NO_EXCEPTIONS
|
||||||
return !pugi::xpath_query(query);
|
return !pugi::xpath_query(query, variables);
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pugi::xpath_query q(query);
|
pugi::xpath_query q(query, variables);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (const pugi::xpath_exception&)
|
catch (const pugi::xpath_exception&)
|
||||||
|
@ -38,11 +38,17 @@ bool test_node(const pugi::xml_node& node, const pugi::char_t* contents, const p
|
|||||||
bool test_double_nan(double value);
|
bool test_double_nan(double value);
|
||||||
|
|
||||||
#ifndef PUGIXML_NO_XPATH
|
#ifndef PUGIXML_NO_XPATH
|
||||||
|
bool test_xpath_string(const pugi::xpath_node& node, const pugi::xpath_query& query, const pugi::char_t* expected);
|
||||||
|
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::xpath_query& query, bool expected);
|
||||||
|
bool test_xpath_number(const pugi::xpath_node& node, const pugi::xpath_query& query, double expected);
|
||||||
|
bool test_xpath_number_nan(const pugi::xpath_node& node, const pugi::xpath_query& query);
|
||||||
|
|
||||||
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, const pugi::char_t* expected);
|
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, const pugi::char_t* expected);
|
||||||
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, bool expected);
|
bool test_xpath_boolean(const pugi::xpath_node& node, const pugi::char_t* query, bool expected);
|
||||||
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, double expected);
|
bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query, double expected);
|
||||||
bool test_xpath_number_nan(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);
|
||||||
bool test_xpath_fail_compile(const pugi::char_t* query);
|
|
||||||
|
bool test_xpath_fail_compile(const pugi::char_t* query, pugi::xpath_variable_set* variables = 0);
|
||||||
|
|
||||||
struct xpath_node_set_tester
|
struct xpath_node_set_tester
|
||||||
{
|
{
|
||||||
@ -128,7 +134,9 @@ struct dummy_fixture {};
|
|||||||
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_TEXT(test_xpath_number(node, query, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
|
#define CHECK_XPATH_NUMBER(node, query, expected) CHECK_TEXT(test_xpath_number(node, query, expected), STRINGIZE(query) " does not evaluate to " STRINGIZE(expected) " in context " STRINGIZE(node))
|
||||||
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_TEXT(test_xpath_number_nan(node, query), STRINGIZE(query) " does not evaluate to NaN in context " STRINGIZE(node))
|
#define CHECK_XPATH_NUMBER_NAN(node, query) CHECK_TEXT(test_xpath_number_nan(node, query), STRINGIZE(query) " does not evaluate to NaN in context " STRINGIZE(node))
|
||||||
#define CHECK_XPATH_FAIL(query) CHECK_TEXT(test_xpath_fail_compile(query), STRINGIZE(query) " should not compile")
|
#define CHECK_XPATH_FAIL(query) CHECK_TEXT(test_xpath_fail_compile(query), STRINGIZE(query) " should not compile")
|
||||||
#define CHECK_XPATH_NODESET(node, query) xpath_node_set_tester(xpath_query(query).evaluate_node_set(node), CHECK_JOIN2(STRINGIZE(query) " does not evaluate to expected set in context " STRINGIZE(node), " at "__FILE__ ":", __LINE__))
|
#define CHECK_XPATH_FAIL_VAR(query, variables) CHECK_TEXT(test_xpath_fail_compile(query, variables), STRINGIZE(query) " should not compile")
|
||||||
|
#define CHECK_XPATH_NODESET_Q(node, query) xpath_node_set_tester(query.evaluate_node_set(node), CHECK_JOIN2(STRINGIZE(query) " does not evaluate to expected set in context " STRINGIZE(node), " at "__FILE__ ":", __LINE__))
|
||||||
|
#define CHECK_XPATH_NODESET(node, query) CHECK_XPATH_NODESET_Q(node, pugi::xpath_query(query))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define STR(text) PUGIXML_TEXT(text)
|
#define STR(text) PUGIXML_TEXT(text)
|
||||||
|
@ -41,8 +41,9 @@ TEST(xpath_number_error)
|
|||||||
|
|
||||||
TEST(xpath_variables)
|
TEST(xpath_variables)
|
||||||
{
|
{
|
||||||
CHECK_XPATH_FAIL(STR("$var")); // not implemented
|
CHECK_XPATH_FAIL(STR("$var")); // no variable var
|
||||||
CHECK_XPATH_FAIL(STR("$1"));
|
CHECK_XPATH_FAIL(STR("$1"));
|
||||||
|
CHECK_XPATH_FAIL(STR("$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(xpath_empty_expression)
|
TEST(xpath_empty_expression)
|
||||||
|
@ -176,7 +176,7 @@ TEST(xpath_variables_set_out_of_memory)
|
|||||||
CHECK(!var);
|
CHECK(!var);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(xpath_variable_out_of_memory)
|
TEST(xpath_variables_out_of_memory)
|
||||||
{
|
{
|
||||||
test_runner::_memory_fail_threshold = 64;
|
test_runner::_memory_fail_threshold = 64;
|
||||||
|
|
||||||
@ -188,4 +188,186 @@ TEST(xpath_variable_out_of_memory)
|
|||||||
CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")));
|
CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_evaluate, "<node/>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("var1"), true);
|
||||||
|
set.set(STR("var2"), 0.5);
|
||||||
|
set.set(STR("var3"), STR("value"));
|
||||||
|
set.set(STR("var4"), doc.select_nodes(STR("*")));
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(doc, xpath_query(STR("$var1"), &set), true);
|
||||||
|
CHECK_XPATH_NUMBER(doc, xpath_query(STR("$var2"), &set), 0.5);
|
||||||
|
CHECK_XPATH_STRING(doc, xpath_query(STR("$var3"), &set), STR("value"));
|
||||||
|
CHECK_XPATH_NODESET_Q(doc, xpath_query(STR("$var4"), &set)) % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_evaluate_conversion, "<node>3</node>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("var"), doc.select_nodes(STR("*")));
|
||||||
|
|
||||||
|
xpath_query query(STR("$var"), &set);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(doc, query, true);
|
||||||
|
CHECK_XPATH_NUMBER(doc, query, 3);
|
||||||
|
CHECK_XPATH_STRING(doc, query, STR("3"));
|
||||||
|
CHECK_XPATH_NODESET_Q(doc, query) % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_evaluate_node_set_fail)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("var"), false);
|
||||||
|
|
||||||
|
xpath_query q(STR("$var"), &set);
|
||||||
|
|
||||||
|
#ifdef PUGIXML_NO_EXCEPTIONS
|
||||||
|
CHECK_XPATH_NODESET_Q(xml_node(), q);
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
q.evaluate_node_set(xml_node());
|
||||||
|
|
||||||
|
CHECK_FORCE_FAIL("Expected exception");
|
||||||
|
}
|
||||||
|
catch (const xpath_exception&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_multiple_documents, "<node/>")
|
||||||
|
{
|
||||||
|
xml_document doc1;
|
||||||
|
CHECK(doc1.load(STR("<node/>")));
|
||||||
|
|
||||||
|
xml_document doc2;
|
||||||
|
CHECK(doc2.load(STR("<node/>")));
|
||||||
|
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("var1"), doc1.select_nodes(STR("*")));
|
||||||
|
set.set(STR("var2"), doc2.select_nodes(STR("*")));
|
||||||
|
|
||||||
|
xpath_node_set ns = doc.select_nodes(STR("$var1 | $var2 | node"), &set);
|
||||||
|
ns.sort();
|
||||||
|
|
||||||
|
CHECK(ns.size() == 3);
|
||||||
|
CHECK(ns[0] != ns[1] && ns[0] != ns[2]);
|
||||||
|
|
||||||
|
xml_node n0 = doc.child(STR("node")), n1 = doc1.child(STR("node")), n2 = doc2.child(STR("node"));
|
||||||
|
|
||||||
|
CHECK(n0 == ns[0].node() || n0 == ns[1].node() || n0 == ns[2].node());
|
||||||
|
CHECK(n1 == ns[0].node() || n1 == ns[1].node() || n1 == ns[2].node());
|
||||||
|
CHECK(n2 == ns[0].node() || n2 == ns[1].node() || n2 == ns[2].node());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_long_name)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), true);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(xml_node(), xpath_query(STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_select, "<node attr='1'/><node attr='2'/>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("one"), 1.0);
|
||||||
|
|
||||||
|
xpath_node_set ns = doc.select_nodes(STR("node[@attr=$one+1]"), &set);
|
||||||
|
CHECK(ns.size() == 1 && ns[0].node() == doc.last_child());
|
||||||
|
|
||||||
|
xpath_node n = doc.select_single_node(STR("node[@attr=$one+1]"), &set);
|
||||||
|
CHECK(n == ns[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_empty_name)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
CHECK(!set.add(STR(""), xpath_type_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_inside_filter, "<node key='1' value='2'/><node key='2' value='1'/><node key='1' value='1'/>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("one"), 1.0);
|
||||||
|
|
||||||
|
xpath_node_set ns = doc.select_nodes(STR("(node[@key = $one])[@value = $one]"), &set);
|
||||||
|
CHECK(ns.size() == 1 && ns[0].node() == doc.last_child());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_step, "<node><child/><child/><child><child/></child></node>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("root"), doc.select_nodes(STR("node")));
|
||||||
|
|
||||||
|
CHECK_XPATH_NODESET_Q(xml_node(), xpath_query(STR("$root/child"), &set)) % 3 % 4 % 5;
|
||||||
|
CHECK_XPATH_NODESET_Q(xml_node(), xpath_query(STR("$root//child"), &set)) % 3 % 4 % 5 % 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_index, "<node><child/><child/><child><child/></child></node>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("index"), 2.0);
|
||||||
|
|
||||||
|
CHECK_XPATH_NODESET_Q(doc, xpath_query(STR("node/child[$index]"), &set)) % 4;
|
||||||
|
CHECK_XPATH_NODESET_Q(doc, xpath_query(STR("node/child[position()=$index]"), &set)) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_qname)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("foo:bar"), true);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(xml_node(), xpath_query(STR("$foo:bar"), &set), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_qname_error)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("foo:"), true);
|
||||||
|
set.set(STR(":bar"), true);
|
||||||
|
set.set(STR("foo:*"), true);
|
||||||
|
|
||||||
|
CHECK_XPATH_FAIL_VAR(STR("$foo:"), &set);
|
||||||
|
CHECK_XPATH_FAIL_VAR(STR("$:bar"), &set);
|
||||||
|
CHECK_XPATH_FAIL_VAR(STR("$foo:*"), &set);
|
||||||
|
CHECK_XPATH_FAIL_VAR(STR("$foo:bar:baz"), &set);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_empty_string)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.add(STR("empty"), xpath_type_string);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(xml_node(), xpath_query(STR("$empty = substring-before('a', 'z')"), &set), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_name_underscore)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("_foo_bar"), true);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(xml_node(), xpath_query(STR("$_foo_bar"), &set), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(xpath_variables_name_case)
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("i"), 5.0);
|
||||||
|
set.set(STR("I"), 2.0);
|
||||||
|
|
||||||
|
CHECK_XPATH_NUMBER(xml_node(), xpath_query(STR("$i div $I"), &set), 2.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_XML(xpath_variables_count_sum, "<node><c1>12</c1><c2>23</c2><c3>34</c3></node>")
|
||||||
|
{
|
||||||
|
xpath_variable_set set;
|
||||||
|
set.set(STR("c12"), doc.select_nodes(STR("node/c1 | node/c2")));
|
||||||
|
set.set(STR("c3"), doc.select_nodes(STR("node/c3")));
|
||||||
|
set.set(STR("c"), doc.select_nodes(STR("node/*")));
|
||||||
|
|
||||||
|
CHECK_XPATH_NUMBER(xml_node(), xpath_query(STR("sum($c12) * count($c) - sum($c3)"), &set), 71);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user