Home | History | Annotate | Download | only in notification
      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