// Copyright 2019 The Fuchsia 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 <fuchsia/inspect/cpp/fidl.h>
#include <lib/async/cpp/executor.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/service/cpp/reader.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/inspect/testing/cpp/inspect.h>

#include <gmock/gmock.h>

using inspect::Inspector;

namespace {

class InspectServiceTest : public gtest::RealLoopFixture {
 public:
  InspectServiceTest()
      : executor_(dispatcher()),
        inspector_(),
        handler_(inspect::MakeTreeHandler(&inspector_, dispatcher())) {}

 protected:
  inspect::Node& root() { return inspector_.GetRoot(); }

  fuchsia::inspect::TreePtr Connect() {
    fuchsia::inspect::TreePtr ret;
    handler_(ret.NewRequest());
    return ret;
  }

  void MakePrivateSnapshotHandler() {
    handler_ = inspect::MakeTreeHandler(
        &inspector_, dispatcher(), inspect::TreeHandlerSettings{.force_private_snapshot = true});
  }

  async::Executor executor_;

 private:
  Inspector inspector_;
  fidl::InterfaceRequestHandler<fuchsia::inspect::Tree> handler_;
};

TEST_F(InspectServiceTest, SingleTree) {
  inspect::ValueList values;
  root().CreateInt("val", 1, &values);

  auto ptr = Connect();
  ptr.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false) << "Error detected on connection"; });

  std::vector<std::string> names;
  bool done = false;
  fuchsia::inspect::TreeNameIteratorPtr name_iter;
  ptr->ListChildNames(name_iter.NewRequest());

  executor_.schedule_task(inspect::ReadAllChildNames(std::move(name_iter))
                              .and_then([&](std::vector<std::string>& promised_names) {
                                names = std::move(promised_names);
                                done = true;
                              }));

  RunLoopUntil([&] { return done; });

  EXPECT_TRUE(names.empty());
}

TEST_F(InspectServiceTest, SingleTreeGetContent) {
  auto val = root().CreateInt("val", 1);

  auto ptr = Connect();
  ptr.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false) << "Error detected on connection"; });

  fit::result<fuchsia::inspect::TreeContent> content;

  ptr->GetContent([&](fuchsia::inspect::TreeContent returned_content) {
    content = fit::ok(std::move(returned_content));
  });

  RunLoopUntil([&] { return !!content; });

  val.Add(1);

  auto hierarchy = inspect::ReadFromVmo(std::move(content.take_value().buffer().vmo));
  ASSERT_TRUE(hierarchy.is_ok());

  const inspect::IntPropertyValue* val_prop =
      hierarchy.value().node().get_property<inspect::IntPropertyValue>("val");
  ASSERT_NE(nullptr, val_prop);
  EXPECT_EQ(2, val_prop->value());
}

TEST_F(InspectServiceTest, SingleTreeGetContentPrivate) {
  auto val = root().CreateInt("val", 1);

  MakePrivateSnapshotHandler();
  auto ptr = Connect();
  ptr.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false) << "Error detected on connection"; });

  fit::result<fuchsia::inspect::TreeContent> content;

  ptr->GetContent([&](fuchsia::inspect::TreeContent returned_content) {
    content = fit::ok(std::move(returned_content));
  });

  RunLoopUntil([&] { return !!content; });

  val.Add(1);

  auto hierarchy = inspect::ReadFromVmo(std::move(content.take_value().buffer().vmo));
  ASSERT_TRUE(hierarchy.is_ok());

  const inspect::IntPropertyValue* val_prop =
      hierarchy.value().node().get_property<inspect::IntPropertyValue>("val");
  ASSERT_NE(nullptr, val_prop);
  EXPECT_EQ(1, val_prop->value());
}

TEST_F(InspectServiceTest, ListChildNames) {
  inspect::ValueList values;
  root().CreateLazyNode(
      "a", []() { return fit::make_result_promise<Inspector>(fit::error()); }, &values);
  root().CreateLazyNode(
      "b", []() { return fit::make_result_promise<Inspector>(fit::error()); }, &values);

  auto ptr = Connect();
  ptr.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false) << "Error detected on connection"; });

  std::vector<std::string> names;
  bool done = false;
  fuchsia::inspect::TreeNameIteratorPtr name_iter;
  ptr->ListChildNames(name_iter.NewRequest());

  executor_.schedule_task(inspect::ReadAllChildNames(std::move(name_iter))
                              .and_then([&](std::vector<std::string>& promised_names) {
                                names = std::move(promised_names);
                                done = true;
                              }));

  RunLoopUntil([&] { return done; });

  EXPECT_EQ(names, std::vector<std::string>({"a-0", "b-1"}));
}

TEST_F(InspectServiceTest, OpenChild) {
  inspect::ValueList values;
  root().CreateInt("val", 20, &values);
  root().CreateLazyNode(
      "valid",
      []() {
        Inspector insp;
        insp.GetRoot().CreateInt("val", 10, &insp);
        return fit::make_ok_promise(insp);
      },
      &values);

  root().CreateLazyNode(
      "invalid", [] { return fit::make_result_promise<Inspector>(fit::error()); }, &values);

  auto ptr = Connect();
  ptr.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false) << "Error detected on connection"; });

  std::vector<std::string> names;
  bool list_done = false;
  fuchsia::inspect::TreeNameIteratorPtr name_iter;
  fit::result<fuchsia::inspect::TreeContent> root, child;
  ptr->ListChildNames(name_iter.NewRequest());

  executor_.schedule_task(inspect::ReadAllChildNames(std::move(name_iter))
                              .and_then([&](std::vector<std::string>& promised_names) {
                                names = std::move(promised_names);
                                list_done = true;
                              }));

  ptr->GetContent(
      [&](fuchsia::inspect::TreeContent content) { root = fit::ok(std::move(content)); });
  fuchsia::inspect::TreePtr child_ptr;
  ptr->OpenChild("valid-0", child_ptr.NewRequest());
  child_ptr->GetContent(
      [&](fuchsia::inspect::TreeContent content) { child = fit::ok(std::move(content)); });

  bool read_error_done = false;
  bool missing_error_done = false;
  fuchsia::inspect::TreePtr read_error_ptr, missing_error_ptr;
  read_error_ptr.set_error_handler([&](zx_status_t status) { read_error_done = true; });
  missing_error_ptr.set_error_handler([&](zx_status_t status) { missing_error_done = true; });
  ptr->OpenChild("invalid-1", read_error_ptr.NewRequest());
  ptr->OpenChild("missing", missing_error_ptr.NewRequest());
  read_error_ptr->GetContent([](fuchsia::inspect::TreeContent unused) {});
  missing_error_ptr->GetContent([](fuchsia::inspect::TreeContent unused) {});

  RunLoopUntil([&] {
    return list_done && root.is_ok() && child.is_ok() && read_error_done && missing_error_done;
  });

  EXPECT_EQ(names, std::vector<std::string>({"invalid-1", "valid-0"}));
  auto root_hierarchy = inspect::ReadFromVmo(root.take_value().buffer().vmo).take_value();
  ASSERT_EQ(1u, root_hierarchy.node().properties().size());
  EXPECT_EQ("val", root_hierarchy.node().properties()[0].name());
  auto child_hierarchy = inspect::ReadFromVmo(child.take_value().buffer().vmo).take_value();
  ASSERT_EQ(1u, child_hierarchy.node().properties().size());
  EXPECT_EQ("val", child_hierarchy.node().properties()[0].name());
}

}  // namespace
