file_manager: Fix a bug where hosted documents could not be opened without active...
[chromium-blink-merge.git] / net / base / net_util_unittest.cc
blob22bcba16edc4cbce3c01fbf33436451b61c306f2
1 // Copyright (c) 2012 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 "net/base/net_util.h"
7 #include <string.h>
9 #include <algorithm>
11 #include "base/files/file_path.h"
12 #include "base/format_macros.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/sys_string_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/sys_byteorder.h"
19 #include "base/test/test_file_util.h"
20 #include "base/time/time.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "url/gurl.h"
24 namespace net {
26 namespace {
28 static const size_t kNpos = base::string16::npos;
30 struct FileCase {
31 const wchar_t* file;
32 const char* url;
35 struct HeaderCase {
36 const char* header_name;
37 const char* expected;
40 struct HeaderParamCase {
41 const char* header_name;
42 const char* param_name;
43 const char* expected;
46 struct FileNameCDCase {
47 const char* header_field;
48 const char* referrer_charset;
49 const wchar_t* expected;
52 const char* kLanguages[] = {
53 "", "en", "zh-CN", "ja", "ko",
54 "he", "ar", "ru", "el", "fr",
55 "de", "pt", "sv", "th", "hi",
56 "de,en", "el,en", "zh-TW,en", "ko,ja", "he,ru,en",
57 "zh,ru,en"
60 struct IDNTestCase {
61 const char* input;
62 const wchar_t* unicode_output;
63 const bool unicode_allowed[arraysize(kLanguages)];
66 // TODO(jungshik) This is just a random sample of languages and is far
67 // from exhaustive. We may have to generate all the combinations
68 // of languages (powerset of a set of all the languages).
69 const IDNTestCase idn_cases[] = {
70 // No IDN
71 {"www.google.com", L"www.google.com",
72 {true, true, true, true, true,
73 true, true, true, true, true,
74 true, true, true, true, true,
75 true, true, true, true, true,
76 true}},
77 {"www.google.com.", L"www.google.com.",
78 {true, true, true, true, true,
79 true, true, true, true, true,
80 true, true, true, true, true,
81 true, true, true, true, true,
82 true}},
83 {".", L".",
84 {true, true, true, true, true,
85 true, true, true, true, true,
86 true, true, true, true, true,
87 true, true, true, true, true,
88 true}},
89 {"", L"",
90 {true, true, true, true, true,
91 true, true, true, true, true,
92 true, true, true, true, true,
93 true, true, true, true, true,
94 true}},
95 // IDN
96 // Hanzi (Traditional Chinese)
97 {"xn--1lq90ic7f1rc.cn", L"\x5317\x4eac\x5927\x5b78.cn",
98 {true, false, true, true, false,
99 false, false, false, false, false,
100 false, false, false, false, false,
101 false, false, true, true, false,
102 true}},
103 // Hanzi ('video' in Simplified Chinese : will pass only in zh-CN,zh)
104 {"xn--cy2a840a.com", L"\x89c6\x9891.com",
105 {true, false, true, false, false,
106 false, false, false, false, false,
107 false, false, false, false, false,
108 false, false, false, false, false,
109 true}},
110 // Hanzi + '123'
111 {"www.xn--123-p18d.com", L"www.\x4e00" L"123.com",
112 {true, false, true, true, false,
113 false, false, false, false, false,
114 false, false, false, false, false,
115 false, false, true, true, false,
116 true}},
117 // Hanzi + Latin : U+56FD is simplified and is regarded
118 // as not supported in zh-TW.
119 {"www.xn--hello-9n1hm04c.com", L"www.hello\x4e2d\x56fd.com",
120 {false, false, true, true, false,
121 false, false, false, false, false,
122 false, false, false, false, false,
123 false, false, false, true, false,
124 true}},
125 // Kanji + Kana (Japanese)
126 {"xn--l8jvb1ey91xtjb.jp", L"\x671d\x65e5\x3042\x3055\x3072.jp",
127 {true, false, false, true, false,
128 false, false, false, false, false,
129 false, false, false, false, false,
130 false, false, false, true, false,
131 false}},
132 // Katakana including U+30FC
133 {"xn--tckm4i2e.jp", L"\x30b3\x30de\x30fc\x30b9.jp",
134 {true, false, false, true, false,
135 false, false, false, false, false,
136 false, false, false, false, false,
137 false, false, false, true, false,
139 {"xn--3ck7a7g.jp", L"\u30ce\u30f3\u30bd.jp",
140 {true, false, false, true, false,
141 false, false, false, false, false,
142 false, false, false, false, false,
143 false, false, false, true, false,
145 // Katakana + Latin (Japanese)
146 // TODO(jungshik): Change 'false' in the first element to 'true'
147 // after upgrading to ICU 4.2.1 to use new uspoof_* APIs instead
148 // of our IsIDNComponentInSingleScript().
149 {"xn--e-efusa1mzf.jp", L"e\x30b3\x30de\x30fc\x30b9.jp",
150 {false, false, false, true, false,
151 false, false, false, false, false,
152 false, false, false, false, false,
153 false, false, false, true, false,
155 {"xn--3bkxe.jp", L"\x30c8\x309a.jp",
156 {false, false, false, true, false,
157 false, false, false, false, false,
158 false, false, false, false, false,
159 false, false, false, true, false,
161 // Hangul (Korean)
162 {"www.xn--or3b17p6jjc.kr", L"www.\xc804\xc790\xc815\xbd80.kr",
163 {true, false, false, false, true,
164 false, false, false, false, false,
165 false, false, false, false, false,
166 false, false, false, true, false,
167 false}},
168 // b<u-umlaut>cher (German)
169 {"xn--bcher-kva.de", L"b\x00fc" L"cher.de",
170 {true, false, false, false, false,
171 false, false, false, false, true,
172 true, false, false, false, false,
173 true, false, false, false, false,
174 false}},
175 // a with diaeresis
176 {"www.xn--frgbolaget-q5a.se", L"www.f\x00e4rgbolaget.se",
177 {true, false, false, false, false,
178 false, false, false, false, false,
179 true, false, true, false, false,
180 true, false, false, false, false,
181 false}},
182 // c-cedilla (French)
183 {"www.xn--alliancefranaise-npb.fr", L"www.alliancefran\x00e7" L"aise.fr",
184 {true, false, false, false, false,
185 false, false, false, false, true,
186 false, true, false, false, false,
187 false, false, false, false, false,
188 false}},
189 // caf'e with acute accent' (French)
190 {"xn--caf-dma.fr", L"caf\x00e9.fr",
191 {true, false, false, false, false,
192 false, false, false, false, true,
193 false, true, true, false, false,
194 false, false, false, false, false,
195 false}},
196 // c-cedillla and a with tilde (Portuguese)
197 {"xn--poema-9qae5a.com.br", L"p\x00e3oema\x00e7\x00e3.com.br",
198 {true, false, false, false, false,
199 false, false, false, false, false,
200 false, true, false, false, false,
201 false, false, false, false, false,
202 false}},
203 // s with caron
204 {"xn--achy-f6a.com", L"\x0161" L"achy.com",
205 {true, false, false, false, false,
206 false, false, false, false, false,
207 false, false, false, false, false,
208 false, false, false, false, false,
209 false}},
210 // TODO(jungshik) : Add examples with Cyrillic letters
211 // only used in some languages written in Cyrillic.
212 // Eutopia (Greek)
213 {"xn--kxae4bafwg.gr", L"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1.gr",
214 {true, false, false, false, false,
215 false, false, false, true, false,
216 false, false, false, false, false,
217 false, true, false, false, false,
218 false}},
219 // Eutopia + 123 (Greek)
220 {"xn---123-pldm0haj2bk.gr",
221 L"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1-123.gr",
222 {true, false, false, false, false,
223 false, false, false, true, false,
224 false, false, false, false, false,
225 false, true, false, false, false,
226 false}},
227 // Cyrillic (Russian)
228 {"xn--n1aeec9b.ru", L"\x0442\x043e\x0440\x0442\x044b.ru",
229 {true, false, false, false, false,
230 false, false, true, false, false,
231 false, false, false, false, false,
232 false, false, false, false, true,
233 true}},
234 // Cyrillic + 123 (Russian)
235 {"xn---123-45dmmc5f.ru", L"\x0442\x043e\x0440\x0442\x044b-123.ru",
236 {true, false, false, false, false,
237 false, false, true, false, false,
238 false, false, false, false, false,
239 false, false, false, false, true,
240 true}},
241 // Arabic
242 {"xn--mgba1fmg.ar", L"\x0627\x0641\x0644\x0627\x0645.ar",
243 {true, false, false, false, false,
244 false, true, false, false, false,
245 false, false, false, false, false,
246 false, false, false, false, false,
247 false}},
248 // Hebrew
249 {"xn--4dbib.he", L"\x05d5\x05d0\x05d4.he",
250 {true, false, false, false, false,
251 true, false, false, false, false,
252 false, false, false, false, false,
253 false, false, false, false, true,
254 false}},
255 // Thai
256 {"xn--12c2cc4ag3b4ccu.th",
257 L"\x0e2a\x0e32\x0e22\x0e01\x0e32\x0e23\x0e1a\x0e34\x0e19.th",
258 {true, false, false, false, false,
259 false, false, false, false, false,
260 false, false, false, true, false,
261 false, false, false, false, false,
262 false}},
263 // Devangari (Hindi)
264 {"www.xn--l1b6a9e1b7c.in", L"www.\x0905\x0915\x094b\x0932\x093e.in",
265 {true, false, false, false, false,
266 false, false, false, false, false,
267 false, false, false, false, true,
268 false, false, false, false, false,
269 false}},
270 // Invalid IDN
271 {"xn--hello?world.com", NULL,
272 {false, false, false, false, false,
273 false, false, false, false, false,
274 false, false, false, false, false,
275 false, false, false, false, false,
276 false}},
277 // Unsafe IDNs
278 // "payp<alpha>l.com"
279 {"www.xn--paypl-g9d.com", L"payp\x03b1l.com",
280 {false, false, false, false, false,
281 false, false, false, false, false,
282 false, false, false, false, false,
283 false, false, false, false, false,
284 false}},
285 // google.gr with Greek omicron and epsilon
286 {"xn--ggl-6xc1ca.gr", L"g\x03bf\x03bfgl\x03b5.gr",
287 {false, false, false, false, false,
288 false, false, false, false, false,
289 false, false, false, false, false,
290 false, false, false, false, false,
291 false}},
292 // google.ru with Cyrillic o
293 {"xn--ggl-tdd6ba.ru", L"g\x043e\x043egl\x0435.ru",
294 {false, false, false, false, false,
295 false, false, false, false, false,
296 false, false, false, false, false,
297 false, false, false, false, false,
298 false}},
299 // h<e with acute>llo<China in Han>.cn
300 {"xn--hllo-bpa7979ih5m.cn", L"h\x00e9llo\x4e2d\x56fd.cn",
301 {false, false, false, false, false,
302 false, false, false, false, false,
303 false, false, false, false, false,
304 false, false, false, false, false,
305 false}},
306 // <Greek rho><Cyrillic a><Cyrillic u>.ru
307 {"xn--2xa6t2b.ru", L"\x03c1\x0430\x0443.ru",
308 {false, false, false, false, false,
309 false, false, false, false, false,
310 false, false, false, false, false,
311 false, false, false, false, false,
312 false}},
313 // One that's really long that will force a buffer realloc
314 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
315 "aaaaaaa",
316 L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
317 L"aaaaaaaa",
318 {true, true, true, true, true,
319 true, true, true, true, true,
320 true, true, true, true, true,
321 true, true, true, true, true,
322 true}},
323 // Test cases for characters we blacklisted although allowed in IDN.
324 // Embedded spaces will be turned to %20 in the display.
325 // TODO(jungshik): We need to have more cases. This is a typical
326 // data-driven trap. The following test cases need to be separated
327 // and tested only for a couple of languages.
328 {"xn--osd3820f24c.kr", L"\xac00\xb098\x115f.kr",
329 {false, false, false, false, false,
330 false, false, false, false, false,
331 false, false, false, false, false,
332 false, false, false, false, false,
333 false}},
334 {"www.xn--google-ho0coa.com", L"www.\x2039google\x203a.com",
335 {false, false, false, false, false,
336 false, false, false, false, false,
337 false, false, false, false, false,
338 false, false, false, false, false,
340 {"google.xn--comabc-k8d", L"google.com\x0338" L"abc",
341 {false, false, false, false, false,
342 false, false, false, false, false,
343 false, false, false, false, false,
344 false, false, false, false, false,
346 {"google.xn--com-oh4ba.evil.jp", L"google.com\x309a\x309a.evil.jp",
347 {false, false, false, false, false,
348 false, false, false, false, false,
349 false, false, false, false, false,
350 false, false, false, false, false,
352 {"google.xn--comevil-v04f.jp", L"google.com\x30ce" L"evil.jp",
353 {false, false, false, false, false,
354 false, false, false, false, false,
355 false, false, false, false, false,
356 false, false, false, false, false,
358 #if 0
359 // These two cases are special. We need a separate test.
360 // U+3000 and U+3002 are normalized to ASCII space and dot.
361 {"xn-- -kq6ay5z.cn", L"\x4e2d\x56fd\x3000.cn",
362 {false, false, true, false, false,
363 false, false, false, false, false,
364 false, false, false, false, false,
365 false, false, true, false, false,
366 true}},
367 {"xn--fiqs8s.cn", L"\x4e2d\x56fd\x3002" L"cn",
368 {false, false, true, false, false,
369 false, false, false, false, false,
370 false, false, false, false, false,
371 false, false, true, false, false,
372 true}},
373 #endif
376 struct AdjustOffsetCase {
377 size_t input_offset;
378 size_t output_offset;
381 struct CompliantHostCase {
382 const char* host;
383 const char* desired_tld;
384 bool expected_output;
387 struct GenerateFilenameCase {
388 int lineno;
389 const char* url;
390 const char* content_disp_header;
391 const char* referrer_charset;
392 const char* suggested_filename;
393 const char* mime_type;
394 const wchar_t* default_filename;
395 const wchar_t* expected_filename;
398 struct UrlTestData {
399 const char* description;
400 const char* input;
401 const char* languages;
402 FormatUrlTypes format_types;
403 UnescapeRule::Type escape_rules;
404 const wchar_t* output; // Use |wchar_t| to handle Unicode constants easily.
405 size_t prefix_len;
408 // Fills in sockaddr for the given 32-bit address (IPv4.)
409 // |bytes| should be an array of length 4.
410 void MakeIPv4Address(const uint8* bytes, int port, SockaddrStorage* storage) {
411 memset(&storage->addr_storage, 0, sizeof(storage->addr_storage));
412 storage->addr_len = sizeof(struct sockaddr_in);
413 struct sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(storage->addr);
414 addr4->sin_port = base::HostToNet16(port);
415 addr4->sin_family = AF_INET;
416 memcpy(&addr4->sin_addr, bytes, 4);
419 // Fills in sockaddr for the given 128-bit address (IPv6.)
420 // |bytes| should be an array of length 16.
421 void MakeIPv6Address(const uint8* bytes, int port, SockaddrStorage* storage) {
422 memset(&storage->addr_storage, 0, sizeof(storage->addr_storage));
423 storage->addr_len = sizeof(struct sockaddr_in6);
424 struct sockaddr_in6* addr6 = reinterpret_cast<sockaddr_in6*>(storage->addr);
425 addr6->sin6_port = base::HostToNet16(port);
426 addr6->sin6_family = AF_INET6;
427 memcpy(&addr6->sin6_addr, bytes, 16);
430 // A helper for IDN*{Fast,Slow}.
431 // Append "::<language list>" to |expected| and |actual| to make it
432 // easy to tell which sub-case fails without debugging.
433 void AppendLanguagesToOutputs(const char* languages,
434 base::string16* expected,
435 base::string16* actual) {
436 base::string16 to_append = ASCIIToUTF16("::") + ASCIIToUTF16(languages);
437 expected->append(to_append);
438 actual->append(to_append);
441 // A pair of helpers for the FormatUrlWithOffsets() test.
442 void VerboseExpect(size_t expected,
443 size_t actual,
444 const std::string& original_url,
445 size_t position,
446 const base::string16& formatted_url) {
447 EXPECT_EQ(expected, actual) << "Original URL: " << original_url
448 << " (at char " << position << ")\nFormatted URL: " << formatted_url;
451 void CheckAdjustedOffsets(const std::string& url_string,
452 const std::string& languages,
453 FormatUrlTypes format_types,
454 UnescapeRule::Type unescape_rules,
455 const AdjustOffsetCase* cases,
456 size_t num_cases,
457 const size_t* all_offsets) {
458 GURL url(url_string);
459 for (size_t i = 0; i < num_cases; ++i) {
460 size_t offset = cases[i].input_offset;
461 base::string16 formatted_url = FormatUrl(url, languages, format_types,
462 unescape_rules, NULL, NULL, &offset);
463 VerboseExpect(cases[i].output_offset, offset, url_string, i, formatted_url);
466 size_t url_size = url_string.length();
467 std::vector<size_t> offsets;
468 for (size_t i = 0; i < url_size + 1; ++i)
469 offsets.push_back(i);
470 base::string16 formatted_url = FormatUrlWithOffsets(url, languages,
471 format_types, unescape_rules, NULL, NULL, &offsets);
472 for (size_t i = 0; i < url_size; ++i)
473 VerboseExpect(all_offsets[i], offsets[i], url_string, i, formatted_url);
474 VerboseExpect(kNpos, offsets[url_size], url_string, url_size, formatted_url);
477 // Helper to strignize an IP number (used to define expectations).
478 std::string DumpIPNumber(const IPAddressNumber& v) {
479 std::string out;
480 for (size_t i = 0; i < v.size(); ++i) {
481 if (i != 0)
482 out.append(",");
483 out.append(base::IntToString(static_cast<int>(v[i])));
485 return out;
488 void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) {
489 std::string default_filename(WideToUTF8(test_case->default_filename));
490 base::FilePath file_path = GenerateFileName(
491 GURL(test_case->url), test_case->content_disp_header,
492 test_case->referrer_charset, test_case->suggested_filename,
493 test_case->mime_type, default_filename);
494 EXPECT_EQ(test_case->expected_filename,
495 file_util::FilePathAsWString(file_path))
496 << "test case at line number: " << test_case->lineno;
499 } // anonymous namespace
501 TEST(NetUtilTest, FileURLConversion) {
502 // a list of test file names and the corresponding URLs
503 const FileCase round_trip_cases[] = {
504 #if defined(OS_WIN)
505 {L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
506 {L"\\\\some computer\\foo\\bar.txt",
507 "file://some%20computer/foo/bar.txt"}, // UNC
508 {L"D:\\Name;with%some symbols*#",
509 "file:///D:/Name%3Bwith%25some%20symbols*%23"},
510 // issue 14153: To be tested with the OS default codepage other than 1252.
511 {L"D:\\latin1\\caf\x00E9\x00DD.txt",
512 "file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
513 {L"D:\\otherlatin\\caf\x0119.txt",
514 "file:///D:/otherlatin/caf%C4%99.txt"},
515 {L"D:\\greek\\\x03B1\x03B2\x03B3.txt",
516 "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
517 {L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
518 "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
519 "%E9%A1%B5.doc"},
520 {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB"
521 "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
522 #elif defined(OS_POSIX)
523 {L"/foo/bar.txt", "file:///foo/bar.txt"},
524 {L"/foo/BAR.txt", "file:///foo/BAR.txt"},
525 {L"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"},
526 {L"/foo/bar?.txt", "file:///foo/bar%3F.txt"},
527 {L"/some computer/foo/bar.txt", "file:///some%20computer/foo/bar.txt"},
528 {L"/Name;with%some symbols*#", "file:///Name%3Bwith%25some%20symbols*%23"},
529 {L"/latin1/caf\x00E9\x00DD.txt", "file:///latin1/caf%C3%A9%C3%9D.txt"},
530 {L"/otherlatin/caf\x0119.txt", "file:///otherlatin/caf%C4%99.txt"},
531 {L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
532 {L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
533 "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
534 "%91%E9%A1%B5.doc"},
535 {L"/plane1/\x1D400\x1D401.txt", // Math alphabet "AB"
536 "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
537 #endif
540 // First, we'll test that we can round-trip all of the above cases of URLs
541 base::FilePath output;
542 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(round_trip_cases); i++) {
543 // convert to the file URL
544 GURL file_url(FilePathToFileURL(
545 file_util::WStringAsFilePath(round_trip_cases[i].file)));
546 EXPECT_EQ(round_trip_cases[i].url, file_url.spec());
548 // Back to the filename.
549 EXPECT_TRUE(FileURLToFilePath(file_url, &output));
550 EXPECT_EQ(round_trip_cases[i].file, file_util::FilePathAsWString(output));
553 // Test that various file: URLs get decoded into the correct file type
554 FileCase url_cases[] = {
555 #if defined(OS_WIN)
556 {L"C:\\foo\\bar.txt", "file:c|/foo\\bar.txt"},
557 {L"C:\\foo\\bar.txt", "file:/c:/foo/bar.txt"},
558 {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
559 {L"C:\\foo\\bar.txt", "file:///c:/foo/bar.txt"},
560 {L"\\\\foo\\bar.txt", "file:////foo\\bar.txt"},
561 {L"\\\\foo\\bar.txt", "file:/foo/bar.txt"},
562 {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
563 {L"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"},
564 #elif defined(OS_POSIX)
565 {L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"},
566 {L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"},
567 {L"/foo/bar.txt", "file:/foo/bar.txt"},
568 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
569 {L"/foo/bar.txt", "file:foo/bar.txt"},
570 {L"/bar.txt", "file://foo/bar.txt"},
571 {L"/foo/bar.txt", "file:///foo/bar.txt"},
572 {L"/foo/bar.txt", "file:////foo/bar.txt"},
573 {L"/foo/bar.txt", "file:////foo//bar.txt"},
574 {L"/foo/bar.txt", "file:////foo///bar.txt"},
575 {L"/foo/bar.txt", "file:////foo////bar.txt"},
576 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
577 {L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
578 // We get these wrong because GURL turns back slashes into forward
579 // slashes.
580 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
581 //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
582 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
583 //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
584 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
585 #endif
587 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_cases); i++) {
588 FileURLToFilePath(GURL(url_cases[i].url), &output);
589 EXPECT_EQ(url_cases[i].file, file_util::FilePathAsWString(output));
592 // Unfortunately, UTF8ToWide discards invalid UTF8 input.
593 #ifdef BUG_878908_IS_FIXED
594 // Test that no conversion happens if the UTF-8 input is invalid, and that
595 // the input is preserved in UTF-8
596 const char invalid_utf8[] = "file:///d:/Blah/\xff.doc";
597 const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc";
598 EXPECT_TRUE(FileURLToFilePath(
599 GURL(std::string(invalid_utf8)), &output));
600 EXPECT_EQ(std::wstring(invalid_wide), output);
601 #endif
603 // Test that if a file URL is malformed, we get a failure
604 EXPECT_FALSE(FileURLToFilePath(GURL("filefoobar"), &output));
607 TEST(NetUtilTest, GetIdentityFromURL) {
608 struct {
609 const char* input_url;
610 const char* expected_username;
611 const char* expected_password;
612 } tests[] = {
614 "http://username:password@google.com",
615 "username",
616 "password",
618 { // Test for http://crbug.com/19200
619 "http://username:p@ssword@google.com",
620 "username",
621 "p@ssword",
623 { // Special URL characters should be unescaped.
624 "http://username:p%3fa%26s%2fs%23@google.com",
625 "username",
626 "p?a&s/s#",
628 { // Username contains %20.
629 "http://use rname:password@google.com",
630 "use rname",
631 "password",
633 { // Keep %00 as is.
634 "http://use%00rname:password@google.com",
635 "use%00rname",
636 "password",
638 { // Use a '+' in the username.
639 "http://use+rname:password@google.com",
640 "use+rname",
641 "password",
643 { // Use a '&' in the password.
644 "http://username:p&ssword@google.com",
645 "username",
646 "p&ssword",
649 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
650 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
651 tests[i].input_url));
652 GURL url(tests[i].input_url);
654 base::string16 username, password;
655 GetIdentityFromURL(url, &username, &password);
657 EXPECT_EQ(ASCIIToUTF16(tests[i].expected_username), username);
658 EXPECT_EQ(ASCIIToUTF16(tests[i].expected_password), password);
662 // Try extracting a username which was encoded with UTF8.
663 TEST(NetUtilTest, GetIdentityFromURL_UTF8) {
664 GURL url(WideToUTF16(L"http://foo:\x4f60\x597d@blah.com"));
666 EXPECT_EQ("foo", url.username());
667 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password());
669 // Extract the unescaped identity.
670 base::string16 username, password;
671 GetIdentityFromURL(url, &username, &password);
673 // Verify that it was decoded as UTF8.
674 EXPECT_EQ(ASCIIToUTF16("foo"), username);
675 EXPECT_EQ(WideToUTF16(L"\x4f60\x597d"), password);
678 // Just a bunch of fake headers.
679 const char* google_headers =
680 "HTTP/1.1 200 OK\n"
681 "Content-TYPE: text/html; charset=utf-8\n"
682 "Content-disposition: attachment; filename=\"download.pdf\"\n"
683 "Content-Length: 378557\n"
684 "X-Google-Google1: 314159265\n"
685 "X-Google-Google2: aaaa2:7783,bbb21:9441\n"
686 "X-Google-Google4: home\n"
687 "Transfer-Encoding: chunked\n"
688 "Set-Cookie: HEHE_AT=6666x66beef666x6-66xx6666x66; Path=/mail\n"
689 "Set-Cookie: HEHE_HELP=owned:0;Path=/\n"
690 "Set-Cookie: S=gmail=Xxx-beefbeefbeef_beefb:gmail_yj=beefbeef000beefbee"
691 "fbee:gmproxy=bee-fbeefbe; Domain=.google.com; Path=/\n"
692 "X-Google-Google2: /one/two/three/four/five/six/seven-height/nine:9411\n"
693 "Server: GFE/1.3\n"
694 "Transfer-Encoding: chunked\n"
695 "Date: Mon, 13 Nov 2006 21:38:09 GMT\n"
696 "Expires: Tue, 14 Nov 2006 19:23:58 GMT\n"
697 "X-Malformed: bla; arg=test\"\n"
698 "X-Malformed2: bla; arg=\n"
699 "X-Test: bla; arg1=val1; arg2=val2";
701 TEST(NetUtilTest, GetSpecificHeader) {
702 const HeaderCase tests[] = {
703 {"content-type", "text/html; charset=utf-8"},
704 {"CONTENT-LENGTH", "378557"},
705 {"Date", "Mon, 13 Nov 2006 21:38:09 GMT"},
706 {"Bad-Header", ""},
707 {"", ""},
710 // Test first with google_headers.
711 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
712 std::string result =
713 GetSpecificHeader(google_headers, tests[i].header_name);
714 EXPECT_EQ(result, tests[i].expected);
717 // Test again with empty headers.
718 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
719 std::string result = GetSpecificHeader(std::string(), tests[i].header_name);
720 EXPECT_EQ(result, std::string());
724 TEST(NetUtilTest, IDNToUnicodeFast) {
725 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) {
726 for (size_t j = 0; j < arraysize(kLanguages); j++) {
727 // ja || zh-TW,en || ko,ja -> IDNToUnicodeSlow
728 if (j == 3 || j == 17 || j == 18)
729 continue;
730 base::string16 output(IDNToUnicode(idn_cases[i].input, kLanguages[j]));
731 base::string16 expected(idn_cases[i].unicode_allowed[j] ?
732 WideToUTF16(idn_cases[i].unicode_output) :
733 ASCIIToUTF16(idn_cases[i].input));
734 AppendLanguagesToOutputs(kLanguages[j], &expected, &output);
735 EXPECT_EQ(expected, output);
740 TEST(NetUtilTest, IDNToUnicodeSlow) {
741 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) {
742 for (size_t j = 0; j < arraysize(kLanguages); j++) {
743 // !(ja || zh-TW,en || ko,ja) -> IDNToUnicodeFast
744 if (!(j == 3 || j == 17 || j == 18))
745 continue;
746 base::string16 output(IDNToUnicode(idn_cases[i].input, kLanguages[j]));
747 base::string16 expected(idn_cases[i].unicode_allowed[j] ?
748 WideToUTF16(idn_cases[i].unicode_output) :
749 ASCIIToUTF16(idn_cases[i].input));
750 AppendLanguagesToOutputs(kLanguages[j], &expected, &output);
751 EXPECT_EQ(expected, output);
756 TEST(NetUtilTest, CompliantHost) {
757 const CompliantHostCase compliant_host_cases[] = {
758 {"", "", false},
759 {"a", "", true},
760 {"-", "", false},
761 {".", "", false},
762 {"9", "", true},
763 {"9a", "", true},
764 {"a.", "", true},
765 {"a.a", "", true},
766 {"9.a", "", true},
767 {"a.9", "", true},
768 {"_9a", "", false},
769 {"-9a", "", false},
770 {"-9a", "a", true},
771 {"a.a9", "", true},
772 {"a.-a9", "", false},
773 {"a+9a", "", false},
774 {"-a.a9", "", true},
775 {"1-.a-b", "", true},
776 {"1_.a-b", "", false},
777 {"1-2.a_b", "", true},
778 {"a.b.c.d.e", "", true},
779 {"1.2.3.4.5", "", true},
780 {"1.2.3.4.5.", "", true},
783 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(compliant_host_cases); ++i) {
784 EXPECT_EQ(compliant_host_cases[i].expected_output,
785 IsCanonicalizedHostCompliant(compliant_host_cases[i].host,
786 compliant_host_cases[i].desired_tld));
790 TEST(NetUtilTest, StripWWW) {
791 EXPECT_EQ(base::string16(), StripWWW(base::string16()));
792 EXPECT_EQ(base::string16(), StripWWW(ASCIIToUTF16("www.")));
793 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("www.blah")));
794 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("blah")));
797 #if defined(OS_WIN)
798 #define JPEG_EXT L".jpg"
799 #define HTML_EXT L".htm"
800 #elif defined(OS_MACOSX)
801 #define JPEG_EXT L".jpeg"
802 #define HTML_EXT L".html"
803 #else
804 #define JPEG_EXT L".jpg"
805 #define HTML_EXT L".html"
806 #endif
807 #define TXT_EXT L".txt"
808 #define TAR_EXT L".tar"
810 TEST(NetUtilTest, GenerateSafeFileName) {
811 const struct {
812 const char* mime_type;
813 const base::FilePath::CharType* filename;
814 const base::FilePath::CharType* expected_filename;
815 } safe_tests[] = {
816 #if defined(OS_WIN)
818 "text/html",
819 FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
820 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
823 "text/html",
824 FILE_PATH_LITERAL("C:\\foo\\bar.html"),
825 FILE_PATH_LITERAL("C:\\foo\\bar.html")
828 "text/html",
829 FILE_PATH_LITERAL("C:\\foo\\bar"),
830 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
833 "image/png",
834 FILE_PATH_LITERAL("C:\\bar.html"),
835 FILE_PATH_LITERAL("C:\\bar.html")
838 "image/png",
839 FILE_PATH_LITERAL("C:\\bar"),
840 FILE_PATH_LITERAL("C:\\bar.png")
843 "text/html",
844 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
845 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
848 "image/gif",
849 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
850 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
853 "text/html",
854 FILE_PATH_LITERAL("C:\\foo\\google.com"),
855 FILE_PATH_LITERAL("C:\\foo\\google.com")
858 "text/html",
859 FILE_PATH_LITERAL("C:\\foo\\con.htm"),
860 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
863 "text/html",
864 FILE_PATH_LITERAL("C:\\foo\\con"),
865 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
868 "text/html",
869 FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
870 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
873 "text/html",
874 FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
875 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
878 "text/html",
879 FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
880 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
883 "text/html",
884 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
885 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
887 // Allow extension synonyms.
889 "image/jpeg",
890 FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
891 FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
894 "image/jpeg",
895 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
896 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
898 #else // !defined(OS_WIN)
900 "text/html",
901 FILE_PATH_LITERAL("/foo/bar.htm"),
902 FILE_PATH_LITERAL("/foo/bar.htm")
905 "text/html",
906 FILE_PATH_LITERAL("/foo/bar.html"),
907 FILE_PATH_LITERAL("/foo/bar.html")
910 "text/html",
911 FILE_PATH_LITERAL("/foo/bar"),
912 FILE_PATH_LITERAL("/foo/bar.html")
915 "image/png",
916 FILE_PATH_LITERAL("/bar.html"),
917 FILE_PATH_LITERAL("/bar.html")
920 "image/png",
921 FILE_PATH_LITERAL("/bar"),
922 FILE_PATH_LITERAL("/bar.png")
925 "image/gif",
926 FILE_PATH_LITERAL("/foo/bar.exe"),
927 FILE_PATH_LITERAL("/foo/bar.exe")
930 "text/html",
931 FILE_PATH_LITERAL("/foo/google.com"),
932 FILE_PATH_LITERAL("/foo/google.com")
935 "text/html",
936 FILE_PATH_LITERAL("/foo/con.htm"),
937 FILE_PATH_LITERAL("/foo/con.htm")
940 "text/html",
941 FILE_PATH_LITERAL("/foo/con"),
942 FILE_PATH_LITERAL("/foo/con.html")
944 // Allow extension synonyms.
946 "image/jpeg",
947 FILE_PATH_LITERAL("/bar.jpg"),
948 FILE_PATH_LITERAL("/bar.jpg")
951 "image/jpeg",
952 FILE_PATH_LITERAL("/bar.jpeg"),
953 FILE_PATH_LITERAL("/bar.jpeg")
955 #endif // !defined(OS_WIN)
958 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(safe_tests); ++i) {
959 base::FilePath file_path(safe_tests[i].filename);
960 GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path);
961 EXPECT_EQ(safe_tests[i].expected_filename, file_path.value())
962 << "Iteration " << i;
966 TEST(NetUtilTest, GenerateFileName) {
967 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
968 // This test doesn't run when the locale is not UTF-8 because some of the
969 // string conversions fail. This is OK (we have the default value) but they
970 // don't match our expectations.
971 std::string locale = setlocale(LC_CTYPE, NULL);
972 StringToLowerASCII(&locale);
973 EXPECT_TRUE(locale.find("utf-8") != std::string::npos ||
974 locale.find("utf8") != std::string::npos)
975 << "Your locale (" << locale << ") must be set to UTF-8 "
976 << "for this test to pass!";
977 #endif
979 // Tests whether the correct filename is selected from the the given
980 // parameters and that Content-Disposition headers are properly
981 // handled including failovers when the header is malformed.
982 const GenerateFilenameCase selection_tests[] = {
984 __LINE__,
985 "http://www.google.com/",
986 "attachment; filename=test.html",
990 L"",
991 L"test.html"
994 __LINE__,
995 "http://www.google.com/",
996 "attachment; filename=\"test.html\"",
1000 L"",
1001 L"test.html"
1004 __LINE__,
1005 "http://www.google.com/",
1006 "attachment; filename= \"test.html\"",
1010 L"",
1011 L"test.html"
1014 __LINE__,
1015 "http://www.google.com/",
1016 "attachment; filename = \"test.html\"",
1020 L"",
1021 L"test.html"
1023 { // filename is whitespace. Should failover to URL host
1024 __LINE__,
1025 "http://www.google.com/",
1026 "attachment; filename= ",
1030 L"",
1031 L"www.google.com"
1033 { // No filename.
1034 __LINE__,
1035 "http://www.google.com/path/test.html",
1036 "attachment",
1040 L"",
1041 L"test.html"
1043 { // Ditto
1044 __LINE__,
1045 "http://www.google.com/path/test.html",
1046 "attachment;",
1050 L"",
1051 L"test.html"
1053 { // No C-D
1054 __LINE__,
1055 "http://www.google.com/",
1060 L"",
1061 L"www.google.com"
1064 __LINE__,
1065 "http://www.google.com/test.html",
1070 L"",
1071 L"test.html"
1073 { // Now that we use src/url's ExtractFileName, this case falls back to
1074 // the hostname. If this behavior is not desirable, we'd better change
1075 // ExtractFileName (in url_parse).
1076 __LINE__,
1077 "http://www.google.com/path/",
1082 L"",
1083 L"www.google.com"
1086 __LINE__,
1087 "http://www.google.com/path",
1092 L"",
1093 L"path"
1096 __LINE__,
1097 "file:///",
1102 L"",
1103 L"download"
1106 __LINE__,
1107 "file:///path/testfile",
1112 L"",
1113 L"testfile"
1116 __LINE__,
1117 "non-standard-scheme:",
1122 L"",
1123 L"download"
1125 { // C-D should override default
1126 __LINE__,
1127 "http://www.google.com/",
1128 "attachment; filename =\"test.html\"",
1132 L"download",
1133 L"test.html"
1135 { // But the URL shouldn't
1136 __LINE__,
1137 "http://www.google.com/",
1142 L"download",
1143 L"download"
1146 __LINE__,
1147 "http://www.google.com/",
1148 "attachment; filename=\"../test.html\"",
1152 L"",
1153 L"-test.html"
1156 __LINE__,
1157 "http://www.google.com/",
1158 "attachment; filename=\"..\\test.html\"",
1162 L"",
1163 L"test.html"
1166 __LINE__,
1167 "http://www.google.com/",
1168 "attachment; filename=\"..\\\\test.html\"",
1172 L"",
1173 L"-test.html"
1175 { // Filename disappears after leading and trailing periods are removed.
1176 __LINE__,
1177 "http://www.google.com/",
1178 "attachment; filename=\"..\"",
1182 L"default",
1183 L"default"
1185 { // C-D specified filename disappears. Failover to final filename.
1186 __LINE__,
1187 "http://www.google.com/test.html",
1188 "attachment; filename=\"..\"",
1192 L"default",
1193 L"default"
1195 // Below is a small subset of cases taken from HttpContentDisposition tests.
1197 __LINE__,
1198 "http://www.google.com/",
1199 "attachment; filename=\"%EC%98%88%EC%88%A0%20"
1200 "%EC%98%88%EC%88%A0.jpg\"",
1204 L"",
1205 L"\uc608\uc220 \uc608\uc220.jpg"
1208 __LINE__,
1209 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1214 L"download",
1215 L"\uc608\uc220 \uc608\uc220.jpg"
1218 __LINE__,
1219 "http://www.google.com/",
1220 "attachment;",
1224 L"\uB2E4\uC6B4\uB85C\uB4DC",
1225 L"\uB2E4\uC6B4\uB85C\uB4DC"
1228 __LINE__,
1229 "http://www.google.com/",
1230 "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
1231 "D13=2Epng?=\"",
1235 L"download",
1236 L"\u82b8\u88533.png"
1239 __LINE__,
1240 "http://www.example.com/images?id=3",
1241 "attachment; filename=caf\xc3\xa9.png",
1242 "iso-8859-1",
1245 L"",
1246 L"caf\u00e9.png"
1249 __LINE__,
1250 "http://www.example.com/images?id=3",
1251 "attachment; filename=caf\xe5.png",
1252 "windows-1253",
1255 L"",
1256 L"caf\u03b5.png"
1259 __LINE__,
1260 "http://www.example.com/file?id=3",
1261 "attachment; name=\xcf\xc2\xd4\xd8.zip",
1262 "GBK",
1265 L"",
1266 L"\u4e0b\u8f7d.zip"
1268 { // Invalid C-D header. Extracts filename from url.
1269 __LINE__,
1270 "http://www.google.com/test.html",
1271 "attachment; filename==?iiso88591?Q?caf=EG?=",
1275 L"",
1276 L"test.html"
1278 // about: and data: URLs
1280 __LINE__,
1281 "about:chrome",
1286 L"",
1287 L"download"
1290 __LINE__,
1291 "data:,looks/like/a.path",
1296 L"",
1297 L"download"
1300 __LINE__,
1301 "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
1306 L"",
1307 L"download"
1310 __LINE__,
1311 "data:,looks/like/a.path",
1316 L"default_filename_is_given",
1317 L"default_filename_is_given"
1320 __LINE__,
1321 "data:,looks/like/a.path",
1326 L"\u65e5\u672c\u8a9e", // Japanese Kanji.
1327 L"\u65e5\u672c\u8a9e"
1329 { // The filename encoding is specified by the referrer charset.
1330 __LINE__,
1331 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1333 "iso-8859-1",
1336 L"",
1337 L"V\u00fdvojov\u00e1 psychologie.doc"
1339 { // Suggested filename takes precedence over URL
1340 __LINE__,
1341 "http://www.google.com/test",
1344 "suggested",
1346 L"",
1347 L"suggested"
1349 { // The content-disposition has higher precedence over the suggested name.
1350 __LINE__,
1351 "http://www.google.com/test",
1352 "attachment; filename=test.html",
1354 "suggested",
1356 L"",
1357 L"test.html"
1359 #if 0
1360 { // The filename encoding doesn't match the referrer charset, the system
1361 // charset, or UTF-8.
1362 // TODO(jshin): we need to handle this case.
1363 __LINE__,
1364 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1366 "utf-8",
1369 L"",
1370 L"V\u00fdvojov\u00e1 psychologie.doc",
1372 #endif
1373 // Raw 8bit characters in C-D
1375 __LINE__,
1376 "http://www.example.com/images?id=3",
1377 "attachment; filename=caf\xc3\xa9.png",
1378 "iso-8859-1",
1380 "image/png",
1381 L"",
1382 L"caf\u00e9.png"
1385 __LINE__,
1386 "http://www.example.com/images?id=3",
1387 "attachment; filename=caf\xe5.png",
1388 "windows-1253",
1390 "image/png",
1391 L"",
1392 L"caf\u03b5.png"
1394 { // No 'filename' keyword in the disposition, use the URL
1395 __LINE__,
1396 "http://www.evil.com/my_download.txt",
1397 "a_file_name.txt",
1400 "text/plain",
1401 L"download",
1402 L"my_download.txt"
1404 { // Spaces in the disposition file name
1405 __LINE__,
1406 "http://www.frontpagehacker.com/a_download.exe",
1407 "filename=My Downloaded File.exe",
1410 "application/octet-stream",
1411 L"download",
1412 L"My Downloaded File.exe"
1414 { // % encoded
1415 __LINE__,
1416 "http://www.examples.com/",
1417 "attachment; "
1418 "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
1421 "image/jpeg",
1422 L"download",
1423 L"\uc608\uc220 \uc608\uc220.jpg"
1425 { // name= parameter
1426 __LINE__,
1427 "http://www.examples.com/q.cgi?id=abc",
1428 "attachment; name=abc de.pdf",
1431 "application/octet-stream",
1432 L"download",
1433 L"abc de.pdf"
1436 __LINE__,
1437 "http://www.example.com/path",
1438 "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
1441 "image/png",
1442 L"download",
1443 L"\x82b8\x8853" L"3.png"
1445 { // The following two have invalid CD headers and filenames come from the
1446 // URL.
1447 __LINE__,
1448 "http://www.example.com/test%20123",
1449 "attachment; filename==?iiso88591?Q?caf=EG?=",
1452 "image/jpeg",
1453 L"download",
1454 L"test 123" JPEG_EXT
1457 __LINE__,
1458 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1459 "malformed_disposition",
1462 "image/jpeg",
1463 L"download",
1464 L"\uc608\uc220 \uc608\uc220.jpg"
1466 { // Invalid C-D. No filename from URL. Falls back to 'download'.
1467 __LINE__,
1468 "http://www.google.com/path1/path2/",
1469 "attachment; filename==?iso88591?Q?caf=E3?",
1472 "image/jpeg",
1473 L"download",
1474 L"download" JPEG_EXT
1478 // Tests filename generation. Once the correct filename is
1479 // selected, they should be passed through the validation steps and
1480 // a correct extension should be added if necessary.
1481 const GenerateFilenameCase generation_tests[] = {
1482 // Dotfiles. Ensures preceeding period(s) stripped.
1484 __LINE__,
1485 "http://www.google.com/.test.html",
1490 L"",
1491 L"test.html"
1494 __LINE__,
1495 "http://www.google.com/.test",
1500 L"",
1501 L"test"
1504 __LINE__,
1505 "http://www.google.com/..test",
1510 L"",
1511 L"test"
1513 { // Disposition has relative paths, remove directory separators
1514 __LINE__,
1515 "http://www.evil.com/my_download.txt",
1516 "filename=../../../../././../a_file_name.txt",
1519 "text/plain",
1520 L"download",
1521 L"-..-..-..-.-.-..-a_file_name.txt"
1523 { // Disposition has parent directories, remove directory separators
1524 __LINE__,
1525 "http://www.evil.com/my_download.txt",
1526 "filename=dir1/dir2/a_file_name.txt",
1529 "text/plain",
1530 L"download",
1531 L"dir1-dir2-a_file_name.txt"
1533 { // Disposition has relative paths, remove directory separators
1534 __LINE__,
1535 "http://www.evil.com/my_download.txt",
1536 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt",
1539 "text/plain",
1540 L"download",
1541 L"-..-..-..-.-.-..-a_file_name.txt"
1543 { // Disposition has parent directories, remove directory separators
1544 __LINE__,
1545 "http://www.evil.com/my_download.txt",
1546 "filename=dir1\\dir2\\a_file_name.txt",
1549 "text/plain",
1550 L"download",
1551 L"dir1-dir2-a_file_name.txt"
1553 { // No useful information in disposition or URL, use default
1554 __LINE__,
1555 "http://www.truncated.com/path/",
1559 "text/plain",
1560 L"download",
1561 L"download" TXT_EXT
1563 { // Filename looks like HTML?
1564 __LINE__,
1565 "http://www.evil.com/get/malware/here",
1566 "filename=\"<blink>Hello kitty</blink>\"",
1569 "text/plain",
1570 L"default",
1571 L"-blink-Hello kitty--blink-" TXT_EXT
1573 { // A normal avi should get .avi and not .avi.avi
1574 __LINE__,
1575 "https://blah.google.com/misc/2.avi",
1579 "video/x-msvideo",
1580 L"download",
1581 L"2.avi"
1583 { // Extension generation
1584 __LINE__,
1585 "http://www.example.com/my-cat",
1586 "filename=my-cat",
1589 "image/jpeg",
1590 L"download",
1591 L"my-cat" JPEG_EXT
1594 __LINE__,
1595 "http://www.example.com/my-cat",
1596 "filename=my-cat",
1599 "text/plain",
1600 L"download",
1601 L"my-cat.txt"
1604 __LINE__,
1605 "http://www.example.com/my-cat",
1606 "filename=my-cat",
1609 "text/html",
1610 L"download",
1611 L"my-cat" HTML_EXT
1613 { // Unknown MIME type
1614 __LINE__,
1615 "http://www.example.com/my-cat",
1616 "filename=my-cat",
1619 "dance/party",
1620 L"download",
1621 L"my-cat"
1624 __LINE__,
1625 "http://www.example.com/my-cat.jpg",
1626 "filename=my-cat.jpg",
1629 "text/plain",
1630 L"download",
1631 L"my-cat.jpg"
1633 // Windows specific tests
1634 #if defined(OS_WIN)
1636 __LINE__,
1637 "http://www.goodguy.com/evil.exe",
1638 "filename=evil.exe",
1641 "image/jpeg",
1642 L"download",
1643 L"evil.exe"
1646 __LINE__,
1647 "http://www.goodguy.com/ok.exe",
1648 "filename=ok.exe",
1651 "binary/octet-stream",
1652 L"download",
1653 L"ok.exe"
1656 __LINE__,
1657 "http://www.goodguy.com/evil.dll",
1658 "filename=evil.dll",
1661 "dance/party",
1662 L"download",
1663 L"evil.dll"
1666 __LINE__,
1667 "http://www.goodguy.com/evil.exe",
1668 "filename=evil",
1671 "application/rss+xml",
1672 L"download",
1673 L"evil"
1675 // Test truncation of trailing dots and spaces
1677 __LINE__,
1678 "http://www.goodguy.com/evil.exe ",
1679 "filename=evil.exe ",
1682 "binary/octet-stream",
1683 L"download",
1684 L"evil.exe"
1687 __LINE__,
1688 "http://www.goodguy.com/evil.exe.",
1689 "filename=evil.exe.",
1692 "binary/octet-stream",
1693 L"download",
1694 L"evil.exe-"
1697 __LINE__,
1698 "http://www.goodguy.com/evil.exe. . .",
1699 "filename=evil.exe. . .",
1702 "binary/octet-stream",
1703 L"download",
1704 L"evil.exe-------"
1707 __LINE__,
1708 "http://www.goodguy.com/evil.",
1709 "filename=evil.",
1712 "binary/octet-stream",
1713 L"download",
1714 L"evil-"
1717 __LINE__,
1718 "http://www.goodguy.com/. . . . .",
1719 "filename=. . . . .",
1722 "binary/octet-stream",
1723 L"download",
1724 L"download"
1727 __LINE__,
1728 "http://www.badguy.com/attachment?name=meh.exe%C2%A0",
1729 "attachment; filename=\"meh.exe\xC2\xA0\"",
1732 "binary/octet-stream",
1733 L"",
1734 L"meh.exe-"
1736 #endif // OS_WIN
1738 __LINE__,
1739 "http://www.goodguy.com/utils.js",
1740 "filename=utils.js",
1743 "application/x-javascript",
1744 L"download",
1745 L"utils.js"
1748 __LINE__,
1749 "http://www.goodguy.com/contacts.js",
1750 "filename=contacts.js",
1753 "application/json",
1754 L"download",
1755 L"contacts.js"
1758 __LINE__,
1759 "http://www.goodguy.com/utils.js",
1760 "filename=utils.js",
1763 "text/javascript",
1764 L"download",
1765 L"utils.js"
1768 __LINE__,
1769 "http://www.goodguy.com/utils.js",
1770 "filename=utils.js",
1773 "text/javascript;version=2",
1774 L"download",
1775 L"utils.js"
1778 __LINE__,
1779 "http://www.goodguy.com/utils.js",
1780 "filename=utils.js",
1783 "application/ecmascript",
1784 L"download",
1785 L"utils.js"
1788 __LINE__,
1789 "http://www.goodguy.com/utils.js",
1790 "filename=utils.js",
1793 "application/ecmascript;version=4",
1794 L"download",
1795 L"utils.js"
1798 __LINE__,
1799 "http://www.goodguy.com/program.exe",
1800 "filename=program.exe",
1803 "application/foo-bar",
1804 L"download",
1805 L"program.exe"
1808 __LINE__,
1809 "http://www.evil.com/../foo.txt",
1810 "filename=../foo.txt",
1813 "text/plain",
1814 L"download",
1815 L"-foo.txt"
1818 __LINE__,
1819 "http://www.evil.com/..\\foo.txt",
1820 "filename=..\\foo.txt",
1823 "text/plain",
1824 L"download",
1825 L"-foo.txt"
1828 __LINE__,
1829 "http://www.evil.com/.hidden",
1830 "filename=.hidden",
1833 "text/plain",
1834 L"download",
1835 L"hidden" TXT_EXT
1838 __LINE__,
1839 "http://www.evil.com/trailing.",
1840 "filename=trailing.",
1843 "dance/party",
1844 L"download",
1845 #if defined(OS_WIN)
1846 L"trailing-"
1847 #else
1848 L"trailing"
1849 #endif
1852 __LINE__,
1853 "http://www.evil.com/trailing.",
1854 "filename=trailing.",
1857 "text/plain",
1858 L"download",
1859 #if defined(OS_WIN)
1860 L"trailing-" TXT_EXT
1861 #else
1862 L"trailing" TXT_EXT
1863 #endif
1866 __LINE__,
1867 "http://www.evil.com/.",
1868 "filename=.",
1871 "dance/party",
1872 L"download",
1873 L"download"
1876 __LINE__,
1877 "http://www.evil.com/..",
1878 "filename=..",
1881 "dance/party",
1882 L"download",
1883 L"download"
1886 __LINE__,
1887 "http://www.evil.com/...",
1888 "filename=...",
1891 "dance/party",
1892 L"download",
1893 L"download"
1895 { // Note that this one doesn't have "filename=" on it.
1896 __LINE__,
1897 "http://www.evil.com/",
1898 "a_file_name.txt",
1901 "image/jpeg",
1902 L"download",
1903 L"download" JPEG_EXT
1906 __LINE__,
1907 "http://www.evil.com/",
1908 "filename=",
1911 "image/jpeg",
1912 L"download",
1913 L"download" JPEG_EXT
1916 __LINE__,
1917 "http://www.example.com/simple",
1918 "filename=simple",
1921 "application/octet-stream",
1922 L"download",
1923 L"simple"
1925 // Reserved words on Windows
1927 __LINE__,
1928 "http://www.goodguy.com/COM1",
1929 "filename=COM1",
1932 "application/foo-bar",
1933 L"download",
1934 #if defined(OS_WIN)
1935 L"_COM1"
1936 #else
1937 L"COM1"
1938 #endif
1941 __LINE__,
1942 "http://www.goodguy.com/COM4.txt",
1943 "filename=COM4.txt",
1946 "text/plain",
1947 L"download",
1948 #if defined(OS_WIN)
1949 L"_COM4.txt"
1950 #else
1951 L"COM4.txt"
1952 #endif
1955 __LINE__,
1956 "http://www.goodguy.com/lpt1.TXT",
1957 "filename=lpt1.TXT",
1960 "text/plain",
1961 L"download",
1962 #if defined(OS_WIN)
1963 L"_lpt1.TXT"
1964 #else
1965 L"lpt1.TXT"
1966 #endif
1969 __LINE__,
1970 "http://www.goodguy.com/clock$.txt",
1971 "filename=clock$.txt",
1974 "text/plain",
1975 L"download",
1976 #if defined(OS_WIN)
1977 L"_clock$.txt"
1978 #else
1979 L"clock$.txt"
1980 #endif
1982 { // Validation should also apply to sugested name
1983 __LINE__,
1984 "http://www.goodguy.com/blah$.txt",
1985 "filename=clock$.txt",
1987 "clock$.txt",
1988 "text/plain",
1989 L"download",
1990 #if defined(OS_WIN)
1991 L"_clock$.txt"
1992 #else
1993 L"clock$.txt"
1994 #endif
1997 __LINE__,
1998 "http://www.goodguy.com/mycom1.foo",
1999 "filename=mycom1.foo",
2002 "text/plain",
2003 L"download",
2004 L"mycom1.foo"
2007 __LINE__,
2008 "http://www.badguy.com/Setup.exe.local",
2009 "filename=Setup.exe.local",
2012 "application/foo-bar",
2013 L"download",
2014 #if defined(OS_WIN)
2015 L"Setup.exe.download"
2016 #else
2017 L"Setup.exe.local"
2018 #endif
2021 __LINE__,
2022 "http://www.badguy.com/Setup.exe.local",
2023 "filename=Setup.exe.local.local",
2026 "application/foo-bar",
2027 L"download",
2028 #if defined(OS_WIN)
2029 L"Setup.exe.local.download"
2030 #else
2031 L"Setup.exe.local.local"
2032 #endif
2035 __LINE__,
2036 "http://www.badguy.com/Setup.exe.lnk",
2037 "filename=Setup.exe.lnk",
2040 "application/foo-bar",
2041 L"download",
2042 #if defined(OS_WIN)
2043 L"Setup.exe.download"
2044 #else
2045 L"Setup.exe.lnk"
2046 #endif
2049 __LINE__,
2050 "http://www.badguy.com/Desktop.ini",
2051 "filename=Desktop.ini",
2054 "application/foo-bar",
2055 L"download",
2056 #if defined(OS_WIN)
2057 L"_Desktop.ini"
2058 #else
2059 L"Desktop.ini"
2060 #endif
2063 __LINE__,
2064 "http://www.badguy.com/Thumbs.db",
2065 "filename=Thumbs.db",
2068 "application/foo-bar",
2069 L"download",
2070 #if defined(OS_WIN)
2071 L"_Thumbs.db"
2072 #else
2073 L"Thumbs.db"
2074 #endif
2077 __LINE__,
2078 "http://www.hotmail.com",
2079 "filename=source.jpg",
2082 "application/x-javascript",
2083 L"download",
2084 L"source.jpg"
2086 { // http://crbug.com/5772.
2087 __LINE__,
2088 "http://www.example.com/foo.tar.gz",
2092 "application/x-tar",
2093 L"download",
2094 L"foo.tar.gz"
2096 { // http://crbug.com/52250.
2097 __LINE__,
2098 "http://www.example.com/foo.tgz",
2102 "application/x-tar",
2103 L"download",
2104 L"foo.tgz"
2106 { // http://crbug.com/7337.
2107 __LINE__,
2108 "http://maged.lordaeron.org/blank.reg",
2112 "text/x-registry",
2113 L"download",
2114 L"blank.reg"
2117 __LINE__,
2118 "http://www.example.com/bar.tar",
2122 "application/x-tar",
2123 L"download",
2124 L"bar.tar"
2127 __LINE__,
2128 "http://www.example.com/bar.bogus",
2132 "application/x-tar",
2133 L"download",
2134 L"bar.bogus"
2136 { // http://crbug.com/20337
2137 __LINE__,
2138 "http://www.example.com/.download.txt",
2139 "filename=.download.txt",
2142 "text/plain",
2143 L"-download",
2144 L"download.txt"
2146 { // http://crbug.com/56855.
2147 __LINE__,
2148 "http://www.example.com/bar.sh",
2152 "application/x-sh",
2153 L"download",
2154 L"bar.sh"
2156 { // http://crbug.com/61571
2157 __LINE__,
2158 "http://www.example.com/npdf.php?fn=foobar.pdf",
2162 "text/plain",
2163 L"download",
2164 L"npdf" TXT_EXT
2166 { // Shouldn't overwrite C-D specified extension.
2167 __LINE__,
2168 "http://www.example.com/npdf.php?fn=foobar.pdf",
2169 "filename=foobar.jpg",
2172 "text/plain",
2173 L"download",
2174 L"foobar.jpg"
2176 { // http://crbug.com/87719
2177 __LINE__,
2178 "http://www.example.com/image.aspx?id=blargh",
2182 "image/jpeg",
2183 L"download",
2184 L"image" JPEG_EXT
2186 #if defined(OS_CHROMEOS)
2187 { // http://crosbug.com/26028
2188 __LINE__,
2189 "http://www.example.com/fooa%cc%88.txt",
2193 "image/jpeg",
2194 L"foo\xe4",
2195 L"foo\xe4.txt"
2197 #endif
2200 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(selection_tests); ++i)
2201 RunGenerateFileNameTestCase(&selection_tests[i]);
2203 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i)
2204 RunGenerateFileNameTestCase(&generation_tests[i]);
2206 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) {
2207 GenerateFilenameCase test_case = generation_tests[i];
2208 test_case.referrer_charset = "GBK";
2209 RunGenerateFileNameTestCase(&test_case);
2213 // This is currently a windows specific function.
2214 #if defined(OS_WIN)
2215 namespace {
2217 struct GetDirectoryListingEntryCase {
2218 const wchar_t* name;
2219 const char* raw_bytes;
2220 bool is_dir;
2221 int64 filesize;
2222 base::Time time;
2223 const char* expected;
2226 } // namespace
2227 TEST(NetUtilTest, GetDirectoryListingEntry) {
2228 const GetDirectoryListingEntryCase test_cases[] = {
2229 {L"Foo",
2231 false,
2232 10000,
2233 base::Time(),
2234 "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
2235 {L"quo\"tes",
2237 false,
2238 10000,
2239 base::Time(),
2240 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2241 "\n"},
2242 {L"quo\"tes",
2243 "quo\"tes",
2244 false,
2245 10000,
2246 base::Time(),
2247 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2248 "\n"},
2249 // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
2250 // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
2251 {L"\xD55C\xAE00.txt",
2253 false,
2254 10000,
2255 base::Time(),
2256 "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%ED%95%9C%EA%B8%80.txt\""
2257 ",0,\"9.8 kB\",\"\");</script>\n"},
2258 // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
2259 // a local or remote file in EUC-KR.
2260 {L"\xD55C\xAE00.txt",
2261 "\xC7\xD1\xB1\xDB.txt",
2262 false,
2263 10000,
2264 base::Time(),
2265 "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%C7%D1%B1%DB.txt\""
2266 ",0,\"9.8 kB\",\"\");</script>\n"},
2269 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
2270 const std::string results = GetDirectoryListingEntry(
2271 WideToUTF16(test_cases[i].name),
2272 test_cases[i].raw_bytes,
2273 test_cases[i].is_dir,
2274 test_cases[i].filesize,
2275 test_cases[i].time);
2276 EXPECT_EQ(test_cases[i].expected, results);
2280 #endif
2282 TEST(NetUtilTest, ParseHostAndPort) {
2283 const struct {
2284 const char* input;
2285 bool success;
2286 const char* expected_host;
2287 int expected_port;
2288 } tests[] = {
2289 // Valid inputs:
2290 {"foo:10", true, "foo", 10},
2291 {"foo", true, "foo", -1},
2293 "[1080:0:0:0:8:800:200C:4171]:11",
2294 true,
2295 "[1080:0:0:0:8:800:200C:4171]",
2298 // Invalid inputs:
2299 {"foo:bar", false, "", -1},
2300 {"foo:", false, "", -1},
2301 {":", false, "", -1},
2302 {":80", false, "", -1},
2303 {"", false, "", -1},
2304 {"porttoolong:300000", false, "", -1},
2305 {"usrname@host", false, "", -1},
2306 {"usrname:password@host", false, "", -1},
2307 {":password@host", false, "", -1},
2308 {":password@host:80", false, "", -1},
2309 {":password@host", false, "", -1},
2310 {"@host", false, "", -1},
2313 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2314 std::string host;
2315 int port;
2316 bool ok = ParseHostAndPort(tests[i].input, &host, &port);
2318 EXPECT_EQ(tests[i].success, ok);
2320 if (tests[i].success) {
2321 EXPECT_EQ(tests[i].expected_host, host);
2322 EXPECT_EQ(tests[i].expected_port, port);
2327 TEST(NetUtilTest, GetHostAndPort) {
2328 const struct {
2329 GURL url;
2330 const char* expected_host_and_port;
2331 } tests[] = {
2332 { GURL("http://www.foo.com/x"), "www.foo.com:80"},
2333 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2335 // For IPv6 literals should always include the brackets.
2336 { GURL("http://[1::2]/x"), "[1::2]:80"},
2337 { GURL("http://[::a]:33/x"), "[::a]:33"},
2339 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2340 std::string host_and_port = GetHostAndPort(tests[i].url);
2341 EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
2345 TEST(NetUtilTest, GetHostAndOptionalPort) {
2346 const struct {
2347 GURL url;
2348 const char* expected_host_and_port;
2349 } tests[] = {
2350 { GURL("http://www.foo.com/x"), "www.foo.com"},
2351 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2353 // For IPv6 literals should always include the brackets.
2354 { GURL("http://[1::2]/x"), "[1::2]"},
2355 { GURL("http://[::a]:33/x"), "[::a]:33"},
2357 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2358 std::string host_and_port = GetHostAndOptionalPort(tests[i].url);
2359 EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
2363 TEST(NetUtilTest, IPAddressToString) {
2364 uint8 addr1[4] = {0, 0, 0, 0};
2365 EXPECT_EQ("0.0.0.0", IPAddressToString(addr1, sizeof(addr1)));
2367 uint8 addr2[4] = {192, 168, 0, 1};
2368 EXPECT_EQ("192.168.0.1", IPAddressToString(addr2, sizeof(addr2)));
2370 uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
2371 EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3, sizeof(addr3)));
2374 TEST(NetUtilTest, IPAddressToStringWithPort) {
2375 uint8 addr1[4] = {0, 0, 0, 0};
2376 EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(addr1, sizeof(addr1), 3));
2378 uint8 addr2[4] = {192, 168, 0, 1};
2379 EXPECT_EQ("192.168.0.1:99",
2380 IPAddressToStringWithPort(addr2, sizeof(addr2), 99));
2382 uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
2383 EXPECT_EQ("[fedc:ba98::]:8080",
2384 IPAddressToStringWithPort(addr3, sizeof(addr3), 8080));
2387 TEST(NetUtilTest, NetAddressToString_IPv4) {
2388 const struct {
2389 uint8 addr[4];
2390 const char* result;
2391 } tests[] = {
2392 {{0, 0, 0, 0}, "0.0.0.0"},
2393 {{127, 0, 0, 1}, "127.0.0.1"},
2394 {{192, 168, 0, 1}, "192.168.0.1"},
2397 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2398 SockaddrStorage storage;
2399 MakeIPv4Address(tests[i].addr, 80, &storage);
2400 std::string result = NetAddressToString(storage.addr, storage.addr_len);
2401 EXPECT_EQ(std::string(tests[i].result), result);
2405 TEST(NetUtilTest, NetAddressToString_IPv6) {
2406 const struct {
2407 uint8 addr[16];
2408 const char* result;
2409 } tests[] = {
2410 {{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2411 0x98, 0x76, 0x54, 0x32, 0x10},
2412 "fedc:ba98:7654:3210:fedc:ba98:7654:3210"},
2415 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2416 SockaddrStorage storage;
2417 MakeIPv6Address(tests[i].addr, 80, &storage);
2418 EXPECT_EQ(std::string(tests[i].result),
2419 NetAddressToString(storage.addr, storage.addr_len));
2423 TEST(NetUtilTest, NetAddressToStringWithPort_IPv4) {
2424 uint8 addr[] = {127, 0, 0, 1};
2425 SockaddrStorage storage;
2426 MakeIPv4Address(addr, 166, &storage);
2427 std::string result = NetAddressToStringWithPort(storage.addr,
2428 storage.addr_len);
2429 EXPECT_EQ("127.0.0.1:166", result);
2432 TEST(NetUtilTest, NetAddressToStringWithPort_IPv6) {
2433 uint8 addr[] = {
2434 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2435 0x98, 0x76, 0x54, 0x32, 0x10
2437 SockaddrStorage storage;
2438 MakeIPv6Address(addr, 361, &storage);
2439 std::string result = NetAddressToStringWithPort(storage.addr,
2440 storage.addr_len);
2442 // May fail on systems that don't support IPv6.
2443 if (!result.empty())
2444 EXPECT_EQ("[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:361", result);
2447 TEST(NetUtilTest, GetHostName) {
2448 // We can't check the result of GetHostName() directly, since the result
2449 // will differ across machines. Our goal here is to simply exercise the
2450 // code path, and check that things "look about right".
2451 std::string hostname = GetHostName();
2452 EXPECT_FALSE(hostname.empty());
2455 TEST(NetUtilTest, FormatUrl) {
2456 FormatUrlTypes default_format_type = kFormatUrlOmitUsernamePassword;
2457 const UrlTestData tests[] = {
2458 {"Empty URL", "", "", default_format_type, UnescapeRule::NORMAL, L"", 0},
2460 {"Simple URL",
2461 "http://www.google.com/", "", default_format_type, UnescapeRule::NORMAL,
2462 L"http://www.google.com/", 7},
2464 {"With a port number and a reference",
2465 "http://www.google.com:8080/#\xE3\x82\xB0", "", default_format_type,
2466 UnescapeRule::NORMAL,
2467 L"http://www.google.com:8080/#\x30B0", 7},
2469 // -------- IDN tests --------
2470 {"Japanese IDN with ja",
2471 "http://xn--l8jvb1ey91xtjb.jp", "ja", default_format_type,
2472 UnescapeRule::NORMAL, L"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2474 {"Japanese IDN with en",
2475 "http://xn--l8jvb1ey91xtjb.jp", "en", default_format_type,
2476 UnescapeRule::NORMAL, L"http://xn--l8jvb1ey91xtjb.jp/", 7},
2478 {"Japanese IDN without any languages",
2479 "http://xn--l8jvb1ey91xtjb.jp", "", default_format_type,
2480 UnescapeRule::NORMAL,
2481 // Single script is safe for empty languages.
2482 L"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2484 {"mailto: with Japanese IDN",
2485 "mailto:foo@xn--l8jvb1ey91xtjb.jp", "ja", default_format_type,
2486 UnescapeRule::NORMAL,
2487 // GURL doesn't assume an email address's domain part as a host name.
2488 L"mailto:foo@xn--l8jvb1ey91xtjb.jp", 7},
2490 {"file: with Japanese IDN",
2491 "file://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type,
2492 UnescapeRule::NORMAL,
2493 L"file://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 7},
2495 {"ftp: with Japanese IDN",
2496 "ftp://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type,
2497 UnescapeRule::NORMAL,
2498 L"ftp://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 6},
2500 // -------- omit_username_password flag tests --------
2501 {"With username and password, omit_username_password=false",
2502 "http://user:passwd@example.com/foo", "",
2503 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2504 L"http://user:passwd@example.com/foo", 19},
2506 {"With username and password, omit_username_password=true",
2507 "http://user:passwd@example.com/foo", "", default_format_type,
2508 UnescapeRule::NORMAL, L"http://example.com/foo", 7},
2510 {"With username and no password",
2511 "http://user@example.com/foo", "", default_format_type,
2512 UnescapeRule::NORMAL, L"http://example.com/foo", 7},
2514 {"Just '@' without username and password",
2515 "http://@example.com/foo", "", default_format_type, UnescapeRule::NORMAL,
2516 L"http://example.com/foo", 7},
2518 // GURL doesn't think local-part of an email address is username for URL.
2519 {"mailto:, omit_username_password=true",
2520 "mailto:foo@example.com", "", default_format_type, UnescapeRule::NORMAL,
2521 L"mailto:foo@example.com", 7},
2523 // -------- unescape flag tests --------
2524 {"Do not unescape",
2525 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2526 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2527 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type,
2528 UnescapeRule::NONE,
2529 // GURL parses %-encoded hostnames into Punycode.
2530 L"http://xn--qcka1pmc.jp/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2531 L"?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", 7},
2533 {"Unescape normally",
2534 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2535 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2536 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type,
2537 UnescapeRule::NORMAL,
2538 L"http://xn--qcka1pmc.jp/\x30B0\x30FC\x30B0\x30EB"
2539 L"?q=\x30B0\x30FC\x30B0\x30EB", 7},
2541 {"Unescape normally including unescape spaces",
2542 "http://www.google.com/search?q=Hello%20World", "en", default_format_type,
2543 UnescapeRule::SPACES, L"http://www.google.com/search?q=Hello World", 7},
2546 {"unescape=true with some special characters",
2547 "http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", "",
2548 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2549 L"http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", 25},
2551 // Disabled: the resultant URL becomes "...user%253A:%2540passwd...".
2553 // -------- omit http: --------
2554 {"omit http with user name",
2555 "http://user@example.com/foo", "", kFormatUrlOmitAll,
2556 UnescapeRule::NORMAL, L"example.com/foo", 0},
2558 {"omit http",
2559 "http://www.google.com/", "en", kFormatUrlOmitHTTP,
2560 UnescapeRule::NORMAL, L"www.google.com/",
2563 {"omit http with https",
2564 "https://www.google.com/", "en", kFormatUrlOmitHTTP,
2565 UnescapeRule::NORMAL, L"https://www.google.com/",
2568 {"omit http starts with ftp.",
2569 "http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
2570 UnescapeRule::NORMAL, L"http://ftp.google.com/",
2573 // -------- omit trailing slash on bare hostname --------
2574 {"omit slash when it's the entire path",
2575 "http://www.google.com/", "en",
2576 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2577 L"http://www.google.com", 7},
2578 {"omit slash when there's a ref",
2579 "http://www.google.com/#ref", "en",
2580 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2581 L"http://www.google.com/#ref", 7},
2582 {"omit slash when there's a query",
2583 "http://www.google.com/?", "en",
2584 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2585 L"http://www.google.com/?", 7},
2586 {"omit slash when it's not the entire path",
2587 "http://www.google.com/foo", "en",
2588 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2589 L"http://www.google.com/foo", 7},
2590 {"omit slash for nonstandard URLs",
2591 "data:/", "en", kFormatUrlOmitTrailingSlashOnBareHostname,
2592 UnescapeRule::NORMAL, L"data:/", 5},
2593 {"omit slash for file URLs",
2594 "file:///", "en", kFormatUrlOmitTrailingSlashOnBareHostname,
2595 UnescapeRule::NORMAL, L"file:///", 7},
2597 // -------- view-source: --------
2598 {"view-source",
2599 "view-source:http://xn--qcka1pmc.jp/", "ja", default_format_type,
2600 UnescapeRule::NORMAL, L"view-source:http://\x30B0\x30FC\x30B0\x30EB.jp/",
2601 19},
2603 {"view-source of view-source",
2604 "view-source:view-source:http://xn--qcka1pmc.jp/", "ja",
2605 default_format_type, UnescapeRule::NORMAL,
2606 L"view-source:view-source:http://xn--qcka1pmc.jp/", 12},
2608 // view-source should omit http and trailing slash where non-view-source
2609 // would.
2610 {"view-source omit http",
2611 "view-source:http://a.b/c", "en", kFormatUrlOmitAll,
2612 UnescapeRule::NORMAL, L"view-source:a.b/c",
2613 12},
2614 {"view-source omit http starts with ftp.",
2615 "view-source:http://ftp.b/c", "en", kFormatUrlOmitAll,
2616 UnescapeRule::NORMAL, L"view-source:http://ftp.b/c",
2617 19},
2618 {"view-source omit slash when it's the entire path",
2619 "view-source:http://a.b/", "en", kFormatUrlOmitAll,
2620 UnescapeRule::NORMAL, L"view-source:a.b",
2621 12},
2624 for (size_t i = 0; i < arraysize(tests); ++i) {
2625 size_t prefix_len;
2626 base::string16 formatted = FormatUrl(
2627 GURL(tests[i].input), tests[i].languages, tests[i].format_types,
2628 tests[i].escape_rules, NULL, &prefix_len, NULL);
2629 EXPECT_EQ(WideToUTF16(tests[i].output), formatted) << tests[i].description;
2630 EXPECT_EQ(tests[i].prefix_len, prefix_len) << tests[i].description;
2634 TEST(NetUtilTest, FormatUrlParsed) {
2635 // No unescape case.
2636 url_parse::Parsed parsed;
2637 base::string16 formatted = FormatUrl(
2638 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2639 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2640 "ja", kFormatUrlOmitNothing, UnescapeRule::NONE, &parsed, NULL,
2641 NULL);
2642 EXPECT_EQ(WideToUTF16(
2643 L"http://%E3%82%B0:%E3%83%BC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2644 L"/%E3%82%B0/?q=%E3%82%B0#\x30B0"), formatted);
2645 EXPECT_EQ(WideToUTF16(L"%E3%82%B0"),
2646 formatted.substr(parsed.username.begin, parsed.username.len));
2647 EXPECT_EQ(WideToUTF16(L"%E3%83%BC"),
2648 formatted.substr(parsed.password.begin, parsed.password.len));
2649 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2650 formatted.substr(parsed.host.begin, parsed.host.len));
2651 EXPECT_EQ(WideToUTF16(L"8080"),
2652 formatted.substr(parsed.port.begin, parsed.port.len));
2653 EXPECT_EQ(WideToUTF16(L"/%E3%82%B0/"),
2654 formatted.substr(parsed.path.begin, parsed.path.len));
2655 EXPECT_EQ(WideToUTF16(L"q=%E3%82%B0"),
2656 formatted.substr(parsed.query.begin, parsed.query.len));
2657 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2658 formatted.substr(parsed.ref.begin, parsed.ref.len));
2660 // Unescape case.
2661 formatted = FormatUrl(
2662 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2663 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2664 "ja", kFormatUrlOmitNothing, UnescapeRule::NORMAL, &parsed, NULL,
2665 NULL);
2666 EXPECT_EQ(WideToUTF16(L"http://\x30B0:\x30FC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2667 L"/\x30B0/?q=\x30B0#\x30B0"), formatted);
2668 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2669 formatted.substr(parsed.username.begin, parsed.username.len));
2670 EXPECT_EQ(WideToUTF16(L"\x30FC"),
2671 formatted.substr(parsed.password.begin, parsed.password.len));
2672 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2673 formatted.substr(parsed.host.begin, parsed.host.len));
2674 EXPECT_EQ(WideToUTF16(L"8080"),
2675 formatted.substr(parsed.port.begin, parsed.port.len));
2676 EXPECT_EQ(WideToUTF16(L"/\x30B0/"),
2677 formatted.substr(parsed.path.begin, parsed.path.len));
2678 EXPECT_EQ(WideToUTF16(L"q=\x30B0"),
2679 formatted.substr(parsed.query.begin, parsed.query.len));
2680 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2681 formatted.substr(parsed.ref.begin, parsed.ref.len));
2683 // Omit_username_password + unescape case.
2684 formatted = FormatUrl(
2685 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2686 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2687 "ja", kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, &parsed,
2688 NULL, NULL);
2689 EXPECT_EQ(WideToUTF16(L"http://\x30B0\x30FC\x30B0\x30EB.jp:8080"
2690 L"/\x30B0/?q=\x30B0#\x30B0"), formatted);
2691 EXPECT_FALSE(parsed.username.is_valid());
2692 EXPECT_FALSE(parsed.password.is_valid());
2693 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2694 formatted.substr(parsed.host.begin, parsed.host.len));
2695 EXPECT_EQ(WideToUTF16(L"8080"),
2696 formatted.substr(parsed.port.begin, parsed.port.len));
2697 EXPECT_EQ(WideToUTF16(L"/\x30B0/"),
2698 formatted.substr(parsed.path.begin, parsed.path.len));
2699 EXPECT_EQ(WideToUTF16(L"q=\x30B0"),
2700 formatted.substr(parsed.query.begin, parsed.query.len));
2701 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2702 formatted.substr(parsed.ref.begin, parsed.ref.len));
2704 // View-source case.
2705 formatted =
2706 FormatUrl(GURL("view-source:http://user:passwd@host:81/path?query#ref"),
2707 std::string(),
2708 kFormatUrlOmitUsernamePassword,
2709 UnescapeRule::NORMAL,
2710 &parsed,
2711 NULL,
2712 NULL);
2713 EXPECT_EQ(WideToUTF16(L"view-source:http://host:81/path?query#ref"),
2714 formatted);
2715 EXPECT_EQ(WideToUTF16(L"view-source:http"),
2716 formatted.substr(parsed.scheme.begin, parsed.scheme.len));
2717 EXPECT_FALSE(parsed.username.is_valid());
2718 EXPECT_FALSE(parsed.password.is_valid());
2719 EXPECT_EQ(WideToUTF16(L"host"),
2720 formatted.substr(parsed.host.begin, parsed.host.len));
2721 EXPECT_EQ(WideToUTF16(L"81"),
2722 formatted.substr(parsed.port.begin, parsed.port.len));
2723 EXPECT_EQ(WideToUTF16(L"/path"),
2724 formatted.substr(parsed.path.begin, parsed.path.len));
2725 EXPECT_EQ(WideToUTF16(L"query"),
2726 formatted.substr(parsed.query.begin, parsed.query.len));
2727 EXPECT_EQ(WideToUTF16(L"ref"),
2728 formatted.substr(parsed.ref.begin, parsed.ref.len));
2730 // omit http case.
2731 formatted = FormatUrl(GURL("http://host:8000/a?b=c#d"),
2732 std::string(),
2733 kFormatUrlOmitHTTP,
2734 UnescapeRule::NORMAL,
2735 &parsed,
2736 NULL,
2737 NULL);
2738 EXPECT_EQ(WideToUTF16(L"host:8000/a?b=c#d"), formatted);
2739 EXPECT_FALSE(parsed.scheme.is_valid());
2740 EXPECT_FALSE(parsed.username.is_valid());
2741 EXPECT_FALSE(parsed.password.is_valid());
2742 EXPECT_EQ(WideToUTF16(L"host"),
2743 formatted.substr(parsed.host.begin, parsed.host.len));
2744 EXPECT_EQ(WideToUTF16(L"8000"),
2745 formatted.substr(parsed.port.begin, parsed.port.len));
2746 EXPECT_EQ(WideToUTF16(L"/a"),
2747 formatted.substr(parsed.path.begin, parsed.path.len));
2748 EXPECT_EQ(WideToUTF16(L"b=c"),
2749 formatted.substr(parsed.query.begin, parsed.query.len));
2750 EXPECT_EQ(WideToUTF16(L"d"),
2751 formatted.substr(parsed.ref.begin, parsed.ref.len));
2753 // omit http starts with ftp case.
2754 formatted = FormatUrl(GURL("http://ftp.host:8000/a?b=c#d"),
2755 std::string(),
2756 kFormatUrlOmitHTTP,
2757 UnescapeRule::NORMAL,
2758 &parsed,
2759 NULL,
2760 NULL);
2761 EXPECT_EQ(WideToUTF16(L"http://ftp.host:8000/a?b=c#d"), formatted);
2762 EXPECT_TRUE(parsed.scheme.is_valid());
2763 EXPECT_FALSE(parsed.username.is_valid());
2764 EXPECT_FALSE(parsed.password.is_valid());
2765 EXPECT_EQ(WideToUTF16(L"http"),
2766 formatted.substr(parsed.scheme.begin, parsed.scheme.len));
2767 EXPECT_EQ(WideToUTF16(L"ftp.host"),
2768 formatted.substr(parsed.host.begin, parsed.host.len));
2769 EXPECT_EQ(WideToUTF16(L"8000"),
2770 formatted.substr(parsed.port.begin, parsed.port.len));
2771 EXPECT_EQ(WideToUTF16(L"/a"),
2772 formatted.substr(parsed.path.begin, parsed.path.len));
2773 EXPECT_EQ(WideToUTF16(L"b=c"),
2774 formatted.substr(parsed.query.begin, parsed.query.len));
2775 EXPECT_EQ(WideToUTF16(L"d"),
2776 formatted.substr(parsed.ref.begin, parsed.ref.len));
2778 // omit http starts with 'f' case.
2779 formatted = FormatUrl(GURL("http://f/"),
2780 std::string(),
2781 kFormatUrlOmitHTTP,
2782 UnescapeRule::NORMAL,
2783 &parsed,
2784 NULL,
2785 NULL);
2786 EXPECT_EQ(WideToUTF16(L"f/"), formatted);
2787 EXPECT_FALSE(parsed.scheme.is_valid());
2788 EXPECT_FALSE(parsed.username.is_valid());
2789 EXPECT_FALSE(parsed.password.is_valid());
2790 EXPECT_FALSE(parsed.port.is_valid());
2791 EXPECT_TRUE(parsed.path.is_valid());
2792 EXPECT_FALSE(parsed.query.is_valid());
2793 EXPECT_FALSE(parsed.ref.is_valid());
2794 EXPECT_EQ(WideToUTF16(L"f"),
2795 formatted.substr(parsed.host.begin, parsed.host.len));
2796 EXPECT_EQ(WideToUTF16(L"/"),
2797 formatted.substr(parsed.path.begin, parsed.path.len));
2800 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2801 // results in the original GURL, for each ASCII character in the path.
2802 TEST(NetUtilTest, FormatUrlRoundTripPathASCII) {
2803 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2804 GURL url(std::string("http://www.google.com/") +
2805 static_cast<char>(test_char));
2806 size_t prefix_len;
2807 base::string16 formatted = FormatUrl(url,
2808 std::string(),
2809 kFormatUrlOmitUsernamePassword,
2810 UnescapeRule::NORMAL,
2811 NULL,
2812 &prefix_len,
2813 NULL);
2814 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2818 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2819 // results in the original GURL, for each escaped ASCII character in the path.
2820 TEST(NetUtilTest, FormatUrlRoundTripPathEscaped) {
2821 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2822 std::string original_url("http://www.google.com/");
2823 original_url.push_back('%');
2824 original_url.append(base::HexEncode(&test_char, 1));
2826 GURL url(original_url);
2827 size_t prefix_len;
2828 base::string16 formatted = FormatUrl(url,
2829 std::string(),
2830 kFormatUrlOmitUsernamePassword,
2831 UnescapeRule::NORMAL,
2832 NULL,
2833 &prefix_len,
2834 NULL);
2835 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2839 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2840 // results in the original GURL, for each ASCII character in the query.
2841 TEST(NetUtilTest, FormatUrlRoundTripQueryASCII) {
2842 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2843 GURL url(std::string("http://www.google.com/?") +
2844 static_cast<char>(test_char));
2845 size_t prefix_len;
2846 base::string16 formatted = FormatUrl(url,
2847 std::string(),
2848 kFormatUrlOmitUsernamePassword,
2849 UnescapeRule::NORMAL,
2850 NULL,
2851 &prefix_len,
2852 NULL);
2853 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2857 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2858 // only results in a different GURL for certain characters.
2859 TEST(NetUtilTest, FormatUrlRoundTripQueryEscaped) {
2860 // A full list of characters which FormatURL should unescape and GURL should
2861 // not escape again, when they appear in a query string.
2862 const char* kUnescapedCharacters =
2863 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~";
2864 for (unsigned char test_char = 0; test_char < 128; ++test_char) {
2865 std::string original_url("http://www.google.com/?");
2866 original_url.push_back('%');
2867 original_url.append(base::HexEncode(&test_char, 1));
2869 GURL url(original_url);
2870 size_t prefix_len;
2871 base::string16 formatted = FormatUrl(url,
2872 std::string(),
2873 kFormatUrlOmitUsernamePassword,
2874 UnescapeRule::NORMAL,
2875 NULL,
2876 &prefix_len,
2877 NULL);
2879 if (test_char &&
2880 strchr(kUnescapedCharacters, static_cast<char>(test_char))) {
2881 EXPECT_NE(url.spec(), GURL(formatted).spec());
2882 } else {
2883 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2888 TEST(NetUtilTest, FormatUrlWithOffsets) {
2889 const AdjustOffsetCase null_cases[] = {
2890 {0, base::string16::npos},
2892 CheckAdjustedOffsets(std::string(), "en", kFormatUrlOmitNothing,
2893 UnescapeRule::NORMAL, null_cases, arraysize(null_cases), NULL);
2895 const AdjustOffsetCase basic_cases[] = {
2896 {0, 0},
2897 {3, 3},
2898 {5, 5},
2899 {6, 6},
2900 {13, 13},
2901 {21, 21},
2902 {22, 22},
2903 {23, 23},
2904 {25, 25},
2905 {26, base::string16::npos},
2906 {500000, base::string16::npos},
2907 {base::string16::npos, base::string16::npos},
2909 const size_t basic_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2910 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
2911 CheckAdjustedOffsets("http://www.google.com/foo/", "en",
2912 kFormatUrlOmitNothing, UnescapeRule::NORMAL, basic_cases,
2913 arraysize(basic_cases), basic_offsets);
2915 const AdjustOffsetCase omit_auth_cases_1[] = {
2916 {6, 6},
2917 {7, base::string16::npos},
2918 {8, base::string16::npos},
2919 {10, base::string16::npos},
2920 {12, base::string16::npos},
2921 {14, base::string16::npos},
2922 {15, 7},
2923 {25, 17},
2925 const size_t omit_auth_offsets_1[] = {0, 1, 2, 3, 4, 5, 6, kNpos, kNpos,
2926 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2927 16, 17, 18, 19, 20, 21};
2928 CheckAdjustedOffsets("http://foo:bar@www.google.com/", "en",
2929 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, omit_auth_cases_1,
2930 arraysize(omit_auth_cases_1), omit_auth_offsets_1);
2932 const AdjustOffsetCase omit_auth_cases_2[] = {
2933 {9, base::string16::npos},
2934 {11, 7},
2936 const size_t omit_auth_offsets_2[] = {0, 1, 2, 3, 4, 5, 6, kNpos, kNpos,
2937 kNpos, kNpos, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
2938 CheckAdjustedOffsets("http://foo@www.google.com/", "en",
2939 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, omit_auth_cases_2,
2940 arraysize(omit_auth_cases_2), omit_auth_offsets_2);
2942 // "http://foo\x30B0:\x30B0bar@www.google.com"
2943 const AdjustOffsetCase dont_omit_auth_cases[] = {
2944 {0, 0},
2945 /*{3, base::string16::npos},
2946 {7, 0},
2947 {11, 4},
2948 {12, base::string16::npos},
2949 {20, 5},
2950 {24, 9},*/
2952 const size_t dont_omit_auth_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2953 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 11, 12, kNpos,
2954 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 13, 14, 15, 16, 17, 18,
2955 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
2956 CheckAdjustedOffsets("http://foo%E3%82%B0:%E3%82%B0bar@www.google.com/", "en",
2957 kFormatUrlOmitNothing, UnescapeRule::NORMAL, dont_omit_auth_cases,
2958 arraysize(dont_omit_auth_cases), dont_omit_auth_offsets);
2960 const AdjustOffsetCase view_source_cases[] = {
2961 {0, 0},
2962 {3, 3},
2963 {11, 11},
2964 {12, 12},
2965 {13, 13},
2966 {18, 18},
2967 {19, base::string16::npos},
2968 {20, base::string16::npos},
2969 {23, 19},
2970 {26, 22},
2971 {base::string16::npos, base::string16::npos},
2973 const size_t view_source_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
2974 12, 13, 14, 15, 16, 17, 18, kNpos, kNpos, kNpos, kNpos, 19, 20, 21, 22,
2975 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33};
2976 CheckAdjustedOffsets("view-source:http://foo@www.google.com/", "en",
2977 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, view_source_cases,
2978 arraysize(view_source_cases), view_source_offsets);
2980 // "http://\x671d\x65e5\x3042\x3055\x3072.jp/foo/"
2981 const AdjustOffsetCase idn_hostname_cases_1[] = {
2982 {8, base::string16::npos},
2983 {16, base::string16::npos},
2984 {24, base::string16::npos},
2985 {25, 12},
2986 {30, 17},
2988 const size_t idn_hostname_offsets_1[] = {0, 1, 2, 3, 4, 5, 6, 7, kNpos, kNpos,
2989 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2990 kNpos, kNpos, kNpos, kNpos, kNpos, 12, 13, 14, 15, 16, 17, 18, 19};
2991 CheckAdjustedOffsets("http://xn--l8jvb1ey91xtjb.jp/foo/", "ja",
2992 kFormatUrlOmitNothing, UnescapeRule::NORMAL, idn_hostname_cases_1,
2993 arraysize(idn_hostname_cases_1), idn_hostname_offsets_1);
2995 // "http://test.\x89c6\x9891.\x5317\x4eac\x5927\x5b78.test/"
2996 const AdjustOffsetCase idn_hostname_cases_2[] = {
2997 {7, 7},
2998 {9, 9},
2999 {11, 11},
3000 {12, 12},
3001 {13, base::string16::npos},
3002 {23, base::string16::npos},
3003 {24, 14},
3004 {25, 15},
3005 {26, base::string16::npos},
3006 {32, base::string16::npos},
3007 {41, 19},
3008 {42, 20},
3009 {45, 23},
3010 {46, 24},
3011 {47, base::string16::npos},
3012 {base::string16::npos, base::string16::npos},
3014 const size_t idn_hostname_offsets_2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
3015 12, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
3016 kNpos, 14, 15, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
3017 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 19, 20, 21, 22, 23, 24};
3018 CheckAdjustedOffsets("http://test.xn--cy2a840a.xn--1lq90ic7f1rc.test/",
3019 "zh-CN", kFormatUrlOmitNothing, UnescapeRule::NORMAL,
3020 idn_hostname_cases_2, arraysize(idn_hostname_cases_2),
3021 idn_hostname_offsets_2);
3023 // "http://www.google.com/foo bar/\x30B0\x30FC\x30B0\x30EB"
3024 const AdjustOffsetCase unescape_cases[] = {
3025 {25, 25},
3026 {26, base::string16::npos},
3027 {27, base::string16::npos},
3028 {28, 26},
3029 {35, base::string16::npos},
3030 {41, 31},
3031 {59, 33},
3032 {60, base::string16::npos},
3033 {67, base::string16::npos},
3034 {68, base::string16::npos},
3036 const size_t unescape_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
3037 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, kNpos, kNpos, 26, 27,
3038 28, 29, 30, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 31,
3039 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 32, kNpos, kNpos,
3040 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 33, kNpos, kNpos, kNpos, kNpos,
3041 kNpos, kNpos, kNpos, kNpos};
3042 CheckAdjustedOffsets(
3043 "http://www.google.com/foo%20bar/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB",
3044 "en", kFormatUrlOmitNothing, UnescapeRule::SPACES, unescape_cases,
3045 arraysize(unescape_cases), unescape_offsets);
3047 // "http://www.google.com/foo.html#\x30B0\x30B0z"
3048 const AdjustOffsetCase ref_cases[] = {
3049 {30, 30},
3050 {31, 31},
3051 {32, base::string16::npos},
3052 {34, 32},
3053 {35, base::string16::npos},
3054 {37, 33},
3055 {38, base::string16::npos},
3057 const size_t ref_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
3058 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3059 kNpos, kNpos, 32, kNpos, kNpos, 33};
3060 CheckAdjustedOffsets(
3061 "http://www.google.com/foo.html#\xE3\x82\xB0\xE3\x82\xB0z", "en",
3062 kFormatUrlOmitNothing, UnescapeRule::NORMAL, ref_cases,
3063 arraysize(ref_cases), ref_offsets);
3065 const AdjustOffsetCase omit_http_cases[] = {
3066 {0, base::string16::npos},
3067 {3, base::string16::npos},
3068 {7, 0},
3069 {8, 1},
3071 const size_t omit_http_offsets[] = {kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
3072 kNpos, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
3073 CheckAdjustedOffsets("http://www.google.com/", "en",
3074 kFormatUrlOmitHTTP, UnescapeRule::NORMAL, omit_http_cases,
3075 arraysize(omit_http_cases), omit_http_offsets);
3077 const AdjustOffsetCase omit_http_start_with_ftp_cases[] = {
3078 {0, 0},
3079 {3, 3},
3080 {8, 8},
3082 const size_t omit_http_start_with_ftp_offsets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
3083 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
3084 CheckAdjustedOffsets("http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
3085 UnescapeRule::NORMAL, omit_http_start_with_ftp_cases,
3086 arraysize(omit_http_start_with_ftp_cases),
3087 omit_http_start_with_ftp_offsets);
3089 const AdjustOffsetCase omit_all_cases[] = {
3090 {12, 0},
3091 {13, 1},
3092 {0, base::string16::npos},
3093 {3, base::string16::npos},
3095 const size_t omit_all_offsets[] = {kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
3096 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, kNpos};
3097 CheckAdjustedOffsets("http://user@foo.com/", "en", kFormatUrlOmitAll,
3098 UnescapeRule::NORMAL, omit_all_cases,
3099 arraysize(omit_all_cases), omit_all_offsets);
3102 TEST(NetUtilTest, SimplifyUrlForRequest) {
3103 struct {
3104 const char* input_url;
3105 const char* expected_simplified_url;
3106 } tests[] = {
3108 // Reference section should be stripped.
3109 "http://www.google.com:78/foobar?query=1#hash",
3110 "http://www.google.com:78/foobar?query=1",
3113 // Reference section can itself contain #.
3114 "http://192.168.0.1?query=1#hash#10#11#13#14",
3115 "http://192.168.0.1?query=1",
3117 { // Strip username/password.
3118 "http://user:pass@google.com",
3119 "http://google.com/",
3121 { // Strip both the reference and the username/password.
3122 "http://user:pass@google.com:80/sup?yo#X#X",
3123 "http://google.com/sup?yo",
3125 { // Try an HTTPS URL -- strip both the reference and the username/password.
3126 "https://user:pass@google.com:80/sup?yo#X#X",
3127 "https://google.com:80/sup?yo",
3129 { // Try an FTP URL -- strip both the reference and the username/password.
3130 "ftp://user:pass@google.com:80/sup?yo#X#X",
3131 "ftp://google.com:80/sup?yo",
3133 { // Try an nonstandard URL
3134 "foobar://user:pass@google.com:80/sup?yo#X#X",
3135 "foobar://user:pass@google.com:80/sup?yo#X#X",
3138 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3139 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
3140 tests[i].input_url));
3141 GURL input_url(GURL(tests[i].input_url));
3142 GURL expected_url(GURL(tests[i].expected_simplified_url));
3143 EXPECT_EQ(expected_url, SimplifyUrlForRequest(input_url));
3147 TEST(NetUtilTest, SetExplicitlyAllowedPortsTest) {
3148 std::string invalid[] = { "1,2,a", "'1','2'", "1, 2, 3", "1 0,11,12" };
3149 std::string valid[] = { "", "1", "1,2", "1,2,3", "10,11,12,13" };
3151 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(invalid); ++i) {
3152 SetExplicitlyAllowedPorts(invalid[i]);
3153 EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts()));
3156 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid); ++i) {
3157 SetExplicitlyAllowedPorts(valid[i]);
3158 EXPECT_EQ(i, GetCountOfExplicitlyAllowedPorts());
3162 TEST(NetUtilTest, GetHostOrSpecFromURL) {
3163 EXPECT_EQ("example.com",
3164 GetHostOrSpecFromURL(GURL("http://example.com/test")));
3165 EXPECT_EQ("example.com",
3166 GetHostOrSpecFromURL(GURL("http://example.com./test")));
3167 EXPECT_EQ("file:///tmp/test.html",
3168 GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
3171 TEST(NetUtilTest, GetAddressFamily) {
3172 IPAddressNumber number;
3173 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number));
3174 EXPECT_EQ(ADDRESS_FAMILY_IPV4, GetAddressFamily(number));
3175 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
3176 EXPECT_EQ(ADDRESS_FAMILY_IPV6, GetAddressFamily(number));
3179 // Test that invalid IP literals fail to parse.
3180 TEST(NetUtilTest, ParseIPLiteralToNumber_FailParse) {
3181 IPAddressNumber number;
3183 EXPECT_FALSE(ParseIPLiteralToNumber("bad value", &number));
3184 EXPECT_FALSE(ParseIPLiteralToNumber("bad:value", &number));
3185 EXPECT_FALSE(ParseIPLiteralToNumber(std::string(), &number));
3186 EXPECT_FALSE(ParseIPLiteralToNumber("192.168.0.1:30", &number));
3187 EXPECT_FALSE(ParseIPLiteralToNumber(" 192.168.0.1 ", &number));
3188 EXPECT_FALSE(ParseIPLiteralToNumber("[::1]", &number));
3191 // Test parsing an IPv4 literal.
3192 TEST(NetUtilTest, ParseIPLiteralToNumber_IPv4) {
3193 IPAddressNumber number;
3194 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number));
3195 EXPECT_EQ("192,168,0,1", DumpIPNumber(number));
3196 EXPECT_EQ("192.168.0.1", IPAddressToString(number));
3199 // Test parsing an IPv6 literal.
3200 TEST(NetUtilTest, ParseIPLiteralToNumber_IPv6) {
3201 IPAddressNumber number;
3202 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
3203 EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number));
3204 EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number));
3207 // Test mapping an IPv4 address to an IPv6 address.
3208 TEST(NetUtilTest, ConvertIPv4NumberToIPv6Number) {
3209 IPAddressNumber ipv4_number;
3210 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
3212 IPAddressNumber ipv6_number =
3213 ConvertIPv4NumberToIPv6Number(ipv4_number);
3215 // ::ffff:192.168.0.1
3216 EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
3217 DumpIPNumber(ipv6_number));
3218 EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number));
3221 TEST(NetUtilTest, IsIPv4Mapped) {
3222 IPAddressNumber ipv4_number;
3223 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
3224 EXPECT_FALSE(IsIPv4Mapped(ipv4_number));
3226 IPAddressNumber ipv6_number;
3227 EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number));
3228 EXPECT_FALSE(IsIPv4Mapped(ipv6_number));
3230 IPAddressNumber ipv4mapped_number;
3231 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
3232 EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number));
3235 TEST(NetUtilTest, ConvertIPv4MappedToIPv4) {
3236 IPAddressNumber ipv4mapped_number;
3237 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
3238 IPAddressNumber expected;
3239 EXPECT_TRUE(ParseIPLiteralToNumber("1.1.0.1", &expected));
3240 IPAddressNumber result = ConvertIPv4MappedToIPv4(ipv4mapped_number);
3241 EXPECT_EQ(expected, result);
3244 // Test parsing invalid CIDR notation literals.
3245 TEST(NetUtilTest, ParseCIDRBlock_Invalid) {
3246 const char* bad_literals[] = {
3247 "foobar",
3249 "192.168.0.1",
3250 "::1",
3251 "/",
3252 "/1",
3253 "1",
3254 "192.168.1.1/-1",
3255 "192.168.1.1/33",
3256 "::1/-3",
3257 "a::3/129",
3258 "::1/x",
3259 "192.168.0.1//11"
3262 for (size_t i = 0; i < arraysize(bad_literals); ++i) {
3263 IPAddressNumber ip_number;
3264 size_t prefix_length_in_bits;
3266 EXPECT_FALSE(ParseCIDRBlock(bad_literals[i],
3267 &ip_number,
3268 &prefix_length_in_bits));
3272 // Test parsing a valid CIDR notation literal.
3273 TEST(NetUtilTest, ParseCIDRBlock_Valid) {
3274 IPAddressNumber ip_number;
3275 size_t prefix_length_in_bits;
3277 EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
3278 &ip_number,
3279 &prefix_length_in_bits));
3281 EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number));
3282 EXPECT_EQ(11u, prefix_length_in_bits);
3285 TEST(NetUtilTest, IPNumberMatchesPrefix) {
3286 struct {
3287 const char* cidr_literal;
3288 const char* ip_literal;
3289 bool expected_to_match;
3290 } tests[] = {
3291 // IPv4 prefix with IPv4 inputs.
3293 "10.10.1.32/27",
3294 "10.10.1.44",
3295 true
3298 "10.10.1.32/27",
3299 "10.10.1.90",
3300 false
3303 "10.10.1.32/27",
3304 "10.10.1.90",
3305 false
3308 // IPv6 prefix with IPv6 inputs.
3310 "2001:db8::/32",
3311 "2001:DB8:3:4::5",
3312 true
3315 "2001:db8::/32",
3316 "2001:c8::",
3317 false
3320 // IPv6 prefix with IPv4 inputs.
3322 "2001:db8::/33",
3323 "192.168.0.1",
3324 false
3327 "::ffff:192.168.0.1/112",
3328 "192.168.33.77",
3329 true
3332 // IPv4 prefix with IPv6 inputs.
3334 "10.11.33.44/16",
3335 "::ffff:0a0b:89",
3336 true
3339 "10.11.33.44/16",
3340 "::ffff:10.12.33.44",
3341 false
3344 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3345 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i,
3346 tests[i].cidr_literal,
3347 tests[i].ip_literal));
3349 IPAddressNumber ip_number;
3350 EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number));
3352 IPAddressNumber ip_prefix;
3353 size_t prefix_length_in_bits;
3355 EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal,
3356 &ip_prefix,
3357 &prefix_length_in_bits));
3359 EXPECT_EQ(tests[i].expected_to_match,
3360 IPNumberMatchesPrefix(ip_number,
3361 ip_prefix,
3362 prefix_length_in_bits));
3366 TEST(NetUtilTest, IsLocalhost) {
3367 EXPECT_TRUE(net::IsLocalhost("localhost"));
3368 EXPECT_TRUE(net::IsLocalhost("localhost.localdomain"));
3369 EXPECT_TRUE(net::IsLocalhost("localhost6"));
3370 EXPECT_TRUE(net::IsLocalhost("localhost6.localdomain6"));
3371 EXPECT_TRUE(net::IsLocalhost("127.0.0.1"));
3372 EXPECT_TRUE(net::IsLocalhost("127.0.1.0"));
3373 EXPECT_TRUE(net::IsLocalhost("127.1.0.0"));
3374 EXPECT_TRUE(net::IsLocalhost("127.0.0.255"));
3375 EXPECT_TRUE(net::IsLocalhost("127.0.255.0"));
3376 EXPECT_TRUE(net::IsLocalhost("127.255.0.0"));
3377 EXPECT_TRUE(net::IsLocalhost("::1"));
3378 EXPECT_TRUE(net::IsLocalhost("0:0:0:0:0:0:0:1"));
3380 EXPECT_FALSE(net::IsLocalhost("localhostx"));
3381 EXPECT_FALSE(net::IsLocalhost("foo.localdomain"));
3382 EXPECT_FALSE(net::IsLocalhost("localhost6x"));
3383 EXPECT_FALSE(net::IsLocalhost("localhost.localdomain6"));
3384 EXPECT_FALSE(net::IsLocalhost("localhost6.localdomain"));
3385 EXPECT_FALSE(net::IsLocalhost("127.0.0.1.1"));
3386 EXPECT_FALSE(net::IsLocalhost(".127.0.0.255"));
3387 EXPECT_FALSE(net::IsLocalhost("::2"));
3388 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3389 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:1:0:0:1"));
3390 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3391 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:0:0:0:0:1"));
3394 // Verify GetNetworkList().
3395 TEST(NetUtilTest, GetNetworkList) {
3396 NetworkInterfaceList list;
3397 ASSERT_TRUE(GetNetworkList(&list));
3399 for (NetworkInterfaceList::iterator it = list.begin();
3400 it != list.end(); ++it) {
3401 // Verify that the name is not empty.
3402 EXPECT_FALSE(it->name.empty());
3404 // Verify that the address is correct.
3405 EXPECT_TRUE(it->address.size() == kIPv4AddressSize ||
3406 it->address.size() == kIPv6AddressSize)
3407 << "Invalid address of size " << it->address.size();
3408 bool all_zeroes = true;
3409 for (size_t i = 0; i < it->address.size(); ++i) {
3410 if (it->address[i] != 0) {
3411 all_zeroes = false;
3412 break;
3415 EXPECT_FALSE(all_zeroes);
3419 static const base::FilePath::CharType* kSafePortableBasenames[] = {
3420 FILE_PATH_LITERAL("a"),
3421 FILE_PATH_LITERAL("a.txt"),
3422 FILE_PATH_LITERAL("a b.txt"),
3423 FILE_PATH_LITERAL("a-b.txt"),
3424 FILE_PATH_LITERAL("My Computer"),
3425 FILE_PATH_LITERAL(" Computer"),
3428 static const base::FilePath::CharType* kUnsafePortableBasenames[] = {
3429 FILE_PATH_LITERAL(""),
3430 FILE_PATH_LITERAL("."),
3431 FILE_PATH_LITERAL(".."),
3432 FILE_PATH_LITERAL("..."),
3433 FILE_PATH_LITERAL("con"),
3434 FILE_PATH_LITERAL("con.zip"),
3435 FILE_PATH_LITERAL("NUL"),
3436 FILE_PATH_LITERAL("NUL.zip"),
3437 FILE_PATH_LITERAL(".a"),
3438 FILE_PATH_LITERAL("a."),
3439 FILE_PATH_LITERAL("a\"a"),
3440 FILE_PATH_LITERAL("a<a"),
3441 FILE_PATH_LITERAL("a>a"),
3442 FILE_PATH_LITERAL("a?a"),
3443 FILE_PATH_LITERAL("a/"),
3444 FILE_PATH_LITERAL("a\\"),
3445 FILE_PATH_LITERAL("a "),
3446 FILE_PATH_LITERAL("a . ."),
3447 FILE_PATH_LITERAL("My Computer.{a}"),
3448 FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"),
3449 #if !defined(OS_WIN)
3450 FILE_PATH_LITERAL("a\\a"),
3451 #endif
3454 static const base::FilePath::CharType* kSafePortableRelativePaths[] = {
3455 FILE_PATH_LITERAL("a/a"),
3456 #if defined(OS_WIN)
3457 FILE_PATH_LITERAL("a\\a"),
3458 #endif
3461 TEST(NetUtilTest, IsSafePortableBasename) {
3462 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
3463 EXPECT_TRUE(IsSafePortableBasename(base::FilePath(
3464 kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
3466 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
3467 EXPECT_FALSE(IsSafePortableBasename(base::FilePath(
3468 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
3470 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
3471 EXPECT_FALSE(IsSafePortableBasename(base::FilePath(
3472 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
3476 TEST(NetUtilTest, IsSafePortableRelativePath) {
3477 base::FilePath safe_dirname(FILE_PATH_LITERAL("a"));
3478 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
3479 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3480 kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
3481 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
3482 kSafePortableBasenames[i])))) << kSafePortableBasenames[i];
3484 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
3485 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3486 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
3487 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
3488 kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i];
3490 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
3491 EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
3492 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
3493 if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
3494 EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append(
3495 base::FilePath(kUnsafePortableBasenames[i]))))
3496 << kUnsafePortableBasenames[i];
3501 struct NonUniqueNameTestData {
3502 bool is_unique;
3503 const char* hostname;
3506 // Google Test pretty-printer.
3507 void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
3508 ASSERT_TRUE(data.hostname);
3509 *os << " hostname: " << testing::PrintToString(data.hostname)
3510 << "; is_unique: " << testing::PrintToString(data.is_unique);
3513 const NonUniqueNameTestData kNonUniqueNameTestData[] = {
3514 // Domains under ICANN-assigned domains.
3515 { true, "google.com" },
3516 { true, "google.co.uk" },
3517 // Domains under private registries.
3518 { true, "appspot.com" },
3519 { true, "test.appspot.com" },
3520 // Unreserved IPv4 addresses (in various forms).
3521 { true, "8.8.8.8" },
3522 { true, "99.64.0.0" },
3523 { true, "212.15.0.0" },
3524 { true, "212.15" },
3525 { true, "212.15.0" },
3526 { true, "3557752832" },
3527 // Reserved IPv4 addresses (in various forms).
3528 { false, "192.168.0.0" },
3529 { false, "192.168.0.6" },
3530 { false, "10.0.0.5" },
3531 { false, "10.0" },
3532 { false, "10.0.0" },
3533 { false, "3232235526" },
3534 // Unreserved IPv6 addresses.
3535 { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3536 { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
3537 // Reserved IPv6 addresses.
3538 { false, "::192.9.5.5" },
3539 { false, "FEED::BEEF" },
3540 { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3541 // 'internal'/non-IANA assigned domains.
3542 { false, "intranet" },
3543 { false, "intranet." },
3544 { false, "intranet.example" },
3545 { false, "host.intranet.example" },
3546 // gTLDs under discussion, but not yet assigned.
3547 { false, "intranet.corp" },
3548 { false, "example.tech" },
3549 { false, "intranet.internal" },
3550 // Invalid host names are treated as unique - but expected to be
3551 // filtered out before then.
3552 { true, "junk)(£)$*!@~#" },
3553 { true, "w$w.example.com" },
3554 { true, "nocolonsallowed:example" },
3555 { true, "[::4.5.6.9]" },
3558 class NetUtilNonUniqueNameTest
3559 : public testing::TestWithParam<NonUniqueNameTestData> {
3560 public:
3561 virtual ~NetUtilNonUniqueNameTest() {}
3563 protected:
3564 bool IsUnique(const std::string& hostname) {
3565 return !IsHostnameNonUnique(hostname);
3569 // Test that internal/non-unique names are properly identified as such, but
3570 // that IP addresses and hosts beneath registry-controlled domains are flagged
3571 // as unique names.
3572 TEST_P(NetUtilNonUniqueNameTest, IsHostnameNonUnique) {
3573 const NonUniqueNameTestData& test_data = GetParam();
3575 EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
3578 INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest,
3579 testing::ValuesIn(kNonUniqueNameTestData));
3581 } // namespace net