From 02cee98492233f4ae91f025fc38f9df8b4bc0efe Mon Sep 17 00:00:00 2001
From: Arseny Kapoulkine <arseny.kapoulkine@gmail.com>
Date: Mon, 30 Jan 2017 21:36:05 -0800
Subject: [PATCH] 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(-)

diff --git a/tests/test_document.cpp b/tests/test_document.cpp
index c7219e1b..95bd873a 100644
--- a/tests/test_document.cpp
+++ b/tests/test_document.cpp
@@ -496,6 +496,15 @@ TEST_XML(document_save_declaration_latin1, "<node/>")
 	CHECK(writer.as_narrow() == "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<node />\n");
 }
 
+TEST_XML(document_save_declaration_raw, "<node/>")
+{
+	xml_writer_string writer;
+
+	doc.save(writer, STR(""), pugi::format_raw, get_native_encoding());
+
+	CHECK(writer.as_string() == STR("<?xml version=\"1.0\"?><node/>"));
+}
+
 struct temp_file
 {
 	char path[512];
diff --git a/tests/test_xpath.cpp b/tests/test_xpath.cpp
index 33c1696d..ea771210 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, "<n/>")
+{
+	test_runner::_memory_fail_threshold = 4196 * sizeof(char_t) + 4096 * 2 + 32768;
+
+	std::basic_string<char_t> 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 6b32b689..1e7f924c 100644
--- a/tests/test_xpath_api.cpp
+++ b/tests/test_xpath_api.cpp
@@ -107,6 +107,7 @@ TEST_XML(xpath_api_nodeset_accessors, "<node><foo/><foo/></node>")
 
 TEST_XML(xpath_api_nodeset_copy, "<node><foo/><foo/></node>")
 {
+	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, "<node><foo/><foo/></node>")
 
 	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, "<node><foo/><foo/><bar/></node>")
 {
diff --git a/tests/test_xpath_functions.cpp b/tests/test_xpath_functions.cpp
index 211dbfb1..480eb97f 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, "<node>foobar</node>")
 	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 1a97c7df..c2281e6f 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, "<node><c1><v>1</v><v>-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 1f511188..c39481b1 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, "<node><child/></node>")
+{
+	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
-- 
GitLab