// Copyright (c) 2012 The Chromium 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 "base/test/values_test_util.h"

#include <ostream>
#include <utility>

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {

void ExpectDictBooleanValue(bool expected_value,
                            const DictionaryValue& value,
                            const std::string& key) {
  bool boolean_value = false;
  EXPECT_TRUE(value.GetBoolean(key, &boolean_value)) << key;
  EXPECT_EQ(expected_value, boolean_value) << key;
}

void ExpectDictDictionaryValue(const DictionaryValue& expected_value,
                               const DictionaryValue& value,
                               const std::string& key) {
  const DictionaryValue* dict_value = nullptr;
  EXPECT_TRUE(value.GetDictionary(key, &dict_value)) << key;
  EXPECT_EQ(expected_value, *dict_value) << key;
}

void ExpectDictIntegerValue(int expected_value,
                            const DictionaryValue& value,
                            const std::string& key) {
  int integer_value = 0;
  EXPECT_TRUE(value.GetInteger(key, &integer_value)) << key;
  EXPECT_EQ(expected_value, integer_value) << key;
}

void ExpectDictListValue(const ListValue& expected_value,
                         const DictionaryValue& value,
                         const std::string& key) {
  const ListValue* list_value = nullptr;
  EXPECT_TRUE(value.GetList(key, &list_value)) << key;
  EXPECT_EQ(expected_value, *list_value) << key;
}

void ExpectDictStringValue(const std::string& expected_value,
                           const DictionaryValue& value,
                           const std::string& key) {
  std::string string_value;
  EXPECT_TRUE(value.GetString(key, &string_value)) << key;
  EXPECT_EQ(expected_value, string_value) << key;
}

void ExpectStringValue(const std::string& expected_str, const Value& actual) {
  EXPECT_EQ(Value::Type::STRING, actual.type());
  EXPECT_EQ(expected_str, actual.GetString());
}

namespace test {

namespace {

std::string FormatAsJSON(const base::Value& value) {
  std::string json;
  JSONWriter::Write(value, &json);
  return json;
}

class DictionaryHasValueMatcher
    : public testing::MatcherInterface<const base::Value&> {
 public:
  DictionaryHasValueMatcher(const std::string& key,
                            const base::Value& expected_value)
      : key_(key), expected_value_(expected_value.Clone()) {}

  ~DictionaryHasValueMatcher() = default;

  bool MatchAndExplain(const base::Value& value,
                       testing::MatchResultListener* listener) const override {
    if (!value.is_dict()) {
      *listener << "The value '" << FormatAsJSON(value)
                << "' is not a dictionary";
      return false;
    }
    const base::Value* sub_value = value.FindKey(key_);
    if (!sub_value) {
      *listener << "Dictionary '" << FormatAsJSON(value)
                << "' does not have key '" << key_ << "'";
      return false;
    }
    if (*sub_value != expected_value_) {
      *listener << "Dictionary value under key '" << key_ << "' is '"
                << FormatAsJSON(*sub_value) << "', expected '"
                << FormatAsJSON(expected_value_) << "'";
      return false;
    }
    return true;
  }

  void DescribeTo(std::ostream* os) const override {
    *os << "has key '" << key_ << "' with value '"
        << FormatAsJSON(expected_value_) << "'";
  }

  void DescribeNegationTo(std::ostream* os) const override {
    *os << "does not have key '" << key_ << "' with value '"
        << FormatAsJSON(expected_value_) << "'";
  }

 private:
  DictionaryHasValueMatcher& operator=(const DictionaryHasValueMatcher& other) =
      delete;

  const std::string key_;
  const base::Value expected_value_;
};

class DictionaryHasValuesMatcher
    : public testing::MatcherInterface<const base::Value&> {
 public:
  DictionaryHasValuesMatcher(const base::Value& template_value)
      : template_value_(template_value.Clone()) {
    CHECK(template_value.is_dict());
  }

  ~DictionaryHasValuesMatcher() = default;

  bool MatchAndExplain(const base::Value& value,
                       testing::MatchResultListener* listener) const override {
    if (!value.is_dict()) {
      *listener << "The value '" << FormatAsJSON(value)
                << "' is not a dictionary";
      return false;
    }

    bool ok = true;
    for (const auto& template_dict_item : template_value_.DictItems()) {
      const base::Value* sub_value = value.FindKey(template_dict_item.first);
      if (!sub_value) {
        *listener << "\nDictionary does not have key '"
                  << template_dict_item.first << "'";
        ok = false;
        continue;
      }
      if (*sub_value != template_dict_item.second) {
        *listener << "\nDictionary value under key '"
                  << template_dict_item.first << "' is '"
                  << FormatAsJSON(*sub_value) << "', expected '"
                  << FormatAsJSON(template_dict_item.second) << "'";
        ok = false;
      }
    }
    return ok;
  }

  void DescribeTo(std::ostream* os) const override {
    *os << "contains all key-values from '" << FormatAsJSON(template_value_)
        << "'";
  }

  void DescribeNegationTo(std::ostream* os) const override {
    *os << "does not contain key-values from '" << FormatAsJSON(template_value_)
        << "'";
  }

 private:
  DictionaryHasValueMatcher& operator=(const DictionaryHasValueMatcher& other) =
      delete;

  const base::Value template_value_;
};

}  // namespace

testing::Matcher<const base::Value&> DictionaryHasValue(
    const std::string& key,
    const base::Value& expected_value) {
  return testing::MakeMatcher(
      new DictionaryHasValueMatcher(key, expected_value));
}

testing::Matcher<const base::Value&> DictionaryHasValues(
    const base::Value& template_value) {
  return testing::MakeMatcher(new DictionaryHasValuesMatcher(template_value));
}

IsJsonMatcher::IsJsonMatcher(base::StringPiece json)
    : expected_value_(test::ParseJson(json)) {}

IsJsonMatcher::IsJsonMatcher(const base::Value& value)
    : expected_value_(value.Clone()) {}

IsJsonMatcher::IsJsonMatcher(const IsJsonMatcher& other)
    : expected_value_(other.expected_value_.Clone()) {}

IsJsonMatcher::~IsJsonMatcher() = default;

bool IsJsonMatcher::MatchAndExplain(
    base::StringPiece json,
    testing::MatchResultListener* listener) const {
  // This is almost the same logic as ParseJson, but the parser uses stricter
  // options for JSON data that is assumed to be generated by the code under
  // test rather than written by hand as part of a unit test.
  JSONReader::ValueWithError ret =
      JSONReader::ReadAndReturnValueWithError(json, JSON_PARSE_RFC);
  if (!ret.value) {
    *listener << "Failed to parse \"" << json << "\": " << ret.error_message;
    return false;
  }
  return MatchAndExplain(*ret.value, listener);
}

bool IsJsonMatcher::MatchAndExplain(
    const base::Value& value,
    testing::MatchResultListener* /* listener */) const {
  return expected_value_ == value;
}

void IsJsonMatcher::DescribeTo(std::ostream* os) const {
  *os << "is the JSON value " << expected_value_;
}

void IsJsonMatcher::DescribeNegationTo(std::ostream* os) const {
  *os << "is not the JSON value " << expected_value_;
}

Value ParseJson(StringPiece json) {
  JSONReader::ValueWithError result =
      JSONReader::ReadAndReturnValueWithError(json, JSON_ALLOW_TRAILING_COMMAS);
  if (!result.value) {
    ADD_FAILURE() << "Failed to parse \"" << json
                  << "\": " << result.error_message;
    return Value();
  }
  return std::move(result.value.value());
}

std::unique_ptr<Value> ParseJsonDeprecated(StringPiece json) {
  return Value::ToUniquePtrValue(ParseJson(json));
}

}  // namespace test
}  // namespace base
