Home | History | Annotate | Download | only in url
      1 // Copyright 2013 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 "testing/gtest/include/gtest/gtest.h"
      6 #include "url/gurl.h"
      7 #include "url/url_canon.h"
      8 #include "url/url_test_utils.h"
      9 
     10 // Some implementations of base/basictypes.h may define ARRAYSIZE.
     11 // If it's not defined, we define it to the ARRAYSIZE_UNSAFE macro
     12 // which is in our version of basictypes.h.
     13 #ifndef ARRAYSIZE
     14 #define ARRAYSIZE ARRAYSIZE_UNSAFE
     15 #endif
     16 
     17 namespace url {
     18 
     19 using test_utils::WStringToUTF16;
     20 using test_utils::ConvertUTF8ToUTF16;
     21 
     22 namespace {
     23 
     24 template<typename CHAR>
     25 void SetupReplacement(
     26     void (Replacements<CHAR>::*func)(const CHAR*, const Component&),
     27     Replacements<CHAR>* replacements,
     28     const CHAR* str) {
     29   if (str) {
     30     Component comp;
     31     if (str[0])
     32       comp.len = static_cast<int>(strlen(str));
     33     (replacements->*func)(str, comp);
     34   }
     35 }
     36 
     37 // Returns the canonicalized string for the given URL string for the
     38 // GURLTest.Types test.
     39 std::string TypesTestCase(const char* src) {
     40   GURL gurl(src);
     41   return gurl.possibly_invalid_spec();
     42 }
     43 
     44 }  // namespace
     45 
     46 // Different types of URLs should be handled differently, and handed off to
     47 // different canonicalizers.
     48 TEST(GURLTest, Types) {
     49   // URLs with unknown schemes should be treated as path URLs, even when they
     50   // have things like "://".
     51   EXPECT_EQ("something:///HOSTNAME.com/",
     52             TypesTestCase("something:///HOSTNAME.com/"));
     53 
     54   // In the reverse, known schemes should always trigger standard URL handling.
     55   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:HOSTNAME.com"));
     56   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:/HOSTNAME.com"));
     57   EXPECT_EQ("http://hostname.com/", TypesTestCase("http://HOSTNAME.com"));
     58   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:///HOSTNAME.com"));
     59 
     60 #ifdef WIN32
     61   // URLs that look like absolute Windows drive specs.
     62   EXPECT_EQ("file:///C:/foo.txt", TypesTestCase("c:\\foo.txt"));
     63   EXPECT_EQ("file:///Z:/foo.txt", TypesTestCase("Z|foo.txt"));
     64   EXPECT_EQ("file://server/foo.txt", TypesTestCase("\\\\server\\foo.txt"));
     65   EXPECT_EQ("file://server/foo.txt", TypesTestCase("//server/foo.txt"));
     66 #endif
     67 }
     68 
     69 // Test the basic creation and querying of components in a GURL. We assume
     70 // the parser is already tested and works, so we are mostly interested if the
     71 // object does the right thing with the results.
     72 TEST(GURLTest, Components) {
     73   GURL url(WStringToUTF16(L"http://user:pass@google.com:99/foo;bar?q=a#ref"));
     74   EXPECT_TRUE(url.is_valid());
     75   EXPECT_TRUE(url.SchemeIs("http"));
     76   EXPECT_FALSE(url.SchemeIsFile());
     77 
     78   // This is the narrow version of the URL, which should match the wide input.
     79   EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url.spec());
     80 
     81   EXPECT_EQ("http", url.scheme());
     82   EXPECT_EQ("user", url.username());
     83   EXPECT_EQ("pass", url.password());
     84   EXPECT_EQ("google.com", url.host());
     85   EXPECT_EQ("99", url.port());
     86   EXPECT_EQ(99, url.IntPort());
     87   EXPECT_EQ("/foo;bar", url.path());
     88   EXPECT_EQ("q=a", url.query());
     89   EXPECT_EQ("ref", url.ref());
     90 
     91   // Test parsing userinfo with special characters.
     92   GURL url_special_pass("http://user:%40!$&'()*+,;=:@google.com:12345");
     93   EXPECT_TRUE(url_special_pass.is_valid());
     94   // GURL canonicalizes some delimiters.
     95   EXPECT_EQ("%40!$&%27()*+,%3B%3D%3A", url_special_pass.password());
     96   EXPECT_EQ("google.com", url_special_pass.host());
     97   EXPECT_EQ("12345", url_special_pass.port());
     98 }
     99 
    100 TEST(GURLTest, Empty) {
    101   GURL url;
    102   EXPECT_FALSE(url.is_valid());
    103   EXPECT_EQ("", url.spec());
    104 
    105   EXPECT_EQ("", url.scheme());
    106   EXPECT_EQ("", url.username());
    107   EXPECT_EQ("", url.password());
    108   EXPECT_EQ("", url.host());
    109   EXPECT_EQ("", url.port());
    110   EXPECT_EQ(PORT_UNSPECIFIED, url.IntPort());
    111   EXPECT_EQ("", url.path());
    112   EXPECT_EQ("", url.query());
    113   EXPECT_EQ("", url.ref());
    114 }
    115 
    116 TEST(GURLTest, Copy) {
    117   GURL url(WStringToUTF16(L"http://user:pass@google.com:99/foo;bar?q=a#ref"));
    118 
    119   GURL url2(url);
    120   EXPECT_TRUE(url2.is_valid());
    121 
    122   EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
    123   EXPECT_EQ("http", url2.scheme());
    124   EXPECT_EQ("user", url2.username());
    125   EXPECT_EQ("pass", url2.password());
    126   EXPECT_EQ("google.com", url2.host());
    127   EXPECT_EQ("99", url2.port());
    128   EXPECT_EQ(99, url2.IntPort());
    129   EXPECT_EQ("/foo;bar", url2.path());
    130   EXPECT_EQ("q=a", url2.query());
    131   EXPECT_EQ("ref", url2.ref());
    132 
    133   // Copying of invalid URL should be invalid
    134   GURL invalid;
    135   GURL invalid2(invalid);
    136   EXPECT_FALSE(invalid2.is_valid());
    137   EXPECT_EQ("", invalid2.spec());
    138   EXPECT_EQ("", invalid2.scheme());
    139   EXPECT_EQ("", invalid2.username());
    140   EXPECT_EQ("", invalid2.password());
    141   EXPECT_EQ("", invalid2.host());
    142   EXPECT_EQ("", invalid2.port());
    143   EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
    144   EXPECT_EQ("", invalid2.path());
    145   EXPECT_EQ("", invalid2.query());
    146   EXPECT_EQ("", invalid2.ref());
    147 }
    148 
    149 TEST(GURLTest, Assign) {
    150   GURL url(WStringToUTF16(L"http://user:pass@google.com:99/foo;bar?q=a#ref"));
    151 
    152   GURL url2;
    153   url2 = url;
    154   EXPECT_TRUE(url2.is_valid());
    155 
    156   EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
    157   EXPECT_EQ("http", url2.scheme());
    158   EXPECT_EQ("user", url2.username());
    159   EXPECT_EQ("pass", url2.password());
    160   EXPECT_EQ("google.com", url2.host());
    161   EXPECT_EQ("99", url2.port());
    162   EXPECT_EQ(99, url2.IntPort());
    163   EXPECT_EQ("/foo;bar", url2.path());
    164   EXPECT_EQ("q=a", url2.query());
    165   EXPECT_EQ("ref", url2.ref());
    166 
    167   // Assignment of invalid URL should be invalid
    168   GURL invalid;
    169   GURL invalid2;
    170   invalid2 = invalid;
    171   EXPECT_FALSE(invalid2.is_valid());
    172   EXPECT_EQ("", invalid2.spec());
    173   EXPECT_EQ("", invalid2.scheme());
    174   EXPECT_EQ("", invalid2.username());
    175   EXPECT_EQ("", invalid2.password());
    176   EXPECT_EQ("", invalid2.host());
    177   EXPECT_EQ("", invalid2.port());
    178   EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
    179   EXPECT_EQ("", invalid2.path());
    180   EXPECT_EQ("", invalid2.query());
    181   EXPECT_EQ("", invalid2.ref());
    182 }
    183 
    184 // This is a regression test for http://crbug.com/309975 .
    185 TEST(GURLTest, SelfAssign) {
    186   GURL a("filesystem:http://example.com/temporary/");
    187   // This should not crash.
    188   a = a;
    189 }
    190 
    191 TEST(GURLTest, CopyFileSystem) {
    192   GURL url(WStringToUTF16(L"filesystem:https://user:pass@google.com:99/t/foo;bar?q=a#ref"));
    193 
    194   GURL url2(url);
    195   EXPECT_TRUE(url2.is_valid());
    196 
    197   EXPECT_EQ("filesystem:https://user:pass@google.com:99/t/foo;bar?q=a#ref", url2.spec());
    198   EXPECT_EQ("filesystem", url2.scheme());
    199   EXPECT_EQ("", url2.username());
    200   EXPECT_EQ("", url2.password());
    201   EXPECT_EQ("", url2.host());
    202   EXPECT_EQ("", url2.port());
    203   EXPECT_EQ(PORT_UNSPECIFIED, url2.IntPort());
    204   EXPECT_EQ("/foo;bar", url2.path());
    205   EXPECT_EQ("q=a", url2.query());
    206   EXPECT_EQ("ref", url2.ref());
    207 
    208   const GURL* inner = url2.inner_url();
    209   ASSERT_TRUE(inner);
    210   EXPECT_EQ("https", inner->scheme());
    211   EXPECT_EQ("user", inner->username());
    212   EXPECT_EQ("pass", inner->password());
    213   EXPECT_EQ("google.com", inner->host());
    214   EXPECT_EQ("99", inner->port());
    215   EXPECT_EQ(99, inner->IntPort());
    216   EXPECT_EQ("/t", inner->path());
    217   EXPECT_EQ("", inner->query());
    218   EXPECT_EQ("", inner->ref());
    219 }
    220 
    221 TEST(GURLTest, IsValid) {
    222   const char* valid_cases[] = {
    223     "http://google.com",
    224     "unknown://google.com",
    225     "http://user:pass@google.com",
    226     "http://google.com:12345",
    227     "http://google.com/path",
    228     "http://google.com//path",
    229     "http://google.com?k=v#fragment",
    230     "http://user:pass@google.com:12345/path?k=v#fragment",
    231     "http:/path",
    232     "http:path",
    233     "://google.com",
    234   };
    235   for (size_t i = 0; i < ARRAYSIZE(valid_cases); i++) {
    236     EXPECT_TRUE(GURL(valid_cases[i]).is_valid())
    237         << "Case: " << valid_cases[i];
    238   }
    239 
    240   const char* invalid_cases[] = {
    241     "http://?k=v",
    242     "http:://google.com",
    243     "http//google.com",
    244     "http://google.com:12three45",
    245     "path",
    246   };
    247   for (size_t i = 0; i < ARRAYSIZE(invalid_cases); i++) {
    248     EXPECT_FALSE(GURL(invalid_cases[i]).is_valid())
    249         << "Case: " << invalid_cases[i];
    250   }
    251 }
    252 
    253 TEST(GURLTest, ExtraSlashesBeforeAuthority) {
    254   // According to RFC3986, the hier-part for URI with an authority must use only
    255   // two slashes, GURL intentionally just ignores slashes more than 2 and parses
    256   // the following part as an authority.
    257   GURL url("http:///host");
    258   EXPECT_EQ("host", url.host());
    259   EXPECT_EQ("/", url.path());
    260 }
    261 
    262 // Given an invalid URL, we should still get most of the components.
    263 TEST(GURLTest, ComponentGettersWorkEvenForInvalidURL) {
    264   GURL url("http:google.com:foo");
    265   EXPECT_FALSE(url.is_valid());
    266   EXPECT_EQ("http://google.com:foo/", url.possibly_invalid_spec());
    267 
    268   EXPECT_EQ("http", url.scheme());
    269   EXPECT_EQ("", url.username());
    270   EXPECT_EQ("", url.password());
    271   EXPECT_EQ("google.com", url.host());
    272   EXPECT_EQ("foo", url.port());
    273   EXPECT_EQ(PORT_INVALID, url.IntPort());
    274   EXPECT_EQ("/", url.path());
    275   EXPECT_EQ("", url.query());
    276   EXPECT_EQ("", url.ref());
    277 }
    278 
    279 TEST(GURLTest, Resolve) {
    280   // The tricky cases for relative URL resolving are tested in the
    281   // canonicalizer unit test. Here, we just test that the GURL integration
    282   // works properly.
    283   struct ResolveCase {
    284     const char* base;
    285     const char* relative;
    286     bool expected_valid;
    287     const char* expected;
    288   } resolve_cases[] = {
    289     {"http://www.google.com/", "foo.html", true, "http://www.google.com/foo.html"},
    290     {"http://www.google.com/", "http://images.google.com/foo.html", true, "http://images.google.com/foo.html"},
    291     {"http://www.google.com/blah/bloo?c#d", "../../../hello/./world.html?a#b", true, "http://www.google.com/hello/world.html?a#b"},
    292     {"http://www.google.com/foo#bar", "#com", true, "http://www.google.com/foo#com"},
    293     {"http://www.google.com/", "Https:images.google.com", true, "https://images.google.com/"},
    294       // A non-standard base can be replaced with a standard absolute URL.
    295     {"data:blahblah", "http://google.com/", true, "http://google.com/"},
    296     {"data:blahblah", "http:google.com", true, "http://google.com/"},
    297       // Filesystem URLs have different paths to test.
    298     {"filesystem:http://www.google.com/type/", "foo.html", true, "filesystem:http://www.google.com/type/foo.html"},
    299     {"filesystem:http://www.google.com/type/", "../foo.html", true, "filesystem:http://www.google.com/type/foo.html"},
    300   };
    301 
    302   for (size_t i = 0; i < ARRAYSIZE(resolve_cases); i++) {
    303     // 8-bit code path.
    304     GURL input(resolve_cases[i].base);
    305     GURL output = input.Resolve(resolve_cases[i].relative);
    306     EXPECT_EQ(resolve_cases[i].expected_valid, output.is_valid()) << i;
    307     EXPECT_EQ(resolve_cases[i].expected, output.spec()) << i;
    308     EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
    309 
    310     // Wide code path.
    311     GURL inputw(ConvertUTF8ToUTF16(resolve_cases[i].base));
    312     GURL outputw =
    313         input.Resolve(ConvertUTF8ToUTF16(resolve_cases[i].relative));
    314     EXPECT_EQ(resolve_cases[i].expected_valid, outputw.is_valid()) << i;
    315     EXPECT_EQ(resolve_cases[i].expected, outputw.spec()) << i;
    316     EXPECT_EQ(outputw.SchemeIsFileSystem(), outputw.inner_url() != NULL);
    317   }
    318 }
    319 
    320 TEST(GURLTest, GetOrigin) {
    321   struct TestCase {
    322     const char* input;
    323     const char* expected;
    324   } cases[] = {
    325     {"http://www.google.com", "http://www.google.com/"},
    326     {"javascript:window.alert(\"hello,world\");", ""},
    327     {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/"},
    328     {"http://user@www.google.com", "http://www.google.com/"},
    329     {"http://:pass@www.google.com", "http://www.google.com/"},
    330     {"http://:@www.google.com", "http://www.google.com/"},
    331     {"filesystem:http://www.google.com/temp/foo?q#b", "http://www.google.com/"},
    332     {"filesystem:http://user:pass@google.com:21/blah#baz", "http://google.com:21/"},
    333   };
    334   for (size_t i = 0; i < ARRAYSIZE(cases); i++) {
    335     GURL url(cases[i].input);
    336     GURL origin = url.GetOrigin();
    337     EXPECT_EQ(cases[i].expected, origin.spec());
    338   }
    339 }
    340 
    341 TEST(GURLTest, GetAsReferrer) {
    342   struct TestCase {
    343     const char* input;
    344     const char* expected;
    345   } cases[] = {
    346     {"http://www.google.com", "http://www.google.com/"},
    347     {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/blah"},
    348     {"http://user@www.google.com", "http://www.google.com/"},
    349     {"http://:pass@www.google.com", "http://www.google.com/"},
    350     {"http://:@www.google.com", "http://www.google.com/"},
    351     {"http://www.google.com/temp/foo?q#b", "http://www.google.com/temp/foo?q"},
    352   };
    353   for (size_t i = 0; i < ARRAYSIZE(cases); i++) {
    354     GURL url(cases[i].input);
    355     GURL origin = url.GetAsReferrer();
    356     EXPECT_EQ(cases[i].expected, origin.spec());
    357   }
    358 }
    359 
    360 TEST(GURLTest, GetWithEmptyPath) {
    361   struct TestCase {
    362     const char* input;
    363     const char* expected;
    364   } cases[] = {
    365     {"http://www.google.com", "http://www.google.com/"},
    366     {"javascript:window.alert(\"hello, world\");", ""},
    367     {"http://www.google.com/foo/bar.html?baz=22", "http://www.google.com/"},
    368     {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
    369     {"filesystem:file:///temporary/bar.html?baz=22", "filesystem:file:///temporary/"},
    370   };
    371 
    372   for (size_t i = 0; i < ARRAYSIZE(cases); i++) {
    373     GURL url(cases[i].input);
    374     GURL empty_path = url.GetWithEmptyPath();
    375     EXPECT_EQ(cases[i].expected, empty_path.spec());
    376   }
    377 }
    378 
    379 TEST(GURLTest, Replacements) {
    380   // The url canonicalizer replacement test will handle most of these case.
    381   // The most important thing to do here is to check that the proper
    382   // canonicalizer gets called based on the scheme of the input.
    383   struct ReplaceCase {
    384     const char* base;
    385     const char* scheme;
    386     const char* username;
    387     const char* password;
    388     const char* host;
    389     const char* port;
    390     const char* path;
    391     const char* query;
    392     const char* ref;
    393     const char* expected;
    394   } replace_cases[] = {
    395     {"http://www.google.com/foo/bar.html?foo#bar", NULL, NULL, NULL, NULL, NULL, "/", "", "", "http://www.google.com/"},
    396     {"http://www.google.com/foo/bar.html?foo#bar", "javascript", "", "", "", "", "window.open('foo');", "", "", "javascript:window.open('foo');"},
    397     {"file:///C:/foo/bar.txt", "http", NULL, NULL, "www.google.com", "99", "/foo","search", "ref", "http://www.google.com:99/foo?search#ref"},
    398 #ifdef WIN32
    399     {"http://www.google.com/foo/bar.html?foo#bar", "file", "", "", "", "", "c:\\", "", "", "file:///C:/"},
    400 #endif
    401     {"filesystem:http://www.google.com/foo/bar.html?foo#bar", NULL, NULL, NULL, NULL, NULL, "/", "", "", "filesystem:http://www.google.com/foo/"},
    402   };
    403 
    404   for (size_t i = 0; i < ARRAYSIZE(replace_cases); i++) {
    405     const ReplaceCase& cur = replace_cases[i];
    406     GURL url(cur.base);
    407     GURL::Replacements repl;
    408     SetupReplacement(&GURL::Replacements::SetScheme, &repl, cur.scheme);
    409     SetupReplacement(&GURL::Replacements::SetUsername, &repl, cur.username);
    410     SetupReplacement(&GURL::Replacements::SetPassword, &repl, cur.password);
    411     SetupReplacement(&GURL::Replacements::SetHost, &repl, cur.host);
    412     SetupReplacement(&GURL::Replacements::SetPort, &repl, cur.port);
    413     SetupReplacement(&GURL::Replacements::SetPath, &repl, cur.path);
    414     SetupReplacement(&GURL::Replacements::SetQuery, &repl, cur.query);
    415     SetupReplacement(&GURL::Replacements::SetRef, &repl, cur.ref);
    416     GURL output = url.ReplaceComponents(repl);
    417 
    418     EXPECT_EQ(replace_cases[i].expected, output.spec());
    419     EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
    420   }
    421 }
    422 
    423 TEST(GURLTest, ClearFragmentOnDataUrl) {
    424   // http://crbug.com/291747 - a data URL may legitimately have trailing
    425   // whitespace in the spec after the ref is cleared. Test this does not trigger
    426   // the Parsed importing validation DCHECK in GURL.
    427   GURL url(" data: one ? two # three ");
    428 
    429   // By default the trailing whitespace will have been stripped.
    430   EXPECT_EQ("data: one ? two # three", url.spec());
    431   GURL::Replacements repl;
    432   repl.ClearRef();
    433   GURL url_no_ref = url.ReplaceComponents(repl);
    434 
    435   EXPECT_EQ("data: one ? two ", url_no_ref.spec());
    436 
    437   // Importing a parsed url via this constructor overload will retain trailing
    438   // whitespace.
    439   GURL import_url(url_no_ref.spec(),
    440                   url_no_ref.parsed_for_possibly_invalid_spec(),
    441                   url_no_ref.is_valid());
    442   EXPECT_EQ(url_no_ref, import_url);
    443   EXPECT_EQ(import_url.query(), " two ");
    444 }
    445 
    446 TEST(GURLTest, PathForRequest) {
    447   struct TestCase {
    448     const char* input;
    449     const char* expected;
    450     const char* inner_expected;
    451   } cases[] = {
    452     {"http://www.google.com", "/", NULL},
    453     {"http://www.google.com/", "/", NULL},
    454     {"http://www.google.com/foo/bar.html?baz=22", "/foo/bar.html?baz=22", NULL},
    455     {"http://www.google.com/foo/bar.html#ref", "/foo/bar.html", NULL},
    456     {"http://www.google.com/foo/bar.html?query#ref", "/foo/bar.html?query", NULL},
    457     {"filesystem:http://www.google.com/temporary/foo/bar.html?query#ref", "/foo/bar.html?query", "/temporary"},
    458     {"filesystem:http://www.google.com/temporary/foo/bar.html?query", "/foo/bar.html?query", "/temporary"},
    459   };
    460 
    461   for (size_t i = 0; i < ARRAYSIZE(cases); i++) {
    462     GURL url(cases[i].input);
    463     std::string path_request = url.PathForRequest();
    464     EXPECT_EQ(cases[i].expected, path_request);
    465     EXPECT_EQ(cases[i].inner_expected == NULL, url.inner_url() == NULL);
    466     if (url.inner_url() && cases[i].inner_expected)
    467       EXPECT_EQ(cases[i].inner_expected, url.inner_url()->PathForRequest());
    468   }
    469 }
    470 
    471 TEST(GURLTest, EffectiveIntPort) {
    472   struct PortTest {
    473     const char* spec;
    474     int expected_int_port;
    475   } port_tests[] = {
    476     // http
    477     {"http://www.google.com/", 80},
    478     {"http://www.google.com:80/", 80},
    479     {"http://www.google.com:443/", 443},
    480 
    481     // https
    482     {"https://www.google.com/", 443},
    483     {"https://www.google.com:443/", 443},
    484     {"https://www.google.com:80/", 80},
    485 
    486     // ftp
    487     {"ftp://www.google.com/", 21},
    488     {"ftp://www.google.com:21/", 21},
    489     {"ftp://www.google.com:80/", 80},
    490 
    491     // gopher
    492     {"gopher://www.google.com/", 70},
    493     {"gopher://www.google.com:70/", 70},
    494     {"gopher://www.google.com:80/", 80},
    495 
    496     // file - no port
    497     {"file://www.google.com/", PORT_UNSPECIFIED},
    498     {"file://www.google.com:443/", PORT_UNSPECIFIED},
    499 
    500     // data - no port
    501     {"data:www.google.com:90", PORT_UNSPECIFIED},
    502     {"data:www.google.com", PORT_UNSPECIFIED},
    503 
    504     // filesystem - no port
    505     {"filesystem:http://www.google.com:90/t/foo", PORT_UNSPECIFIED},
    506     {"filesystem:file:///t/foo", PORT_UNSPECIFIED},
    507   };
    508 
    509   for (size_t i = 0; i < ARRAYSIZE(port_tests); i++) {
    510     GURL url(port_tests[i].spec);
    511     EXPECT_EQ(port_tests[i].expected_int_port, url.EffectiveIntPort());
    512   }
    513 }
    514 
    515 TEST(GURLTest, IPAddress) {
    516   struct IPTest {
    517     const char* spec;
    518     bool expected_ip;
    519   } ip_tests[] = {
    520     {"http://www.google.com/", false},
    521     {"http://192.168.9.1/", true},
    522     {"http://192.168.9.1.2/", false},
    523     {"http://192.168.m.1/", false},
    524     {"http://2001:db8::1/", false},
    525     {"http://[2001:db8::1]/", true},
    526     {"", false},
    527     {"some random input!", false},
    528   };
    529 
    530   for (size_t i = 0; i < ARRAYSIZE(ip_tests); i++) {
    531     GURL url(ip_tests[i].spec);
    532     EXPECT_EQ(ip_tests[i].expected_ip, url.HostIsIPAddress());
    533   }
    534 }
    535 
    536 TEST(GURLTest, HostNoBrackets) {
    537   struct TestCase {
    538     const char* input;
    539     const char* expected_host;
    540     const char* expected_plainhost;
    541   } cases[] = {
    542     {"http://www.google.com", "www.google.com", "www.google.com"},
    543     {"http://[2001:db8::1]/", "[2001:db8::1]", "2001:db8::1"},
    544     {"http://[::]/", "[::]", "::"},
    545 
    546     // Don't require a valid URL, but don't crash either.
    547     {"http://[]/", "[]", ""},
    548     {"http://[x]/", "[x]", "x"},
    549     {"http://[x/", "[x", "[x"},
    550     {"http://x]/", "x]", "x]"},
    551     {"http://[/", "[", "["},
    552     {"http://]/", "]", "]"},
    553     {"", "", ""},
    554   };
    555   for (size_t i = 0; i < ARRAYSIZE(cases); i++) {
    556     GURL url(cases[i].input);
    557     EXPECT_EQ(cases[i].expected_host, url.host());
    558     EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBrackets());
    559   }
    560 }
    561 
    562 TEST(GURLTest, DomainIs) {
    563   const char google_domain[] = "google.com";
    564 
    565   GURL url_1("http://www.google.com:99/foo");
    566   EXPECT_TRUE(url_1.DomainIs(google_domain));
    567 
    568   GURL url_2("http://google.com:99/foo");
    569   EXPECT_TRUE(url_2.DomainIs(google_domain));
    570 
    571   GURL url_3("http://google.com./foo");
    572   EXPECT_TRUE(url_3.DomainIs(google_domain));
    573 
    574   GURL url_4("http://google.com/foo");
    575   EXPECT_FALSE(url_4.DomainIs("google.com."));
    576 
    577   GURL url_5("http://google.com./foo");
    578   EXPECT_TRUE(url_5.DomainIs("google.com."));
    579 
    580   GURL url_6("http://www.google.com./foo");
    581   EXPECT_TRUE(url_6.DomainIs(".com."));
    582 
    583   GURL url_7("http://www.balabala.com/foo");
    584   EXPECT_FALSE(url_7.DomainIs(google_domain));
    585 
    586   GURL url_8("http://www.google.com.cn/foo");
    587   EXPECT_FALSE(url_8.DomainIs(google_domain));
    588 
    589   GURL url_9("http://www.iamnotgoogle.com/foo");
    590   EXPECT_FALSE(url_9.DomainIs(google_domain));
    591 
    592   GURL url_10("http://www.iamnotgoogle.com../foo");
    593   EXPECT_FALSE(url_10.DomainIs(".com"));
    594 
    595   GURL url_11("filesystem:http://www.google.com:99/foo/");
    596   EXPECT_TRUE(url_11.DomainIs(google_domain));
    597 
    598   GURL url_12("filesystem:http://www.iamnotgoogle.com/foo/");
    599   EXPECT_FALSE(url_12.DomainIs(google_domain));
    600 }
    601 
    602 // Newlines should be stripped from inputs.
    603 TEST(GURLTest, Newlines) {
    604   // Constructor.
    605   GURL url_1(" \t ht\ntp://\twww.goo\rgle.com/as\ndf \n ");
    606   EXPECT_EQ("http://www.google.com/asdf", url_1.spec());
    607 
    608   // Relative path resolver.
    609   GURL url_2 = url_1.Resolve(" \n /fo\to\r ");
    610   EXPECT_EQ("http://www.google.com/foo", url_2.spec());
    611 
    612   // Note that newlines are NOT stripped from ReplaceComponents.
    613 }
    614 
    615 TEST(GURLTest, IsStandard) {
    616   GURL a("http:foo/bar");
    617   EXPECT_TRUE(a.IsStandard());
    618 
    619   GURL b("foo:bar/baz");
    620   EXPECT_FALSE(b.IsStandard());
    621 
    622   GURL c("foo://bar/baz");
    623   EXPECT_FALSE(c.IsStandard());
    624 }
    625 
    626 TEST(GURLTest, SchemeIsHTTPOrHTTPS) {
    627   EXPECT_TRUE(GURL("http://bar/").SchemeIsHTTPOrHTTPS());
    628   EXPECT_TRUE(GURL("HTTPS://BAR").SchemeIsHTTPOrHTTPS());
    629   EXPECT_FALSE(GURL("ftp://bar/").SchemeIsHTTPOrHTTPS());
    630 }
    631 
    632 TEST(GURLTest, SchemeIsWSOrWSS) {
    633   EXPECT_TRUE(GURL("WS://BAR/").SchemeIsWSOrWSS());
    634   EXPECT_TRUE(GURL("wss://bar/").SchemeIsWSOrWSS());
    635   EXPECT_FALSE(GURL("http://bar/").SchemeIsWSOrWSS());
    636 }
    637 
    638 TEST(GURLTest, SchemeIsBlob) {
    639   EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsBlob());
    640   EXPECT_TRUE(GURL("blob://bar/").SchemeIsBlob());
    641   EXPECT_FALSE(GURL("http://bar/").SchemeIsBlob());
    642 }
    643 
    644 }  // namespace url
    645