From 8aa8e11ba6473ae35844930ac4319c647a8d9679 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 29 Jan 2017 21:53:40 -0800 Subject: tests: Add query out of memory test --- tests/test_xpath_api.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tests') diff --git a/tests/test_xpath_api.cpp b/tests/test_xpath_api.cpp index c1a4968..6b32b68 100644 --- a/tests/test_xpath_api.cpp +++ b/tests/test_xpath_api.cpp @@ -418,6 +418,13 @@ TEST(xpath_api_empty) CHECK(!q.evaluate_boolean(c)); } +TEST(xpath_api_query_out_of_memory) +{ + test_runner::_memory_fail_threshold = 1; + + CHECK_ALLOC_FAIL(xpath_query q(STR("node"))); +} + #ifdef PUGIXML_HAS_MOVE TEST_XML(xpath_api_nodeset_move_ctor, "") { -- cgit v1.2.3 From cac1d8ad9f602e74841acb05596396ee00994ebb Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 30 Jan 2017 08:57:42 -0800 Subject: tests: Add an error propagation test for XPath This test is supposed to test error coverage in different expressions that are nested in other expressions to reduce the number of never-taken branches in tests (and make sure we aren't missing any). --- tests/test_xpath_parse.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'tests') diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp index b6de42e..1f51118 100644 --- a/tests/test_xpath_parse.cpp +++ b/tests/test_xpath_parse.cpp @@ -313,4 +313,26 @@ TEST(xpath_parse_result_default) CHECK(result.offset == 0); } +TEST(xpath_parse_error_propagation) +{ + char_t query[] = STR("(//foo[count(. | @*)] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); + + xpath_variable_set vars; + vars.set(STR("x"), 1.0); + + xpath_query q(query, &vars); + CHECK(q); + + for (size_t i = 0; i + 1 < sizeof(query) / sizeof(query[0]); ++i) + { + char_t ch = query[i]; + + query[i] = '%'; + + CHECK_XPATH_FAIL(query); + + query[i] = ch; + } +} + #endif -- cgit v1.2.3 From 02cee98492233f4ae91f025fc38f9df8b4bc0efe Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 30 Jan 2017 21:36:05 -0800 Subject: tests: Add more tests for branch coverage gcov -b surfaced many lines with partial coverage, where branch is only ever taken or not taken, or one of the expressions in a complex conditional is always either true or false. This change adds a series of tests (mostly focusing on XPath) to reduce the number of partially covered lines. --- tests/test_document.cpp | 9 +++++++++ tests/test_xpath.cpp | 37 +++++++++++++++++++++++++++++++++++++ tests/test_xpath_api.cpp | 10 ++-------- tests/test_xpath_functions.cpp | 14 ++++++++++++++ tests/test_xpath_operators.cpp | 10 ++++++++++ tests/test_xpath_parse.cpp | 8 ++++++++ 6 files changed, 80 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/test_document.cpp b/tests/test_document.cpp index c7219e1..95bd873 100644 --- a/tests/test_document.cpp +++ b/tests/test_document.cpp @@ -496,6 +496,15 @@ TEST_XML(document_save_declaration_latin1, "") CHECK(writer.as_narrow() == "\n\n"); } +TEST_XML(document_save_declaration_raw, "") +{ + xml_writer_string writer; + + doc.save(writer, STR(""), pugi::format_raw, get_native_encoding()); + + CHECK(writer.as_string() == STR("")); +} + struct temp_file { char path[512]; diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index 33c1696..ea77121 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -367,6 +367,32 @@ TEST(xpath_large_node_set) CHECK(ns.size() == 10001); } +TEST(xpath_out_of_memory_query) +{ + test_runner::_memory_fail_threshold = 1; + + CHECK_ALLOC_FAIL(xpath_query q(STR("node"))); +} + +TEST_XML(xpath_out_of_memory_evaluate, "") +{ + test_runner::_memory_fail_threshold = 4196 * sizeof(char_t) + 4096 * 2 + 32768; + + std::basic_string query = STR("*[concat(\"a\", \""); + + query.resize(4196, 'a'); + query += STR("\")]"); + + pugi::xpath_query q(query.c_str()); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_boolean(doc) == false)); + CHECK_ALLOC_FAIL(CHECK_DOUBLE_NAN(q.evaluate_number(doc))); + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1)); + CHECK_ALLOC_FAIL(CHECK(q.evaluate_node(doc) == xpath_node())); + CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc).empty())); +} + TEST(xpath_out_of_memory_evaluate_concat) { test_runner::_memory_fail_threshold = 4196 * sizeof(char_t) + 4096 * 2; @@ -612,4 +638,15 @@ TEST(xpath_remove_duplicates) tester % (2 + i); } } + +TEST(xpath_anonymous_nodes) +{ + xml_document doc; + doc.append_child(node_element); + doc.append_child(node_pi); + + CHECK_XPATH_NODESET(doc, STR("/name")); + CHECK_XPATH_NODESET(doc, STR("/processing-instruction('a')")); + CHECK_XPATH_NODESET(doc, STR("/ns:*")); +} #endif diff --git a/tests/test_xpath_api.cpp b/tests/test_xpath_api.cpp index 6b32b68..1e7f924 100644 --- a/tests/test_xpath_api.cpp +++ b/tests/test_xpath_api.cpp @@ -107,6 +107,7 @@ TEST_XML(xpath_api_nodeset_accessors, "") TEST_XML(xpath_api_nodeset_copy, "") { + xpath_node_set empty; xpath_node_set set = doc.select_nodes(STR("node/foo")); xpath_node_set copy1 = set; @@ -132,7 +133,7 @@ TEST_XML(xpath_api_nodeset_copy, "") xpath_node_set copy5; copy5 = set; - copy5 = xpath_node_set(); + copy5 = empty; CHECK(copy5.size() == 0); } @@ -418,13 +419,6 @@ TEST(xpath_api_empty) CHECK(!q.evaluate_boolean(c)); } -TEST(xpath_api_query_out_of_memory) -{ - test_runner::_memory_fail_threshold = 1; - - CHECK_ALLOC_FAIL(xpath_query q(STR("node"))); -} - #ifdef PUGIXML_HAS_MOVE TEST_XML(xpath_api_nodeset_move_ctor, "") { diff --git a/tests/test_xpath_functions.cpp b/tests/test_xpath_functions.cpp index 211dbfb..480eb97 100644 --- a/tests/test_xpath_functions.cpp +++ b/tests/test_xpath_functions.cpp @@ -566,6 +566,7 @@ TEST(xpath_string_translate_table) CHECK_XPATH_STRING(c, STR("translate('abcd\xe9 ', 'abc', 'ABC')"), STR("ABCd\xe9 ")); CHECK_XPATH_STRING(c, STR("translate('abcd\xe9 ', 'abc\xe9', 'ABC!')"), STR("ABCd! ")); + CHECK_XPATH_STRING(c, STR("translate('abcd! ', 'abc!', 'ABC\xe9')"), STR("ABCd\xe9 ")); CHECK_XPATH_STRING(c, STR("translate('abcde', concat('abc', 'd'), 'ABCD')"), STR("ABCDe")); CHECK_XPATH_STRING(c, STR("translate('abcde', 'abcd', concat('ABC', 'D'))"), STR("ABCDe")); } @@ -799,4 +800,17 @@ TEST_XML(xpath_string_concat_translate, "foobar") CHECK_XPATH_STRING(doc, STR("concat('a', 'b', 'c', translate(node, 'o', 'a'), 'd')"), STR("abcfaabard")); } +TEST(xpath_unknown_functions) +{ + char_t query[] = STR("a()"); + + for (char ch = 'a'; ch <= 'z'; ++ch) + { + query[0] = ch; + CHECK_XPATH_FAIL(query); + + query[0] = ch - 32; + CHECK_XPATH_FAIL(query); + } +} #endif diff --git a/tests/test_xpath_operators.cpp b/tests/test_xpath_operators.cpp index 1a97c7d..c2281e6 100644 --- a/tests/test_xpath_operators.cpp +++ b/tests/test_xpath_operators.cpp @@ -332,11 +332,21 @@ TEST_XML(xpath_operators_inequality_node_set_node_set, "1-1< CHECK_XPATH_BOOLEAN(n, STR("c1/v < c3/v"), true); CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c3/v"), true); + CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] > c1/v[1]"), false); + CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] < c1/v[1]"), false); + CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] >= c1/v[1]"), true); + CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] <= c1/v[1]"), true); + #ifndef MSVC6_NAN_BUG CHECK_XPATH_BOOLEAN(n, STR("c1/v > c2/v"), false); CHECK_XPATH_BOOLEAN(n, STR("c1/v >= c2/v"), true); CHECK_XPATH_BOOLEAN(n, STR("c1/v < c2/v"), true); CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c2/v"), true); + + CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] < c2/v[2]"), false); + CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] > c2/v[2]"), false); + CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] <= c2/v[2]"), false); + CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] >= c2/v[2]"), false); #endif } diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp index 1f51118..c39481b 100644 --- a/tests/test_xpath_parse.cpp +++ b/tests/test_xpath_parse.cpp @@ -335,4 +335,12 @@ TEST(xpath_parse_error_propagation) } } +TEST_XML(xpath_parse_location_path, "") +{ + CHECK_XPATH_NODESET(doc, STR("/node")) % 2; + CHECK_XPATH_NODESET(doc, STR("/@*")); + CHECK_XPATH_NODESET(doc, STR("/.")) % 1; + CHECK_XPATH_NODESET(doc, STR("/..")); + CHECK_XPATH_NODESET(doc, STR("/*")) % 2; +} #endif -- cgit v1.2.3 From 60d5688a87b03aa85b74026c1fb79fd0ca8903d7 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 30 Jan 2017 22:27:48 -0800 Subject: tests: Make predicate out-of-memory test less aggressive Currently this test has very large runtime and relies on the fact that the first memory allocation error causes the test to terminate. This does not work with new behavior of running the query through and reporting the error at the end, so make the runtime reasonable but still generate enough memory to blow past the budget. --- tests/test_xpath.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index ea77121..8359f4f 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -430,11 +430,11 @@ TEST_XML(xpath_out_of_memory_evaluate_union, " CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc.child(STR("node"))).empty())); } -TEST_XML(xpath_out_of_memory_evaluate_predicate, "") +TEST_XML(xpath_out_of_memory_evaluate_predicate, "") { test_runner::_memory_fail_threshold = 32768 + 4096 * 2; - pugi::xpath_query q(STR("//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[true()]]]]]]]]]]]]]]")); + pugi::xpath_query q(STR("//a[//a[//a[//a[true()]]]]")); CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc).empty())); } -- cgit v1.2.3 From a1bc15c8d525ff2cac165cc0e5d08b272d79fc33 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 30 Jan 2017 23:24:20 -0800 Subject: tests: Add more coverage tests Expand out of memory coverage during XPath parsing and evaluation and add some other small tests. --- tests/test_xpath.cpp | 36 ++++++++++++++++++++++++++++++++++++ tests/test_xpath_api.cpp | 12 ++++++++++++ tests/test_xpath_parse.cpp | 25 ++++++++++++++++++++++++- tests/test_xpath_paths.cpp | 7 +++++++ 4 files changed, 79 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index 8359f4f..f8a4b15 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -439,6 +439,42 @@ TEST_XML(xpath_out_of_memory_evaluate_predicate, " CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc).empty())); } +TEST_XML(xpath_out_of_memory_evaluate_normalize_space_0, " a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z ") +{ + test_runner::_memory_fail_threshold = 32768 + 4096 * 2; + + pugi::xpath_query q(STR("concat(normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space())")); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc.first_child()).empty())); +} + +TEST_XML(xpath_out_of_memory_evaluate_normalize_space_1, " a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z ") +{ + test_runner::_memory_fail_threshold = 32768 + 4096 * 2; + + pugi::xpath_query q(STR("concat(normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node))")); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); +} + +TEST_XML(xpath_out_of_memory_evaluate_translate, " a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z ") +{ + test_runner::_memory_fail_threshold = 32768 + 4096 * 2; + + pugi::xpath_query q(STR("concat(translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'))")); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); +} + +TEST_XML(xpath_out_of_memory_evaluate_translate_table, " a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z ") +{ + test_runner::_memory_fail_threshold = 32768 + 4096 * 2; + + pugi::xpath_query q(STR("concat(translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'))")); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); +} + TEST(xpath_memory_concat_massive) { pugi::xml_document doc; diff --git a/tests/test_xpath_api.cpp b/tests/test_xpath_api.cpp index 1e7f924..3f05e13 100644 --- a/tests/test_xpath_api.cpp +++ b/tests/test_xpath_api.cpp @@ -573,6 +573,18 @@ TEST(xpath_api_nodeset_move_assign_empty) CHECK(move.type() == xpath_node_set::type_sorted); } +TEST_XML(xpath_api_nodeset_move_assign_self, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar")); + + CHECK(set.size() == 1); + CHECK(set.type() == xpath_node_set::type_sorted); + + test_runner::_memory_fail_threshold = 1; + + set = std::move(*&set); +} + TEST(xpath_api_query_move) { xml_node c; diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp index c39481b..9b28478 100644 --- a/tests/test_xpath_parse.cpp +++ b/tests/test_xpath_parse.cpp @@ -274,7 +274,7 @@ TEST_XML(xpath_parse_absolute, "
") TEST(xpath_parse_out_of_memory_first_page) { - test_runner::_memory_fail_threshold = 1; + test_runner::_memory_fail_threshold = 128; CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(STR("1"))); } @@ -335,6 +335,29 @@ TEST(xpath_parse_error_propagation) } } +TEST(xpath_parse_oom_propagation) +{ + const char_t* query_base = STR("(//foo[count(. | @*)] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); + + xpath_variable_set vars; + vars.set(STR("x"), 1.0); + + test_runner::_memory_fail_threshold = 4096 + 128; + + { + xpath_query q(query_base, &vars); + CHECK(q); + } + + for (size_t i = 3200; i < 4200; ++i) + { + std::basic_string literal(i, 'a'); + std::basic_string query = STR("processing-instruction('") + literal + STR("') | ") + query_base; + + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(query.c_str())); + } +} + TEST_XML(xpath_parse_location_path, "") { CHECK_XPATH_NODESET(doc, STR("/node")) % 2; diff --git a/tests/test_xpath_paths.cpp b/tests/test_xpath_paths.cpp index 69215d8..7915df1 100644 --- a/tests/test_xpath_paths.cpp +++ b/tests/test_xpath_paths.cpp @@ -358,6 +358,13 @@ TEST_XML_FLAGS(xpath_paths_nodetest_principal, "pcdata") +{ + CHECK_XPATH_NODESET(doc, STR("node/attribute::node()")) % 3; + CHECK_XPATH_NODESET(doc, STR("node/attribute::xmlns:x")); + CHECK_XPATH_NODESET(doc, STR("node/attribute::xmlns:*")); +} + TEST_XML(xpath_paths_absolute, "") { xml_node c; -- cgit v1.2.3 From 6ffd2ffc418eab0699124d2739f487782460a263 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 31 Jan 2017 00:10:20 -0800 Subject: tests: Add more DOM coverage tests Add tests for various corner cases of DOM inspection and modification routines. --- tests/test_dom_modify.cpp | 28 ++++++++++++++++++++-------- tests/test_dom_traverse.cpp | 17 +++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index f2d7ea8..7b26c5f 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -389,7 +389,7 @@ TEST_XML(dom_node_append_copy_attribute, " CHECK_NODE(doc, STR("")); } -TEST_XML(dom_node_insert_copy_after_attribute, "") +TEST_XML(dom_node_insert_copy_after_attribute, "text") { CHECK(xml_node().insert_copy_after(xml_attribute(), xml_attribute()) == xml_attribute()); @@ -402,6 +402,7 @@ TEST_XML(dom_node_insert_copy_after_attribute, "")); + CHECK_NODE(doc, STR("text")); a3.set_name(STR("a3")); a3 = STR("v3"); @@ -425,10 +426,10 @@ TEST_XML(dom_node_insert_copy_after_attribute, "")); + CHECK_NODE(doc, STR("text")); } -TEST_XML(dom_node_insert_copy_before_attribute, "") +TEST_XML(dom_node_insert_copy_before_attribute, "text") { CHECK(xml_node().insert_copy_before(xml_attribute(), xml_attribute()) == xml_attribute()); @@ -441,6 +442,7 @@ TEST_XML(dom_node_insert_copy_before_attribute, "< CHECK(node.insert_copy_before(a1, xml_attribute()) == xml_attribute()); CHECK(node.insert_copy_before(xml_attribute(), a1) == xml_attribute()); CHECK(node.insert_copy_before(a2, a2) == xml_attribute()); + CHECK(node.last_child().insert_copy_before(a2, a2) == xml_attribute()); xml_attribute a3 = node.insert_copy_before(a1, a1); CHECK(a3 && a3 != a2 && a3 != a1); @@ -453,7 +455,7 @@ TEST_XML(dom_node_insert_copy_before_attribute, "< CHECK(child.insert_copy_before(a4, a4) == xml_attribute()); - CHECK_NODE(doc, STR("")); + CHECK_NODE(doc, STR("text")); a3.set_name(STR("a3")); a3 = STR("v3"); @@ -464,7 +466,7 @@ TEST_XML(dom_node_insert_copy_before_attribute, "< a5.set_name(STR("a5")); a5 = STR("v5"); - CHECK_NODE(doc, STR("")); + CHECK_NODE(doc, STR("text")); } TEST_XML(dom_node_remove_attribute, "") @@ -550,6 +552,7 @@ TEST_XML(dom_node_insert_child_after, "foo") xml_node node = doc.child(STR("node")); xml_node child = node.child(STR("child")); + CHECK(node.insert_child_after(node_element, xml_node()) == xml_node()); CHECK(node.insert_child_after(node_element, node) == xml_node()); CHECK(child.insert_child_after(node_element, node) == xml_node()); @@ -584,6 +587,7 @@ TEST_XML(dom_node_insert_child_before, "foo") xml_node node = doc.child(STR("node")); xml_node child = node.child(STR("child")); + CHECK(node.insert_child_before(node_element, xml_node()) == xml_node()); CHECK(node.insert_child_before(node_element, node) == xml_node()); CHECK(child.insert_child_before(node_element, node) == xml_node()); @@ -770,13 +774,16 @@ TEST_XML(dom_node_append_copy, "foo") TEST_XML(dom_node_insert_copy_after, "foo") { + xml_node child = doc.child(STR("node")).child(STR("child")); + CHECK(xml_node().insert_copy_after(xml_node(), xml_node()) == xml_node()); CHECK(doc.child(STR("node")).first_child().insert_copy_after(doc.child(STR("node")), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_after(doc, doc) == xml_node()); CHECK(doc.insert_copy_after(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_after(doc.child(STR("node")), xml_node()) == xml_node()); + CHECK(doc.insert_copy_after(doc.child(STR("node")), child) == xml_node()); - xml_node n1 = doc.child(STR("node")).insert_copy_after(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child()); + xml_node n1 = doc.child(STR("node")).insert_copy_after(child, doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.name(), STR("child")); CHECK_NODE(doc, STR("foo")); @@ -794,13 +801,16 @@ TEST_XML(dom_node_insert_copy_after, "foo") TEST_XML(dom_node_insert_copy_before, "foo") { + xml_node child = doc.child(STR("node")).child(STR("child")); + CHECK(xml_node().insert_copy_before(xml_node(), xml_node()) == xml_node()); CHECK(doc.child(STR("node")).first_child().insert_copy_before(doc.child(STR("node")), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_before(doc, doc) == xml_node()); CHECK(doc.insert_copy_before(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_before(doc.child(STR("node")), xml_node()) == xml_node()); + CHECK(doc.insert_copy_before(doc.child(STR("node")), child) == xml_node()); - xml_node n1 = doc.child(STR("node")).insert_copy_before(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child()); + xml_node n1 = doc.child(STR("node")).insert_copy_before(child, doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.name(), STR("child")); CHECK_NODE(doc, STR("foo")); @@ -1314,6 +1324,7 @@ TEST_XML(dom_node_insert_move_after, "foobar") CHECK(doc.insert_move_after(doc, doc) == xml_node()); CHECK(doc.insert_move_after(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_move_after(doc.child(STR("node")), xml_node()) == xml_node()); + CHECK(doc.insert_move_after(doc.child(STR("node")), child) == xml_node()); xml_node n1 = doc.child(STR("node")).insert_move_after(child, doc.child(STR("node")).first_child()); CHECK(n1 && n1 == child); @@ -1340,6 +1351,7 @@ TEST_XML(dom_node_insert_move_before, "foobar") CHECK(doc.insert_move_before(doc, doc) == xml_node()); CHECK(doc.insert_move_before(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_move_before(doc.child(STR("node")), xml_node()) == xml_node()); + CHECK(doc.insert_move_before(doc.child(STR("node")), child) == xml_node()); xml_node n1 = doc.child(STR("node")).insert_move_before(child, doc.child(STR("node")).first_child()); CHECK(n1 && n1 == child); diff --git a/tests/test_dom_traverse.cpp b/tests/test_dom_traverse.cpp index f977e15..773f0f0 100644 --- a/tests/test_dom_traverse.cpp +++ b/tests/test_dom_traverse.cpp @@ -736,6 +736,9 @@ TEST_XML(dom_node_path, "text") CHECK(doc.child(STR("node")).child(STR("child1")).first_child().path() == STR("/node/child1/")); CHECK(doc.child(STR("node")).child(STR("child1")).path('\\') == STR("\\node\\child1")); + + doc.append_child(node_element); + CHECK(doc.last_child().path() == STR("/")); } #endif @@ -1274,3 +1277,17 @@ TEST_XML(dom_as_int_plus, "") CHECK(node.attribute(STR("attr2")).as_ullong() == 10); #endif } + +TEST(dom_node_anonymous) +{ + xml_document doc; + doc.append_child(node_element); + doc.append_child(node_element); + doc.append_child(node_pcdata); + + CHECK(doc.child(STR("node")) == xml_node()); + CHECK(doc.first_child().next_sibling(STR("node")) == xml_node()); + CHECK(doc.last_child().previous_sibling(STR("node")) == xml_node()); + CHECK_STRING(doc.child_value(), STR("")); + CHECK_STRING(doc.last_child().child_value(), STR("")); +} -- cgit v1.2.3 From ef64bef5c3e80144f4e0d1ca0cc07c68e3ad5a6b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 31 Jan 2017 00:35:15 -0800 Subject: tests: More XPath coverage tests --- tests/test_xpath_parse.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp index 9b28478..8819a5d 100644 --- a/tests/test_xpath_parse.cpp +++ b/tests/test_xpath_parse.cpp @@ -293,6 +293,27 @@ TEST(xpath_parse_out_of_memory_string_to_number) CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(STR("0.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"))); } +TEST(xpath_parse_out_of_memory_quoted_string) +{ + test_runner::_memory_fail_threshold = 4096 + 128; + + std::basic_string literal(5000, 'a'); + std::basic_string query = STR("'") + literal + STR("'"); + + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(query.c_str())); +} + +TEST(xpath_parse_out_of_memory_variable) +{ + test_runner::_memory_fail_threshold = 4096 + 128; + + std::basic_string literal(5000, 'a'); + std::basic_string query = STR("$") + literal; + + xpath_variable_set vars; + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL_VAR(query.c_str(), &vars)); +} + TEST(xpath_parse_qname_error) { CHECK_XPATH_FAIL(STR("foo: bar")); @@ -315,7 +336,7 @@ TEST(xpath_parse_result_default) TEST(xpath_parse_error_propagation) { - char_t query[] = STR("(//foo[count(. | @*)] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); + char_t query[] = STR("(//foo[count(. | @*)] | ((a)//b)[1] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); xpath_variable_set vars; vars.set(STR("x"), 1.0); @@ -337,7 +358,7 @@ TEST(xpath_parse_error_propagation) TEST(xpath_parse_oom_propagation) { - const char_t* query_base = STR("(//foo[count(. | @*)] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); + const char_t* query_base = STR("(//foo[count(. | @*)] | ((a)//b)[1] | /foo | /foo/bar//more/ancestor-or-self::foobar | /text() | a[1 + 2 * 3 div (1+0) mod 2]//b[1]/c | a[$x])[true()]"); xpath_variable_set vars; vars.set(STR("x"), 1.0); -- cgit v1.2.3 From 41fb880bf0c3246df50103c6ef3cf91d0fd5eefc Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 31 Jan 2017 07:50:39 -0800 Subject: tests: Add coverage tests for encoding detection Enumerate successfull cases and also cases where the detection stops half-way and results in a different detected encoding. --- tests/test_parse.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'tests') diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index ba45a45..f94a565 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -1206,3 +1206,83 @@ TEST(parse_encoding_detect_latin1) CHECK(doc.load_buffer(test3, sizeof(test3)).encoding == encoding_latin1); CHECK(doc.load_buffer(test4, sizeof(test4)).encoding == encoding_latin1); } + +TEST(parse_encoding_detect_auto) +{ + struct data_t + { + const char* contents; + size_t size; + xml_encoding encoding; + }; + + 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 ", 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 }, + // ", 25, encoding_latin1 }, + }; + + for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i) + { + xml_document doc; + xml_parse_result result = doc.load_buffer(data[i].contents, data[i].size, parse_fragment); + + CHECK(result); + CHECK(result.encoding == data[i].encoding); + } +} + +TEST(parse_encoding_detect_auto_incomplete) +{ + struct data_t + { + const char* contents; + size_t size; + xml_encoding encoding; + }; + + 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", 8, encoding_utf16_le }, + { "\x00", 8, encoding_utf16_be }, + { "<\x00?n/\x00>\x00", 8, encoding_utf16_le }, + { "\x00 ", 8, encoding_utf8 }, + // ", 25, encoding_utf8 }, + { "", 25, encoding_utf8 }, + { "", 25, encoding_utf8 }, + { "<_ABC encoding='latin1'/>", 25, encoding_utf8 }, + }; + + for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i) + { + xml_document doc; + xml_parse_result result = doc.load_buffer(data[i].contents, data[i].size, parse_fragment); + + CHECK(result); + CHECK(result.encoding == data[i].encoding); + } +} -- cgit v1.2.3 From 094a0c8ebe44a1bfeb8575b33138a8b258bf8f4b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 31 Jan 2017 19:19:04 -0800 Subject: tests: Add compact hash table reserve test This makes sure all .reserve calls failure paths are covered. These tests don't explicitly test if reserve is present on all paths - this is much harder to test since not all modifications require reserve to be called, so we'll have to rely on a combination of automated testing and sanity checking for this. Also add more parsing out of memory coverage tests. --- tests/test_compact.cpp | 110 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/test_parse.cpp | 13 +++++- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 tests/test_compact.cpp (limited to 'tests') diff --git a/tests/test_compact.cpp b/tests/test_compact.cpp new file mode 100644 index 0000000..7c90d07 --- /dev/null +++ b/tests/test_compact.cpp @@ -0,0 +1,110 @@ +#ifdef PUGIXML_COMPACT +#include "common.hpp" + +static void overflow_hash_table(xml_document& doc) +{ + xml_node n = doc.child(STR("n")); + + // compact encoding assumes next_sibling is a forward-only pointer so we can allocate hash entries by reordering nodes + // we allocate enough hash entries to be exactly on the edge of rehash threshold + for (int i = 0; i < 8; ++i) + CHECK(n.prepend_child(node_element)); +} + +TEST_XML(compact_out_of_memory_string, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + + CHECK_ALLOC_FAIL(CHECK(!n.set_name(STR("name")))); +} + +TEST_XML(compact_out_of_memory_attribute, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + xml_attribute a = n.attribute(STR("a")); + + CHECK_ALLOC_FAIL(CHECK(!n.append_attribute(STR("")))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_attribute(STR("")))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_attribute_after(STR(""), a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_attribute_before(STR(""), a))); +} + +TEST_XML(compact_out_of_memory_attribute_copy, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + xml_attribute a = n.attribute(STR("a")); + + CHECK_ALLOC_FAIL(CHECK(!n.append_copy(a))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_copy(a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_after(a, a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_before(a, a))); +} + +TEST_XML(compact_out_of_memory_node, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + + CHECK_ALLOC_FAIL(CHECK(!doc.append_child(node_element))); + CHECK_ALLOC_FAIL(CHECK(!doc.prepend_child(node_element))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_child_after(node_element, n))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_child_before(node_element, n))); +} + +TEST_XML(compact_out_of_memory_node_copy, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + + CHECK_ALLOC_FAIL(CHECK(!doc.append_copy(n))); + CHECK_ALLOC_FAIL(CHECK(!doc.prepend_copy(n))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_copy_after(n, n))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_copy_before(n, n))); +} + +TEST_XML(compact_out_of_memory_node_move, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + xml_node ne = doc.child(STR("ne")); + + CHECK_ALLOC_FAIL(CHECK(!doc.append_move(n))); + CHECK_ALLOC_FAIL(CHECK(!doc.prepend_move(n))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_move_after(n, ne))); + CHECK_ALLOC_FAIL(CHECK(!doc.insert_move_before(n, ne))); +} + +TEST_XML(compact_out_of_memory_remove, "") +{ + test_runner::_memory_fail_threshold = 1; + + overflow_hash_table(doc); + + xml_node n = doc.child(STR("n")); + xml_attribute a = n.attribute(STR("a")); + + CHECK_ALLOC_FAIL(CHECK(!n.remove_attribute(a))); + CHECK_ALLOC_FAIL(CHECK(!doc.remove_child(n))); +} +#endif diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index f94a565..fa9555d 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -928,13 +928,24 @@ TEST(parse_out_of_memory_halfway_attr) TEST(parse_out_of_memory_conversion) { - test_runner::_memory_fail_threshold = 256; + test_runner::_memory_fail_threshold = 1; xml_document doc; CHECK_ALLOC_FAIL(CHECK(doc.load_buffer("", 7, parse_default, encoding_latin1).status == status_out_of_memory)); CHECK(!doc.first_child()); } +#ifdef PUGIXML_WCHAR_MODE +TEST(parse_out_of_memory_conversion_wchar) +{ + test_runner::_memory_fail_threshold = 1; + + xml_document doc; + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer("", 7).status == status_out_of_memory)); + CHECK(!doc.first_child()); +} +#endif + TEST(parse_out_of_memory_allocator_state_sync) { const unsigned int count = 10000; -- cgit v1.2.3 From 1a3e92a7cc80a719efd988f14860a1aa9692d584 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 31 Jan 2017 20:36:59 -0800 Subject: tests: Add more tests to increase coverage This change adds more thorough tests for attribute conversion as well as some assorted tests that fix gaps in coverage. --- tests/test_compact.cpp | 10 +++++++--- tests/test_dom_traverse.cpp | 4 ++++ tests/test_parse.cpp | 30 ++++++++++++++++++++++++++++++ tests/test_write.cpp | 6 ++++++ 4 files changed, 47 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/test_compact.cpp b/tests/test_compact.cpp index 7c90d07..f9560c9 100644 --- a/tests/test_compact.cpp +++ b/tests/test_compact.cpp @@ -11,15 +11,19 @@ static void overflow_hash_table(xml_document& doc) CHECK(n.prepend_child(node_element)); } -TEST_XML(compact_out_of_memory_string, "") +TEST_XML_FLAGS(compact_out_of_memory_string, "", parse_pi) { test_runner::_memory_fail_threshold = 1; overflow_hash_table(doc); - xml_node n = doc.child(STR("n")); + xml_attribute a = doc.child(STR("n")).attribute(STR("a")); + xml_node pi = doc.last_child(); - CHECK_ALLOC_FAIL(CHECK(!n.set_name(STR("name")))); + CHECK_ALLOC_FAIL(CHECK(!pi.set_name(STR("name")))); + CHECK_ALLOC_FAIL(CHECK(!pi.set_value(STR("value")))); + CHECK_ALLOC_FAIL(CHECK(!a.set_name(STR("name")))); + CHECK_ALLOC_FAIL(CHECK(!a.set_value(STR("value")))); } TEST_XML(compact_out_of_memory_attribute, "") diff --git a/tests/test_dom_traverse.cpp b/tests/test_dom_traverse.cpp index 773f0f0..3d30a82 100644 --- a/tests/test_dom_traverse.cpp +++ b/tests/test_dom_traverse.cpp @@ -137,6 +137,10 @@ TEST_XML(dom_attr_as_integer_space, "") diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index fa9555d..882ba3a 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -746,6 +746,36 @@ TEST(parse_attribute_quot_inside) } } +TEST(parse_attribute_wnorm_coverage) +{ + xml_document doc; + CHECK(doc.load_string(STR(""), parse_wnorm_attribute)); + CHECK_NODE(doc, STR("")); + + CHECK(doc.load_string(STR(""), parse_wnorm_attribute | parse_escapes)); + CHECK_NODE(doc, STR("")); +} + +TEST(parse_attribute_wconv_coverage) +{ + xml_document doc; + CHECK(doc.load_string(STR(""), parse_wconv_attribute)); + CHECK_NODE(doc, STR("")); + + CHECK(doc.load_string(STR(""), parse_wconv_attribute | parse_escapes)); + CHECK_NODE(doc, STR("")); +} + +TEST(parse_attribute_eol_coverage) +{ + xml_document doc; + CHECK(doc.load_string(STR(""), parse_eol)); + CHECK_NODE(doc, STR("")); + + CHECK(doc.load_string(STR(""), parse_eol | parse_escapes)); + CHECK_NODE(doc, STR("")); +} + TEST(parse_tag_single) { xml_document doc; diff --git a/tests/test_write.cpp b/tests/test_write.cpp index d5f3dad..5cd92a5 100644 --- a/tests/test_write.cpp +++ b/tests/test_write.cpp @@ -69,6 +69,12 @@ TEST_XML_FLAGS(write_cdata_escape, "", parse_cdata | parse_frag doc.first_child().set_value(STR("1]]>2]]>3")); CHECK_NODE(doc, STR("2]]]]>3]]>")); + + doc.first_child().set_value(STR("1]")); + CHECK_NODE(doc, STR("")); + + doc.first_child().set_value(STR("1]]")); + CHECK_NODE(doc, STR("")); } TEST_XML(write_cdata_inner, "") -- cgit v1.2.3 From e56686f1e57236d4b1c5fb3f7de99ddfbf2a016b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 1 Feb 2017 20:21:14 -0800 Subject: tests: Remove redundant coverage test The only point was to try to test all paths where we can run out of memory while decoding something. It seems like it may be impossible to actually do this given that we can't run all paths as wchar_t size detection is done at runtime... --- tests/test_parse.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'tests') diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index 882ba3a..efc3ca6 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -965,17 +965,6 @@ TEST(parse_out_of_memory_conversion) CHECK(!doc.first_child()); } -#ifdef PUGIXML_WCHAR_MODE -TEST(parse_out_of_memory_conversion_wchar) -{ - test_runner::_memory_fail_threshold = 1; - - xml_document doc; - CHECK_ALLOC_FAIL(CHECK(doc.load_buffer("", 7).status == status_out_of_memory)); - CHECK(!doc.first_child()); -} -#endif - TEST(parse_out_of_memory_allocator_state_sync) { const unsigned int count = 10000; -- cgit v1.2.3 From f9f1c867166d9d07ebe2b370b7951d68c1f5c3ff Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 1 Feb 2017 21:07:46 -0800 Subject: tests: Improve parsing coverage Add tests for PI erroring exactly at the buffer boundary with non-zero-terminated buffers (so we have to clear the last character which changes the parsing flow slightly) and a test that makes sure parse_embed_pcdata works properly with XML fragments where PCDATA can be at the root level but can't be embedded into the document node. --- tests/test_parse.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tests') diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index efc3ca6..94e6f24 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -88,6 +88,16 @@ TEST(parse_pi_error) CHECK(doc.load_string(STR(""), parse_fragment | parse_pi).status == status_bad_pi); } +TEST(parse_pi_error_buffer_boundary) +{ + char buf1[] = ""; + char buf2[] = ""; -- cgit v1.2.3 From c28ff128d862ace16b7377dd943a8ca8f7bcfcb0 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 2 Feb 2017 08:40:34 -0800 Subject: tests: Add more embed_pcdata tests --- tests/test_parse.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'tests') diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index 94e6f24..013bca9 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -1230,6 +1230,26 @@ TEST_XML_FLAGS(parse_embed_pcdata_fragment, "text", parse_fragment | parse_embed CHECK_STRING(doc.first_child().value(), STR("text")); } +TEST_XML_FLAGS(parse_embed_pcdata_child, "text", parse_embed_pcdata) +{ + xml_node n = doc.child(STR("n")); + + CHECK_NODE(doc, STR("text")); + CHECK(n.last_child().type() == node_pcdata); + CHECK_STRING(n.last_child().value(), STR("text")); +} + +TEST_XML_FLAGS(parse_embed_pcdata_comment, "text1text2", parse_embed_pcdata) +{ + xml_node n = doc.child(STR("n")); + + CHECK_NODE(doc, STR("text1text2")); + CHECK_STRING(n.value(), STR("text1")); + CHECK(n.first_child() == n.last_child()); + CHECK(n.last_child().type() == node_pcdata); + CHECK_STRING(n.last_child().value(), STR("text2")); +} + TEST(parse_encoding_detect) { char test[] = ""; -- cgit v1.2.3 From faadd460c4f578645bb7dc759d4e66e0db11a13c Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 2 Feb 2017 08:57:02 -0800 Subject: tests: Add more out of memory tests for XPath evaluation --- tests/test_xpath.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'tests') diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index f8a4b15..9cf8bd5 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -475,6 +475,38 @@ TEST_XML(xpath_out_of_memory_evaluate_translate_table, " a b c d e f g h i CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); } +TEST(xpath_out_of_memory_evaluate_string_append) +{ + test_runner::_memory_fail_threshold = 32768 + 4096 * 2; + + std::basic_string literal(5000, 'a'); + + std::basic_string buf; + buf += STR("text"); + buf += literal; + buf += STR(""); + + xml_document doc; + CHECK(doc.load_buffer_inplace(&buf[0], buf.size() * sizeof(char_t))); + + pugi::xpath_query q(STR("string(n)")); + CHECK(q); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty())); +} + +TEST(xpath_out_of_memory_evaluate_number_to_string) +{ + test_runner::_memory_fail_threshold = 4096 + 128; + + xpath_variable_set vars; + vars.set(STR("x"), 1e+308); + + xpath_query q(STR("concat($x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x)"), &vars); + + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(xml_node()).empty())); +} + TEST(xpath_memory_concat_massive) { pugi::xml_document doc; -- cgit v1.2.3 From 10676b6b8548ddbf9458993062e6a27c2c233d48 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 4 Feb 2017 18:43:43 -0800 Subject: tests: Add more XPath sorting tests Cover empty node case - no XPath query can result in that but it's possible to create a node set with empty nodes manually. --- tests/test_xpath.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp index 9cf8bd5..6cae607 100644 --- a/tests/test_xpath.cpp +++ b/tests/test_xpath.cpp @@ -672,6 +672,17 @@ TEST(xpath_sort_crossdoc_different_depth) CHECK((ns[0] == ns1[0] && ns[1] == ns2[0]) || (ns[0] == ns2[0] && ns[1] == ns1[0])); } +TEST_XML(xpath_sort_empty_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_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0])); + + ns.sort(); + + CHECK(!ns[0] && !ns[1] && ns[2] == nodes[2] && ns[3] == nodes[0]); +} + TEST(xpath_allocate_string_out_of_memory) { std::basic_string query; -- cgit v1.2.3