// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// clang-format off
#include <lib/sysconfig/sync-client.h>
#include <lib/sysconfig/sysconfig-header.h>

// clang-format on

#include <lib/fdio/cpp/caller.h>
#include <lib/zx/channel.h>
#include <zircon/hw/gpt.h>

#include <fbl/algorithm.h>
#include <ramdevice-client-test/ramnandctl.h>
#include <zxtest/zxtest.h>

namespace {

constexpr uint32_t kOobSize = 8;
constexpr uint32_t kPageSize = 4096;
constexpr uint32_t kPagesPerBlock = 64;
constexpr uint32_t kBlockSize = kPageSize * kPagesPerBlock;
constexpr uint32_t kNumBlocks = 8;

fuchsia_hardware_nand::wire::RamNandInfo NandInfo() {
  return {
      .nand_info =
          {
              .page_size = kPageSize,
              .pages_per_block = kPagesPerBlock,
              .num_blocks = kNumBlocks,
              .ecc_bits = 8,
              .oob_size = kOobSize,
              .nand_class = fuchsia_hardware_nand::wire::Class::kPartmap,
              .partition_guid = {},
          },
      .partition_map =
          {
              .device_guid = {},
              .partition_count = 2,
              .partitions =
                  {
                      fuchsia_hardware_nand::wire::Partition{
                          .type_guid = {},
                          .unique_guid = {},
                          .first_block = 0,
                          .last_block = 3,
                          .copy_count = 0,
                          .copy_byte_offset = 0,
                          .name = {},
                          .hidden = true,
                          .bbt = true,
                      },
                      {
                          .type_guid = GUID_SYS_CONFIG_VALUE,
                          .unique_guid = {},
                          .first_block = 4,
                          .last_block = 7,
                          .copy_count = 4,
                          .copy_byte_offset = 0,
                          .name = {'s', 'y', 's', 'c', 'o', 'n', 'f', 'i', 'g'},
                          .hidden = false,
                          .bbt = false,
                      },
                  },
          },
      .export_nand_config = true,
      .export_partition_map = true,
  };
}

class SkipBlockDevice {
 public:
  static void Create(fuchsia_hardware_nand::wire::RamNandInfo nand_info,
                     std::optional<SkipBlockDevice>* device);

  fidl::UnownedClientEnd<fuchsia_io::Directory> devfs_root() const {
    fdio_cpp::UnownedFdioCaller caller(ctl_->devfs_root());
    return caller.directory();
  }

  fzl::VmoMapper& mapper() { return mapper_; }

  ~SkipBlockDevice() = default;

  SkipBlockDevice(std::unique_ptr<ramdevice_client_test::RamNandCtl> ctl,
                  ramdevice_client::RamNand ram_nand, fzl::VmoMapper mapper)
      : ctl_(std::move(ctl)), ram_nand_(std::move(ram_nand)), mapper_(std::move(mapper)) {}

 private:
  std::unique_ptr<ramdevice_client_test::RamNandCtl> ctl_;
  ramdevice_client::RamNand ram_nand_;
  fzl::VmoMapper mapper_;
};

void CreateBadBlockMap(void* buffer) {
  // Set all entries in first BBT to be good blocks.
  constexpr uint8_t kBlockGood = 0;
  memset(buffer, kBlockGood, kPageSize);

  struct OobMetadata {
    uint32_t magic;
    int16_t program_erase_cycles;
    uint16_t generation;
  };

  const size_t oob_offset = kPageSize * kPagesPerBlock * kNumBlocks;
  auto* oob = reinterpret_cast<OobMetadata*>(reinterpret_cast<uintptr_t>(buffer) + oob_offset);
  oob->magic = 0x7462626E;  // "nbbt"
  oob->program_erase_cycles = 0;
  oob->generation = 1;
}

void SkipBlockDevice::Create(fuchsia_hardware_nand::wire::RamNandInfo nand_info,
                             std::optional<SkipBlockDevice>* device) {
  fzl::VmoMapper mapper;
  zx::vmo vmo;
  ASSERT_OK(mapper.CreateAndMap((kPageSize + kOobSize) * kPagesPerBlock * kNumBlocks,
                                ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
  memset(mapper.start(), 0xff, mapper.size());
  CreateBadBlockMap(mapper.start());
  ASSERT_OK(vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &nand_info.vmo));

  std::unique_ptr<ramdevice_client_test::RamNandCtl> ctl;
  ASSERT_OK(ramdevice_client_test::RamNandCtl::Create(&ctl));
  std::optional<ramdevice_client::RamNand> ram_nand;
  ASSERT_OK(ctl->CreateRamNand(std::move(nand_info), &ram_nand));
  ASSERT_OK(
      device_watcher::RecursiveWaitForFile(ctl->devfs_root().get(), "sys/platform").status_value());
  device->emplace(std::move(ctl), *std::move(ram_nand), std::move(mapper));
}

void CreatePayload(size_t size, zx::vmo* out, uint8_t data = 0x4a) {
  zx::vmo vmo;
  fzl::VmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(size, zx_system_get_page_size()),
                                ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
  memset(mapper.start(), data, mapper.size());
  *out = std::move(vmo);
}

void ValidateBuffer(void* buffer, size_t size, uint8_t expected = 0x5c) {
  const auto* start = static_cast<uint8_t*>(buffer);
  for (size_t i = 0; i < size; i++) {
    ASSERT_EQ(start[i], expected, "i = %zu", i);
  }
}

class SyncClientTest : public zxtest::Test {
 protected:
  SyncClientTest() { ASSERT_NO_FATAL_FAILURE(SkipBlockDevice::Create(NandInfo(), &device_)); }

  void ValidateWritten(size_t offset, size_t size, uint8_t expected = 0x4a) {
    for (size_t block = 4; block < 5; block++) {
      const uint8_t* start =
          static_cast<uint8_t*>(device_->mapper().start()) + (block * kBlockSize) + offset;
      for (size_t i = 0; i < size; i++) {
        ASSERT_EQ(start[i], expected, "block = %zu, i = %zu", block, i);
      }
    }
  }

  void ValidateUnwritten(size_t offset, size_t size) {
    for (size_t block = 4; block < 5; block++) {
      const uint8_t* start =
          static_cast<uint8_t*>(device_->mapper().start()) + (block * kBlockSize) + offset;
      for (size_t i = 0; i < size; i++) {
        ASSERT_EQ(start[i], 0xff, "block = %zu, offset: %zu i = %zu", block, offset, i);
      }
    }
  }

  void WriteData(size_t offset, size_t size, uint8_t data = 0x5c) {
    for (size_t block = 4; block < 7; block++) {
      uint8_t* start =
          static_cast<uint8_t*>(device_->mapper().start()) + (block * kBlockSize) + offset;
      memset(start, data, size);
    }
  }

  void TestLayoutUpdate(std::optional<sysconfig_header> current_header,
                        const sysconfig_header& target_header);

  std::optional<SkipBlockDevice> device_;
};

TEST_F(SyncClientTest, CreateAstro) {
  ASSERT_OK(sysconfig::SyncClient::Create(device_->devfs_root()));
}

using PartitionType = sysconfig::SyncClient::PartitionType;

constexpr size_t kKilobyte = 1 << 10;

TEST_F(SyncClientTest, WritePartitionSysconfig) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(60 * kKilobyte, &vmo));
  ASSERT_OK(client.value().WritePartition(PartitionType::kSysconfig, vmo, 0));

  ASSERT_NO_FATAL_FAILURE(ValidateWritten(0, 60 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(60 * kKilobyte, 196 * kKilobyte));
}

TEST_F(SyncClientTest, WritePartitionAbrMetadata) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(4 * kKilobyte, &vmo));
  ASSERT_OK(client.value().WritePartition(PartitionType::kABRMetadata, vmo, 0));

  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(0, 60 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateWritten(60 * kKilobyte, 4 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(64 * kKilobyte, 192 * kKilobyte));
}

TEST_F(SyncClientTest, WritePartitionVbMetaA) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(64 * kKilobyte, &vmo));
  ASSERT_OK(client.value().WritePartition(PartitionType::kVerifiedBootMetadataA, vmo, 0));

  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(0, 64 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateWritten(64 * kKilobyte, 64 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(128 * kKilobyte, 128 * kKilobyte));
}

TEST_F(SyncClientTest, WritePartitionVbMetaB) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(64 * kKilobyte, &vmo));
  ASSERT_OK(client.value().WritePartition(PartitionType::kVerifiedBootMetadataB, vmo, 0));

  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(0, 128 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateWritten(128 * kKilobyte, 64 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(192 * kKilobyte, 64 * kKilobyte));
}

TEST_F(SyncClientTest, WritePartitionVbMetaR) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(64 * kKilobyte, &vmo));
  ASSERT_OK(client.value().WritePartition(PartitionType::kVerifiedBootMetadataR, vmo, 0));

  ASSERT_NO_FATAL_FAILURE(ValidateUnwritten(0, 192 * kKilobyte));
  ASSERT_NO_FATAL_FAILURE(ValidateWritten(192 * kKilobyte, 64 * kKilobyte));
}

TEST_F(SyncClientTest, ReadPartitionSysconfig) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(60 * kKilobyte, zx_system_get_page_size()), "test"));

  ASSERT_NO_FATAL_FAILURE(WriteData(0, 60 * kKilobyte));
  ASSERT_OK(client.value().ReadPartition(PartitionType::kSysconfig, mapper.vmo(), 0));
  ASSERT_NO_FATAL_FAILURE(ValidateBuffer(mapper.start(), 60 * kKilobyte));
}

TEST_F(SyncClientTest, ReadPartitionAbrMetadata) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(4 * kKilobyte, zx_system_get_page_size()), "test"));

  ASSERT_NO_FATAL_FAILURE(WriteData(60 * kKilobyte, 4 * kKilobyte));
  ASSERT_OK(client.value().ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));
  ASSERT_NO_FATAL_FAILURE(ValidateBuffer(mapper.start(), 4 * kKilobyte));
}

TEST_F(SyncClientTest, ReadPartitionVbMetaA) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(64 * kKilobyte, zx_system_get_page_size()), "test"));

  ASSERT_NO_FATAL_FAILURE(WriteData(64 * kKilobyte, 64 * kKilobyte));
  ASSERT_OK(client.value().ReadPartition(PartitionType::kVerifiedBootMetadataA, mapper.vmo(), 0));
  ASSERT_NO_FATAL_FAILURE(ValidateBuffer(mapper.start(), 64 * kKilobyte));
}

TEST_F(SyncClientTest, ReadPartitionVbMetaB) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(64 * kKilobyte, zx_system_get_page_size()), "test"));

  ASSERT_NO_FATAL_FAILURE(WriteData(128 * kKilobyte, 64 * kKilobyte));
  ASSERT_OK(client.value().ReadPartition(PartitionType::kVerifiedBootMetadataB, mapper.vmo(), 0));
  ASSERT_NO_FATAL_FAILURE(ValidateBuffer(mapper.start(), 64 * kKilobyte));
}

TEST_F(SyncClientTest, ReadPartitionVbMetaR) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(fbl::round_up(64 * kKilobyte, zx_system_get_page_size()), "test"));

  ASSERT_NO_FATAL_FAILURE(WriteData(192 * kKilobyte, 64 * kKilobyte));
  ASSERT_OK(client.value().ReadPartition(PartitionType::kVerifiedBootMetadataR, mapper.vmo(), 0));
  ASSERT_NO_FATAL_FAILURE(ValidateBuffer(mapper.start(), 64 * kKilobyte));
}

TEST_F(SyncClientTest, GetPartitionSizeSysconfig) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  size_t size;
  ASSERT_OK(client.value().GetPartitionSize(PartitionType::kSysconfig, &size));
  ASSERT_EQ(size, 60 * kKilobyte);
}

TEST_F(SyncClientTest, GetPartitionSizeAbrMetadata) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  size_t size;
  ASSERT_OK(client.value().GetPartitionSize(PartitionType::kABRMetadata, &size));
  ASSERT_EQ(size, 4 * kKilobyte);
}

TEST_F(SyncClientTest, GetPartitionSizeVbMetaA) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  size_t size;
  ASSERT_OK(client.value().GetPartitionSize(PartitionType::kVerifiedBootMetadataA, &size));
  ASSERT_EQ(size, 64 * kKilobyte);
}

TEST_F(SyncClientTest, GetPartitionSizeVbMetaB) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  size_t size;
  ASSERT_OK(client.value().GetPartitionSize(PartitionType::kVerifiedBootMetadataB, &size));
  ASSERT_EQ(size, 64 * kKilobyte);
}

TEST_F(SyncClientTest, GetPartitionSizeVbMetaR) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  size_t size;
  ASSERT_OK(client.value().GetPartitionSize(PartitionType::kVerifiedBootMetadataR, &size));
  ASSERT_EQ(size, 64 * kKilobyte);
}

namespace {
sysconfig_header GetNonLegacyHeaderForTest() {
  return {
      .magic = SYSCONFIG_HEADER_MAGIC_ARRAY,
      .sysconfig_data = {200 * kKilobyte, 56 * kKilobyte},
      .abr_metadata = {196 * kKilobyte, 4 * kKilobyte},
      .vb_metadata_a = {4 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_b = {68 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_r = {132 * kKilobyte, 64 * kKilobyte},
  };
}
}  // namespace

TEST(SysconfigHeaderTest, ValidHeader) {
  auto header = GetNonLegacyHeaderForTest();
  update_sysconfig_header_magic_and_crc(&header);
  ASSERT_TRUE(sysconfig_header_valid(&header, kPageSize, kBlockSize));
}

TEST(SysconfigHeaderTest, InvalidMagic) {
  auto invalid_magic = GetNonLegacyHeaderForTest();
  invalid_magic.magic[0] = 'A';
  ASSERT_FALSE(sysconfig_header_valid(&invalid_magic, kPageSize, kBlockSize));
}

TEST(SysconfigHeaderTest, InvalidCrc) {
  auto base = GetNonLegacyHeaderForTest();
  auto invalid_crc = base;
  invalid_crc.crc_value += 1;
  ASSERT_FALSE(sysconfig_header_valid(&invalid_crc, kPageSize, kBlockSize));
  // However, crc_value shall not affect comparison.
  ASSERT_TRUE(sysconfig_header_equal(&invalid_crc, &base));
}

TEST_F(SyncClientTest, HeaderNotPageAligned) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto not_page_alinged = GetNonLegacyHeaderForTest();
  not_page_alinged.sysconfig_data.size = 55 * kKilobyte;
  update_sysconfig_header_magic_and_crc(&not_page_alinged);
  ASSERT_FALSE(sysconfig_header_valid(&not_page_alinged, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(not_page_alinged), ZX_ERR_INVALID_ARGS);
}

TEST_F(SyncClientTest, HeaderInvalidOffset) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto invalid_offset = GetNonLegacyHeaderForTest();
  invalid_offset.sysconfig_data.offset = 256 * kKilobyte;
  update_sysconfig_header_magic_and_crc(&invalid_offset);
  ASSERT_FALSE(sysconfig_header_valid(&invalid_offset, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(invalid_offset), ZX_ERR_INVALID_ARGS);
}

TEST_F(SyncClientTest, HeaderInvalidSize) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto invalid_size = GetNonLegacyHeaderForTest();
  invalid_size.sysconfig_data.size = 252 * kKilobyte;
  update_sysconfig_header_magic_and_crc(&invalid_size);
  ASSERT_FALSE(sysconfig_header_valid(&invalid_size, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(invalid_size), ZX_ERR_INVALID_ARGS);
}

TEST_F(SyncClientTest, HeaderInvalidSizePlusOffset) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto invalid_size_offset = GetNonLegacyHeaderForTest();
  invalid_size_offset.sysconfig_data = {200 * kKilobyte, 60 * kKilobyte};
  update_sysconfig_header_magic_and_crc(&invalid_size_offset);
  ASSERT_FALSE(sysconfig_header_valid(&invalid_size_offset, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(invalid_size_offset), ZX_ERR_INVALID_ARGS);
}

TEST_F(SyncClientTest, HeaderOverlapSubpart) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto overlap_subpart = GetNonLegacyHeaderForTest();
  overlap_subpart.sysconfig_data = {196 * kKilobyte, 56 * kKilobyte};
  update_sysconfig_header_magic_and_crc(&overlap_subpart);
  ASSERT_FALSE(sysconfig_header_valid(&overlap_subpart, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(overlap_subpart), ZX_ERR_INVALID_ARGS);
}

TEST_F(SyncClientTest, HeaderPage0NotReserved) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto page0_not_reserved = GetNonLegacyHeaderForTest();
  page0_not_reserved.vb_metadata_a.offset = 0;
  update_sysconfig_header_magic_and_crc(&page0_not_reserved);
  ASSERT_FALSE(sysconfig_header_valid(&page0_not_reserved, kPageSize, kBlockSize));
  ASSERT_STATUS(client.value().UpdateLayout(page0_not_reserved), ZX_ERR_INVALID_ARGS);
}

void SyncClientTest::TestLayoutUpdate(const std::optional<sysconfig_header> current_header,
                                      const sysconfig_header& target_header) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;
  using PartitionType = sysconfig::SyncClient::PartitionType;
  auto init_header = current_header;
  // If current header is not provided, assume legacy layout.
  if (!init_header) {
    init_header = {
        .magic = SYSCONFIG_HEADER_MAGIC_ARRAY,
        .sysconfig_data = {0 * kKilobyte, 60 * kKilobyte},
        .abr_metadata = {60 * kKilobyte, 4 * kKilobyte},
        .vb_metadata_a = {64 * kKilobyte, 64 * kKilobyte},
        .vb_metadata_b = {128 * kKilobyte, 64 * kKilobyte},
        .vb_metadata_r = {192 * kKilobyte, 64 * kKilobyte},
        .crc_value = 2716817057,  // pre-calculated crc
    };
  }

  // Initialize the memory according to init_header.
  memset(memory, 0xff, 256 * kKilobyte);
  memset(&memory[init_header->sysconfig_data.offset], 1, init_header->sysconfig_data.size);
  memset(&memory[init_header->abr_metadata.offset], 2, init_header->abr_metadata.size);
  memset(&memory[init_header->vb_metadata_a.offset], 3, init_header->vb_metadata_a.size);
  memset(&memory[init_header->vb_metadata_b.offset], 4, init_header->vb_metadata_b.size);
  memset(&memory[init_header->vb_metadata_r.offset], 5, init_header->vb_metadata_r.size);
  // Write header to storage if provided.
  if (current_header) {
    update_sysconfig_header_magic_and_crc(&*init_header);
    memcpy(memory, &*init_header, sizeof(*init_header));
  }

  auto update_header = target_header;
  update_sysconfig_header_magic_and_crc(&update_header);
  ASSERT_OK(client.value().UpdateLayout(update_header));

  struct PartitionRange {
    uint64_t offset;
    uint64_t size;
    PartitionRange(sysconfig_subpartition info) : offset(info.offset), size(info.size) {}
  };

  struct ValidationData {
    PartitionType name;
    PartitionRange old_info;
    PartitionRange new_info;
    uint8_t expected;
  } validation_data[] = {
      {PartitionType::kSysconfig, init_header->sysconfig_data, update_header.sysconfig_data, 1},
      {PartitionType::kABRMetadata, init_header->abr_metadata, update_header.abr_metadata, 2},
      {PartitionType::kVerifiedBootMetadataA, init_header->vb_metadata_a,
       update_header.vb_metadata_a, 3},
      {PartitionType::kVerifiedBootMetadataB, init_header->vb_metadata_b,
       update_header.vb_metadata_b, 4},
      {PartitionType::kVerifiedBootMetadataR, init_header->vb_metadata_r,
       update_header.vb_metadata_r, 5},
  };

  for (auto item : validation_data) {
    auto content_size = std::min(item.old_info.size, item.new_info.size);
    ASSERT_NO_FATAL_FAILURE(ValidateWritten(item.new_info.offset, content_size, item.expected));
    size_t part_size, part_offset;
    ASSERT_OK(client.value().GetPartitionSize(item.name, &part_size));
    ASSERT_EQ(part_size, item.new_info.size);
    ASSERT_OK(client.value().GetPartitionOffset(item.name, &part_offset));
    ASSERT_EQ(part_offset, item.new_info.offset);
    fzl::OwnedVmoMapper vmo;
    // vmo::CreateAndMap does not allow creating a zero size vmo. But we are testing
    // empty sub-partition cases. Thus, give a minimum size below.
    ASSERT_OK(vmo.CreateAndMap(std::max(part_size, static_cast<size_t>(kPageSize)), "",
                               ZX_VM_PERM_READ | ZX_VM_PERM_WRITE));
    ASSERT_OK(client.value().ReadPartition(item.name, vmo.vmo(), 0));
    ASSERT_NO_FATAL_FAILURE(ValidateBuffer(vmo.start(), content_size, item.expected));
  }
}

TEST_F(SyncClientTest, UpdateLayoutShrink) {
  sysconfig_header shrunken_size_only = {
      .sysconfig_data = {4 * kKilobyte, 32 * kKilobyte},
      .abr_metadata = {60 * kKilobyte, 4 * kKilobyte},
      .vb_metadata_a = {64 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_b = {128 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_r = {192 * kKilobyte, 32 * kKilobyte},
  };
  TestLayoutUpdate(std::nullopt, shrunken_size_only);
}

TEST_F(SyncClientTest, UpdateLayoutShrinkAndExpand) {
  sysconfig_header shrunken_and_expand = {
      .sysconfig_data = {4 * kKilobyte, 20 * kKilobyte},
      .abr_metadata = {24 * kKilobyte, 40 * kKilobyte},
      .vb_metadata_a = {64 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_b = {128 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_r = {192 * kKilobyte, 32 * kKilobyte},
  };
  TestLayoutUpdate(std::nullopt, shrunken_and_expand);
}

TEST_F(SyncClientTest, UpdateLayoutReverseOrder) {
  sysconfig_header reverse_order = {
      .sysconfig_data = {192 * kKilobyte, 64 * kKilobyte},
      .abr_metadata = {128 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_a = {64 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_b = {60 * kKilobyte, 4 * kKilobyte},
      .vb_metadata_r = {4 * kKilobyte, 56 * kKilobyte},
  };
  TestLayoutUpdate(std::nullopt, reverse_order);
}

TEST_F(SyncClientTest, UpdateLayoutReverseOrderWithGap) {
  // To create gap between sub-paritions as well as order change.
  sysconfig_header reverse_order = {
      .sysconfig_data = {192 * kKilobyte, 32 * kKilobyte},
      .abr_metadata = {128 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_a = {64 * kKilobyte, 32 * kKilobyte},
      .vb_metadata_b = {52 * kKilobyte, 12 * kKilobyte},
      .vb_metadata_r = {4 * kKilobyte, 32 * kKilobyte},
  };
  TestLayoutUpdate(std::nullopt, reverse_order);
}

sysconfig_header shrunken_configdata_abr_expand_at_end = {
    .sysconfig_data = {4 * kKilobyte, 20 * kKilobyte},
    .abr_metadata = {216 * kKilobyte, 40 * kKilobyte},
    .vb_metadata_a = {24 * kKilobyte, 64 * kKilobyte},
    .vb_metadata_b = {88 * kKilobyte, 64 * kKilobyte},
    .vb_metadata_r = {152 * kKilobyte, 64 * kKilobyte},
};

sysconfig_header empty_configdata_abr_expand_at_end = {
    .sysconfig_data = {4 * kKilobyte, 0},
    .abr_metadata = {196 * kKilobyte, 60 * kKilobyte},
    .vb_metadata_a = {4 * kKilobyte, 64 * kKilobyte},
    .vb_metadata_b = {68 * kKilobyte, 64 * kKilobyte},
    .vb_metadata_r = {132 * kKilobyte, 64 * kKilobyte},
};

TEST_F(SyncClientTest, UpdateLayoutShrinkConfigDataExpandAbrAtEnd) {
  TestLayoutUpdate(std::nullopt, shrunken_configdata_abr_expand_at_end);
}

TEST_F(SyncClientTest, UpdateLayoutEmptyConfigDataExpandAbrAtEnd) {
  TestLayoutUpdate(std::nullopt, empty_configdata_abr_expand_at_end);
}

TEST_F(SyncClientTest, UpdateLayoutFromShrukenToEmptyConfigData) {
  TestLayoutUpdate(shrunken_configdata_abr_expand_at_end, empty_configdata_abr_expand_at_end);
}

class SyncClientBufferedTest : public SyncClientTest {
 public:
  struct PartitionInfo {
    PartitionType partition;
    size_t partition_offset;
    size_t partition_size;
    std::optional<uint8_t> write_value;
  };

  // Tests that SyncClientBuffered correctly writes to caches and storage for one or more
  // sub-partitions.
  void TestWrite(const std::vector<PartitionInfo>& parts_to_test_write);

  // Tests that SyncClientBuffered correctly reads from cache and storage for one or more
  // sub-partitions.
  void TestRead(const std::vector<PartitionInfo>& parts_to_test_read);

  // Tests that SyncClientBuffered correctly writes according to a non-legacy header for
  // one or more sub-partitions.
  void TestWriteWithHeader(const std::vector<PartitionInfo>& parts_to_test_write);

 protected:
  static void ValidateReadBuffer(const void* buffer, size_t len, uint8_t expected) {
    auto mem = static_cast<const uint8_t*>(buffer);
    for (size_t i = 0; i < len; i++) {
      ASSERT_EQ(mem[i], expected, "offset = %zu", i);
    }
  }

  static std::optional<uint8_t> GetExpectedWriteValue(size_t index,
                                                      const std::vector<PartitionInfo>& parts,
                                                      uint8_t unwritten_default) {
    for (auto& part : parts) {
      if (index >= part.partition_offset && index < part.partition_offset + part.partition_size) {
        return part.write_value;
      }
    }
    return unwritten_default;
  }

  void ValidateMemory(const std::vector<PartitionInfo>& parts) {
    const uint8_t* start = static_cast<uint8_t*>(device_->mapper().start()) + (4 * kBlockSize);
    for (size_t i = 0; i < 256 * kKilobyte; i++) {
      if (auto expected = GetExpectedWriteValue(i, parts, 0xff); expected) {
        ASSERT_EQ(start[i], *expected, "offset = %zu", i);
      }
    }
  }
};

void SyncClientBufferedTest::TestWrite(const std::vector<PartitionInfo>& parts_to_test_write) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientBuffered sync_client_buffered(*std::move(client));

  // Write something to cache.
  for (auto& part : parts_to_test_write) {
    zx::vmo vmo;
    ASSERT_NO_FATAL_FAILURE(
        CreatePayload(part.partition_size, &vmo, part.write_value ? *part.write_value : 0x4a));
    ASSERT_OK(sync_client_buffered.WritePartition(part.partition, vmo, 0));
  }

  // Verify that cache is correctly written.
  for (auto& part : parts_to_test_write) {
    if (part.write_value) {
      auto cache_buffer = sync_client_buffered.GetCacheBuffer(part.partition);
      ASSERT_NOT_NULL(cache_buffer);
      ValidateReadBuffer(cache_buffer, part.partition_size, *part.write_value);
    }
  }

  // Verify that nothing is written to memory yet.
  ASSERT_NO_FATAL_FAILURE(ValidateMemory({}));

  ASSERT_OK(sync_client_buffered.Flush());

  // Veiry that memory is correctly written after flushing
  ASSERT_NO_FATAL_FAILURE(ValidateMemory(parts_to_test_write));
}

constexpr SyncClientBufferedTest::PartitionInfo kLegacySysconfigPartitionInfo = {
    PartitionType::kSysconfig, 0, 60 * kKilobyte, 0x1};
constexpr SyncClientBufferedTest::PartitionInfo kLegacyAbrPartitionInfo = {
    PartitionType::kABRMetadata, 60 * kKilobyte, 4 * kKilobyte, 0x2};
constexpr SyncClientBufferedTest::PartitionInfo kLegacyVbAPartitionInfo = {
    PartitionType::kVerifiedBootMetadataA, 64 * kKilobyte, 64 * kKilobyte, 0x3};
constexpr SyncClientBufferedTest::PartitionInfo kLegacyVbBPartitionInfo = {
    PartitionType::kVerifiedBootMetadataB, 128 * kKilobyte, 64 * kKilobyte, 0x4};
constexpr SyncClientBufferedTest::PartitionInfo kLegacyVbRPartitionInfo = {
    PartitionType::kVerifiedBootMetadataR, 192 * kKilobyte, 64 * kKilobyte, 0x5};

TEST_F(SyncClientBufferedTest, WritePartitionSysconfig) {
  TestWrite({kLegacySysconfigPartitionInfo});
}

TEST_F(SyncClientBufferedTest, WritePartitionAbrMetadata) { TestWrite({kLegacyAbrPartitionInfo}); }

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaA) { TestWrite({kLegacyVbAPartitionInfo}); }

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaB) { TestWrite({kLegacyVbBPartitionInfo}); }

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaR) { TestWrite({kLegacyVbRPartitionInfo}); }

TEST_F(SyncClientBufferedTest, WriteAllPartitions) {
  TestWrite({
      kLegacySysconfigPartitionInfo,
      kLegacyAbrPartitionInfo,
      kLegacyVbAPartitionInfo,
      kLegacyVbBPartitionInfo,
      kLegacyVbRPartitionInfo,
  });
}

void SyncClientBufferedTest::TestRead(const std::vector<PartitionInfo>& parts_to_test_read) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientBuffered sync_client_buffered(*std::move(client));

  // Write something to cache.
  for (auto& part : parts_to_test_read) {
    zx::vmo vmo;
    ASSERT_NO_FATAL_FAILURE(
        CreatePayload(part.partition_size, &vmo, part.write_value ? *part.write_value : 0x4a));
    ASSERT_OK(sync_client_buffered.WritePartition(part.partition, vmo, 0));
  }

  // Verify that data from cache is correctly read.
  for (auto& part : parts_to_test_read) {
    fzl::OwnedVmoMapper mapper;
    ASSERT_OK(mapper.CreateAndMap(part.partition_size, "test"));
    ASSERT_OK(sync_client_buffered.ReadPartition(part.partition, mapper.vmo(), 0));
    uint8_t expected = part.write_value ? *part.write_value : 0x4a;
    ASSERT_NO_FATAL_FAILURE(ValidateReadBuffer(mapper.start(), part.partition_size, expected));
  }

  ASSERT_OK(sync_client_buffered.Flush());

  // Verify that data can still be correctly read after flushing to memory.
  for (auto& part : parts_to_test_read) {
    fzl::OwnedVmoMapper mapper;
    ASSERT_OK(mapper.CreateAndMap(part.partition_size, "test"));
    ASSERT_OK(sync_client_buffered.ReadPartition(part.partition, mapper.vmo(), 0));
    uint8_t expected = part.write_value ? *part.write_value : 0x4a;
    ASSERT_NO_FATAL_FAILURE(ValidateReadBuffer(mapper.start(), part.partition_size, expected));
  }

  // Overwrite the memory with new data directly.
  for (auto& part : parts_to_test_read) {
    ASSERT_NO_FATAL_FAILURE(WriteData(part.partition_offset, part.partition_size));
  }

  // Verify that new data from memory is correctly read.
  for (auto& part : parts_to_test_read) {
    fzl::OwnedVmoMapper mapper;
    ASSERT_OK(mapper.CreateAndMap(part.partition_size, "test"));
    ASSERT_OK(sync_client_buffered.ReadPartition(part.partition, mapper.vmo(), 0));
    ASSERT_NO_FATAL_FAILURE(ValidateReadBuffer(mapper.start(), part.partition_size, 0x5c));
  }
}

TEST_F(SyncClientBufferedTest, ReadPartitionSysconfig) {
  TestRead({kLegacySysconfigPartitionInfo});
}

TEST_F(SyncClientBufferedTest, ReadPartitionAbrMetadata) { TestRead({kLegacyAbrPartitionInfo}); }

TEST_F(SyncClientBufferedTest, ReadPartitionVbMetaA) { TestRead({kLegacyVbAPartitionInfo}); }

TEST_F(SyncClientBufferedTest, ReadPartitionVbMetaB) { TestRead({kLegacyVbBPartitionInfo}); }

TEST_F(SyncClientBufferedTest, ReadPartitionVbMetaR) { TestRead({kLegacyVbRPartitionInfo}); }

TEST_F(SyncClientBufferedTest, ReadAllPartitions) {
  TestRead({
      kLegacySysconfigPartitionInfo,
      kLegacyAbrPartitionInfo,
      kLegacyVbAPartitionInfo,
      kLegacyVbBPartitionInfo,
      kLegacyVbRPartitionInfo,
  });
}

sysconfig_subpartition GetSubpartitionInfo(const sysconfig_header& header,
                                           sysconfig::SyncClient::PartitionType partition) {
  switch (partition) {
    case sysconfig::SyncClient::PartitionType::kSysconfig:
      return header.sysconfig_data;
    case sysconfig::SyncClient::PartitionType::kABRMetadata:
      return header.abr_metadata;
    case sysconfig::SyncClient::PartitionType::kVerifiedBootMetadataA:
      return header.vb_metadata_a;
    case sysconfig::SyncClient::PartitionType::kVerifiedBootMetadataB:
      return header.vb_metadata_b;
    case sysconfig::SyncClient::PartitionType::kVerifiedBootMetadataR:
      return header.vb_metadata_r;
  }
  ZX_ASSERT(false);  // Unreachable.
}

void SyncClientBufferedTest::TestWriteWithHeader(
    const std::vector<PartitionInfo>& parts_to_test_write) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientBuffered sync_client_buffered(*std::move(client));
  // Sysconfig partition starts at the 5th block in this test environment.
  // Please refer to NandInfo() definition.
  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;

  sysconfig_header header = {
      .magic = SYSCONFIG_HEADER_MAGIC_ARRAY,
      .sysconfig_data = {200 * kKilobyte, 56 * kKilobyte},
      .abr_metadata = {196 * kKilobyte, 4 * kKilobyte},
      .vb_metadata_a = {4 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_b = {68 * kKilobyte, 64 * kKilobyte},
      .vb_metadata_r = {132 * kKilobyte, 64 * kKilobyte},
  };
  update_sysconfig_header_magic_and_crc(&header);
  memcpy(memory, &header, sizeof(header));

  for (auto& part : parts_to_test_write) {
    if (!part.write_value) {
      continue;
    }
    auto subpartition_info = GetSubpartitionInfo(header, part.partition);
    zx::vmo vmo;
    ASSERT_NO_FATAL_FAILURE(
        CreatePayload(subpartition_info.size, &vmo, part.write_value ? *part.write_value : 0x4a));
    ASSERT_OK(sync_client_buffered.WritePartition(part.partition, vmo, 0));
  }

  ASSERT_OK(sync_client_buffered.Flush());

  // set sub-partition offset and size according to our test header.
  auto parts_copy = parts_to_test_write;
  for (auto& part : parts_copy) {
    auto subpartition_info = GetSubpartitionInfo(header, part.partition);
    part.partition_offset = subpartition_info.offset;
    part.partition_size = subpartition_info.size;
  }

  // Header in storage shall not change
  ASSERT_BYTES_EQ(memory, &header, sizeof(header));

  // make a dummy header partition to exempt it from validation
  parts_copy.push_back({.partition_offset = 0, .partition_size = 4 * kKilobyte, .write_value = {}});

  ASSERT_NO_FATAL_FAILURE(ValidateMemory(parts_copy));
}

TEST_F(SyncClientBufferedTest, WritePartitionSysconfigWithHeader) {
  // Subpartition position determined by header. No need to pass offset and size here.
  TestWriteWithHeader({{PartitionType::kSysconfig, 0, 0, 0x4a}});
}

TEST_F(SyncClientBufferedTest, WritePartitionAbrMetadataWithHeader) {
  TestWriteWithHeader({{PartitionType::kABRMetadata, 0, 0, 0x4a}});
}

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaAWithHeader) {
  TestWriteWithHeader({{PartitionType::kVerifiedBootMetadataA, 0, 0, 0x4a}});
}

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaBWithHeader) {
  TestWriteWithHeader({{PartitionType::kVerifiedBootMetadataB, 0, 0, 0x4a}});
}

TEST_F(SyncClientBufferedTest, WritePartitionVbMetaRWithHeader) {
  TestWriteWithHeader({{PartitionType::kVerifiedBootMetadataR, 0, 0, 0x4a}});
}

TEST_F(SyncClientBufferedTest, WriteAllPartitionsWithHeader) {
  TestWriteWithHeader({{PartitionType::kSysconfig, 0, 0, 0x1},
                       {PartitionType::kABRMetadata, 0, 0, 0x2},
                       {PartitionType::kVerifiedBootMetadataA, 0, 0, 0x3},
                       {PartitionType::kVerifiedBootMetadataB, 0, 0, 0x4},
                       {PartitionType::kVerifiedBootMetadataR, 0, 0, 0x5}});
}

enum class VerifyAbrPageMagic { ON, OFF };
void VerifyAbrMetaDataPage(const abr_metadata_ext& abr_data, uint8_t value,
                           VerifyAbrPageMagic opt = VerifyAbrPageMagic::ON) {
  uint8_t expected[ABR_WEAR_LEVELING_ABR_DATA_SIZE];
  memset(expected, value, ABR_WEAR_LEVELING_ABR_DATA_SIZE);
  ASSERT_BYTES_EQ(&abr_data, expected, ABR_WEAR_LEVELING_ABR_DATA_SIZE);
  if (opt == VerifyAbrPageMagic::ON) {
    uint8_t magic[] = {
        ABR_WEAR_LEVELING_MAGIC_BYTE_0,
        ABR_WEAR_LEVELING_MAGIC_BYTE_1,
        ABR_WEAR_LEVELING_MAGIC_BYTE_2,
        ABR_WEAR_LEVELING_MAGIC_BYTE_3,
    };
    ASSERT_BYTES_EQ(abr_data.magic, magic, ABR_WEAR_LEVELING_MAGIC_LEN);
  }
}

TEST_F(SyncClientBufferedTest, AbrWearLevelingUnsupportedLayout) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);
  sysconfig::SyncClientAbrWearLeveling astro_client(*std::move(client));

  size_t partition_size;
  ASSERT_OK(astro_client.GetPartitionSize(PartitionType::kABRMetadata, &partition_size));

  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(partition_size, &vmo, 0xa5));
  ASSERT_OK(astro_client.WritePartition(PartitionType::kABRMetadata, vmo, 0));
  ASSERT_OK(astro_client.Flush());

  // The new abr data should still be at the 16th page as it will use default flush.
  ASSERT_NO_FATAL_FAILURE(
      ValidateMemory({{PartitionType::kABRMetadata, 60 * kKilobyte, 4 * kKilobyte, 0xa5}}));

  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(partition_size, "test"));
  ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));
  abr_metadata_ext abr_data;
  memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
  ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, 0xa5, VerifyAbrPageMagic::OFF));
}

sysconfig_header WriteHeaderSupportingAbrWearLeveling(void* memory) {
  // Provide a supporting header in storage.
  auto header = sysconfig::SyncClientAbrWearLeveling::GetAbrWearLevelingSupportedLayout();
  memcpy(memory, &header, sizeof(header));
  return header;
}

TEST_F(SyncClientBufferedTest, AbrWearLeveling) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientAbrWearLeveling astro_client(*std::move(client));
  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;
  auto header = WriteHeaderSupportingAbrWearLeveling(memory);

  uint8_t empty_page[kPageSize];
  memset(empty_page, 0xff, sizeof(empty_page));
  size_t abr_part_size;
  ASSERT_OK(astro_client.GetPartitionSize(PartitionType::kABRMetadata, &abr_part_size));
  const size_t num_pages = header.abr_metadata.size / kPageSize;
  // Verify that client can write abr meta data <num_pages> times without an erase.
  for (uint8_t i = 0; i < num_pages; i++) {
    zx::vmo vmo;
    // Fill the payload with value |i+1|.
    ASSERT_NO_FATAL_FAILURE(CreatePayload(abr_part_size, &vmo, i + 1));
    ASSERT_OK(astro_client.WritePartition(PartitionType::kABRMetadata, vmo, 0));
    ASSERT_OK(astro_client.Flush());
    ASSERT_EQ(astro_client.GetEraseCount(), 0);

    abr_metadata_ext abr_data;

    // Validate that memory is as expected:
    //
    // 1. Previous and newly written pages are as expected.
    auto abr_subpart = memory + header.abr_metadata.offset;
    for (uint8_t j = 0; j <= i; j++) {
      memcpy(&abr_data, abr_subpart + j * kPageSize, sizeof(abr_data));
      ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, j + 1));
    }
    // 2. Pages after stay empty.
    for (uint8_t j = i + 1; j < num_pages; j++) {
      ASSERT_BYTES_EQ(abr_subpart + j * kPageSize, empty_page, kPageSize, "@ page %d", j);
    }

    // Verify that latest abr meta data can be correctly read.
    fzl::OwnedVmoMapper mapper;
    ASSERT_OK(mapper.CreateAndMap(abr_part_size, "test"));
    ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));

    memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
    ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, i + 1));
  }

  // Verify that the |num_pages + 1|th write should introduce an erase.
  zx::vmo vmo;
  ASSERT_NO_FATAL_FAILURE(CreatePayload(abr_part_size, &vmo, 0xAB));
  ASSERT_OK(astro_client.WritePartition(PartitionType::kABRMetadata, vmo, 0));
  ASSERT_OK(astro_client.Flush());
  ASSERT_EQ(astro_client.GetEraseCount(), 1);

  // Verify that the (<num_pages> + 1)th write is correct.
  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(abr_part_size, "test"));
  ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));

  abr_metadata_ext abr_data;
  memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
  ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, 0xAB));
}

TEST_F(SyncClientBufferedTest, AbrWearLevelingMultiplePartitionsModifiedInCache) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientAbrWearLeveling astro_client(*std::move(client));
  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;
  auto header = WriteHeaderSupportingAbrWearLeveling(memory);

  auto write_partition = [&](PartitionType partition, uint8_t data) {
    zx::vmo vmo;
    size_t part_size;
    ASSERT_OK(astro_client.GetPartitionSize(partition, &part_size));
    ASSERT_NO_FATAL_FAILURE(CreatePayload(part_size, &vmo, data));
    ASSERT_OK(astro_client.WritePartition(partition, vmo, 0));
  };

  // Write multiple sub-partitions: vb_a, vb_r and abr
  ASSERT_NO_FATAL_FAILURE(write_partition(PartitionType::kVerifiedBootMetadataA, 0xAB));
  ASSERT_NO_FATAL_FAILURE(write_partition(PartitionType::kVerifiedBootMetadataR, 0xCD));
  ASSERT_NO_FATAL_FAILURE(write_partition(PartitionType::kABRMetadata, 0xEF));

  // Verify that for flushing changes more than just abr metadata introduce an erase
  ASSERT_EQ(astro_client.GetEraseCount(), 0);
  ASSERT_OK(astro_client.Flush());
  ASSERT_EQ(astro_client.GetEraseCount(), 1);

  // Verify that abr data is correctly written
  size_t abr_part_size;
  ASSERT_OK(astro_client.GetPartitionSize(PartitionType::kABRMetadata, &abr_part_size));
  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(abr_part_size, "test"));
  ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));

  abr_metadata_ext abr_data;
  memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
  ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, 0xEF));

  // Veiry that all partition are written correctly
  ASSERT_NO_FATAL_FAILURE(ValidateMemory(
      {// a place holder header partition to exempt it from validation
       {.partition_offset = 0, .partition_size = 4 * kKilobyte, .write_value = {}},
       // dont care sysconfig
       {PartitionType::kSysconfig, header.sysconfig_data.offset, header.sysconfig_data.size, {}},
       // abr metadata in the first page has just been validated. Exempt it.
       {PartitionType::kABRMetadata, header.abr_metadata.offset, kPageSize, {}},
       // the rest of pages in abr partition should be reset to 0xff
       {PartitionType::kABRMetadata, header.abr_metadata.offset + kPageSize,
        header.abr_metadata.size - kPageSize, 0xff},
       // vb metadata a
       {PartitionType::kVerifiedBootMetadataA, header.vb_metadata_a.offset,
        header.vb_metadata_a.size, 0xAB},
       // vb metadata r
       {PartitionType::kVerifiedBootMetadataR, header.vb_metadata_r.offset,
        header.vb_metadata_r.size, 0xCD}}));

  // Introduces an additional abr writes.
  // Since we just performed a reset flush, there should be enough empty pages for the
  // write. It shouldn't introduce additional erase.
  ASSERT_NO_FATAL_FAILURE(write_partition(PartitionType::kABRMetadata, 0x01));

  ASSERT_OK(astro_client.Flush());
  ASSERT_EQ(astro_client.GetEraseCount(), 1);

  // Read back the new abr meta and validate it is correct.
  ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));
  memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
  ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, 0x1));
}

TEST_F(SyncClientBufferedTest, AbrWearLevelingDefaultToFirstPage) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientAbrWearLeveling astro_client(*std::move(client));
  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;
  auto header = WriteHeaderSupportingAbrWearLeveling(memory);

  // Write data to all pages such that none contains valid magic values.
  const size_t num_pages = header.abr_metadata.size / kPageSize;
  for (uint8_t i = 0; i < num_pages; i++) {
    zx::vmo vmo;
    WriteData(header.abr_metadata.offset + i * kPageSize, kPageSize, i + 1);
  }

  // Verify that the read will default to the 1st page in abr sub-partition.
  fzl::OwnedVmoMapper mapper;
  ASSERT_OK(mapper.CreateAndMap(kPageSize, "test"));
  ASSERT_OK(astro_client.ReadPartition(PartitionType::kABRMetadata, mapper.vmo(), 0));

  abr_metadata_ext abr_data;
  memcpy(&abr_data, mapper.start(), sizeof(abr_metadata_ext));
  ASSERT_NO_FATAL_FAILURE(VerifyAbrMetaDataPage(abr_data, 0x1, VerifyAbrPageMagic::OFF));
}

TEST_F(SyncClientBufferedTest, ValidateAbrMetadataInStorageFail) {
  zx::result client = sysconfig::SyncClient::Create(device_->devfs_root());
  ASSERT_OK(client);

  sysconfig::SyncClientAbrWearLeveling astro_client(*std::move(client));
  auto memory = static_cast<uint8_t*>(device_->mapper().start()) + 4 * kBlockSize;
  auto header = WriteHeaderSupportingAbrWearLeveling(memory);

  size_t abr_part_size;
  ASSERT_OK(astro_client.GetPartitionSize(PartitionType::kABRMetadata, &abr_part_size));
  const size_t num_pages = header.abr_metadata.size / kPageSize;
  // Verify that abr read validation can detect error wherever the latest abr page is.
  for (uint8_t i = 0; i < num_pages; i++) {
    zx::vmo vmo;
    // Fill the payload with value |i+1|.
    ASSERT_NO_FATAL_FAILURE(CreatePayload(abr_part_size, &vmo, i + 1));
    ASSERT_OK(astro_client.WritePartition(PartitionType::kABRMetadata, vmo, 0));
    ASSERT_OK(astro_client.Flush());

    abr_metadata_ext abr_data;
    memset(abr_data.abr_data, i, sizeof(abr_data.abr_data));
    ASSERT_NOT_OK(astro_client.ValidateAbrMetadataInStorage(&abr_data));
  }
}

}  // namespace
