// 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/json/json_value_converter.h"

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

#include "base/json/json_reader.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace {

// Very simple messages.
struct SimpleMessage {
  enum SimpleEnum {
    FOO, BAR,
  };
  int foo;
  std::string bar;
  bool baz;
  bool bstruct;
  SimpleEnum simple_enum;
  std::vector<std::unique_ptr<int>> ints;
  std::vector<std::unique_ptr<std::string>> string_values;
  SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}

  static bool ParseSimpleEnum(StringPiece value, SimpleEnum* field) {
    if (value == "foo") {
      *field = FOO;
      return true;
    }
    if (value == "bar") {
      *field = BAR;
      return true;
    }
    return false;
  }

  static bool HasFieldPresent(const base::Value* value, bool* result) {
    *result = value != nullptr;
    return true;
  }

  static bool GetValueString(const base::Value* value, std::string* result) {
    const std::string* str = value->FindStringKey("val");
    if (!str)
      return false;
    if (result)
      *result = *str;
    return true;
  }

  static void RegisterJSONConverter(
      base::JSONValueConverter<SimpleMessage>* converter) {
    converter->RegisterIntField("foo", &SimpleMessage::foo);
    converter->RegisterStringField("bar", &SimpleMessage::bar);
    converter->RegisterBoolField("baz", &SimpleMessage::baz);
    converter->RegisterCustomField<SimpleEnum>(
        "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
    converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
    converter->RegisterCustomValueField<bool>("bstruct",
                                              &SimpleMessage::bstruct,
                                              &HasFieldPresent);
    converter->RegisterRepeatedCustomValue<std::string>(
        "string_values",
        &SimpleMessage::string_values,
        &GetValueString);
  }
};

// For nested messages.
struct NestedMessage {
  double foo;
  SimpleMessage child;
  std::vector<std::unique_ptr<SimpleMessage>> children;

  NestedMessage() : foo(0) {}

  static void RegisterJSONConverter(
      base::JSONValueConverter<NestedMessage>* converter) {
    converter->RegisterDoubleField("foo", &NestedMessage::foo);
    converter->RegisterNestedField("child", &NestedMessage::child);
    converter->RegisterRepeatedMessage("children", &NestedMessage::children);
  }
};

}  // namespace

TEST(JSONValueConverterTest, ParseSimpleMessage) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1,\n"
      "  \"bar\": \"bar\",\n"
      "  \"baz\": true,\n"
      "  \"bstruct\": {},\n"
      "  \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
      "  \"simple_enum\": \"foo\","
      "  \"ints\": [1, 2]"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  SimpleMessage message;
  base::JSONValueConverter<SimpleMessage> converter;
  EXPECT_TRUE(converter.Convert(*value, &message));

  EXPECT_EQ(1, message.foo);
  EXPECT_EQ("bar", message.bar);
  EXPECT_TRUE(message.baz);
  EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
  EXPECT_EQ(2, static_cast<int>(message.ints.size()));
  ASSERT_EQ(2U, message.string_values.size());
  EXPECT_EQ("value_1", *message.string_values[0]);
  EXPECT_EQ("value_2", *message.string_values[1]);
  EXPECT_EQ(1, *(message.ints[0]));
  EXPECT_EQ(2, *(message.ints[1]));
}

TEST(JSONValueConverterTest, ParseNestedMessage) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1.0,\n"
      "  \"child\": {\n"
      "    \"foo\": 1,\n"
      "    \"bar\": \"bar\",\n"
      "    \"bstruct\": {},\n"
      "    \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
      "    \"baz\": true\n"
      "  },\n"
      "  \"children\": [{\n"
      "    \"foo\": 2,\n"
      "    \"bar\": \"foobar\",\n"
      "    \"bstruct\": \"\",\n"
      "    \"string_values\": [{\"val\": \"value_1\"}],"
      "    \"baz\": true\n"
      "  },\n"
      "  {\n"
      "    \"foo\": 3,\n"
      "    \"bar\": \"barbaz\",\n"
      "    \"baz\": false\n"
      "  }]\n"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  NestedMessage message;
  base::JSONValueConverter<NestedMessage> converter;
  EXPECT_TRUE(converter.Convert(*value, &message));

  EXPECT_EQ(1.0, message.foo);
  EXPECT_EQ(1, message.child.foo);
  EXPECT_EQ("bar", message.child.bar);
  EXPECT_TRUE(message.child.baz);
  EXPECT_TRUE(message.child.bstruct);
  ASSERT_EQ(2U, message.child.string_values.size());
  EXPECT_EQ("value_1", *message.child.string_values[0]);
  EXPECT_EQ("value_2", *message.child.string_values[1]);

  EXPECT_EQ(2, static_cast<int>(message.children.size()));
  const SimpleMessage* first_child = message.children[0].get();
  ASSERT_TRUE(first_child);
  EXPECT_EQ(2, first_child->foo);
  EXPECT_EQ("foobar", first_child->bar);
  EXPECT_TRUE(first_child->baz);
  EXPECT_TRUE(first_child->bstruct);
  ASSERT_EQ(1U, first_child->string_values.size());
  EXPECT_EQ("value_1", *first_child->string_values[0]);

  const SimpleMessage* second_child = message.children[1].get();
  ASSERT_TRUE(second_child);
  EXPECT_EQ(3, second_child->foo);
  EXPECT_EQ("barbaz", second_child->bar);
  EXPECT_FALSE(second_child->baz);
  EXPECT_FALSE(second_child->bstruct);
  EXPECT_EQ(0U, second_child->string_values.size());
}

TEST(JSONValueConverterTest, ParseFailures) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1,\n"
      "  \"bar\": 2,\n"  // "bar" is an integer here.
      "  \"baz\": true,\n"
      "  \"ints\": [1, 2]"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  SimpleMessage message;
  base::JSONValueConverter<SimpleMessage> converter;
  EXPECT_FALSE(converter.Convert(*value, &message));
  // Do not check the values below.  |message| may be modified during
  // Convert() even it fails.
}

TEST(JSONValueConverterTest, ParseWithMissingFields) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1,\n"
      "  \"baz\": true,\n"
      "  \"ints\": [1, 2]"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  SimpleMessage message;
  base::JSONValueConverter<SimpleMessage> converter;
  // Convert() still succeeds even if the input doesn't have "bar" field.
  EXPECT_TRUE(converter.Convert(*value, &message));

  EXPECT_EQ(1, message.foo);
  EXPECT_TRUE(message.baz);
  EXPECT_EQ(2, static_cast<int>(message.ints.size()));
  EXPECT_EQ(1, *(message.ints[0]));
  EXPECT_EQ(2, *(message.ints[1]));
}

TEST(JSONValueConverterTest, EnumParserFails) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1,\n"
      "  \"bar\": \"bar\",\n"
      "  \"baz\": true,\n"
      "  \"simple_enum\": \"baz\","
      "  \"ints\": [1, 2]"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  SimpleMessage message;
  base::JSONValueConverter<SimpleMessage> converter;
  EXPECT_FALSE(converter.Convert(*value, &message));
  // No check the values as mentioned above.
}

TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
  const char normal_data[] =
      "{\n"
      "  \"foo\": 1,\n"
      "  \"bar\": \"bar\",\n"
      "  \"baz\": true,\n"
      "  \"simple_enum\": \"baz\","
      "  \"ints\": [1, false]"
      "}\n";

  Optional<Value> value = base::JSONReader::Read(normal_data);
  ASSERT_TRUE(value);
  SimpleMessage message;
  base::JSONValueConverter<SimpleMessage> converter;
  EXPECT_FALSE(converter.Convert(*value, &message));
  // No check the values as mentioned above.
}

}  // namespace base
