Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / base / json / string_escape_unittest.cc
blobf7ccafc9cb5f4ccd5704b6c0c5a429cc5b447b3b
1 // Copyright (c) 2013 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.
5 #include "base/json/string_escape.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 namespace base {
13 TEST(JSONStringEscapeTest, EscapeUTF8) {
14 const struct {
15 const char* to_escape;
16 const char* escaped;
17 } cases[] = {
18 {"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
19 {"a\b\f\n\r\t\v\1\\.\"z",
20 "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
21 {"b\x0f\x7f\xf0\xff!", // \xf0\xff is not a valid UTF-8 unit.
22 "b\\u000F\x7F\xEF\xBF\xBD\xEF\xBF\xBD!"},
23 {"c<>d", "c\\u003C>d"},
24 {"Hello\xe2\x80\xa8world", "Hello\\u2028world"},
25 {"\xe2\x80\xa9purple", "\\u2029purple"},
28 for (size_t i = 0; i < arraysize(cases); ++i) {
29 const char* in_ptr = cases[i].to_escape;
30 std::string in_str = in_ptr;
32 std::string out;
33 EscapeJSONString(in_ptr, false, &out);
34 EXPECT_EQ(std::string(cases[i].escaped), out);
35 EXPECT_TRUE(IsStringUTF8(out));
37 out.erase();
38 bool convert_ok = EscapeJSONString(in_str, false, &out);
39 EXPECT_EQ(std::string(cases[i].escaped), out);
40 EXPECT_TRUE(IsStringUTF8(out));
42 if (convert_ok) {
43 std::string fooout = GetQuotedJSONString(in_str);
44 EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"", fooout);
45 EXPECT_TRUE(IsStringUTF8(out));
49 std::string in = cases[0].to_escape;
50 std::string out;
51 EscapeJSONString(in, false, &out);
52 EXPECT_TRUE(IsStringUTF8(out));
54 // test quoting
55 std::string out_quoted;
56 EscapeJSONString(in, true, &out_quoted);
57 EXPECT_EQ(out.length() + 2, out_quoted.length());
58 EXPECT_EQ(out_quoted.find(out), 1U);
59 EXPECT_TRUE(IsStringUTF8(out_quoted));
61 // now try with a NULL in the string
62 std::string null_prepend = "test";
63 null_prepend.push_back(0);
64 in = null_prepend + in;
65 std::string expected = "test\\u0000";
66 expected += cases[0].escaped;
67 out.clear();
68 EscapeJSONString(in, false, &out);
69 EXPECT_EQ(expected, out);
70 EXPECT_TRUE(IsStringUTF8(out));
73 TEST(JSONStringEscapeTest, EscapeUTF16) {
74 const struct {
75 const wchar_t* to_escape;
76 const char* escaped;
77 } cases[] = {
78 {L"b\uffb1\u00ff", "b\xEF\xBE\xB1\xC3\xBF"},
79 {L"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
80 {L"a\b\f\n\r\t\v\1\\.\"z",
81 "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
82 {L"b\x0f\x7f\xf0\xff!", "b\\u000F\x7F\xC3\xB0\xC3\xBF!"},
83 {L"c<>d", "c\\u003C>d"},
84 {L"Hello\u2028world", "Hello\\u2028world"},
85 {L"\u2029purple", "\\u2029purple"},
88 for (size_t i = 0; i < arraysize(cases); ++i) {
89 string16 in = WideToUTF16(cases[i].to_escape);
91 std::string out;
92 EscapeJSONString(in, false, &out);
93 EXPECT_EQ(std::string(cases[i].escaped), out);
94 EXPECT_TRUE(IsStringUTF8(out));
96 out = GetQuotedJSONString(in);
97 EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"", out);
98 EXPECT_TRUE(IsStringUTF8(out));
101 string16 in = WideToUTF16(cases[0].to_escape);
102 std::string out;
103 EscapeJSONString(in, false, &out);
104 EXPECT_TRUE(IsStringUTF8(out));
106 // test quoting
107 std::string out_quoted;
108 EscapeJSONString(in, true, &out_quoted);
109 EXPECT_EQ(out.length() + 2, out_quoted.length());
110 EXPECT_EQ(out_quoted.find(out), 1U);
111 EXPECT_TRUE(IsStringUTF8(out));
113 // now try with a NULL in the string
114 string16 null_prepend = WideToUTF16(L"test");
115 null_prepend.push_back(0);
116 in = null_prepend + in;
117 std::string expected = "test\\u0000";
118 expected += cases[0].escaped;
119 out.clear();
120 EscapeJSONString(in, false, &out);
121 EXPECT_EQ(expected, out);
122 EXPECT_TRUE(IsStringUTF8(out));
125 TEST(JSONStringEscapeTest, EscapeUTF16OutsideBMP) {
127 // {a, U+10300, !}, SMP.
128 string16 test;
129 test.push_back('a');
130 test.push_back(0xD800);
131 test.push_back(0xDF00);
132 test.push_back('!');
133 std::string actual;
134 EXPECT_TRUE(EscapeJSONString(test, false, &actual));
135 EXPECT_EQ("a\xF0\x90\x8C\x80!", actual);
138 // {U+20021, U+2002B}, SIP.
139 string16 test;
140 test.push_back(0xD840);
141 test.push_back(0xDC21);
142 test.push_back(0xD840);
143 test.push_back(0xDC2B);
144 std::string actual;
145 EXPECT_TRUE(EscapeJSONString(test, false, &actual));
146 EXPECT_EQ("\xF0\xA0\x80\xA1\xF0\xA0\x80\xAB", actual);
149 // {?, U+D800, @}, lone surrogate.
150 string16 test;
151 test.push_back('?');
152 test.push_back(0xD800);
153 test.push_back('@');
154 std::string actual;
155 EXPECT_FALSE(EscapeJSONString(test, false, &actual));
156 EXPECT_EQ("?\xEF\xBF\xBD@", actual);
160 TEST(JSONStringEscapeTest, EscapeBytes) {
161 const struct {
162 const char* to_escape;
163 const char* escaped;
164 } cases[] = {
165 {"b\x0f\x7f\xf0\xff!", "b\\u000F\\u007F\\u00F0\\u00FF!"},
166 {"\xe5\xc4\x4f\x05\xb6\xfd", "\\u00E5\\u00C4O\\u0005\\u00B6\\u00FD"},
169 for (size_t i = 0; i < arraysize(cases); ++i) {
170 std::string in = std::string(cases[i].to_escape);
171 EXPECT_FALSE(IsStringUTF8(in));
173 EXPECT_EQ(std::string(cases[i].escaped),
174 EscapeBytesAsInvalidJSONString(in, false));
175 EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"",
176 EscapeBytesAsInvalidJSONString(in, true));
179 const char kEmbedNull[] = { '\xab', '\x39', '\0', '\x9f', '\xab' };
180 std::string in(kEmbedNull, arraysize(kEmbedNull));
181 EXPECT_FALSE(IsStringUTF8(in));
182 EXPECT_EQ(std::string("\\u00AB9\\u0000\\u009F\\u00AB"),
183 EscapeBytesAsInvalidJSONString(in, false));
186 } // namespace base