// Copyright 2015 The Chromium OS 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 "buffet/dbus_conversion.h"

#include <limits>
#include <memory>
#include <string>
#include <vector>

#include <base/guid.h>
#include <base/rand_util.h>
#include <base/values.h>
#include <brillo/variant_dictionary.h>
#include <gtest/gtest.h>
#include <weave/test/unittest_utils.h>

namespace buffet {

namespace {

using brillo::Any;
using brillo::VariantDictionary;
using weave::test::CreateDictionaryValue;
using weave::test::IsEqualValue;

brillo::VariantDictionary ToDBus(const base::DictionaryValue& object) {
  return DictionaryToDBusVariantDictionary(object);
}

std::unique_ptr<base::DictionaryValue> FromDBus(
    const brillo::VariantDictionary& object) {
  brillo::ErrorPtr error;
  auto result = DictionaryFromDBusVariantDictionary(object, &error);
  EXPECT_TRUE(result || error);
  return result;
}

std::unique_ptr<base::Value> CreateRandomValue(int children);
std::unique_ptr<base::Value> CreateRandomValue(int children,
                                               base::Value::Type type);

const base::Value::Type kRandomTypes[] = {
    base::Value::TYPE_BOOLEAN,    base::Value::TYPE_INTEGER,
    base::Value::TYPE_DOUBLE,     base::Value::TYPE_STRING,
    base::Value::TYPE_DICTIONARY, base::Value::TYPE_LIST,
};

const base::Value::Type kRandomTypesWithChildren[] = {
    base::Value::TYPE_DICTIONARY, base::Value::TYPE_LIST,
};

base::Value::Type CreateRandomValueType(bool with_children) {
  if (with_children) {
    return kRandomTypesWithChildren[base::RandInt(
        0, arraysize(kRandomTypesWithChildren) - 1)];
  }
  return kRandomTypes[base::RandInt(0, arraysize(kRandomTypes) - 1)];
}

std::unique_ptr<base::DictionaryValue> CreateRandomDictionary(int children) {
  std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};

  while (children > 0) {
    int sub_children = base::RandInt(1, children);
    children -= sub_children;
    result->Set(base::GenerateGUID(), CreateRandomValue(sub_children));
  }

  return result;
}

std::unique_ptr<base::ListValue> CreateRandomList(int children) {
  std::unique_ptr<base::ListValue> result{new base::ListValue};

  base::Value::Type type = CreateRandomValueType(children > 0);
  while (children > 0) {
    size_t max_children =
        (type != base::Value::TYPE_DICTIONARY && type != base::Value::TYPE_LIST)
            ? 1
            : children;
    size_t sub_children = base::RandInt(1, max_children);
    children -= sub_children;
    result->Append(CreateRandomValue(sub_children, type));
  }

  return result;
}

std::unique_ptr<base::Value> CreateRandomValue(int children,
                                               base::Value::Type type) {
  CHECK_GE(children, 1);
  switch (type) {
    case base::Value::TYPE_INTEGER:
      return std::unique_ptr<base::Value>{new base::FundamentalValue{
          base::RandInt(std::numeric_limits<int>::min(),
                        std::numeric_limits<int>::max())}};
    case base::Value::TYPE_DOUBLE:
      return std::unique_ptr<base::Value>{
          new base::FundamentalValue{base::RandDouble()}};
    case base::Value::TYPE_STRING:
      return std::unique_ptr<base::Value>{
          new base::StringValue{base::GenerateGUID()}};
    case base::Value::TYPE_DICTIONARY:
      CHECK_GE(children, 1);
      return CreateRandomDictionary(children - 1);
    case base::Value::TYPE_LIST:
      CHECK_GE(children, 1);
      return CreateRandomList(children - 1);
    default:
      return std::unique_ptr<base::Value>{
          new base::FundamentalValue{base::RandInt(0, 1) != 0}};
  }
}

std::unique_ptr<base::Value> CreateRandomValue(int children) {
  return CreateRandomValue(children, CreateRandomValueType(children > 0));
}

}  // namespace

TEST(DBusConversionTest, DictionaryToDBusVariantDictionary) {
  EXPECT_EQ((VariantDictionary{{"bool", true}}),
            ToDBus(*CreateDictionaryValue("{'bool': true}")));
  EXPECT_EQ((VariantDictionary{{"int", 5}}),
            ToDBus(*CreateDictionaryValue("{'int': 5}")));
  EXPECT_EQ((VariantDictionary{{"double", 6.7}}),
            ToDBus(*CreateDictionaryValue("{'double': 6.7}")));
  EXPECT_EQ((VariantDictionary{{"string", std::string{"abc"}}}),
            ToDBus(*CreateDictionaryValue("{'string': 'abc'}")));
  EXPECT_EQ((VariantDictionary{{"object", VariantDictionary{{"bool", true}}}}),
            ToDBus(*CreateDictionaryValue("{'object': {'bool': true}}")));
  EXPECT_EQ((VariantDictionary{{"emptyList", std::vector<Any>{}}}),
            ToDBus(*CreateDictionaryValue("{'emptyList': []}")));
  EXPECT_EQ((VariantDictionary{{"intList", std::vector<int>{5}}}),
            ToDBus(*CreateDictionaryValue("{'intList': [5]}")));
  EXPECT_EQ((VariantDictionary{
                {"intListList", std::vector<Any>{std::vector<int>{5},
                                                 std::vector<int>{6, 7}}}}),
            ToDBus(*CreateDictionaryValue("{'intListList': [[5], [6, 7]]}")));
  EXPECT_EQ((VariantDictionary{{"objList",
                                std::vector<VariantDictionary>{
                                    {{"string", std::string{"abc"}}}}}}),
            ToDBus(*CreateDictionaryValue("{'objList': [{'string': 'abc'}]}")));
}

TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary) {
  EXPECT_JSON_EQ("{'bool': true}", *FromDBus({{"bool", true}}));
  EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", 5}}));
  EXPECT_JSON_EQ("{'double': 6.7}", *FromDBus({{"double", 6.7}}));
  EXPECT_JSON_EQ("{'string': 'abc'}",
                 *FromDBus({{"string", std::string{"abc"}}}));
  EXPECT_JSON_EQ("{'object': {'bool': true}}",
                 *FromDBus({{"object", VariantDictionary{{"bool", true}}}}));
  EXPECT_JSON_EQ("{'emptyList': []}",
                 *FromDBus({{"emptyList", std::vector<bool>{}}}));
  EXPECT_JSON_EQ("{'intList': [5]}",
                 *FromDBus({{"intList", std::vector<int>{5}}}));
  EXPECT_JSON_EQ(
      "{'intListList': [[5], [6, 7]]}",
      *FromDBus({{"intListList", std::vector<Any>{std::vector<int>{5},
                                                  std::vector<int>{6, 7}}}}));
  EXPECT_JSON_EQ(
      "{'objList': [{'string': 'abc'}]}",
      *FromDBus({{"objList", std::vector<VariantDictionary>{
                                 {{"string", std::string{"abc"}}}}}}));
  EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", Any{Any{5}}}}));
}

TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary_Errors) {
  EXPECT_FALSE(FromDBus({{"cString", "abc"}}));
  EXPECT_FALSE(FromDBus({{"float", 1.0f}}));
  EXPECT_FALSE(FromDBus({{"listList", std::vector<std::vector<int>>{}}}));
  EXPECT_FALSE(FromDBus({{"any", Any{}}}));
  EXPECT_FALSE(FromDBus({{"null", nullptr}}));
}

TEST(DBusConversionTest, DBusRandomDictionaryConversion) {
  auto dict = CreateRandomDictionary(10000);
  auto varian_dict = ToDBus(*dict);
  auto dict_restored = FromDBus(varian_dict);
  EXPECT_PRED2(IsEqualValue, *dict, *dict_restored);
}

}  // namespace buffet
