1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "base/json/json_reader.h"
7 #include "base/json/json_writer.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/values.h"
12 #include "components/safe_json/json_sanitizer.h"
13 #include "components/safe_json/safe_json_parser.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 #if !defined(OS_ANDROID)
17 #include "components/safe_json/testing_json_parser.h"
22 class JsonSanitizerTest
: public ::testing::Test
{
24 void TearDown() override
{
25 // Flush any tasks from the message loop to avoid leaks.
26 base::RunLoop().RunUntilIdle();
30 void CheckSuccess(const std::string
& json
);
31 void CheckError(const std::string
& json
);
35 // ERROR is a #define on Windows, so we prefix the values with STATE_.
41 void Sanitize(const std::string
& json
);
43 void OnSuccess(const std::string
& json
);
44 void OnError(const std::string
& error
);
46 base::MessageLoop message_loop_
;
48 #if !defined(OS_ANDROID)
49 safe_json::TestingJsonParser::ScopedFactoryOverride factory_override_
;
56 scoped_ptr
<base::RunLoop
> run_loop_
;
59 void JsonSanitizerTest::CheckSuccess(const std::string
& json
) {
62 scoped_ptr
<base::Value
> parsed
= base::JSONReader::Read(json
);
64 EXPECT_EQ(State::STATE_SUCCESS
, state_
) << "Error: " << error_
;
66 // The JSON parser should accept the result.
69 scoped_ptr
<base::Value
> reparsed
= base::JSONReader::ReadAndReturnError(
70 result_
, base::JSON_PARSE_RFC
, &error_code
, &error
);
72 << "Invalid result: " << error
;
74 // The parsed values should be equal.
75 EXPECT_TRUE(reparsed
->Equals(parsed
.get()));
78 void JsonSanitizerTest::CheckError(const std::string
& json
) {
81 EXPECT_EQ(State::STATE_ERROR
, state_
) << "Result: " << result_
;
84 void JsonSanitizerTest::Sanitize(const std::string
& json
) {
85 state_
= State::STATE_IDLE
;
88 run_loop_
.reset(new base::RunLoop
);
89 JsonSanitizer::Sanitize(
91 base::Bind(&JsonSanitizerTest::OnSuccess
, base::Unretained(this)),
92 base::Bind(&JsonSanitizerTest::OnError
, base::Unretained(this)));
94 // We should never get a result immediately.
95 EXPECT_EQ(State::STATE_IDLE
, state_
);
99 void JsonSanitizerTest::OnSuccess(const std::string
& json
) {
100 ASSERT_EQ(State::STATE_IDLE
, state_
);
101 state_
= State::STATE_SUCCESS
;
106 void JsonSanitizerTest::OnError(const std::string
& error
) {
107 ASSERT_EQ(State::STATE_IDLE
, state_
);
108 state_
= State::STATE_ERROR
;
113 TEST_F(JsonSanitizerTest
, Json
) {
115 CheckSuccess("{\n \"foo\": \"bar\"\n}");
116 CheckSuccess("[true]");
117 CheckSuccess("[42]");
118 CheckSuccess("[3.14]");
119 CheckSuccess("[4.0]");
120 CheckSuccess("[null]");
121 CheckSuccess("[\"foo\", \"bar\"]");
123 // JSON syntax errors:
128 // Unterminated array.
129 CheckError("[1,2,3,]");
132 TEST_F(JsonSanitizerTest
, Nesting
) {
133 // 99 nested arrays are fine.
134 std::string
nested(99u, '[');
135 nested
.append(99u, ']');
136 CheckSuccess(nested
);
138 // 100 nested arrays is too much.
139 CheckError(std::string(100u, '[') + std::string(100u, ']'));
142 TEST_F(JsonSanitizerTest
, Unicode
) {
143 // Non-ASCII characters encoded either directly as UTF-8 or escaped as UTF-16:
144 CheckSuccess("[\"☃\"]");
145 CheckSuccess("[\"\\u2603\"]");
146 CheckSuccess("[\"😃\"]");
147 CheckSuccess("[\"\\ud83d\\ude03\"]");
150 // A continuation byte outside of a sequence.
151 CheckError("[\"\x80\"]");
153 // A start byte that is missing a continuation byte.
154 CheckError("[\"\xc0\"]");
156 // An invalid byte in UTF-8.
157 CheckError("[\"\xfe\"]");
159 // An overlong encoding (of the letter 'A').
160 CheckError("[\"\xc1\x81\"]");
162 // U+D83D, a code point reserved for (high) surrogates.
163 CheckError("[\"\xed\xa0\xbd\"]");
165 // U+4567890, a code point outside of the valid range for Unicode.
166 CheckError("[\"\xfc\x84\x95\xa7\xa2\x90\"]");
168 // Malformed escaped UTF-16:
169 // An unmatched high surrogate.
170 CheckError("[\"\\ud83d\"]");
172 // An unmatched low surrogate.
173 CheckError("[\"\\ude03\"]");
175 // A low surrogate followed by a high surrogate.
176 CheckError("[\"\\ude03\\ud83d\"]");
178 // Valid escaped UTF-16 that encodes non-characters:
179 CheckError("[\"\\ufdd0\"]");
180 CheckError("[\"\\ufffe\"]");
181 CheckError("[\"\\ud83f\\udffe\"]");
184 } // namespace safe_json