blob: fa8fe31031d07166e38b48a18971e1c404d835e7 [file] [log] [blame]
// 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 <stddef.h>
#include <memory>
#include <optional>
#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<size_t>(parser->index_), parser->input_.length());
}
};
TEST_F(JSONParserTest, NextChar) {
std::string input("Hello world");
std::unique_ptr<JSONParser> 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<size_t>(parser->index_), parser->input_.length());
}
TEST_F(JSONParserTest, ConsumeString) {
std::string input("\"test\",|");
std::unique_ptr<JSONParser> parser(NewTestParser(input));
std::optional<Value> 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<JSONParser> parser(NewTestParser(input));
std::optional<Value> 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<JSONParser> parser(NewTestParser(input));
std::optional<Value> 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<JSONParser> parser(NewTestParser(input));
std::optional<Value> 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<JSONParser> parser(NewTestParser(input));
std::optional<Value> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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