普通文本  |  208行  |  6.34 KB

// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/notification/xml_node.h"

#include <memory>

#include <gtest/gtest.h>

#include "src/notification/xmpp_stream_parser.h"

namespace weave {
namespace {

class XmlParser : public XmppStreamParser::Delegate {
 public:
  std::unique_ptr<XmlNode> Parse(const std::string& xml) {
    parser_.ParseData(xml);
    return std::move(node_);
  }

 private:
  // Overrides from XmppStreamParser::Delegate.
  void OnStreamStart(const std::string& node_name,
                     std::map<std::string, std::string> attributes) override {
    node_.reset(new XmlNode{node_name, std::move(attributes)});
  }

  void OnStreamEnd(const std::string& node_name) override {}

  void OnStanza(std::unique_ptr<XmlNode> stanza) override {
    node_->AddChild(std::move(stanza));
  }

  std::unique_ptr<XmlNode> node_;
  XmppStreamParser parser_{this};
};

}  // anonymous namespace

class XmlNodeTest : public testing::Test {
 public:
  void SetUp() override {
    node_.reset(
        new XmlNode{"test_node", {{"attr1", "val1"}, {"attr2", "val2"}}});
  }

  // Accessor helpers for private members of XmlNode.
  static const XmlNode* GetParent(const XmlNode& node) { return node.parent_; }

  static void SetText(XmlNode* node, const std::string& text) {
    node->SetText(text);
  }

  static void AppendText(XmlNode* node, const std::string& text) {
    node->AppendText(text);
  }

  void CreateNodeTree() {
    node_ = XmlParser{}.Parse(R"(
        <top>
          <node1 id="1"><node2 id="2"><node3 id="3"/></node2></node1>
          <node2 id="4"><node3 id="5"/></node2>
          <node3 id="6"/>
          <node2 id="7"><node4 id="8"><node3 id="9"/></node4></node2>
        </top>
        )");
  }

  std::unique_ptr<XmlNode> node_;
};

TEST_F(XmlNodeTest, DefaultConstruction) {
  EXPECT_EQ("test_node", node_->name());
  EXPECT_TRUE(node_->children().empty());
  EXPECT_TRUE(node_->text().empty());
}

TEST_F(XmlNodeTest, SetText) {
  SetText(node_.get(), "foobar");
  EXPECT_EQ("foobar", node_->text());
}

TEST_F(XmlNodeTest, AppendText) {
  SetText(node_.get(), "foobar");
  AppendText(node_.get(), "-baz");
  EXPECT_EQ("foobar-baz", node_->text());
}

TEST_F(XmlNodeTest, AddChild) {
  std::unique_ptr<XmlNode> child{new XmlNode{"child", {}}};
  node_->AddChild(std::move(child));
  EXPECT_EQ(1u, node_->children().size());
  EXPECT_EQ("child", node_->children().front()->name());
  EXPECT_EQ(node_.get(), GetParent(*node_->children().front().get()));
}

TEST_F(XmlNodeTest, Attributes) {
  const std::map<std::string, std::string> expected_attrs{{"attr1", "val1"},
                                                          {"attr2", "val2"}};
  EXPECT_EQ(expected_attrs, node_->attributes());
  std::string attr = "bar";
  EXPECT_FALSE(node_->GetAttribute("foo", &attr));
  EXPECT_EQ("bar", attr);  // Shouldn't be changed by failed GetAttribute().
  EXPECT_TRUE(node_->GetAttribute("attr1", &attr));
  EXPECT_EQ("val1", attr);
  EXPECT_TRUE(node_->GetAttribute("attr2", &attr));
  EXPECT_EQ("val2", attr);

  XmlNode new_node{"node", {}};
  EXPECT_FALSE(new_node.GetAttribute("attr1", &attr));
}

TEST_F(XmlNodeTest, FindFirstChild_SingleNode) {
  CreateNodeTree();
  const XmlNode* node = node_->FindFirstChild("node3", false);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("6", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("node3", true);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("foo", true);
  ASSERT_EQ(nullptr, node);
}

TEST_F(XmlNodeTest, FindFirstChild_Path) {
  CreateNodeTree();
  const XmlNode* node = node_->FindFirstChild("node2/node3", false);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("5", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("node2/node3", true);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("node1/node2/node3", false);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("node1/node2/node3", true);
  ASSERT_NE(nullptr, node);
  EXPECT_EQ("node3", node->name());
  EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));

  node = node_->FindFirstChild("foo/node3", true);
  ASSERT_EQ(nullptr, node);
}

TEST_F(XmlNodeTest, FindChildren_SingleNode) {
  CreateNodeTree();
  auto children = node_->FindChildren("node3", false);
  ASSERT_EQ(1u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("6", children[0]->GetAttributeOrEmpty("id"));

  children = node_->FindChildren("node3", true);
  ASSERT_EQ(4u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
  EXPECT_EQ("node3", children[1]->name());
  EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id"));
  EXPECT_EQ("node3", children[2]->name());
  EXPECT_EQ("6", children[2]->GetAttributeOrEmpty("id"));
  EXPECT_EQ("node3", children[3]->name());
  EXPECT_EQ("9", children[3]->GetAttributeOrEmpty("id"));
}

TEST_F(XmlNodeTest, FindChildren_Path) {
  CreateNodeTree();
  auto children = node_->FindChildren("node2/node3", false);
  ASSERT_EQ(1u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("5", children[0]->GetAttributeOrEmpty("id"));

  children = node_->FindChildren("node2/node3", true);
  ASSERT_EQ(2u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
  EXPECT_EQ("node3", children[1]->name());
  EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id"));

  children = node_->FindChildren("node1/node2/node3", false);
  ASSERT_EQ(1u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));

  children = node_->FindChildren("node1/node2/node3", true);
  ASSERT_EQ(1u, children.size());
  EXPECT_EQ("node3", children[0]->name());
  EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));

  children = node_->FindChildren("foo/bar", false);
  ASSERT_EQ(0u, children.size());

  children = node_->FindChildren("node2/baz", false);
  ASSERT_EQ(0u, children.size());
}

}  // namespace weave