From 4dd86943ce0fa8e550cfa10f40a9082d1a5ad133 Mon Sep 17 00:00:00 2001 From: Dave Cridland Date: Mon, 1 Jul 2024 22:08:12 +0100 Subject: [PATCH] Add some more tests --- CMakeLists.txt | 1 + rapidxml.hpp | 32 +++++++-------- test/manipulations.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++ test/parse-simple.cpp | 35 +++++++++++++++- 4 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 test/manipulations.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b03b84..38c7cae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(rapidxml-test rapidxml_print.hpp rapidxml_utils.hpp rapidxml.hpp + test/manipulations.cpp ) target_link_libraries(rapidxml-test GTest::gtest_main diff --git a/rapidxml.hpp b/rapidxml.hpp index 9b64708..17c3abd 100644 --- a/rapidxml.hpp +++ b/rapidxml.hpp @@ -1260,31 +1260,27 @@ namespace rapidxml //! Behaviour is undefined if node has no parent. //! Use parent() to test if node has a parent. //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param xmlns Namespace of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found sibling, or 0 if not found. xml_node *next_sibling(const Ch *name = 0, const Ch *xmlns = 0, std::size_t name_size = 0, std::size_t xmlns_size = 0, bool case_sensitive = true) const { assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns); - if (!xmlns && name) { - // No XMLNS asked for, but a name is present. - // Assume "same XMLNS". - xmlns = this->xmlns(); - xmlns_size = this->xmlns_size(); - } - for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) - if ((!name || internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) - && (!xmlns || internal::compare(sibling->xmlns(), sibling->xmlns_size(), xmlns, xmlns_size, case_sensitive))) - return sibling; - return 0; + if (name && name_size == 0) + name_size = internal::measure(name); + if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns); + if (!xmlns && name) { + // No XMLNS asked for, but a name is present. + // Assume "same XMLNS". + xmlns = this->xmlns(); + xmlns_size = this->xmlns_size(); } - else - return m_next_sibling; + for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) + if ((!name || internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + && (!xmlns || internal::compare(sibling->xmlns(), sibling->xmlns_size(), xmlns, xmlns_size, case_sensitive))) + return sibling; + return 0; } //! Gets first attribute of node, optionally matching attribute name. diff --git a/test/manipulations.cpp b/test/manipulations.cpp new file mode 100644 index 0000000..e132cf1 --- /dev/null +++ b/test/manipulations.cpp @@ -0,0 +1,93 @@ +// +// Created by dwd on 01/07/24. +// + +#include + +#include "rapidxml.hpp" +#include "rapidxml_print.hpp" + +namespace { + auto print(rapidxml::xml_document<> & doc) { + std::string output; + rapidxml::print(std::back_inserter(output), *doc.first_node()); + return output; + } +} + +TEST(Create, Node) { + rapidxml::xml_document<> doc; + auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes"); + doc.append_node(node); + + EXPECT_EQ( + print(doc), + "cakes\n" + ); +} + +TEST(Create, NodeEmpty) { + rapidxml::xml_document<> doc; + auto node = doc.allocate_node(rapidxml::node_element, "fish"); + doc.append_node(node); + + EXPECT_EQ( + print(doc), + "\n" + ); +} + +TEST(Create, Node2) { + rapidxml::xml_document<> doc; + auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes", 4, 5); + doc.append_node(node); + + EXPECT_EQ( + print(doc), + "cakes\n" + ); +} + +TEST(Create, NodeAttr) { + rapidxml::xml_document<> doc; + auto node = doc.allocate_node(rapidxml::node_element, "fish", "cakes"); + auto haddock = doc.allocate_attribute("id", "haddock"); + node->append_attribute(haddock); + doc.append_node(node); + + EXPECT_EQ( + print(doc), + "cakes\n" + ); + + auto tuna = doc.allocate_attribute("not-id", "tuna"); + node->append_attribute(tuna); + EXPECT_EQ(haddock->next_attribute(), tuna); + EXPECT_EQ(tuna->parent(), node); + EXPECT_EQ( + print(doc), + "cakes\n" + ); + node->remove_attribute(tuna); + EXPECT_EQ(haddock->next_attribute(), nullptr); + EXPECT_EQ(tuna->parent(), nullptr); + EXPECT_EQ( + print(doc), + "cakes\n" + ); + node->prepend_attribute(tuna); + EXPECT_EQ( + print(doc), + "cakes\n" + ); + node->value("pie"); + EXPECT_EQ( + print(doc), + "pie\n" + ); + node->remove_all_attributes(); + EXPECT_EQ( + print(doc), + "pie\n" + ); +} \ No newline at end of file diff --git a/test/parse-simple.cpp b/test/parse-simple.cpp index c2a4075..0795492 100644 --- a/test/parse-simple.cpp +++ b/test/parse-simple.cpp @@ -87,7 +87,7 @@ TEST(Parser, Xmlns) { TEST(Parser, ChildXmlns) { rapidxml::xml_document<> doc; - char doc_text[] = ""; + char doc_text[] = ""; doc.parse<0>(doc_text); auto node = doc.first_node(); @@ -99,12 +99,44 @@ TEST(Parser, ChildXmlns) { child = node->first_node(); EXPECT_STREQ("firstchild", child->name()); EXPECT_STREQ("urn:xmpp:example", child->xmlns()); + child = child->next_sibling(); + EXPECT_STREQ("child", child->name()); + EXPECT_STREQ("urn:potato", child->xmlns()); + child = child->next_sibling(); + EXPECT_STREQ("child", child->name()); + EXPECT_STREQ("urn:xmpp:example", child->xmlns()); child = node->first_node("child"); EXPECT_STREQ("child", child->name()); EXPECT_STREQ("urn:xmpp:example", child->xmlns()); + child = node->first_node()->next_sibling(nullptr, "urn:xmpp:example"); + EXPECT_STREQ("child", child->name()); + EXPECT_STREQ("urn:xmpp:example", child->xmlns()); + child = node->first_node()->next_sibling("child"); + // This will default to the same namespace as the first child ndoe. + EXPECT_STREQ("child", child->name()); + EXPECT_STREQ("urn:xmpp:example", child->xmlns()); + auto attr = node->first_attribute(); + EXPECT_STREQ(attr->xmlns(), "http://www.w3.org/2000/xmlns/"); + EXPECT_STREQ(attr->local_name(), "pfx"); + EXPECT_STREQ(attr->name(), "xmlns:pfx"); + EXPECT_EQ(attr->value_str(), "urn:xmpp:example"); + attr = attr->next_attribute(); + EXPECT_STREQ(attr->xmlns(), ""); + EXPECT_STREQ(attr->local_name(), "foo"); + EXPECT_STREQ(attr->name(), "foo"); + EXPECT_EQ(attr->value_str(), "bar"); doc.validate(); } +TEST(Parser, HandleEOF){ + rapidxml::xml_document<> doc; + char doc_text[] = ""; + EXPECT_THROW( + doc.parse<0>(doc_text), + rapidxml::eof_error + ); +} + TEST(ParseOptions, Fastest) { rapidxml::xml_document<> doc; char doc_text[] = ""; @@ -226,4 +258,3 @@ TEST(ParseOptions, OpenOnlyFastest) { subdoc.validate(); } } -