// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/json/json_parser.h" #include #include #include #include "base/json/json_reader.h" #include "base/memory/ptr_util.h" #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace internal { class JSONParserTest : public testing::Test { public: JSONParser* NewTestParser(const std::string& input, int options = JSON_PARSE_RFC) { JSONParser* parser = new JSONParser(options); parser->input_ = input; parser->index_ = 0; return parser; } void TestLastThree(JSONParser* parser) { EXPECT_EQ(',', *parser->PeekChar()); parser->ConsumeChar(); EXPECT_EQ('|', *parser->PeekChar()); parser->ConsumeChar(); EXPECT_EQ('\0', *parser->pos()); EXPECT_EQ(static_cast(parser->index_), parser->input_.length()); } }; TEST_F(JSONParserTest, NextChar) { std::string input("Hello world"); std::unique_ptr parser(NewTestParser(input)); EXPECT_EQ('H', *parser->pos()); for (size_t i = 1; i < input.length(); ++i) { parser->ConsumeChar(); EXPECT_EQ(input[i], *parser->PeekChar()); } parser->ConsumeChar(); EXPECT_EQ('\0', *parser->pos()); EXPECT_EQ(static_cast(parser->index_), parser->input_.length()); } TEST_F(JSONParserTest, ConsumeString) { std::string input("\"test\",|"); std::unique_ptr parser(NewTestParser(input)); std::optional value(parser->ConsumeString()); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_string()); EXPECT_EQ("test", value->GetString()); } TEST_F(JSONParserTest, ConsumeList) { std::string input("[true, false],|"); std::unique_ptr parser(NewTestParser(input)); std::optional value(parser->ConsumeList()); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); Value::List* list = value->GetIfList(); ASSERT_TRUE(list); EXPECT_EQ(2u, list->size()); } TEST_F(JSONParserTest, ConsumeDictionary) { std::string input("{\"abc\":\"def\"},|"); std::unique_ptr parser(NewTestParser(input)); std::optional value(parser->ConsumeDictionary()); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); const Value::Dict* value_dict = value->GetIfDict(); ASSERT_TRUE(value_dict); const std::string* str = value_dict->FindString("abc"); ASSERT_TRUE(str); EXPECT_EQ("def", *str); } TEST_F(JSONParserTest, ConsumeLiterals) { // Literal |true|. std::string input("true,|"); std::unique_ptr parser(NewTestParser(input)); std::optional value(parser->ConsumeLiteral()); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_bool()); EXPECT_TRUE(value->GetBool()); // Literal |false|. input = "false,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeLiteral(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_bool()); EXPECT_FALSE(value->GetBool()); // Literal |null|. input = "null,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeLiteral(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); EXPECT_TRUE(value->is_none()); } TEST_F(JSONParserTest, ConsumeNumbers) { // Integer. std::string input("1234,|"); std::unique_ptr parser(NewTestParser(input)); std::optional value(parser->ConsumeNumber()); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_int()); EXPECT_EQ(1234, value->GetInt()); // Negative integer. input = "-1234,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_int()); EXPECT_EQ(-1234, value->GetInt()); // Negative zero integer. input = "-0,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(-0.0, value->GetDouble()); // Double. input = "12.34,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(12.34, value->GetDouble()); // Negative zero double. input = "-0.0,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(-0.0, value->GetDouble()); // Scientific. input = "42e3,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(42000, value->GetDouble()); // Negative scientific. input = "314159e-5,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(3.14159, value->GetDouble()); // Positive scientific. input = "0.42e+3,|"; parser.reset(NewTestParser(input)); value = parser->ConsumeNumber(); EXPECT_EQ(',', *parser->pos()); TestLastThree(parser.get()); ASSERT_TRUE(value); ASSERT_TRUE(value->is_double()); EXPECT_EQ(420, value->GetDouble()); } TEST_F(JSONParserTest, ErrorMessages) { { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("[42]"); EXPECT_TRUE(value); EXPECT_TRUE(parser.GetErrorMessage().empty()); EXPECT_EQ(0, parser.error_code()); } // Test each of the error conditions { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("{},{}"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage( 1, 3, JSONParser::kUnexpectedDataAfterRoot), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_UNEXPECTED_DATA_AFTER_ROOT, parser.error_code()); } { std::string nested_json; for (int i = 0; i < 201; ++i) { nested_json.insert(nested_json.begin(), '['); nested_json.append(1, ']'); } JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse(nested_json); EXPECT_FALSE(value); EXPECT_EQ( JSONParser::FormatErrorMessage(1, 200, JSONParser::kTooMuchNesting), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_TOO_MUCH_NESTING, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("[1,]"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 4, JSONParser::kTrailingComma), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_TRAILING_COMMA, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("{foo:\"bar\"}"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage( 1, 2, JSONParser::kUnquotedDictionaryKey), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_UNQUOTED_DICTIONARY_KEY, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("{\"foo\":\"bar\",}"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 14, JSONParser::kTrailingComma), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_TRAILING_COMMA, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("[nu]"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2, JSONParser::kSyntaxError), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_SYNTAX_ERROR, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC | JSON_ALLOW_X_ESCAPES); std::optional value = parser.Parse("[\"xxx\\xq\"]"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("[\"xxx\\uq\"]"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("[\"xxx\\q\"]"); EXPECT_FALSE(value); EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); } { JSONParser parser(JSON_PARSE_RFC); std::optional value = parser.Parse("\"abc\ndef\""); EXPECT_FALSE(value); EXPECT_EQ( JSONParser::FormatErrorMessage(1, 4, JSONParser::kUnsupportedEncoding), parser.GetErrorMessage()); EXPECT_EQ(JSONParser::JSON_UNSUPPORTED_ENCODING, parser.error_code()); } } } // namespace internal } // namespace base