// Copyright 2019 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 <fs-management/fvm.h>
#include <fs-management/mount.h>
#include <fvm/format.h>
#include <lib/devmgr-integration-test/fixture.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/vmo.h>
#include <ramdevice-client/ramdisk.h>
#include <unittest/unittest.h>

namespace {

using devmgr_integration_test::IsolatedDevmgr;

const uint32_t kBlockCount = 1024 * 256;
const uint32_t kBlockSize = 512;
const uint32_t kSliceSize = (1 << 20);
const size_t kDeviceSize = kBlockCount * kBlockSize;
const char* kDataName = "fs-recovery-data";
const char* kRamdiskPath = "misc/ramctl";

// Test fixture that builds a ramdisk and destroys it when destructed.
class FsRecoveryTest {
 public:
  // Create an IsolatedDevmgr that can load device drivers such as fvm,
  // zxcrypt, etc.
  bool Initialize() {
    BEGIN_HELPER;
    auto args = IsolatedDevmgr::DefaultArgs();
    args.disable_block_watcher = false;
    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");
    ASSERT_EQ(IsolatedDevmgr::Create(std::move(args), &devmgr_), ZX_OK);
    END_HELPER;
  }

  // Create a ram disk that is back by a VMO, which is formatted to look like
  // an FVM volume.
  bool CreateFvmRamdisk(size_t device_size, size_t block_size) {
    BEGIN_HELPER;

    // Calculate total size of data + metadata.
    device_size = fbl::round_up(device_size, fvm::kBlockSize);
    size_t old_meta = fvm::MetadataSize(device_size, fvm::kBlockSize);
    size_t new_meta = fvm::MetadataSize(old_meta + device_size, fvm::kBlockSize);
    while (old_meta != new_meta) {
      old_meta = new_meta;
      new_meta = fvm::MetadataSize(old_meta + device_size, fvm::kBlockSize);
    }
    device_size = device_size + (new_meta * 2);

    zx::vmo disk;
    ASSERT_EQ(zx::vmo::create(device_size, 0, &disk), ZX_OK);
    int fd = -1;
    ASSERT_EQ(fdio_fd_create(disk.get(), &fd), ZX_OK);
    ASSERT_GE(fd, 0);
    ASSERT_EQ(fvm_init_with_size(fd, device_size, kSliceSize), ZX_OK);

    fbl::unique_fd ramdisk;
    ASSERT_TRUE(WaitForDevice(kRamdiskPath, &ramdisk));

    ASSERT_EQ(ramdisk_create_at_from_vmo(devmgr_.devfs_root().get(), disk.get(), &ramdisk_client_),
              ZX_OK);
    END_HELPER;
  }

  // Create a partition in the FVM volume that has the data guid.
  bool CreateFvmPartition(char* fvm_block_path) {
    BEGIN_HELPER;

    char fvm_path[PATH_MAX];
    snprintf(fvm_path, PATH_MAX, "%s/fvm", ramdisk_get_path(ramdisk_client_));
    fbl::unique_fd fvm_fd;
    ASSERT_TRUE(WaitForDevice(fvm_path, &fvm_fd));

    // Allocate a FVM partition with the data guid but don't actually format the
    // partition.
    alloc_req_t req;
    memset(&req, 0, sizeof(alloc_req_t));
    req.slice_count = 1;
    static const uint8_t data_guid[GPT_GUID_LEN] = GUID_DATA_VALUE;
    memcpy(req.type, data_guid, GUID_LEN);
    snprintf(req.name, NAME_LEN, "%s", kDataName);

    fuchsia_hardware_block_partition_GUID type_guid;
    memcpy(type_guid.value, req.type, GUID_LEN);
    fuchsia_hardware_block_partition_GUID instance_guid;
    memcpy(instance_guid.value, req.guid, GUID_LEN);

    fzl::UnownedFdioCaller caller(fvm_fd.get());
    zx_status_t status;
    ASSERT_EQ(fuchsia_hardware_block_volume_VolumeManagerAllocatePartition(
                  caller.borrow_channel(), req.slice_count, &type_guid, &instance_guid, req.name,
                  NAME_LEN, req.flags, &status),
              ZX_OK);
    ASSERT_EQ(status, ZX_OK);

    snprintf(fvm_block_path, PATH_MAX, "%s/%s-p-1/block", fvm_path, kDataName);
    fbl::unique_fd fvm_block_fd;
    ASSERT_TRUE(WaitForDevice(fvm_block_path, &fvm_block_fd));

    END_HELPER;
  }

  // Wait for the device to be available and then check to make sure it is
  // formatted of the passed in type. Since formatting can take some time
  // after the device becomes available, we must recheck.
  bool WaitForDiskFormat(const char* path, disk_format_t format, zx::duration deadline) {
    fbl::unique_fd fd;
    if (!WaitForDevice(path, &fd)) {
      return false;
    }
    while (deadline.get() > 0) {
      fd.reset(openat(devmgr_.devfs_root().get(), path, O_RDONLY));
      if (detect_disk_format(fd.get()) == format)
        return true;
      sleep(1);
      deadline -= zx::duration(ZX_SEC(1));
    }
    return false;
  }

 private:
  bool WaitForDevice(const char* path, fbl::unique_fd* fd) {
    BEGIN_HELPER;
    printf("Wait for device %s\n", path);
    ASSERT_EQ(devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(), path, fd), ZX_OK);

    ASSERT_TRUE(*fd);
    END_HELPER;
  }

  ramdisk_client_t* ramdisk_client_;
  devmgr_integration_test::IsolatedDevmgr devmgr_;
};

bool EmptyPartitionRecoveryTest() {
  BEGIN_TEST;

  char fvm_block_path[PATH_MAX];
  fbl::unique_ptr<FsRecoveryTest> recovery(new FsRecoveryTest());
  ASSERT_TRUE(recovery->Initialize());
  // Creates an FVM partition under an isolated devmgr. It creates, but does
  // not properly format the data partition.
  ASSERT_TRUE(recovery->CreateFvmRamdisk(kDeviceSize, kBlockSize));
  ASSERT_TRUE(recovery->CreateFvmPartition(fvm_block_path));

  // We then expect the devmgr to self-recover, i.e., format the zxcrypt/data
  // partitions as expected from the FVM partition.

  // First, wait for the zxcrypt partition to be formatted.
  EXPECT_TRUE(
      recovery->WaitForDiskFormat(fvm_block_path, DISK_FORMAT_ZXCRYPT, zx::duration(ZX_SEC(3))));

  // Second, wait for the data partition to be formatted.
  char data_path[PATH_MAX];
  snprintf(data_path, sizeof(data_path), "%s/zxcrypt/unsealed/block", fvm_block_path);
  EXPECT_TRUE(recovery->WaitForDiskFormat(data_path, DISK_FORMAT_MINFS, zx::duration(ZX_SEC(3))));

  END_TEST;
}

BEGIN_TEST_CASE(FsRecoveryTest)
RUN_TEST(EmptyPartitionRecoveryTest)
END_TEST_CASE(FsRecoveryTest)

}  // namespace
