// Copyright 2021 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 <fcntl.h>
#include <lib/fdio/vfs.h>
#include <lib/service/llcpp/service.h>
#include <sys/stat.h>
#include <sys/statvfs.h>

#include <gtest/gtest.h>

#include "sdk/lib/fdio/include/lib/fdio/spawn.h"
#include "src/lib/storage/fs_management/cpp/mount.h"
#include "src/storage/fshost/constants.h"
#include "src/storage/fshost/testing/fshost_integration_test.h"
#include "src/storage/testing/fvm.h"
#include "src/storage/testing/ram_disk.h"

namespace fshost {
namespace {

using AdminServerTest = testing::FshostIntegrationTest;

void Join(const zx::process& process, int64_t* return_code) {
  *return_code = -1;

  ASSERT_EQ(process.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), nullptr), ZX_OK);

  zx_info_process_t proc_info{};
  ASSERT_EQ(process.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr),
            ZX_OK);

  *return_code = proc_info.return_code;
}

TEST_F(AdminServerTest, MountAndUnmount) {
  auto ram_disk_or = storage::RamDisk::Create(1024, 64 * 1024);
  ASSERT_EQ(ram_disk_or.status_value(), ZX_OK);
  ASSERT_EQ(fs_management::Mkfs(ram_disk_or->path().c_str(), fs_management::kDiskFormatMinfs,
                                fs_management::LaunchStdioSync, fs_management::MkfsOptions()),
            ZX_OK);

  std::string device_path = ram_disk_or->path();

  const std::string fshost_hub_path =
      "/hub/children/" + FshostComponentCollection() + ":" + FshostComponentName();
  const std::string fshost_svc_path = fshost_hub_path + "/exec/out/svc/fuchsia.fshost.Admin";

  // Use the mount and umount binaries so that we get a full end-to-end test.
  constexpr const char* kMountBinPath = "/pkg/bin/mount";
  constexpr const char* kUmountBinPath = "/pkg/bin/umount";
  constexpr const char* kMountPath = "/mnt/test";

  zx::process mount_process;
  ASSERT_EQ(fdio_spawn(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, kMountBinPath,
                       (const char*[]){kMountBinPath, "--fshost-path", fshost_svc_path.c_str(),
                                       device_path.c_str(), kMountPath, nullptr},
                       mount_process.reset_and_get_address()),
            ZX_OK);

  int64_t return_code;
  Join(mount_process, &return_code);
  ASSERT_EQ(return_code, 0);

  const std::string file_path = fshost_hub_path + "/exec/out/mnt/test/hello";
  fbl::unique_fd fd(open(file_path.c_str(), O_RDWR | O_CREAT, 0666));
  ASSERT_TRUE(fd);
  ASSERT_EQ(write(fd.get(), "hello", 5), 5);
  fd.reset();

  // Check GetDevicePath.
  const std::string root = fshost_hub_path + "/exec/out/mnt/test/";
  struct statvfs buf;
  ASSERT_EQ(statvfs(root.c_str(), &buf), 0);

  auto fshost_or = service::Connect<fuchsia_fshost::Admin>(fshost_svc_path.c_str());
  ASSERT_EQ(fshost_or.status_value(), ZX_OK);

  auto result = fidl::WireCall(*fshost_or)->GetDevicePath(buf.f_fsid);
  ASSERT_TRUE(result.ok());

  ASSERT_TRUE(result->is_ok());
  EXPECT_EQ(result->value()->path.get(), device_path);

  zx::process umount_process;
  ASSERT_EQ(fdio_spawn(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, kUmountBinPath,
                       (const char*[]){kUmountBinPath, "--fshost-path", fshost_svc_path.c_str(),
                                       kMountPath, nullptr},
                       umount_process.reset_and_get_address()),
            ZX_OK);

  Join(umount_process, &return_code);
  ASSERT_EQ(return_code, 0);

  // The file should no longer exist.
  struct stat stat_buf;
  ASSERT_EQ(stat(file_path.c_str(), &stat_buf), -1);

  ASSERT_EQ(fdio_spawn(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, kMountBinPath,
                       (const char*[]){kMountBinPath, "--fshost-path", fshost_svc_path.c_str(),
                                       device_path.c_str(), kMountPath, nullptr},
                       mount_process.reset_and_get_address()),
            ZX_OK);

  Join(mount_process, &return_code);
  ASSERT_EQ(return_code, 0);

  // Check the contents of the file.
  fd.reset(open(file_path.c_str(), O_RDWR));
  ASSERT_TRUE(fd);
  char buffer[5];
  ASSERT_EQ(read(fd.get(), buffer, 5), 5);
  ASSERT_EQ(memcmp(buffer, "hello", 5), 0);

  ASSERT_EQ(fdio_spawn(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, kUmountBinPath,
                       (const char*[]){kUmountBinPath, "--fshost-path", fshost_svc_path.c_str(),
                                       kMountPath, nullptr},
                       umount_process.reset_and_get_address()),
            ZX_OK);

  Join(umount_process, &return_code);
  ASSERT_EQ(return_code, 0);
}

TEST_F(AdminServerTest, GetDevicePathForBuiltInFilesystem) {
  constexpr uint32_t kBlockCount = 9 * 1024 * 256;
  constexpr uint32_t kBlockSize = 512;
  constexpr uint32_t kSliceSize = 32'768;
  constexpr size_t kDeviceSize = kBlockCount * kBlockSize;

  const std::string fshost_hub_path =
      "/hub/children/" + FshostComponentCollection() + ":" + FshostComponentName();
  const std::string fshost_svc_path = fshost_hub_path + "/exec/out/svc/fuchsia.fshost.Admin";

  PauseWatcher();  // Pause whilst we create a ramdisk.

  // Create a ramdisk with an unformatted minfs partitition.
  zx::vmo vmo;
  ASSERT_EQ(zx::vmo::create(kDeviceSize, 0, &vmo), ZX_OK);

  // Create a child VMO so that we can keep hold of the original.
  zx::vmo child_vmo;
  ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_SLICE, 0, kDeviceSize, &child_vmo), ZX_OK);

  // Now create the ram-disk with a single FVM partition.
  {
    auto ramdisk_or = storage::RamDisk::CreateWithVmo(std::move(child_vmo), kBlockSize);
    ASSERT_EQ(ramdisk_or.status_value(), ZX_OK);
    storage::FvmOptions options{
        .name = kDataPartitionLabel,
        .type = std::array<uint8_t, BLOCK_GUID_LEN>{GUID_DATA_VALUE},
    };
    auto fvm_partition_or = storage::CreateFvmPartition(ramdisk_or->path(), kSliceSize, options);
    ASSERT_EQ(fvm_partition_or.status_value(), ZX_OK);
  }

  ResumeWatcher();

  // Now reattach the ram-disk and fshost should format it.
  auto ramdisk_or = storage::RamDisk::CreateWithVmo(std::move(vmo), kBlockSize);
  ASSERT_EQ(ramdisk_or.status_value(), ZX_OK);
  auto [fd, fs_type] = WaitForMount("minfs");
  ASSERT_TRUE(fd);
  EXPECT_TRUE(fs_type == VFS_TYPE_MINFS || fs_type == VFS_TYPE_FXFS);

  struct statvfs buf;
  ASSERT_EQ(fstatvfs(fd.get(), &buf), 0);

  auto fshost_or = service::Connect<fuchsia_fshost::Admin>(fshost_svc_path.c_str());
  ASSERT_EQ(fshost_or.status_value(), ZX_OK);

  // The device path is registered in fshost *after* the mount point shows up so this is racy.  It's
  // not worth fixing fshost since the device path is used for debugging/diagnostics, so we just
  // loop here.
  int attempts = 0;
  for (;;) {
    auto result = fidl::WireCall(*fshost_or)->GetDevicePath(buf.f_fsid);
    ASSERT_TRUE(result.ok());
    if (result.value().is_error()) {
      if (++attempts == 100)
        GTEST_FAIL() << "Timed out trying to get device path";
      usleep(100'000);
    } else {
      if (DataFilesystemFormat() == "fxfs") {
        // Fxfs doesn't use zxcrypt.
        EXPECT_EQ(result.value().value()->path.get(), ramdisk_or->path() + "/fvm/data-p-1/block");
      } else {
        EXPECT_EQ(result.value().value()->path.get(),
                  ramdisk_or->path() + "/fvm/data-p-1/block/zxcrypt/unsealed/block");
      }
      break;
    }
  }
}

}  // namespace
}  // namespace fshost
