// Copyright 2018 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 <errno.h>
#include <fcntl.h>
#include <fuchsia/device/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/unsafe.h>
#include <lib/memfs/memfs.h>
#include <lib/sync/completion.h>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <zircon/assert.h>
#include <zircon/device/vfs.h>
#include <zircon/errors.h>

#include <fbl/string_buffer.h>
#include <fbl/string_printf.h>
#include <fbl/unique_fd.h>
#include <fs-management/fvm.h>
#include <fs-test-utils/fixture.h>
#include <ramdevice-client/ramdisk.h>

namespace fs_test_utils {

namespace {

constexpr char kRamdiskCtlPath[] = "misc/ramctl";

constexpr char kDevPath[] = "/dev";
// Used as path for referencing devices bound to the isolated devmgr
// in the current test case.
constexpr char kIsolatedDevPath[] = "/isolated-dev";

// Mount point for local MemFs to be mounted.
constexpr char kMemFsPath[] = "/memfs";

// Name for MemFs serving thread.
constexpr char kMemFsThreadName[] = "TestServingMemFsName";

// Path where to mount the filesystem.
constexpr char kFsPath[] = "%s/fs-root";

// Partition name where the filesystem will be mounted when using fvm.
constexpr char kFsPartitionName[] = "fs-test-partition";

// FVM Driver lib
constexpr char kFvmDriverLibPath[] = "/boot/driver/fvm.so";

constexpr uint8_t kTestUniqueGUID[] = {0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

constexpr uint8_t kTestPartGUID[] = {0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
                                     0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

zx_status_t MountMemFs(async::Loop* loop, memfs_filesystem_t** memfs_out) {
  zx_status_t result = ZX_OK;
  result = loop->StartThread(kMemFsThreadName);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Failed to start serving thread for MemFs.\n");
    return result;
  }

  return memfs_install_at(loop->dispatcher(), kMemFsPath, memfs_out);
}

zx_status_t UnmountMemFs(memfs_filesystem_t* memfs) {
  return memfs_uninstall_unsafe(memfs, kMemFsPath);
}

zx_status_t MakeRamdisk(int devfs_root, const FixtureOptions& options,
                        ramdisk_client_t** out_ramdisk) {
  ZX_DEBUG_ASSERT(options.use_ramdisk);
  if (options.use_ramdisk) {
    zx_status_t result = ramdisk_create_at(devfs_root, options.ramdisk_block_size,
                                           options.ramdisk_block_count, out_ramdisk);
    if (result != ZX_OK) {
      LOG_ERROR(result, "Failed to create ramdisk(block_size=%lu, ramdisk_block_count=%lu)\n",
                options.ramdisk_block_size, options.ramdisk_block_count);
      return result;
    }
  }

  return ZX_OK;
}

zx_status_t RemoveRamdisk(const FixtureOptions& options, ramdisk_client_t* ramdisk) {
  ZX_DEBUG_ASSERT(options.use_ramdisk);
  if (options.use_ramdisk && ramdisk != nullptr) {
    zx_status_t result = ramdisk_destroy(ramdisk);
    if (result != ZX_OK) {
      LOG_ERROR(result, "Failed to destroy ramdisk.\n");
    }
  }
  return ZX_OK;
}

zx_status_t MakeFvm(int devfs_root, const char* root_path, const fbl::String& block_device_path,
                    uint64_t fvm_slice_size,

                    fbl::String* partition_path, bool* fvm_mounted) {
  zx_status_t result = ZX_OK;
  fbl::unique_fd fd(open(block_device_path.c_str(), O_RDWR));
  if (!fd) {
    LOG_ERROR(ZX_ERR_IO, "%s.\nblock_device_path: %s\n", strerror(errno),
              block_device_path.c_str());
    return ZX_ERR_IO;
  }
  result = fvm_init(fd.get(), fvm_slice_size);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Failed to format device with FVM.\nblock_device_path: %s\n",
              block_device_path.c_str());
    return result;
  }
  *fvm_mounted = true;
  fbl::String fvm_device_path = fbl::StringPrintf("%s/fvm", block_device_path.c_str());
  // Bind FVM Driver.
  fdio_t* io = fdio_unsafe_fd_to_io(fd.get());
  if (io == NULL) {
    return ZX_ERR_INTERNAL;
  }
  zx_status_t call_status = ZX_OK;
  auto resp = ::llcpp::fuchsia::device::Controller::Call::Bind(
      zx::unowned_channel(fdio_unsafe_borrow_channel(io)),
      ::fidl::StringView(kFvmDriverLibPath, strlen(kFvmDriverLibPath)));
  result = resp.status();
  if (resp->result.is_err()) {
    call_status = resp->result.err();
  }
  fdio_unsafe_release(io);
  if (result == ZX_OK) {
    result = call_status;
  }
  if (result != ZX_OK) {
    LOG_ERROR(result, "Failed to bind fvm driver to block device.\nblock_device:%s\n",
              block_device_path.c_str());
    return result;
  }

  result = wait_for_device(fvm_device_path.c_str(), zx::sec(3).get());
  if (result != ZX_OK) {
    LOG_ERROR(result, "FVM driver failed to start.\nfvm_device_path:%s\n", fvm_device_path.c_str());
    return result;
  }

  fbl::unique_fd fvm_fd(open(fvm_device_path.c_str(), O_RDWR));
  if (!fvm_fd) {
    LOG_ERROR(ZX_ERR_IO, "%s.\nfvm_device_path:%s\n", strerror(errno), fvm_device_path.c_str());
    return ZX_ERR_IO;
  }

  alloc_req_t request;
  memset(&request, 0, sizeof(request));
  request.slice_count = 1;
  strcpy(request.name, kFsPartitionName);
  memcpy(request.type, kTestPartGUID, sizeof(request.type));
  memcpy(request.guid, kTestUniqueGUID, sizeof(request.guid));

  fbl::unique_fd partition_fd(
      fvm_allocate_partition_with_devfs(devfs_root, fvm_fd.get(), &request));
  if (!partition_fd) {
    LOG_ERROR(ZX_ERR_IO, "Failed to allocate FVM partition. Error: %s \n", strerror(errno));
    return ZX_ERR_IO;
  }

  char buffer[kPathSize];
  partition_fd.reset(
      open_partition_with_devfs(devfs_root, kTestUniqueGUID, kTestPartGUID, 0, buffer));
  *partition_path = fbl::String::Concat({root_path, "/", buffer});
  if (!partition_fd) {
    LOG_ERROR(ZX_ERR_IO, "Could not locate FVM partition. %s\n", strerror(errno));
    return ZX_ERR_IO;
  }

  return ZX_OK;
}

}  // namespace

bool FixtureOptions::IsValid(fbl::String* err_description) const {
  ZX_DEBUG_ASSERT(err_description != nullptr);
  fbl::StringBuffer<400> buffer;
  err_description->clear();

  if (use_ramdisk) {
    if (!block_device_path.empty()) {
      buffer.Append("use_ramdisk and block_device_path are mutually exclusive.\n");
    }
    size_t max_size = zx_system_get_physmem();
    size_t requested_size = ramdisk_block_count * ramdisk_block_size;
    if (max_size < requested_size) {
      buffer.AppendPrintf("ramdisk size(%lu) cannot exceed available memory(%lu).\n",
                          requested_size, requested_size);
    }
    if (ramdisk_block_count == 0) {
      buffer.Append("ramdisk_block_count must be greater than 0.\n");
    }
    if (ramdisk_block_size == 0) {
      buffer.Append("ramdisk_block_size must be greater than 0.\n");
    }
  } else if (block_device_path.empty()) {
    buffer.Append("block_device_path or use_ramdisk must be set\n.");
  }

  if (use_fvm) {
    if (fvm_slice_size == 0 || fvm_slice_size % kFvmBlockSize != 0) {
      buffer.AppendPrintf("fvm_slize_size must be a multiple of %lu.\n", kFvmBlockSize);
    }
  }

  *err_description = buffer.ToString();

  return err_description->empty();
}

Fixture::Fixture(const FixtureOptions& options) : options_(options) {}

Fixture::~Fixture() {
  // Sanity check, teardown any resources if these two were not called yet.
  TearDown();
  TearDownTestCase();
}

zx_status_t Fixture::Mount() {
  fbl::unique_fd fd(open(GetFsBlockDevice().c_str(), O_RDWR));
  if (!fd) {
    LOG_ERROR(ZX_ERR_IO, "%s.\nblock_device_path:%s\n", strerror(errno),
              GetFsBlockDevice().c_str());
    return ZX_ERR_IO;
  }

  // Already mounted.
  if (fs_state_ == ResourceState::kAllocated) {
    return ZX_OK;
  }

  mount_options_t mount_options = default_mount_options;
  mount_options.create_mountpoint = true;
  mount_options.wait_until_ready = true;
  mount_options.register_fs = false;
  if (options_.write_compression_algorithm) {
    mount_options.write_compression_algorithm = options_.write_compression_algorithm;
  }

  disk_format_t format = detect_disk_format(fd.get());
  zx_status_t result =
      mount(fd.release(), fs_path_.c_str(), format, &mount_options, launch_stdio_async);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Failed to mount device at %s.\nblock_device_path:%s\n", fs_path_.c_str(),
              GetFsBlockDevice().c_str());
    return result;
  }
  fs_state_ = ResourceState::kAllocated;
  return ZX_OK;
}

zx_status_t Fixture::Fsck() const {
  const fbl::String& block_dev = GetFsBlockDevice().c_str();
  if (block_dev.empty()) {
    // the block device doesn't exist, in which case there's nothing to
    // check. since this is a test fixture, that's probably not what wanted,
    // so surface the error.
    LOG_ERROR(ZX_ERR_BAD_STATE, "Fsck called on an empty fixture\n");
    return ZX_ERR_BAD_STATE;
  }

  // set up the fsck options
  fsck_options_t fsck_options = default_fsck_options;
  fsck_options.never_modify = true;
  fsck_options.force = true;

  // run fsck
  zx_status_t result = fsck(block_dev.c_str(), options_.fs_type, &fsck_options, launch_stdio_sync);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Fsck failed on device at block_device_path:%s\n", block_dev.c_str());
    return result;
  }

  return ZX_OK;
}

zx_status_t Fixture::Umount() {
  if (fs_state_ != ResourceState::kAllocated) {
    return ZX_OK;
  }
  if (!fs_path_.empty()) {
    zx_status_t result = umount(fs_path_.c_str());
    if (result != ZX_OK) {
      LOG_ERROR(result,
                "Failed to umount device from MemFs.\nblock_device_path:%s\nmount_path:%s\n",
                GetFsBlockDevice().c_str(), fs_path_.c_str());
      return result;
    }
    fs_state_ = ResourceState::kFreed;
  }
  return ZX_OK;
}

zx_status_t Fixture::Format() const {
  // Format device.
  mkfs_options_t mkfs_options = default_mkfs_options;
  fbl::String block_device_path = GetFsBlockDevice();
  zx_status_t result =
      mkfs(block_device_path.c_str(), options_.fs_type, launch_stdio_sync, &mkfs_options);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Failed to format block device.\nblock_device_path:%s\n",
              block_device_path.c_str());
    return result;
  }

  // Verify format.
  fsck_options_t fsck_options = default_fsck_options;
  result = fsck(block_device_path.c_str(), options_.fs_type, &fsck_options, launch_stdio_sync);
  if (result != ZX_OK) {
    LOG_ERROR(result, "Block device format has errors.\nblock_device_path:%s\n",
              block_device_path.c_str());
    return result;
  }

  return ZX_OK;
}

zx_status_t Fixture::SetUpTestCase() {
  LOG_INFO("Using random seed: %u\n", options_.seed);
  zx_status_t result;
  seed_ = options_.seed;

  // Create the devmgr instance and bind it
  if (options_.isolated_devmgr) {
    devmgr_launcher::Args args = devmgr_integration_test::IsolatedDevmgr::DefaultArgs();
    args.disable_block_watcher = true;
    args.sys_device_driver = devmgr_integration_test::IsolatedDevmgr::kSysdevDriver;
    args.load_drivers.push_back(devmgr_integration_test::IsolatedDevmgr::kSysdevDriver);
    args.driver_search_paths.push_back("/boot/driver");

    result = devmgr_integration_test::IsolatedDevmgr::Create(std::move(args), &devmgr_);

    if (result != ZX_OK) {
      return result;
    }
    fdio_ns_t* ns;
    result = fdio_ns_get_installed(&ns);
    if (result != ZX_OK) {
      return result;
    }
    result = fdio_ns_bind_fd(ns, kIsolatedDevPath, devmgr_.devfs_root().get());
    if (result != ZX_OK) {
      return result;
    }
    // Wait for RamCtl to appear.
    result = wait_for_device_at(devmgr_.devfs_root().get(), kRamdiskCtlPath, zx::sec(5).get());

    if (result != ZX_OK) {
      return result;
    }
    devfs_root_.reset(open(kIsolatedDevPath, O_RDWR));
    root_path_ = kIsolatedDevPath;
  } else {
    devfs_root_.reset(open(kDevPath, O_RDWR));
    root_path_ = kDevPath;
  }

  if (options_.use_ramdisk) {
    result = MakeRamdisk(devfs_root_.get(), options_, &ramdisk_);
    if (result != ZX_OK) {
      return result;
    }
    block_device_path_ =
        fbl::StringPrintf("%s/%s", options_.isolated_devmgr ? kIsolatedDevPath : kDevPath,
                          ramdisk_get_path(ramdisk_));
    ramdisk_state_ = ResourceState::kAllocated;
  }

  if (!options_.block_device_path.empty()) {
    block_device_path_ = options_.block_device_path;
  }

  return ZX_OK;
}

zx_status_t Fixture::SetUp() {
  fvm_state_ = ResourceState::kUnallocated;
  fs_state_ = ResourceState::kUnallocated;
  if (options_.use_fvm) {
    bool allocated = false;
    zx_status_t result = MakeFvm(devfs_root_.get(), root_path_, block_device_path_,
                                 options_.fvm_slice_size, &partition_path_, &allocated);
    if (allocated) {
      fvm_state_ = ResourceState::kAllocated;
    }

    if (result != ZX_OK) {
      return result;
    }
  }

  fs_path_ = fbl::StringPrintf(kFsPath, kMemFsPath);
  zx_status_t result;
  if (options_.fs_format) {
    result = Format();
    if (result != ZX_OK) {
      return result;
    }
  }

  if (options_.fs_mount) {
    result = Mount();
    if (result != ZX_OK) {
      return result;
    }
    fs_state_ = ResourceState::kAllocated;
  }

  return ZX_OK;
}

zx_status_t Fixture::TearDown() {
  zx_status_t result;
  // Umount Fs from MemFs.
  if (fs_state_ == ResourceState::kAllocated) {
    result = Umount();
    if (result != ZX_OK) {
      return result;
    }
  }

  // If real device not in FVM, clean it.
  if (!block_device_path_.empty() && !options_.use_fvm && fs_state_ == ResourceState::kAllocated) {
    result = Format();
    if (result != ZX_OK) {
      return result;
    }
    fs_state_ = ResourceState::kFreed;
  }

  // If using FVM on top of device, just destroy the fvm, this only applies if
  // the fvm was created within this process.
  if (options_.use_fvm && fvm_state_ == ResourceState::kAllocated) {
    result = fvm_destroy(block_device_path_.c_str());
    if (result != ZX_OK) {
      LOG_ERROR(result, "Failed to destroy fvm in block_device.\nblock_device: %s\n",
                block_device_path_.cend());
      return result;
    }
    fs_state_ = ResourceState::kFreed;
    fvm_state_ = ResourceState::kFreed;
  }
  return ZX_OK;
}

zx_status_t Fixture::TearDownTestCase() {
  if (options_.isolated_devmgr) {
    zx_status_t result;
    fdio_ns_t* ns;
    result = fdio_ns_get_installed(&ns);
    if (result != ZX_OK) {
      return result;
    }
    result = fdio_ns_unbind(ns, kIsolatedDevPath);
    // Either successfuly unbind or we already unbound it.
    if (result != ZX_OK && result != ZX_ERR_NOT_FOUND) {
      return result;
    }
  }

  if (ramdisk_state_ == ResourceState::kAllocated) {
    zx_status_t ramdisk_result = RemoveRamdisk(options_, ramdisk_);
    ramdisk_ = nullptr;
    if (ramdisk_result != ZX_OK) {
      return ramdisk_result;
    }
  }
  ramdisk_state_ = ResourceState::kFreed;

  return ZX_OK;
}

int RunWithMemFs(const fbl::Function<int()>& main_fn) {
  memfs_filesystem_t* fs;
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  zx_status_t status;
  if ((status = MountMemFs(&loop, &fs)) != ZX_OK) {
    LOG_ERROR(status, "Failed to mount memfs\n");
    return -1;
  }
  int result = main_fn();
  loop.Shutdown();
  if ((status = UnmountMemFs(fs)) != ZX_OK) {
    LOG_ERROR(status, "Failed to unmount memfs\n");
    return -1;
  }
  return result;
}

}  // namespace fs_test_utils
