// Copyright 2018 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 "garnet/bin/guest/vmm/device/qcow.h"

#include <sys/stat.h>

#include <fbl/unique_fd.h>
#include <gtest/gtest.h>
#include <lib/fxl/arraysize.h>
#include <lib/fxl/logging.h>

#include "garnet/bin/guest/vmm/device/qcow_test_data.h"

namespace {

using namespace qcow_test_data;

class FdBlockDispatcher : public BlockDispatcher {
 public:
  explicit FdBlockDispatcher(int fd) : fd_(fd) {}

 private:
  int fd_;

  void Sync(Callback callback) override {
    int ret = fsync(fd_);
    callback(ret < 0 ? ZX_ERR_IO : ZX_OK);
  }

  void ReadAt(void* data, uint64_t size, uint64_t off,
              Callback callback) override {
    int ret = pread(fd_, data, size, off);
    callback(ret < 0 ? ZX_ERR_IO : ZX_OK);
  }

  void WriteAt(const void* data, uint64_t size, uint64_t off,
               Callback callback) override {
    int ret = pwrite(fd_, data, size, off);
    callback(ret < 0 ? ZX_ERR_IO : ZX_OK);
  }
};

class QcowTest : public testing::Test {
 public:
  QcowTest() {}

  void SetUp() override {
    fd_.reset(mkstemp(&path_[0]));
    ASSERT_TRUE(fd_);
  }

  void TearDown() override { VerifyPaddingClustersAreEmpty(); }

  void VerifyPaddingClustersAreEmpty() {
    uint8_t cluster[kClusterSize];
    for (size_t i = 0; i < arraysize(kPaddingClusterOffsets); ++i) {
      ASSERT_EQ(
          static_cast<int>(kClusterSize),
          pread(fd_.get(), cluster, kClusterSize, kPaddingClusterOffsets[i]));
      ASSERT_EQ(0, memcmp(cluster, kZeroCluster, kClusterSize));
    }
  }

  void WriteQcowHeader(const QcowHeader& header) {
    header_ = header;
    QcowHeader be_header = header.HostToBigEndian();
    WriteAt(&be_header, 0);
    WriteL1Table();
    WriteRefcountTable();
  }

  void WriteL1Table() {
    // Convert l1 entries to big-endian
    uint64_t be_table[arraysize(kL2TableClusterOffsets)];
    for (size_t i = 0; i < arraysize(kL2TableClusterOffsets); ++i) {
      be_table[i] = HostToBigEndianTraits::Convert(kL2TableClusterOffsets[i]);
    }

    // Write L1 table.
    WriteAt(be_table, arraysize(kL2TableClusterOffsets),
            header_.l1_table_offset);

    // Initialize empty L2 tables.
    for (size_t i = 0; i < arraysize(kL2TableClusterOffsets); ++i) {
      WriteAt(kZeroCluster, sizeof(kZeroCluster), kL2TableClusterOffsets[i]);
    }
  }

  void WriteRefcountTable() {
    // Convert entries to big-endian
    uint64_t be_table[arraysize(kRefcountBlockClusterOffsets)];
    for (size_t i = 0; i < arraysize(kRefcountBlockClusterOffsets); ++i) {
      be_table[i] =
          HostToBigEndianTraits::Convert(kRefcountBlockClusterOffsets[i]);
    }

    // Write refcount table
    WriteAt(be_table, arraysize(kRefcountBlockClusterOffsets),
            header_.refcount_table_offset);

    // Initialize empty refcount blocks.
    for (size_t i = 0; i < arraysize(kRefcountBlockClusterOffsets); ++i) {
      WriteAt(kZeroCluster, sizeof(kZeroCluster),
              kRefcountBlockClusterOffsets[i]);
    }
  }

  template <typename T>
  void WriteAt(const T* ptr, off_t off) {
    ASSERT_EQ(static_cast<ssize_t>(sizeof(T)),
              pwrite(fd_.get(), ptr, sizeof(T), off));
  }

  // Writes an array of T values at the current file location.
  template <typename T>
  void WriteAt(const T* ptr, size_t len, off_t off) {
    ASSERT_EQ(static_cast<ssize_t>(len * sizeof(T)),
              pwrite(fd_.get(), ptr, len * sizeof(T), off));
  }

  zx_status_t Load() {
    FdBlockDispatcher disp(fd_.get());
    zx_status_t status;
    file_.Load(&disp, [&status](zx_status_t s) { status = s; });
    return status;
  }

  zx_status_t ReadAt(void* data, uint64_t size) {
    FdBlockDispatcher disp(fd_.get());
    zx_status_t status;
    file_.ReadAt(&disp, data, size, 0,
                 [&status](zx_status_t s) { status = s; });
    return status;
  }

 protected:
  std::string path_ = "/tmp/qcow-test.XXXXXX";
  fbl::unique_fd fd_;
  QcowHeader header_;
  QcowFile file_;
};

TEST_F(QcowTest, V2Load) {
  WriteQcowHeader(kDefaultHeaderV2);
  ASSERT_EQ(ZX_OK, Load());
}

TEST_F(QcowTest, V2IgnoreExtendedAttributes) {
  // Write some values to the fields that do not exist with QCOW2 files.
  QcowHeader header = kDefaultHeaderV2;
  header.incompatible_features = 0xff;
  header.compatible_features = 0xff;
  header.autoclear_features = 0xff;
  header.refcount_order = 0xff;
  header.header_length = 0xff;
  WriteQcowHeader(header);

  // Load and validate the QCOW2 defaults are used.
  ASSERT_EQ(ZX_OK, Load());
  EXPECT_EQ(0u, file_.header().incompatible_features);
  EXPECT_EQ(0u, file_.header().compatible_features);
  EXPECT_EQ(0u, file_.header().autoclear_features);
  EXPECT_EQ(4u, file_.header().refcount_order);
  EXPECT_EQ(72u, file_.header().header_length);
}

TEST_F(QcowTest, V3Load) {
  WriteQcowHeader(kDefaultHeaderV3);
  ASSERT_EQ(ZX_OK, Load());
}

TEST_F(QcowTest, V3RejectIncompatibleFeatures) {
  QcowHeader header = kDefaultHeaderV3;
  header.incompatible_features = 1;
  WriteQcowHeader(header);
  ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, Load());
}

TEST_F(QcowTest, V3RejectCryptMethod) {
  QcowHeader header = kDefaultHeaderV3;
  header.crypt_method = 1;
  WriteQcowHeader(header);
  ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, Load());
}

TEST_F(QcowTest, ReadUnmappedCluster) {
  WriteQcowHeader(kDefaultHeaderV2);

  // The cluster is not mapped. Verify that reads return all 0's.
  uint8_t result[kClusterSize];
  memset(result, 0xff, sizeof(result));
  uint8_t expected[kClusterSize] = {};
  ASSERT_EQ(ZX_OK, Load());
  ASSERT_EQ(ZX_OK, ReadAt(result, sizeof(result)));
  ASSERT_EQ(0, memcmp(result, expected, sizeof(result)));
}

TEST_F(QcowTest, ReadMappedCluster) {
  WriteQcowHeader(kDefaultHeaderV2);

  // Write L2 entry
  uint64_t l2_offset = kL2TableClusterOffsets[0];
  uint64_t data_cluster_offset = ClusterOffset(kFirstDataCluster);
  uint64_t l2_entry = HostToBigEndianTraits::Convert(data_cluster_offset);
  WriteAt(&l2_entry, l2_offset);

  // Write data to cluster.
  uint8_t cluster_data[kClusterSize];
  memset(cluster_data, 0xab, sizeof(cluster_data));
  WriteAt(cluster_data, kClusterSize, data_cluster_offset);

  // Read cluster.
  uint8_t result[kClusterSize];
  ASSERT_EQ(ZX_OK, Load());
  ASSERT_EQ(ZX_OK, ReadAt(result, sizeof(result)));
  ASSERT_EQ(memcmp(result, cluster_data, sizeof(result)), 0);
}

TEST_F(QcowTest, RejectCompressedCluster) {
  WriteQcowHeader(kDefaultHeaderV2);

  // Write L2 entry
  uint64_t l2_offset = kL2TableClusterOffsets[0];
  uint64_t data_cluster_offset = ClusterOffset(kFirstDataCluster);
  uint64_t l2_entry = HostToBigEndianTraits::Convert(data_cluster_offset |
                                                     kTableEntryCompressedBit);
  WriteAt(&l2_entry, l2_offset);

  // Write data to cluster.
  uint8_t cluster_data[kClusterSize];
  memset(cluster_data, 0xab, sizeof(cluster_data));
  WriteAt(cluster_data, kClusterSize, data_cluster_offset);

  // Attempt to read compressed cluster.
  ASSERT_EQ(ZX_OK, Load());
  ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, ReadAt(cluster_data, sizeof(cluster_data)));
}

}  // namespace
