// Copyright 2022 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/sys/early_boot_instrumentation/coverage_source.h"

#include <fcntl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/namespace.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <sys/stat.h>

#include <memory>

#include <fbl/unique_fd.h>
#include <gtest/gtest.h>
#include <sdk/lib/vfs/cpp/flags.h>
#include <sdk/lib/vfs/cpp/pseudo_dir.h>
#include <sdk/lib/vfs/cpp/vmo_file.h>

namespace early_boot_instrumentation {
namespace {

constexpr auto kFlags = fuchsia::io::OpenFlags::RIGHT_READABLE;

zx_koid_t GetKoid(zx_handle_t handle) {
  zx_info_handle_basic_t info;
  zx_status_t status =
      zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  return status == ZX_OK ? info.koid : ZX_KOID_INVALID;
}

// Serve the vmos from /somepath/kernel/vmofile.name.
class FakeBootItemsFixture : public testing::Test {
 public:
  void Serve(const std::string& path) {
    zx::channel dir_server, dir_client;
    ASSERT_EQ(zx::channel::create(0, &dir_server, &dir_client), 0);

    fdio_ns_t* root_ns = nullptr;
    path_ = path;
    ASSERT_EQ(fdio_ns_get_installed(&root_ns), ZX_OK);
    ASSERT_EQ(fdio_ns_bind(root_ns, path.c_str(), dir_client.release()), ZX_OK);

    ASSERT_EQ(kernel_dir_.Serve(kFlags, std::move(dir_server), loop_.dispatcher()), ZX_OK);
    loop_.StartThread("kernel_data_dir");
  }

  void BindFile(std::string_view path) {
    zx::vmo path_vmo;
    ASSERT_EQ(zx::vmo::create(4096, 0, &path_vmo), 0);
    zx_koid_t koid = GetKoid(path_vmo.get());
    ASSERT_NE(koid, ZX_KOID_INVALID);
    auto str_path = std::string(path);
    path_to_koid_[str_path] = koid;

    auto file = std::make_unique<vfs::VmoFile>(std::move(path_vmo), 0, 4096);
    ASSERT_EQ(kernel_dir_.AddEntry(str_path, std::move(file)), ZX_OK);
  }

  void TearDown() override {
    // Best effort.
    fdio_ns_t* root_ns = nullptr;
    ASSERT_EQ(fdio_ns_get_installed(&root_ns), ZX_OK);
    fdio_ns_unbind(root_ns, path_.c_str());
    loop_.Shutdown();
  }

 private:
  async::Loop loop_ = async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  vfs::PseudoDir kernel_dir_;

  std::map<std::string, zx_koid_t> path_to_koid_;
  std::string path_;
};

using ExposeKernelProfileDataTest = FakeBootItemsFixture;
using ExposePhysbootProfileDataTest = FakeBootItemsFixture;

TEST_F(ExposeKernelProfileDataTest, WithSymbolizerLogExposesBoth) {
  BindFile("zircon.elf.profraw");
  BindFile("symbolizer.log");
  ASSERT_NO_FATAL_FAILURE(Serve("/boot/kernel/data"));

  fbl::unique_fd kernel_data_dir(open("/boot/kernel/data", O_RDONLY));
  ASSERT_TRUE(kernel_data_dir) << strerror(errno);

  vfs::PseudoDir out_dir;
  ASSERT_TRUE(ExposeKernelProfileData(kernel_data_dir, out_dir).is_ok());
  ASSERT_FALSE(out_dir.IsEmpty());

  std::string kernel_file(kKernelFile);
  vfs::internal::Node* node = nullptr;
  ASSERT_EQ(out_dir.Lookup(kernel_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);

  node = nullptr;
  std::string symbolizer_file(kKernelSymbolizerFile);
  ASSERT_EQ(out_dir.Lookup(symbolizer_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);
}

TEST_F(ExposeKernelProfileDataTest, OnlyKernelFileIsOk) {
  // Dispatcher
  BindFile("zircon.elf.profraw");
  ASSERT_NO_FATAL_FAILURE(Serve("/boot/kernel/data"));

  fbl::unique_fd kernel_data_dir(open("/boot/kernel/data", O_RDONLY));
  ASSERT_TRUE(kernel_data_dir) << strerror(errno);

  vfs::PseudoDir out_dir;
  ASSERT_TRUE(ExposeKernelProfileData(kernel_data_dir, out_dir).is_ok());
  ASSERT_FALSE(out_dir.IsEmpty());

  std::string kernel_file(kKernelFile);
  vfs::internal::Node* node = nullptr;
  ASSERT_EQ(out_dir.Lookup(kernel_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);

  node = nullptr;
  std::string symbolizer_file(kKernelSymbolizerFile);
  ASSERT_NE(out_dir.Lookup(symbolizer_file, &node), ZX_OK);
}

TEST_F(ExposePhysbootProfileDataTest, WithSymbolizerFileIsOk) {
  // Dispatcher
  BindFile("physboot.profraw");
  BindFile("symbolizer.log");
  ASSERT_NO_FATAL_FAILURE(Serve("/boot/kernel/data/phys"));

  fbl::unique_fd kernel_data_dir(open("/boot/kernel/data/phys", O_RDONLY));
  ASSERT_TRUE(kernel_data_dir) << strerror(errno);

  vfs::PseudoDir out_dir;
  ASSERT_TRUE(ExposePhysbootProfileData(kernel_data_dir, out_dir).is_ok());
  ASSERT_FALSE(out_dir.IsEmpty());

  std::string phys_file(kPhysFile);
  vfs::internal::Node* node = nullptr;
  ASSERT_EQ(out_dir.Lookup(phys_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);

  node = nullptr;
  std::string symbolizer_file(kPhysSymbolizerFile);
  ASSERT_EQ(out_dir.Lookup(symbolizer_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);
}

TEST_F(ExposePhysbootProfileDataTest, OnlyProfrawFileIsOk) {
  // Dispatcher
  BindFile("physboot.profraw");
  ASSERT_NO_FATAL_FAILURE(Serve("/boot/kernel/data/phys"));

  fbl::unique_fd kernel_data_dir(open("/boot/kernel/data/phys", O_RDONLY));
  ASSERT_TRUE(kernel_data_dir) << strerror(errno);

  vfs::PseudoDir out_dir;
  ASSERT_TRUE(ExposePhysbootProfileData(kernel_data_dir, out_dir).is_ok());
  ASSERT_FALSE(out_dir.IsEmpty());

  std::string phys_file(kPhysFile);
  vfs::internal::Node* node = nullptr;
  ASSERT_EQ(out_dir.Lookup(phys_file, &node), ZX_OK);
  ASSERT_NE(node, nullptr);

  node = nullptr;
  std::string symbolizer_file(kPhysSymbolizerFile);
  ASSERT_NE(out_dir.Lookup(symbolizer_file, &node), ZX_OK);
}

}  // namespace
}  // namespace early_boot_instrumentation
