summaryrefslogtreecommitdiff
path: root/tests/core
diff options
context:
space:
mode:
authorHaoyu Qiu <timothyqiu32@gmail.com>2022-09-09 09:42:24 +0800
committerHaoyu Qiu <timothyqiu32@gmail.com>2022-09-09 09:42:24 +0800
commitf5760ed65deefd8a7fe8ce03ff9bd4676bdc4406 (patch)
treec2fbc62cf0d03248a44f68f89849e0bb6cba8bd6 /tests/core
parent95c35417cdf82c990075953320a0d06c81b6c980 (diff)
Fix parsing of XML CDATA and add test cases
Diffstat (limited to 'tests/core')
-rw-r--r--tests/core/io/test_xml_parser.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/tests/core/io/test_xml_parser.h b/tests/core/io/test_xml_parser.h
index 87592b56ce..35e86d8203 100644
--- a/tests/core/io/test_xml_parser.h
+++ b/tests/core/io/test_xml_parser.h
@@ -66,6 +66,170 @@ TEST_CASE("[XMLParser] End-to-end") {
parser.close();
}
+
+TEST_CASE("[XMLParser] Comments") {
+ XMLParser parser;
+
+ SUBCASE("Missing end of comment") {
+ const String input = "<first></first><!-- foo";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), " foo");
+ }
+ SUBCASE("Bad start of comment") {
+ const String input = "<first></first><!-";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), "-");
+ }
+ SUBCASE("Unblanced angle brackets in comment") {
+ const String input = "<!-- example << --><next-tag></next-tag>";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), " example << ");
+ }
+ SUBCASE("Doctype") {
+ const String input = "<!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]>";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), "DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]");
+ }
+}
+
+TEST_CASE("[XMLParser] Premature endings") {
+ SUBCASE("Simple cases") {
+ String input;
+ String expected_name;
+ XMLParser::NodeType expected_type;
+
+ SUBCASE("Incomplete Unknown") {
+ input = "<first></first><?xml";
+ expected_type = XMLParser::NodeType::NODE_UNKNOWN;
+ expected_name = "?xml";
+ }
+ SUBCASE("Incomplete CDStart") {
+ input = "<first></first><![CD";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "";
+ }
+ SUBCASE("Incomplete CData") {
+ input = "<first></first><![CDATA[example";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "example";
+ }
+ SUBCASE("Incomplete CDEnd") {
+ input = "<first></first><![CDATA[example]]";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "example]]";
+ }
+ SUBCASE("Incomplete start-tag name") {
+ input = "<first></first><second";
+ expected_type = XMLParser::NodeType::NODE_ELEMENT;
+ expected_name = "second";
+ }
+
+ XMLParser parser;
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), expected_type);
+ CHECK_EQ(parser.get_node_name(), expected_name);
+ }
+
+ SUBCASE("With attributes and texts") {
+ XMLParser parser;
+
+ SUBCASE("Incomplete start-tag attribute name") {
+ const String input = "<first></first><second attr1=\"foo\" attr2";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 1);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ }
+
+ SUBCASE("Incomplete start-tag attribute unquoted value") {
+ const String input = "<first></first><second attr1=\"foo\" attr2=bar";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 1);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ }
+
+ SUBCASE("Incomplete start-tag attribute quoted value") {
+ const String input = "<first></first><second attr1=\"foo\" attr2=\"bar";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 2);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ CHECK_EQ(parser.get_attribute_name(1), "attr2");
+ CHECK_EQ(parser.get_attribute_value(1), "bar");
+ }
+
+ SUBCASE("Incomplete end-tag name") {
+ const String input = "<first></fir";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ CHECK_EQ(parser.get_node_name(), "fir");
+ }
+
+ SUBCASE("Trailing text") {
+ const String input = "<first></first>example";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_TEXT);
+ CHECK_EQ(parser.get_node_data(), "example");
+ }
+ }
+}
+
+TEST_CASE("[XMLParser] CDATA") {
+ const String input = "<a><![CDATA[my cdata content goes here]]></a>";
+ XMLParser parser;
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "a");
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_CDATA);
+ CHECK_EQ(parser.get_node_name(), "my cdata content goes here");
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ CHECK_EQ(parser.get_node_name(), "a");
+}
} // namespace TestXMLParser
#endif // TEST_XML_PARSER_H