// 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 <fidl/fuchsia.device.inspect.test/cpp/wire.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <lib/async/cpp/executor.h>
#include <lib/ddk/device.h>
#include <lib/ddk/platform-defs.h>
#include <lib/diagnostics/reader/cpp/archive_reader.h>
#include <lib/driver-integration-test/fixture.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/fpromise/promise.h>
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <string>

#include <src/lib/testing/loop_fixture/real_loop_fixture.h>

namespace {
using driver_integration_test::IsolatedDevmgr;
using fuchsia_device_inspect_test::TestInspect;

class InspectTestCase : public gtest::RealLoopFixture {
 public:
  ~InspectTestCase() override = default;

  void SetUp() override {
    IsolatedDevmgr::Args args;
    board_test::DeviceEntry dev = {};
    strlcpy(dev.name, kPlatformDeviceName, sizeof(dev.name));
    dev.vid = PDEV_VID_TEST;
    dev.pid = PDEV_PID_INSPECT_TEST;
    dev.did = 0;
    args.device_list.push_back(dev);

    ASSERT_EQ(ZX_OK, IsolatedDevmgr::Create(&args, &devmgr_));

    static char path_buf[128];
    snprintf(path_buf, sizeof(path_buf), "sys/platform/%s/inspect-test", kPlatformDeviceName);
    zx::result channel = device_watcher::RecursiveWaitForFile(devmgr_.devfs_root().get(), path_buf);
    ASSERT_EQ(ZX_OK, channel.status_value());
    client_ = fidl::ClientEnd<TestInspect>{std::move(channel.value())};
  }

  const IsolatedDevmgr& devmgr() { return devmgr_; }
  const fidl::ClientEnd<TestInspect>& client() { return client_; }

  fpromise::promise<inspect::Hierarchy> ReadInspect() {
    using diagnostics::reader::ArchiveReader;
    using diagnostics::reader::SanitizeMonikerForSelectors;

    std::string moniker;
    {
      std::ostringstream builder;
      builder << "realm_builder:" << devmgr_.RealmChildName()
              << "/driver_test_realm/realm_builder:0/boot-drivers:dev.sys.platform."
              << kPlatformDeviceName;
      moniker = builder.str();
    }

    return fpromise::make_ok_promise(
               std::unique_ptr<ArchiveReader>(new ArchiveReader(
                   dispatcher(), {SanitizeMonikerForSelectors(moniker) + ":root"})))
        .and_then([moniker = std::move(moniker)](std::unique_ptr<ArchiveReader>& reader) {
          return reader->SnapshotInspectUntilPresent({moniker}).then(
              [](fpromise::result<std::vector<diagnostics::reader::InspectData>, std::string>&
                     wrapped) {
                EXPECT_TRUE(wrapped.is_ok()) << wrapped.take_error();
                auto data = wrapped.take_value();
                EXPECT_EQ(1ul, data.size());
                auto& inspect_data = data[0];
                if (!inspect_data.payload().has_value()) {
                  FX_LOGS(WARNING) << "inspect_data had nullopt payload";
                }
                if (inspect_data.payload().has_value() &&
                    inspect_data.payload().value() == nullptr) {
                  FX_LOGS(WARNING) << "inspect_data had nullptr for payload";
                }
                if (inspect_data.metadata().errors.has_value()) {
                  for (const auto& e : inspect_data.metadata().errors.value()) {
                    FX_LOGS(WARNING) << e.message;
                  }
                }

                return fpromise::ok(inspect_data.TakePayload());
              });
        });
  }

  // Returns whether or not the property value matches the input.
  bool CheckStringProperty(const inspect::NodeValue& node, const std::string& property_name,
                           const std::string& expected_value) {
    const auto* actual_value = node.get_property<inspect::StringPropertyValue>(property_name);
    if (actual_value == nullptr) {
      return false;
    }
    return expected_value == actual_value->value();
  }

 private:
  static constexpr char kPlatformDeviceName[board_test::kNameLengthMax] = "test-platform-device";

  IsolatedDevmgr devmgr_;
  fidl::ClientEnd<TestInspect> client_;
};

TEST_F(InspectTestCase, ReadInspectData) {
  // Use a new connection rather than using devfs_root because devfs_root has the empty set of
  // rights.
  {
    // Check initial inspect data
    std::optional<inspect::Hierarchy> hierarchy = std::nullopt;
    async::Executor exec(dispatcher());
    exec.schedule_task(
        ReadInspect().and_then([&](inspect::Hierarchy& h) { hierarchy.emplace(std::move(h)); }));
    RunLoopUntil([&] { return hierarchy.has_value(); });

    // testBeforeDdkAdd: "OK"
    ASSERT_TRUE(CheckStringProperty(hierarchy->node(), "testBeforeDdkAdd", "OK"));
  }

  // Call test-driver to modify inspect data
  const fidl::WireResult result = fidl::WireCall(client())->ModifyInspect();
  ASSERT_TRUE(result.ok());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok()) << zx_status_get_string(response.error_value());

  // Verify new inspect data is reflected
  {
    std::optional<inspect::Hierarchy> hierarchy = std::nullopt;
    async::Executor exec(dispatcher());
    exec.schedule_task(
        ReadInspect().and_then([&](inspect::Hierarchy& h) { hierarchy.emplace(std::move(h)); }));
    RunLoopUntil([&] { return hierarchy.has_value(); });

    // Previous values
    ASSERT_TRUE(CheckStringProperty(hierarchy->node(), "testBeforeDdkAdd", "OK"));
    // New addition - testModify: "OK"
    ASSERT_TRUE(CheckStringProperty(hierarchy->node(), "testModify", "OK"));
  }
}

}  // namespace
