Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: base/utf_string_conversions_unittest.cc

Issue 372017: Fix various problems with inline autocomplete and URLs that change length dur... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/utf_string_conversions.cc ('k') | chrome/browser/autocomplete/autocomplete.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <math.h>
6 #include <stdarg.h>
7
8 #include <limits>
9 #include <sstream>
10
11 #include "base/basictypes.h" 5 #include "base/basictypes.h"
12 #include "base/string_util.h" 6 #include "base/string_util.h"
13 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
14 8
15 namespace base { 9 namespace base {
16 10
17 namespace { 11 namespace {
18 12
19 // Given a null-terminated string of wchar_t with each wchar_t representing 13 // Given a null-terminated string of wchar_t with each wchar_t representing
20 // a UTF-16 code unit, returns a string16 made up of wchar_t's in the input. 14 // a UTF-16 code unit, returns a string16 made up of wchar_t's in the input.
21 // Each wchar_t should be <= 0xFFFF and a non-BMP character (> U+FFFF) 15 // Each wchar_t should be <= 0xFFFF and a non-BMP character (> U+FFFF)
22 // should be represented as a surrogate pair (two UTF-16 units) 16 // should be represented as a surrogate pair (two UTF-16 units)
23 // *even* where wchar_t is 32-bit (Linux and Mac). 17 // *even* where wchar_t is 32-bit (Linux and Mac).
24 // 18 //
25 // This is to help write tests for functions with string16 params until 19 // This is to help write tests for functions with string16 params until
26 // the C++ 0x UTF-16 literal is well-supported by compilers. 20 // the C++ 0x UTF-16 literal is well-supported by compilers.
27 string16 BuildString16(const wchar_t* s) { 21 string16 BuildString16(const wchar_t* s) {
28 #if defined(WCHAR_T_IS_UTF16) 22 #if defined(WCHAR_T_IS_UTF16)
29 return string16(s); 23 return string16(s);
30 #elif defined(WCHAR_T_IS_UTF32) 24 #elif defined(WCHAR_T_IS_UTF32)
31 string16 u16; 25 string16 u16;
32 while (*s != 0) { 26 while (*s != 0) {
33 DCHECK(static_cast<unsigned int>(*s) <= 0xFFFFu); 27 DCHECK(static_cast<unsigned int>(*s) <= 0xFFFFu);
34 u16.push_back(*s++); 28 u16.push_back(*s++);
35 } 29 }
36 return u16; 30 return u16;
37 #endif 31 #endif
38 } 32 }
39 33
40 } // namespace 34 const wchar_t* const kConvertRoundtripCases[] = {
41
42 static const struct trim_case {
43 const wchar_t* input;
44 const TrimPositions positions;
45 const wchar_t* output;
46 const TrimPositions return_value;
47 } trim_cases[] = {
48 {L" Google Video ", TRIM_LEADING, L"Google Video ", TRIM_LEADING},
49 {L" Google Video ", TRIM_TRAILING, L" Google Video", TRIM_TRAILING},
50 {L" Google Video ", TRIM_ALL, L"Google Video", TRIM_ALL},
51 {L"Google Video", TRIM_ALL, L"Google Video", TRIM_NONE},
52 {L"", TRIM_ALL, L"", TRIM_NONE},
53 {L" ", TRIM_LEADING, L"", TRIM_LEADING},
54 {L" ", TRIM_TRAILING, L"", TRIM_TRAILING},
55 {L" ", TRIM_ALL, L"", TRIM_ALL},
56 {L"\t\rTest String\n", TRIM_ALL, L"Test String", TRIM_ALL},
57 {L"\x2002Test String\x00A0\x3000", TRIM_ALL, L"Test String", TRIM_ALL},
58 };
59
60 static const struct trim_case_ascii {
61 const char* input;
62 const TrimPositions positions;
63 const char* output;
64 const TrimPositions return_value;
65 } trim_cases_ascii[] = {
66 {" Google Video ", TRIM_LEADING, "Google Video ", TRIM_LEADING},
67 {" Google Video ", TRIM_TRAILING, " Google Video", TRIM_TRAILING},
68 {" Google Video ", TRIM_ALL, "Google Video", TRIM_ALL},
69 {"Google Video", TRIM_ALL, "Google Video", TRIM_NONE},
70 {"", TRIM_ALL, "", TRIM_NONE},
71 {" ", TRIM_LEADING, "", TRIM_LEADING},
72 {" ", TRIM_TRAILING, "", TRIM_TRAILING},
73 {" ", TRIM_ALL, "", TRIM_ALL},
74 {"\t\rTest String\n", TRIM_ALL, "Test String", TRIM_ALL},
75 };
76
77 TEST(StringUtilTest, TrimWhitespace) {
78 std::wstring output; // Allow contents to carry over to next testcase
79 for (size_t i = 0; i < arraysize(trim_cases); ++i) {
80 const trim_case& value = trim_cases[i];
81 EXPECT_EQ(value.return_value,
82 TrimWhitespace(value.input, value.positions, &output));
83 EXPECT_EQ(value.output, output);
84 }
85
86 // Test that TrimWhitespace() can take the same string for input and output
87 output = L" This is a test \r\n";
88 EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
89 EXPECT_EQ(L"This is a test", output);
90
91 // Once more, but with a string of whitespace
92 output = L" \r\n";
93 EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
94 EXPECT_EQ(L"", output);
95
96 std::string output_ascii;
97 for (size_t i = 0; i < arraysize(trim_cases_ascii); ++i) {
98 const trim_case_ascii& value = trim_cases_ascii[i];
99 EXPECT_EQ(value.return_value,
100 TrimWhitespace(value.input, value.positions, &output_ascii));
101 EXPECT_EQ(value.output, output_ascii);
102 }
103 }
104
105 static const struct collapse_case {
106 const wchar_t* input;
107 const bool trim;
108 const wchar_t* output;
109 } collapse_cases[] = {
110 {L" Google Video ", false, L"Google Video"},
111 {L"Google Video", false, L"Google Video"},
112 {L"", false, L""},
113 {L" ", false, L""},
114 {L"\t\rTest String\n", false, L"Test String"},
115 {L"\x2002Test String\x00A0\x3000", false, L"Test String"},
116 {L" Test \n \t String ", false, L"Test String"},
117 {L"\x2002Test\x1680 \x2028 \tString\x00A0\x3000", false, L"Test String"},
118 {L" Test String", false, L"Test String"},
119 {L"Test String ", false, L"Test String"},
120 {L"Test String", false, L"Test String"},
121 {L"", true, L""},
122 {L"\n", true, L""},
123 {L" \r ", true, L""},
124 {L"\nFoo", true, L"Foo"},
125 {L"\r Foo ", true, L"Foo"},
126 {L" Foo bar ", true, L"Foo bar"},
127 {L" \tFoo bar \n", true, L"Foo bar"},
128 {L" a \r b\n c \r\n d \t\re \t f \n ", true, L"abcde f"},
129 };
130
131 TEST(StringUtilTest, CollapseWhitespace) {
132 for (size_t i = 0; i < arraysize(collapse_cases); ++i) {
133 const collapse_case& value = collapse_cases[i];
134 EXPECT_EQ(value.output, CollapseWhitespace(value.input, value.trim));
135 }
136 }
137
138 static const struct collapse_case_ascii {
139 const char* input;
140 const bool trim;
141 const char* output;
142 } collapse_cases_ascii[] = {
143 {" Google Video ", false, "Google Video"},
144 {"Google Video", false, "Google Video"},
145 {"", false, ""},
146 {" ", false, ""},
147 {"\t\rTest String\n", false, "Test String"},
148 {" Test \n \t String ", false, "Test String"},
149 {" Test String", false, "Test String"},
150 {"Test String ", false, "Test String"},
151 {"Test String", false, "Test String"},
152 {"", true, ""},
153 {"\n", true, ""},
154 {" \r ", true, ""},
155 {"\nFoo", true, "Foo"},
156 {"\r Foo ", true, "Foo"},
157 {" Foo bar ", true, "Foo bar"},
158 {" \tFoo bar \n", true, "Foo bar"},
159 {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
160 };
161
162 TEST(StringUtilTest, CollapseWhitespaceASCII) {
163 for (size_t i = 0; i < arraysize(collapse_cases_ascii); ++i) {
164 const collapse_case_ascii& value = collapse_cases_ascii[i];
165 EXPECT_EQ(value.output, CollapseWhitespaceASCII(value.input, value.trim));
166 }
167 }
168
169 TEST(StringUtilTest, IsStringUTF8) {
170 EXPECT_TRUE(IsStringUTF8("abc"));
171 EXPECT_TRUE(IsStringUTF8("\xc2\x81"));
172 EXPECT_TRUE(IsStringUTF8("\xe1\x80\xbf"));
173 EXPECT_TRUE(IsStringUTF8("\xf1\x80\xa0\xbf"));
174 EXPECT_TRUE(IsStringUTF8("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"));
175 EXPECT_TRUE(IsStringUTF8("\xef\xbb\xbf" "abc")); // UTF-8 BOM
176
177 // surrogate code points
178 EXPECT_FALSE(IsStringUTF8("\xed\xa0\x80\xed\xbf\xbf"));
179 EXPECT_FALSE(IsStringUTF8("\xed\xa0\x8f"));
180 EXPECT_FALSE(IsStringUTF8("\xed\xbf\xbf"));
181
182 // overlong sequences
183 EXPECT_FALSE(IsStringUTF8("\xc0\x80")); // U+0000
184 EXPECT_FALSE(IsStringUTF8("\xc1\x80\xc1\x81")); // "AB"
185 EXPECT_FALSE(IsStringUTF8("\xe0\x80\x80")); // U+0000
186 EXPECT_FALSE(IsStringUTF8("\xe0\x82\x80")); // U+0080
187 EXPECT_FALSE(IsStringUTF8("\xe0\x9f\xbf")); // U+07ff
188 EXPECT_FALSE(IsStringUTF8("\xf0\x80\x80\x8D")); // U+000D
189 EXPECT_FALSE(IsStringUTF8("\xf0\x80\x82\x91")); // U+0091
190 EXPECT_FALSE(IsStringUTF8("\xf0\x80\xa0\x80")); // U+0800
191 EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbb\xbf")); // U+FEFF (BOM)
192 EXPECT_FALSE(IsStringUTF8("\xf8\x80\x80\x80\xbf")); // U+003F
193 EXPECT_FALSE(IsStringUTF8("\xfc\x80\x80\x80\xa0\xa5")); // U+00A5
194
195 // Beyond U+10FFFF (the upper limit of Unicode codespace)
196 EXPECT_FALSE(IsStringUTF8("\xf4\x90\x80\x80")); // U+110000
197 EXPECT_FALSE(IsStringUTF8("\xf8\xa0\xbf\x80\xbf")); // 5 bytes
198 EXPECT_FALSE(IsStringUTF8("\xfc\x9c\xbf\x80\xbf\x80")); // 6 bytes
199
200 // BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
201 EXPECT_FALSE(IsStringUTF8("\xfe\xff"));
202 EXPECT_FALSE(IsStringUTF8("\xff\xfe"));
203 EXPECT_FALSE(IsStringUTF8(std::string("\x00\x00\xfe\xff", 4)));
204 EXPECT_FALSE(IsStringUTF8("\xff\xfe\x00\x00"));
205
206 // Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
207 EXPECT_FALSE(IsStringUTF8("\xef\xbf\xbe")); // U+FFFE)
208 EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbf\xbe")); // U+1FFFE
209 EXPECT_FALSE(IsStringUTF8("\xf3\xbf\xbf\xbf")); // U+10FFFF
210
211 // This should also be false, but currently we pass them through.
212 // Disable them for now.
213 #if 0
214 EXPECT_FALSE(IsStringUTF8("\xef\xb7\x90")); // U+FDD0
215 EXPECT_FALSE(IsStringUTF8("\xef\xb7\xaf")); // U+FDEF
216 #endif
217
218 // Strings in legacy encodings. We can certainly make up strings
219 // in a legacy encoding that are valid in UTF-8, but in real data,
220 // most of them are invalid as UTF-8.
221 EXPECT_FALSE(IsStringUTF8("caf\xe9")); // cafe with U+00E9 in ISO-8859-1
222 EXPECT_FALSE(IsStringUTF8("\xb0\xa1\xb0\xa2")); // U+AC00, U+AC001 in EUC-KR
223 EXPECT_FALSE(IsStringUTF8("\xa7\x41\xa6\x6e")); // U+4F60 U+597D in Big5
224 // "abc" with U+201[CD] in windows-125[0-8]
225 EXPECT_FALSE(IsStringUTF8("\x93" "abc\x94"));
226 // U+0639 U+064E U+0644 U+064E in ISO-8859-6
227 EXPECT_FALSE(IsStringUTF8("\xd9\xee\xe4\xee"));
228 // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
229 EXPECT_FALSE(IsStringUTF8("\xe3\xe5\xe9\xdC"));
230 }
231
232 static const wchar_t* const kConvertRoundtripCases[] = {
233 L"Google Video", 35 L"Google Video",
234 // "网页 图片 资讯更多 »" 36 // "网页 图片 资讯更多 »"
235 L"\x7f51\x9875\x0020\x56fe\x7247\x0020\x8d44\x8baf\x66f4\x591a\x0020\x00bb", 37 L"\x7f51\x9875\x0020\x56fe\x7247\x0020\x8d44\x8baf\x66f4\x591a\x0020\x00bb",
236 // "Παγκόσμιος Ιστός" 38 // "Παγκόσμιος Ιστός"
237 L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9" 39 L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
238 L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2", 40 L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2",
239 // "Поиск страниц на русском" 41 // "Поиск страниц на русском"
240 L"\x041f\x043e\x0438\x0441\x043a\x0020\x0441\x0442" 42 L"\x041f\x043e\x0438\x0441\x043a\x0020\x0441\x0442"
241 L"\x0440\x0430\x043d\x0438\x0446\x0020\x043d\x0430" 43 L"\x0440\x0430\x043d\x0438\x0446\x0020\x043d\x0430"
242 L"\x0020\x0440\x0443\x0441\x0441\x043a\x043e\x043c", 44 L"\x0020\x0440\x0443\x0441\x0441\x043a\x043e\x043c",
243 // "전체서비스" 45 // "전체서비스"
244 L"\xc804\xccb4\xc11c\xbe44\xc2a4", 46 L"\xc804\xccb4\xc11c\xbe44\xc2a4",
245 47
246 // Test characters that take more than 16 bits. This will depend on whether 48 // Test characters that take more than 16 bits. This will depend on whether
247 // wchar_t is 16 or 32 bits. 49 // wchar_t is 16 or 32 bits.
248 #if defined(WCHAR_T_IS_UTF16) 50 #if defined(WCHAR_T_IS_UTF16)
249 L"\xd800\xdf00", 51 L"\xd800\xdf00",
250 // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E) 52 // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
251 L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44", 53 L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44",
252 #elif defined(WCHAR_T_IS_UTF32) 54 #elif defined(WCHAR_T_IS_UTF32)
253 L"\x10300", 55 L"\x10300",
254 // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E) 56 // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
255 L"\x11d40\x11d41\x11d42\x11d43\x11d44", 57 L"\x11d40\x11d41\x11d42\x11d43\x11d44",
256 #endif 58 #endif
257 }; 59 };
258 60
259 TEST(StringUtilTest, ConvertUTF8AndWide) { 61 } // namespace
62
63 TEST(UTFStringConversionsTest, ConvertUTF8AndWide) {
260 // we round-trip all the wide strings through UTF-8 to make sure everything 64 // we round-trip all the wide strings through UTF-8 to make sure everything
261 // agrees on the conversion. This uses the stream operators to test them 65 // agrees on the conversion. This uses the stream operators to test them
262 // simultaneously. 66 // simultaneously.
263 for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) { 67 for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
264 std::ostringstream utf8; 68 std::ostringstream utf8;
265 utf8 << WideToUTF8(kConvertRoundtripCases[i]); 69 utf8 << WideToUTF8(kConvertRoundtripCases[i]);
266 std::wostringstream wide; 70 std::wostringstream wide;
267 wide << UTF8ToWide(utf8.str()); 71 wide << UTF8ToWide(utf8.str());
268 72
269 EXPECT_EQ(kConvertRoundtripCases[i], wide.str()); 73 EXPECT_EQ(kConvertRoundtripCases[i], wide.str());
270 } 74 }
271 } 75 }
272 76
273 TEST(StringUtilTest, ConvertUTF8AndWideEmptyString) { 77 TEST(UTFStringConversionsTest, ConvertUTF8AndWideEmptyString) {
274 // An empty std::wstring should be converted to an empty std::string, 78 // An empty std::wstring should be converted to an empty std::string,
275 // and vice versa. 79 // and vice versa.
276 std::wstring wempty; 80 std::wstring wempty;
277 std::string empty; 81 std::string empty;
278 EXPECT_EQ(empty, WideToUTF8(wempty)); 82 EXPECT_EQ(empty, WideToUTF8(wempty));
279 EXPECT_EQ(wempty, UTF8ToWide(empty)); 83 EXPECT_EQ(wempty, UTF8ToWide(empty));
280 } 84 }
281 85
282 TEST(StringUtilTest, ConvertUTF8ToWide) { 86 TEST(UTFStringConversionsTest, ConvertUTF8ToWide) {
283 struct UTF8ToWideCase { 87 struct UTF8ToWideCase {
284 const char* utf8; 88 const char* utf8;
285 const wchar_t* wide; 89 const wchar_t* wide;
286 bool success; 90 bool success;
287 } convert_cases[] = { 91 } convert_cases[] = {
288 // Regular UTF-8 input. 92 // Regular UTF-8 input.
289 {"\xe4\xbd\xa0\xe5\xa5\xbd", L"\x4f60\x597d", true}, 93 {"\xe4\xbd\xa0\xe5\xa5\xbd", L"\x4f60\x597d", true},
290 // Non-character is passed through. 94 // Non-character is passed through.
291 {"\xef\xbf\xbfHello", L"\xffffHello", true}, 95 {"\xef\xbf\xbfHello", L"\xffffHello", true},
292 // Truncated UTF-8 sequence. 96 // Truncated UTF-8 sequence.
(...skipping 22 matching lines...) Expand all
315 strlen(convert_cases[i].utf8), 119 strlen(convert_cases[i].utf8),
316 &converted)); 120 &converted));
317 std::wstring expected(convert_cases[i].wide); 121 std::wstring expected(convert_cases[i].wide);
318 EXPECT_EQ(expected, converted); 122 EXPECT_EQ(expected, converted);
319 } 123 }
320 124
321 // Manually test an embedded NULL. 125 // Manually test an embedded NULL.
322 std::wstring converted; 126 std::wstring converted;
323 EXPECT_TRUE(UTF8ToWide("\00Z\t", 3, &converted)); 127 EXPECT_TRUE(UTF8ToWide("\00Z\t", 3, &converted));
324 ASSERT_EQ(3U, converted.length()); 128 ASSERT_EQ(3U, converted.length());
325 #if defined(WCHAR_T_IS_UNSIGNED) 129 EXPECT_EQ(static_cast<wchar_t>(0), converted[0]);
326 EXPECT_EQ(0U, converted[0]);
327 #else
328 EXPECT_EQ(0, converted[0]);
329 #endif
330 EXPECT_EQ('Z', converted[1]); 130 EXPECT_EQ('Z', converted[1]);
331 EXPECT_EQ('\t', converted[2]); 131 EXPECT_EQ('\t', converted[2]);
332 132
333 // Make sure that conversion replaces, not appends. 133 // Make sure that conversion replaces, not appends.
334 EXPECT_TRUE(UTF8ToWide("B", 1, &converted)); 134 EXPECT_TRUE(UTF8ToWide("B", 1, &converted));
335 ASSERT_EQ(1U, converted.length()); 135 ASSERT_EQ(1U, converted.length());
336 EXPECT_EQ('B', converted[0]); 136 EXPECT_EQ('B', converted[0]);
337 } 137 }
338 138
339 #if defined(WCHAR_T_IS_UTF16) 139 #if defined(WCHAR_T_IS_UTF16)
340 // This test is only valid when wchar_t == UTF-16. 140 // This test is only valid when wchar_t == UTF-16.
341 TEST(StringUtilTest, ConvertUTF16ToUTF8) { 141 TEST(UTFStringConversionsTest, ConvertUTF16ToUTF8) {
342 struct UTF16ToUTF8Case { 142 struct WideToUTF8Case {
343 const wchar_t* utf16; 143 const wchar_t* utf16;
344 const char* utf8; 144 const char* utf8;
345 bool success; 145 bool success;
346 } convert_cases[] = { 146 } convert_cases[] = {
347 // Regular UTF-16 input. 147 // Regular UTF-16 input.
348 {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true}, 148 {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true},
349 // Test a non-BMP character. 149 // Test a non-BMP character.
350 {L"\xd800\xdf00", "\xF0\x90\x8C\x80", true}, 150 {L"\xd800\xdf00", "\xF0\x90\x8C\x80", true},
351 // Non-characters are passed through. 151 // Non-characters are passed through.
352 {L"\xffffHello", "\xEF\xBF\xBFHello", true}, 152 {L"\xffffHello", "\xEF\xBF\xBFHello", true},
(...skipping 10 matching lines...) Expand all
363 WideToUTF8(convert_cases[i].utf16, 163 WideToUTF8(convert_cases[i].utf16,
364 wcslen(convert_cases[i].utf16), 164 wcslen(convert_cases[i].utf16),
365 &converted)); 165 &converted));
366 std::string expected(convert_cases[i].utf8); 166 std::string expected(convert_cases[i].utf8);
367 EXPECT_EQ(expected, converted); 167 EXPECT_EQ(expected, converted);
368 } 168 }
369 } 169 }
370 170
371 #elif defined(WCHAR_T_IS_UTF32) 171 #elif defined(WCHAR_T_IS_UTF32)
372 // This test is only valid when wchar_t == UTF-32. 172 // This test is only valid when wchar_t == UTF-32.
373 TEST(StringUtilTest, ConvertUTF32ToUTF8) { 173 TEST(UTFStringConversionsTest, ConvertUTF32ToUTF8) {
374 struct WideToUTF8Case { 174 struct WideToUTF8Case {
375 const wchar_t* utf32; 175 const wchar_t* utf32;
376 const char* utf8; 176 const char* utf8;
377 bool success; 177 bool success;
378 } convert_cases[] = { 178 } convert_cases[] = {
379 // Regular 16-bit input. 179 // Regular 16-bit input.
380 {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true}, 180 {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true},
381 // Test a non-BMP character. 181 // Test a non-BMP character.
382 {L"A\x10300z", "A\xF0\x90\x8C\x80z", true}, 182 {L"A\x10300z", "A\xF0\x90\x8C\x80z", true},
383 // Non-characters are passed through. 183 // Non-characters are passed through.
(...skipping 11 matching lines...) Expand all
395 EXPECT_EQ(convert_cases[i].success, 195 EXPECT_EQ(convert_cases[i].success,
396 WideToUTF8(convert_cases[i].utf32, 196 WideToUTF8(convert_cases[i].utf32,
397 wcslen(convert_cases[i].utf32), 197 wcslen(convert_cases[i].utf32),
398 &converted)); 198 &converted));
399 std::string expected(convert_cases[i].utf8); 199 std::string expected(convert_cases[i].utf8);
400 EXPECT_EQ(expected, converted); 200 EXPECT_EQ(expected, converted);
401 } 201 }
402 } 202 }
403 #endif // defined(WCHAR_T_IS_UTF32) 203 #endif // defined(WCHAR_T_IS_UTF32)
404 204
405 TEST(StringUtilTest, ConvertMultiString) { 205 TEST(UTFStringConversionsTest, ConvertMultiString) {
406 static wchar_t wmulti[] = { 206 static wchar_t wmulti[] = {
407 L'f', L'o', L'o', L'\0', 207 L'f', L'o', L'o', L'\0',
408 L'b', L'a', L'r', L'\0', 208 L'b', L'a', L'r', L'\0',
409 L'b', L'a', L'z', L'\0', 209 L'b', L'a', L'z', L'\0',
410 L'\0' 210 L'\0'
411 }; 211 };
412 static char multi[] = { 212 static char multi[] = {
413 'f', 'o', 'o', '\0', 213 'f', 'o', 'o', '\0',
414 'b', 'a', 'r', '\0', 214 'b', 'a', 'r', '\0',
415 'b', 'a', 'z', '\0', 215 'b', 'a', 'z', '\0',
416 '\0' 216 '\0'
417 }; 217 };
418 std::wstring wmultistring; 218 std::wstring wmultistring;
419 memcpy(WriteInto(&wmultistring, arraysize(wmulti)), wmulti, sizeof(wmulti)); 219 memcpy(WriteInto(&wmultistring, arraysize(wmulti)), wmulti, sizeof(wmulti));
420 EXPECT_EQ(arraysize(wmulti) - 1, wmultistring.length()); 220 EXPECT_EQ(arraysize(wmulti) - 1, wmultistring.length());
421 std::string expected; 221 std::string expected;
422 memcpy(WriteInto(&expected, arraysize(multi)), multi, sizeof(multi)); 222 memcpy(WriteInto(&expected, arraysize(multi)), multi, sizeof(multi));
423 EXPECT_EQ(arraysize(multi) - 1, expected.length()); 223 EXPECT_EQ(arraysize(multi) - 1, expected.length());
424 const std::string& converted = WideToUTF8(wmultistring); 224 const std::string& converted = WideToUTF8(wmultistring);
425 EXPECT_EQ(arraysize(multi) - 1, converted.length()); 225 EXPECT_EQ(arraysize(multi) - 1, converted.length());
426 EXPECT_EQ(expected, converted); 226 EXPECT_EQ(expected, converted);
427 } 227 }
428 228
429 TEST(StringUtilTest, ConvertASCII) { 229 TEST(UTFStringConversionsTest, AdjustOffset) {
430 static const char* char_cases[] = { 230 // Under the hood, all the functions call the same converter function, so we
431 "Google Video", 231 // don't need to exhaustively check every case.
432 "Hello, world\n", 232 struct WideToUTF8Case {
433 "0123ABCDwxyz \a\b\t\r\n!+,.~" 233 const wchar_t* wide;
234 size_t input_offset;
235 size_t output_offset;
236 } wide_to_utf8_cases[] = {
237 {L"", 0, std::string::npos},
238 {L"\x4f60\x597d", 0, 0},
239 {L"\x4f60\x597d", 1, 3},
240 {L"\x4f60\x597d", 2, std::string::npos},
241 {L"\x4f60\x597d", std::wstring::npos, std::string::npos},
242 {L"\xd800\x597dz", 1, 0},
243 {L"\xd800\x597dz", 2, 3},
434 }; 244 };
435 245 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(wide_to_utf8_cases); ++i) {
436 static const wchar_t* const wchar_cases[] = { 246 size_t offset = wide_to_utf8_cases[i].input_offset;
437 L"Google Video", 247 WideToUTF8AndAdjustOffset(wide_to_utf8_cases[i].wide, &offset);
438 L"Hello, world\n", 248 EXPECT_EQ(wide_to_utf8_cases[i].output_offset, offset);
439 L"0123ABCDwxyz \a\b\t\r\n!+,.~"
440 };
441
442 for (size_t i = 0; i < arraysize(char_cases); ++i) {
443 EXPECT_TRUE(IsStringASCII(char_cases[i]));
444 std::wstring wide = ASCIIToWide(char_cases[i]);
445 EXPECT_EQ(wchar_cases[i], wide);
446
447 EXPECT_TRUE(IsStringASCII(wchar_cases[i]));
448 std::string ascii = WideToASCII(wchar_cases[i]);
449 EXPECT_EQ(char_cases[i], ascii);
450 } 249 }
451 250
452 EXPECT_FALSE(IsStringASCII("Google \x80Video")); 251 struct UTF8ToWideCase {
453 EXPECT_FALSE(IsStringASCII(L"Google \x80Video")); 252 const char* utf8;
454 253 size_t input_offset;
455 // Convert empty strings. 254 size_t output_offset;
456 std::wstring wempty; 255 } utf8_to_wide_cases[] = {
457 std::string empty; 256 {"\xe4\xbd\xa0\xe5\xa5\xbd", 1, std::wstring::npos},
458 EXPECT_EQ(empty, WideToASCII(wempty)); 257 {"\xe4\xbd\xa0\xe5\xa5\xbd", 3, 1},
459 EXPECT_EQ(wempty, ASCIIToWide(empty)); 258 {"\xed\xb0\x80z", 3, 0},
460 259 {"A\xF0\x90\x8C\x80z", 1, 1},
461 // Convert strings with an embedded NUL character. 260 {"A\xF0\x90\x8C\x80z", 2, std::wstring::npos},
462 const char chars_with_nul[] = "test\0string"; 261 #if defined(WCHAR_T_IS_UTF16)
463 const int length_with_nul = arraysize(chars_with_nul) - 1; 262 {"A\xF0\x90\x8C\x80z", 5, 3},
464 std::string string_with_nul(chars_with_nul, length_with_nul); 263 #elif defined(WCHAR_T_IS_UTF32)
465 std::wstring wide_with_nul = ASCIIToWide(string_with_nul); 264 {"A\xF0\x90\x8C\x80z", 5, 2},
466 EXPECT_EQ(static_cast<std::wstring::size_type>(length_with_nul),
467 wide_with_nul.length());
468 std::string narrow_with_nul = WideToASCII(wide_with_nul);
469 EXPECT_EQ(static_cast<std::string::size_type>(length_with_nul),
470 narrow_with_nul.length());
471 EXPECT_EQ(0, string_with_nul.compare(narrow_with_nul));
472 }
473
474 TEST(StringUtilTest, ToUpperASCII) {
475 EXPECT_EQ('C', ToUpperASCII('C'));
476 EXPECT_EQ('C', ToUpperASCII('c'));
477 EXPECT_EQ('2', ToUpperASCII('2'));
478
479 EXPECT_EQ(L'C', ToUpperASCII(L'C'));
480 EXPECT_EQ(L'C', ToUpperASCII(L'c'));
481 EXPECT_EQ(L'2', ToUpperASCII(L'2'));
482
483 std::string in_place_a("Cc2");
484 StringToUpperASCII(&in_place_a);
485 EXPECT_EQ("CC2", in_place_a);
486
487 std::wstring in_place_w(L"Cc2");
488 StringToUpperASCII(&in_place_w);
489 EXPECT_EQ(L"CC2", in_place_w);
490
491 std::string original_a("Cc2");
492 std::string upper_a = StringToUpperASCII(original_a);
493 EXPECT_EQ("CC2", upper_a);
494
495 std::wstring original_w(L"Cc2");
496 std::wstring upper_w = StringToUpperASCII(original_w);
497 EXPECT_EQ(L"CC2", upper_w);
498 }
499
500 static const struct {
501 const wchar_t* src_w;
502 const char* src_a;
503 const char* dst;
504 } lowercase_cases[] = {
505 {L"FoO", "FoO", "foo"},
506 {L"foo", "foo", "foo"},
507 {L"FOO", "FOO", "foo"},
508 };
509
510 TEST(StringUtilTest, LowerCaseEqualsASCII) {
511 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(lowercase_cases); ++i) {
512 EXPECT_TRUE(LowerCaseEqualsASCII(lowercase_cases[i].src_w,
513 lowercase_cases[i].dst));
514 EXPECT_TRUE(LowerCaseEqualsASCII(lowercase_cases[i].src_a,
515 lowercase_cases[i].dst));
516 }
517 }
518
519 TEST(StringUtilTest, GetByteDisplayUnits) {
520 static const struct {
521 int64 bytes;
522 DataUnits expected;
523 } cases[] = {
524 {0, DATA_UNITS_BYTE},
525 {512, DATA_UNITS_BYTE},
526 {10*1024, DATA_UNITS_KILOBYTE},
527 {10*1024*1024, DATA_UNITS_MEGABYTE},
528 {10LL*1024*1024*1024, DATA_UNITS_GIGABYTE},
529 {~(1LL<<63), DATA_UNITS_GIGABYTE},
530 #ifdef NDEBUG
531 {-1, DATA_UNITS_BYTE},
532 #endif 265 #endif
533 }; 266 };
534 267 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(utf8_to_wide_cases); ++i) {
535 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) 268 size_t offset = utf8_to_wide_cases[i].input_offset;
536 EXPECT_EQ(cases[i].expected, GetByteDisplayUnits(cases[i].bytes)); 269 UTF8ToWideAndAdjustOffset(utf8_to_wide_cases[i].utf8, &offset);
537 } 270 EXPECT_EQ(utf8_to_wide_cases[i].output_offset, offset);
538
539 TEST(StringUtilTest, FormatBytes) {
540 static const struct {
541 int64 bytes;
542 DataUnits units;
543 const wchar_t* expected;
544 const wchar_t* expected_with_units;
545 } cases[] = {
546 {0, DATA_UNITS_BYTE, L"0", L"0 B"},
547 {512, DATA_UNITS_BYTE, L"512", L"512 B"},
548 {512, DATA_UNITS_KILOBYTE, L"0.5", L"0.5 kB"},
549 {1024*1024, DATA_UNITS_KILOBYTE, L"1024", L"1024 kB"},
550 {1024*1024, DATA_UNITS_MEGABYTE, L"1", L"1 MB"},
551 {1024*1024*1024, DATA_UNITS_GIGABYTE, L"1", L"1 GB"},
552 {10LL*1024*1024*1024, DATA_UNITS_GIGABYTE, L"10", L"10 GB"},
553 {~(1LL<<63), DATA_UNITS_GIGABYTE, L"8589934592", L"8589934592 GB"},
554 // Make sure the first digit of the fractional part works.
555 {1024*1024 + 103, DATA_UNITS_KILOBYTE, L"1024.1", L"1024.1 kB"},
556 {1024*1024 + 205 * 1024, DATA_UNITS_MEGABYTE, L"1.2", L"1.2 MB"},
557 {1024*1024*1024 + (927 * 1024*1024), DATA_UNITS_GIGABYTE,
558 L"1.9", L"1.9 GB"},
559 {10LL*1024*1024*1024, DATA_UNITS_GIGABYTE, L"10", L"10 GB"},
560 #ifdef NDEBUG
561 {-1, DATA_UNITS_BYTE, L"", L""},
562 #endif
563 };
564
565 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
566 EXPECT_EQ(cases[i].expected,
567 FormatBytes(cases[i].bytes, cases[i].units, false));
568 EXPECT_EQ(cases[i].expected_with_units,
569 FormatBytes(cases[i].bytes, cases[i].units, true));
570 }
571 }
572
573 TEST(StringUtilTest, ReplaceSubstringsAfterOffset) {
574 static const struct {
575 const char* str;
576 string16::size_type start_offset;
577 const char* find_this;
578 const char* replace_with;
579 const char* expected;
580 } cases[] = {
581 {"aaa", 0, "a", "b", "bbb"},
582 {"abb", 0, "ab", "a", "ab"},
583 {"Removing some substrings inging", 0, "ing", "", "Remov some substrs "},
584 {"Not found", 0, "x", "0", "Not found"},
585 {"Not found again", 5, "x", "0", "Not found again"},
586 {" Making it much longer ", 0, " ", "Four score and seven years ago",
587 "Four score and seven years agoMakingFour score and seven years agoit"
588 "Four score and seven years agomuchFour score and seven years agolonger"
589 "Four score and seven years ago"},
590 {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
591 {"Replace me only me once", 9, "me ", "", "Replace me only once"},
592 {"abababab", 2, "ab", "c", "abccc"},
593 };
594
595 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
596 string16 str = ASCIIToUTF16(cases[i].str);
597 ReplaceSubstringsAfterOffset(&str, cases[i].start_offset,
598 ASCIIToUTF16(cases[i].find_this),
599 ASCIIToUTF16(cases[i].replace_with));
600 EXPECT_EQ(ASCIIToUTF16(cases[i].expected), str);
601 }
602 }
603
604 TEST(StringUtilTest, ReplaceFirstSubstringAfterOffset) {
605 static const struct {
606 const char* str;
607 string16::size_type start_offset;
608 const char* find_this;
609 const char* replace_with;
610 const char* expected;
611 } cases[] = {
612 {"aaa", 0, "a", "b", "baa"},
613 {"abb", 0, "ab", "a", "ab"},
614 {"Removing some substrings inging", 0, "ing", "",
615 "Remov some substrings inging"},
616 {"Not found", 0, "x", "0", "Not found"},
617 {"Not found again", 5, "x", "0", "Not found again"},
618 {" Making it much longer ", 0, " ", "Four score and seven years ago",
619 "Four score and seven years agoMaking it much longer "},
620 {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
621 {"Replace me only me once", 4, "me ", "", "Replace only me once"},
622 {"abababab", 2, "ab", "c", "abcabab"},
623 };
624
625 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
626 string16 str = ASCIIToUTF16(cases[i].str);
627 ReplaceFirstSubstringAfterOffset(&str, cases[i].start_offset,
628 ASCIIToUTF16(cases[i].find_this),
629 ASCIIToUTF16(cases[i].replace_with));
630 EXPECT_EQ(ASCIIToUTF16(cases[i].expected), str);
631 }
632 }
633
634 namespace {
635
636 template <typename INT>
637 struct IntToStringTest {
638 INT num;
639 const char* sexpected;
640 const char* uexpected;
641 };
642
643 }
644
645 TEST(StringUtilTest, IntToString) {
646
647 static const IntToStringTest<int> int_tests[] = {
648 { 0, "0", "0" },
649 { -1, "-1", "4294967295" },
650 { std::numeric_limits<int>::max(), "2147483647", "2147483647" },
651 { std::numeric_limits<int>::min(), "-2147483648", "2147483648" },
652 };
653 static const IntToStringTest<int64> int64_tests[] = {
654 { 0, "0", "0" },
655 { -1, "-1", "18446744073709551615" },
656 { std::numeric_limits<int64>::max(),
657 "9223372036854775807",
658 "9223372036854775807", },
659 { std::numeric_limits<int64>::min(),
660 "-9223372036854775808",
661 "9223372036854775808" },
662 };
663
664 for (size_t i = 0; i < arraysize(int_tests); ++i) {
665 const IntToStringTest<int>* test = &int_tests[i];
666 EXPECT_EQ(IntToString(test->num), test->sexpected);
667 EXPECT_EQ(IntToWString(test->num), UTF8ToWide(test->sexpected));
668 EXPECT_EQ(UintToString(test->num), test->uexpected);
669 EXPECT_EQ(UintToWString(test->num), UTF8ToWide(test->uexpected));
670 }
671 for (size_t i = 0; i < arraysize(int64_tests); ++i) {
672 const IntToStringTest<int64>* test = &int64_tests[i];
673 EXPECT_EQ(Int64ToString(test->num), test->sexpected);
674 EXPECT_EQ(Int64ToWString(test->num), UTF8ToWide(test->sexpected));
675 EXPECT_EQ(Uint64ToString(test->num), test->uexpected);
676 EXPECT_EQ(Uint64ToWString(test->num), UTF8ToWide(test->uexpected));
677 }
678 }
679
680 TEST(StringUtilTest, Uint64ToString) {
681 static const struct {
682 uint64 input;
683 std::string output;
684 } cases[] = {
685 {0, "0"},
686 {42, "42"},
687 {INT_MAX, "2147483647"},
688 {kuint64max, "18446744073709551615"},
689 };
690
691 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i)
692 EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
693 }
694
695 TEST(StringUtilTest, StringToInt) {
696 static const struct {
697 std::string input;
698 int output;
699 bool success;
700 } cases[] = {
701 {"0", 0, true},
702 {"42", 42, true},
703 {"-2147483648", INT_MIN, true},
704 {"2147483647", INT_MAX, true},
705 {"", 0, false},
706 {" 42", 42, false},
707 {"42 ", 42, false},
708 {"\t\n\v\f\r 42", 42, false},
709 {"blah42", 0, false},
710 {"42blah", 42, false},
711 {"blah42blah", 0, false},
712 {"-273.15", -273, false},
713 {"+98.6", 98, false},
714 {"--123", 0, false},
715 {"++123", 0, false},
716 {"-+123", 0, false},
717 {"+-123", 0, false},
718 {"-", 0, false},
719 {"-2147483649", INT_MIN, false},
720 {"-99999999999", INT_MIN, false},
721 {"2147483648", INT_MAX, false},
722 {"99999999999", INT_MAX, false},
723 };
724
725 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
726 EXPECT_EQ(cases[i].output, StringToInt(cases[i].input));
727 int output;
728 EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
729 EXPECT_EQ(cases[i].output, output);
730
731 std::wstring wide_input = ASCIIToWide(cases[i].input);
732 EXPECT_EQ(cases[i].output, StringToInt(WideToUTF16Hack(wide_input)));
733 EXPECT_EQ(cases[i].success, StringToInt(WideToUTF16Hack(wide_input),
734 &output));
735 EXPECT_EQ(cases[i].output, output);
736 } 271 }
737 272
738 // One additional test to verify that conversion of numbers in strings with 273 #if defined(WCHAR_T_IS_UTF32)
739 // embedded NUL characters. The NUL and extra data after it should be 274 struct WideToUTF16Case {
740 // interpreted as junk after the number. 275 const wchar_t* wide;
741 const char input[] = "6\06"; 276 size_t input_offset;
742 std::string input_string(input, arraysize(input) - 1); 277 size_t output_offset;
743 int output; 278 } wide_to_utf16_cases[] = {
744 EXPECT_FALSE(StringToInt(input_string, &output)); 279 {L"\x4F60\x597D", 1, 1},
745 EXPECT_EQ(6, output); 280 {L"\x20000\x4E00", 1, 2},
746
747 std::wstring wide_input = ASCIIToWide(input_string);
748 EXPECT_FALSE(StringToInt(WideToUTF16Hack(wide_input), &output));
749 EXPECT_EQ(6, output);
750 }
751
752 TEST(StringUtilTest, StringToInt64) {
753 static const struct {
754 std::string input;
755 int64 output;
756 bool success;
757 } cases[] = {
758 {"0", 0, true},
759 {"42", 42, true},
760 {"-2147483648", INT_MIN, true},
761 {"2147483647", INT_MAX, true},
762 {"-2147483649", GG_INT64_C(-2147483649), true},
763 {"-99999999999", GG_INT64_C(-99999999999), true},
764 {"2147483648", GG_INT64_C(2147483648), true},
765 {"99999999999", GG_INT64_C(99999999999), true},
766 {"9223372036854775807", kint64max, true},
767 {"-9223372036854775808", kint64min, true},
768 {"09", 9, true},
769 {"-09", -9, true},
770 {"", 0, false},
771 {" 42", 42, false},
772 {"42 ", 42, false},
773 {"\t\n\v\f\r 42", 42, false},
774 {"blah42", 0, false},
775 {"42blah", 42, false},
776 {"blah42blah", 0, false},
777 {"-273.15", -273, false},
778 {"+98.6", 98, false},
779 {"--123", 0, false},
780 {"++123", 0, false},
781 {"-+123", 0, false},
782 {"+-123", 0, false},
783 {"-", 0, false},
784 {"-9223372036854775809", kint64min, false},
785 {"-99999999999999999999", kint64min, false},
786 {"9223372036854775808", kint64max, false},
787 {"99999999999999999999", kint64max, false},
788 }; 281 };
789 282 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(wide_to_utf16_cases); ++i) {
790 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { 283 size_t offset = wide_to_utf16_cases[i].input_offset;
791 EXPECT_EQ(cases[i].output, StringToInt64(cases[i].input)); 284 WideToUTF16AndAdjustOffset(wide_to_utf16_cases[i].wide, &offset);
792 int64 output; 285 EXPECT_EQ(wide_to_utf16_cases[i].output_offset, offset);
793 EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output));
794 EXPECT_EQ(cases[i].output, output);
795
796 std::wstring wide_input = ASCIIToWide(cases[i].input);
797 EXPECT_EQ(cases[i].output, StringToInt64(WideToUTF16Hack(wide_input)));
798 EXPECT_EQ(cases[i].success, StringToInt64(WideToUTF16Hack(wide_input),
799 &output));
800 EXPECT_EQ(cases[i].output, output);
801 } 286 }
802 287
803 // One additional test to verify that conversion of numbers in strings with 288 struct UTF16ToWideCase {
804 // embedded NUL characters. The NUL and extra data after it should be 289 const wchar_t* wide;
805 // interpreted as junk after the number. 290 size_t input_offset;
806 const char input[] = "6\06"; 291 size_t output_offset;
807 std::string input_string(input, arraysize(input) - 1); 292 } utf16_to_wide_cases[] = {
808 int64 output; 293 {L"\xD840\xDC00\x4E00", 0, 0},
809 EXPECT_FALSE(StringToInt64(input_string, &output)); 294 {L"\xD840\xDC00\x4E00", 1, std::wstring::npos},
810 EXPECT_EQ(6, output); 295 {L"\xD840\xDC00\x4E00", 2, 1},
811
812 std::wstring wide_input = ASCIIToWide(input_string);
813 EXPECT_FALSE(StringToInt64(WideToUTF16Hack(wide_input), &output));
814 EXPECT_EQ(6, output);
815 }
816
817 TEST(StringUtilTest, HexStringToInt) {
818 static const struct {
819 std::string input;
820 int output;
821 bool success;
822 } cases[] = {
823 {"0", 0, true},
824 {"42", 66, true},
825 {"-42", -66, true},
826 {"+42", 66, true},
827 {"7fffffff", INT_MAX, true},
828 {"80000000", INT_MIN, true},
829 {"ffffffff", -1, true},
830 {"DeadBeef", 0xdeadbeef, true},
831 {"0x42", 66, true},
832 {"-0x42", -66, true},
833 {"+0x42", 66, true},
834 {"0x7fffffff", INT_MAX, true},
835 {"0x80000000", INT_MIN, true},
836 {"0xffffffff", -1, true},
837 {"0XDeadBeef", 0xdeadbeef, true},
838 {"0x0f", 15, true},
839 {"0f", 15, true},
840 {" 45", 0x45, false},
841 {"\t\n\v\f\r 0x45", 0x45, false},
842 {" 45", 0x45, false},
843 {"45 ", 0x45, false},
844 {"efgh", 0xef, false},
845 {"0xefgh", 0xef, false},
846 {"hgfe", 0, false},
847 {"100000000", -1, false}, // don't care about |output|, just |success|
848 {"-", 0, false},
849 {"", 0, false},
850 }; 296 };
851 297 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(utf16_to_wide_cases); ++i) {
852 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { 298 size_t offset = utf16_to_wide_cases[i].input_offset;
853 EXPECT_EQ(cases[i].output, HexStringToInt(cases[i].input)); 299 UTF16ToWideAndAdjustOffset(BuildString16(utf16_to_wide_cases[i].wide),
854 int output; 300 &offset);
855 EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output)); 301 EXPECT_EQ(utf16_to_wide_cases[i].output_offset, offset);
856 EXPECT_EQ(cases[i].output, output);
857
858 std::wstring wide_input = ASCIIToWide(cases[i].input);
859 EXPECT_EQ(cases[i].output, HexStringToInt(WideToUTF16Hack(wide_input)));
860 EXPECT_EQ(cases[i].success, HexStringToInt(WideToUTF16Hack(wide_input),
861 &output));
862 EXPECT_EQ(cases[i].output, output);
863 } 302 }
864 // One additional test to verify that conversion of numbers in strings with
865 // embedded NUL characters. The NUL and extra data after it should be
866 // interpreted as junk after the number.
867 const char input[] = "0xc0ffee\09";
868 std::string input_string(input, arraysize(input) - 1);
869 int output;
870 EXPECT_FALSE(HexStringToInt(input_string, &output));
871 EXPECT_EQ(0xc0ffee, output);
872
873 std::wstring wide_input = ASCIIToWide(input_string);
874 EXPECT_FALSE(HexStringToInt(WideToUTF16Hack(wide_input), &output));
875 EXPECT_EQ(0xc0ffee, output);
876 }
877
878 TEST(StringUtilTest, HexStringToBytes) {
879 static const struct {
880 const std::string input;
881 const char* output;
882 size_t output_len;
883 bool success;
884 } cases[] = {
885 {"0", "", 0, false}, // odd number of characters fails
886 {"00", "\0", 1, true},
887 {"42", "\x42", 1, true},
888 {"-42", "", 0, false}, // any non-hex value fails
889 {"+42", "", 0, false},
890 {"7fffffff", "\x7f\xff\xff\xff", 4, true},
891 {"80000000", "\x80\0\0\0", 4, true},
892 {"deadbeef", "\xde\xad\xbe\xef", 4, true},
893 {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
894 {"0x42", "", 0, false}, // leading 0x fails (x is not hex)
895 {"0f", "\xf", 1, true},
896 {"45 ", "\x45", 1, false},
897 {"efgh", "\xef", 1, false},
898 {"", "", 0, false},
899 {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
900 {"0123456789ABCDEF012345",
901 "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true},
902 };
903
904
905 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
906 std::vector<uint8> output;
907 std::vector<uint8> compare;
908 EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) <<
909 i << ": " << cases[i].input;
910 for (size_t j = 0; j < cases[i].output_len; ++j)
911 compare.push_back(static_cast<uint8>(cases[i].output[j]));
912 ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
913 EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
914 i << ": " << cases[i].input;
915
916 output.clear();
917 compare.clear();
918
919 std::wstring wide_input = ASCIIToWide(cases[i].input);
920 EXPECT_EQ(cases[i].success,
921 HexStringToBytes(WideToUTF16Hack(wide_input), &output)) <<
922 i << ": " << cases[i].input;
923 for (size_t j = 0; j < cases[i].output_len; ++j)
924 compare.push_back(static_cast<uint8>(cases[i].output[j]));
925 ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
926 EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
927 i << ": " << cases[i].input;
928 }
929 }
930
931 TEST(StringUtilTest, StringToDouble) {
932 static const struct {
933 std::string input;
934 double output;
935 bool success;
936 } cases[] = {
937 {"0", 0.0, true},
938 {"42", 42.0, true},
939 {"-42", -42.0, true},
940 {"123.45", 123.45, true},
941 {"-123.45", -123.45, true},
942 {"+123.45", 123.45, true},
943 {"2.99792458e8", 299792458.0, true},
944 {"149597870.691E+3", 149597870691.0, true},
945 {"6.", 6.0, true},
946 {"9e99999999999999999999", HUGE_VAL, false},
947 {"-9e99999999999999999999", -HUGE_VAL, false},
948 {"1e-2", 0.01, true},
949 {" 1e-2", 0.01, false},
950 {"1e-2 ", 0.01, false},
951 {"-1E-7", -0.0000001, true},
952 {"01e02", 100, true},
953 {"2.3e15", 2.3e15, true},
954 {"\t\n\v\f\r -123.45e2", -12345.0, false},
955 {"+123 e4", 123.0, false},
956 {"123e ", 123.0, false},
957 {"123e", 123.0, false},
958 {" 2.99", 2.99, false},
959 {"1e3.4", 1000.0, false},
960 {"nothing", 0.0, false},
961 {"-", 0.0, false},
962 {"+", 0.0, false},
963 {"", 0.0, false},
964 };
965
966 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
967 EXPECT_DOUBLE_EQ(cases[i].output, StringToDouble(cases[i].input));
968 double output;
969 EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output));
970 EXPECT_DOUBLE_EQ(cases[i].output, output);
971
972 std::wstring wide_input = ASCIIToWide(cases[i].input);
973 EXPECT_DOUBLE_EQ(cases[i].output,
974 StringToDouble(WideToUTF16Hack(wide_input)));
975 EXPECT_EQ(cases[i].success, StringToDouble(WideToUTF16Hack(wide_input),
976 &output));
977 EXPECT_DOUBLE_EQ(cases[i].output, output);
978 }
979
980 // One additional test to verify that conversion of numbers in strings with
981 // embedded NUL characters. The NUL and extra data after it should be
982 // interpreted as junk after the number.
983 const char input[] = "3.14\0159";
984 std::string input_string(input, arraysize(input) - 1);
985 double output;
986 EXPECT_FALSE(StringToDouble(input_string, &output));
987 EXPECT_DOUBLE_EQ(3.14, output);
988
989 std::wstring wide_input = ASCIIToWide(input_string);
990 EXPECT_FALSE(StringToDouble(WideToUTF16Hack(wide_input), &output));
991 EXPECT_DOUBLE_EQ(3.14, output);
992 }
993
994 // This checks where we can use the assignment operator for a va_list. We need
995 // a way to do this since Visual C doesn't support va_copy, but assignment on
996 // va_list is not guaranteed to be a copy. See StringAppendVT which uses this
997 // capability.
998 static void VariableArgsFunc(const char* format, ...) {
999 va_list org;
1000 va_start(org, format);
1001
1002 va_list dup;
1003 GG_VA_COPY(dup, org);
1004 int i1 = va_arg(org, int);
1005 int j1 = va_arg(org, int);
1006 char* s1 = va_arg(org, char*);
1007 double d1 = va_arg(org, double);
1008 va_end(org);
1009
1010 int i2 = va_arg(dup, int);
1011 int j2 = va_arg(dup, int);
1012 char* s2 = va_arg(dup, char*);
1013 double d2 = va_arg(dup, double);
1014
1015 EXPECT_EQ(i1, i2);
1016 EXPECT_EQ(j1, j2);
1017 EXPECT_STREQ(s1, s2);
1018 EXPECT_EQ(d1, d2);
1019
1020 va_end(dup);
1021 }
1022
1023 TEST(StringUtilTest, VAList) {
1024 VariableArgsFunc("%d %d %s %lf", 45, 92, "This is interesting", 9.21);
1025 }
1026
1027 TEST(StringUtilTest, StringPrintfEmptyFormat) {
1028 const char* empty = "";
1029 EXPECT_EQ("", StringPrintf(empty));
1030 EXPECT_EQ("", StringPrintf("%s", ""));
1031 }
1032
1033 TEST(StringUtilTest, StringPrintfMisc) {
1034 EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w'));
1035 EXPECT_EQ(L"123hello w", StringPrintf(L"%3d%2ls %1lc", 123, L"hello", 'w'));
1036 }
1037
1038 TEST(StringUtilTest, StringAppendfStringEmptyParam) {
1039 std::string value("Hello");
1040 StringAppendF(&value, "");
1041 EXPECT_EQ("Hello", value);
1042
1043 std::wstring valuew(L"Hello");
1044 StringAppendF(&valuew, L"");
1045 EXPECT_EQ(L"Hello", valuew);
1046 }
1047
1048 TEST(StringUtilTest, StringAppendfEmptyString) {
1049 std::string value("Hello");
1050 StringAppendF(&value, "%s", "");
1051 EXPECT_EQ("Hello", value);
1052
1053 std::wstring valuew(L"Hello");
1054 StringAppendF(&valuew, L"%ls", L"");
1055 EXPECT_EQ(L"Hello", valuew);
1056 }
1057
1058 TEST(StringUtilTest, StringAppendfString) {
1059 std::string value("Hello");
1060 StringAppendF(&value, " %s", "World");
1061 EXPECT_EQ("Hello World", value);
1062
1063 std::wstring valuew(L"Hello");
1064 StringAppendF(&valuew, L" %ls", L"World");
1065 EXPECT_EQ(L"Hello World", valuew);
1066 }
1067
1068 TEST(StringUtilTest, StringAppendfInt) {
1069 std::string value("Hello");
1070 StringAppendF(&value, " %d", 123);
1071 EXPECT_EQ("Hello 123", value);
1072
1073 std::wstring valuew(L"Hello");
1074 StringAppendF(&valuew, L" %d", 123);
1075 EXPECT_EQ(L"Hello 123", valuew);
1076 }
1077
1078 // Make sure that lengths exactly around the initial buffer size are handled
1079 // correctly.
1080 TEST(StringUtilTest, StringPrintfBounds) {
1081 const int src_len = 1026;
1082 char src[src_len];
1083 for (size_t i = 0; i < arraysize(src); i++)
1084 src[i] = 'A';
1085
1086 wchar_t srcw[src_len];
1087 for (size_t i = 0; i < arraysize(srcw); i++)
1088 srcw[i] = 'A';
1089
1090 for (int i = 1; i < 3; i++) {
1091 src[src_len - i] = 0;
1092 std::string out;
1093 SStringPrintf(&out, "%s", src);
1094 EXPECT_STREQ(src, out.c_str());
1095
1096 srcw[src_len - i] = 0;
1097 std::wstring outw;
1098 SStringPrintf(&outw, L"%ls", srcw);
1099 EXPECT_STREQ(srcw, outw.c_str());
1100 }
1101 }
1102
1103 // Test very large sprintfs that will cause the buffer to grow.
1104 TEST(StringUtilTest, Grow) {
1105 char src[1026];
1106 for (size_t i = 0; i < arraysize(src); i++)
1107 src[i] = 'A';
1108 src[1025] = 0;
1109
1110 const char* fmt = "%sB%sB%sB%sB%sB%sB%s";
1111
1112 std::string out;
1113 SStringPrintf(&out, fmt, src, src, src, src, src, src, src);
1114
1115 char* ref = new char[320000];
1116 #if defined(OS_WIN)
1117 sprintf_s(ref, 320000, fmt, src, src, src, src, src, src, src);
1118 #elif defined(OS_POSIX)
1119 snprintf(ref, 320000, fmt, src, src, src, src, src, src, src);
1120 #endif 303 #endif
1121
1122 EXPECT_STREQ(ref, out.c_str());
1123 delete[] ref;
1124 }
1125
1126 // Test the boundary condition for the size of the string_util's
1127 // internal buffer.
1128 TEST(StringUtilTest, GrowBoundary) {
1129 const int string_util_buf_len = 1024;
1130 // Our buffer should be one larger than the size of StringAppendVT's stack
1131 // buffer.
1132 const int buf_len = string_util_buf_len + 1;
1133 char src[buf_len + 1]; // Need extra one for NULL-terminator.
1134 for (int i = 0; i < buf_len; ++i)
1135 src[i] = 'a';
1136 src[buf_len] = 0;
1137
1138 std::string out;
1139 SStringPrintf(&out, "%s", src);
1140
1141 EXPECT_STREQ(src, out.c_str());
1142 }
1143
1144 // TODO(evanm): what's the proper cross-platform test here?
1145 #if defined(OS_WIN)
1146 // sprintf in Visual Studio fails when given U+FFFF. This tests that the
1147 // failure case is gracefuly handled.
1148 TEST(StringUtilTest, Invalid) {
1149 wchar_t invalid[2];
1150 invalid[0] = 0xffff;
1151 invalid[1] = 0;
1152
1153 std::wstring out;
1154 SStringPrintf(&out, L"%ls", invalid);
1155 EXPECT_STREQ(L"", out.c_str());
1156 }
1157 #endif
1158
1159 // Test for SplitString
1160 TEST(StringUtilTest, SplitString) {
1161 std::vector<std::wstring> r;
1162
1163 SplitString(L"a,b,c", L',', &r);
1164 EXPECT_EQ(3U, r.size());
1165 EXPECT_EQ(r[0], L"a");
1166 EXPECT_EQ(r[1], L"b");
1167 EXPECT_EQ(r[2], L"c");
1168 r.clear();
1169
1170 SplitString(L"a, b, c", L',', &r);
1171 EXPECT_EQ(3U, r.size());
1172 EXPECT_EQ(r[0], L"a");
1173 EXPECT_EQ(r[1], L"b");
1174 EXPECT_EQ(r[2], L"c");
1175 r.clear();
1176
1177 SplitString(L"a,,c", L',', &r);
1178 EXPECT_EQ(3U, r.size());
1179 EXPECT_EQ(r[0], L"a");
1180 EXPECT_EQ(r[1], L"");
1181 EXPECT_EQ(r[2], L"c");
1182 r.clear();
1183
1184 SplitString(L"", L'*', &r);
1185 EXPECT_EQ(1U, r.size());
1186 EXPECT_EQ(r[0], L"");
1187 r.clear();
1188
1189 SplitString(L"foo", L'*', &r);
1190 EXPECT_EQ(1U, r.size());
1191 EXPECT_EQ(r[0], L"foo");
1192 r.clear();
1193
1194 SplitString(L"foo ,", L',', &r);
1195 EXPECT_EQ(2U, r.size());
1196 EXPECT_EQ(r[0], L"foo");
1197 EXPECT_EQ(r[1], L"");
1198 r.clear();
1199
1200 SplitString(L",", L',', &r);
1201 EXPECT_EQ(2U, r.size());
1202 EXPECT_EQ(r[0], L"");
1203 EXPECT_EQ(r[1], L"");
1204 r.clear();
1205
1206 SplitString(L"\t\ta\t", L'\t', &r);
1207 EXPECT_EQ(4U, r.size());
1208 EXPECT_EQ(r[0], L"");
1209 EXPECT_EQ(r[1], L"");
1210 EXPECT_EQ(r[2], L"a");
1211 EXPECT_EQ(r[3], L"");
1212 r.clear();
1213
1214 SplitStringDontTrim(L"\t\ta\t", L'\t', &r);
1215 EXPECT_EQ(4U, r.size());
1216 EXPECT_EQ(r[0], L"");
1217 EXPECT_EQ(r[1], L"");
1218 EXPECT_EQ(r[2], L"a");
1219 EXPECT_EQ(r[3], L"");
1220 r.clear();
1221
1222 SplitString(L"\ta\t\nb\tcc", L'\n', &r);
1223 EXPECT_EQ(2U, r.size());
1224 EXPECT_EQ(r[0], L"a");
1225 EXPECT_EQ(r[1], L"b\tcc");
1226 r.clear();
1227
1228 SplitStringDontTrim(L"\ta\t\nb\tcc", L'\n', &r);
1229 EXPECT_EQ(2U, r.size());
1230 EXPECT_EQ(r[0], L"\ta\t");
1231 EXPECT_EQ(r[1], L"b\tcc");
1232 r.clear();
1233 }
1234
1235 // Test for JoinString
1236 TEST(StringUtilTest, JoinString) {
1237 std::vector<std::string> in;
1238 EXPECT_EQ("", JoinString(in, ','));
1239
1240 in.push_back("a");
1241 EXPECT_EQ("a", JoinString(in, ','));
1242
1243 in.push_back("b");
1244 in.push_back("c");
1245 EXPECT_EQ("a,b,c", JoinString(in, ','));
1246
1247 in.push_back("");
1248 EXPECT_EQ("a,b,c,", JoinString(in, ','));
1249 in.push_back(" ");
1250 EXPECT_EQ("a|b|c|| ", JoinString(in, '|'));
1251 }
1252
1253 TEST(StringUtilTest, StartsWith) {
1254 EXPECT_TRUE(StartsWithASCII("javascript:url", "javascript", true));
1255 EXPECT_FALSE(StartsWithASCII("JavaScript:url", "javascript", true));
1256 EXPECT_TRUE(StartsWithASCII("javascript:url", "javascript", false));
1257 EXPECT_TRUE(StartsWithASCII("JavaScript:url", "javascript", false));
1258 EXPECT_FALSE(StartsWithASCII("java", "javascript", true));
1259 EXPECT_FALSE(StartsWithASCII("java", "javascript", false));
1260 EXPECT_FALSE(StartsWithASCII("", "javascript", false));
1261 EXPECT_FALSE(StartsWithASCII("", "javascript", true));
1262 EXPECT_TRUE(StartsWithASCII("java", "", false));
1263 EXPECT_TRUE(StartsWithASCII("java", "", true));
1264
1265 EXPECT_TRUE(StartsWith(L"javascript:url", L"javascript", true));
1266 EXPECT_FALSE(StartsWith(L"JavaScript:url", L"javascript", true));
1267 EXPECT_TRUE(StartsWith(L"javascript:url", L"javascript", false));
1268 EXPECT_TRUE(StartsWith(L"JavaScript:url", L"javascript", false));
1269 EXPECT_FALSE(StartsWith(L"java", L"javascript", true));
1270 EXPECT_FALSE(StartsWith(L"java", L"javascript", false));
1271 EXPECT_FALSE(StartsWith(L"", L"javascript", false));
1272 EXPECT_FALSE(StartsWith(L"", L"javascript", true));
1273 EXPECT_TRUE(StartsWith(L"java", L"", false));
1274 EXPECT_TRUE(StartsWith(L"java", L"", true));
1275 }
1276
1277 TEST(StringUtilTest, EndsWith) {
1278 EXPECT_TRUE(EndsWith(L"Foo.plugin", L".plugin", true));
1279 EXPECT_FALSE(EndsWith(L"Foo.Plugin", L".plugin", true));
1280 EXPECT_TRUE(EndsWith(L"Foo.plugin", L".plugin", false));
1281 EXPECT_TRUE(EndsWith(L"Foo.Plugin", L".plugin", false));
1282 EXPECT_FALSE(EndsWith(L".plug", L".plugin", true));
1283 EXPECT_FALSE(EndsWith(L".plug", L".plugin", false));
1284 EXPECT_FALSE(EndsWith(L"Foo.plugin Bar", L".plugin", true));
1285 EXPECT_FALSE(EndsWith(L"Foo.plugin Bar", L".plugin", false));
1286 EXPECT_FALSE(EndsWith(L"", L".plugin", false));
1287 EXPECT_FALSE(EndsWith(L"", L".plugin", true));
1288 EXPECT_TRUE(EndsWith(L"Foo.plugin", L"", false));
1289 EXPECT_TRUE(EndsWith(L"Foo.plugin", L"", true));
1290 EXPECT_TRUE(EndsWith(L".plugin", L".plugin", false));
1291 EXPECT_TRUE(EndsWith(L".plugin", L".plugin", true));
1292 EXPECT_TRUE(EndsWith(L"", L"", false));
1293 EXPECT_TRUE(EndsWith(L"", L"", true));
1294 }
1295
1296 TEST(StringUtilTest, GetStringFWithOffsets) {
1297 std::vector<string16> subst;
1298 subst.push_back(ASCIIToUTF16("1"));
1299 subst.push_back(ASCIIToUTF16("2"));
1300 std::vector<size_t> offsets;
1301
1302 ReplaceStringPlaceholders(ASCIIToUTF16("Hello, $1. Your number is $2."),
1303 subst,
1304 &offsets);
1305 EXPECT_EQ(2U, offsets.size());
1306 EXPECT_EQ(7U, offsets[0]);
1307 EXPECT_EQ(25U, offsets[1]);
1308 offsets.clear();
1309
1310 ReplaceStringPlaceholders(ASCIIToUTF16("Hello, $2. Your number is $1."),
1311 subst,
1312 &offsets);
1313 EXPECT_EQ(2U, offsets.size());
1314 EXPECT_EQ(25U, offsets[0]);
1315 EXPECT_EQ(7U, offsets[1]);
1316 offsets.clear();
1317 }
1318
1319 TEST(StringUtilTest, ReplaceStringPlaceholders) {
1320 std::vector<string16> subst;
1321 subst.push_back(ASCIIToUTF16("9a"));
1322 subst.push_back(ASCIIToUTF16("8b"));
1323 subst.push_back(ASCIIToUTF16("7c"));
1324 subst.push_back(ASCIIToUTF16("6d"));
1325 subst.push_back(ASCIIToUTF16("5e"));
1326 subst.push_back(ASCIIToUTF16("4f"));
1327 subst.push_back(ASCIIToUTF16("3g"));
1328 subst.push_back(ASCIIToUTF16("2h"));
1329 subst.push_back(ASCIIToUTF16("1i"));
1330
1331 string16 formatted =
1332 ReplaceStringPlaceholders(
1333 ASCIIToUTF16("$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i"), subst, NULL);
1334
1335 EXPECT_EQ(formatted, ASCIIToUTF16("9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii"));
1336 }
1337
1338 TEST(StringUtilTest, ReplaceStringPlaceholdersTooFew) {
1339 // Test whether replacestringplaceholders works as expected when there
1340 // are fewer inputs than outputs.
1341 std::vector<string16> subst;
1342 subst.push_back(ASCIIToUTF16("9a"));
1343 subst.push_back(ASCIIToUTF16("8b"));
1344 subst.push_back(ASCIIToUTF16("7c"));
1345
1346 string16 formatted =
1347 ReplaceStringPlaceholders(
1348 ASCIIToUTF16("$1a,$2b,$3c,$4d,$5e,$6f,$1g,$2h,$3i"), subst, NULL);
1349
1350 EXPECT_EQ(formatted, ASCIIToUTF16("9aa,8bb,7cc,d,e,f,9ag,8bh,7ci"));
1351 }
1352
1353 TEST(StringUtilTest, StdStringReplaceStringPlaceholders) {
1354 std::vector<std::string> subst;
1355 subst.push_back("9a");
1356 subst.push_back("8b");
1357 subst.push_back("7c");
1358 subst.push_back("6d");
1359 subst.push_back("5e");
1360 subst.push_back("4f");
1361 subst.push_back("3g");
1362 subst.push_back("2h");
1363 subst.push_back("1i");
1364
1365 std::string formatted =
1366 ReplaceStringPlaceholders(
1367 "$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, NULL);
1368
1369 EXPECT_EQ(formatted, "9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii");
1370 }
1371
1372 TEST(StringUtilTest, SplitStringAlongWhitespace) {
1373 struct TestData {
1374 const std::wstring input;
1375 const size_t expected_result_count;
1376 const std::wstring output1;
1377 const std::wstring output2;
1378 } data[] = {
1379 { L"a", 1, L"a", L"" },
1380 { L" ", 0, L"", L"" },
1381 { L" a", 1, L"a", L"" },
1382 { L" ab ", 1, L"ab", L"" },
1383 { L" ab c", 2, L"ab", L"c" },
1384 { L" ab c ", 2, L"ab", L"c" },
1385 { L" ab cd", 2, L"ab", L"cd" },
1386 { L" ab cd ", 2, L"ab", L"cd" },
1387 { L" \ta\t", 1, L"a", L"" },
1388 { L" b\ta\t", 2, L"b", L"a" },
1389 { L" b\tat", 2, L"b", L"at" },
1390 { L"b\tat", 2, L"b", L"at" },
1391 { L"b\t at", 2, L"b", L"at" },
1392 };
1393 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
1394 std::vector<std::wstring> results;
1395 SplitStringAlongWhitespace(data[i].input, &results);
1396 ASSERT_EQ(data[i].expected_result_count, results.size());
1397 if (data[i].expected_result_count > 0)
1398 ASSERT_EQ(data[i].output1, results[0]);
1399 if (data[i].expected_result_count > 1)
1400 ASSERT_EQ(data[i].output2, results[1]);
1401 }
1402 }
1403
1404 TEST(StringUtilTest, MatchPatternTest) {
1405 EXPECT_EQ(MatchPattern(L"www.google.com", L"*.com"), true);
1406 EXPECT_EQ(MatchPattern(L"www.google.com", L"*"), true);
1407 EXPECT_EQ(MatchPattern(L"www.google.com", L"www*.g*.org"), false);
1408 EXPECT_EQ(MatchPattern(L"Hello", L"H?l?o"), true);
1409 EXPECT_EQ(MatchPattern(L"www.google.com", L"http://*)"), false);
1410 EXPECT_EQ(MatchPattern(L"www.msn.com", L"*.COM"), false);
1411 EXPECT_EQ(MatchPattern(L"Hello*1234", L"He??o\\*1*"), true);
1412 EXPECT_EQ(MatchPattern(L"", L"*.*"), false);
1413 EXPECT_EQ(MatchPattern(L"", L"*"), true);
1414 EXPECT_EQ(MatchPattern(L"", L"?"), true);
1415 EXPECT_EQ(MatchPattern(L"", L""), true);
1416 EXPECT_EQ(MatchPattern(L"Hello", L""), false);
1417 EXPECT_EQ(MatchPattern(L"Hello*", L"Hello*"), true);
1418 EXPECT_EQ(MatchPattern("Hello*", "Hello*"), true); // narrow string
1419 }
1420
1421 TEST(StringUtilTest, LcpyTest) {
1422 // Test the normal case where we fit in our buffer.
1423 {
1424 char dst[10];
1425 wchar_t wdst[10];
1426 EXPECT_EQ(7U, base::strlcpy(dst, "abcdefg", arraysize(dst)));
1427 EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
1428 EXPECT_EQ(7U, base::wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
1429 EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
1430 }
1431
1432 // Test dst_size == 0, nothing should be written to |dst| and we should
1433 // have the equivalent of strlen(src).
1434 {
1435 char dst[2] = {1, 2};
1436 wchar_t wdst[2] = {1, 2};
1437 EXPECT_EQ(7U, base::strlcpy(dst, "abcdefg", 0));
1438 EXPECT_EQ(1, dst[0]);
1439 EXPECT_EQ(2, dst[1]);
1440 EXPECT_EQ(7U, base::wcslcpy(wdst, L"abcdefg", 0));
1441 #if defined(WCHAR_T_IS_UNSIGNED)
1442 EXPECT_EQ(1U, wdst[0]);
1443 EXPECT_EQ(2U, wdst[1]);
1444 #else
1445 EXPECT_EQ(1, wdst[0]);
1446 EXPECT_EQ(2, wdst[1]);
1447 #endif
1448 }
1449
1450 // Test the case were we _just_ competely fit including the null.
1451 {
1452 char dst[8];
1453 wchar_t wdst[8];
1454 EXPECT_EQ(7U, base::strlcpy(dst, "abcdefg", arraysize(dst)));
1455 EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
1456 EXPECT_EQ(7U, base::wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
1457 EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
1458 }
1459
1460 // Test the case were we we are one smaller, so we can't fit the null.
1461 {
1462 char dst[7];
1463 wchar_t wdst[7];
1464 EXPECT_EQ(7U, base::strlcpy(dst, "abcdefg", arraysize(dst)));
1465 EXPECT_EQ(0, memcmp(dst, "abcdef", 7));
1466 EXPECT_EQ(7U, base::wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
1467 EXPECT_EQ(0, memcmp(wdst, L"abcdef", sizeof(wchar_t) * 7));
1468 }
1469
1470 // Test the case were we are just too small.
1471 {
1472 char dst[3];
1473 wchar_t wdst[3];
1474 EXPECT_EQ(7U, base::strlcpy(dst, "abcdefg", arraysize(dst)));
1475 EXPECT_EQ(0, memcmp(dst, "ab", 3));
1476 EXPECT_EQ(7U, base::wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
1477 EXPECT_EQ(0, memcmp(wdst, L"ab", sizeof(wchar_t) * 3));
1478 }
1479 }
1480
1481 TEST(StringUtilTest, WprintfFormatPortabilityTest) {
1482 struct TestData {
1483 const wchar_t* input;
1484 bool portable;
1485 } cases[] = {
1486 { L"%ls", true },
1487 { L"%s", false },
1488 { L"%S", false },
1489 { L"%lS", false },
1490 { L"Hello, %s", false },
1491 { L"%lc", true },
1492 { L"%c", false },
1493 { L"%C", false },
1494 { L"%lC", false },
1495 { L"%ls %s", false },
1496 { L"%s %ls", false },
1497 { L"%s %ls %s", false },
1498 { L"%f", true },
1499 { L"%f %F", false },
1500 { L"%d %D", false },
1501 { L"%o %O", false },
1502 { L"%u %U", false },
1503 { L"%f %d %o %u", true },
1504 { L"%-8d (%02.1f%)", true },
1505 { L"% 10s", false },
1506 { L"% 10ls", true }
1507 };
1508 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1509 EXPECT_EQ(cases[i].portable, base::IsWprintfFormatPortable(cases[i].input));
1510 }
1511 }
1512
1513 TEST(StringUtilTest, ElideString) {
1514 struct TestData {
1515 const wchar_t* input;
1516 int max_len;
1517 bool result;
1518 const wchar_t* output;
1519 } cases[] = {
1520 { L"Hello", 0, true, L"" },
1521 { L"", 0, false, L"" },
1522 { L"Hello, my name is Tom", 1, true, L"H" },
1523 { L"Hello, my name is Tom", 2, true, L"He" },
1524 { L"Hello, my name is Tom", 3, true, L"H.m" },
1525 { L"Hello, my name is Tom", 4, true, L"H..m" },
1526 { L"Hello, my name is Tom", 5, true, L"H...m" },
1527 { L"Hello, my name is Tom", 6, true, L"He...m" },
1528 { L"Hello, my name is Tom", 7, true, L"He...om" },
1529 { L"Hello, my name is Tom", 10, true, L"Hell...Tom" },
1530 { L"Hello, my name is Tom", 100, false, L"Hello, my name is Tom" }
1531 };
1532 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1533 std::wstring output;
1534 EXPECT_EQ(cases[i].result,
1535 ElideString(cases[i].input, cases[i].max_len, &output));
1536 EXPECT_TRUE(output == cases[i].output);
1537 }
1538 }
1539
1540 TEST(StringUtilTest, HexEncode) {
1541 std::string hex(HexEncode(NULL, 0));
1542 EXPECT_EQ(hex.length(), 0U);
1543 unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
1544 hex = HexEncode(bytes, sizeof(bytes));
1545 EXPECT_EQ(hex.compare("01FF02FE038081"), 0);
1546 } 304 }
1547 305
1548 } // namaspace base 306 } // namaspace base
OLDNEW
« no previous file with comments | « base/utf_string_conversions.cc ('k') | chrome/browser/autocomplete/autocomplete.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698