// Copyright 2020 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 "src/storage/blobfs/test/integration/fdio_test.h"

#include <fidl/fuchsia.io/cpp/wire.h>
#include <fuchsia/inspect/cpp/fidl.h>
#include <lib/async/cpp/executor.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/inspect/service/cpp/reader.h>

#include <fs-management/admin.h>

#include "src/storage/blobfs/mkfs.h"

namespace blobfs {

constexpr uint32_t kBlockSize = 512;
constexpr uint32_t kNumBlocks = 8192;

void FdioTest::SetUp() {
  loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);

  auto device = std::make_unique<block_client::FakeBlockDevice>(kNumBlocks, kBlockSize);
  block_device_ = device.get();
  ASSERT_EQ(FormatFilesystem(block_device_,
                             FilesystemOptions{
                                 .blob_layout_format = GetBlobLayoutFormat(),
                                 .oldest_minor_version = GetOldestMinorVersion(),
                             }),
            ZX_OK);

  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  ASSERT_EQ(endpoints.status_value(), ZX_OK);
  auto [export_root_client, export_root_server] = *std::move(endpoints);

  auto runner_or =
      Runner::Create(loop_.get(), std::move(device), mount_options_, std::move(vmex_resource_));
  ASSERT_TRUE(runner_or.is_ok());
  runner_ = std::move(runner_or.value());
  ASSERT_EQ(runner_->ServeRoot(std::move(export_root_server), ServeLayout::kExportDirectory),
            ZX_OK);
  ASSERT_EQ(loop_->StartThread("blobfs test dispatcher"), ZX_OK);

  zx::channel root_client;
  ASSERT_EQ(fs_root_handle(export_root_client.channel().get(), root_client.reset_and_get_address()),
            ZX_OK);

  // FDIO serving the root directory.
  ASSERT_EQ(fdio_fd_create(root_client.release(), root_fd_.reset_and_get_address()), ZX_OK);
  ASSERT_TRUE(root_fd_.is_valid());
  ASSERT_EQ(fdio_fd_create(export_root_client.TakeChannel().release(),
                           export_root_fd_.reset_and_get_address()),
            ZX_OK);
  ASSERT_TRUE(export_root_fd_.is_valid());
}

void FdioTest::TearDown() {
  zx::channel root_client;
  ASSERT_EQ(fdio_fd_transfer(root_fd_.release(), root_client.reset_and_get_address()), ZX_OK);
  ASSERT_EQ(
      fidl::WireCall(fidl::ClientEnd<fuchsia_io_admin::DirectoryAdmin>(std::move(root_client)))
          .Unmount()
          .status(),
      ZX_OK);
}

zx_handle_t FdioTest::export_root() {
  zx::channel export_root;
  fdio_fd_clone(export_root_fd_.get(), export_root.reset_and_get_address());
  return export_root.release();
}

fpromise::result<inspect::Hierarchy> FdioTest::TakeSnapshot() {
  async::Loop loop = async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  loop.StartThread("metric-collection-thread");
  async::Executor executor(loop.dispatcher());

  fuchsia::inspect::TreePtr tree;
  async_dispatcher_t* dispatcher = executor.dispatcher();
  zx_status_t status = fdio_service_connect_at(export_root(), "diagnostics/fuchsia.inspect.Tree",
                                               tree.NewRequest(dispatcher).TakeChannel().release());
  if (status != ZX_OK) {
    return fpromise::error();
  }

  std::condition_variable cv;
  std::mutex m;
  bool done = false;
  fpromise::result<inspect::Hierarchy> hierarchy_or_error;

  auto promise = inspect::ReadFromTree(std::move(tree))
                     .then([&](fpromise::result<inspect::Hierarchy>& result) {
                       {
                         std::unique_lock<std::mutex> lock(m);
                         hierarchy_or_error = std::move(result);
                         done = true;
                       }
                       cv.notify_all();
                     });

  executor.schedule_task(std::move(promise));

  std::unique_lock<std::mutex> lock(m);
  cv.wait(lock, [&done]() { return done; });

  loop.Quit();
  loop.JoinThreads();

  return hierarchy_or_error;
}

void FdioTest::GetUintMetricFromHierarchy(const inspect::Hierarchy& hierarchy,
                                          const std::vector<std::string>& path,
                                          const std::string& property, uint64_t* value) {
  ASSERT_NE(value, nullptr);
  const inspect::Hierarchy* direct_parent = hierarchy.GetByPath(path);
  ASSERT_NE(direct_parent, nullptr);

  const inspect::UintPropertyValue* property_node =
      direct_parent->node().get_property<inspect::UintPropertyValue>(property);
  ASSERT_NE(property_node, nullptr);

  *value = property_node->value();
}

void FdioTest::GetUintMetric(const std::vector<std::string>& path, const std::string& property,
                             uint64_t* value) {
  fpromise::result<inspect::Hierarchy> hierarchy_or_error = TakeSnapshot();
  ASSERT_TRUE(hierarchy_or_error.is_ok());
  GetUintMetricFromHierarchy(hierarchy_or_error.value(), path, property, value);
}

}  // namespace blobfs
