// 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/lib/loader_service/loader_service_test_fixture.h"

#include <fuchsia/security/resource/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fidl/llcpp/memory.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/zx/channel.h>
#include <lib/zx/object.h>
#include <lib/zx/resource.h>
#include <lib/zx/status.h>
#include <zircon/errors.h>
#include <zircon/limits.h>

#include <string_view>

#define ASSERT_OK(expr) ASSERT_EQ(ZX_OK, expr)
#define EXPECT_OK(expr) EXPECT_EQ(ZX_OK, expr)

namespace loader {
namespace test {

namespace fldsvc = ::llcpp::fuchsia::ldsvc;
namespace fsec = ::llcpp::fuchsia::security::resource;

namespace {

zx_rights_t get_rights(const zx::object_base& handle) {
  zx_info_handle_basic_t info;
  zx_status_t status = handle.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  return status == ZX_OK ? info.rights : ZX_RIGHT_NONE;
}

}  // namespace

void LoaderServiceTest::TearDown() {
  if (vfs_) {
    std::optional<zx_status_t> shutdown_status;
    vfs_->Shutdown([&](zx_status_t status) { shutdown_status = status; });
    RunLoopUntil([&]() { return shutdown_status.has_value(); });
    ASSERT_OK(shutdown_status.value());
  }
}

void LoaderServiceTest::CreateTestDirectory(std::vector<TestDirectoryEntry> config,
                                            fbl::unique_fd* root_fd) {
  ASSERT_FALSE(vfs_);
  ASSERT_FALSE(root_dir_);

  ASSERT_OK(memfs::Vfs::Create("<tmp>", &vfs_, &root_dir_));
  vfs_->SetDispatcher(fs_loop_.dispatcher());

  for (auto entry : config) {
    ASSERT_NO_FATAL_FAILURE(AddDirectoryEntry(root_dir_, entry));
  }

  zx::channel client, server;
  ASSERT_OK(zx::channel::create(0, &client, &server));
  ASSERT_OK(vfs_->ServeDirectory(fbl::RefPtr(root_dir_), std::move(server)));

  // Must start fs_loop before fdio_fd_create, since that will attempt to Describe the directory.
  ASSERT_OK(fs_loop_.StartThread("fs_loop"));
  ASSERT_OK(fdio_fd_create(client.release(), root_fd->reset_and_get_address()));

  // The loader needs a separate thread from the FS because it uses synchronous fd-based I/O.
  ASSERT_OK(loader_loop_.StartThread("loader_loop"));
}

void LoaderServiceTest::AddDirectoryEntry(const fbl::RefPtr<memfs::VnodeDir>& root,
                                          TestDirectoryEntry entry) {
  ASSERT_FALSE(entry.path.empty() || entry.path.front() == '/' || entry.path.back() == '/');

  zx::vmo vmo;
  ASSERT_OK(zx::vmo::create(ZX_PAGE_SIZE, 0, &vmo));
  ASSERT_OK(vmo.write(entry.file_contents.data(), 0, entry.file_contents.size()));
  if (entry.executable) {
    auto vmex_rsrc = GetVmexResource();
    ASSERT_OK(vmex_rsrc.status_value());
    ASSERT_TRUE(vmex_rsrc.value()->is_valid());
    ASSERT_OK(vmo.replace_as_executable(*vmex_rsrc.value(), &vmo));
  }

  fbl::RefPtr<memfs::VnodeDir> dir(root);
  std::string_view view(entry.path);
  while (true) {
    size_t next = view.find('/');
    if (next == std::string_view::npos) {
      // No more subdirectories; create vnode for vmo, then done!
      ASSERT_FALSE(view.empty());
      ASSERT_OK(dir->CreateFromVmo(view, vmo.release(), 0, entry.file_contents.size()));
      return;
    } else {
      // Create subdirectory if it doesn't already exist.
      std::string_view subdir(view.substr(0, next));
      ASSERT_FALSE(subdir.empty());

      fbl::RefPtr<fs::Vnode> out;
      zx_status_t status = dir->Lookup(subdir, &out);
      if (status == ZX_ERR_NOT_FOUND) {
        status = dir->Create(subdir, S_IFDIR, &out);
      }
      ASSERT_OK(status);

      dir = fbl::RefPtr<memfs::VnodeDir>::Downcast(std::move(out));
      view.remove_prefix(next + 1);
    }
  }
}

void LoaderServiceTest::LoadObject(fldsvc::Loader::SyncClient& client, std::string name,
                                   zx::status<std::string> expected) {
  auto result = client.LoadObject(fidl::unowned_str(name));
  ASSERT_TRUE(result.ok());
  auto response = result.Unwrap();
  ASSERT_EQ(expected.status_value(), response->rv);

  zx::vmo vmo = std::move(response->object);
  if (expected.is_error()) {
    ASSERT_FALSE(vmo.is_valid());
  } else {
    ASSERT_TRUE(vmo.is_valid());
    ASSERT_EQ(get_rights(vmo) & ZX_RIGHT_EXECUTE, ZX_RIGHT_EXECUTE);

    char data[ZX_PAGE_SIZE] = {};
    ASSERT_OK(vmo.read(data, 0, ZX_PAGE_SIZE));
    ASSERT_EQ(std::string(data), expected.value());
  }
}

void LoaderServiceTest::Config(fldsvc::Loader::SyncClient& client, std::string config,
                               zx::status<zx_status_t> expected) {
  auto result = client.Config(fidl::StringView(fidl::unowned_ptr(config.data()), config.size()));
  ASSERT_EQ(result.status(), expected.status_value());
  if (expected.is_ok()) {
    ASSERT_EQ(result.Unwrap()->rv, expected.value());
  }
}

// static
zx::status<zx::unowned_resource> LoaderServiceTest::GetVmexResource() {
  static const std::string kVmexResourcePath = "/svc/" + std::string(fsec::Vmex::Name);

  static zx::resource vmex_resource;
  if (!vmex_resource.is_valid()) {
    zx::channel client, server;
    auto status = zx::make_status(zx::channel::create(0, &client, &server));
    if (status.is_error()) {
      return status.take_error();
    }
    status = zx::make_status(fdio_service_connect(kVmexResourcePath.c_str(), server.release()));
    if (status.is_error()) {
      return status.take_error();
    }

    auto result = fsec::Vmex::Call::Get(client.borrow());
    if (!result.ok()) {
      return zx::error(result.status());
    }
    vmex_resource = std::move(result.Unwrap()->vmex);
  }
  return zx::ok(vmex_resource.borrow());
}

}  // namespace test
}  // namespace loader
