From 29fef9aca2f5832eb721f9d097d2a6f6ebdb0179 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 11 Apr 2015 00:16:39 -0700 Subject: tests: Add more out of memory tests This provides more coverage for #17. --- tests/test_dom_modify.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'tests/test_dom_modify.cpp') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index fa50112..8610a74 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -1100,6 +1100,42 @@ TEST(dom_node_append_buffer_out_of_memory_buffer) CHECK(!doc.first_child()); } +TEST(dom_node_append_buffer_out_of_memory_nodes) +{ + unsigned int count = 4000; + std::basic_string data; + + for (unsigned int i = 0; i < count; ++i) + data += STR(""); + + test_runner::_memory_fail_threshold = 32768 + 128 + data.length() * sizeof(wchar_t) + 32; + + xml_document doc; + CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(wchar_t), parse_fragment).status == status_out_of_memory); + + unsigned int valid = 0; + + for (xml_node n = doc.first_child(); n; n = n.next_sibling()) + { + CHECK_STRING(n.name(), STR("a")); + valid++; + } + + CHECK(valid > 0 && valid < count); +} + +TEST(dom_node_append_buffer_out_of_memory_name) +{ + test_runner::_memory_fail_threshold = 32768 + 128; + + char data[128] = {0}; + + xml_document doc; + CHECK(doc.append_child(STR("root"))); + CHECK(doc.first_child().append_buffer(data, sizeof(data)).status == status_out_of_memory); + CHECK_STRING(doc.first_child().name(), STR("root")); +} + TEST_XML(dom_node_append_buffer_fragment, "") { xml_node node = doc.child(STR("node")); -- cgit v1.2.3 From 03ea04c32a6c1961d28d3b5dc66dad906dfc8ca6 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 11 Apr 2015 00:33:35 -0700 Subject: tests: Use char_t instead of wchar_t --- tests/test_dom_modify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/test_dom_modify.cpp') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index 8610a74..af833a6 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -1108,10 +1108,10 @@ TEST(dom_node_append_buffer_out_of_memory_nodes) for (unsigned int i = 0; i < count; ++i) data += STR(""); - test_runner::_memory_fail_threshold = 32768 + 128 + data.length() * sizeof(wchar_t) + 32; + test_runner::_memory_fail_threshold = 32768 + 128 + data.length() * sizeof(char_t) + 32; xml_document doc; - CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(wchar_t), parse_fragment).status == status_out_of_memory); + CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(char_t), parse_fragment).status == status_out_of_memory); unsigned int valid = 0; -- cgit v1.2.3 From 4e004176bacb0160007102742ec62e79a9d958bb Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 11 Apr 2015 22:46:08 -0700 Subject: tests: Improve out-of-memory tests Previously there was no guarantee that the tests that check for out of memory handling behavior are actually correct - e.g. that they correctly simulate out of memory conditions. Now every simulated out of memory condition has to be "guarded" using CHECK_ALLOC_FAIL. It makes sure that every piece of code that is supposed to cause out-of-memory does so, and that no other code runs out of memory unnoticed. --- tests/test_dom_modify.cpp | 67 ++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'tests/test_dom_modify.cpp') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index af833a6..ae18171 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -858,10 +858,10 @@ TEST(dom_string_out_of_memory) // no value => long value test_runner::_memory_fail_threshold = 32; - CHECK(!node.set_name(string)); - CHECK(!text.set_value(string)); - CHECK(!attr.set_name(string)); - CHECK(!attr.set_value(string)); + CHECK_ALLOC_FAIL(CHECK(!node.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!text.set_value(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_value(string))); // set some names/values test_runner::_memory_fail_threshold = 0; @@ -873,10 +873,10 @@ TEST(dom_string_out_of_memory) // some value => long value test_runner::_memory_fail_threshold = 32; - CHECK(!node.set_name(string)); - CHECK(!text.set_value(string)); - CHECK(!attr.set_name(string)); - CHECK(!attr.set_value(string)); + CHECK_ALLOC_FAIL(CHECK(!node.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!text.set_value(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_value(string))); // check that original state was preserved test_runner::_memory_fail_threshold = 0; @@ -897,30 +897,27 @@ TEST(dom_node_out_of_memory) xml_attribute a = n.append_attribute(STR("a")); CHECK(a); - while (n.append_child(node_comment) || n.append_attribute(STR("b"))) - { - // nop - } + CHECK_ALLOC_FAIL(while (n.append_child(node_comment) || n.append_attribute(STR("b"))) { /* nop */ }); // verify all node modification operations - CHECK(!n.append_child()); - CHECK(!n.prepend_child()); - CHECK(!n.insert_child_after(node_element, n.first_child())); - CHECK(!n.insert_child_before(node_element, n.first_child())); - CHECK(!n.append_attribute(STR(""))); - CHECK(!n.prepend_attribute(STR(""))); - CHECK(!n.insert_attribute_after(STR(""), a)); - CHECK(!n.insert_attribute_before(STR(""), a)); + CHECK_ALLOC_FAIL(CHECK(!n.append_child())); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_child())); + CHECK_ALLOC_FAIL(CHECK(!n.insert_child_after(node_element, n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_child_before(node_element, n.first_child()))); + 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))); // verify node copy operations - CHECK(!n.append_copy(n.first_child())); - CHECK(!n.prepend_copy(n.first_child())); - CHECK(!n.insert_copy_after(n.first_child(), n.first_child())); - CHECK(!n.insert_copy_before(n.first_child(), n.first_child())); - CHECK(!n.append_copy(a)); - CHECK(!n.prepend_copy(a)); - CHECK(!n.insert_copy_after(a, a)); - CHECK(!n.insert_copy_before(a, a)); + CHECK_ALLOC_FAIL(CHECK(!n.append_copy(n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_copy(n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_after(n.first_child(), n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_before(n.first_child(), n.first_child()))); + 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(dom_node_memory_limit) @@ -1085,7 +1082,7 @@ TEST(dom_node_append_buffer_out_of_memory_extra) test_runner::_memory_fail_threshold = 1; xml_document doc; - CHECK(doc.append_buffer("", 4).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer("", 4).status == status_out_of_memory)); CHECK(!doc.first_child()); } @@ -1096,7 +1093,7 @@ TEST(dom_node_append_buffer_out_of_memory_buffer) char data[128] = {0}; xml_document doc; - CHECK(doc.append_buffer(data, sizeof(data)).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer(data, sizeof(data)).status == status_out_of_memory)); CHECK(!doc.first_child()); } @@ -1111,7 +1108,7 @@ TEST(dom_node_append_buffer_out_of_memory_nodes) test_runner::_memory_fail_threshold = 32768 + 128 + data.length() * sizeof(char_t) + 32; xml_document doc; - CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(char_t), parse_fragment).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(char_t), parse_fragment).status == status_out_of_memory)); unsigned int valid = 0; @@ -1132,7 +1129,7 @@ TEST(dom_node_append_buffer_out_of_memory_name) xml_document doc; CHECK(doc.append_child(STR("root"))); - CHECK(doc.first_child().append_buffer(data, sizeof(data)).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.first_child().append_buffer(data, sizeof(data)).status == status_out_of_memory)); CHECK_STRING(doc.first_child().name(), STR("root")); } @@ -1441,8 +1438,7 @@ TEST_XML(dom_node_copy_out_of_memory_node, "te test_runner::_memory_fail_threshold = 32768 * 2 + 4096; xml_document copy; - for (int i = 0; i < 1000; ++i) - copy.append_copy(doc.first_child()); + CHECK_ALLOC_FAIL(for (int i = 0; i < 1000; ++i) copy.append_copy(doc.first_child())); } TEST_XML(dom_node_copy_out_of_memory_attr, "") @@ -1450,8 +1446,7 @@ TEST_XML(dom_node_copy_out_of_memory_attr, "text") -- cgit v1.2.3 From 2537cccad34b64086ad2ff47db07c3674b9be07a Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 12 Apr 2015 02:17:20 -0700 Subject: tests: Fix some Coverity issues --- tests/test_dom_modify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/test_dom_modify.cpp') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index ae18171..fc6dd59 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -644,7 +644,7 @@ TEST_XML(dom_node_remove_child, "") { - doc.child(STR("node")).remove_child(STR("n1")); + CHECK(doc.child(STR("node")).remove_child(STR("n1"))); CHECK_NODE(doc, STR("")); @@ -1040,7 +1040,7 @@ TEST_XML(dom_node_append_buffer_remove, "test") CHECK_NODE(doc, STR("test")); - doc.remove_child(STR("node")); + CHECK(doc.remove_child(STR("node"))); CHECK(!doc.first_child()); } -- cgit v1.2.3 From a0d065cd22d1d43c417f6d3db88a04bf57b67ed0 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 12 Apr 2015 03:03:56 -0700 Subject: Implment copyless copy for attributes Previously attributes that were copied with their node used string sharing, but standalone attributes that were copied using xml_node::*_copy(xml_attribute) were not. --- tests/test_dom_modify.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'tests/test_dom_modify.cpp') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index fc6dd59..41120e5 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -771,6 +771,14 @@ TEST_XML(dom_node_copy_crossdoc, "") CHECK_NODE(newdoc, STR("")); } +TEST_XML(dom_node_copy_crossdoc_attribute, "") +{ + xml_document newdoc; + newdoc.append_child(STR("copy")).append_copy(doc.child(STR("node")).attribute(STR("attr"))); + CHECK_NODE(doc, STR("")); + CHECK_NODE(newdoc, STR("")); +} + TEST_XML_FLAGS(dom_node_copy_types, "pcdata", parse_full) { doc.append_copy(doc.child(STR("root"))); @@ -1409,7 +1417,7 @@ TEST(dom_node_copy_copyless_mix) CHECK_NODE(copy2, dataxml.c_str()); } -TEST_XML(dom_node_copyless_taint, "") +TEST_XML(dom_node_copy_copyless_taint, "") { xml_node node = doc.child(STR("node")); xml_node copy = doc.append_copy(node); @@ -1433,6 +1441,59 @@ TEST_XML(dom_node_copyless_taint, "") CHECK_NODE(doc, STR("")); } +TEST(dom_node_copy_attribute_copyless) +{ + std::basic_string data; + data += STR(""); + + std::basic_string datacopy = data; + + // the document is parsed in-place so there should only be 1 page worth of allocations + test_runner::_memory_fail_threshold = 32768 + 128; + + xml_document doc; + CHECK(doc.load_buffer_inplace(&datacopy[0], datacopy.size() * sizeof(char_t), parse_full)); + + // this copy should share all string storage; since there are not a lot of nodes we should not have *any* allocations here (everything will fit in the same page in the document) + xml_node copy1 = doc.append_child(STR("node")); + copy1.append_copy(doc.first_child().first_attribute()); + + xml_node copy2 = doc.append_child(STR("node")); + copy2.append_copy(copy1.first_attribute()); + + CHECK_NODE(copy1, data.c_str()); + CHECK_NODE(copy2, data.c_str()); +} + +TEST_XML(dom_node_copy_attribute_copyless_taint, "") +{ + xml_node node = doc.child(STR("node")); + xml_attribute attr = node.first_attribute(); + + xml_node copy1 = doc.append_child(STR("copy1")); + xml_node copy2 = doc.append_child(STR("copy2")); + xml_node copy3 = doc.append_child(STR("copy3")); + + CHECK_NODE(doc, STR("")); + + copy1.append_copy(attr); + + CHECK_NODE(doc, STR("")); + + attr.set_name(STR("att1")); + copy2.append_copy(attr); + + CHECK_NODE(doc, STR("")); + + copy1.first_attribute().set_value(STR("valu2")); + copy3.append_copy(copy1.first_attribute()); + + CHECK_NODE(doc, STR("")); +} + TEST_XML(dom_node_copy_out_of_memory_node, "text1text2") { test_runner::_memory_fail_threshold = 32768 * 2 + 4096; -- cgit v1.2.3