Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / base / net_util_unittest.cc
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.
4
5 #include "net/base/net_util.h"
6
7 #include <string.h>
8
9 #include <algorithm>
10
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"
23
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
31
32 using base::ASCIIToUTF16;
33 using base::WideToUTF16;
34
35 namespace net {
36
37 namespace {
38
39 static const size_t kNpos = base::string16::npos;
40
41 struct HeaderCase {
42   const char* header_name;
43   const char* expected;
44 };
45
46 struct HeaderParamCase {
47   const char* header_name;
48   const char* param_name;
49   const char* expected;
50 };
51
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"
58 };
59
60 struct IDNTestCase {
61   const char* input;
62   const wchar_t* unicode_output;
63   const bool unicode_allowed[arraysize(kLanguages)];
64 };
65
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,
138     }},
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,
144     }},
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,
154     }},
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,
160     }},
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,
339   }},
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,
345   }},
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,
351   }},
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,
357   }},
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
374 };
375
376 struct AdjustOffsetCase {
377   size_t input_offset;
378   size_t output_offset;
379 };
380
381 struct CompliantHostCase {
382   const char* host;
383   const char* desired_tld;
384   bool expected_output;
385 };
386
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;
395 };
396
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);
406 }
407
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);
417 }
418
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);
428 }
429
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;
438 }
439
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);
462 }
463
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])));
471   }
472   return out;
473 }
474
475 }  // anonymous namespace
476
477 TEST(NetUtilTest, GetIdentityFromURL) {
478   struct {
479     const char* input_url;
480     const char* expected_username;
481     const char* expected_password;
482   } tests[] = {
483     {
484       "http://username:password@google.com",
485       "username",
486       "password",
487     },
488     { // Test for http://crbug.com/19200
489       "http://username:p@ssword@google.com",
490       "username",
491       "p@ssword",
492     },
493     { // Special URL characters should be unescaped.
494       "http://username:p%3fa%26s%2fs%23@google.com",
495       "username",
496       "p?a&s/s#",
497     },
498     { // Username contains %20.
499       "http://use rname:password@google.com",
500       "use rname",
501       "password",
502     },
503     { // Keep %00 as is.
504       "http://use%00rname:password@google.com",
505       "use%00rname",
506       "password",
507     },
508     { // Use a '+' in the username.
509       "http://use+rname:password@google.com",
510       "use+rname",
511       "password",
512     },
513     { // Use a '&' in the password.
514       "http://username:p&ssword@google.com",
515       "username",
516       "p&ssword",
517     },
518   };
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);
523
524     base::string16 username, password;
525     GetIdentityFromURL(url, &username, &password);
526
527     EXPECT_EQ(ASCIIToUTF16(tests[i].expected_username), username);
528     EXPECT_EQ(ASCIIToUTF16(tests[i].expected_password), password);
529   }
530 }
531
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"));
535
536   EXPECT_EQ("foo", url.username());
537   EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password());
538
539   // Extract the unescaped identity.
540   base::string16 username, password;
541   GetIdentityFromURL(url, &username, &password);
542
543   // Verify that it was decoded as UTF8.
544   EXPECT_EQ(ASCIIToUTF16("foo"), username);
545   EXPECT_EQ(WideToUTF16(L"\x4f60\x597d"), password);
546 }
547
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";
570
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     {"", ""},
578   };
579
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);
585   }
586
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());
591   }
592 }
593
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);
606     }
607   }
608 }
609
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);
622     }
623   }
624 }
625
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},
651   };
652
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));
657   }
658 }
659
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")));
665 }
666
667 // This is currently a windows specific function.
668 #if defined(OS_WIN)
669 namespace {
670
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;
678 };
679
680 }  // namespace
681 TEST(NetUtilTest, GetDirectoryListingEntry) {
682   const GetDirectoryListingEntryCase test_cases[] = {
683     {L"Foo",
684      "",
685      false,
686      10000,
687      base::Time(),
688      "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
689     {L"quo\"tes",
690      "",
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",
706      "",
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"},
721   };
722
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);
731   }
732 }
733
734 #endif
735
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},
746     {
747       "[1080:0:0:0:8:800:200C:4171]:11",
748       true,
749       "[1080:0:0:0:8:800:200C:4171]",
750       11,
751     },
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},
765   };
766
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);
771
772     EXPECT_EQ(tests[i].success, ok);
773
774     if (tests[i].success) {
775       EXPECT_EQ(tests[i].expected_host, host);
776       EXPECT_EQ(tests[i].expected_port, port);
777     }
778   }
779 }
780
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"},
788
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"},
792   };
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);
796   }
797 }
798
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"},
806
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"},
810   };
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);
814   }
815 }
816
817 TEST(NetUtilTest, IPAddressToString) {
818   uint8 addr1[4] = {0, 0, 0, 0};
819   EXPECT_EQ("0.0.0.0", IPAddressToString(addr1, sizeof(addr1)));
820
821   uint8 addr2[4] = {192, 168, 0, 1};
822   EXPECT_EQ("192.168.0.1", IPAddressToString(addr2, sizeof(addr2)));
823
824   uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
825   EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3, sizeof(addr3)));
826 }
827
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));
831
832   uint8 addr2[4] = {192, 168, 0, 1};
833   EXPECT_EQ("192.168.0.1:99",
834             IPAddressToStringWithPort(addr2, sizeof(addr2), 99));
835
836   uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
837   EXPECT_EQ("[fedc:ba98::]:8080",
838             IPAddressToStringWithPort(addr3, sizeof(addr3), 8080));
839 }
840
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"},
849   };
850
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);
856   }
857 }
858
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"},
867   };
868
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));
874   }
875 }
876
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);
884 }
885
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
890   };
891   SockaddrStorage storage;
892   MakeIPv6Address(addr, 361, &storage);
893   std::string result = NetAddressToStringWithPort(storage.addr,
894                                                   storage.addr_len);
895
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);
899 }
900
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());
907 }
908
909 TEST(NetUtilTest, FormatUrl) {
910   FormatUrlTypes default_format_type = kFormatUrlOmitUsernamePassword;
911   const UrlTestData tests[] = {
912     {"Empty URL", "", "", default_format_type, UnescapeRule::NORMAL, L"", 0},
913
914     {"Simple URL",
915      "http://www.google.com/", "", default_format_type, UnescapeRule::NORMAL,
916      L"http://www.google.com/", 7},
917
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},
922
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},
927
928     {"Japanese IDN with en",
929      "http://xn--l8jvb1ey91xtjb.jp", "en", default_format_type,
930      UnescapeRule::NORMAL, L"http://xn--l8jvb1ey91xtjb.jp/", 7},
931
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},
937
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},
943
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},
948
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},
953
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},
959
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},
963
964     {"With username and no password",
965      "http://user@example.com/foo", "", default_format_type,
966      UnescapeRule::NORMAL, L"http://example.com/foo", 7},
967
968     {"Just '@' without username and password",
969      "http://@example.com/foo", "", default_format_type, UnescapeRule::NORMAL,
970      L"http://example.com/foo", 7},
971
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},
976
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},
986
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},
994
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},
998
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},
1002
1003     /*
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},
1008     */
1009     // Disabled: the resultant URL becomes "...user%253A:%2540passwd...".
1010
1011     // -------- omit http: --------
1012     {"omit http with user name",
1013      "http://user@example.com/foo", "", kFormatUrlOmitAll,
1014      UnescapeRule::NORMAL, L"example.com/foo", 0},
1015
1016     {"omit http",
1017      "http://www.google.com/", "en", kFormatUrlOmitHTTP,
1018      UnescapeRule::NORMAL, L"www.google.com/",
1019      0},
1020
1021     {"omit http with https",
1022      "https://www.google.com/", "en", kFormatUrlOmitHTTP,
1023      UnescapeRule::NORMAL, L"https://www.google.com/",
1024      8},
1025
1026     {"omit http starts with ftp.",
1027      "http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
1028      UnescapeRule::NORMAL, L"http://ftp.google.com/",
1029      7},
1030
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},
1054
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},
1060
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},
1065
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},
1080   };
1081
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;
1089   }
1090 }
1091
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));
1117
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));
1140
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));
1161
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));
1187
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));
1210
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));
1235
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));
1256 }
1257
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());
1273   }
1274 }
1275
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));
1283
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());
1294   }
1295 }
1296
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());
1312   }
1313 }
1314
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));
1326
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);
1336
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());
1342     }
1343   }
1344 }
1345
1346 TEST(NetUtilTest, FormatUrlWithOffsets) {
1347   CheckAdjustedOffsets(std::string(), "en", kFormatUrlOmitNothing,
1348                        UnescapeRule::NORMAL, NULL);
1349
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
1353   };
1354   CheckAdjustedOffsets("http://www.google.com/foo/", "en",
1355                        kFormatUrlOmitNothing, UnescapeRule::NORMAL,
1356                        basic_offsets);
1357
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
1361   };
1362   CheckAdjustedOffsets("http://foo:bar@www.google.com/", "en",
1363                        kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
1364                        omit_auth_offsets_1);
1365
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
1369   };
1370   CheckAdjustedOffsets("http://foo@www.google.com/", "en",
1371                        kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
1372                        omit_auth_offsets_2);
1373
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
1379   };
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);
1384
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
1388   };
1389   CheckAdjustedOffsets("view-source:http://foo@www.google.com/", "en",
1390                        kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
1391                        view_source_offsets);
1392
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
1397   };
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);
1402
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
1408   };
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);
1414
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
1421   };
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);
1426
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,
1430     33
1431   };
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);
1436
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
1440   };
1441   CheckAdjustedOffsets("http://www.google.com/", "en", kFormatUrlOmitHTTP,
1442                        UnescapeRule::NORMAL, omit_http_offsets);
1443
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
1446   };
1447   CheckAdjustedOffsets("http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
1448                        UnescapeRule::NORMAL, omit_http_start_with_ftp_offsets);
1449
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
1453   };
1454   CheckAdjustedOffsets("http://user@foo.com/", "en", kFormatUrlOmitAll,
1455                        UnescapeRule::NORMAL, omit_all_offsets);
1456 }
1457
1458 TEST(NetUtilTest, SimplifyUrlForRequest) {
1459   struct {
1460     const char* input_url;
1461     const char* expected_simplified_url;
1462   } tests[] = {
1463     {
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",
1467     },
1468     {
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",
1472     },
1473     { // Strip username/password.
1474       "http://user:pass@google.com",
1475       "http://google.com/",
1476     },
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",
1480     },
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",
1484     },
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",
1488     },
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",
1492     },
1493   };
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));
1500   }
1501 }
1502
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" };
1506
1507   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(invalid); ++i) {
1508     SetExplicitlyAllowedPorts(invalid[i]);
1509     EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts()));
1510   }
1511
1512   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid); ++i) {
1513     SetExplicitlyAllowedPorts(valid[i]);
1514     EXPECT_EQ(i, GetCountOfExplicitlyAllowedPorts());
1515   }
1516 }
1517
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")));
1525 }
1526
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));
1533 }
1534
1535 // Test that invalid IP literals fail to parse.
1536 TEST(NetUtilTest, ParseIPLiteralToNumber_FailParse) {
1537   IPAddressNumber number;
1538
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));
1545 }
1546
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));
1553 }
1554
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));
1561 }
1562
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));
1567
1568   IPAddressNumber ipv6_number =
1569       ConvertIPv4NumberToIPv6Number(ipv4_number);
1570
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));
1575 }
1576
1577 TEST(NetUtilTest, IsIPv4Mapped) {
1578   IPAddressNumber ipv4_number;
1579   EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
1580   EXPECT_FALSE(IsIPv4Mapped(ipv4_number));
1581
1582   IPAddressNumber ipv6_number;
1583   EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number));
1584   EXPECT_FALSE(IsIPv4Mapped(ipv6_number));
1585
1586   IPAddressNumber ipv4mapped_number;
1587   EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
1588   EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number));
1589 }
1590
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);
1598 }
1599
1600 // Test parsing invalid CIDR notation literals.
1601 TEST(NetUtilTest, ParseCIDRBlock_Invalid) {
1602   const char* bad_literals[] = {
1603       "foobar",
1604       "",
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"
1616   };
1617
1618   for (size_t i = 0; i < arraysize(bad_literals); ++i) {
1619     IPAddressNumber ip_number;
1620     size_t prefix_length_in_bits;
1621
1622     EXPECT_FALSE(ParseCIDRBlock(bad_literals[i],
1623                                      &ip_number,
1624                                      &prefix_length_in_bits));
1625   }
1626 }
1627
1628 // Test parsing a valid CIDR notation literal.
1629 TEST(NetUtilTest, ParseCIDRBlock_Valid) {
1630   IPAddressNumber ip_number;
1631   size_t prefix_length_in_bits;
1632
1633   EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
1634                                   &ip_number,
1635                                   &prefix_length_in_bits));
1636
1637   EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number));
1638   EXPECT_EQ(11u, prefix_length_in_bits);
1639 }
1640
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.
1648     {
1649       "10.10.1.32/27",
1650       "10.10.1.44",
1651       true
1652     },
1653     {
1654       "10.10.1.32/27",
1655       "10.10.1.90",
1656       false
1657     },
1658     {
1659       "10.10.1.32/27",
1660       "10.10.1.90",
1661       false
1662     },
1663
1664     // IPv6 prefix with IPv6 inputs.
1665     {
1666       "2001:db8::/32",
1667       "2001:DB8:3:4::5",
1668       true
1669     },
1670     {
1671       "2001:db8::/32",
1672       "2001:c8::",
1673       false
1674     },
1675
1676     // IPv6 prefix with IPv4 inputs.
1677     {
1678       "2001:db8::/33",
1679       "192.168.0.1",
1680       false
1681     },
1682     {
1683       "::ffff:192.168.0.1/112",
1684       "192.168.33.77",
1685       true
1686     },
1687
1688     // IPv4 prefix with IPv6 inputs.
1689     {
1690       "10.11.33.44/16",
1691       "::ffff:0a0b:89",
1692       true
1693     },
1694     {
1695       "10.11.33.44/16",
1696       "::ffff:10.12.33.44",
1697       false
1698     },
1699   };
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));
1704
1705     IPAddressNumber ip_number;
1706     EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number));
1707
1708     IPAddressNumber ip_prefix;
1709     size_t prefix_length_in_bits;
1710
1711     EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal,
1712                                &ip_prefix,
1713                                &prefix_length_in_bits));
1714
1715     EXPECT_EQ(tests[i].expected_to_match,
1716               IPNumberMatchesPrefix(ip_number,
1717                                     ip_prefix,
1718                                     prefix_length_in_bits));
1719   }
1720 }
1721
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"));
1735
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"));
1748 }
1749
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());
1759
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;
1769       }
1770     }
1771     EXPECT_FALSE(all_zeroes);
1772     EXPECT_GT(it->network_prefix, 1u);
1773     EXPECT_LE(it->network_prefix, it->address.size() * 8);
1774
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"));
1785
1786     typedef NETIO_STATUS (WINAPI* ConvertInterfaceLuidToGuid)(NET_LUID*,
1787                                                               GUID*);
1788     ConvertInterfaceLuidToGuid luid_to_guid =
1789         reinterpret_cast<ConvertInterfaceLuidToGuid>(
1790             phlpapi_lib.GetFunctionPointer("ConvertInterfaceLuidToGuid"));
1791
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.
1806     }
1807     if (it->type == NetworkChangeNotifier::CONNECTION_WIFI) {
1808       EXPECT_NE(WIFI_PHY_LAYER_PROTOCOL_NONE, GetWifiPHYLayerProtocol());
1809     }
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
1815   }
1816 }
1817
1818 struct NonUniqueNameTestData {
1819   bool is_unique;
1820   const char* hostname;
1821 };
1822
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);
1828 }
1829
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]" },
1873 };
1874
1875 class NetUtilNonUniqueNameTest
1876     : public testing::TestWithParam<NonUniqueNameTestData> {
1877  public:
1878   virtual ~NetUtilNonUniqueNameTest() {}
1879
1880  protected:
1881   bool IsUnique(const std::string& hostname) {
1882     return !IsHostnameNonUnique(hostname);
1883   }
1884 };
1885
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();
1891
1892   EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
1893 }
1894
1895 INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest,
1896                         testing::ValuesIn(kNonUniqueNameTestData));
1897
1898 }  // namespace net