// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/json/json_parser.h"

#include <array>

#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {

TEST(JSONParserTest, Reading) {
  JSONParseError error;
  bool has_comments = false;
  JSONValue* tmp_value;
  std::unique_ptr<JSONValue> root;
  std::unique_ptr<JSONValue> root2;
  String str_val;
  int int_val = 0;

  // Successful parsing returns kNoError.
  root = ParseJSON("1", &error);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
  root = ParseJSON("\"string\"", &error);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
  root = ParseJSON("[]", &error);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
  root = ParseJSON("{}", &error);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONParseErrorType::kNoError, error.type);

  // some whitespace checking
  root = ParseJSON("    null    ", &error);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
  EXPECT_EQ(JSONParseErrorType::kNoError, error.type);

  // Invalid JSON string
  root = ParseJSON("nu", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);

  // Error reporting
  root = ParseJSON("\n\n  nu", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 3, column: 3, Syntax error.", error.message);
  EXPECT_EQ(JSONParseErrorType::kSyntaxError, error.type);
  EXPECT_EQ(3, error.line);
  EXPECT_EQ(3, error.column);

  // Simple bool
  root = ParseJSON("true  ");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeBoolean, root->GetType());

  // Embedded comment
  root = ParseJSONWithCommentsDeprecated("40 /*/", &error, &has_comments);
  EXPECT_EQ(has_comments, true);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
  root = ParseJSONWithCommentsDeprecated("/* comment */null", &error,
                                         &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
  root = ParseJSONWithCommentsDeprecated("40 /* comment */", &error,
                                         &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(40, int_val);
  root = ParseJSONWithCommentsDeprecated(
      "/**/ 40 /* multi-line\n comment */ // more comment", &error,
      &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(40, int_val);
  root =
      ParseJSONWithCommentsDeprecated("true // comment", &error, &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeBoolean, root->GetType());
  root = ParseJSONWithCommentsDeprecated("/* comment */\"sample string\"",
                                         &error, &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_TRUE(root->AsString(&str_val));
  EXPECT_EQ("sample string", str_val);
  root = ParseJSONWithCommentsDeprecated("[1, /* comment, 2 ] */ \n 3]", &error,
                                         &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  JSONArray* list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(2u, list->size());
  tmp_value = list->at(0);
  ASSERT_TRUE(tmp_value);
  EXPECT_TRUE(tmp_value->AsInteger(&int_val));
  EXPECT_EQ(1, int_val);
  tmp_value = list->at(1);
  ASSERT_TRUE(tmp_value);
  EXPECT_TRUE(tmp_value->AsInteger(&int_val));
  EXPECT_EQ(3, int_val);
  root =
      ParseJSONWithCommentsDeprecated("[1, /*a*/2, 3]", &error, &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(3u, list->size());
  root = ParseJSONWithCommentsDeprecated("/* comment **/42", &error,
                                         &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(42, int_val);
  root = ParseJSONWithCommentsDeprecated(
      "/* comment **/\n"
      "// */ 43\n"
      "44",
      &error, &has_comments);
  EXPECT_EQ(has_comments, true);
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(44, int_val);

  // Comments are otherwise rejected.
  root = ParseJSON("/* comment */null", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("40 /* comment */", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);
  root = ParseJSON("[1, /*a*/2, 3]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 5, Syntax error.", error.message);

  // Test number formats
  root = ParseJSON("43");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(43, int_val);

  // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
  root = ParseJSON("043", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
  root = ParseJSON("0x43", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Unexpected data after root element.",
            error.message);
  root = ParseJSON("00", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);

  // Test 0 (which needs to be special cased because of the leading zero
  // clause).
  root = ParseJSON("0");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  int_val = 1;
  EXPECT_TRUE(root->AsInteger(&int_val));
  EXPECT_EQ(0, int_val);

  // Numbers that overflow ints should succeed, being internally promoted to
  // storage as doubles
  root = ParseJSON("2147483648");
  ASSERT_TRUE(root.get());
  double double_val;
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(2147483648.0, double_val);
  root = ParseJSON("-2147483649");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(-2147483649.0, double_val);

  // Parse a double
  root = ParseJSON("43.1");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(43.1, double_val);

  root = ParseJSON("4.3e-1");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(.43, double_val);

  root = ParseJSON("2.1e0");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(2.1, double_val);

  root = ParseJSON("2.1e+0001");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(21.0, double_val);

  root = ParseJSON("0.01");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeDouble, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(0.01, double_val);

  root = ParseJSON("1.00");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeInteger, root->GetType());
  double_val = 0.0;
  EXPECT_TRUE(root->AsDouble(&double_val));
  EXPECT_DOUBLE_EQ(1.0, double_val);

  // Fractional parts must have a digit before and after the decimal point.
  root = ParseJSON("1.", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
  root = ParseJSON(".1", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("1.e10", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);

  // Exponent must have a digit following the 'e'.
  root = ParseJSON("1e", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
  root = ParseJSON("1E", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
  root = ParseJSON("1e1.", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);
  root = ParseJSON("1e1.0", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);

  // INF/-INF/NaN are not valid
  root = ParseJSON("NaN", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("nan", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("inf", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);

  // Invalid number formats
  root = ParseJSON("4.3.1", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);
  root = ParseJSON("4e3.1", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);

  // Test string parser
  root = ParseJSON("\"hello world\"");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeString, root->GetType());
  EXPECT_TRUE(root->AsString(&str_val));
  EXPECT_EQ("hello world", str_val);

  // Empty string
  root = ParseJSON("\"\"");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeString, root->GetType());
  EXPECT_TRUE(root->AsString(&str_val));
  EXPECT_EQ("", str_val);

  // Test basic string escapes
  root = ParseJSON("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeString, root->GetType());
  EXPECT_TRUE(root->AsString(&str_val));
  EXPECT_EQ(" \"\\/\b\f\n\r\t\v", str_val);

  // Test hex and unicode escapes including the null character.
  root = ParseJSON("\"\\x41\\x00\\u1234\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);

  // Test invalid strings
  root = ParseJSON("\"no closing quote", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 18, Syntax error.", error.message);
  root = ParseJSON("\"\\z invalid escape char\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
  root = ParseJSON("\"not enough escape chars\\u123\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 27, Invalid escape sequence.", error.message);
  root = ParseJSON("\"extra backslash at end of input\\\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 35, Syntax error.", error.message);
  root = ParseJSON("\"a\"extra data", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
            error.message);

  // Bare control characters (including newlines) are not permitted in string
  // literals.
  root = ParseJSON("\"\n\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
  root = ParseJSON("[\"\n\"]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
  root = ParseJSON("{\"\n\": true}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
  root = ParseJSON("{\"key\": \"\n\"}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);
  root = ParseJSON("\"\x1b\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
  root = ParseJSON("[\"\x07\"]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
  root = ParseJSON("{\"\x09\": true}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
  root = ParseJSON("{\"key\": \"\x01\"}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);

  // Basic array
  root = ParseJSON("[true, false, null]");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(3U, list->size());

  // Empty array
  root = ParseJSON("[]");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(0U, list->size());

  // Nested arrays
  root = ParseJSON("[[true], [], [false, [], [null]], null]");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(4U, list->size());

  // Invalid, missing close brace.
  root = ParseJSON("[[true], [], [false, [], [null]], null", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 39, Syntax error.", error.message);

  // Invalid, too many commas
  root = ParseJSON("[true,, null]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);

  // Invalid, no commas
  root = ParseJSON("[true null]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);

  // Invalid, trailing comma
  root = ParseJSON("[true,]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);

  root = ParseJSON("[true]");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(1U, list->size());
  tmp_value = list->at(0);
  ASSERT_TRUE(tmp_value);
  EXPECT_EQ(JSONValue::kTypeBoolean, tmp_value->GetType());
  bool bool_value = false;
  EXPECT_TRUE(tmp_value->AsBoolean(&bool_value));
  EXPECT_TRUE(bool_value);

  // Don't allow empty elements.
  root = ParseJSON("[,]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
  root = ParseJSON("[true,,]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
  root = ParseJSON("[,true,]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
  root = ParseJSON("[true,,false]", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);

  // Test objects
  root = ParseJSON("{}");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeObject, root->GetType());

  root = ParseJSON("{\"number\":9.87654321, \"null\":null , \"S\" : \"str\" }");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
  JSONObject* object_val = JSONObject::Cast(root.get());
  ASSERT_TRUE(object_val);
  double_val = 0.0;
  EXPECT_TRUE(object_val->GetDouble("number", &double_val));
  EXPECT_DOUBLE_EQ(9.87654321, double_val);
  JSONValue* null_val = object_val->Get("null");
  ASSERT_TRUE(null_val);
  EXPECT_EQ(JSONValue::kTypeNull, null_val->GetType());
  EXPECT_TRUE(object_val->GetString("S", &str_val));
  EXPECT_EQ("str", str_val);

  // Test newline equivalence.
  root2 = ParseJSON(
      "{\n"
      "  \"number\":9.87654321,\n"
      "  \"null\":null,\n"
      "  \"S\":\"str\"\n"
      "}\n");
  ASSERT_TRUE(root2.get());
  EXPECT_EQ(root->ToJSONString(), root2->ToJSONString());

  root2 = ParseJSON(
      "{\r\n"
      "  \"number\":9.87654321,\r\n"
      "  \"null\":null,\r\n"
      "  \"S\":\"str\"\r\n"
      "}\r\n");
  ASSERT_TRUE(root2.get());
  EXPECT_EQ(root->ToJSONString(), root2->ToJSONString());

  // Test that allowed whitespace is limited to TAB, CR, LF and SP. There are
  // several other Unicode characters defined as whitespace, so a selection of
  // them are tested to ensure that they are not allowed.
  // U+0009 CHARACTER TABULATION is allowed
  root = ParseJSON("\t{\t\"key\"\t:\t[\t\"value1\"\t,\t\"value2\"\t]\t}\t");
  ASSERT_TRUE(root.get());
  // U+000A LINE FEED is allowed
  root = ParseJSON("\n{\n\"key\"\n:\n[\n\"value1\"\n,\n\"value2\"\n]\n}\n");
  ASSERT_TRUE(root.get());
  // U+000D CARRIAGE RETURN is allowed
  root = ParseJSON("\r{\r\"key\"\r:\r[\r\"value1\"\r,\r\"value2\"\r]\r}\r");
  ASSERT_TRUE(root.get());
  // U+0020 SPACE is allowed
  root = ParseJSON(" { \"key\" : [ \"value1\" , \"value2\" ] } ");
  ASSERT_TRUE(root.get());
  // U+000B LINE TABULATION is not allowed
  root = ParseJSON("[\x0b\"value\"]");
  ASSERT_FALSE(root.get());
  // U+00A0 NO-BREAK SPACE is not allowed
  UChar invalid_space_1[] = {0x5b, 0x00a0, 0x5d};  // [<U+00A0>]
  root = ParseJSON(String(base::span(invalid_space_1)));
  ASSERT_FALSE(root.get());
  // U+3000 IDEOGRAPHIC SPACE is not allowed
  UChar invalid_space_2[] = {0x5b, 0x3000, 0x5d};  // [<U+3000>]
  root = ParseJSON(String(base::span(invalid_space_2)));
  ASSERT_FALSE(root.get());

  // Test nesting
  root = ParseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
  object_val = JSONObject::Cast(root.get());
  ASSERT_TRUE(object_val);
  JSONObject* inner_object = object_val->GetJSONObject("inner");
  ASSERT_TRUE(inner_object);
  JSONArray* inner_array = inner_object->GetArray("array");
  ASSERT_TRUE(inner_array);
  EXPECT_EQ(1U, inner_array->size());
  bool_value = true;
  EXPECT_TRUE(object_val->GetBoolean("false", &bool_value));
  EXPECT_FALSE(bool_value);
  inner_object = object_val->GetJSONObject("d");
  EXPECT_TRUE(inner_object);

  // Test keys with periods
  root = ParseJSON("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
  object_val = JSONObject::Cast(root.get());
  ASSERT_TRUE(object_val);
  int integer_value = 0;
  EXPECT_TRUE(object_val->GetInteger("a.b", &integer_value));
  EXPECT_EQ(3, integer_value);
  EXPECT_TRUE(object_val->GetInteger("c", &integer_value));
  EXPECT_EQ(2, integer_value);
  inner_object = object_val->GetJSONObject("d.e.f");
  ASSERT_TRUE(inner_object);
  EXPECT_EQ(1U, inner_object->size());
  EXPECT_TRUE(inner_object->GetInteger("g.h.i.j", &integer_value));
  EXPECT_EQ(1, integer_value);

  root = ParseJSON("{\"a\":{\"b\":2},\"a.b\":1}");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeObject, root->GetType());
  object_val = JSONObject::Cast(root.get());
  ASSERT_TRUE(object_val);
  inner_object = object_val->GetJSONObject("a");
  ASSERT_TRUE(inner_object);
  EXPECT_TRUE(inner_object->GetInteger("b", &integer_value));
  EXPECT_EQ(2, integer_value);
  EXPECT_TRUE(object_val->GetInteger("a.b", &integer_value));
  EXPECT_EQ(1, integer_value);

  // Invalid, no closing brace
  root = ParseJSON("{\"a\": true");
  EXPECT_FALSE(root.get());

  // Invalid, keys must be quoted
  root = ParseJSON("{foo:true}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);

  // Invalid, trailing comma
  root = ParseJSON("{\"a\":true,}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);

  // Invalid, too many commas
  root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);

  // Invalid, no separator
  root = ParseJSON("{\"a\" \"b\"}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 6, Unexpected token.", error.message);

  // Invalid, lone comma.
  root = ParseJSON("{,}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
  root = ParseJSON("{\"a\":true,,}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
  root = ParseJSON("{,\"a\":true}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
  root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);

  // Test stack overflow
  StringBuilder evil;
  evil.ReserveCapacity(2000000);
  for (int i = 0; i < 1000000; ++i)
    evil.Append('[');
  for (int i = 0; i < 1000000; ++i)
    evil.Append(']');
  root = ParseJSON(evil.ToString(), &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);

  // A few thousand adjacent lists is fine.
  StringBuilder not_evil;
  not_evil.ReserveCapacity(15010);
  not_evil.Append('[');
  for (int i = 0; i < 5000; ++i)
    not_evil.Append("[],");
  not_evil.Append("[]]");
  root = ParseJSON(not_evil.ToString());
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeArray, root->GetType());
  list = JSONArray::Cast(root.get());
  ASSERT_TRUE(list);
  EXPECT_EQ(5001U, list->size());

  // Test utf8 encoded input
  root = ParseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\"", &error);
  ASSERT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);

  // Test utf16 encoded strings.
  root = ParseJSON("\"\\u20ac3,14\"");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeString, root->GetType());
  EXPECT_TRUE(root->AsString(&str_val));
  UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34};
  EXPECT_EQ(String(base::span(tmp2)), str_val);

  root = ParseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeString, root->GetType());
  EXPECT_TRUE(root->AsString(&str_val));
  UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c};
  EXPECT_EQ(String(base::span(tmp3)), str_val);

  // Invalid unicode in a string literal after applying escape sequences.
  root = ParseJSON("\n\n    \"\\ud800\"", &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ(
      "Line: 3, column: 5, Unsupported encoding. JSON and all string literals "
      "must contain valid Unicode characters.",
      error.message);

  // Invalid unicode in a JSON itself.
  UChar tmp4[] = {0x22, 0xd800, 0x22};  // "?"
  root = ParseJSON(String(base::span(tmp4)), &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ(
      "Line: 1, column: 1, Unsupported encoding. JSON and all string literals "
      "must contain valid Unicode characters.",
      error.message);

  // Invalid unicode in a JSON itself.
  UChar tmp5[] = {0x7b, 0x22, 0xd800, 0x22, 0x3a, 0x31, 0x7d};  // {"?":1}
  root = ParseJSON(String(base::span(tmp5)), &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ(
      "Line: 1, column: 2, Unsupported encoding. JSON and all string literals "
      "must contain valid Unicode characters.",
      error.message);

  // Test literal root objects.
  root = ParseJSON("null");
  ASSERT_TRUE(root.get());
  EXPECT_EQ(JSONValue::kTypeNull, root->GetType());

  root = ParseJSON("true");
  ASSERT_TRUE(root.get());
  EXPECT_TRUE(root->AsBoolean(&bool_value));
  EXPECT_TRUE(bool_value);

  root = ParseJSON("10");
  ASSERT_TRUE(root.get());
  EXPECT_TRUE(root->AsInteger(&integer_value));
  EXPECT_EQ(10, integer_value);

  root = ParseJSON("\"root\"");
  ASSERT_TRUE(root.get());
  EXPECT_TRUE(root->AsString(&str_val));
  EXPECT_EQ("root", str_val);
}

TEST(JSONParserTest, InvalidSanity) {
  constexpr auto kInvalidJson = std::to_array<const char* const>(
      {"/* test *", "{\"foo\"", "{\"foo\":", "  [", "\"\\u123g\"",
       "{\n\"eh:\n}", "////", "*/**/", "/**/", "/*/", "//**/", "\"\\"});

  for (const auto* invalid_json : kInvalidJson) {
    std::unique_ptr<JSONValue> result = ParseJSON(invalid_json);
    EXPECT_FALSE(result.get());
  }
}

// Test that the nesting depth can be limited to values less than 1000, but
// cannot be extended past that maximum.
TEST(JSONParserTest, LimitedDepth) {
  std::unique_ptr<JSONValue> root;
  JSONCommentState comment_state = JSONCommentState::kDisallowed;
  JSONParseError error;

  // Test cases. Each pair is a JSON string, and the minimum depth required
  // to successfully parse that string.
  Vector<std::pair<const char*, int>> test_cases = {
      {"[[[[[]]]]]", 5},
      {"[[[[[\"a\"]]]]]", 6},
      {"[[],[],[],[],[]]", 2},
      {"{\"a\":{\"a\":{\"a\":{\"a\":{\"a\": \"a\"}}}}}", 6},
      {"\"root\"", 1}};

  for (const auto& test_case : test_cases) {
    // Each test case should parse successfully at the default depth
    root = ParseJSON(test_case.first);
    EXPECT_TRUE(root.get());

    // ... and should parse successfully at the minimum depth
    root = ParseJSON(test_case.first, comment_state, test_case.second);
    EXPECT_TRUE(root.get());

    // ... but should fail to parse at a shallower depth.
    root = ParseJSON(test_case.first, comment_state, test_case.second - 1);
    EXPECT_FALSE(root.get());
  }

  // Test that everything fails to parse with depth 0
  root = ParseJSON("", comment_state, 0, &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("", comment_state, -1, &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
  root = ParseJSON("true", comment_state, 0, &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1, Too much nesting.", error.message);

  // Test that the limit can be set to the constant maximum.
  StringBuilder evil;
  evil.ReserveCapacity(2002);
  for (int i = 0; i < 1000; ++i)
    evil.Append('[');
  for (int i = 0; i < 1000; ++i)
    evil.Append(']');
  root = ParseJSON(evil.ToString());
  EXPECT_TRUE(root.get());
  root = ParseJSON(evil.ToString(), comment_state, 1000);
  EXPECT_TRUE(root.get());

  // Test that the limit cannot be set higher than the constant maximum.
  evil.Clear();
  for (int i = 0; i < 1001; ++i)
    evil.Append('[');
  for (int i = 0; i < 1001; ++i)
    evil.Append(']');
  root = ParseJSON(evil.ToString(), &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
  root = ParseJSON(evil.ToString(), comment_state, 1001, &error);
  EXPECT_FALSE(root.get());
  EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
}

}  // namespace blink
