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"
13 TEST(JSONStringEscapeTest
, EscapeUTF8
) {
15 const char* to_escape
;
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
;
33 EscapeJSONString(in_ptr
, false, &out
);
34 EXPECT_EQ(std::string(cases
[i
].escaped
), out
);
35 EXPECT_TRUE(IsStringUTF8(out
));
38 bool convert_ok
= EscapeJSONString(in_str
, false, &out
);
39 EXPECT_EQ(std::string(cases
[i
].escaped
), out
);
40 EXPECT_TRUE(IsStringUTF8(out
));
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
;
51 EscapeJSONString(in
, false, &out
);
52 EXPECT_TRUE(IsStringUTF8(out
));
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
;
68 EscapeJSONString(in
, false, &out
);
69 EXPECT_EQ(expected
, out
);
70 EXPECT_TRUE(IsStringUTF8(out
));
73 TEST(JSONStringEscapeTest
, EscapeUTF16
) {
75 const wchar_t* to_escape
;
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
);
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
);
103 EscapeJSONString(in
, false, &out
);
104 EXPECT_TRUE(IsStringUTF8(out
));
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
;
120 EscapeJSONString(in
, false, &out
);
121 EXPECT_EQ(expected
, out
);
122 EXPECT_TRUE(IsStringUTF8(out
));
125 TEST(JSONStringEscapeTest
, EscapeUTF16OutsideBMP
) {
127 // {a, U+10300, !}, SMP.
130 test
.push_back(0xD800);
131 test
.push_back(0xDF00);
134 EXPECT_TRUE(EscapeJSONString(test
, false, &actual
));
135 EXPECT_EQ("a\xF0\x90\x8C\x80!", actual
);
138 // {U+20021, U+2002B}, SIP.
140 test
.push_back(0xD840);
141 test
.push_back(0xDC21);
142 test
.push_back(0xD840);
143 test
.push_back(0xDC2B);
145 EXPECT_TRUE(EscapeJSONString(test
, false, &actual
));
146 EXPECT_EQ("\xF0\xA0\x80\xA1\xF0\xA0\x80\xAB", actual
);
149 // {?, U+D800, @}, lone surrogate.
152 test
.push_back(0xD800);
155 EXPECT_FALSE(EscapeJSONString(test
, false, &actual
));
156 EXPECT_EQ("?\xEF\xBF\xBD@", actual
);
160 TEST(JSONStringEscapeTest
, EscapeBytes
) {
162 const char* to_escape
;
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));