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

#include <endian.h>
#include <fcntl.h>
#include <fuchsia/boot/llcpp/fidl.h>
#include <fuchsia/hardware/nand/c/fidl.h>
#include <fuchsia/paver/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/cksum.h>
#include <lib/fdio/directory.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fzl/fdio.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/paver/provider.h>
#include <lib/zx/vmo.h>
#include <zircon/hw/gpt.h>

#include <optional>

#include <fbl/algorithm.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fs/pseudo_dir.h>
#include <fs/service.h>
#include <fs/synchronous_vfs.h>
#include <zxtest/zxtest.h>

#include "device-partitioner.h"
#include "paver.h"
#include "test/test-utils.h"

namespace {

using devmgr_integration_test::IsolatedDevmgr;
using devmgr_integration_test::RecursiveWaitForFile;

constexpr fuchsia_hardware_nand_RamNandInfo
    kNandInfo =
        {
            .vmo = ZX_HANDLE_INVALID,
            .nand_info =
                {
                    .page_size = kPageSize,
                    .pages_per_block = kPagesPerBlock,
                    .num_blocks = kNumBlocks,
                    .ecc_bits = 8,
                    .oob_size = kOobSize,
                    .nand_class = fuchsia_hardware_nand_Class_PARTMAP,
                    .partition_guid = {},
                },
            .partition_map =
                {
                    .device_guid = {},
                    .partition_count = 6,
                    .partitions =
                        {
                            {
                                .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_BOOTLOADER_VALUE,
                                .unique_guid = {},
                                .first_block = 4,
                                .last_block = 7,
                                .copy_count = 0,
                                .copy_byte_offset = 0,
                                .name = {'b', 'o', 'o', 't', 'l', 'o', 'a', 'd', 'e', 'r'},
                                .hidden = false,
                                .bbt = false,
                            },
                            {
                                .type_guid = GUID_ZIRCON_A_VALUE,
                                .unique_guid = {},
                                .first_block = 8,
                                .last_block = 9,
                                .copy_count = 0,
                                .copy_byte_offset = 0,
                                .name = {'z', 'i', 'r', 'c', 'o', 'n', '-', 'a'},
                                .hidden = false,
                                .bbt = false,
                            },
                            {
                                .type_guid = GUID_ZIRCON_B_VALUE,
                                .unique_guid = {},
                                .first_block = 10,
                                .last_block = 11,
                                .copy_count = 0,
                                .copy_byte_offset = 0,
                                .name = {'z', 'i', 'r', 'c', 'o', 'n', '-', 'b'},
                                .hidden = false,
                                .bbt = false,
                            },
                            {
                                .type_guid = GUID_ZIRCON_R_VALUE,
                                .unique_guid = {},
                                .first_block = 12,
                                .last_block = 13,
                                .copy_count = 0,
                                .copy_byte_offset = 0,
                                .name = {'z', 'i', 'r', 'c', 'o', 'n', '-', 'r'},
                                .hidden = false,
                                .bbt = false,
                            },
                            {
                                .type_guid = GUID_SYS_CONFIG_VALUE,
                                .unique_guid = {},
                                .first_block = 14,
                                .last_block = 17,
                                .copy_count = 0,
                                .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 FakeBootArgs : public ::llcpp::fuchsia::boot::Arguments::Interface {
 public:
  zx_status_t Connect(async_dispatcher_t* dispatcher, zx::channel request) {
    return fidl::Bind(dispatcher, std::move(request), this);
  }

  void Get(GetCompleter::Sync completer) {
    zx::vmo vmo;
    zx::vmo::create(fbl::round_up(sizeof(kArgs), ZX_PAGE_SIZE), 0, &vmo);
    vmo.write(kArgs, 0, sizeof(kArgs));
    completer.Reply(std::move(vmo), sizeof(kArgs));
  }

 private:
  static constexpr char kArgs[] = "zvb.current_slot=-a";
};

class FakeSvc {
 public:
  explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
    auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
    root_dir->AddEntry(::llcpp::fuchsia::boot::Arguments::Name,
                       fbl::MakeRefCounted<fs::Service>([this](zx::channel request) {
                         return fake_boot_args_.Connect(dispatcher_, std::move(request));
                       }));

    zx::channel svc_remote;
    ASSERT_OK(zx::channel::create(0, &svc_local_, &svc_remote));

    vfs_.ServeDirectory(root_dir, std::move(svc_remote));
  }

  FakeBootArgs& fake_boot_args() { return fake_boot_args_; }
  zx::channel& svc_chan() { return svc_local_; }

 private:
  async_dispatcher_t* dispatcher_;
  fs::SynchronousVfs vfs_;
  FakeBootArgs fake_boot_args_;
  zx::channel svc_local_;
};

class PaverServiceTest : public zxtest::Test {
 public:
  PaverServiceTest();

  ~PaverServiceTest();

 protected:
  void CreatePayload(size_t num_pages, ::llcpp::fuchsia::mem::Buffer* out);

  static constexpr size_t kKilobyte = 1 << 10;

  void ValidateWritten(const ::llcpp::fuchsia::mem::Buffer& buf, size_t num_pages) {
    ASSERT_GE(buf.size, num_pages * kPageSize);
    fzl::VmoMapper mapper;
    ASSERT_OK(mapper.Map(buf.vmo, 0, fbl::round_up(num_pages * kPageSize, ZX_PAGE_SIZE),
                         ZX_VM_PERM_READ));
    const uint8_t* start = reinterpret_cast<uint8_t*>(mapper.start());
    for (size_t i = 0; i < num_pages * kPageSize; i++) {
      ASSERT_EQ(start[i], 0x4a, "i = %zu", i);
    }
  }

  void* provider_ctx_ = nullptr;
  std::optional<::llcpp::fuchsia::paver::Paver::SyncClient> client_;
  async::Loop loop_;
  // The paver makes synchronous calls into /svc, so it must run in a seperate loop to not
  // deadlock.
  async::Loop loop2_;
  FakeSvc fake_svc_;
};

PaverServiceTest::PaverServiceTest()
    : loop_(&kAsyncLoopConfigAttachToCurrentThread),
      loop2_(&kAsyncLoopConfigNoAttachToCurrentThread),
      fake_svc_(loop2_.dispatcher()) {
  zx::channel client, server;
  ASSERT_OK(zx::channel::create(0, &client, &server));

  client_.emplace(std::move(client));

  ASSERT_OK(paver_get_service_provider()->ops->init(&provider_ctx_));

  ASSERT_OK(paver_get_service_provider()->ops->connect(
      provider_ctx_, loop_.dispatcher(), ::llcpp::fuchsia::paver::Paver::Name, server.release()));
  loop_.StartThread("paver-svc-test-loop");
  loop2_.StartThread("paver-svc-test-loop-2");
}

PaverServiceTest::~PaverServiceTest() {
  loop_.Shutdown();
  loop2_.Shutdown();
  paver_get_service_provider()->ops->release(provider_ctx_);
  provider_ctx_ = nullptr;
}

void PaverServiceTest::CreatePayload(size_t num_pages, ::llcpp::fuchsia::mem::Buffer* out) {
  zx::vmo vmo;
  fzl::VmoMapper mapper;
  const size_t size = kPageSize * num_pages;
  ASSERT_OK(mapper.CreateAndMap(size, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
  memset(mapper.start(), 0x4a, mapper.size());
  out->vmo = std::move(vmo);
  out->size = size;
}

class PaverServiceSkipBlockTest : public PaverServiceTest {
 public:
  PaverServiceSkipBlockTest() {
    ASSERT_NO_FATAL_FAILURES(SpawnIsolatedDevmgr());
    ASSERT_NO_FATAL_FAILURES(WaitForSysconfig());
  }

 protected:
  void SpawnIsolatedDevmgr() {
    ASSERT_EQ(device_.get(), nullptr);
    SkipBlockDevice::Create(kNandInfo, &device_);
    static_cast<paver::Paver*>(provider_ctx_)->set_devfs_root(device_->devfs_root());
    static_cast<paver::Paver*>(provider_ctx_)->set_svc_root(std::move(fake_svc_.svc_chan()));
  }

  void WaitForSysconfig() {
    fbl::unique_fd fd;
    ASSERT_OK(RecursiveWaitForFile(device_->devfs_root(),
                                   "misc/nand-ctl/ram-nand-0/sysconfig/skip-block", &fd));
  }

  void SetAbr(const abr::Data& data) {
    auto* buf = reinterpret_cast<uint8_t*>(device_->mapper().start()) + (14 * kSkipBlockSize) +
                (60 * kKilobyte);
    *reinterpret_cast<abr::Data*>(buf) = data;
  }

  abr::Data GetAbr() {
    auto* buf = reinterpret_cast<uint8_t*>(device_->mapper().start()) + (14 * kSkipBlockSize) +
                (60 * kKilobyte);
    return *reinterpret_cast<abr::Data*>(buf);
  }

  using PaverServiceTest::ValidateWritten;

  void ValidateWritten(uint32_t block, size_t num_blocks) {
    const uint8_t* start =
        static_cast<uint8_t*>(device_->mapper().start()) + (block * kSkipBlockSize);
    for (size_t i = 0; i < kSkipBlockSize * num_blocks; i++) {
      ASSERT_EQ(start[i], 0x4a, "i = %zu", i);
    }
  }

  void ValidateUnwritten(uint32_t block, size_t num_blocks) {
    const uint8_t* start =
        static_cast<uint8_t*>(device_->mapper().start()) + (block * kSkipBlockSize);
    for (size_t i = 0; i < kSkipBlockSize * num_blocks; i++) {
      ASSERT_EQ(start[i], 0xff, "i = %zu", i);
    }
  }

  void ValidateWrittenPages(uint32_t page, size_t num_pages) {
    const uint8_t* start =
        static_cast<uint8_t*>(device_->mapper().start()) + (page * kPageSize);
    for (size_t i = 0; i < kPageSize * num_pages; i++) {
      ASSERT_EQ(start[i], 0x4a, "i = %zu", i);
    }
  }

  void ValidateUnwrittenPages(uint32_t page, size_t num_pages) {
    const uint8_t* start =
        static_cast<uint8_t*>(device_->mapper().start()) + (page * kPageSize);
    for (size_t i = 0; i < kPageSize * num_pages; i++) {
      ASSERT_EQ(start[i], 0xff, "i = %zu", i);
    }
  }

  void WriteData(uint32_t page, size_t num_pages, uint8_t data) {
    uint8_t* start =
        static_cast<uint8_t*>(device_->mapper().start()) + (page * kPageSize);
    memset(start, data, kPageSize * num_pages);
  }


  fbl::unique_ptr<SkipBlockDevice> device_;
};

constexpr abr::Data kAbrData = {
    .magic = {'\0', 'A', 'B', '0'},
    .version_major = abr::kMajorVersion,
    .version_minor = abr::kMinorVersion,
    .reserved1 = {},
    .slots =
        {
            {
                .priority = 0,
                .tries_remaining = 0,
                .successful_boot = 0,
                .reserved = {},
            },
            {
                .priority = 1,
                .tries_remaining = 0,
                .successful_boot = 1,
                .reserved = {},
            },
        },
    .oneshot_recovery_boot = 0,
    .reserved2 = {},
    .crc32 = {},
};

void ComputeCrc(abr::Data* data) {
  data->crc32 = htobe32(
      crc32(0, reinterpret_cast<const uint8_t*>(data), offsetof(abr::Data, crc32)));
}

TEST_F(PaverServiceSkipBlockTest, InitializeAbr) {
  abr::Data abr_data = {};
  memset(&abr_data, 0x3d, sizeof(abr_data));
  SetAbr(abr_data);

  auto result = client_->InitializeAbr();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
}

TEST_F(PaverServiceSkipBlockTest, InitializeAbrAlreadyValid) {
  abr::Data abr_data = kAbrData;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->InitializeAbr();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
}

TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationInvalidAbr) {
  abr::Data abr_data = {};
  memset(&abr_data, 0x3d, sizeof(abr_data));
  SetAbr(abr_data);

  auto result = client_->QueryActiveConfiguration();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_err());
  ASSERT_STATUS(result->result.err(), ZX_ERR_NOT_SUPPORTED);
}

TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationBothPriority0) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[0].priority = 0;
  abr_data.slots[1].priority = 0;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryActiveConfiguration();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_err());
  ASSERT_STATUS(result->result.err(), ZX_ERR_NOT_SUPPORTED);
}

TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationSlotB) {
  abr::Data abr_data = kAbrData;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryActiveConfiguration();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ASSERT_EQ(result->result.response().configuration, ::llcpp::fuchsia::paver::Configuration::B);
}

TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationSlotA) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[0].priority = 2;
  abr_data.slots[0].successful_boot = 1;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryActiveConfiguration();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ASSERT_EQ(result->result.response().configuration, ::llcpp::fuchsia::paver::Configuration::A);
}

TEST_F(PaverServiceSkipBlockTest, QueryConfigurationStatusHealthy) {
  abr::Data abr_data = kAbrData;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryConfigurationStatus(::llcpp::fuchsia::paver::Configuration::B);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ASSERT_EQ(result->result.response().status,
            ::llcpp::fuchsia::paver::ConfigurationStatus::HEALTHY);
}

TEST_F(PaverServiceSkipBlockTest, QueryConfigurationStatusPending) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[1].successful_boot = 0;
  abr_data.slots[1].tries_remaining = 1;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryConfigurationStatus(::llcpp::fuchsia::paver::Configuration::B);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ASSERT_EQ(result->result.response().status,
            ::llcpp::fuchsia::paver::ConfigurationStatus::PENDING);
}

TEST_F(PaverServiceSkipBlockTest, QueryConfigurationStatusUnbootable) {
  abr::Data abr_data = kAbrData;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->QueryConfigurationStatus(::llcpp::fuchsia::paver::Configuration::A);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ASSERT_EQ(result->result.response().status,
            ::llcpp::fuchsia::paver::ConfigurationStatus::UNBOOTABLE);
}

TEST_F(PaverServiceSkipBlockTest, SetConfigurationActive) {
  abr::Data abr_data = kAbrData;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  abr_data.slots[0].priority = 2;
  abr_data.slots[0].tries_remaining = abr::kMaxTriesRemaining;
  abr_data.slots[0].successful_boot = 0;
  ComputeCrc(&abr_data);

  auto result = client_->SetConfigurationActive(::llcpp::fuchsia::paver::Configuration::A);
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  auto actual = GetAbr();
  ASSERT_BYTES_EQ(&abr_data, &actual, sizeof(abr_data));
}

TEST_F(PaverServiceSkipBlockTest, SetConfigurationActiveRollover) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[1].priority = abr::kMaxPriority;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  abr_data.slots[1].priority = 1;
  abr_data.slots[0].priority = 2;
  abr_data.slots[0].tries_remaining = abr::kMaxTriesRemaining;
  abr_data.slots[0].successful_boot = 0;
  ComputeCrc(&abr_data);

  auto result = client_->SetConfigurationActive(::llcpp::fuchsia::paver::Configuration::A);
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  auto actual = GetAbr();
  ASSERT_BYTES_EQ(&abr_data, &actual, sizeof(abr_data));
}

TEST_F(PaverServiceSkipBlockTest, SetConfigurationUnbootableSlotA) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[0].priority = 2;
  abr_data.slots[0].tries_remaining = 3;
  abr_data.slots[0].successful_boot = 0;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  abr_data.slots[0].priority = 0;
  abr_data.slots[0].tries_remaining = 0;
  abr_data.slots[0].successful_boot = 0;
  ComputeCrc(&abr_data);

  auto result = client_->SetConfigurationUnbootable(::llcpp::fuchsia::paver::Configuration::A);
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  auto actual = GetAbr();
  ASSERT_BYTES_EQ(&abr_data, &actual, sizeof(abr_data));
}

TEST_F(PaverServiceSkipBlockTest, SetConfigurationUnbootableSlotB) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[1].tries_remaining = 3;
  abr_data.slots[1].successful_boot = 0;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  abr_data.slots[1].priority = 0;
  abr_data.slots[1].tries_remaining = 0;
  abr_data.slots[1].successful_boot = 0;
  ComputeCrc(&abr_data);

  auto result = client_->SetConfigurationUnbootable(::llcpp::fuchsia::paver::Configuration::B);
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  auto actual = GetAbr();
  ASSERT_BYTES_EQ(&abr_data, &actual, sizeof(abr_data));
}

TEST_F(PaverServiceSkipBlockTest, SetActiveConfigurationHealthy) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[1].tries_remaining = 3;
  abr_data.slots[1].successful_boot = 0;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  abr_data.slots[1].tries_remaining = 0;
  abr_data.slots[1].successful_boot = 1;
  ComputeCrc(&abr_data);

  auto result = client_->SetActiveConfigurationHealthy();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  auto actual = GetAbr();
  ASSERT_BYTES_EQ(&abr_data, &actual, sizeof(abr_data));
}

TEST_F(PaverServiceSkipBlockTest, SetActiveConfigurationHealthyBothPriorityZero) {
  abr::Data abr_data = kAbrData;
  abr_data.slots[1].tries_remaining = 3;
  abr_data.slots[1].successful_boot = 0;
  abr_data.slots[1].priority = 0;
  ComputeCrc(&abr_data);
  SetAbr(abr_data);

  auto result = client_->SetActiveConfigurationHealthy();
  ASSERT_OK(result.status());
  ASSERT_NE(result->status, ZX_OK);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetKernelConfigA) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(2 * kPagesPerBlock, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::A,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL, std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWritten(8, 2);
  ValidateUnwritten(10, 4);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetKernelConfigB) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(2 * kPagesPerBlock, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::B,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL, std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateUnwritten(8, 2);
  ValidateWritten(10, 2);
  ValidateUnwritten(12, 2);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetKernelConfigRecovery) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(2 * kPagesPerBlock, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::RECOVERY,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL, std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateUnwritten(8, 4);
  ValidateWritten(12, 2);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetVbMetaConfigA) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(32, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::A,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA,
                                    std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWrittenPages(14 * kPagesPerBlock + 32, 32);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetVbMetaConfigB) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(32, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::B,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA,
                                    std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWrittenPages(14 * kPagesPerBlock + 64, 32);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetVbMetaConfigRecovery) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(32, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::RECOVERY,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA,
                                    std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWrittenPages(14 * kPagesPerBlock + 96, 32);
}

TEST_F(PaverServiceSkipBlockTest, WriteAssetTwice) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(2 * kPagesPerBlock, &payload);
  auto result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::A,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL, std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  CreatePayload(2 * kPagesPerBlock, &payload);
  ValidateWritten(8, 2);
  ValidateUnwritten(10, 4);
  result = client_->WriteAsset(::llcpp::fuchsia::paver::Configuration::A,
                               ::llcpp::fuchsia::paver::Asset::KERNEL, std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWritten(8, 2);
  ValidateUnwritten(10, 4);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetKernelConfigA) {
  WriteData(8 * kPagesPerBlock, 2 * kPagesPerBlock, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::A,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 2 * kPagesPerBlock);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetKernelConfigB) {
  WriteData(10 * kPagesPerBlock, 2 * kPagesPerBlock, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::B,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 2 * kPagesPerBlock);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetKernelConfigRecovery) {
  WriteData(12 * kPagesPerBlock, 2 * kPagesPerBlock, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::RECOVERY,
                                    ::llcpp::fuchsia::paver::Asset::KERNEL);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 2 * kPagesPerBlock);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetVbMetaConfigA) {
  WriteData(14 * kPagesPerBlock + 32, 32, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::A,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 32);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetVbMetaConfigB) {
  WriteData(14 * kPagesPerBlock + 64, 32, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::B,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 32);
}

TEST_F(PaverServiceSkipBlockTest, ReadAssetVbMetaConfigRecovery) {
  WriteData(14 * kPagesPerBlock + 96, 32, 0x4a);
  auto result = client_->ReadAsset(::llcpp::fuchsia::paver::Configuration::RECOVERY,
                                    ::llcpp::fuchsia::paver::Asset::VERIFIED_BOOT_METADATA);
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->result.is_response());
  ValidateWritten(result->result.response().asset, 32);
}

TEST_F(PaverServiceSkipBlockTest, WriteBootloader) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(4 * kPagesPerBlock, &payload);
  auto result = client_->WriteBootloader(std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWritten(4, 4);
}

// We prefill the bootloader partition with the expected data, leaving the last block as 0xFF.
// Normally the last page would be overwritten with 0s, but because the actual payload is identical,
// we don't actually pave the image, so the extra page stays as 0xFF.
TEST_F(PaverServiceSkipBlockTest, WriteBootloaderNotAligned) {
  ::llcpp::fuchsia::mem::Buffer payload;
  CreatePayload(4 * kPagesPerBlock, &payload);
  payload.size = 4 * kPagesPerBlock - 1;
  WriteData(4 * kPagesPerBlock, 4 * kPagesPerBlock - 1, 0x4a);
  WriteData(8 * kPagesPerBlock - 1 , 1, 0xff);
  auto result = client_->WriteBootloader(std::move(payload));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
  ValidateWrittenPages(4 * kPagesPerBlock, 4 * kPagesPerBlock - 1);
  ValidateUnwrittenPages(8 * kPagesPerBlock - 1, 1);
}

TEST_F(PaverServiceSkipBlockTest, WriteDataFile) {
  // TODO(ZX-4007): Figure out a way to test this.
}

TEST_F(PaverServiceSkipBlockTest, WriteVolumes) {
  // TODO(ZX-4007): Figure out a way to test this.
}

TEST_F(PaverServiceSkipBlockTest, WipeVolumes) {
  // TODO(ZX-4007): Figure out a way to test this.
}

// TODO(34771): Re-enable once bug in GPT is fixed.
#if 0
class PaverServiceBlockTest : public PaverServiceTest {
 public:
  PaverServiceBlockTest() {
    ASSERT_NO_FATAL_FAILURES(SpawnIsolatedDevmgr());
  }

 protected:
  void SpawnIsolatedDevmgr() {
    devmgr_launcher::Args args;
    args.sys_device_driver = IsolatedDevmgr::kSysdevDriver;
    args.driver_search_paths.push_back("/boot/driver");
    args.disable_block_watcher = true;
    ASSERT_OK(IsolatedDevmgr::Create(std::move(args), &devmgr_));

    fbl::unique_fd fd;
    ASSERT_OK(RecursiveWaitForFile(devmgr_.devfs_root(), "misc/ramctl", &fd));
    static_cast<paver::Paver*>(provider_ctx_)->set_devfs_root(devmgr_.devfs_root().duplicate());
    static_cast<paver::Paver*>(provider_ctx_)->set_svc_root(std::move(fake_svc_.svc_chan()));
  }

  IsolatedDevmgr devmgr_;
};

#if defined(__x86_64__)
constexpr uint8_t kEmptyType[GPT_GUID_LEN] = GUID_EMPTY_VALUE;

TEST_F(PaverServiceBlockTest, InitializePartitionTables) {
  fbl::unique_ptr<BlockDevice> gpt_dev;
  constexpr uint64_t block_count = (1LU << 34) / kBlockSize;
  ASSERT_NO_FATAL_FAILURES(BlockDevice::Create(devmgr_.devfs_root(), kEmptyType, block_count,
                                               &gpt_dev));

  zx::channel gpt_chan;
  ASSERT_OK(fdio_fd_clone(gpt_dev->fd(), gpt_chan.reset_and_get_address()));

  auto result = client_->InitializePartitionTables(std::move(gpt_chan));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
}

TEST_F(PaverServiceBlockTest, InitializePartitionTablesMultipleDevices) {
  fbl::unique_ptr<BlockDevice> gpt_dev1, gpt_dev2;
  constexpr uint64_t block_count = (1LU << 34) / kBlockSize;
  ASSERT_NO_FATAL_FAILURES(BlockDevice::Create(devmgr_.devfs_root(), kEmptyType, block_count,
                                               &gpt_dev1));
  ASSERT_NO_FATAL_FAILURES(BlockDevice::Create(devmgr_.devfs_root(), kEmptyType, block_count,
                                               &gpt_dev2));

  zx::channel gpt_chan;
  ASSERT_OK(fdio_fd_clone(gpt_dev1->fd(), gpt_chan.reset_and_get_address()));

  auto result = client_->InitializePartitionTables(std::move(gpt_chan));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);
}

TEST_F(PaverServiceBlockTest, WipePartitionTables) {
  fbl::unique_ptr<BlockDevice> gpt_dev;
  constexpr uint64_t block_count = (1LU << 34) / kBlockSize;
  ASSERT_NO_FATAL_FAILURES(BlockDevice::Create(devmgr_.devfs_root(), kEmptyType, block_count,
                                               &gpt_dev));

  zx::channel gpt_chan;
  ASSERT_OK(fdio_fd_clone(gpt_dev->fd(), gpt_chan.reset_and_get_address()));

  auto result = client_->InitializePartitionTables(std::move(gpt_chan));
  ASSERT_OK(result.status());
  ASSERT_OK(result.value().status);

  ASSERT_OK(fdio_fd_clone(gpt_dev->fd(), gpt_chan.reset_and_get_address()));

  auto wipe_result = client_->WipePartitionTables(std::move(gpt_chan));
  ASSERT_OK(wipe_result.status());
  ASSERT_OK(wipe_result.value().status);
}
#endif
#endif

}  // namespace
