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"
11 #include "base/files/file_path.h"
12 #include "base/format_macros.h"
13 #include "base/scoped_native_library.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/sys_byteorder.h"
20 #include "base/time/time.h"
21 #include "testing/gtest/include/gtest/gtest.h"
27 #include "base/win/windows_version.h"
28 #elif !defined(OS_ANDROID)
32 using base::ASCIIToUTF16
;
33 using base::WideToUTF16
;
39 static const size_t kNpos
= base::string16::npos
;
42 const char* header_name
;
46 struct HeaderParamCase
{
47 const char* header_name
;
48 const char* param_name
;
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",
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
[] = {
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,
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,
84 {true, true, true, true, true,
85 true, true, true, true, true,
86 true, true, true, true, true,
87 true, true, true, true, true,
90 {true, true, true, true, true,
91 true, true, true, true, true,
92 true, true, true, true, true,
93 true, true, true, true, true,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
210 // TODO(jungshik) : Add examples with Cyrillic letters
211 // only used in some languages written in Cyrillic.
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
313 // One that's really long that will force a buffer realloc
314 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
316 L
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
318 {true, true, true, true, true,
319 true, true, true, true, true,
320 true, true, true, true, true,
321 true, true, true, true, 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,
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,
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,
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,
376 struct AdjustOffsetCase
{
378 size_t output_offset
;
381 struct CompliantHostCase
{
383 const char* desired_tld
;
384 bool expected_output
;
388 const char* description
;
390 const char* languages
;
391 FormatUrlTypes format_types
;
392 UnescapeRule::Type escape_rules
;
393 const wchar_t* output
; // Use |wchar_t| to handle Unicode constants easily.
397 // Fills in sockaddr for the given 32-bit address (IPv4.)
398 // |bytes| should be an array of length 4.
399 void MakeIPv4Address(const uint8
* bytes
, int port
, SockaddrStorage
* storage
) {
400 memset(&storage
->addr_storage
, 0, sizeof(storage
->addr_storage
));
401 storage
->addr_len
= sizeof(struct sockaddr_in
);
402 struct sockaddr_in
* addr4
= reinterpret_cast<sockaddr_in
*>(storage
->addr
);
403 addr4
->sin_port
= base::HostToNet16(port
);
404 addr4
->sin_family
= AF_INET
;
405 memcpy(&addr4
->sin_addr
, bytes
, 4);
408 // Fills in sockaddr for the given 128-bit address (IPv6.)
409 // |bytes| should be an array of length 16.
410 void MakeIPv6Address(const uint8
* bytes
, int port
, SockaddrStorage
* storage
) {
411 memset(&storage
->addr_storage
, 0, sizeof(storage
->addr_storage
));
412 storage
->addr_len
= sizeof(struct sockaddr_in6
);
413 struct sockaddr_in6
* addr6
= reinterpret_cast<sockaddr_in6
*>(storage
->addr
);
414 addr6
->sin6_port
= base::HostToNet16(port
);
415 addr6
->sin6_family
= AF_INET6
;
416 memcpy(&addr6
->sin6_addr
, bytes
, 16);
419 // A helper for IDN*{Fast,Slow}.
420 // Append "::<language list>" to |expected| and |actual| to make it
421 // easy to tell which sub-case fails without debugging.
422 void AppendLanguagesToOutputs(const char* languages
,
423 base::string16
* expected
,
424 base::string16
* actual
) {
425 base::string16 to_append
= ASCIIToUTF16("::") + ASCIIToUTF16(languages
);
426 expected
->append(to_append
);
427 actual
->append(to_append
);
430 // A pair of helpers for the FormatUrlWithOffsets() test.
431 void VerboseExpect(size_t expected
,
433 const std::string
& original_url
,
435 const base::string16
& formatted_url
) {
436 EXPECT_EQ(expected
, actual
) << "Original URL: " << original_url
437 << " (at char " << position
<< ")\nFormatted URL: " << formatted_url
;
440 void CheckAdjustedOffsets(const std::string
& url_string
,
441 const std::string
& languages
,
442 FormatUrlTypes format_types
,
443 UnescapeRule::Type unescape_rules
,
444 const size_t* output_offsets
) {
445 GURL
url(url_string
);
446 size_t url_length
= url_string
.length();
447 std::vector
<size_t> offsets
;
448 for (size_t i
= 0; i
<= url_length
+ 1; ++i
)
449 offsets
.push_back(i
);
450 offsets
.push_back(500000); // Something larger than any input length.
451 offsets
.push_back(std::string::npos
);
452 base::string16 formatted_url
= FormatUrlWithOffsets(url
, languages
,
453 format_types
, unescape_rules
, NULL
, NULL
, &offsets
);
454 for (size_t i
= 0; i
< url_length
; ++i
)
455 VerboseExpect(output_offsets
[i
], offsets
[i
], url_string
, i
, formatted_url
);
456 VerboseExpect(formatted_url
.length(), offsets
[url_length
], url_string
,
457 url_length
, formatted_url
);
458 VerboseExpect(base::string16::npos
, offsets
[url_length
+ 1], url_string
,
459 500000, formatted_url
);
460 VerboseExpect(base::string16::npos
, offsets
[url_length
+ 2], url_string
,
461 std::string::npos
, formatted_url
);
464 // Helper to strignize an IP number (used to define expectations).
465 std::string
DumpIPNumber(const IPAddressNumber
& v
) {
467 for (size_t i
= 0; i
< v
.size(); ++i
) {
470 out
.append(base::IntToString(static_cast<int>(v
[i
])));
475 } // anonymous namespace
477 TEST(NetUtilTest
, GetIdentityFromURL
) {
479 const char* input_url
;
480 const char* expected_username
;
481 const char* expected_password
;
484 "http://username:password@google.com",
488 { // Test for http://crbug.com/19200
489 "http://username:p@ssword@google.com",
493 { // Special URL characters should be unescaped.
494 "http://username:p%3fa%26s%2fs%23@google.com",
498 { // Username contains %20.
499 "http://use rname:password@google.com",
504 "http://use%00rname:password@google.com",
508 { // Use a '+' in the username.
509 "http://use+rname:password@google.com",
513 { // Use a '&' in the password.
514 "http://username:p&ssword@google.com",
519 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
520 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s", i
,
521 tests
[i
].input_url
));
522 GURL
url(tests
[i
].input_url
);
524 base::string16 username
, password
;
525 GetIdentityFromURL(url
, &username
, &password
);
527 EXPECT_EQ(ASCIIToUTF16(tests
[i
].expected_username
), username
);
528 EXPECT_EQ(ASCIIToUTF16(tests
[i
].expected_password
), password
);
532 // Try extracting a username which was encoded with UTF8.
533 TEST(NetUtilTest
, GetIdentityFromURL_UTF8
) {
534 GURL
url(WideToUTF16(L
"http://foo:\x4f60\x597d@blah.com"));
536 EXPECT_EQ("foo", url
.username());
537 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url
.password());
539 // Extract the unescaped identity.
540 base::string16 username
, password
;
541 GetIdentityFromURL(url
, &username
, &password
);
543 // Verify that it was decoded as UTF8.
544 EXPECT_EQ(ASCIIToUTF16("foo"), username
);
545 EXPECT_EQ(WideToUTF16(L
"\x4f60\x597d"), password
);
548 // Just a bunch of fake headers.
549 const char* google_headers
=
551 "Content-TYPE: text/html; charset=utf-8\n"
552 "Content-disposition: attachment; filename=\"download.pdf\"\n"
553 "Content-Length: 378557\n"
554 "X-Google-Google1: 314159265\n"
555 "X-Google-Google2: aaaa2:7783,bbb21:9441\n"
556 "X-Google-Google4: home\n"
557 "Transfer-Encoding: chunked\n"
558 "Set-Cookie: HEHE_AT=6666x66beef666x6-66xx6666x66; Path=/mail\n"
559 "Set-Cookie: HEHE_HELP=owned:0;Path=/\n"
560 "Set-Cookie: S=gmail=Xxx-beefbeefbeef_beefb:gmail_yj=beefbeef000beefbee"
561 "fbee:gmproxy=bee-fbeefbe; Domain=.google.com; Path=/\n"
562 "X-Google-Google2: /one/two/three/four/five/six/seven-height/nine:9411\n"
564 "Transfer-Encoding: chunked\n"
565 "Date: Mon, 13 Nov 2006 21:38:09 GMT\n"
566 "Expires: Tue, 14 Nov 2006 19:23:58 GMT\n"
567 "X-Malformed: bla; arg=test\"\n"
568 "X-Malformed2: bla; arg=\n"
569 "X-Test: bla; arg1=val1; arg2=val2";
571 TEST(NetUtilTest
, GetSpecificHeader
) {
572 const HeaderCase tests
[] = {
573 {"content-type", "text/html; charset=utf-8"},
574 {"CONTENT-LENGTH", "378557"},
575 {"Date", "Mon, 13 Nov 2006 21:38:09 GMT"},
580 // Test first with google_headers.
581 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
583 GetSpecificHeader(google_headers
, tests
[i
].header_name
);
584 EXPECT_EQ(result
, tests
[i
].expected
);
587 // Test again with empty headers.
588 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
589 std::string result
= GetSpecificHeader(std::string(), tests
[i
].header_name
);
590 EXPECT_EQ(result
, std::string());
594 TEST(NetUtilTest
, IDNToUnicodeFast
) {
595 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(idn_cases
); i
++) {
596 for (size_t j
= 0; j
< arraysize(kLanguages
); j
++) {
597 // ja || zh-TW,en || ko,ja -> IDNToUnicodeSlow
598 if (j
== 3 || j
== 17 || j
== 18)
600 base::string16
output(IDNToUnicode(idn_cases
[i
].input
, kLanguages
[j
]));
601 base::string16
expected(idn_cases
[i
].unicode_allowed
[j
] ?
602 WideToUTF16(idn_cases
[i
].unicode_output
) :
603 ASCIIToUTF16(idn_cases
[i
].input
));
604 AppendLanguagesToOutputs(kLanguages
[j
], &expected
, &output
);
605 EXPECT_EQ(expected
, output
);
610 TEST(NetUtilTest
, IDNToUnicodeSlow
) {
611 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(idn_cases
); i
++) {
612 for (size_t j
= 0; j
< arraysize(kLanguages
); j
++) {
613 // !(ja || zh-TW,en || ko,ja) -> IDNToUnicodeFast
614 if (!(j
== 3 || j
== 17 || j
== 18))
616 base::string16
output(IDNToUnicode(idn_cases
[i
].input
, kLanguages
[j
]));
617 base::string16
expected(idn_cases
[i
].unicode_allowed
[j
] ?
618 WideToUTF16(idn_cases
[i
].unicode_output
) :
619 ASCIIToUTF16(idn_cases
[i
].input
));
620 AppendLanguagesToOutputs(kLanguages
[j
], &expected
, &output
);
621 EXPECT_EQ(expected
, output
);
626 TEST(NetUtilTest
, CompliantHost
) {
627 const CompliantHostCase compliant_host_cases
[] = {
642 {"a.-a9", "", false},
645 {"1-.a-b", "", true},
646 {"1_.a-b", "", false},
647 {"1-2.a_b", "", true},
648 {"a.b.c.d.e", "", true},
649 {"1.2.3.4.5", "", true},
650 {"1.2.3.4.5.", "", true},
653 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(compliant_host_cases
); ++i
) {
654 EXPECT_EQ(compliant_host_cases
[i
].expected_output
,
655 IsCanonicalizedHostCompliant(compliant_host_cases
[i
].host
,
656 compliant_host_cases
[i
].desired_tld
));
660 TEST(NetUtilTest
, StripWWW
) {
661 EXPECT_EQ(base::string16(), StripWWW(base::string16()));
662 EXPECT_EQ(base::string16(), StripWWW(ASCIIToUTF16("www.")));
663 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("www.blah")));
664 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("blah")));
667 // This is currently a windows specific function.
671 struct GetDirectoryListingEntryCase
{
673 const char* raw_bytes
;
677 const char* expected
;
681 TEST(NetUtilTest
, GetDirectoryListingEntry
) {
682 const GetDirectoryListingEntryCase test_cases
[] = {
688 "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
694 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
701 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
703 // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
704 // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
705 {L
"\xD55C\xAE00.txt",
710 "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\","
711 "\"%ED%95%9C%EA%B8%80.txt\",0,\"9.8 kB\",\"\");</script>\n"},
712 // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
713 // a local or remote file in EUC-KR.
714 {L
"\xD55C\xAE00.txt",
715 "\xC7\xD1\xB1\xDB.txt",
719 "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\",\"%C7%D1%B1%DB.txt\""
720 ",0,\"9.8 kB\",\"\");</script>\n"},
723 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
724 const std::string results
= GetDirectoryListingEntry(
725 WideToUTF16(test_cases
[i
].name
),
726 test_cases
[i
].raw_bytes
,
727 test_cases
[i
].is_dir
,
728 test_cases
[i
].filesize
,
730 EXPECT_EQ(test_cases
[i
].expected
, results
);
736 TEST(NetUtilTest
, ParseHostAndPort
) {
740 const char* expected_host
;
744 {"foo:10", true, "foo", 10},
745 {"foo", true, "foo", -1},
747 "[1080:0:0:0:8:800:200C:4171]:11",
749 "[1080:0:0:0:8:800:200C:4171]",
753 {"foo:bar", false, "", -1},
754 {"foo:", false, "", -1},
755 {":", false, "", -1},
756 {":80", false, "", -1},
758 {"porttoolong:300000", false, "", -1},
759 {"usrname@host", false, "", -1},
760 {"usrname:password@host", false, "", -1},
761 {":password@host", false, "", -1},
762 {":password@host:80", false, "", -1},
763 {":password@host", false, "", -1},
764 {"@host", false, "", -1},
767 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
770 bool ok
= ParseHostAndPort(tests
[i
].input
, &host
, &port
);
772 EXPECT_EQ(tests
[i
].success
, ok
);
774 if (tests
[i
].success
) {
775 EXPECT_EQ(tests
[i
].expected_host
, host
);
776 EXPECT_EQ(tests
[i
].expected_port
, port
);
781 TEST(NetUtilTest
, GetHostAndPort
) {
784 const char* expected_host_and_port
;
786 { GURL("http://www.foo.com/x"), "www.foo.com:80"},
787 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
789 // For IPv6 literals should always include the brackets.
790 { GURL("http://[1::2]/x"), "[1::2]:80"},
791 { GURL("http://[::a]:33/x"), "[::a]:33"},
793 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
794 std::string host_and_port
= GetHostAndPort(tests
[i
].url
);
795 EXPECT_EQ(std::string(tests
[i
].expected_host_and_port
), host_and_port
);
799 TEST(NetUtilTest
, GetHostAndOptionalPort
) {
802 const char* expected_host_and_port
;
804 { GURL("http://www.foo.com/x"), "www.foo.com"},
805 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
807 // For IPv6 literals should always include the brackets.
808 { GURL("http://[1::2]/x"), "[1::2]"},
809 { GURL("http://[::a]:33/x"), "[::a]:33"},
811 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
812 std::string host_and_port
= GetHostAndOptionalPort(tests
[i
].url
);
813 EXPECT_EQ(std::string(tests
[i
].expected_host_and_port
), host_and_port
);
817 TEST(NetUtilTest
, IPAddressToString
) {
818 uint8 addr1
[4] = {0, 0, 0, 0};
819 EXPECT_EQ("0.0.0.0", IPAddressToString(addr1
, sizeof(addr1
)));
821 uint8 addr2
[4] = {192, 168, 0, 1};
822 EXPECT_EQ("192.168.0.1", IPAddressToString(addr2
, sizeof(addr2
)));
824 uint8 addr3
[16] = {0xFE, 0xDC, 0xBA, 0x98};
825 EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3
, sizeof(addr3
)));
828 TEST(NetUtilTest
, IPAddressToStringWithPort
) {
829 uint8 addr1
[4] = {0, 0, 0, 0};
830 EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(addr1
, sizeof(addr1
), 3));
832 uint8 addr2
[4] = {192, 168, 0, 1};
833 EXPECT_EQ("192.168.0.1:99",
834 IPAddressToStringWithPort(addr2
, sizeof(addr2
), 99));
836 uint8 addr3
[16] = {0xFE, 0xDC, 0xBA, 0x98};
837 EXPECT_EQ("[fedc:ba98::]:8080",
838 IPAddressToStringWithPort(addr3
, sizeof(addr3
), 8080));
841 TEST(NetUtilTest
, NetAddressToString_IPv4
) {
846 {{0, 0, 0, 0}, "0.0.0.0"},
847 {{127, 0, 0, 1}, "127.0.0.1"},
848 {{192, 168, 0, 1}, "192.168.0.1"},
851 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
852 SockaddrStorage storage
;
853 MakeIPv4Address(tests
[i
].addr
, 80, &storage
);
854 std::string result
= NetAddressToString(storage
.addr
, storage
.addr_len
);
855 EXPECT_EQ(std::string(tests
[i
].result
), result
);
859 TEST(NetUtilTest
, NetAddressToString_IPv6
) {
864 {{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
865 0x98, 0x76, 0x54, 0x32, 0x10},
866 "fedc:ba98:7654:3210:fedc:ba98:7654:3210"},
869 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
870 SockaddrStorage storage
;
871 MakeIPv6Address(tests
[i
].addr
, 80, &storage
);
872 EXPECT_EQ(std::string(tests
[i
].result
),
873 NetAddressToString(storage
.addr
, storage
.addr_len
));
877 TEST(NetUtilTest
, NetAddressToStringWithPort_IPv4
) {
878 uint8 addr
[] = {127, 0, 0, 1};
879 SockaddrStorage storage
;
880 MakeIPv4Address(addr
, 166, &storage
);
881 std::string result
= NetAddressToStringWithPort(storage
.addr
,
883 EXPECT_EQ("127.0.0.1:166", result
);
886 TEST(NetUtilTest
, NetAddressToStringWithPort_IPv6
) {
888 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
889 0x98, 0x76, 0x54, 0x32, 0x10
891 SockaddrStorage storage
;
892 MakeIPv6Address(addr
, 361, &storage
);
893 std::string result
= NetAddressToStringWithPort(storage
.addr
,
896 // May fail on systems that don't support IPv6.
898 EXPECT_EQ("[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:361", result
);
901 TEST(NetUtilTest
, GetHostName
) {
902 // We can't check the result of GetHostName() directly, since the result
903 // will differ across machines. Our goal here is to simply exercise the
904 // code path, and check that things "look about right".
905 std::string hostname
= GetHostName();
906 EXPECT_FALSE(hostname
.empty());
909 TEST(NetUtilTest
, FormatUrl
) {
910 FormatUrlTypes default_format_type
= kFormatUrlOmitUsernamePassword
;
911 const UrlTestData tests
[] = {
912 {"Empty URL", "", "", default_format_type
, UnescapeRule::NORMAL
, L
"", 0},
915 "http://www.google.com/", "", default_format_type
, UnescapeRule::NORMAL
,
916 L
"http://www.google.com/", 7},
918 {"With a port number and a reference",
919 "http://www.google.com:8080/#\xE3\x82\xB0", "", default_format_type
,
920 UnescapeRule::NORMAL
,
921 L
"http://www.google.com:8080/#\x30B0", 7},
923 // -------- IDN tests --------
924 {"Japanese IDN with ja",
925 "http://xn--l8jvb1ey91xtjb.jp", "ja", default_format_type
,
926 UnescapeRule::NORMAL
, L
"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
928 {"Japanese IDN with en",
929 "http://xn--l8jvb1ey91xtjb.jp", "en", default_format_type
,
930 UnescapeRule::NORMAL
, L
"http://xn--l8jvb1ey91xtjb.jp/", 7},
932 {"Japanese IDN without any languages",
933 "http://xn--l8jvb1ey91xtjb.jp", "", default_format_type
,
934 UnescapeRule::NORMAL
,
935 // Single script is safe for empty languages.
936 L
"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
938 {"mailto: with Japanese IDN",
939 "mailto:foo@xn--l8jvb1ey91xtjb.jp", "ja", default_format_type
,
940 UnescapeRule::NORMAL
,
941 // GURL doesn't assume an email address's domain part as a host name.
942 L
"mailto:foo@xn--l8jvb1ey91xtjb.jp", 7},
944 {"file: with Japanese IDN",
945 "file://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type
,
946 UnescapeRule::NORMAL
,
947 L
"file://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 7},
949 {"ftp: with Japanese IDN",
950 "ftp://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type
,
951 UnescapeRule::NORMAL
,
952 L
"ftp://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 6},
954 // -------- omit_username_password flag tests --------
955 {"With username and password, omit_username_password=false",
956 "http://user:passwd@example.com/foo", "",
957 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
958 L
"http://user:passwd@example.com/foo", 19},
960 {"With username and password, omit_username_password=true",
961 "http://user:passwd@example.com/foo", "", default_format_type
,
962 UnescapeRule::NORMAL
, L
"http://example.com/foo", 7},
964 {"With username and no password",
965 "http://user@example.com/foo", "", default_format_type
,
966 UnescapeRule::NORMAL
, L
"http://example.com/foo", 7},
968 {"Just '@' without username and password",
969 "http://@example.com/foo", "", default_format_type
, UnescapeRule::NORMAL
,
970 L
"http://example.com/foo", 7},
972 // GURL doesn't think local-part of an email address is username for URL.
973 {"mailto:, omit_username_password=true",
974 "mailto:foo@example.com", "", default_format_type
, UnescapeRule::NORMAL
,
975 L
"mailto:foo@example.com", 7},
977 // -------- unescape flag tests --------
979 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
980 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
981 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type
,
983 // GURL parses %-encoded hostnames into Punycode.
984 L
"http://xn--qcka1pmc.jp/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
985 L
"?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", 7},
987 {"Unescape normally",
988 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
989 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
990 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type
,
991 UnescapeRule::NORMAL
,
992 L
"http://xn--qcka1pmc.jp/\x30B0\x30FC\x30B0\x30EB"
993 L
"?q=\x30B0\x30FC\x30B0\x30EB", 7},
995 {"Unescape normally with BiDi control character",
996 "http://example.com/%E2%80%AEabc?q=%E2%80%8Fxy", "en", default_format_type
,
997 UnescapeRule::NORMAL
, L
"http://example.com/%E2%80%AEabc?q=%E2%80%8Fxy", 7},
999 {"Unescape normally including unescape spaces",
1000 "http://www.google.com/search?q=Hello%20World", "en", default_format_type
,
1001 UnescapeRule::SPACES
, L
"http://www.google.com/search?q=Hello World", 7},
1004 {"unescape=true with some special characters",
1005 "http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", "",
1006 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
1007 L"http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", 25},
1009 // Disabled: the resultant URL becomes "...user%253A:%2540passwd...".
1011 // -------- omit http: --------
1012 {"omit http with user name",
1013 "http://user@example.com/foo", "", kFormatUrlOmitAll
,
1014 UnescapeRule::NORMAL
, L
"example.com/foo", 0},
1017 "http://www.google.com/", "en", kFormatUrlOmitHTTP
,
1018 UnescapeRule::NORMAL
, L
"www.google.com/",
1021 {"omit http with https",
1022 "https://www.google.com/", "en", kFormatUrlOmitHTTP
,
1023 UnescapeRule::NORMAL
, L
"https://www.google.com/",
1026 {"omit http starts with ftp.",
1027 "http://ftp.google.com/", "en", kFormatUrlOmitHTTP
,
1028 UnescapeRule::NORMAL
, L
"http://ftp.google.com/",
1031 // -------- omit trailing slash on bare hostname --------
1032 {"omit slash when it's the entire path",
1033 "http://www.google.com/", "en",
1034 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
1035 L
"http://www.google.com", 7},
1036 {"omit slash when there's a ref",
1037 "http://www.google.com/#ref", "en",
1038 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
1039 L
"http://www.google.com/#ref", 7},
1040 {"omit slash when there's a query",
1041 "http://www.google.com/?", "en",
1042 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
1043 L
"http://www.google.com/?", 7},
1044 {"omit slash when it's not the entire path",
1045 "http://www.google.com/foo", "en",
1046 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
1047 L
"http://www.google.com/foo", 7},
1048 {"omit slash for nonstandard URLs",
1049 "data:/", "en", kFormatUrlOmitTrailingSlashOnBareHostname
,
1050 UnescapeRule::NORMAL
, L
"data:/", 5},
1051 {"omit slash for file URLs",
1052 "file:///", "en", kFormatUrlOmitTrailingSlashOnBareHostname
,
1053 UnescapeRule::NORMAL
, L
"file:///", 7},
1055 // -------- view-source: --------
1057 "view-source:http://xn--qcka1pmc.jp/", "ja", default_format_type
,
1058 UnescapeRule::NORMAL
, L
"view-source:http://\x30B0\x30FC\x30B0\x30EB.jp/",
1061 {"view-source of view-source",
1062 "view-source:view-source:http://xn--qcka1pmc.jp/", "ja",
1063 default_format_type
, UnescapeRule::NORMAL
,
1064 L
"view-source:view-source:http://xn--qcka1pmc.jp/", 12},
1066 // view-source should omit http and trailing slash where non-view-source
1068 {"view-source omit http",
1069 "view-source:http://a.b/c", "en", kFormatUrlOmitAll
,
1070 UnescapeRule::NORMAL
, L
"view-source:a.b/c",
1072 {"view-source omit http starts with ftp.",
1073 "view-source:http://ftp.b/c", "en", kFormatUrlOmitAll
,
1074 UnescapeRule::NORMAL
, L
"view-source:http://ftp.b/c",
1076 {"view-source omit slash when it's the entire path",
1077 "view-source:http://a.b/", "en", kFormatUrlOmitAll
,
1078 UnescapeRule::NORMAL
, L
"view-source:a.b",
1082 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
1084 base::string16 formatted
= FormatUrl(
1085 GURL(tests
[i
].input
), tests
[i
].languages
, tests
[i
].format_types
,
1086 tests
[i
].escape_rules
, NULL
, &prefix_len
, NULL
);
1087 EXPECT_EQ(WideToUTF16(tests
[i
].output
), formatted
) << tests
[i
].description
;
1088 EXPECT_EQ(tests
[i
].prefix_len
, prefix_len
) << tests
[i
].description
;
1092 TEST(NetUtilTest
, FormatUrlParsed
) {
1093 // No unescape case.
1095 base::string16 formatted
= FormatUrl(
1096 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
1097 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
1098 "ja", kFormatUrlOmitNothing
, UnescapeRule::NONE
, &parsed
, NULL
,
1100 EXPECT_EQ(WideToUTF16(
1101 L
"http://%E3%82%B0:%E3%83%BC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
1102 L
"/%E3%82%B0/?q=%E3%82%B0#\x30B0"), formatted
);
1103 EXPECT_EQ(WideToUTF16(L
"%E3%82%B0"),
1104 formatted
.substr(parsed
.username
.begin
, parsed
.username
.len
));
1105 EXPECT_EQ(WideToUTF16(L
"%E3%83%BC"),
1106 formatted
.substr(parsed
.password
.begin
, parsed
.password
.len
));
1107 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
1108 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1109 EXPECT_EQ(WideToUTF16(L
"8080"),
1110 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1111 EXPECT_EQ(WideToUTF16(L
"/%E3%82%B0/"),
1112 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1113 EXPECT_EQ(WideToUTF16(L
"q=%E3%82%B0"),
1114 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1115 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
1116 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1119 formatted
= FormatUrl(
1120 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
1121 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
1122 "ja", kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, &parsed
, NULL
,
1124 EXPECT_EQ(WideToUTF16(L
"http://\x30B0:\x30FC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
1125 L
"/\x30B0/?q=\x30B0#\x30B0"), formatted
);
1126 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
1127 formatted
.substr(parsed
.username
.begin
, parsed
.username
.len
));
1128 EXPECT_EQ(WideToUTF16(L
"\x30FC"),
1129 formatted
.substr(parsed
.password
.begin
, parsed
.password
.len
));
1130 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
1131 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1132 EXPECT_EQ(WideToUTF16(L
"8080"),
1133 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1134 EXPECT_EQ(WideToUTF16(L
"/\x30B0/"),
1135 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1136 EXPECT_EQ(WideToUTF16(L
"q=\x30B0"),
1137 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1138 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
1139 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1141 // Omit_username_password + unescape case.
1142 formatted
= FormatUrl(
1143 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
1144 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
1145 "ja", kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
, &parsed
,
1147 EXPECT_EQ(WideToUTF16(L
"http://\x30B0\x30FC\x30B0\x30EB.jp:8080"
1148 L
"/\x30B0/?q=\x30B0#\x30B0"), formatted
);
1149 EXPECT_FALSE(parsed
.username
.is_valid());
1150 EXPECT_FALSE(parsed
.password
.is_valid());
1151 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
1152 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1153 EXPECT_EQ(WideToUTF16(L
"8080"),
1154 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1155 EXPECT_EQ(WideToUTF16(L
"/\x30B0/"),
1156 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1157 EXPECT_EQ(WideToUTF16(L
"q=\x30B0"),
1158 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1159 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
1160 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1162 // View-source case.
1164 FormatUrl(GURL("view-source:http://user:passwd@host:81/path?query#ref"),
1166 kFormatUrlOmitUsernamePassword
,
1167 UnescapeRule::NORMAL
,
1171 EXPECT_EQ(WideToUTF16(L
"view-source:http://host:81/path?query#ref"),
1173 EXPECT_EQ(WideToUTF16(L
"view-source:http"),
1174 formatted
.substr(parsed
.scheme
.begin
, parsed
.scheme
.len
));
1175 EXPECT_FALSE(parsed
.username
.is_valid());
1176 EXPECT_FALSE(parsed
.password
.is_valid());
1177 EXPECT_EQ(WideToUTF16(L
"host"),
1178 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1179 EXPECT_EQ(WideToUTF16(L
"81"),
1180 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1181 EXPECT_EQ(WideToUTF16(L
"/path"),
1182 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1183 EXPECT_EQ(WideToUTF16(L
"query"),
1184 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1185 EXPECT_EQ(WideToUTF16(L
"ref"),
1186 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1189 formatted
= FormatUrl(GURL("http://host:8000/a?b=c#d"),
1192 UnescapeRule::NORMAL
,
1196 EXPECT_EQ(WideToUTF16(L
"host:8000/a?b=c#d"), formatted
);
1197 EXPECT_FALSE(parsed
.scheme
.is_valid());
1198 EXPECT_FALSE(parsed
.username
.is_valid());
1199 EXPECT_FALSE(parsed
.password
.is_valid());
1200 EXPECT_EQ(WideToUTF16(L
"host"),
1201 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1202 EXPECT_EQ(WideToUTF16(L
"8000"),
1203 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1204 EXPECT_EQ(WideToUTF16(L
"/a"),
1205 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1206 EXPECT_EQ(WideToUTF16(L
"b=c"),
1207 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1208 EXPECT_EQ(WideToUTF16(L
"d"),
1209 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1211 // omit http starts with ftp case.
1212 formatted
= FormatUrl(GURL("http://ftp.host:8000/a?b=c#d"),
1215 UnescapeRule::NORMAL
,
1219 EXPECT_EQ(WideToUTF16(L
"http://ftp.host:8000/a?b=c#d"), formatted
);
1220 EXPECT_TRUE(parsed
.scheme
.is_valid());
1221 EXPECT_FALSE(parsed
.username
.is_valid());
1222 EXPECT_FALSE(parsed
.password
.is_valid());
1223 EXPECT_EQ(WideToUTF16(L
"http"),
1224 formatted
.substr(parsed
.scheme
.begin
, parsed
.scheme
.len
));
1225 EXPECT_EQ(WideToUTF16(L
"ftp.host"),
1226 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1227 EXPECT_EQ(WideToUTF16(L
"8000"),
1228 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
1229 EXPECT_EQ(WideToUTF16(L
"/a"),
1230 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1231 EXPECT_EQ(WideToUTF16(L
"b=c"),
1232 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
1233 EXPECT_EQ(WideToUTF16(L
"d"),
1234 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
1236 // omit http starts with 'f' case.
1237 formatted
= FormatUrl(GURL("http://f/"),
1240 UnescapeRule::NORMAL
,
1244 EXPECT_EQ(WideToUTF16(L
"f/"), formatted
);
1245 EXPECT_FALSE(parsed
.scheme
.is_valid());
1246 EXPECT_FALSE(parsed
.username
.is_valid());
1247 EXPECT_FALSE(parsed
.password
.is_valid());
1248 EXPECT_FALSE(parsed
.port
.is_valid());
1249 EXPECT_TRUE(parsed
.path
.is_valid());
1250 EXPECT_FALSE(parsed
.query
.is_valid());
1251 EXPECT_FALSE(parsed
.ref
.is_valid());
1252 EXPECT_EQ(WideToUTF16(L
"f"),
1253 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
1254 EXPECT_EQ(WideToUTF16(L
"/"),
1255 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
1258 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
1259 // results in the original GURL, for each ASCII character in the path.
1260 TEST(NetUtilTest
, FormatUrlRoundTripPathASCII
) {
1261 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
1262 GURL
url(std::string("http://www.google.com/") +
1263 static_cast<char>(test_char
));
1265 base::string16 formatted
= FormatUrl(url
,
1267 kFormatUrlOmitUsernamePassword
,
1268 UnescapeRule::NORMAL
,
1272 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
1276 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
1277 // results in the original GURL, for each escaped ASCII character in the path.
1278 TEST(NetUtilTest
, FormatUrlRoundTripPathEscaped
) {
1279 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
1280 std::string
original_url("http://www.google.com/");
1281 original_url
.push_back('%');
1282 original_url
.append(base::HexEncode(&test_char
, 1));
1284 GURL
url(original_url
);
1286 base::string16 formatted
= FormatUrl(url
,
1288 kFormatUrlOmitUsernamePassword
,
1289 UnescapeRule::NORMAL
,
1293 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
1297 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
1298 // results in the original GURL, for each ASCII character in the query.
1299 TEST(NetUtilTest
, FormatUrlRoundTripQueryASCII
) {
1300 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
1301 GURL
url(std::string("http://www.google.com/?") +
1302 static_cast<char>(test_char
));
1304 base::string16 formatted
= FormatUrl(url
,
1306 kFormatUrlOmitUsernamePassword
,
1307 UnescapeRule::NORMAL
,
1311 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
1315 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
1316 // only results in a different GURL for certain characters.
1317 TEST(NetUtilTest
, FormatUrlRoundTripQueryEscaped
) {
1318 // A full list of characters which FormatURL should unescape and GURL should
1319 // not escape again, when they appear in a query string.
1320 const char* kUnescapedCharacters
=
1321 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~";
1322 for (unsigned char test_char
= 0; test_char
< 128; ++test_char
) {
1323 std::string
original_url("http://www.google.com/?");
1324 original_url
.push_back('%');
1325 original_url
.append(base::HexEncode(&test_char
, 1));
1327 GURL
url(original_url
);
1329 base::string16 formatted
= FormatUrl(url
,
1331 kFormatUrlOmitUsernamePassword
,
1332 UnescapeRule::NORMAL
,
1338 strchr(kUnescapedCharacters
, static_cast<char>(test_char
))) {
1339 EXPECT_NE(url
.spec(), GURL(formatted
).spec());
1341 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
1346 TEST(NetUtilTest
, FormatUrlWithOffsets
) {
1347 CheckAdjustedOffsets(std::string(), "en", kFormatUrlOmitNothing
,
1348 UnescapeRule::NORMAL
, NULL
);
1350 const size_t basic_offsets
[] = {
1351 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
1354 CheckAdjustedOffsets("http://www.google.com/foo/", "en",
1355 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
1358 const size_t omit_auth_offsets_1
[] = {
1359 0, 1, 2, 3, 4, 5, 6, 7, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 7,
1360 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
1362 CheckAdjustedOffsets("http://foo:bar@www.google.com/", "en",
1363 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
,
1364 omit_auth_offsets_1
);
1366 const size_t omit_auth_offsets_2
[] = {
1367 0, 1, 2, 3, 4, 5, 6, 7, kNpos
, kNpos
, kNpos
, 7, 8, 9, 10, 11, 12, 13, 14,
1368 15, 16, 17, 18, 19, 20, 21
1370 CheckAdjustedOffsets("http://foo@www.google.com/", "en",
1371 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
,
1372 omit_auth_offsets_2
);
1374 const size_t dont_omit_auth_offsets
[] = {
1375 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1376 kNpos
, kNpos
, 11, 12, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1377 kNpos
, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
1380 // Unescape to "http://foo\x30B0:\x30B0bar@www.google.com".
1381 CheckAdjustedOffsets("http://foo%E3%82%B0:%E3%82%B0bar@www.google.com/", "en",
1382 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
1383 dont_omit_auth_offsets
);
1385 const size_t view_source_offsets
[] = {
1386 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, kNpos
,
1387 kNpos
, kNpos
, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
1389 CheckAdjustedOffsets("view-source:http://foo@www.google.com/", "en",
1390 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
,
1391 view_source_offsets
);
1393 const size_t idn_hostname_offsets_1
[] = {
1394 0, 1, 2, 3, 4, 5, 6, 7, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1395 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 12,
1396 13, 14, 15, 16, 17, 18, 19
1398 // Convert punycode to "http://\x671d\x65e5\x3042\x3055\x3072.jp/foo/".
1399 CheckAdjustedOffsets("http://xn--l8jvb1ey91xtjb.jp/foo/", "ja",
1400 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
1401 idn_hostname_offsets_1
);
1403 const size_t idn_hostname_offsets_2
[] = {
1404 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1405 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 14, 15, kNpos
, kNpos
, kNpos
,
1406 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1407 kNpos
, 19, 20, 21, 22, 23, 24
1409 // Convert punycode to
1410 // "http://test.\x89c6\x9891.\x5317\x4eac\x5927\x5b78.test/".
1411 CheckAdjustedOffsets("http://test.xn--cy2a840a.xn--1lq90ic7f1rc.test/",
1412 "zh-CN", kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
1413 idn_hostname_offsets_2
);
1415 const size_t unescape_offsets
[] = {
1416 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
1417 21, 22, 23, 24, 25, kNpos
, kNpos
, 26, 27, 28, 29, 30, kNpos
, kNpos
, kNpos
,
1418 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 31, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1419 kNpos
, kNpos
, kNpos
, 32, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
1420 kNpos
, 33, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
1422 // Unescape to "http://www.google.com/foo bar/\x30B0\x30FC\x30B0\x30EB".
1423 CheckAdjustedOffsets(
1424 "http://www.google.com/foo%20bar/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB",
1425 "en", kFormatUrlOmitNothing
, UnescapeRule::SPACES
, unescape_offsets
);
1427 const size_t ref_offsets
[] = {
1428 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
1429 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, kNpos
, kNpos
, 32, kNpos
, kNpos
,
1432 // Unescape to "http://www.google.com/foo.html#\x30B0\x30B0z".
1433 CheckAdjustedOffsets(
1434 "http://www.google.com/foo.html#\xE3\x82\xB0\xE3\x82\xB0z", "en",
1435 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, ref_offsets
);
1437 const size_t omit_http_offsets
[] = {
1438 0, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1441 CheckAdjustedOffsets("http://www.google.com/", "en", kFormatUrlOmitHTTP
,
1442 UnescapeRule::NORMAL
, omit_http_offsets
);
1444 const size_t omit_http_start_with_ftp_offsets
[] = {
1445 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
1447 CheckAdjustedOffsets("http://ftp.google.com/", "en", kFormatUrlOmitHTTP
,
1448 UnescapeRule::NORMAL
, omit_http_start_with_ftp_offsets
);
1450 const size_t omit_all_offsets
[] = {
1451 0, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 0, kNpos
, kNpos
, kNpos
, kNpos
,
1452 0, 1, 2, 3, 4, 5, 6, 7
1454 CheckAdjustedOffsets("http://user@foo.com/", "en", kFormatUrlOmitAll
,
1455 UnescapeRule::NORMAL
, omit_all_offsets
);
1458 TEST(NetUtilTest
, SimplifyUrlForRequest
) {
1460 const char* input_url
;
1461 const char* expected_simplified_url
;
1464 // Reference section should be stripped.
1465 "http://www.google.com:78/foobar?query=1#hash",
1466 "http://www.google.com:78/foobar?query=1",
1469 // Reference section can itself contain #.
1470 "http://192.168.0.1?query=1#hash#10#11#13#14",
1471 "http://192.168.0.1?query=1",
1473 { // Strip username/password.
1474 "http://user:pass@google.com",
1475 "http://google.com/",
1477 { // Strip both the reference and the username/password.
1478 "http://user:pass@google.com:80/sup?yo#X#X",
1479 "http://google.com/sup?yo",
1481 { // Try an HTTPS URL -- strip both the reference and the username/password.
1482 "https://user:pass@google.com:80/sup?yo#X#X",
1483 "https://google.com:80/sup?yo",
1485 { // Try an FTP URL -- strip both the reference and the username/password.
1486 "ftp://user:pass@google.com:80/sup?yo#X#X",
1487 "ftp://google.com:80/sup?yo",
1489 { // Try a nonstandard URL
1490 "foobar://user:pass@google.com:80/sup?yo#X#X",
1491 "foobar://user:pass@google.com:80/sup?yo",
1494 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
1495 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s", i
,
1496 tests
[i
].input_url
));
1497 GURL
input_url(GURL(tests
[i
].input_url
));
1498 GURL
expected_url(GURL(tests
[i
].expected_simplified_url
));
1499 EXPECT_EQ(expected_url
, SimplifyUrlForRequest(input_url
));
1503 TEST(NetUtilTest
, SetExplicitlyAllowedPortsTest
) {
1504 std::string invalid
[] = { "1,2,a", "'1','2'", "1, 2, 3", "1 0,11,12" };
1505 std::string valid
[] = { "", "1", "1,2", "1,2,3", "10,11,12,13" };
1507 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(invalid
); ++i
) {
1508 SetExplicitlyAllowedPorts(invalid
[i
]);
1509 EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts()));
1512 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(valid
); ++i
) {
1513 SetExplicitlyAllowedPorts(valid
[i
]);
1514 EXPECT_EQ(i
, GetCountOfExplicitlyAllowedPorts());
1518 TEST(NetUtilTest
, GetHostOrSpecFromURL
) {
1519 EXPECT_EQ("example.com",
1520 GetHostOrSpecFromURL(GURL("http://example.com/test")));
1521 EXPECT_EQ("example.com",
1522 GetHostOrSpecFromURL(GURL("http://example.com./test")));
1523 EXPECT_EQ("file:///tmp/test.html",
1524 GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
1527 TEST(NetUtilTest
, GetAddressFamily
) {
1528 IPAddressNumber number
;
1529 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number
));
1530 EXPECT_EQ(ADDRESS_FAMILY_IPV4
, GetAddressFamily(number
));
1531 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number
));
1532 EXPECT_EQ(ADDRESS_FAMILY_IPV6
, GetAddressFamily(number
));
1535 // Test that invalid IP literals fail to parse.
1536 TEST(NetUtilTest
, ParseIPLiteralToNumber_FailParse
) {
1537 IPAddressNumber number
;
1539 EXPECT_FALSE(ParseIPLiteralToNumber("bad value", &number
));
1540 EXPECT_FALSE(ParseIPLiteralToNumber("bad:value", &number
));
1541 EXPECT_FALSE(ParseIPLiteralToNumber(std::string(), &number
));
1542 EXPECT_FALSE(ParseIPLiteralToNumber("192.168.0.1:30", &number
));
1543 EXPECT_FALSE(ParseIPLiteralToNumber(" 192.168.0.1 ", &number
));
1544 EXPECT_FALSE(ParseIPLiteralToNumber("[::1]", &number
));
1547 // Test parsing an IPv4 literal.
1548 TEST(NetUtilTest
, ParseIPLiteralToNumber_IPv4
) {
1549 IPAddressNumber number
;
1550 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number
));
1551 EXPECT_EQ("192,168,0,1", DumpIPNumber(number
));
1552 EXPECT_EQ("192.168.0.1", IPAddressToString(number
));
1555 // Test parsing an IPv6 literal.
1556 TEST(NetUtilTest
, ParseIPLiteralToNumber_IPv6
) {
1557 IPAddressNumber number
;
1558 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number
));
1559 EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number
));
1560 EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number
));
1563 // Test mapping an IPv4 address to an IPv6 address.
1564 TEST(NetUtilTest
, ConvertIPv4NumberToIPv6Number
) {
1565 IPAddressNumber ipv4_number
;
1566 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number
));
1568 IPAddressNumber ipv6_number
=
1569 ConvertIPv4NumberToIPv6Number(ipv4_number
);
1571 // ::ffff:192.168.0.1
1572 EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
1573 DumpIPNumber(ipv6_number
));
1574 EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number
));
1577 TEST(NetUtilTest
, IsIPv4Mapped
) {
1578 IPAddressNumber ipv4_number
;
1579 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number
));
1580 EXPECT_FALSE(IsIPv4Mapped(ipv4_number
));
1582 IPAddressNumber ipv6_number
;
1583 EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number
));
1584 EXPECT_FALSE(IsIPv4Mapped(ipv6_number
));
1586 IPAddressNumber ipv4mapped_number
;
1587 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number
));
1588 EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number
));
1591 TEST(NetUtilTest
, ConvertIPv4MappedToIPv4
) {
1592 IPAddressNumber ipv4mapped_number
;
1593 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number
));
1594 IPAddressNumber expected
;
1595 EXPECT_TRUE(ParseIPLiteralToNumber("1.1.0.1", &expected
));
1596 IPAddressNumber result
= ConvertIPv4MappedToIPv4(ipv4mapped_number
);
1597 EXPECT_EQ(expected
, result
);
1600 // Test parsing invalid CIDR notation literals.
1601 TEST(NetUtilTest
, ParseCIDRBlock_Invalid
) {
1602 const char* bad_literals
[] = {
1618 for (size_t i
= 0; i
< arraysize(bad_literals
); ++i
) {
1619 IPAddressNumber ip_number
;
1620 size_t prefix_length_in_bits
;
1622 EXPECT_FALSE(ParseCIDRBlock(bad_literals
[i
],
1624 &prefix_length_in_bits
));
1628 // Test parsing a valid CIDR notation literal.
1629 TEST(NetUtilTest
, ParseCIDRBlock_Valid
) {
1630 IPAddressNumber ip_number
;
1631 size_t prefix_length_in_bits
;
1633 EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
1635 &prefix_length_in_bits
));
1637 EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number
));
1638 EXPECT_EQ(11u, prefix_length_in_bits
);
1641 TEST(NetUtilTest
, IPNumberMatchesPrefix
) {
1643 const char* cidr_literal
;
1644 const char* ip_literal
;
1645 bool expected_to_match
;
1647 // IPv4 prefix with IPv4 inputs.
1664 // IPv6 prefix with IPv6 inputs.
1676 // IPv6 prefix with IPv4 inputs.
1683 "::ffff:192.168.0.1/112",
1688 // IPv4 prefix with IPv6 inputs.
1696 "::ffff:10.12.33.44",
1700 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
1701 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s, %s", i
,
1702 tests
[i
].cidr_literal
,
1703 tests
[i
].ip_literal
));
1705 IPAddressNumber ip_number
;
1706 EXPECT_TRUE(ParseIPLiteralToNumber(tests
[i
].ip_literal
, &ip_number
));
1708 IPAddressNumber ip_prefix
;
1709 size_t prefix_length_in_bits
;
1711 EXPECT_TRUE(ParseCIDRBlock(tests
[i
].cidr_literal
,
1713 &prefix_length_in_bits
));
1715 EXPECT_EQ(tests
[i
].expected_to_match
,
1716 IPNumberMatchesPrefix(ip_number
,
1718 prefix_length_in_bits
));
1722 TEST(NetUtilTest
, IsLocalhost
) {
1723 EXPECT_TRUE(net::IsLocalhost("localhost"));
1724 EXPECT_TRUE(net::IsLocalhost("localhost.localdomain"));
1725 EXPECT_TRUE(net::IsLocalhost("localhost6"));
1726 EXPECT_TRUE(net::IsLocalhost("localhost6.localdomain6"));
1727 EXPECT_TRUE(net::IsLocalhost("127.0.0.1"));
1728 EXPECT_TRUE(net::IsLocalhost("127.0.1.0"));
1729 EXPECT_TRUE(net::IsLocalhost("127.1.0.0"));
1730 EXPECT_TRUE(net::IsLocalhost("127.0.0.255"));
1731 EXPECT_TRUE(net::IsLocalhost("127.0.255.0"));
1732 EXPECT_TRUE(net::IsLocalhost("127.255.0.0"));
1733 EXPECT_TRUE(net::IsLocalhost("::1"));
1734 EXPECT_TRUE(net::IsLocalhost("0:0:0:0:0:0:0:1"));
1736 EXPECT_FALSE(net::IsLocalhost("localhostx"));
1737 EXPECT_FALSE(net::IsLocalhost("foo.localdomain"));
1738 EXPECT_FALSE(net::IsLocalhost("localhost6x"));
1739 EXPECT_FALSE(net::IsLocalhost("localhost.localdomain6"));
1740 EXPECT_FALSE(net::IsLocalhost("localhost6.localdomain"));
1741 EXPECT_FALSE(net::IsLocalhost("127.0.0.1.1"));
1742 EXPECT_FALSE(net::IsLocalhost(".127.0.0.255"));
1743 EXPECT_FALSE(net::IsLocalhost("::2"));
1744 EXPECT_FALSE(net::IsLocalhost("::1:1"));
1745 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:1:0:0:1"));
1746 EXPECT_FALSE(net::IsLocalhost("::1:1"));
1747 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:0:0:0:0:1"));
1750 // Verify GetNetworkList().
1751 TEST(NetUtilTest
, GetNetworkList
) {
1752 NetworkInterfaceList list
;
1753 ASSERT_TRUE(GetNetworkList(&list
, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES
));
1754 for (NetworkInterfaceList::iterator it
= list
.begin();
1755 it
!= list
.end(); ++it
) {
1756 // Verify that the names are not empty.
1757 EXPECT_FALSE(it
->name
.empty());
1758 EXPECT_FALSE(it
->friendly_name
.empty());
1760 // Verify that the address is correct.
1761 EXPECT_TRUE(it
->address
.size() == kIPv4AddressSize
||
1762 it
->address
.size() == kIPv6AddressSize
)
1763 << "Invalid address of size " << it
->address
.size();
1764 bool all_zeroes
= true;
1765 for (size_t i
= 0; i
< it
->address
.size(); ++i
) {
1766 if (it
->address
[i
] != 0) {
1771 EXPECT_FALSE(all_zeroes
);
1772 EXPECT_GT(it
->network_prefix
, 1u);
1773 EXPECT_LE(it
->network_prefix
, it
->address
.size() * 8);
1776 // On Windows |name| is NET_LUID.
1777 base::ScopedNativeLibrary
phlpapi_lib(
1778 base::FilePath(FILE_PATH_LITERAL("iphlpapi.dll")));
1779 ASSERT_TRUE(phlpapi_lib
.is_valid());
1780 typedef NETIO_STATUS (WINAPI
* ConvertInterfaceIndexToLuid
)(NET_IFINDEX
,
1782 ConvertInterfaceIndexToLuid interface_to_luid
=
1783 reinterpret_cast<ConvertInterfaceIndexToLuid
>(
1784 phlpapi_lib
.GetFunctionPointer("ConvertInterfaceIndexToLuid"));
1786 typedef NETIO_STATUS (WINAPI
* ConvertInterfaceLuidToGuid
)(NET_LUID
*,
1788 ConvertInterfaceLuidToGuid luid_to_guid
=
1789 reinterpret_cast<ConvertInterfaceLuidToGuid
>(
1790 phlpapi_lib
.GetFunctionPointer("ConvertInterfaceLuidToGuid"));
1792 if (interface_to_luid
&& luid_to_guid
) {
1794 EXPECT_EQ(interface_to_luid(it
->interface_index
, &luid
), NO_ERROR
);
1796 EXPECT_EQ(luid_to_guid(&luid
, &guid
), NO_ERROR
);
1798 StringFromCLSID(guid
, &name
);
1799 EXPECT_STREQ(base::UTF8ToWide(it
->name
).c_str(), name
);
1800 CoTaskMemFree(name
);
1803 EXPECT_LT(base::win::GetVersion(), base::win::VERSION_VISTA
);
1804 EXPECT_LT(it
->interface_index
, 1u << 24u); // Must fit 0.x.x.x.
1805 EXPECT_NE(it
->interface_index
, 0u); // 0 means to use default.
1807 if (it
->type
== NetworkChangeNotifier::CONNECTION_WIFI
) {
1808 EXPECT_NE(WIFI_PHY_LAYER_PROTOCOL_NONE
, GetWifiPHYLayerProtocol());
1810 #elif !defined(OS_ANDROID)
1811 char name
[IF_NAMESIZE
];
1812 EXPECT_TRUE(if_indextoname(it
->interface_index
, name
));
1813 EXPECT_STREQ(it
->name
.c_str(), name
);
1818 struct NonUniqueNameTestData
{
1820 const char* hostname
;
1823 // Google Test pretty-printer.
1824 void PrintTo(const NonUniqueNameTestData
& data
, std::ostream
* os
) {
1825 ASSERT_TRUE(data
.hostname
);
1826 *os
<< " hostname: " << testing::PrintToString(data
.hostname
)
1827 << "; is_unique: " << testing::PrintToString(data
.is_unique
);
1830 const NonUniqueNameTestData kNonUniqueNameTestData
[] = {
1831 // Domains under ICANN-assigned domains.
1832 { true, "google.com" },
1833 { true, "google.co.uk" },
1834 // Domains under private registries.
1835 { true, "appspot.com" },
1836 { true, "test.appspot.com" },
1837 // Unreserved IPv4 addresses (in various forms).
1838 { true, "8.8.8.8" },
1839 { true, "99.64.0.0" },
1840 { true, "212.15.0.0" },
1842 { true, "212.15.0" },
1843 { true, "3557752832" },
1844 // Reserved IPv4 addresses (in various forms).
1845 { false, "192.168.0.0" },
1846 { false, "192.168.0.6" },
1847 { false, "10.0.0.5" },
1849 { false, "10.0.0" },
1850 { false, "3232235526" },
1851 // Unreserved IPv6 addresses.
1852 { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
1853 { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
1854 // Reserved IPv6 addresses.
1855 { false, "::192.9.5.5" },
1856 { false, "FEED::BEEF" },
1857 { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
1858 // 'internal'/non-IANA assigned domains.
1859 { false, "intranet" },
1860 { false, "intranet." },
1861 { false, "intranet.example" },
1862 { false, "host.intranet.example" },
1863 // gTLDs under discussion, but not yet assigned.
1864 { false, "intranet.corp" },
1865 { false, "example.tech" },
1866 { false, "intranet.internal" },
1867 // Invalid host names are treated as unique - but expected to be
1868 // filtered out before then.
1869 { true, "junk)(£)$*!@~#" },
1870 { true, "w$w.example.com" },
1871 { true, "nocolonsallowed:example" },
1872 { true, "[::4.5.6.9]" },
1875 class NetUtilNonUniqueNameTest
1876 : public testing::TestWithParam
<NonUniqueNameTestData
> {
1878 virtual ~NetUtilNonUniqueNameTest() {}
1881 bool IsUnique(const std::string
& hostname
) {
1882 return !IsHostnameNonUnique(hostname
);
1886 // Test that internal/non-unique names are properly identified as such, but
1887 // that IP addresses and hosts beneath registry-controlled domains are flagged
1889 TEST_P(NetUtilNonUniqueNameTest
, IsHostnameNonUnique
) {
1890 const NonUniqueNameTestData
& test_data
= GetParam();
1892 EXPECT_EQ(test_data
.is_unique
, IsUnique(test_data
.hostname
));
1895 INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest
,
1896 testing::ValuesIn(kNonUniqueNameTestData
));