// Copyright 2020 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.
#ifndef SRC_BRINGUP_BIN_NETSVC_TEST_PAVER_TEST_COMMON_H_
#define SRC_BRINGUP_BIN_NETSVC_TEST_PAVER_TEST_COMMON_H_

#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/paver/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/dispatcher.h>
#include <lib/driver-integration-test/fixture.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/sync/completion.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <threads.h>
#include <zircon/boot/netboot.h>
#include <zircon/errors.h>
#include <zircon/time.h>

#include <algorithm>
#include <memory>
#include <vector>

#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <ramdevice-client/ramdisk.h>
#include <zxtest/zxtest.h>

#include "src/bringup/bin/netsvc/paver.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/service.h"
#include "src/lib/storage/vfs/cpp/synchronous_vfs.h"

enum class Command {
  kUnknown,
  kInitializeAbr,
  kQueryCurrentConfiguration,
  kQueryActiveConfiguration,
  kQueryConfigurationStatus,
  kSetConfigurationActive,
  kSetConfigurationUnbootable,
  kSetConfigurationHealthy,
  kReadAsset,
  kWriteAsset,
  kWriteFirmware,
  kWriteVolumes,
  kWriteBootloader,
  kWriteDataFile,
  kWipeVolume,
  kInitPartitionTables,
  kWipePartitionTables,
  kDataSinkFlush,
  kBootManagerFlush,
};

struct AbrSlotData {
  bool unbootable;
  bool active;
};

struct AbrData {
  AbrSlotData slot_a;
  AbrSlotData slot_b;
};

constexpr AbrData kInitAbrData = {
    .slot_a =
        {
            .unbootable = false,
            .active = false,
        },
    .slot_b =
        {
            .unbootable = false,
            .active = false,
        },
};

class FakePaver : public fidl::WireRawChannelInterface<fuchsia_paver::Paver>,
                  public fidl::WireInterface<fuchsia_paver::BootManager>,
                  public fidl::WireRawChannelInterface<fuchsia_paver::DynamicDataSink> {
 public:
  zx_status_t Connect(async_dispatcher_t* dispatcher, zx::channel request) {
    dispatcher_ = dispatcher;
    return fidl::BindSingleInFlightOnly<fidl::WireRawChannelInterface<fuchsia_paver::Paver>>(
        dispatcher, std::move(request), this);
  }

  void FindDataSink(zx::channel data_sink, FindDataSinkCompleter::Sync& _completer) override {
    fidl::BindSingleInFlightOnly<fidl::WireRawChannelInterface<fuchsia_paver::DynamicDataSink>>(
        dispatcher_, std::move(data_sink), this);
  }

  void UseBlockDevice(zx::channel block_device, zx::channel dynamic_data_sink,
                      UseBlockDeviceCompleter::Sync& _completer) override {
    auto result =
        fidl::WireCall<fuchsia_device::Controller>(zx::unowned(block_device)).GetTopologicalPath();
    if (!result.ok() || result->result.is_err()) {
      return;
    }
    const auto& path = result->result.response().path;
    {
      fbl::AutoLock al(&lock_);
      if (std::string(path.data(), path.size()) != expected_block_device_) {
        return;
      }
    }
    fidl::BindSingleInFlightOnly<fidl::WireRawChannelInterface<fuchsia_paver::DynamicDataSink>>(
        dispatcher_, std::move(dynamic_data_sink), this);
  }

  void FindBootManager(zx::channel boot_manager,
                       FindBootManagerCompleter::Sync& _completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kInitializeAbr);
    if (abr_supported_) {
      fidl::BindSingleInFlightOnly<fidl::WireInterface<fuchsia_paver::BootManager>>(
          dispatcher_, std::move(boot_manager), this);
    }
  }

  void QueryCurrentConfiguration(QueryCurrentConfigurationCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kQueryCurrentConfiguration);
    completer.ReplySuccess(fuchsia_paver::wire::Configuration::A);
  }

  void FindSysconfig(zx::channel sysconfig, FindSysconfigCompleter::Sync& _completer) override {}

  void QueryActiveConfiguration(QueryActiveConfigurationCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kQueryActiveConfiguration);
    completer.ReplySuccess(fuchsia_paver::wire::Configuration::A);
  }

  void QueryConfigurationStatus(fuchsia_paver::wire::Configuration configuration,
                                QueryConfigurationStatusCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kQueryConfigurationStatus);
    completer.ReplySuccess(fuchsia_paver::wire::ConfigurationStatus::HEALTHY);
  }

  void SetConfigurationActive(fuchsia_paver::wire::Configuration configuration,
                              SetConfigurationActiveCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kSetConfigurationActive);
    zx_status_t status;
    switch (configuration) {
      case fuchsia_paver::wire::Configuration::A:
        abr_data_.slot_a.active = true;
        abr_data_.slot_a.unbootable = false;
        status = ZX_OK;
        break;

      case fuchsia_paver::wire::Configuration::B:
        abr_data_.slot_b.active = true;
        abr_data_.slot_b.unbootable = false;
        status = ZX_OK;
        break;

      case fuchsia_paver::wire::Configuration::RECOVERY:
        status = ZX_ERR_INVALID_ARGS;
        break;
    }
    completer.Reply(status);
  }

  void SetConfigurationUnbootable(fuchsia_paver::wire::Configuration configuration,
                                  SetConfigurationUnbootableCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kSetConfigurationUnbootable);
    zx_status_t status;
    switch (configuration) {
      case fuchsia_paver::wire::Configuration::A:
        abr_data_.slot_a.unbootable = true;
        status = ZX_OK;
        break;

      case fuchsia_paver::wire::Configuration::B:
        abr_data_.slot_b.unbootable = true;
        status = ZX_OK;
        break;

      case fuchsia_paver::wire::Configuration::RECOVERY:
        status = ZX_ERR_INVALID_ARGS;
        break;
    }
    completer.Reply(status);
  }

  void SetConfigurationHealthy(fuchsia_paver::wire::Configuration configuration,
                               SetConfigurationHealthyCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kSetConfigurationHealthy);
    completer.Reply(ZX_OK);
  }

  void Flush(fidl::WireRawChannelInterface<fuchsia_paver::DynamicDataSink>::FlushCompleter::Sync&
                 completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kDataSinkFlush);
    completer.Reply(ZX_OK);
  }

  void Flush(
      fidl::WireInterface<fuchsia_paver::BootManager>::FlushCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kBootManagerFlush);
    completer.Reply(ZX_OK);
  }

  void ReadAsset(fuchsia_paver::wire::Configuration configuration, fuchsia_paver::wire::Asset asset,
                 ReadAssetCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kReadAsset);
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }

  void WriteAsset(fuchsia_paver::wire::Configuration configuration,
                  fuchsia_paver::wire::Asset asset, fuchsia_mem::wire::Buffer payload,
                  WriteAssetCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWriteAsset);
    auto status = payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
    completer.Reply(status);
  }

  void WriteFirmware(fuchsia_paver::wire::Configuration configuration, fidl::StringView type,
                     fuchsia_mem::wire::Buffer payload,
                     WriteFirmwareCompleter::Sync& completer) override {
    using fuchsia_paver::wire::WriteFirmwareResult;
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWriteFirmware);
    last_firmware_type_ = std::string(type.data(), type.size());

    // Reply varies depending on whether we support |type| or not.
    if (supported_firmware_type_ == std::string_view(type.data(), type.size())) {
      auto status = payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
      completer.Reply(
          WriteFirmwareResult::WithStatus(fidl::ObjectView<zx_status_t>::FromExternal(&status)));
    } else {
      bool unsupported = true;
      completer.Reply(
          WriteFirmwareResult::WithUnsupported(fidl::ObjectView<bool>::FromExternal(&unsupported)));
    }
  }

  void WriteVolumes(zx::channel payload_stream, WriteVolumesCompleter::Sync& completer) override {
    {
      fbl::AutoLock al(&lock_);
      AppendCommand(Command::kWriteVolumes);
    }
    // Register VMO.
    zx::vmo vmo;
    auto status = zx::vmo::create(1024, 0, &vmo);
    if (status != ZX_OK) {
      completer.Reply(status);
      return;
    }
    fidl::WireSyncClient<fuchsia_paver::PayloadStream> stream(std::move(payload_stream));
    auto result = stream.RegisterVmo(std::move(vmo));
    status = result.ok() ? result.value().status : result.status();
    if (status != ZX_OK) {
      completer.Reply(status);
      return;
    }
    // Stream until EOF.
    status = [&]() {
      size_t data_transferred = 0;
      for (;;) {
        {
          fbl::AutoLock al(&lock_);
          if (wait_for_start_signal_) {
            al.release();
            sync_completion_wait(&start_signal_, ZX_TIME_INFINITE);
            sync_completion_reset(&start_signal_);
          } else {
            signal_size_ = expected_payload_size_ + 1;
          }
        }
        while (data_transferred < signal_size_) {
          auto result = stream.ReadData();
          if (!result.ok()) {
            return result.status();
          }
          const auto& response = result.value();
          switch (response.result.which()) {
            case fuchsia_paver::wire::ReadResult::Tag::kErr:
              return response.result.err();
            case fuchsia_paver::wire::ReadResult::Tag::kEof:
              return data_transferred == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
            case fuchsia_paver::wire::ReadResult::Tag::kInfo:
              data_transferred += response.result.info().size;
              continue;
            default:
              return ZX_ERR_INTERNAL;
          }
        }
        sync_completion_signal(&done_signal_);
      }
    }();

    sync_completion_signal(&done_signal_);

    completer.Reply(status);
  }

  void WriteBootloader(fuchsia_mem::wire::Buffer payload,
                       WriteBootloaderCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWriteBootloader);
    auto status = payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
    completer.Reply(status);
  }

  void WriteDataFile(fidl::StringView filename, fuchsia_mem::wire::Buffer payload,
                     WriteDataFileCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWriteDataFile);
    auto status = payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
    completer.Reply(status);
  }

  void WipeVolume(WipeVolumeCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWipeVolume);
    completer.ReplySuccess({});
  }

  void InitializePartitionTables(InitializePartitionTablesCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kInitPartitionTables);
    completer.Reply(ZX_OK);
  }

  void WipePartitionTables(WipePartitionTablesCompleter::Sync& completer) override {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWipePartitionTables);
    completer.Reply(ZX_OK);
  }

  void WaitForWritten(size_t size) {
    signal_size_ = size;
    sync_completion_signal(&start_signal_);
    sync_completion_wait(&done_signal_, ZX_TIME_INFINITE);
    sync_completion_reset(&done_signal_);
  }

  const std::vector<Command> GetCommandTrace() {
    fbl::AutoLock al(&lock_);
    return command_trace_;
  }

  std::string last_firmware_type() const {
    fbl::AutoLock al(&lock_);
    return last_firmware_type_;
  }

  void set_expected_payload_size(size_t size) { expected_payload_size_ = size; }
  void set_supported_firmware_type(std::string type) {
    fbl::AutoLock al(&lock_);
    supported_firmware_type_ = type;
  }
  void set_abr_supported(bool supported) { abr_supported_ = supported; }
  void set_wait_for_start_signal(bool wait) { wait_for_start_signal_ = wait; }
  void set_expected_device(std::string expected) {
    fbl::AutoLock al(&lock_);
    expected_block_device_ = expected;
  }

  const AbrData abr_data() {
    fbl::AutoLock al(&lock_);
    return abr_data_;
  }

 private:
  std::atomic<bool> wait_for_start_signal_ = false;
  sync_completion_t start_signal_;
  sync_completion_t done_signal_;
  std::atomic<size_t> signal_size_;

  mutable fbl::Mutex lock_;

  std::string last_firmware_type_ TA_GUARDED(lock_);

  std::atomic<size_t> expected_payload_size_ = 0;
  std::string expected_block_device_ TA_GUARDED(lock_);
  std::string supported_firmware_type_ TA_GUARDED(lock_);
  std::atomic<bool> abr_supported_ = false;
  AbrData abr_data_ TA_GUARDED(lock_) = kInitAbrData;

  std::atomic<async_dispatcher_t*> dispatcher_ = nullptr;

  std::vector<Command> command_trace_ TA_GUARDED(lock_);
  void AppendCommand(Command cmd) TA_REQ(lock_) { command_trace_.push_back(cmd); }
};

class FakeSvc {
 public:
  explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
    auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
    root_dir->AddEntry(fuchsia_paver::Paver::Name,
                       fbl::MakeRefCounted<fs::Service>([this](zx::channel request) {
                         return fake_paver_.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));
  }

  FakePaver& fake_paver() { return fake_paver_; }
  zx::channel& svc_chan() { return svc_local_; }

 private:
  async_dispatcher_t* dispatcher_;
  fs::SynchronousVfs vfs_;
  FakePaver fake_paver_;
  zx::channel svc_local_;
};

class FakeDev {
 public:
  FakeDev() {
    driver_integration_test::IsolatedDevmgr::Args args;
    args.driver_search_paths.push_back("/boot/driver");

    ASSERT_OK(driver_integration_test::IsolatedDevmgr::Create(&args, &devmgr_));
    fbl::unique_fd fd;
    ASSERT_OK(
        devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(), "sys/platform", &fd));
  }

  driver_integration_test::IsolatedDevmgr devmgr_;
};

class PaverTest : public zxtest::Test {
 protected:
  PaverTest()
      : loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
        fake_svc_(loop_.dispatcher()),
        paver_(std::move(fake_svc_.svc_chan()), fake_dev_.devmgr_.devfs_root().duplicate()) {
    paver_.set_timeout(zx::msec(500));
    loop_.StartThread("paver-test-loop");
  }

  ~PaverTest() {
    // Need to make sure paver thread exits.
    Wait();
    if (ramdisk_ != nullptr) {
      ramdisk_destroy(ramdisk_);
      ramdisk_ = nullptr;
    }
    loop_.Shutdown();
  }

  void Wait() {
    while (paver_.InProgress())
      continue;
  }

  void SpawnBlockDevice() {
    fbl::unique_fd fd;
    ASSERT_OK(devmgr_integration_test::RecursiveWaitForFile(fake_dev_.devmgr_.devfs_root(),
                                                            "misc/ramctl", &fd));
    ASSERT_OK(ramdisk_create_at(fake_dev_.devmgr_.devfs_root().get(), zx_system_get_page_size(),
                                100, &ramdisk_));
    std::string expected = std::string("/dev/") + ramdisk_get_path(ramdisk_);
    fake_svc_.fake_paver().set_expected_device(expected);
  }

  async::Loop loop_;
  ramdisk_client_t* ramdisk_ = nullptr;
  FakeSvc fake_svc_;
  FakeDev fake_dev_;
  netsvc::Paver paver_;
};

#endif  // SRC_BRINGUP_BIN_NETSVC_TEST_PAVER_TEST_COMMON_H_
