// 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.

#include "src/storage/volume_image/address_descriptor.h"

#include <string>
#include <string_view>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "rapidjson/document.h"
#include "rapidjson/schema.h"
#include "rapidjson/writer.h"
#include "src/lib/json_parser/json_parser.h"
#include "src/lib/json_parser/rapidjson_validation.h"
#include "src/storage/volume_image/serialization/schema.h"

namespace storage::volume_image {
namespace {

std::string GetSerializedJson(fit::function<void(rapidjson::Document*)> mutator = nullptr) {
  constexpr std::string_view kSerializedAddressDescriptor = R"(
    {
        "magic": 12526821592682033285,
        "mappings": [
          {
            "source": 20,
            "target": 120,
            "count": 10,
            "options": {}
          },
          {
            "source": 250,
            "target": 160,
            "count": 10
          },
          {
            "source": 2900,
            "target": 170,
            "count": 10,
            "size": 20
          }
        ]
    })";
  json_parser::JSONParser parser;
  rapidjson::Document parsed_document = parser.ParseFromString(
      kSerializedAddressDescriptor.data(), "serialized_address_descriptor.json");
  ZX_ASSERT_MSG(!parser.HasError(), "%s\n", parser.error_str().c_str());
  if (mutator != nullptr) {
    mutator(&parsed_document);
  }
  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  parsed_document.Accept(writer);
  return buffer.GetString();
}

TEST(AddressDescriptorTest, SerializeReturnsSchemaValidData) {
  AddressDescriptor descriptor = {};
  descriptor.mappings = std::vector<AddressMap>({
      {.source = 10,
       .target = 20,
       .count = 10,
       .options = {{"random_option_1", 32}, {"random_option_2", 33}}},
      {.source = 20, .target = 30, .count = 10},
  });
  auto schema_json = GetSchema(Schema::kAddressDescriptor);
  ASSERT_FALSE(schema_json.empty());

  json_parser::JSONParser parser;
  auto result = descriptor.Serialize();
  ASSERT_TRUE(result.is_ok()) << result.error();
  auto value = result.take_value();
  auto document =
      parser.ParseFromString(std::string(value.begin(), value.end()), "serialized.json");
  ASSERT_FALSE(parser.HasError()) << parser.error_str();
  auto schema_result = json_parser::InitSchema(schema_json);
  ASSERT_TRUE(schema_result.is_ok()) << schema_result.error_value().ToString();
  auto validation_result = json_parser::ValidateSchema(document, schema_result.value());
  EXPECT_TRUE(validation_result.is_ok()) << validation_result.error_value();
}

MATCHER(AddressMapEq, "") {
  auto [a, b] = arg;
  return a.source == b.source && a.target == b.target && a.count == b.count && a.size == b.size;
}

TEST(AddressDescriptorTest, DeserializeSerializedDataIsOk) {
  const auto deserialized_result = AddressDescriptor::Deserialize(GetSerializedJson());
  ASSERT_TRUE(deserialized_result.is_ok());

  const auto serialized_result = deserialized_result.value().Serialize();
  ASSERT_TRUE(serialized_result.is_ok());

  const auto redeserialized_result = AddressDescriptor::Deserialize(serialized_result.value());
  ASSERT_TRUE(redeserialized_result.is_ok());

  const auto& deserialized_1 = deserialized_result.value();
  const auto& deserialized_2 = deserialized_result.value();

  ASSERT_THAT(deserialized_1.mappings,
              testing::UnorderedPointwise(AddressMapEq(), deserialized_2.mappings));
}

TEST(AddressDescriptorTest, DeserializeFromValidDataReturnsAddressDescritptor) {
  const auto deserialized_result = AddressDescriptor::Deserialize(GetSerializedJson());
  ASSERT_TRUE(deserialized_result.is_ok()) << deserialized_result.error();

  ASSERT_THAT(
      deserialized_result.value().mappings,
      testing::UnorderedPointwise(
          AddressMapEq(), std::vector<AddressMap>({
                              {.source = 250, .target = 160, .count = 10, .size = std::nullopt},
                              {.source = 20, .target = 120, .count = 10, .size = std::nullopt},
                              {.source = 2900, .target = 170, .count = 10, .size = 20},
                          })));
}

TEST(AddressMapTest, DebugStringIsOk) {
  AddressMap map = {
      .source = 100,
      .target = 200,
      .count = 50,
  };

  EXPECT_THAT(map.DebugString(),
              testing::AllOf(testing::ContainsRegex("source:[ ]+100"),
                             testing::ContainsRegex("target:[ ]+200"),
                             testing::ContainsRegex("count:[ ]+50"),
                             testing::ContainsRegex("size:[ ]+std::nullopt"),
                             testing::ContainsRegex("options:[ ]+\\{[ \n]*\\}")));

  map.size = 150;
  EXPECT_THAT(
      map.DebugString(),
      testing::AllOf(testing::ContainsRegex("source:[ ]+100"),
                     testing::ContainsRegex("target:[ ]+200"),
                     testing::ContainsRegex("count:[ ]+50"), testing::ContainsRegex("size:[ ]+150"),
                     testing::ContainsRegex("options:[ ]+\\{[ \n]*\\}")));

  map.options["option_name"] = 1234;
  map.options["option_name_2"] = 12345;
  EXPECT_THAT(
      map.DebugString(),
      testing::AllOf(
          testing::ContainsRegex("source:[ ]+100"), testing::ContainsRegex("target:[ ]+200"),
          testing::ContainsRegex("count:[ ]+50"), testing::ContainsRegex("size:[ ]+150"),
          testing::ContainsRegex(
              "options:[ ]+\\{\n[ ]+option_name:[ ]+1234[ \n]+option_name_2:[ ]+12345[ \n]+\\}")));
}

TEST(AddressDescriptorTest, DeserializeWithBadMagicIsError) {
  ASSERT_TRUE(AddressDescriptor::Deserialize(GetSerializedJson([](auto* document) {
                (*document)["magic"] = AddressDescriptor::kMagic - 1;
              })).is_error());
}

TEST(AddressDescriptorTest, DeserializeWithEmptyMappingsIsError) {
  ASSERT_TRUE(AddressDescriptor::Deserialize(GetSerializedJson([](auto* document) {
                rapidjson::Value value;
                value.SetArray();
                (*document)["mappings"] = value;
              })).is_error());
}

}  // namespace

}  // namespace storage::volume_image
