// Copyright 2017 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 <fidl/fuchsia.device/cpp/wire.h>
#include <fidl/fuchsia.hardware.block.partition/cpp/wire.h>
#include <fidl/fuchsia.hardware.block.volume/cpp/wire.h>
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fuchsia/hardware/block/driver/c/banjo.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/component/incoming/cpp/clone.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/device-watcher/cpp/device-watcher.h>
#include <lib/driver-integration-test/fixture.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/namespace.h>
#include <lib/fit/function.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/channel.h>
#include <lib/zx/fifo.h>
#include <lib/zx/vmo.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <threads.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <algorithm>
#include <climits>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
#include <ramdevice-client/ramdisk.h>
#include <zxtest/zxtest.h>

#include "lib/fidl/cpp/wire/internal/transport_channel.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/storage/blobfs/format.h"
#include "src/storage/fvm/format.h"
#include "src/storage/fvm/fvm_check.h"
#include "src/storage/lib/block_client/cpp/client.h"
#include "src/storage/lib/block_client/cpp/remote_block_device.h"
#include "src/storage/lib/fs_management/cpp/admin.h"
#include "src/storage/lib/fs_management/cpp/fvm.h"
#include "src/storage/lib/fs_management/cpp/mount.h"
#include "src/storage/minfs/format.h"

constexpr char kFvmDriverLib[] = "fvm.cm";
#define STRLEN(s) (sizeof(s) / sizeof((s)[0]))

namespace {

using VolumeManagerInfo = fuchsia_hardware_block_volume::wire::VolumeManagerInfo;

constexpr char kMountPath[] = "/test/minfs_test_mountpath";
constexpr char kTestDevPath[] = "/fake/dev";

// Returns the number of usable slices for a standard layout on a given-sized device.
size_t UsableSlicesCount(size_t disk_size, size_t slice_size) {
  return fvm::Header::FromDiskSize(fvm::kMaxUsablePartitions, disk_size, slice_size)
      .GetAllocationTableUsedEntryCount();
}

struct PartitionChannel {
  fidl::UnownedClientEnd<fuchsia_hardware_block::Block> as_block() {
    return fidl::UnownedClientEnd<fuchsia_hardware_block::Block>(partition.channel().borrow());
  }

  fidl::UnownedClientEnd<fuchsia_hardware_block_volume::Volume> as_volume() {
    return fidl::UnownedClientEnd<fuchsia_hardware_block_volume::Volume>(
        partition.channel().borrow());
  }

  static zx::result<PartitionChannel> Create(
      fidl::ClientEnd<fuchsia_device::Controller> controller) {
    PartitionChannel partition;
    partition.controller = std::move(controller);
    zx::result partition_server = fidl::CreateEndpoints(&partition.partition);
    if (partition_server.is_error()) {
      return partition_server.take_error();
    }
    if (fidl::OneWayStatus status = fidl::WireCall(partition.controller)
                                        ->ConnectToDeviceFidl(partition_server->TakeChannel());
        !status.ok()) {
      return zx::error(status.status());
    }
    return zx::ok(std::move(partition));
  }

  fidl::ClientEnd<fuchsia_device::Controller> controller;
  fidl::ClientEnd<fuchsia_hardware_block_partition::Partition> partition;
};

using driver_integration_test::IsolatedDevmgr;

class FvmTest : public zxtest::Test {
 protected:
  void SetUp() override {
    IsolatedDevmgr::Args args;
    args.disable_block_watcher = true;

    ASSERT_OK(IsolatedDevmgr::Create(&args, &devmgr_));
    ASSERT_OK(device_watcher::RecursiveWaitForFile(devfs_root_fd().get(),
                                                   "sys/platform/00:00:2d/ramctl"));

    fdio_ns_t* name_space;
    ASSERT_OK(fdio_ns_get_installed(&name_space));

    ASSERT_OK(fdio_ns_bind_fd(name_space, kTestDevPath, devmgr_.devfs_root().get()));
  }

  const fbl::unique_fd& devfs_root_fd() const { return devmgr_.devfs_root(); }

  zx::result<fidl::ClientEnd<fuchsia_io::Directory>> devfs_root() const {
    fdio_cpp::UnownedFdioCaller caller(devfs_root_fd());
    return component::Clone(caller.directory());
  }

  void TearDown() override {
    fdio_ns_t* name_space;
    ASSERT_OK(fdio_ns_get_installed(&name_space));
    ASSERT_OK(fdio_ns_unbind(name_space, kTestDevPath));
    ASSERT_OK(ramdisk_destroy(ramdisk_));
  }

  fbl::String fvm_path() const { return fxl::StringPrintf("%s/fvm", ramdisk_get_path(ramdisk_)); }

  zx::result<fbl::unique_fd> fvm_device_fd() const {
    fbl::unique_fd fd;
    zx_status_t status =
        fdio_open_fd_at(devfs_root_fd().get(), fvm_path().c_str(), 0, fd.reset_and_get_address());
    return zx::make_result(status, std::move(fd));
  }

  zx::result<fidl::ClientEnd<fuchsia_hardware_block_volume::VolumeManager>> fvm_device() const {
    zx::result devfs = devfs_root();
    if (devfs.is_error()) {
      return devfs.take_error();
    }
    return component::ConnectAt<fuchsia_hardware_block_volume::VolumeManager>(devfs.value(),
                                                                              fvm_path().c_str());
  }

  fidl::UnownedClientEnd<fuchsia_device::Controller> ramdisk_controller_interface() const {
    return fidl::UnownedClientEnd<fuchsia_device::Controller>(
        ramdisk_get_block_controller_interface(ramdisk_));
  }

  fidl::UnownedClientEnd<fuchsia_hardware_block::Block> ramdisk_block_interface() const {
    return fidl::UnownedClientEnd<fuchsia_hardware_block::Block>(
        ramdisk_get_block_interface(ramdisk_));
  }

  const ramdisk_client* ramdisk() const { return ramdisk_; }

  void FVMRebind();

  void CreateFVM(uint64_t block_size, uint64_t block_count, uint64_t slice_size);

  void CreateRamdisk(uint64_t block_size, uint64_t block_count);

  zx::result<PartitionChannel> OpenPartition(const fs_management::PartitionMatcher& matcher) const {
    zx::result controller =
        fs_management::OpenPartitionWithDevfs(devfs_root().value(), matcher, false);
    if (controller.is_error()) {
      return controller.take_error();
    }
    return PartitionChannel::Create(std::move(controller.value()));
  }

  zx::result<PartitionChannel> WaitForPartition(
      const fs_management::PartitionMatcher& matcher) const {
    zx::result controller =
        fs_management::OpenPartitionWithDevfs(devfs_root().value(), matcher, true);
    if (controller.is_error()) {
      return controller.take_error();
    }
    return PartitionChannel::Create(std::move(controller.value()));
  }

  struct AllocatePartitionRequest {
    size_t slice_count = 1;
    const uuid::Uuid& type;
    const uuid::Uuid& guid;
    const std::string_view& name;
    uint32_t flags = 0;
  };

  zx::result<PartitionChannel> AllocatePartition(AllocatePartitionRequest request) const {
    zx::result fvm = fvm_device();
    if (fvm.is_error()) {
      return fvm.take_error();
    }
    zx::result devfs = devfs_root();
    if (devfs.is_error()) {
      return devfs.take_error();
    }

    zx::result controller = fs_management::FvmAllocatePartitionWithDevfs(
        *devfs, *fvm, request.slice_count, request.type, request.guid, request.name, request.flags);
    if (controller.is_error()) {
      return controller.take_error();
    }
    return PartitionChannel::Create(std::move(controller.value()));
  }

 private:
  IsolatedDevmgr devmgr_;
  ramdisk_client_t* ramdisk_ = nullptr;
};

void FvmTest::CreateRamdisk(uint64_t block_size, uint64_t block_count) {
  if (ramdisk_ != nullptr) {
    ramdisk_destroy(ramdisk_);
  }
  ASSERT_OK(ramdisk_create_at(devfs_root_fd().get(), block_size, block_count, &ramdisk_));
}

void FvmTest::CreateFVM(uint64_t block_size, uint64_t block_count, uint64_t slice_size) {
  CreateRamdisk(block_size, block_count);

  ASSERT_OK(fs_management::FvmInitPreallocated(ramdisk_block_interface(), block_count * block_size,
                                               block_count * block_size, slice_size));

  auto resp = fidl::WireCall(ramdisk_controller_interface())->Bind(kFvmDriverLib);
  ASSERT_OK(resp.status());
  ASSERT_TRUE(resp->is_ok());

  ASSERT_OK(device_watcher::RecursiveWaitForFile(devfs_root_fd().get(), fvm_path().c_str()));
}

void FvmTest::FVMRebind() {
  auto resp = fidl::WireCall(ramdisk_controller_interface())->Rebind(kFvmDriverLib);
  ASSERT_OK(resp.status());
  ASSERT_TRUE(resp->is_ok());

  ASSERT_OK(device_watcher::RecursiveWaitForFile(devfs_root_fd().get(), fvm_path().c_str()));
}

void FVMCheckSliceSize(fidl::UnownedClientEnd<fuchsia_hardware_block_volume::VolumeManager> fvm,
                       size_t expected_slice_size) {
  auto volume_info_or = fs_management::FvmQuery(fvm);
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK, "Failed to query fvm\n");
  ASSERT_EQ(expected_slice_size, volume_info_or->slice_size, "Unexpected slice size\n");
}

void FVMCheckAllocatedCount(
    fidl::UnownedClientEnd<fuchsia_hardware_block_volume::VolumeManager> fvm,
    size_t expected_allocated, size_t expected_total) {
  auto volume_info_or = fs_management::FvmQuery(fvm);
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  ASSERT_EQ(volume_info_or->slice_count, expected_total);
  ASSERT_EQ(volume_info_or->assigned_slice_count, expected_allocated);
}

enum class ValidationResult {
  Valid,
  Corrupted,
};

void ValidateFVM(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device,
                 ValidationResult expected_result = ValidationResult::Valid) {
  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  fvm::Checker checker(device, block_info.block_size, true);
  switch (expected_result) {
    case ValidationResult::Valid:
      ASSERT_TRUE(checker.Validate());
      break;
    case ValidationResult::Corrupted:
      ASSERT_FALSE(checker.Validate());
      break;
  }
}

zx::result<std::string> GetPartitionPath(fidl::ClientEnd<fuchsia_device::Controller>& controller) {
  auto path = fidl::WireCall(controller)->GetTopologicalPath();
  if (!path.ok()) {
    return zx::error(path.status());
  }
  if (path->is_error()) {
    return zx::error(path->error_value());
  }
  // The partition doesn't know that the devmgr it's in is bound at "/fake".
  std::string topological_path = std::string("/fake") + path->value()->path.data();
  return zx::ok(std::move(topological_path));
}

/////////////////////// Helper functions, definitions

constexpr uuid::Uuid kTestUniqueGuid1 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
constexpr uuid::Uuid kTestUniqueGuid2 = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
                                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};

// Intentionally avoid aligning these GUIDs with
// the actual system GUIDs; otherwise, limited versions
// of Fuchsia may attempt to actually mount these
// partitions automatically.

constexpr std::string_view kTestPartDataName = "data";
constexpr uuid::Uuid kTestPartDataGuid = {
    0xAA, 0xFF, 0xBB, 0x00, 0x33, 0x44, 0x88, 0x99, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
};

constexpr std::string_view kTestPartBlobName = "blob";
constexpr uuid::Uuid kTestPartBlobGuid = {
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0xAA, 0xFF, 0xBB, 0x00, 0x33, 0x44, 0x88, 0x99,
};

constexpr std::string_view kTestPartSystemName = "system";
constexpr uuid::Uuid kTestPartSystemGuid = {
    0xEE, 0xFF, 0xBB, 0x00, 0x33, 0x44, 0x88, 0x99, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
};

const fs_management::PartitionMatcher kPartition1Matcher = {
    .type_guids = {kTestPartDataGuid},
    .instance_guids = {kTestUniqueGuid1},
};
const fs_management::PartitionMatcher kPartition2Matcher = {
    .type_guids = {kTestPartDataGuid},
    .instance_guids = {kTestUniqueGuid2},
};

class VmoBuf;

class VmoClient : public fbl::RefCounted<VmoClient> {
 public:
  explicit VmoClient(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device);
  ~VmoClient() = default;

  void CheckWrite(VmoBuf& vbuf, size_t buf_off, size_t dev_off, size_t len);
  void CheckRead(VmoBuf& vbuf, size_t buf_off, size_t dev_off, size_t len);
  void Transaction(block_fifo_request_t* requests, size_t count) {
    ASSERT_OK(client_->Transaction(requests, count));
  }
  zx::result<storage::OwnedVmoid> RegisterVmo(const zx::vmo& vmo) {
    return client_->RegisterVmo(vmo);
  }

  fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device() const { return device_; }

  static groupid_t group() { return 0; }

 private:
  const fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device_;
  uint32_t block_size_;
  std::unique_ptr<block_client::Client> client_;
};

class VmoBuf {
 public:
  VmoBuf(fbl::RefPtr<VmoClient> client, size_t size) : client_(std::move(client)) {
    buf_ = std::make_unique<uint8_t[]>(size);

    ASSERT_EQ(zx::vmo::create(size, 0, &vmo_), ZX_OK);
    zx::result vmoid = client_->RegisterVmo(vmo_);
    ASSERT_OK(vmoid);
    vmoid_ = std::move(vmoid.value());
  }

  ~VmoBuf() {
    if (vmo_.is_valid()) {
      block_fifo_request_t request = {
          .command = {.opcode = BLOCK_OPCODE_CLOSE_VMO, .flags = 0},
          .group = client_->group(),
          .vmoid = vmoid_.TakeId(),
      };
      client_->Transaction(&request, 1);
    }
  }

 private:
  friend VmoClient;

  fbl::RefPtr<VmoClient> client_;
  zx::vmo vmo_;
  std::unique_ptr<uint8_t[]> buf_;
  storage::OwnedVmoid vmoid_;
};

VmoClient::VmoClient(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device)
    : device_(device) {
  {
    const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    block_size_ = response.value()->info.block_size;
  }

  auto [session, server] = fidl::Endpoints<fuchsia_hardware_block::Session>::Create();

  const fidl::Status result = fidl::WireCall(device)->OpenSession(std::move(server));
  ASSERT_OK(result.status());

  const fidl::WireResult fifo_result = fidl::WireCall(session)->GetFifo();
  ASSERT_OK(fifo_result.status());
  const fit::result fifo_response = fifo_result.value();
  ASSERT_TRUE(fifo_response.is_ok(), "%s", zx_status_get_string(fifo_response.error_value()));

  client_ = std::make_unique<block_client::Client>(std::move(session),
                                                   std::move(fifo_response.value()->fifo));
}

void VmoClient::CheckWrite(VmoBuf& vbuf, size_t buf_off, size_t dev_off, size_t len) {
  // Write to the client-side buffer
  for (size_t i = 0; i < len; i++)
    vbuf.buf_[i + buf_off] = static_cast<uint8_t>(rand());

  // Write to the registered VMO
  ASSERT_EQ(vbuf.vmo_.write(&vbuf.buf_[buf_off], buf_off, len), ZX_OK);
  ASSERT_EQ(len % block_size_, 0);
  ASSERT_EQ(buf_off % block_size_, 0);
  ASSERT_EQ(dev_off % block_size_, 0);

  // Write to the block device
  block_fifo_request_t request = {
      .command = {.opcode = BLOCK_OPCODE_WRITE, .flags = 0},
      .group = group(),
      .vmoid = vbuf.vmoid_.get(),
      .length = static_cast<uint32_t>(len / block_size_),
      .vmo_offset = buf_off / block_size_,
      .dev_offset = dev_off / block_size_,
  };
  Transaction(&request, 1);
}

void VmoClient::CheckRead(VmoBuf& vbuf, size_t buf_off, size_t dev_off, size_t len) {
  // Create a comparison buffer
  fbl::AllocChecker ac;
  std::unique_ptr<uint8_t[]> out(new (&ac) uint8_t[len]);
  ASSERT_TRUE(ac.check());
  memset(out.get(), 0, len);

  ASSERT_EQ(len % block_size_, 0);
  ASSERT_EQ(buf_off % block_size_, 0);
  ASSERT_EQ(dev_off % block_size_, 0);

  // Read from the block device
  block_fifo_request_t request = {
      .command = {.opcode = BLOCK_OPCODE_READ, .flags = 0},
      .group = group(),
      .vmoid = vbuf.vmoid_.get(),
      .length = static_cast<uint32_t>(len / block_size_),
      .vmo_offset = buf_off / block_size_,
      .dev_offset = dev_off / block_size_,
  };
  Transaction(&request, 1);

  // Read from the registered VMO
  ASSERT_EQ(vbuf.vmo_.read(out.get(), buf_off, len), ZX_OK);

  ASSERT_EQ(memcmp(&vbuf.buf_[buf_off], out.get(), len), 0);
}

void CheckWrite(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device, size_t off,
                size_t len, uint8_t* buf) {
  for (size_t i = 0; i < len; i++) {
    buf[i] = static_cast<uint8_t>(rand());
  }
  ASSERT_OK(block_client::SingleWriteBytes(device, buf, len, off));
}

void CheckRead(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device, size_t off, size_t len,
               const uint8_t* in) {
  fbl::AllocChecker ac;
  std::unique_ptr<uint8_t[]> out(new (&ac) uint8_t[len]);
  ASSERT_TRUE(ac.check());
  memset(out.get(), 0, len);
  ASSERT_OK(block_client::SingleReadBytes(device, out.get(), len, off));
  ASSERT_EQ(memcmp(in, out.get(), len), 0);
}

void CheckWriteReadBlock(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device, size_t block,
                         size_t count) {
  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  size_t len = block_info.block_size * count;
  size_t off = block_info.block_size * block;
  std::unique_ptr<uint8_t[]> in(new uint8_t[len]);
  ASSERT_NO_FATAL_FAILURE(CheckWrite(device, off, len, in.get()));
  ASSERT_NO_FATAL_FAILURE(CheckRead(device, off, len, in.get()));
}

void CheckWriteReadBytesFifo(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device,
                             size_t off, size_t len) {
  std::unique_ptr<uint8_t[]> write_buf(new uint8_t[len]);
  memset(write_buf.get(), 0xa3, len);

  ASSERT_OK(block_client::SingleWriteBytes(device, write_buf.get(), len, off));
  std::unique_ptr<uint8_t[]> read_buf(new uint8_t[len]);
  memset(read_buf.get(), 0, len);
  ASSERT_OK(block_client::SingleReadBytes(device, read_buf.get(), len, off));
  EXPECT_EQ(memcmp(write_buf.get(), read_buf.get(), len), 0);
}

void CheckNoAccessBlock(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> device, size_t block,
                        size_t count) {
  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  size_t len = block_info.block_size * count;
  size_t off = block_info.block_size * block;
  std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
  for (size_t i = 0; i < len; i++) {
    buf[i] = static_cast<uint8_t>(rand());
  }
  ASSERT_STATUS(block_client::SingleWriteBytes(device, buf.get(), len, off), ZX_ERR_OUT_OF_RANGE);
  ASSERT_STATUS(block_client::SingleReadBytes(device, buf.get(), len, off), ZX_ERR_OUT_OF_RANGE);
}

void CheckDeadConnection(zx::channel& chan) {
  ASSERT_OK(chan.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time::infinite(), nullptr));
}

void Upgrade(fidl::UnownedClientEnd<fuchsia_hardware_block_volume::VolumeManager> fvm,
             const uuid::Uuid& old_guid, const uuid::Uuid& new_guid, zx_status_t status) {
  fuchsia_hardware_block_partition::wire::Guid old_guid_fidl;
  std::copy(old_guid.cbegin(), old_guid.cend(), old_guid_fidl.value.begin());
  fuchsia_hardware_block_partition::wire::Guid new_guid_fidl;
  std::copy(new_guid.cbegin(), new_guid.cend(), new_guid_fidl.value.begin());

  const fidl::WireResult result = fidl::WireCall(fvm)->Activate(old_guid_fidl, new_guid_fidl);
  ASSERT_OK(result.status());
  const fidl::WireResponse response = result.value();
  ASSERT_STATUS(response.status, status);
}

/////////////////////// Actual tests:

// Test initializing the FVM on a partition that is smaller than a slice
TEST_F(FvmTest, TestTooSmall) {
  uint64_t block_size = 512;
  uint64_t block_count = (1 << 15);

  CreateRamdisk(block_size, block_count);
  size_t slice_size = block_size * block_count;
  ASSERT_EQ(fs_management::FvmInit(ramdisk_block_interface(), slice_size), ZX_ERR_NO_SPACE);
  ValidateFVM(ramdisk_block_interface(), ValidationResult::Corrupted);
}

// Test initializing the FVM on a large partition, with metadata size > the max transfer size
TEST_F(FvmTest, TestLarge) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount{UINT64_C(8) * (1 << 20)};
  CreateRamdisk(kBlockSize, kBlockCount);

  constexpr size_t kSliceSize{static_cast<size_t>(16) * (1 << 10)};
  fvm::Header fvm_header =
      fvm::Header::FromDiskSize(fvm::kMaxUsablePartitions, kBlockSize * kBlockCount, kSliceSize);

  const fidl::WireResult result = fidl::WireCall(ramdisk_block_interface())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_LT(block_info.max_transfer_size, fvm_header.GetMetadataAllocatedBytes());

  ASSERT_EQ(fs_management::FvmInit(ramdisk_block_interface(), kSliceSize), ZX_OK);

  auto resp = fidl::WireCall(ramdisk_controller_interface())->Bind(kFvmDriverLib);
  ASSERT_OK(resp.status());
  ASSERT_TRUE(resp->is_ok());

  ASSERT_OK(device_watcher::RecursiveWaitForFile(devfs_root_fd().get(), fvm_path().c_str()));
  ValidateFVM(ramdisk_block_interface());
}

// Load and unload an empty FVM
TEST_F(FvmTest, TestEmpty) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  ValidateFVM(ramdisk_block_interface());
}

// Test allocating a single partition
TEST_F(FvmTest, TestAllocateOne) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // Allocate one VPart
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = std::move(vp_or.value());

  // Check that the name matches what we provided
  const fidl::WireResult result = fidl::WireCall(vp.partition)->GetName();
  ASSERT_OK(result.status());
  const fidl::WireResponse response = result.value();
  ASSERT_OK(response.status);
  ASSERT_STREQ(response.name.get(), kTestPartDataName.data());

  // Check that we can read from / write to it.
  CheckWriteReadBlock(vp.as_block(), 0, 1);

  // Try accessing the block again after closing / re-opening it.
  vp = {};
  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_EQ(vp_or.status_value(), ZX_OK, "Couldn't re-open Data VPart");
  vp = std::move(vp_or.value());
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  vp = {};

  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  ValidateFVM(ramdisk_block_interface());
}

// Test Reading and writing with RemoteBlockDevice helpers
TEST_F(FvmTest, TestReadWriteSingle) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // Allocate one VPart
  zx::result vp = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_OK(vp);

  // Check that we can read from / write to it.
  CheckWriteReadBytesFifo(vp->as_block(), 0, kBlockSize);
  // Check with an offset
  CheckWriteReadBytesFifo(vp->as_block(), kBlockSize * 7, kBlockSize * 4);
  vp = {};

  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  ValidateFVM(ramdisk_block_interface());
}

// Test allocating a collection of partitions
TEST_F(FvmTest, TestAllocateMany) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // Test allocation of multiple VPartitions
  zx::result data_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(data_or.status_value(), ZX_OK);
  PartitionChannel data = *std::move(data_or);

  zx::result blob_or = AllocatePartition({
      .type = kTestPartBlobGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartBlobName,
  });
  ASSERT_EQ(blob_or.status_value(), ZX_OK);
  PartitionChannel blob = *std::move(blob_or);

  zx::result sys_or = AllocatePartition({
      .type = kTestPartSystemGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartSystemName,
  });
  ASSERT_EQ(sys_or.status_value(), ZX_OK);
  PartitionChannel sys = *std::move(sys_or);

  CheckWriteReadBlock(data.as_block(), 0, 1);
  CheckWriteReadBlock(blob.as_block(), 0, 1);
  CheckWriteReadBlock(sys.as_block(), 0, 1);

  data = {};
  blob = {};
  sys = {};

  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  ValidateFVM(ramdisk_block_interface());
}

// Test allocating additional slices to a vpartition.
TEST_F(FvmTest, TestVPartitionExtend) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  size_t slice_size = volume_info_or->slice_size;
  constexpr uint64_t kDiskSize = kBlockSize * kBlockCount;
  size_t slices_total = UsableSlicesCount(kDiskSize, slice_size);
  size_t slices_left = slices_total;

  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  // Allocate one VPart
  size_t slice_count = 1;
  auto vp_or = AllocatePartition({
      .slice_count = slice_count,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK, "Couldn't open Volume");
  PartitionChannel vp = *std::move(vp_or);
  slices_left--;
  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  // Confirm that the disk reports the correct number of slices
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
  }

  // Try re-allocating an already allocated vslice
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(0, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
  }

  // Try again with a portion of the request which is unallocated
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(0, 2);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  // Allocate OBSCENELY too many slices
  {
    const fidl::WireResult result =
        fidl::WireCall(vp.as_volume())->Extend(slice_count, std::numeric_limits<uint64_t>::max());
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  // Allocate slices at a too-large offset
  {
    const fidl::WireResult result =
        fidl::WireCall(vp.as_volume())->Extend(std::numeric_limits<uint64_t>::max(), 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  // Attempt to allocate slightly too many slices
  {
    const fidl::WireResult result =
        fidl::WireCall(vp.as_volume())->Extend(slice_count, slices_left + 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_NO_SPACE);
  }

  // The number of free slices should be unchanged.
  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  // Allocate exactly the remaining number of slices
  {
    const fidl::WireResult result =
        fidl::WireCall(vp.as_volume())->Extend(slice_count, slices_left);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  slice_count += slices_left;
  slices_left = 0;
  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
  }

  // We can't allocate any more to this VPartition
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(slice_count, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_NO_SPACE);
  }

  // We can't allocate a new VPartition
  zx::result vp2_or = AllocatePartition({
      .type = kTestPartBlobGuid,
      .guid = kTestUniqueGuid2,
      .name = kTestPartBlobName,
  });
  ASSERT_NE(vp2_or.status_value(), ZX_OK, "Expected VPart allocation failure");

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test allocating very sparse VPartition
TEST_F(FvmTest, TestVPartitionExtendSparse) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = *std::move(vp_or);
  CheckWriteReadBlock(vp.as_block(), 0, 1);

  // Double check that we can access a block at this vslice address
  // (this isn't always possible; for certain slice sizes, blocks may be
  // allocatable / freeable, but not addressable).
  size_t bno = (fvm::kMaxVSlices - 1) * (kSliceSize / kBlockSize);
  ASSERT_EQ(bno / (kSliceSize / kBlockSize), (fvm::kMaxVSlices - 1), "bno overflowed");
  ASSERT_EQ((bno * kBlockSize) / kBlockSize, bno, "block access will overflow");

  // Try allocating at a location that's slightly too large
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(fvm::kMaxVSlices, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  // Try allocating at the largest offset
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(fvm::kMaxVSlices - 1, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  CheckWriteReadBlock(vp.as_block(), bno, 1);

  // Try freeing beyond largest offset
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(fvm::kMaxVSlices, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  CheckWriteReadBlock(vp.as_block(), bno, 1);

  // Try freeing at the largest offset
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(fvm::kMaxVSlices - 1, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  CheckNoAccessBlock(vp.as_block(), bno, 1);

  vp = {};
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  ValidateFVM(ramdisk_block_interface());
}

// Test removing slices from a VPartition.
TEST_F(FvmTest, TestVPartitionShrink) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  size_t slice_size = volume_info_or->slice_size;
  const size_t kDiskSize = kBlockSize * kBlockCount;
  size_t slices_total = UsableSlicesCount(kDiskSize, slice_size);
  size_t slices_left = slices_total;

  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  // Allocate one VPart
  size_t slice_count = 1;
  zx::result vp_or = AllocatePartition({
      .slice_count = slice_count,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK, "Couldn't open Volume");
  PartitionChannel vp = *std::move(vp_or);
  slices_left--;

  // Confirm that the disk reports the correct number of slices
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
    CheckWriteReadBlock(vp.as_block(), (slice_size / block_info.block_size) - 1, 1);
    CheckNoAccessBlock(vp.as_block(), (slice_size / block_info.block_size) - 1, 2);
    FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);
  }

  // Try shrinking the 0th vslice
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(0, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);
  }

  // Try no-op requests (length = 0).
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(1, 0);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(1, 0);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
  }

  // Try again with a portion of the request which is unallocated
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(1, 2);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_INVALID_ARGS);
  }
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
    FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);
  }

  // Allocate exactly the remaining number of slices
  {
    const fidl::WireResult result =
        fidl::WireCall(vp.as_volume())->Extend(slice_count, slices_left);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  slice_count += slices_left;
  slices_left = 0;

  {
    const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
    ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);
    CheckWriteReadBlock(vp.as_block(), (slice_size / block_info.block_size) - 1, 1);
    CheckWriteReadBlock(vp.as_block(), (slice_size / block_info.block_size) - 1, 2);
  }
  FVMCheckAllocatedCount(volume_manager.value(), slices_total - slices_left, slices_total);

  // We can't allocate any more to this VPartition
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(slice_count, 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_NO_SPACE);
  }

  // Try to shrink off the end (okay, since SOME of the slices are allocated)
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(1, slice_count + 3);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  FVMCheckAllocatedCount(volume_manager.value(), 1, slices_total);

  // The same request to shrink should now fail (NONE of the slices are
  // allocated)
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(1, slice_count - 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_STATUS(response.status, ZX_ERR_INVALID_ARGS);
  }
  FVMCheckAllocatedCount(volume_manager.value(), 1, slices_total);

  // ... unless we re-allocate and try again.
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(1, slice_count - 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(1, slice_count - 1);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test splitting a contiguous slice extent into multiple parts
TEST_F(FvmTest, TestVPartitionSplit) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  size_t slice_size = volume_info_or->slice_size;

  // Allocate one VPart
  size_t slice_count = 5;
  zx::result vp_or = AllocatePartition({
      .slice_count = slice_count,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = *std::move(vp_or);

  // Confirm that the disk reports the correct number of slices
  const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * slice_count);

  size_t reset_offset = 1;
  size_t reset_length = slice_count - 1;
  size_t mid_offset = 2;
  size_t mid_length = 1;
  size_t start_offset = 1;
  size_t start_length = 1;
  size_t end_offset = 3;
  size_t end_length = slice_count - 3;

  auto verifyExtents = [&](bool start, bool mid, bool end) {
    size_t start_block = start_offset * (slice_size / block_info.block_size);
    size_t mid_block = mid_offset * (slice_size / block_info.block_size);
    size_t end_block = end_offset * (slice_size / block_info.block_size);

    if (start) {
      CheckWriteReadBlock(vp.as_block(), start_block, 1);
    } else {
      CheckNoAccessBlock(vp.as_block(), start_block, 1);
    }
    if (mid) {
      CheckWriteReadBlock(vp.as_block(), mid_block, 1);
    } else {
      CheckNoAccessBlock(vp.as_block(), mid_block, 1);
    }
    if (end) {
      CheckWriteReadBlock(vp.as_block(), end_block, 1);
    } else {
      CheckNoAccessBlock(vp.as_block(), end_block, 1);
    }
    return true;
  };

  auto doExtend = [&vp](size_t offset, size_t length) {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  };

  auto doShrink = [&vp](size_t offset, size_t length) {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Shrink(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  };

  // We should be able to split the extent.
  verifyExtents(true, true, true);
  doShrink(mid_offset, mid_length);
  verifyExtents(true, false, true);
  doShrink(start_offset, start_length);
  verifyExtents(false, false, true);
  doShrink(end_offset, end_length);
  verifyExtents(false, false, false);

  doExtend(reset_offset, reset_length);

  doShrink(start_offset, start_length);
  verifyExtents(false, true, true);
  doShrink(mid_offset, mid_length);
  verifyExtents(false, false, true);
  doShrink(end_offset, end_length);
  verifyExtents(false, false, false);

  doExtend(reset_offset, reset_length);

  doShrink(end_offset, end_length);
  verifyExtents(true, true, false);
  doShrink(mid_offset, mid_length);
  verifyExtents(true, false, false);
  doShrink(start_offset, start_length);
  verifyExtents(false, false, false);

  doExtend(reset_offset, reset_length);

  doShrink(end_offset, end_length);
  verifyExtents(true, true, false);
  doShrink(start_offset, start_length);
  verifyExtents(false, true, false);
  doShrink(mid_offset, mid_length);
  verifyExtents(false, false, false);

  // We should also be able to combine extents
  doExtend(mid_offset, mid_length);
  verifyExtents(false, true, false);
  doExtend(start_offset, start_length);
  verifyExtents(true, true, false);
  doExtend(end_offset, end_length);
  verifyExtents(true, true, true);

  doShrink(reset_offset, reset_length);

  doExtend(end_offset, end_length);
  verifyExtents(false, false, true);
  doExtend(mid_offset, mid_length);
  verifyExtents(false, true, true);
  doExtend(start_offset, start_length);
  verifyExtents(true, true, true);

  doShrink(reset_offset, reset_length);

  doExtend(end_offset, end_length);
  verifyExtents(false, false, true);
  doExtend(start_offset, start_length);
  verifyExtents(true, false, true);
  doExtend(mid_offset, mid_length);
  verifyExtents(true, true, true);

  vp = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test removing VPartitions within an FVM
TEST_F(FvmTest, TestVPartitionDestroy) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  // Test allocation of multiple VPartitions
  zx::result data_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(data_or.status_value(), ZX_OK);
  PartitionChannel data = *std::move(data_or);

  zx::result blob_or = AllocatePartition({
      .type = kTestPartBlobGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartBlobName,
  });
  ASSERT_EQ(blob_or.status_value(), ZX_OK);
  PartitionChannel blob = *std::move(blob_or);

  zx::result sys_or = AllocatePartition({
      .type = kTestPartSystemGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartSystemName,
  });
  ASSERT_EQ(sys_or.status_value(), ZX_OK);
  PartitionChannel sys = *std::move(sys_or);

  // We can access all three...
  CheckWriteReadBlock(data.as_block(), 0, 1);
  CheckWriteReadBlock(blob.as_block(), 0, 1);
  CheckWriteReadBlock(sys.as_block(), 0, 1);

  // But not after we destroy the blob partition.
  {
    const fidl::WireResult result = fidl::WireCall(blob.as_volume())->Destroy();
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  CheckWriteReadBlock(data.as_block(), 0, 1);
  CheckWriteReadBlock(sys.as_block(), 0, 1);
  CheckDeadConnection(blob.partition.channel());

  // Destroy the other two VPartitions.
  {
    const fidl::WireResult result = fidl::WireCall(data.as_volume())->Destroy();
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  CheckWriteReadBlock(sys.as_block(), 0, 1);
  CheckDeadConnection(data.partition.channel());

  {
    const fidl::WireResult result = fidl::WireCall(sys.as_volume())->Destroy();
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  CheckDeadConnection(sys.partition.channel());

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

TEST_F(FvmTest, TestVPartitionQuery) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  // Allocate partition
  zx::result part_or = AllocatePartition({
      .slice_count = 10,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(part_or.status_value(), ZX_OK);
  PartitionChannel part = *std::move(part_or);

  // Create non-contiguous extent.
  uint64_t offset = 20;
  uint64_t length = 10;
  {
    const fidl::WireResult result = fidl::WireCall(part.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);

  // Query various vslice ranges
  uint64_t start_slices[6];
  start_slices[0] = 0;
  start_slices[1] = 10;
  start_slices[2] = 20;
  start_slices[3] = 50;
  start_slices[4] = 25;
  start_slices[5] = 15;

  // Check response from partition query
  {
    const fidl::WireResult result =
        fidl::WireCall(part.as_volume())
            ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(start_slices));
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
    fidl::Array ranges = response.response;

    ASSERT_EQ(response.response_count, std::size(start_slices));
    ASSERT_TRUE(ranges[0].allocated);
    ASSERT_EQ(ranges[0].count, 10);
    ASSERT_FALSE(ranges[1].allocated);
    ASSERT_EQ(ranges[1].count, 10);
    ASSERT_TRUE(ranges[2].allocated);
    ASSERT_EQ(ranges[2].count, 10);
    ASSERT_FALSE(ranges[3].allocated);
    ASSERT_EQ(ranges[3].count, volume_info_or->max_virtual_slice - 50);
    ASSERT_TRUE(ranges[4].allocated);
    ASSERT_EQ(ranges[4].count, 5);
    ASSERT_FALSE(ranges[5].allocated);
    ASSERT_EQ(ranges[5].count, 5);
  }

  // Merge the extents!
  offset = 10;
  length = 10;
  {
    const fidl::WireResult result = fidl::WireCall(part.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }

  // Check partition query response again after extend
  {
    const fidl::WireResult result =
        fidl::WireCall(part.as_volume())
            ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(start_slices));
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
    fidl::Array ranges = response.response;

    ASSERT_EQ(response.response_count, std::size(start_slices));
    ASSERT_TRUE(ranges[0].allocated);
    ASSERT_EQ(ranges[0].count, 30);
    ASSERT_TRUE(ranges[1].allocated);
    ASSERT_EQ(ranges[1].count, 20);
    ASSERT_TRUE(ranges[2].allocated);
    ASSERT_EQ(ranges[2].count, 10);
    ASSERT_FALSE(ranges[3].allocated);
    ASSERT_EQ(ranges[3].count, volume_info_or->max_virtual_slice - 50);
    ASSERT_TRUE(ranges[4].allocated);
    ASSERT_EQ(ranges[4].count, 5);
    ASSERT_TRUE(ranges[5].allocated);
    ASSERT_EQ(ranges[5].count, 15);
  }

  start_slices[0] = volume_info_or->max_virtual_slice + 1;
  const fidl::WireResult result =
      fidl::WireCall(part.as_volume())
          ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(start_slices));
  ASSERT_OK(result.status());
  const fidl::WireResponse response = result.value();
  ASSERT_STATUS(response.status, ZX_ERR_OUT_OF_RANGE);

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

// Test allocating and accessing slices which are allocated contiguously.
TEST_F(FvmTest, TestSliceAccessContiguous) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  size_t slice_size = volume_info_or->slice_size;

  // Allocate one VPart
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = *std::move(vp_or);
  fidl::UnownedClientEnd device = vp.as_block();

  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;

  // This is the last 'accessible' block.
  size_t last_block = (slice_size / block_info.block_size) - 1;

  {
    auto vc = fbl::MakeRefCounted<VmoClient>(device);
    VmoBuf vb(vc, block_info.block_size * static_cast<size_t>(2));
    vc->CheckWrite(vb, 0, block_info.block_size * last_block, block_info.block_size);
    vc->CheckRead(vb, 0, block_info.block_size * last_block, block_info.block_size);

    // Try writing out of bounds -- check that we don't have access.
    CheckNoAccessBlock(device, (slice_size / block_info.block_size) - 1, 2);
    CheckNoAccessBlock(device, slice_size / block_info.block_size, 1);

    // Attempt to access the next contiguous slice
    {
      const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(1, 1);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // Now we can access the next slice...
    vc->CheckWrite(vb, block_info.block_size, block_info.block_size * (last_block + 1),
                   block_info.block_size);
    vc->CheckRead(vb, block_info.block_size, block_info.block_size * (last_block + 1),
                  block_info.block_size);
    // ... We can still access the previous slice...
    vc->CheckRead(vb, 0, block_info.block_size * last_block, block_info.block_size);
    // ... And we can cross slices
    vc->CheckRead(vb, 0, block_info.block_size * last_block,
                  block_info.block_size * static_cast<size_t>(2));
  }

  vp = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

// Test allocating and accessing multiple (3+) slices at once.
TEST_F(FvmTest, TestSliceAccessMany) {
  // The size of a slice must be carefully constructed for this test
  // so that we can hold multiple slices in memory without worrying
  // about hitting resource limits.
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 20;
  constexpr uint64_t kBlocksPerSlice = 256;
  constexpr uint64_t kSliceSize = kBlocksPerSlice * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  ASSERT_EQ(volume_info_or->slice_size, kSliceSize);

  // Allocate one VPart
  auto vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = *std::move(vp_or);

  fidl::UnownedClientEnd device = vp.as_block();

  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_EQ(block_info.block_size, kBlockSize);

  {
    auto vc = fbl::MakeRefCounted<VmoClient>(device);
    VmoBuf vb(vc, kSliceSize * 3);

    // Access the first slice
    vc->CheckWrite(vb, 0, 0, kSliceSize);
    vc->CheckRead(vb, 0, 0, kSliceSize);

    // Try writing out of bounds -- check that we don't have access.
    CheckNoAccessBlock(device, kBlocksPerSlice - 1, 2);
    CheckNoAccessBlock(device, kBlocksPerSlice, 1);

    // Attempt to access the next contiguous slices
    uint64_t offset = 1;
    uint64_t length = 2;
    {
      const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // Now we can access the next slices...
    vc->CheckWrite(vb, kSliceSize, kSliceSize, 2 * kSliceSize);
    vc->CheckRead(vb, kSliceSize, kSliceSize, 2 * kSliceSize);
    // ... We can still access the previous slice...
    vc->CheckRead(vb, 0, 0, kSliceSize);
    // ... And we can cross slices for reading.
    vc->CheckRead(vb, 0, 0, 3 * kSliceSize);

    // Also, we can cross slices for writing.
    vc->CheckWrite(vb, 0, 0, 3 * kSliceSize);
    vc->CheckRead(vb, 0, 0, 3 * kSliceSize);

    // Additionally, we can access "parts" of slices in a multi-slice
    // operation. Here, read one block into the first slice, and read
    // up to the last block in the final slice.
    vc->CheckWrite(vb, 0, kBlockSize, 3 * kSliceSize - 2 * kBlockSize);
    vc->CheckRead(vb, 0, kBlockSize, 3 * kSliceSize - 2 * kBlockSize);
  }

  vp = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test allocating and accessing slices which are allocated
// virtually contiguously (they appear sequential to the client) but are
// actually noncontiguous on the FVM partition.
TEST_F(FvmTest, TestSliceAccessNonContiguousPhysical) {
  constexpr uint64_t kBlockSize{512};
  constexpr uint64_t kBlockCount{1 << 16};
  constexpr uint64_t kSliceSize{kBlockSize * 64};
  constexpr uint64_t kDiskSize{kBlockSize * kBlockCount};
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  ASSERT_EQ(fs_management::FvmQuery(volume_manager.value()).status_value(), ZX_OK);

  constexpr size_t kNumVParts = 3;
  constexpr size_t kSliceCount = 1;
  typedef struct vdata {
    PartitionChannel partition;
    const uuid::Uuid& guid;
    const std::string_view& name;
    size_t slices_used;
  } vdata_t;

  vdata_t vparts[kNumVParts] = {
      {{}, kTestPartDataGuid, kTestPartDataName, kSliceCount},
      {{}, kTestPartBlobGuid, kTestPartBlobName, kSliceCount},
      {{}, kTestPartSystemGuid, kTestPartSystemName, kSliceCount},
  };

  for (auto& vpart : vparts) {
    zx::result part_or = AllocatePartition({
        .slice_count = kSliceCount,
        .type = vpart.guid,
        .guid = kTestUniqueGuid1,
        .name = vpart.name,
    });
    ASSERT_EQ(part_or.status_value(), ZX_OK);
    vpart.partition = *std::move(part_or);
  }

  const fidl::WireResult result = fidl::WireCall(vparts[0].partition.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;

  size_t usable_slices_per_vpart = UsableSlicesCount(kDiskSize, kSliceSize) / kNumVParts;
  size_t i = 0;
  while (vparts[i].slices_used < usable_slices_per_vpart) {
    // This is the last 'accessible' block.
    size_t last_block = (vparts[i].slices_used * (kSliceSize / block_info.block_size)) - 1;

    auto vc = fbl::MakeRefCounted<VmoClient>(vparts[i].partition.as_block());
    VmoBuf vb(vc, block_info.block_size * static_cast<size_t>(2));

    vc->CheckWrite(vb, 0, block_info.block_size * last_block, block_info.block_size);
    vc->CheckRead(vb, 0, block_info.block_size * last_block, block_info.block_size);

    // Try writing out of bounds -- check that we don't have access.
    CheckNoAccessBlock(vparts[i].partition.as_block(), last_block, 2);
    CheckNoAccessBlock(vparts[i].partition.as_block(), last_block + 1, 1);

    // Attempt to access the next contiguous slice
    uint64_t offset = vparts[i].slices_used;
    uint64_t length = 1;
    {
      const fidl::WireResult result =
          fidl::WireCall(vparts[i].partition.as_volume())->Extend(offset, length);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // Now we can access the next slice...
    vc->CheckWrite(vb, block_info.block_size, block_info.block_size * (last_block + 1),
                   block_info.block_size);
    vc->CheckRead(vb, block_info.block_size, block_info.block_size * (last_block + 1),
                  block_info.block_size);
    // ... We can still access the previous slice...
    vc->CheckRead(vb, 0, block_info.block_size * last_block, block_info.block_size);
    // ... And we can cross slices
    vc->CheckRead(vb, 0, block_info.block_size * last_block,
                  block_info.block_size * static_cast<size_t>(2));

    vparts[i].slices_used++;
    i = (i + 1) % kNumVParts;
  }

  for (size_t i = 0; i < kNumVParts; i++) {
    printf("Testing multi-slice operations on vslice %lu\n", i);

    // We need at least five slices, so we can access three "middle"
    // slices and jitter to test off-by-one errors.
    ASSERT_GE(vparts[i].slices_used, 5);

    {
      auto vc = fbl::MakeRefCounted<VmoClient>(vparts[i].partition.as_block());
      VmoBuf vb(vc, kSliceSize * 4);

      // Try accessing 3 noncontiguous slices at once, with the
      // addition of "off by one block".
      size_t dev_off_start = kSliceSize - block_info.block_size;
      size_t dev_off_end = kSliceSize + block_info.block_size;
      size_t len_start = kSliceSize * 3 - block_info.block_size;
      size_t len_end = kSliceSize * 3 + block_info.block_size;

      // Test a variety of:
      // Starting device offsets,
      size_t bsz = block_info.block_size;
      for (size_t dev_off = dev_off_start; dev_off <= dev_off_end; dev_off += bsz) {
        printf("  Testing non-contiguous write/read starting at offset: %zu\n", dev_off);
        // Operation lengths,
        for (size_t len = len_start; len <= len_end; len += bsz) {
          printf("    Testing operation of length: %zu\n", len);
          // and starting VMO offsets
          for (size_t vmo_off = 0; vmo_off < 3 * bsz; vmo_off += bsz) {
            // Try writing & reading the entire section (multiple
            // slices) at once.
            vc->CheckWrite(vb, vmo_off, dev_off, len);
            vc->CheckRead(vb, vmo_off, dev_off, len);

            // Try reading the section one slice at a time.
            // The results should be the same.
            size_t sub_off = 0;
            size_t sub_len = kSliceSize - (dev_off % kSliceSize);
            while (sub_off < len) {
              vc->CheckRead(vb, vmo_off + sub_off, dev_off + sub_off, sub_len);
              sub_off += sub_len;
              sub_len = std::min(kSliceSize, len - sub_off);
            }
          }
        }
      }
    }
    vparts[i].partition = {};
  }

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test allocating and accessing slices which are
// allocated noncontiguously from the client's perspective.
TEST_F(FvmTest, TestSliceAccessNonContiguousVirtual) {
  constexpr uint64_t kBlockSize{512};
  constexpr uint64_t kBlockCount{1 << 20};
  constexpr uint64_t kSliceSize{UINT64_C(64) * (1 << 20)};
  constexpr uint64_t kDiskSize{kBlockSize * kBlockCount};
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  ASSERT_EQ(fs_management::FvmQuery(volume_manager.value()).status_value(), ZX_OK);

  constexpr size_t kNumVParts = 3;
  constexpr size_t kSliceCount = 1;
  typedef struct vdata {
    PartitionChannel partition;
    const uuid::Uuid& guid;
    const std::string_view& name;
    size_t slices_used;
    size_t last_slice;
  } vdata_t;

  vdata_t vparts[kNumVParts] = {
      {{}, kTestPartDataGuid, kTestPartDataName, kSliceCount, kSliceCount},
      {{}, kTestPartBlobGuid, kTestPartBlobName, kSliceCount, kSliceCount},
      {{}, kTestPartSystemGuid, kTestPartSystemName, kSliceCount, kSliceCount},
  };

  for (auto& vpart : vparts) {
    zx::result part_or = AllocatePartition({
        .slice_count = kSliceCount,
        .type = vpart.guid,
        .guid = kTestUniqueGuid1,
        .name = vpart.name,
    });
    ASSERT_EQ(part_or.status_value(), ZX_OK);
    vpart.partition = *std::move(part_or);
  }

  const fidl::WireResult result = fidl::WireCall(vparts[0].partition.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;

  size_t usable_slices_per_vpart = UsableSlicesCount(kDiskSize, kSliceSize) / kNumVParts;
  size_t i = 0;
  while (vparts[i].slices_used < usable_slices_per_vpart) {
    fidl::UnownedClientEnd device = vparts[i].partition.as_block();
    // This is the last 'accessible' block.
    size_t last_block = (vparts[i].last_slice * (kSliceSize / block_info.block_size)) - 1;
    CheckWriteReadBlock(device, last_block, 1);

    // Try writing out of bounds -- check that we don't have access.
    CheckNoAccessBlock(device, last_block, 2);
    CheckNoAccessBlock(device, last_block + 1, 1);

    // Attempt to access a non-contiguous slice
    uint64_t offset = vparts[i].last_slice + 2;
    uint64_t length = 1;
    {
      const fidl::WireResult result =
          fidl::WireCall(vparts[i].partition.as_volume())->Extend(offset, length);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // We still don't have access to the next slice...
    CheckNoAccessBlock(device, last_block, 2);
    CheckNoAccessBlock(device, last_block + 1, 1);

    // But we have access to the slice we asked for!
    size_t requested_block = (offset * kSliceSize) / block_info.block_size;
    CheckWriteReadBlock(device, requested_block, 1);

    vparts[i].slices_used++;
    vparts[i].last_slice = offset;
    i = (i + 1) % kNumVParts;
  }

  for (vdata_t& vpart : vparts) {
    vpart.partition = {};
  }

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
    ValidateFVM(ramdisk_block_interface());
  }
}

// Test that the FVM driver actually persists updates.
TEST_F(FvmTest, TestPersistenceSimple) {
  constexpr uint64_t kBlockSize{512};
  constexpr uint64_t kBlockCount{1 << 20};
  constexpr uint64_t kSliceSize{UINT64_C(64) * (1 << 20)};
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  constexpr uint64_t kDiskSize = kBlockSize * kBlockCount;
  size_t slices_left = UsableSlicesCount(kDiskSize, kSliceSize);
  const uint64_t kSliceCount = slices_left;

  ASSERT_EQ(fs_management::FvmQuery(volume_manager.value()).status_value(), ZX_OK);

  // Allocate one VPart
  auto vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp = *std::move(vp_or);
  slices_left--;

  fidl::UnownedClientEnd device = vp.as_block();

  // Check that the name matches what we provided
  {
    const fidl::WireResult result = fidl::WireCall(vp.partition)->GetName();
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
    ASSERT_STREQ(response.name.get(), kTestPartDataName.data());
  }

  fuchsia_hardware_block::wire::BlockInfo block_info;
  {
    const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    block_info = response.value()->info;
  }
  std::unique_ptr<uint8_t[]> buf(new uint8_t[block_info.block_size * static_cast<size_t>(2)]);

  // Check that we can read from / write to it
  CheckWrite(device, 0, block_info.block_size, buf.get());
  CheckRead(device, 0, block_info.block_size, buf.get());
  vp = {};

  // Check that it still exists after rebinding the driver
  FVMRebind();
  volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_OK(vp_or.status_value());
  vp = *std::move(vp_or);
  device = vp.as_block();

  CheckRead(device, 0, block_info.block_size, buf.get());

  // Try extending the vpartition, and checking that the extension persists.
  // This is the last 'accessible' block.
  size_t last_block = (kSliceSize / block_info.block_size) - 1;
  CheckWrite(device, block_info.block_size * last_block, block_info.block_size, buf.get());
  CheckRead(device, block_info.block_size * last_block, block_info.block_size, buf.get());

  // Try writing out of bounds -- check that we don't have access.
  CheckNoAccessBlock(vp.as_block(), (kSliceSize / block_info.block_size) - 1, 2);
  CheckNoAccessBlock(vp.as_block(), kSliceSize / block_info.block_size, 1);

  uint64_t offset = 1;
  uint64_t length = 1;
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  slices_left--;

  vp = {};
  // FVMRebind will cause the rebind on ramdisk block device. The fvm device is child device
  // to ramdisk block device. Before issuing rebind make sure the fd is released.
  // Rebind the FVM driver, check the extension has succeeded.
  FVMRebind();
  volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_OK(vp_or.status_value());
  vp = *std::move(vp_or);
  device = vp.as_block();

  // Now we can access the next slice...
  CheckWrite(device, block_info.block_size * (last_block + 1), block_info.block_size,
             &buf[block_info.block_size]);
  CheckRead(device, block_info.block_size * (last_block + 1), block_info.block_size,
            &buf[block_info.block_size]);
  // ... We can still access the previous slice...
  CheckRead(device, block_info.block_size * last_block, block_info.block_size, buf.get());
  // ... And we can cross slices
  CheckRead(device, block_info.block_size * last_block,
            block_info.block_size * static_cast<size_t>(2), buf.get());

  // Try allocating the rest of the slices, rebinding, and ensuring
  // that the size stays updated.
  {
    const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    block_info = response.value()->info;
  }
  ASSERT_EQ(block_info.block_count * block_info.block_size, kSliceSize * 2);

  offset = 2;
  length = slices_left;
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  {
    const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    block_info = response.value()->info;
  }
  ASSERT_EQ(block_info.block_count * block_info.block_size, kSliceSize * kSliceCount);

  vp = {};
  FVMRebind();
  volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_OK(vp_or.status_value());
  vp = *std::move(vp_or);
  device = vp.as_block();

  {
    const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
    ASSERT_OK(result.status());
    const fit::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    block_info = response.value()->info;
  }
  ASSERT_EQ(block_info.block_count * block_info.block_size, kSliceSize * kSliceCount);

  vp = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), 64lu * (1 << 20));
  }
}

void CorruptMountHelper(const fbl::unique_fd& devfs_root, const char* partition_path,
                        const fs_management::MountOptions& mounting_options,
                        fs_management::DiskFormat disk_format, const size_t* vslice_start,
                        size_t vslice_count) {
  fdio_cpp::UnownedFdioCaller devfs_caller(devfs_root.get());
  auto component = fs_management::FsComponent::FromDiskFormat(disk_format);
  // Format the VPart as |disk_format|.
  ASSERT_EQ(fs_management::Mkfs(partition_path, component, {}), ZX_OK);

  fuchsia_hardware_block_volume::wire::VsliceRange
      initial_ranges[fuchsia_hardware_block_volume::wire::kMaxSliceRequests];

  // Check initial slice allocation.
  {
    zx::result controller =
        fs_management::OpenPartitionWithDevfs(devfs_caller.directory(), kPartition1Matcher, true);
    ASSERT_OK(controller);
    zx::result vp = PartitionChannel::Create(std::move(controller.value()));
    ASSERT_OK(vp);

    const fidl::WireResult result = fidl::WireCall(vp->as_volume())
                                        ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(
                                            const_cast<size_t*>(vslice_start), vslice_count));
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
    ASSERT_EQ(vslice_count, response.response_count);

    for (unsigned i = 0; i < response.response_count; i++) {
      ASSERT_TRUE(response.response[i].allocated);
      ASSERT_GT(response.response[i].count, 0);
      initial_ranges[i] = response.response[i];
    }

    // Manually shrink slices so FVM will differ from the partition.
    uint64_t offset = vslice_start[0] + response.response[0].count - 1;
    uint64_t length = 1;
    {
      const fidl::WireResult result = fidl::WireCall(vp->as_volume())->Shrink(offset, length);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // Check slice allocation after manual grow/shrink
    {
      const fidl::WireResult result = fidl::WireCall(vp->as_volume())
                                          ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(
                                              const_cast<size_t*>(vslice_start), vslice_count));
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
      ASSERT_EQ(vslice_count, response.response_count);
      ASSERT_FALSE(response.response[0].allocated);
      ASSERT_EQ(response.response[0].count, vslice_start[1] - vslice_start[0]);
    }

    // Try to mount the VPart. Since this mount call is supposed to fail, we wait for the spawned
    // fs process to finish and associated fidl channels to close before continuing to try and
    // prevent race conditions with the later mount call.
    fidl::ClientEnd device =
        fidl::ClientEnd<fuchsia_hardware_block::Block>(vp->partition.TakeChannel());
    ASSERT_NE(fs_management::Mount(std::move(device), component, mounting_options).status_value(),
              ZX_OK);

    // We can't reuse the component.
    component = fs_management::FsComponent::FromDiskFormat(disk_format);
  }

  {
    zx::result controller =
        fs_management::OpenPartitionWithDevfs(devfs_caller.directory(), kPartition1Matcher, true);
    ASSERT_OK(controller);
    zx::result vp = PartitionChannel::Create(std::move(controller.value()));
    ASSERT_OK(vp);

    // Grow back the slice we shrunk earlier.
    uint64_t offset = vslice_start[0];
    uint64_t length = 1;
    {
      const fidl::WireResult result = fidl::WireCall(vp->as_volume())->Extend(offset, length);
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
    }

    // Verify grow was successful.
    const fidl::WireResult result = fidl::WireCall(vp->as_volume())
                                        ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(
                                            const_cast<size_t*>(vslice_start), vslice_count));
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
    ASSERT_EQ(vslice_count, response.response_count);
    ASSERT_TRUE(response.response[0].allocated);
    ASSERT_EQ(response.response[0].count, 1);

    // Now extend all extents by some number of additional slices.
    fuchsia_hardware_block_volume::wire::VsliceRange
        ranges_before_extend[fuchsia_hardware_block_volume::wire::kMaxSliceRequests];
    for (unsigned i = 0; i < vslice_count; i++) {
      ranges_before_extend[i] = response.response[i];
      uint64_t offset = vslice_start[i] + response.response[i].count;
      uint64_t length = vslice_count - i;
      {
        const fidl::WireResult result = fidl::WireCall(vp->as_volume())->Extend(offset, length);
        ASSERT_OK(result.status());
        const fidl::WireResponse response = result.value();
        ASSERT_OK(response.status);
      }
    }

    // Verify that the extensions were successful.
    {
      const fidl::WireResult result = fidl::WireCall(vp->as_volume())
                                          ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(
                                              const_cast<size_t*>(vslice_start), vslice_count));
      ASSERT_OK(result.status());
      const fidl::WireResponse response = result.value();
      ASSERT_OK(response.status);
      ASSERT_EQ(vslice_count, response.response_count);
      for (unsigned i = 0; i < vslice_count; i++) {
        ASSERT_TRUE(response.response[i].allocated);
        ASSERT_EQ(response.response[i].count, ranges_before_extend[i].count + vslice_count - i);
      }
    }

    // Try mount again.
    fidl::ClientEnd device =
        fidl::ClientEnd<fuchsia_hardware_block::Block>(vp->partition.TakeChannel());
    ASSERT_EQ(fs_management::Mount(std::move(device), component, mounting_options).status_value(),
              ZX_OK);
  }

  zx::result controller =
      fs_management::OpenPartitionWithDevfs(devfs_caller.directory(), kPartition1Matcher, true);
  ASSERT_OK(controller);
  zx::result vp = PartitionChannel::Create(std::move(controller.value()));
  ASSERT_OK(vp);

  // Verify that slices were fixed on mount.
  const fidl::WireResult result = fidl::WireCall(vp->as_volume())
                                      ->QuerySlices(fidl::VectorView<uint64_t>::FromExternal(
                                          const_cast<size_t*>(vslice_start), vslice_count));
  ASSERT_OK(result.status());
  const fidl::WireResponse response = result.value();
  ASSERT_OK(response.status);
  ASSERT_EQ(vslice_count, response.response_count);

  for (unsigned i = 0; i < vslice_count; i++) {
    ASSERT_TRUE(response.response[i].allocated);
    ASSERT_EQ(response.response[i].count, initial_ranges[i].count);
  }
}

TEST_F(FvmTest, TestCorruptMount) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  ASSERT_EQ(kSliceSize, volume_info_or->slice_size);

  // Allocate one VPart
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_OK(vp_or.status_value());

  zx::result partition_path = GetPartitionPath(vp_or.value().controller);
  ASSERT_OK(partition_path.status_value());

  size_t kMinfsBlocksPerSlice = kSliceSize / minfs::kMinfsBlockSize;
  size_t minfs_vslice_count = 4;
  size_t minfs_vslice_start[] = {
      minfs::kFVMBlockInodeBmStart / kMinfsBlocksPerSlice,
      minfs::kFVMBlockDataBmStart / kMinfsBlocksPerSlice,
      minfs::kFVMBlockInodeStart / kMinfsBlocksPerSlice,
      minfs::kFVMBlockDataStart / kMinfsBlocksPerSlice,
  };

  // Run the test for Minfs.
  fs_management::MountOptions mounting_options;
  CorruptMountHelper(devfs_root_fd(), partition_path->c_str(), mounting_options,
                     fs_management::kDiskFormatMinfs, minfs_vslice_start, minfs_vslice_count);

  size_t kBlobfsBlocksPerSlice = kSliceSize / blobfs::kBlobfsBlockSize;
  size_t blobfs_vslice_count = 3;
  size_t blobfs_vslice_start[] = {
      blobfs::kFVMBlockMapStart / kBlobfsBlocksPerSlice,
      blobfs::kFVMNodeMapStart / kBlobfsBlocksPerSlice,
      blobfs::kFVMDataStart / kBlobfsBlocksPerSlice,
  };

  // Run the test for Blobfs.
  CorruptMountHelper(devfs_root_fd(), partition_path->c_str(), mounting_options,
                     fs_management::kDiskFormatBlobfs, blobfs_vslice_start, blobfs_vslice_count);
}

TEST_F(FvmTest, TestVPartitionUpgrade) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // Allocate two VParts, one active, and one inactive.
  {
    auto vp_fd_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid1,
        .name = kTestPartDataName,
        .flags = fuchsia_hardware_block_volume::wire::kAllocatePartitionFlagInactive,
    });
    ASSERT_EQ(vp_fd_or.status_value(), ZX_OK, "Couldn't open Volume");
  }

  {
    auto vp_fd_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid2,
        .name = kTestPartBlobName,
    });
    ASSERT_OK(vp_fd_or.status_value(), "Couldn't open volume");
  }

  // Release FVM device that we opened earlier
  FVMRebind();

  // The active partition should still exist.
  ASSERT_OK(WaitForPartition(kPartition2Matcher).status_value());
  // The inactive partition should be gone.
  ASSERT_STATUS(OpenPartition(kPartition1Matcher).status_value(), ZX_ERR_NOT_FOUND);

  // Reallocate GUID1 as inactive.

  {
    auto vp_fd_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid1,
        .name = kTestPartDataName,
        .flags = fuchsia_hardware_block_volume::wire::kAllocatePartitionFlagInactive,
    });
    ASSERT_OK(vp_fd_or.status_value(), "Couldn't open new volume");
  }

  // Atomically set GUID1 as active and GUID2 as inactive.
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    Upgrade(volume_manager.value(), kTestUniqueGuid2, kTestUniqueGuid1, ZX_OK);
  }
  // After upgrading, we should be able to open both partitions
  ASSERT_OK(WaitForPartition(kPartition1Matcher).status_value());
  ASSERT_OK(WaitForPartition(kPartition2Matcher).status_value());

  // Rebind the FVM driver, check that the upgrade has succeeded.
  // The original (GUID2) should be deleted, and the new partition (GUID)
  // should exist.
  FVMRebind();

  ASSERT_OK(WaitForPartition(kPartition1Matcher).status_value());
  ASSERT_STATUS(OpenPartition(kPartition2Matcher).status_value(), ZX_ERR_NOT_FOUND);

  // Try upgrading when the "new" version doesn't exist.
  // (It should return an error and have no noticeable effect).
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    Upgrade(volume_manager.value(), kTestUniqueGuid1, kTestUniqueGuid2, ZX_ERR_NOT_FOUND);
  }

  // Release FVM device that we opened earlier
  FVMRebind();

  ASSERT_OK(WaitForPartition(kPartition1Matcher).status_value());
  ASSERT_STATUS(OpenPartition(kPartition2Matcher).status_value(), ZX_ERR_NOT_FOUND);

  // Try upgrading when the "old" version doesn't exist.
  {
    auto vp_fd_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid2,
        .name = kTestPartBlobName,
        .flags = fuchsia_hardware_block_volume::wire::kAllocatePartitionFlagInactive,
    });
    ASSERT_EQ(vp_fd_or.status_value(), ZX_OK, "Couldn't open volume");
  }

  uuid::Uuid fake_guid = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    Upgrade(volume_manager.value(), fake_guid, kTestUniqueGuid2, ZX_OK);
  }

  FVMRebind();

  // We should be able to open both partitions again.
  zx::result vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_OK(vp_or.status_value());
  ASSERT_OK(WaitForPartition(kPartition2Matcher).status_value());

  // Destroy and reallocate the first partition as inactive.
  {
    const fidl::WireResult result = fidl::WireCall(vp_or.value().as_volume())->Destroy();
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  {
    zx::result vp_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid1,
        .name = kTestPartDataName,
        .flags = fuchsia_hardware_block_volume::wire::kAllocatePartitionFlagInactive,
    });
    ASSERT_EQ(vp_or.status_value(), ZX_OK, "Couldn't open volume");
  }

  // Upgrade the partition with old_guid == new_guid.
  // This should activate the partition.
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    Upgrade(volume_manager.value(), kTestUniqueGuid1, kTestUniqueGuid1, ZX_OK);
  }

  FVMRebind();

  // We should be able to open both partitions again.
  ASSERT_OK(WaitForPartition(kPartition1Matcher).status_value());
  ASSERT_OK(WaitForPartition(kPartition2Matcher).status_value());
}

// Test that the FVM driver can mount filesystems.
TEST_F(FvmTest, TestMounting) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);

  // Allocate one VPart
  size_t slice_count = 5;
  zx::result vp_or = AllocatePartition({
      .slice_count = slice_count,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp(*std::move(vp_or));

  // Format the VPart as minfs
  zx::result partition_path = GetPartitionPath(vp.controller);
  ASSERT_OK(partition_path.status_value());
  auto component = fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatMinfs);
  ASSERT_EQ(fs_management::Mkfs(partition_path->c_str(), component, fs_management::MkfsOptions()),
            ZX_OK);

  fidl::ClientEnd device =
      fidl::ClientEnd<fuchsia_hardware_block::Block>(vp.partition.TakeChannel());

  // Mount the VPart
  fs_management::MountOptions mounting_options;
  auto mounted_filesystem = fs_management::Mount(std::move(device), component, mounting_options);
  ASSERT_EQ(mounted_filesystem.status_value(), ZX_OK);
  auto data = mounted_filesystem->DataRoot();
  ASSERT_EQ(data.status_value(), ZX_OK);
  auto binding = fs_management::NamespaceBinding::Create(kMountPath, std::move(*data));
  ASSERT_EQ(binding.status_value(), ZX_OK);

  // Verify that the mount was successful.
  fbl::unique_fd rootfd;
  ASSERT_OK(fdio_open_fd(kMountPath, static_cast<uint32_t>(fuchsia_io::OpenFlags::kDirectory),
                         rootfd.reset_and_get_address()));
  fdio_cpp::FdioCaller caller(std::move(rootfd));
  auto result = fidl::WireCall(caller.directory())->QueryFilesystem();
  ASSERT_TRUE(result.ok());
  const char* kFsName = "minfs";
  const char* name = reinterpret_cast<const char*>(result.value().info->name.data());
  ASSERT_EQ(strncmp(name, kFsName, strlen(kFsName)), 0, "Unexpected filesystem mounted");

  // Verify that MinFS does not try to use more of the VPartition than
  // was originally allocated.
  ASSERT_LE(result.value().info->total_bytes, kSliceSize * slice_count);

  // Clean up.
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

// Test that FVM-aware filesystem can be reformatted.
TEST_F(FvmTest, TestMkfs) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);

  // Allocate one VPart.
  size_t slice_count = 5;
  zx::result vp_or = AllocatePartition({
      .slice_count = slice_count,
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp(*std::move(vp_or));

  // Format the VPart as minfs.
  zx::result partition_path = GetPartitionPath(vp.controller);
  ASSERT_OK(partition_path.status_value());
  auto minfs_component =
      fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatMinfs);
  ASSERT_EQ(
      fs_management::Mkfs(partition_path->c_str(), minfs_component, fs_management::MkfsOptions()),
      ZX_OK);

  // Format it as MinFS again, even though it is already formatted.
  ASSERT_EQ(
      fs_management::Mkfs(partition_path->c_str(), minfs_component, fs_management::MkfsOptions()),
      ZX_OK);

  // Now try reformatting as blobfs.
  auto blobfs_component =
      fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatBlobfs);
  ASSERT_EQ(fs_management::Mkfs(partition_path->c_str(), blobfs_component, {}), ZX_OK);

  // Demonstrate that mounting as minfs will fail, but mounting as blobfs
  // is successful.

  {
    fidl::ClientEnd device =
        fidl::ClientEnd<fuchsia_hardware_block::Block>(vp.partition.TakeChannel());
    fs_management::MountOptions mounting_options;
    ASSERT_NE(
        fs_management::Mount(std::move(device), minfs_component, mounting_options).status_value(),
        ZX_OK);
  }

  // We can't reuse the component.
  minfs_component = fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatMinfs);

  {
    zx::result device = component::Connect<fuchsia_hardware_block::Block>(partition_path.value());
    ASSERT_OK(device);
    ASSERT_EQ(fs_management::Mount(std::move(device.value()), blobfs_component, {}).status_value(),
              ZX_OK);
  }

  // ... and reformat back to MinFS again.
  ASSERT_EQ(
      fs_management::Mkfs(partition_path->c_str(), minfs_component, fs_management::MkfsOptions()),
      ZX_OK);

  // Mount the VPart.
  zx::result device = component::Connect<fuchsia_hardware_block::Block>(partition_path.value());
  ASSERT_OK(device);
  fs_management::MountOptions mounting_options;
  auto mounted_filesystem =
      fs_management::Mount(std::move(device.value()), minfs_component, mounting_options);
  ASSERT_EQ(mounted_filesystem.status_value(), ZX_OK);
  auto data = mounted_filesystem->DataRoot();
  ASSERT_EQ(data.status_value(), ZX_OK);
  auto binding = fs_management::NamespaceBinding::Create(kMountPath, std::move(*data));
  ASSERT_EQ(binding.status_value(), ZX_OK);

  // Verify that the mount was successful.
  fbl::unique_fd rootfd;
  ASSERT_OK(fdio_open_fd(kMountPath, static_cast<uint32_t>(fuchsia_io::OpenFlags::kDirectory),
                         rootfd.reset_and_get_address()));
  ASSERT_TRUE(rootfd);
  fdio_cpp::FdioCaller caller(std::move(rootfd));
  auto result = fidl::WireCall(caller.directory())->QueryFilesystem();
  ASSERT_TRUE(result.ok());
  const char* kFsName = "minfs";
  const char* name = reinterpret_cast<const char*>(result.value().info->name.data());
  ASSERT_EQ(strncmp(name, kFsName, strlen(kFsName)), 0, "Unexpected filesystem mounted");

  // Verify that MinFS does not try to use more of the VPartition than
  // was originally allocated.
  ASSERT_LE(result.value().info->total_bytes, kSliceSize * slice_count);

  // Clean up.
  FVMCheckSliceSize(volume_manager.value(), kSliceSize);
}

// Test that the FVM can recover when one copy of
// metadata becomes corrupt.
TEST_F(FvmTest, TestCorruptionOk) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);

  // Allocate one VPart (writes to backup)
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp(*std::move(vp_or));

  // Extend the vpart (writes to primary)
  uint64_t offset = 1;
  uint64_t length = 1;
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_EQ(block_info.block_count * block_info.block_size, kSliceSize * 2);

  // Initial slice access
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  // Extended slice access
  CheckWriteReadBlock(vp.as_block(), kSliceSize / block_info.block_size, 1);

  vp = {};

  // Corrupt the (backup) metadata and rebind.
  // The 'primary' was the last one written, so it'll be used.
  fvm::Header header =
      fvm::Header::FromDiskSize(fvm::kMaxUsablePartitions, kBlockSize * kBlockCount, kSliceSize);
  auto off = static_cast<off_t>(header.GetSuperblockOffset(fvm::SuperblockType::kSecondary));
  uint8_t buf[fvm::kBlockSize];
  fidl::UnownedClientEnd device = ramdisk_block_interface();
  ASSERT_OK(block_client::SingleReadBytes(device, buf, sizeof(buf), off));
  // Modify an arbitrary byte (not the magic bits; we still want it to mount!)
  buf[128]++;
  ASSERT_OK(block_client::SingleWriteBytes(device, buf, sizeof(buf), off));

  FVMRebind();

  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_EQ(vp_or.status_value(), ZX_OK, "Couldn't re-open Data VPart");
  vp = *std::move(vp_or);

  // The slice extension is still accessible.
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  CheckWriteReadBlock(vp.as_block(), kSliceSize / block_info.block_size, 1);

  // Clean up
  vp = {};

  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

TEST_F(FvmTest, TestCorruptionRegression) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);
  zx::result volume_manager = fvm_device();
  ASSERT_OK(volume_manager);

  auto volume_info_or = fs_management::FvmQuery(volume_manager.value());
  ASSERT_EQ(volume_info_or.status_value(), ZX_OK);
  size_t slice_size = volume_info_or->slice_size;

  // Allocate one VPart (writes to backup)
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp(*std::move(vp_or));

  // Extend the vpart (writes to primary)
  uint64_t offset = 1;
  uint64_t length = 1;
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_EQ(block_info.block_count * block_info.block_size, slice_size * 2);

  // Initial slice access
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  // Extended slice access
  CheckWriteReadBlock(vp.as_block(), slice_size / block_info.block_size, 1);

  vp = {};

  // Corrupt the (primary) metadata and rebind.
  // The 'primary' was the last one written, so the backup will be used.
  off_t off = 0;
  uint8_t buf[fvm::kBlockSize];
  fidl::UnownedClientEnd device = ramdisk_block_interface();
  ASSERT_OK(block_client::SingleReadBytes(device, buf, sizeof(buf), off));
  buf[128]++;
  ASSERT_OK(block_client::SingleWriteBytes(device, buf, sizeof(buf), off));

  FVMRebind();

  vp_or = WaitForPartition(kPartition1Matcher);
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  vp = *std::move(vp_or);

  // The slice extension is no longer accessible
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  CheckNoAccessBlock(vp.as_block(), slice_size / block_info.block_size, 1);

  // Clean up
  vp = {};
  {
    zx::result volume_manager = fvm_device();
    ASSERT_OK(volume_manager);
    FVMCheckSliceSize(volume_manager.value(), kSliceSize);
  }
}

TEST_F(FvmTest, TestCorruptionUnrecoverable) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // Allocate one VPart (writes to backup)
  zx::result vp_or = AllocatePartition({
      .type = kTestPartDataGuid,
      .guid = kTestUniqueGuid1,
      .name = kTestPartDataName,
  });
  ASSERT_EQ(vp_or.status_value(), ZX_OK);
  PartitionChannel vp(*std::move(vp_or));

  // Extend the vpart (writes to primary)
  uint64_t offset = 1;
  uint64_t length = 1;
  {
    const fidl::WireResult result = fidl::WireCall(vp.as_volume())->Extend(offset, length);
    ASSERT_OK(result.status());
    const fidl::WireResponse response = result.value();
    ASSERT_OK(response.status);
  }
  const fidl::WireResult result = fidl::WireCall(vp.as_block())->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  ASSERT_EQ(block_info.block_count * block_info.block_size, kSliceSize * 2);

  // Initial slice access
  CheckWriteReadBlock(vp.as_block(), 0, 1);
  // Extended slice access
  CheckWriteReadBlock(vp.as_block(), kSliceSize / block_info.block_size, 1);

  vp = {};

  // Corrupt both copies of the metadata.
  // The 'primary' was the last one written, so the backup will be used.
  off_t off = 0;
  uint8_t buf[fvm::kBlockSize];
  fidl::UnownedClientEnd device = ramdisk_block_interface();
  ASSERT_OK(block_client::SingleReadBytes(device, buf, sizeof(buf), off));
  buf[128]++;
  ASSERT_OK(block_client::SingleWriteBytes(device, buf, sizeof(buf), off));

  fvm::Header header =
      fvm::Header::FromDiskSize(fvm::kMaxUsablePartitions, kBlockSize * kBlockCount, kSliceSize);
  off = static_cast<off_t>(header.GetSuperblockOffset(fvm::SuperblockType::kSecondary));
  ASSERT_OK(block_client::SingleReadBytes(device, buf, sizeof(buf), off));
  buf[128]++;
  ASSERT_OK(block_client::SingleWriteBytes(device, buf, sizeof(buf), off));

  ValidateFVM(ramdisk_block_interface(), ValidationResult::Corrupted);
}

// Tests the FVM checker against a just-initialized FVM.
TEST_F(FvmTest, TestCheckNewFVM) {
  CreateFVM(512, 1 << 20, 64LU * (1 << 20));
  fidl::UnownedClientEnd device = ramdisk_block_interface();
  const fidl::WireResult result = fidl::WireCall(device)->GetInfo();
  ASSERT_OK(result.status());
  const fit::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fuchsia_hardware_block::wire::BlockInfo& block_info = response.value()->info;
  fvm::Checker checker(device, block_info.block_size, true);
  ASSERT_TRUE(checker.Validate());
}

TEST_F(FvmTest, TestAbortDriverLoadSmallDevice) {
  constexpr uint64_t kMB = 1 << 20;
  constexpr uint64_t kGB = 1 << 30;
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 50 * kMB / kBlockSize;
  constexpr uint64_t kSliceSize = kMB;
  constexpr uint64_t kFvmPartitionSize = 4 * kGB;

  CreateRamdisk(kBlockSize, kBlockCount);

  // Init fvm with a partition bigger than the underlying disk.
  fs_management::FvmInitWithSize(ramdisk_block_interface(), kFvmPartitionSize, kSliceSize);

  // Try to bind an fvm to the disk.
  //
  // Bind should return ZX_ERR_IO when the load of a driver fails.
  auto resp = fidl::WireCall(ramdisk_controller_interface())->Bind(kFvmDriverLib);
  ASSERT_OK(resp.status());
  ASSERT_FALSE(resp->is_ok());
  ASSERT_EQ(resp->error_value(), ZX_ERR_INTERNAL);

  CreateRamdisk(kBlockSize, kBlockCount);
  fs_management::FvmInitWithSize(ramdisk_block_interface(), kFvmPartitionSize, kSliceSize);
  // Grow the ramdisk to the appropiate size and bind should succeed.
  ASSERT_OK(ramdisk_grow(ramdisk(), kFvmPartitionSize));
  // Use Controller::Call::Rebind because the driver might still be
  // when init fails. Driver removes the device and will eventually be
  // unloaded but Controller::Bind above does not wait until
  // the device is removed. Controller::Rebind ensures nothing is
  // bound to the device, before it tries to bind the driver again.
  auto resp2 = fidl::WireCall(ramdisk_controller_interface())->Rebind(kFvmDriverLib);
  ASSERT_OK(resp2.status());
  ASSERT_TRUE(resp2->is_ok());
  ASSERT_OK(device_watcher::RecursiveWaitForFile(devfs_root_fd().get(), fvm_path().c_str()));
}

TEST_F(FvmTest, TestPreventDuplicateDeviceNames) {
  constexpr uint64_t kBlockSize = 512;
  constexpr uint64_t kBlockCount = 1 << 16;
  constexpr uint64_t kSliceSize = 64 * kBlockSize;
  CreateFVM(kBlockSize, kBlockCount, kSliceSize);

  // When a partition is destroyed, the slot in FVM is synchronously freed but the device is
  // asynchronously removed. DFv2 prevents multiple child devices with the same name from being
  // bound. This test rapidly allocates and destroys the same partition to try and get a race
  // between the new device being bound and the old device being removed to try and get FVM to bind
  // multiple devices with the same name.
  for (int i = 0; i < 10; ++i) {
    zx::result vp_or = AllocatePartition({
        .type = kTestPartDataGuid,
        .guid = kTestUniqueGuid1,
        .name = kTestPartDataName,
    });
    ASSERT_OK(vp_or.status_value());
    auto result = fidl::WireCall(vp_or.value().as_volume())->Destroy();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }
}

}  // namespace
