1 // Copyright 2015 The Weave Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/notification/xml_node.h" 6 7 #include <memory> 8 9 #include <gtest/gtest.h> 10 11 #include "src/notification/xmpp_stream_parser.h" 12 13 namespace weave { 14 namespace { 15 16 class XmlParser : public XmppStreamParser::Delegate { 17 public: 18 std::unique_ptr<XmlNode> Parse(const std::string& xml) { 19 parser_.ParseData(xml); 20 return std::move(node_); 21 } 22 23 private: 24 // Overrides from XmppStreamParser::Delegate. 25 void OnStreamStart(const std::string& node_name, 26 std::map<std::string, std::string> attributes) override { 27 node_.reset(new XmlNode{node_name, std::move(attributes)}); 28 } 29 30 void OnStreamEnd(const std::string& node_name) override {} 31 32 void OnStanza(std::unique_ptr<XmlNode> stanza) override { 33 node_->AddChild(std::move(stanza)); 34 } 35 36 std::unique_ptr<XmlNode> node_; 37 XmppStreamParser parser_{this}; 38 }; 39 40 } // anonymous namespace 41 42 class XmlNodeTest : public testing::Test { 43 public: 44 void SetUp() override { 45 node_.reset( 46 new XmlNode{"test_node", {{"attr1", "val1"}, {"attr2", "val2"}}}); 47 } 48 49 // Accessor helpers for private members of XmlNode. 50 static const XmlNode* GetParent(const XmlNode& node) { return node.parent_; } 51 52 static void SetText(XmlNode* node, const std::string& text) { 53 node->SetText(text); 54 } 55 56 static void AppendText(XmlNode* node, const std::string& text) { 57 node->AppendText(text); 58 } 59 60 void CreateNodeTree() { 61 node_ = XmlParser{}.Parse(R"( 62 <top> 63 <node1 id="1"><node2 id="2"><node3 id="3"/></node2></node1> 64 <node2 id="4"><node3 id="5"/></node2> 65 <node3 id="6"/> 66 <node2 id="7"><node4 id="8"><node3 id="9"/></node4></node2> 67 </top> 68 )"); 69 } 70 71 std::unique_ptr<XmlNode> node_; 72 }; 73 74 TEST_F(XmlNodeTest, DefaultConstruction) { 75 EXPECT_EQ("test_node", node_->name()); 76 EXPECT_TRUE(node_->children().empty()); 77 EXPECT_TRUE(node_->text().empty()); 78 } 79 80 TEST_F(XmlNodeTest, SetText) { 81 SetText(node_.get(), "foobar"); 82 EXPECT_EQ("foobar", node_->text()); 83 } 84 85 TEST_F(XmlNodeTest, AppendText) { 86 SetText(node_.get(), "foobar"); 87 AppendText(node_.get(), "-baz"); 88 EXPECT_EQ("foobar-baz", node_->text()); 89 } 90 91 TEST_F(XmlNodeTest, AddChild) { 92 std::unique_ptr<XmlNode> child{new XmlNode{"child", {}}}; 93 node_->AddChild(std::move(child)); 94 EXPECT_EQ(1u, node_->children().size()); 95 EXPECT_EQ("child", node_->children().front()->name()); 96 EXPECT_EQ(node_.get(), GetParent(*node_->children().front().get())); 97 } 98 99 TEST_F(XmlNodeTest, Attributes) { 100 const std::map<std::string, std::string> expected_attrs{{"attr1", "val1"}, 101 {"attr2", "val2"}}; 102 EXPECT_EQ(expected_attrs, node_->attributes()); 103 std::string attr = "bar"; 104 EXPECT_FALSE(node_->GetAttribute("foo", &attr)); 105 EXPECT_EQ("bar", attr); // Shouldn't be changed by failed GetAttribute(). 106 EXPECT_TRUE(node_->GetAttribute("attr1", &attr)); 107 EXPECT_EQ("val1", attr); 108 EXPECT_TRUE(node_->GetAttribute("attr2", &attr)); 109 EXPECT_EQ("val2", attr); 110 111 XmlNode new_node{"node", {}}; 112 EXPECT_FALSE(new_node.GetAttribute("attr1", &attr)); 113 } 114 115 TEST_F(XmlNodeTest, FindFirstChild_SingleNode) { 116 CreateNodeTree(); 117 const XmlNode* node = node_->FindFirstChild("node3", false); 118 ASSERT_NE(nullptr, node); 119 EXPECT_EQ("node3", node->name()); 120 EXPECT_EQ("6", node->GetAttributeOrEmpty("id")); 121 122 node = node_->FindFirstChild("node3", true); 123 ASSERT_NE(nullptr, node); 124 EXPECT_EQ("node3", node->name()); 125 EXPECT_EQ("3", node->GetAttributeOrEmpty("id")); 126 127 node = node_->FindFirstChild("foo", true); 128 ASSERT_EQ(nullptr, node); 129 } 130 131 TEST_F(XmlNodeTest, FindFirstChild_Path) { 132 CreateNodeTree(); 133 const XmlNode* node = node_->FindFirstChild("node2/node3", false); 134 ASSERT_NE(nullptr, node); 135 EXPECT_EQ("node3", node->name()); 136 EXPECT_EQ("5", node->GetAttributeOrEmpty("id")); 137 138 node = node_->FindFirstChild("node2/node3", true); 139 ASSERT_NE(nullptr, node); 140 EXPECT_EQ("node3", node->name()); 141 EXPECT_EQ("3", node->GetAttributeOrEmpty("id")); 142 143 node = node_->FindFirstChild("node1/node2/node3", false); 144 ASSERT_NE(nullptr, node); 145 EXPECT_EQ("node3", node->name()); 146 EXPECT_EQ("3", node->GetAttributeOrEmpty("id")); 147 148 node = node_->FindFirstChild("node1/node2/node3", true); 149 ASSERT_NE(nullptr, node); 150 EXPECT_EQ("node3", node->name()); 151 EXPECT_EQ("3", node->GetAttributeOrEmpty("id")); 152 153 node = node_->FindFirstChild("foo/node3", true); 154 ASSERT_EQ(nullptr, node); 155 } 156 157 TEST_F(XmlNodeTest, FindChildren_SingleNode) { 158 CreateNodeTree(); 159 auto children = node_->FindChildren("node3", false); 160 ASSERT_EQ(1u, children.size()); 161 EXPECT_EQ("node3", children[0]->name()); 162 EXPECT_EQ("6", children[0]->GetAttributeOrEmpty("id")); 163 164 children = node_->FindChildren("node3", true); 165 ASSERT_EQ(4u, children.size()); 166 EXPECT_EQ("node3", children[0]->name()); 167 EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id")); 168 EXPECT_EQ("node3", children[1]->name()); 169 EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id")); 170 EXPECT_EQ("node3", children[2]->name()); 171 EXPECT_EQ("6", children[2]->GetAttributeOrEmpty("id")); 172 EXPECT_EQ("node3", children[3]->name()); 173 EXPECT_EQ("9", children[3]->GetAttributeOrEmpty("id")); 174 } 175 176 TEST_F(XmlNodeTest, FindChildren_Path) { 177 CreateNodeTree(); 178 auto children = node_->FindChildren("node2/node3", false); 179 ASSERT_EQ(1u, children.size()); 180 EXPECT_EQ("node3", children[0]->name()); 181 EXPECT_EQ("5", children[0]->GetAttributeOrEmpty("id")); 182 183 children = node_->FindChildren("node2/node3", true); 184 ASSERT_EQ(2u, children.size()); 185 EXPECT_EQ("node3", children[0]->name()); 186 EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id")); 187 EXPECT_EQ("node3", children[1]->name()); 188 EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id")); 189 190 children = node_->FindChildren("node1/node2/node3", false); 191 ASSERT_EQ(1u, children.size()); 192 EXPECT_EQ("node3", children[0]->name()); 193 EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id")); 194 195 children = node_->FindChildren("node1/node2/node3", true); 196 ASSERT_EQ(1u, children.size()); 197 EXPECT_EQ("node3", children[0]->name()); 198 EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id")); 199 200 children = node_->FindChildren("foo/bar", false); 201 ASSERT_EQ(0u, children.size()); 202 203 children = node_->FindChildren("node2/baz", false); 204 ASSERT_EQ(0u, children.size()); 205 } 206 207 } // namespace weave 208