isolate_driver: Enable ninja parsing code all the time.
[chromium-blink-merge.git] / net / base / net_util_unittest.cc
blobebc330754fd929a395d4ae2b6bc22ed40a02d2b3
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/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"
22 #include "url/gurl.h"
24 #if defined(OS_WIN)
25 #include <iphlpapi.h>
26 #include <objbase.h>
27 #include "base/win/windows_version.h"
28 #elif !defined(OS_ANDROID)
29 #include <net/if.h>
30 #endif // OS_WIN
32 using base::ASCIIToUTF16;
33 using base::WideToUTF16;
35 namespace net {
37 namespace {
39 static const size_t kNpos = base::string16::npos;
41 struct HeaderCase {
42 const char* header_name;
43 const char* expected;
46 struct HeaderParamCase {
47 const char* header_name;
48 const char* param_name;
49 const char* 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 UrlTestData {
388 const char* description;
389 const char* input;
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.
394 size_t prefix_len;
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,
432 size_t actual,
433 const std::string& original_url,
434 size_t position,
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) {
466 std::string out;
467 for (size_t i = 0; i < v.size(); ++i) {
468 if (i != 0)
469 out.append(",");
470 out.append(base::IntToString(static_cast<int>(v[i])));
472 return out;
475 } // anonymous namespace
477 TEST(NetUtilTest, GetIdentityFromURL) {
478 struct {
479 const char* input_url;
480 const char* expected_username;
481 const char* expected_password;
482 } tests[] = {
484 "http://username:password@google.com",
485 "username",
486 "password",
488 { // Test for http://crbug.com/19200
489 "http://username:p@ssword@google.com",
490 "username",
491 "p@ssword",
493 { // Special URL characters should be unescaped.
494 "http://username:p%3fa%26s%2fs%23@google.com",
495 "username",
496 "p?a&s/s#",
498 { // Username contains %20.
499 "http://use rname:password@google.com",
500 "use rname",
501 "password",
503 { // Keep %00 as is.
504 "http://use%00rname:password@google.com",
505 "use%00rname",
506 "password",
508 { // Use a '+' in the username.
509 "http://use+rname:password@google.com",
510 "use+rname",
511 "password",
513 { // Use a '&' in the password.
514 "http://username:p&ssword@google.com",
515 "username",
516 "p&ssword",
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 =
550 "HTTP/1.1 200 OK\n"
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"
563 "Server: GFE/1.3\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"},
576 {"Bad-Header", ""},
577 {"", ""},
580 // Test first with google_headers.
581 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
582 std::string result =
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)
599 continue;
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))
615 continue;
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[] = {
628 {"", "", false},
629 {"a", "", true},
630 {"-", "", false},
631 {".", "", false},
632 {"9", "", true},
633 {"9a", "", true},
634 {"a.", "", true},
635 {"a.a", "", true},
636 {"9.a", "", true},
637 {"a.9", "", true},
638 {"_9a", "", false},
639 {"-9a", "", false},
640 {"-9a", "a", true},
641 {"a.a9", "", true},
642 {"a.-a9", "", false},
643 {"a+9a", "", false},
644 {"-a.a9", "", true},
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.
668 #if defined(OS_WIN)
669 namespace {
671 struct GetDirectoryListingEntryCase {
672 const wchar_t* name;
673 const char* raw_bytes;
674 bool is_dir;
675 int64 filesize;
676 base::Time time;
677 const char* expected;
680 } // namespace
681 TEST(NetUtilTest, GetDirectoryListingEntry) {
682 const GetDirectoryListingEntryCase test_cases[] = {
683 {L"Foo",
685 false,
686 10000,
687 base::Time(),
688 "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
689 {L"quo\"tes",
691 false,
692 10000,
693 base::Time(),
694 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
695 "\n"},
696 {L"quo\"tes",
697 "quo\"tes",
698 false,
699 10000,
700 base::Time(),
701 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
702 "\n"},
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",
707 false,
708 10000,
709 base::Time(),
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",
716 false,
717 10000,
718 base::Time(),
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,
729 test_cases[i].time);
730 EXPECT_EQ(test_cases[i].expected, results);
734 #endif
736 TEST(NetUtilTest, ParseHostAndPort) {
737 const struct {
738 const char* input;
739 bool success;
740 const char* expected_host;
741 int expected_port;
742 } tests[] = {
743 // Valid inputs:
744 {"foo:10", true, "foo", 10},
745 {"foo", true, "foo", -1},
747 "[1080:0:0:0:8:800:200C:4171]:11",
748 true,
749 "[1080:0:0:0:8:800:200C:4171]",
752 // Invalid inputs:
753 {"foo:bar", false, "", -1},
754 {"foo:", false, "", -1},
755 {":", false, "", -1},
756 {":80", false, "", -1},
757 {"", 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) {
768 std::string host;
769 int port;
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) {
782 const struct {
783 GURL url;
784 const char* expected_host_and_port;
785 } tests[] = {
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) {
800 const struct {
801 GURL url;
802 const char* expected_host_and_port;
803 } tests[] = {
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) {
842 const struct {
843 uint8 addr[4];
844 const char* result;
845 } tests[] = {
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) {
860 const struct {
861 uint8 addr[16];
862 const char* result;
863 } tests[] = {
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,
882 storage.addr_len);
883 EXPECT_EQ("127.0.0.1:166", result);
886 TEST(NetUtilTest, NetAddressToStringWithPort_IPv6) {
887 uint8 addr[] = {
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,
894 storage.addr_len);
896 // May fail on systems that don't support IPv6.
897 if (!result.empty())
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},
914 {"Simple URL",
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 --------
978 {"Do not unescape",
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,
982 UnescapeRule::NONE,
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},
1016 {"omit http",
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: --------
1056 {"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/",
1059 19},
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
1067 // would.
1068 {"view-source omit http",
1069 "view-source:http://a.b/c", "en", kFormatUrlOmitAll,
1070 UnescapeRule::NORMAL, L"view-source:a.b/c",
1071 12},
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",
1075 19},
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",
1079 12},
1082 for (size_t i = 0; i < arraysize(tests); ++i) {
1083 size_t prefix_len;
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.
1094 url::Parsed parsed;
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,
1099 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));
1118 // Unescape case.
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,
1123 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,
1146 NULL, NULL);
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.
1163 formatted =
1164 FormatUrl(GURL("view-source:http://user:passwd@host:81/path?query#ref"),
1165 std::string(),
1166 kFormatUrlOmitUsernamePassword,
1167 UnescapeRule::NORMAL,
1168 &parsed,
1169 NULL,
1170 NULL);
1171 EXPECT_EQ(WideToUTF16(L"view-source:http://host:81/path?query#ref"),
1172 formatted);
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));
1188 // omit http case.
1189 formatted = FormatUrl(GURL("http://host:8000/a?b=c#d"),
1190 std::string(),
1191 kFormatUrlOmitHTTP,
1192 UnescapeRule::NORMAL,
1193 &parsed,
1194 NULL,
1195 NULL);
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"),
1213 std::string(),
1214 kFormatUrlOmitHTTP,
1215 UnescapeRule::NORMAL,
1216 &parsed,
1217 NULL,
1218 NULL);
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/"),
1238 std::string(),
1239 kFormatUrlOmitHTTP,
1240 UnescapeRule::NORMAL,
1241 &parsed,
1242 NULL,
1243 NULL);
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));
1264 size_t prefix_len;
1265 base::string16 formatted = FormatUrl(url,
1266 std::string(),
1267 kFormatUrlOmitUsernamePassword,
1268 UnescapeRule::NORMAL,
1269 NULL,
1270 &prefix_len,
1271 NULL);
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);
1285 size_t prefix_len;
1286 base::string16 formatted = FormatUrl(url,
1287 std::string(),
1288 kFormatUrlOmitUsernamePassword,
1289 UnescapeRule::NORMAL,
1290 NULL,
1291 &prefix_len,
1292 NULL);
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));
1303 size_t prefix_len;
1304 base::string16 formatted = FormatUrl(url,
1305 std::string(),
1306 kFormatUrlOmitUsernamePassword,
1307 UnescapeRule::NORMAL,
1308 NULL,
1309 &prefix_len,
1310 NULL);
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);
1328 size_t prefix_len;
1329 base::string16 formatted = FormatUrl(url,
1330 std::string(),
1331 kFormatUrlOmitUsernamePassword,
1332 UnescapeRule::NORMAL,
1333 NULL,
1334 &prefix_len,
1335 NULL);
1337 if (test_char &&
1338 strchr(kUnescapedCharacters, static_cast<char>(test_char))) {
1339 EXPECT_NE(url.spec(), GURL(formatted).spec());
1340 } else {
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,
1352 21, 22, 23, 24, 25
1354 CheckAdjustedOffsets("http://www.google.com/foo/", "en",
1355 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
1356 basic_offsets);
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,
1378 30, 31
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,
1439 10, 11, 12, 13, 14
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) {
1459 struct {
1460 const char* input_url;
1461 const char* expected_simplified_url;
1462 } tests[] = {
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[] = {
1603 "foobar",
1605 "192.168.0.1",
1606 "::1",
1607 "/",
1608 "/1",
1609 "1",
1610 "192.168.1.1/-1",
1611 "192.168.1.1/33",
1612 "::1/-3",
1613 "a::3/129",
1614 "::1/x",
1615 "192.168.0.1//11"
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],
1623 &ip_number,
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",
1634 &ip_number,
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) {
1642 struct {
1643 const char* cidr_literal;
1644 const char* ip_literal;
1645 bool expected_to_match;
1646 } tests[] = {
1647 // IPv4 prefix with IPv4 inputs.
1649 "10.10.1.32/27",
1650 "10.10.1.44",
1651 true
1654 "10.10.1.32/27",
1655 "10.10.1.90",
1656 false
1659 "10.10.1.32/27",
1660 "10.10.1.90",
1661 false
1664 // IPv6 prefix with IPv6 inputs.
1666 "2001:db8::/32",
1667 "2001:DB8:3:4::5",
1668 true
1671 "2001:db8::/32",
1672 "2001:c8::",
1673 false
1676 // IPv6 prefix with IPv4 inputs.
1678 "2001:db8::/33",
1679 "192.168.0.1",
1680 false
1683 "::ffff:192.168.0.1/112",
1684 "192.168.33.77",
1685 true
1688 // IPv4 prefix with IPv6 inputs.
1690 "10.11.33.44/16",
1691 "::ffff:0a0b:89",
1692 true
1695 "10.11.33.44/16",
1696 "::ffff:10.12.33.44",
1697 false
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,
1712 &ip_prefix,
1713 &prefix_length_in_bits));
1715 EXPECT_EQ(tests[i].expected_to_match,
1716 IPNumberMatchesPrefix(ip_number,
1717 ip_prefix,
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) {
1767 all_zeroes = false;
1768 break;
1771 EXPECT_FALSE(all_zeroes);
1772 EXPECT_GT(it->network_prefix, 1u);
1773 EXPECT_LE(it->network_prefix, it->address.size() * 8);
1775 #if defined(OS_WIN)
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,
1781 PNET_LUID);
1782 ConvertInterfaceIndexToLuid interface_to_luid =
1783 reinterpret_cast<ConvertInterfaceIndexToLuid>(
1784 phlpapi_lib.GetFunctionPointer("ConvertInterfaceIndexToLuid"));
1786 typedef NETIO_STATUS (WINAPI* ConvertInterfaceLuidToGuid)(NET_LUID*,
1787 GUID*);
1788 ConvertInterfaceLuidToGuid luid_to_guid =
1789 reinterpret_cast<ConvertInterfaceLuidToGuid>(
1790 phlpapi_lib.GetFunctionPointer("ConvertInterfaceLuidToGuid"));
1792 if (interface_to_luid && luid_to_guid) {
1793 NET_LUID luid;
1794 EXPECT_EQ(interface_to_luid(it->interface_index, &luid), NO_ERROR);
1795 GUID guid;
1796 EXPECT_EQ(luid_to_guid(&luid, &guid), NO_ERROR);
1797 LPOLESTR name;
1798 StringFromCLSID(guid, &name);
1799 EXPECT_STREQ(base::UTF8ToWide(it->name).c_str(), name);
1800 CoTaskMemFree(name);
1801 continue;
1802 } else {
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);
1814 #endif
1818 struct NonUniqueNameTestData {
1819 bool is_unique;
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" },
1841 { true, "212.15" },
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" },
1848 { false, "10.0" },
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> {
1877 public:
1878 virtual ~NetUtilNonUniqueNameTest() {}
1880 protected:
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
1888 // as unique names.
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));
1898 } // namespace net