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"},
26 for (size_t i
= 0; i
< arraysize(cases
); ++i
) {
27 const char* in_ptr
= cases
[i
].to_escape
;
28 std::string in_str
= in_ptr
;
31 EscapeJSONString(in_ptr
, false, &out
);
32 EXPECT_EQ(std::string(cases
[i
].escaped
), out
);
33 EXPECT_TRUE(IsStringUTF8(out
));
36 bool convert_ok
= EscapeJSONString(in_str
, false, &out
);
37 EXPECT_EQ(std::string(cases
[i
].escaped
), out
);
38 EXPECT_TRUE(IsStringUTF8(out
));
41 std::string fooout
= GetQuotedJSONString(in_str
);
42 EXPECT_EQ("\"" + std::string(cases
[i
].escaped
) + "\"", fooout
);
43 EXPECT_TRUE(IsStringUTF8(out
));
47 std::string in
= cases
[0].to_escape
;
49 EscapeJSONString(in
, false, &out
);
50 EXPECT_TRUE(IsStringUTF8(out
));
53 std::string out_quoted
;
54 EscapeJSONString(in
, true, &out_quoted
);
55 EXPECT_EQ(out
.length() + 2, out_quoted
.length());
56 EXPECT_EQ(out_quoted
.find(out
), 1U);
57 EXPECT_TRUE(IsStringUTF8(out_quoted
));
59 // now try with a NULL in the string
60 std::string null_prepend
= "test";
61 null_prepend
.push_back(0);
62 in
= null_prepend
+ in
;
63 std::string expected
= "test\\u0000";
64 expected
+= cases
[0].escaped
;
66 EscapeJSONString(in
, false, &out
);
67 EXPECT_EQ(expected
, out
);
68 EXPECT_TRUE(IsStringUTF8(out
));
71 TEST(JSONStringEscapeTest
, EscapeUTF16
) {
73 const wchar_t* to_escape
;
76 {L
"b\uffb1\u00ff", "b\xEF\xBE\xB1\xC3\xBF"},
77 {L
"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
78 {L
"a\b\f\n\r\t\v\1\\.\"z",
79 "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
80 {L
"b\x0f\x7f\xf0\xff!", "b\\u000F\x7F\xC3\xB0\xC3\xBF!"},
81 {L
"c<>d", "c\\u003C>d"},
84 for (size_t i
= 0; i
< arraysize(cases
); ++i
) {
85 string16 in
= WideToUTF16(cases
[i
].to_escape
);
88 EscapeJSONString(in
, false, &out
);
89 EXPECT_EQ(std::string(cases
[i
].escaped
), out
);
90 EXPECT_TRUE(IsStringUTF8(out
));
92 out
= GetQuotedJSONString(in
);
93 EXPECT_EQ("\"" + std::string(cases
[i
].escaped
) + "\"", out
);
94 EXPECT_TRUE(IsStringUTF8(out
));
97 string16 in
= WideToUTF16(cases
[0].to_escape
);
99 EscapeJSONString(in
, false, &out
);
100 EXPECT_TRUE(IsStringUTF8(out
));
103 std::string out_quoted
;
104 EscapeJSONString(in
, true, &out_quoted
);
105 EXPECT_EQ(out
.length() + 2, out_quoted
.length());
106 EXPECT_EQ(out_quoted
.find(out
), 1U);
107 EXPECT_TRUE(IsStringUTF8(out
));
109 // now try with a NULL in the string
110 string16 null_prepend
= WideToUTF16(L
"test");
111 null_prepend
.push_back(0);
112 in
= null_prepend
+ in
;
113 std::string expected
= "test\\u0000";
114 expected
+= cases
[0].escaped
;
116 EscapeJSONString(in
, false, &out
);
117 EXPECT_EQ(expected
, out
);
118 EXPECT_TRUE(IsStringUTF8(out
));
121 TEST(JSONStringEscapeTest
, EscapeUTF16OutsideBMP
) {
123 // {a, U+10300, !}, SMP.
126 test
.push_back(0xD800);
127 test
.push_back(0xDF00);
130 EXPECT_TRUE(EscapeJSONString(test
, false, &actual
));
131 EXPECT_EQ("a\xF0\x90\x8C\x80!", actual
);
134 // {U+20021, U+2002B}, SIP.
136 test
.push_back(0xD840);
137 test
.push_back(0xDC21);
138 test
.push_back(0xD840);
139 test
.push_back(0xDC2B);
141 EXPECT_TRUE(EscapeJSONString(test
, false, &actual
));
142 EXPECT_EQ("\xF0\xA0\x80\xA1\xF0\xA0\x80\xAB", actual
);
145 // {?, U+D800, @}, lone surrogate.
148 test
.push_back(0xD800);
151 EXPECT_FALSE(EscapeJSONString(test
, false, &actual
));
152 EXPECT_EQ("?\xEF\xBF\xBD@", actual
);
156 TEST(JSONStringEscapeTest
, EscapeBytes
) {
158 const char* to_escape
;
161 {"b\x0f\x7f\xf0\xff!", "b\\u000F\\u007F\\u00F0\\u00FF!"},
162 {"\xe5\xc4\x4f\x05\xb6\xfd\0", "\\u00E5\\u00C4O\\u0005\\u00B6\\u00FD"},
165 for (size_t i
= 0; i
< arraysize(cases
); ++i
) {
166 std::string in
= std::string(cases
[i
].to_escape
);
167 EXPECT_FALSE(IsStringUTF8(in
));
169 EXPECT_EQ(std::string(cases
[i
].escaped
),
170 EscapeBytesAsInvalidJSONString(in
, false));
171 EXPECT_EQ("\"" + std::string(cases
[i
].escaped
) + "\"",
172 EscapeBytesAsInvalidJSONString(in
, true));
175 const char kEmbedNull
[] = { '\xab', '\x39', '\0', '\x9f', '\xab' };
176 std::string
in(kEmbedNull
, arraysize(kEmbedNull
));
177 EXPECT_FALSE(IsStringUTF8(in
));
178 EXPECT_EQ(std::string("\\u00AB9\\u0000\\u009F\\u00AB"),
179 EscapeBytesAsInvalidJSONString(in
, false));