// 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;

    args.device_list.push_back({
        .vid = PDEV_VID_TEST,
        .pid = PDEV_PID_INSPECT_TEST,
        .did = 0,
    });

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

    static char path_buf[128];
    snprintf(path_buf, sizeof(path_buf), "sys/platform/%x:%x:0/inspect-test", PDEV_VID_TEST,
             PDEV_PID_INSPECT_TEST);
    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;

    const std::string moniker =
        std::string{"realm_builder:"} + devmgr_.RealmChildName() +
        "/driver_test_realm/realm_builder:0/boot-drivers:dev.sys.platform.11_13_0";

    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:
  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
