// 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 "test-tool-process.h"

#include <fcntl.h>
#include <unistd.h>

#include <cstdlib>
#include <filesystem>

#include <gtest/gtest.h>

#include "piped-command.h"

#ifdef __Fuchsia__
#include <fidl/fuchsia.kernel/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/llcpp/server.h>
#include <zircon/syscalls/object.h>

#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/service.h"
#include "src/lib/storage/vfs/cpp/synchronous_vfs.h"
#else
#include <libgen.h>
#include <sys/wait.h>
#include <unistd.h>
#endif

#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif

namespace zxdump::testing {

std::string GetTmpDir() {
#ifndef __Fuchsia__
  if (const char* tmpdir = getenv("TMPDIR")) {
    std::string dir(tmpdir);
    if (!dir.empty() && dir.back() != '/') {
      dir += '/';
    }
    if (!dir.empty()) {
      return dir;
    }
  }
#endif
  return "/tmp/";
}

std::string ToolPath(std::string tool) {
#ifdef __Fuchsia__
  return std::string("/pkg/bin/") + std::move(tool);
#else
  std::filesystem::path path;
#if defined(__APPLE__)
  uint32_t length = PATH_MAX;
  char self_path[PATH_MAX];
  char self_path_symlink[PATH_MAX];
  _NSGetExecutablePath(self_path_symlink, &length);
  path = dirname(realpath(self_path_symlink, self_path));
#elif defined(__linux__)
  char self_path[PATH_MAX];
  path = dirname(realpath("/proc/self/exe", self_path));
#else
#error unknown platform.
#endif
  return path / tool;
#endif
}

std::string TestToolProcess::FilePathForTool(const TestToolProcess::File& file) const {
#ifdef __Fuchsia__
  // The tool process runs in a sandbox where /tmp/ is actually our tmp_path_.
  return "/tmp/" + file.name_;
#else
  // The tool runs in the same filesystem namespace as this test code.
  return tmp_path_ + file.name_;
#endif
}

std::string TestToolProcess::FilePathForRunner(const std::string& name) const {
  return tmp_path_ + name;
}

std::string TestToolProcess::FilePathForRunner(const TestToolProcess::File& file) const {
  return FilePathForRunner(file.name_);
}

#ifdef __Fuchsia__

// The tool process runs with a sandbox namespace that has only its own special
// /tmp and /svc.  Its /tmp is mapped to the tmp_path_ subdirectory.  Its /svc
// contains only fuchsia.kernel.RootJob pointing at this fake service that just
// gives the test program's own job instead of the real root job.

class SandboxRootJobServer final : public fidl::WireServer<fuchsia_kernel::RootJob> {
 public:
  void Get(GetRequestView request, GetCompleter::Sync& completer) override {
    zx::job job;
    zx_status_t status = zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &job);
    EXPECT_EQ(status, ZX_OK) << zx_status_get_string(status);
    completer.Reply(std::move(job));
  }
};

class TestToolProcess::SandboxRootJobLoop {
 public:
  void Init(fidl::ClientEnd<fuchsia_io::Directory>& out_svc) {
    loop_.emplace(&kAsyncLoopConfigNoAttachToCurrentThread);
    zx_status_t status = loop_->StartThread("SandboxRootJob");
    ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);

    vfs_.emplace(loop_->dispatcher());
    svc_dir_ = fbl::MakeRefCounted<fs::PseudoDir>();

    status = svc_dir_->AddEntry(
        fidl::DiscoverableProtocolName<fuchsia_kernel::RootJob>,
        fbl::MakeRefCounted<fs::Service>(
            [this](fidl::ServerEnd<fuchsia_kernel::RootJob> request) -> zx_status_t {
              fidl::BindServer(loop_->dispatcher(), std::move(request), &server_);
              return ZX_OK;
            }));
    ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);

    auto [svc_client, svc_server] = *fidl::CreateEndpoints<fuchsia_io::Directory>();
    status = vfs_->ServeDirectory(svc_dir_, std::move(svc_server));
    ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
    out_svc = std::move(svc_client);
  }

  ~SandboxRootJobLoop() {
    if (loop_) {
      loop_->Shutdown();
    }
  }

 private:
  std::optional<async::Loop> loop_;
  std::optional<fs::SynchronousVfs> vfs_;
  fbl::RefPtr<fs::PseudoDir> svc_dir_;
  SandboxRootJobServer server_;
  std::optional<fidl::ServerBindingRef<fuchsia_kernel::RootJob>> binding_;
};

// Set the spawn actions to populate the namespace for the tool with only its
// own private /tmp and /svc endpoints.
void TestToolProcess::SandboxCommand(PipedCommand& command) {
  std::vector<fdio_spawn_action_t> actions;

  fbl::unique_fd tmp_fd{open(tmp_path_.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)};
  ASSERT_TRUE(tmp_fd) << tmp_path_ << ": " << strerror(errno);
  zx::channel tmp_handle;
  zx_status_t status =
      fdio_get_service_handle(tmp_fd.release(), tmp_handle.reset_and_get_address());
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
  actions.push_back({.action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
                     .ns = {
                         .prefix = "/tmp",
                         .handle = tmp_handle.release(),
                     }});

  fidl::ClientEnd<fuchsia_io::Directory> svc;
  sandbox_root_job_loop_ = std::make_unique<TestToolProcess::SandboxRootJobLoop>();
  ASSERT_NO_FATAL_FAILURE(sandbox_root_job_loop_->Init(svc));
  actions.push_back({.action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
                     .ns = {
                         .prefix = "/svc",
                         .handle = svc.TakeChannel().release(),
                     }});

  command.SetSpawnActions(FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_NAMESPACE, std::move(actions));
}
#endif  // __Fuchsia__

std::thread SendPipeWorker(fbl::unique_fd fd, std::string contents) {
  return std::thread([fd = std::move(fd), contents = std::move(contents)]() mutable {
    while (!contents.empty()) {
      ssize_t n = write(fd.get(), contents.data(), contents.size());
      if (n < 0) {
        break;
      }
      contents.erase(contents.begin(), contents.begin() + n);
    }
  });
}

std::thread CollectPipeWorker(fbl::unique_fd fd, std::string& result) {
  return std::thread([fd = std::move(fd), &result]() mutable {
    char buf[PIPE_BUF];
    while (true) {
      ssize_t n = read(fd.get(), buf, sizeof(buf));
      if (n <= 0) {
        break;
      }
      result.append(buf, static_cast<size_t>(n));
    }
  });
}

fbl::unique_fd TestToolProcess::File::CreateInput() {
  fbl::unique_fd fd{
      open(owner_->FilePathForRunner(*this).c_str(), O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0666)};
  EXPECT_TRUE(fd) << owner_->FilePathForRunner(*this).c_str() << ": " << strerror(errno);
  if (fd) {
    EXPECT_EQ(fcntl(fd.get(), F_SETFD, FD_CLOEXEC), 0);
  }
  return fd;
}

fbl::unique_fd TestToolProcess::File::OpenOutput() {
  fbl::unique_fd fd{open(owner_->FilePathForRunner(*this).c_str(), O_RDONLY)};
  if (fd) {
    EXPECT_EQ(fcntl(fd.get(), F_SETFD, FD_CLOEXEC), 0);
  }
  return fd;
}

std::string TestToolProcess::File::OutputContents() {
  std::string contents;
  char buf[BUFSIZ];
  ssize_t nread;
  fbl::unique_fd fd = OpenOutput();
  while ((nread = read(fd.get(), buf, sizeof(buf))) > 0) {
    contents.append(buf, static_cast<size_t>(nread));
  }
  EXPECT_GE(nread, 0) << strerror(errno);
  return contents;
}

TestToolProcess::File::~File() = default;

void TestToolProcess::Start(const std::string& tool, const std::vector<std::string>& args) {
  PipedCommand command;

  auto redirect = [&](int number, fbl::unique_fd& tool_fd, bool read) {
    if (!tool_fd) {
      int pipe_fd[2];
      ASSERT_EQ(pipe(pipe_fd), 0) << strerror(errno);
      ASSERT_EQ(fcntl(pipe_fd[0], F_SETFD, FD_CLOEXEC), 0) << strerror(errno);
      ASSERT_EQ(fcntl(pipe_fd[1], F_SETFD, FD_CLOEXEC), 0) << strerror(errno);
      tool_fd.reset(pipe_fd[read ? 0 : 1]);
      command.Redirect(number, fbl::unique_fd{pipe_fd[read ? 1 : 0]});
    }
  };

  redirect(STDIN_FILENO, tool_stdin_, false);
  redirect(STDOUT_FILENO, tool_stdout_, true);
  redirect(STDERR_FILENO, tool_stderr_, true);

#ifdef __Fuchsia__
  ASSERT_NO_FATAL_FAILURE(SandboxCommand(command));
#endif

  auto result = command.Start(ToolPath(tool), args);
  ASSERT_TRUE(result.is_ok()) << result.error_value();

  process_ = std::move(command).process();
}

void TestToolProcess::Finish(int& status) {
#ifdef __Fuchsia__
  ASSERT_TRUE(process_);
  zx_signals_t signals = 0;
  ASSERT_EQ(process_.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), &signals), ZX_OK);
  ASSERT_TRUE(signals & ZX_PROCESS_TERMINATED);
  zx_info_process_t info;
  ASSERT_EQ(process_.get_info(ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr), ZX_OK);
  status = static_cast<int>(info.return_code);
  process_.reset();
#else
  ASSERT_NE(process_, -1);
  ASSERT_EQ(waitpid(process_, &status, 0), process_);
  status = WIFEXITED(status) ? WEXITSTATUS(status) : -WTERMSIG(status);
  process_ = -1;
#endif
}

TestToolProcess::TestToolProcess() {
  tmp_path_ = GetTmpDir() + "tool-tmp.";
  int n = 1;
  while (mkdir((tmp_path_ + std::to_string(n)).c_str(), 0777) < 0) {
    EXPECT_EQ(errno, EEXIST) << strerror(errno);
    ++n;
  }
  tmp_path_ += std::to_string(n) + '/';
}

TestToolProcess::~TestToolProcess() {
  bool live = false;
#ifdef __Fuchsia__
  live = process_.is_valid();
#else
  live = process_ != -1;
#endif

  if (live) {
    int status = -1;
    Finish(status);
    EXPECT_EQ(status, 0);
  }

  if (stdin_thread_.joinable()) {
    stdin_thread_.join();
  }
  if (stdout_thread_.joinable()) {
    stdout_thread_.join();
  }
  if (stderr_thread_.joinable()) {
    stderr_thread_.join();
  }

  for (const File& file : files_) {
    std::string path = FilePathForRunner(file);
    EXPECT_EQ(remove(path.c_str()), 0) << file.name() << " as " << path << ": " << strerror(errno);
  }

  if (!tmp_path_.empty()) {
    EXPECT_EQ(tmp_path_.back(), '/');
    tmp_path_.resize(tmp_path_.size() - 1);  // Remove trailing slash.
    EXPECT_EQ(rmdir(tmp_path_.c_str()), 0) << tmp_path_ << ": " << strerror(errno);
  }
}

void TestToolProcess::SendStdin(std::string contents) {
  ASSERT_TRUE(tool_stdin_);
  ASSERT_FALSE(stdin_thread_.joinable());

  stdin_thread_ = SendPipeWorker(std::move(tool_stdin_), std::move(contents));
}

void TestToolProcess::CollectStdout() {
  ASSERT_TRUE(tool_stdout_);
  ASSERT_FALSE(stdout_thread_.joinable());
  stdout_thread_ = CollectPipeWorker(std::move(tool_stdout_), collected_stdout_);
}

void TestToolProcess::CollectStderr() {
  ASSERT_TRUE(tool_stderr_);
  ASSERT_FALSE(stderr_thread_.joinable());
  stderr_thread_ = CollectPipeWorker(std::move(tool_stderr_), collected_stderr_);
}

std::string TestToolProcess::collected_stdout() {
#ifdef __Fuchsia__
  EXPECT_FALSE(process_);
#else
  EXPECT_EQ(process_, -1);
#endif
  EXPECT_TRUE(stdout_thread_.joinable());
  stdout_thread_.join();
  return std::move(collected_stdout_);
}

std::string TestToolProcess::collected_stderr() {
#ifdef __Fuchsia__
  EXPECT_FALSE(process_);
#else
  EXPECT_EQ(process_, -1);
#endif
  EXPECT_TRUE(stderr_thread_.joinable());
  stderr_thread_.join();
  return std::move(collected_stderr_);
}

TestToolProcess::File& TestToolProcess::MakeFile(std::string_view name, std::string_view suffix) {
  File file;
  file.owner_ = this;
  file.name_ = "test.";
  file.name_ += name;
  file.name_ += '.';
  int n = 1;
  while (std::filesystem::exists(FilePathForRunner(file.name_ + std::to_string(n)) +
                                 std::string(suffix))) {
    ++n;
  }
  file.name_ += std::to_string(n);
  file.name_ += suffix;
  files_.push_back(std::move(file));
  return files_.back();
}

}  // namespace zxdump::testing
