Upload upstream chromium 67.0.3396
[platform/framework/web/chromium-efl.git] / url / gurl_unittest.cc
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 <stddef.h>
6
7 #include "base/macros.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "url/gurl.h"
11 #include "url/url_canon.h"
12 #include "url/url_test_utils.h"
13
14 namespace url {
15
16 namespace {
17
18 template<typename CHAR>
19 void SetupReplacement(
20     void (Replacements<CHAR>::*func)(const CHAR*, const Component&),
21     Replacements<CHAR>* replacements,
22     const CHAR* str) {
23   if (str) {
24     Component comp;
25     if (str[0])
26       comp.len = static_cast<int>(strlen(str));
27     (replacements->*func)(str, comp);
28   }
29 }
30
31 // Returns the canonicalized string for the given URL string for the
32 // GURLTest.Types test.
33 std::string TypesTestCase(const char* src) {
34   GURL gurl(src);
35   return gurl.possibly_invalid_spec();
36 }
37
38 }  // namespace
39
40 // Different types of URLs should be handled differently, and handed off to
41 // different canonicalizers.
42 TEST(GURLTest, Types) {
43   // URLs with unknown schemes should be treated as path URLs, even when they
44   // have things like "://".
45   EXPECT_EQ("something:///HOSTNAME.com/",
46             TypesTestCase("something:///HOSTNAME.com/"));
47
48   // Conversely, URLs with known schemes should always trigger standard URL
49   // handling.
50   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:HOSTNAME.com"));
51   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:/HOSTNAME.com"));
52   EXPECT_EQ("http://hostname.com/", TypesTestCase("http://HOSTNAME.com"));
53   EXPECT_EQ("http://hostname.com/", TypesTestCase("http:///HOSTNAME.com"));
54
55 #ifdef WIN32
56   // URLs that look like Windows absolute path specs.
57   EXPECT_EQ("file:///C:/foo.txt", TypesTestCase("c:\\foo.txt"));
58   EXPECT_EQ("file:///Z:/foo.txt", TypesTestCase("Z|foo.txt"));
59   EXPECT_EQ("file://server/foo.txt", TypesTestCase("\\\\server\\foo.txt"));
60   EXPECT_EQ("file://server/foo.txt", TypesTestCase("//server/foo.txt"));
61 #endif
62 }
63
64 // Test the basic creation and querying of components in a GURL. We assume that
65 // the parser is already tested and works, so we are mostly interested if the
66 // object does the right thing with the results.
67 TEST(GURLTest, Components) {
68   GURL empty_url(base::UTF8ToUTF16(""));
69   EXPECT_TRUE(empty_url.is_empty());
70   EXPECT_FALSE(empty_url.is_valid());
71
72   GURL url(base::UTF8ToUTF16("http://user:pass@google.com:99/foo;bar?q=a#ref"));
73   EXPECT_FALSE(url.is_empty());
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(base::UTF8ToUTF16(
118       "http://user:pass@google.com:99/foo;bar?q=a#ref"));
119
120   GURL url2(url);
121   EXPECT_TRUE(url2.is_valid());
122
123   EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
124   EXPECT_EQ("http", url2.scheme());
125   EXPECT_EQ("user", url2.username());
126   EXPECT_EQ("pass", url2.password());
127   EXPECT_EQ("google.com", url2.host());
128   EXPECT_EQ("99", url2.port());
129   EXPECT_EQ(99, url2.IntPort());
130   EXPECT_EQ("/foo;bar", url2.path());
131   EXPECT_EQ("q=a", url2.query());
132   EXPECT_EQ("ref", url2.ref());
133
134   // Copying of invalid URL should be invalid
135   GURL invalid;
136   GURL invalid2(invalid);
137   EXPECT_FALSE(invalid2.is_valid());
138   EXPECT_EQ("", invalid2.spec());
139   EXPECT_EQ("", invalid2.scheme());
140   EXPECT_EQ("", invalid2.username());
141   EXPECT_EQ("", invalid2.password());
142   EXPECT_EQ("", invalid2.host());
143   EXPECT_EQ("", invalid2.port());
144   EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
145   EXPECT_EQ("", invalid2.path());
146   EXPECT_EQ("", invalid2.query());
147   EXPECT_EQ("", invalid2.ref());
148 }
149
150 TEST(GURLTest, Assign) {
151   GURL url(base::UTF8ToUTF16(
152       "http://user:pass@google.com:99/foo;bar?q=a#ref"));
153
154   GURL url2;
155   url2 = url;
156   EXPECT_TRUE(url2.is_valid());
157
158   EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
159   EXPECT_EQ("http", url2.scheme());
160   EXPECT_EQ("user", url2.username());
161   EXPECT_EQ("pass", url2.password());
162   EXPECT_EQ("google.com", url2.host());
163   EXPECT_EQ("99", url2.port());
164   EXPECT_EQ(99, url2.IntPort());
165   EXPECT_EQ("/foo;bar", url2.path());
166   EXPECT_EQ("q=a", url2.query());
167   EXPECT_EQ("ref", url2.ref());
168
169   // Assignment of invalid URL should be invalid
170   GURL invalid;
171   GURL invalid2;
172   invalid2 = invalid;
173   EXPECT_FALSE(invalid2.is_valid());
174   EXPECT_EQ("", invalid2.spec());
175   EXPECT_EQ("", invalid2.scheme());
176   EXPECT_EQ("", invalid2.username());
177   EXPECT_EQ("", invalid2.password());
178   EXPECT_EQ("", invalid2.host());
179   EXPECT_EQ("", invalid2.port());
180   EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
181   EXPECT_EQ("", invalid2.path());
182   EXPECT_EQ("", invalid2.query());
183   EXPECT_EQ("", invalid2.ref());
184 }
185
186 // This is a regression test for http://crbug.com/309975.
187 TEST(GURLTest, SelfAssign) {
188   GURL a("filesystem:http://example.com/temporary/");
189   // This should not crash.
190   a = *&a;  // The *& defeats Clang's -Wself-assign warning.
191 }
192
193 TEST(GURLTest, CopyFileSystem) {
194   GURL url(base::UTF8ToUTF16(
195       "filesystem:https://user:pass@google.com:99/t/foo;bar?q=a#ref"));
196
197   GURL url2(url);
198   EXPECT_TRUE(url2.is_valid());
199
200   EXPECT_EQ("filesystem:https://google.com:99/t/foo;bar?q=a#ref", url2.spec());
201   EXPECT_EQ("filesystem", url2.scheme());
202   EXPECT_EQ("", url2.username());
203   EXPECT_EQ("", url2.password());
204   EXPECT_EQ("", url2.host());
205   EXPECT_EQ("", url2.port());
206   EXPECT_EQ(PORT_UNSPECIFIED, url2.IntPort());
207   EXPECT_EQ("/foo;bar", url2.path());
208   EXPECT_EQ("q=a", url2.query());
209   EXPECT_EQ("ref", url2.ref());
210
211   const GURL* inner = url2.inner_url();
212   ASSERT_TRUE(inner);
213   EXPECT_EQ("https", inner->scheme());
214   EXPECT_EQ("", inner->username());
215   EXPECT_EQ("", inner->password());
216   EXPECT_EQ("google.com", inner->host());
217   EXPECT_EQ("99", inner->port());
218   EXPECT_EQ(99, inner->IntPort());
219   EXPECT_EQ("/t", inner->path());
220   EXPECT_EQ("", inner->query());
221   EXPECT_EQ("", inner->ref());
222 }
223
224 TEST(GURLTest, IsValid) {
225   const char* valid_cases[] = {
226     "http://google.com",
227     "unknown://google.com",
228     "http://user:pass@google.com",
229     "http://google.com:12345",
230     "http://google.com/path",
231     "http://google.com//path",
232     "http://google.com?k=v#fragment",
233     "http://user:pass@google.com:12345/path?k=v#fragment",
234     "http:/path",
235     "http:path",
236   };
237   for (size_t i = 0; i < arraysize(valid_cases); i++) {
238     EXPECT_TRUE(GURL(valid_cases[i]).is_valid())
239         << "Case: " << valid_cases[i];
240   }
241
242   const char* invalid_cases[] = {
243     "http://?k=v",
244     "http:://google.com",
245     "http//google.com",
246     "http://google.com:12three45",
247     "://google.com",
248     "path",
249   };
250   for (size_t i = 0; i < arraysize(invalid_cases); i++) {
251     EXPECT_FALSE(GURL(invalid_cases[i]).is_valid())
252         << "Case: " << invalid_cases[i];
253   }
254 }
255
256 TEST(GURLTest, ExtraSlashesBeforeAuthority) {
257   // According to RFC3986, the hierarchical part for URI with an authority
258   // must use only two slashes; GURL intentionally just ignores extra slashes
259   // if there are more than 2, and parses the following part as an authority.
260   GURL url("http:///host");
261   EXPECT_EQ("host", url.host());
262   EXPECT_EQ("/", url.path());
263 }
264
265 // Given an invalid URL, we should still get most of the components.
266 TEST(GURLTest, ComponentGettersWorkEvenForInvalidURL) {
267   GURL url("http:google.com:foo");
268   EXPECT_FALSE(url.is_valid());
269   EXPECT_EQ("http://google.com:foo/", url.possibly_invalid_spec());
270
271   EXPECT_EQ("http", url.scheme());
272   EXPECT_EQ("", url.username());
273   EXPECT_EQ("", url.password());
274   EXPECT_EQ("google.com", url.host());
275   EXPECT_EQ("foo", url.port());
276   EXPECT_EQ(PORT_INVALID, url.IntPort());
277   EXPECT_EQ("/", url.path());
278   EXPECT_EQ("", url.query());
279   EXPECT_EQ("", url.ref());
280 }
281
282 TEST(GURLTest, Resolve) {
283   // The tricky cases for relative URL resolving are tested in the
284   // canonicalizer unit test. Here, we just test that the GURL integration
285   // works properly.
286   struct ResolveCase {
287     const char* base;
288     const char* relative;
289     bool expected_valid;
290     const char* expected;
291   } resolve_cases[] = {
292     {"http://www.google.com/", "foo.html", true, "http://www.google.com/foo.html"},
293     {"http://www.google.com/foo/", "bar", true, "http://www.google.com/foo/bar"},
294     {"http://www.google.com/foo/", "/bar", true, "http://www.google.com/bar"},
295     {"http://www.google.com/foo", "bar", true, "http://www.google.com/bar"},
296     {"http://www.google.com/", "http://images.google.com/foo.html", true, "http://images.google.com/foo.html"},
297     {"http://www.google.com/", "http://images.\tgoogle.\ncom/\rfoo.html", true, "http://images.google.com/foo.html"},
298     {"http://www.google.com/blah/bloo?c#d", "../../../hello/./world.html?a#b", true, "http://www.google.com/hello/world.html?a#b"},
299     {"http://www.google.com/foo#bar", "#com", true, "http://www.google.com/foo#com"},
300     {"http://www.google.com/", "Https:images.google.com", true, "https://images.google.com/"},
301       // A non-standard base can be replaced with a standard absolute URL.
302     {"data:blahblah", "http://google.com/", true, "http://google.com/"},
303     {"data:blahblah", "http:google.com", true, "http://google.com/"},
304       // Filesystem URLs have different paths to test.
305     {"filesystem:http://www.google.com/type/", "foo.html", true, "filesystem:http://www.google.com/type/foo.html"},
306     {"filesystem:http://www.google.com/type/", "../foo.html", true, "filesystem:http://www.google.com/type/foo.html"},
307   };
308
309   for (size_t i = 0; i < arraysize(resolve_cases); i++) {
310     // 8-bit code path.
311     GURL input(resolve_cases[i].base);
312     GURL output = input.Resolve(resolve_cases[i].relative);
313     EXPECT_EQ(resolve_cases[i].expected_valid, output.is_valid()) << i;
314     EXPECT_EQ(resolve_cases[i].expected, output.spec()) << i;
315     EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
316
317     // Wide code path.
318     GURL inputw(base::UTF8ToUTF16(resolve_cases[i].base));
319     GURL outputw =
320         input.Resolve(base::UTF8ToUTF16(resolve_cases[i].relative));
321     EXPECT_EQ(resolve_cases[i].expected_valid, outputw.is_valid()) << i;
322     EXPECT_EQ(resolve_cases[i].expected, outputw.spec()) << i;
323     EXPECT_EQ(outputw.SchemeIsFileSystem(), outputw.inner_url() != NULL);
324   }
325 }
326
327 TEST(GURLTest, GetOrigin) {
328   struct TestCase {
329     const char* input;
330     const char* expected;
331   } cases[] = {
332     {"http://www.google.com", "http://www.google.com/"},
333     {"javascript:window.alert(\"hello,world\");", ""},
334     {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/"},
335     {"http://user@www.google.com", "http://www.google.com/"},
336     {"http://:pass@www.google.com", "http://www.google.com/"},
337     {"http://:@www.google.com", "http://www.google.com/"},
338     {"filesystem:http://www.google.com/temp/foo?q#b", "http://www.google.com/"},
339     {"filesystem:http://user:pass@google.com:21/blah#baz", "http://google.com:21/"},
340   };
341   for (size_t i = 0; i < arraysize(cases); i++) {
342     GURL url(cases[i].input);
343     GURL origin = url.GetOrigin();
344     EXPECT_EQ(cases[i].expected, origin.spec());
345   }
346 }
347
348 TEST(GURLTest, GetAsReferrer) {
349   struct TestCase {
350     const char* input;
351     const char* expected;
352   } cases[] = {
353     {"http://www.google.com", "http://www.google.com/"},
354     {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/blah"},
355     {"http://user@www.google.com", "http://www.google.com/"},
356     {"http://:pass@www.google.com", "http://www.google.com/"},
357     {"http://:@www.google.com", "http://www.google.com/"},
358     {"http://www.google.com/temp/foo?q#b", "http://www.google.com/temp/foo?q"},
359     {"not a url", ""},
360     {"unknown-scheme://foo.html", ""},
361     {"file:///tmp/test.html", ""},
362     {"https://www.google.com", "https://www.google.com/"},
363   };
364   for (size_t i = 0; i < arraysize(cases); i++) {
365     GURL url(cases[i].input);
366     GURL origin = url.GetAsReferrer();
367     EXPECT_EQ(cases[i].expected, origin.spec());
368   }
369 }
370
371 TEST(GURLTest, GetWithEmptyPath) {
372   struct TestCase {
373     const char* input;
374     const char* expected;
375   } cases[] = {
376     {"http://www.google.com", "http://www.google.com/"},
377     {"javascript:window.alert(\"hello, world\");", ""},
378     {"http://www.google.com/foo/bar.html?baz=22", "http://www.google.com/"},
379     {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
380     {"filesystem:file:///temporary/bar.html?baz=22", "filesystem:file:///temporary/"},
381   };
382
383   for (size_t i = 0; i < arraysize(cases); i++) {
384     GURL url(cases[i].input);
385     GURL empty_path = url.GetWithEmptyPath();
386     EXPECT_EQ(cases[i].expected, empty_path.spec());
387   }
388 }
389
390 TEST(GURLTest, GetWithoutFilename) {
391   struct TestCase {
392     const char* input;
393     const char* expected;
394   } cases[] = {
395     // Common Standard URLs.
396     {"https://www.google.com",                    "https://www.google.com/"},
397     {"https://www.google.com/",                   "https://www.google.com/"},
398     {"https://www.google.com/maps.htm",           "https://www.google.com/"},
399     {"https://www.google.com/maps/",              "https://www.google.com/maps/"},
400     {"https://www.google.com/index.html",         "https://www.google.com/"},
401     {"https://www.google.com/index.html?q=maps",  "https://www.google.com/"},
402     {"https://www.google.com/index.html#maps/",   "https://www.google.com/"},
403     {"https://foo:bar@www.google.com/maps.htm",   "https://foo:bar@www.google.com/"},
404     {"https://www.google.com/maps/au/index.html", "https://www.google.com/maps/au/"},
405     {"https://www.google.com/maps/au/north",      "https://www.google.com/maps/au/"},
406     {"https://www.google.com/maps/au/north/",     "https://www.google.com/maps/au/north/"},
407     {"https://www.google.com/maps/au/index.html?q=maps#fragment/",     "https://www.google.com/maps/au/"},
408     {"http://www.google.com:8000/maps/au/index.html?q=maps#fragment/", "http://www.google.com:8000/maps/au/"},
409     {"https://www.google.com/maps/au/north/?q=maps#fragment",          "https://www.google.com/maps/au/north/"},
410     {"https://www.google.com/maps/au/north?q=maps#fragment",           "https://www.google.com/maps/au/"},
411     // Less common standard URLs.
412     {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
413     {"file:///temporary/bar.html?baz=22","file:///temporary/"},
414     {"ftp://foo/test/index.html",        "ftp://foo/test/"},
415     {"gopher://foo/test/index.html",     "gopher://foo/test/"},
416     {"ws://foo/test/index.html",         "ws://foo/test/"},
417     // Non-standard, hierarchical URLs.
418     {"chrome://foo/bar.html", "chrome://foo/"},
419     {"httpa://foo/test/index.html", "httpa://foo/test/"},
420     // Non-standard, non-hierarchical URLs.
421     {"blob:https://foo.bar/test/index.html", ""},
422     {"about:blank", ""},
423     {"data:foobar", ""},
424     {"scheme:opaque_data", ""},
425     // Invalid URLs.
426     {"foobar", ""},
427   };
428
429   for (size_t i = 0; i < arraysize(cases); i++) {
430     GURL url(cases[i].input);
431     GURL without_filename = url.GetWithoutFilename();
432     EXPECT_EQ(cases[i].expected, without_filename.spec()) << i;
433   }
434 }
435
436 TEST(GURLTest, Replacements) {
437   // The URL canonicalizer replacement test will handle most of these case.
438   // The most important thing to do here is to check that the proper
439   // canonicalizer gets called based on the scheme of the input.
440   struct ReplaceCase {
441     const char* base;
442     const char* scheme;
443     const char* username;
444     const char* password;
445     const char* host;
446     const char* port;
447     const char* path;
448     const char* query;
449     const char* ref;
450     const char* expected;
451   } replace_cases[] = {
452       {"http://www.google.com/foo/bar.html?foo#bar", NULL, NULL, NULL, NULL,
453        NULL, "/", "", "", "http://www.google.com/"},
454       {"http://www.google.com/foo/bar.html?foo#bar", "javascript", "", "", "",
455        "", "window.open('foo');", "", "", "javascript:window.open('foo');"},
456       {"file:///C:/foo/bar.txt", "http", NULL, NULL, "www.google.com", "99",
457        "/foo", "search", "ref", "http://www.google.com:99/foo?search#ref"},
458 #ifdef WIN32
459       {"http://www.google.com/foo/bar.html?foo#bar", "file", "", "", "", "",
460        "c:\\", "", "", "file:///C:/"},
461 #endif
462       {"filesystem:http://www.google.com/foo/bar.html?foo#bar", NULL, NULL,
463        NULL, NULL, NULL, "/", "", "", "filesystem:http://www.google.com/foo/"},
464       // Lengthen the URL instead of shortening it, to test creation of
465       // inner_url.
466       {"filesystem:http://www.google.com/foo/", NULL, NULL, NULL, NULL, NULL,
467        "bar.html", "foo", "bar",
468        "filesystem:http://www.google.com/foo/bar.html?foo#bar"},
469   };
470
471   for (size_t i = 0; i < arraysize(replace_cases); i++) {
472     const ReplaceCase& cur = replace_cases[i];
473     GURL url(cur.base);
474     GURL::Replacements repl;
475     SetupReplacement(&GURL::Replacements::SetScheme, &repl, cur.scheme);
476     SetupReplacement(&GURL::Replacements::SetUsername, &repl, cur.username);
477     SetupReplacement(&GURL::Replacements::SetPassword, &repl, cur.password);
478     SetupReplacement(&GURL::Replacements::SetHost, &repl, cur.host);
479     SetupReplacement(&GURL::Replacements::SetPort, &repl, cur.port);
480     SetupReplacement(&GURL::Replacements::SetPath, &repl, cur.path);
481     SetupReplacement(&GURL::Replacements::SetQuery, &repl, cur.query);
482     SetupReplacement(&GURL::Replacements::SetRef, &repl, cur.ref);
483     GURL output = url.ReplaceComponents(repl);
484
485     EXPECT_EQ(replace_cases[i].expected, output.spec());
486
487     EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
488     if (output.SchemeIsFileSystem()) {
489       // TODO(mmenke): inner_url()->spec() is currently the same as the spec()
490       // for the GURL itself.  This should be fixed.
491       // See https://crbug.com/619596
492       EXPECT_EQ(replace_cases[i].expected, output.inner_url()->spec());
493     }
494   }
495 }
496
497 TEST(GURLTest, ClearFragmentOnDataUrl) {
498   // http://crbug.com/291747 - a data URL may legitimately have trailing
499   // whitespace in the spec after the ref is cleared. Test this does not trigger
500   // the Parsed importing validation DCHECK in GURL.
501   GURL url(" data: one ? two # three ");
502
503   // By default the trailing whitespace will have been stripped.
504   EXPECT_EQ("data: one ? two # three", url.spec());
505   GURL::Replacements repl;
506   repl.ClearRef();
507   GURL url_no_ref = url.ReplaceComponents(repl);
508
509   EXPECT_EQ("data: one ? two ", url_no_ref.spec());
510
511   // Importing a parsed URL via this constructor overload will retain trailing
512   // whitespace.
513   GURL import_url(url_no_ref.spec(),
514                   url_no_ref.parsed_for_possibly_invalid_spec(),
515                   url_no_ref.is_valid());
516   EXPECT_EQ(url_no_ref, import_url);
517   EXPECT_EQ(import_url.query(), " two ");
518 }
519
520 TEST(GURLTest, PathForRequest) {
521   struct TestCase {
522     const char* input;
523     const char* expected;
524     const char* inner_expected;
525   } cases[] = {
526     {"http://www.google.com", "/", NULL},
527     {"http://www.google.com/", "/", NULL},
528     {"http://www.google.com/foo/bar.html?baz=22", "/foo/bar.html?baz=22", NULL},
529     {"http://www.google.com/foo/bar.html#ref", "/foo/bar.html", NULL},
530     {"http://www.google.com/foo/bar.html?query#ref", "/foo/bar.html?query", NULL},
531     {"filesystem:http://www.google.com/temporary/foo/bar.html?query#ref", "/foo/bar.html?query", "/temporary"},
532     {"filesystem:http://www.google.com/temporary/foo/bar.html?query", "/foo/bar.html?query", "/temporary"},
533   };
534
535   for (size_t i = 0; i < arraysize(cases); i++) {
536     GURL url(cases[i].input);
537     std::string path_request = url.PathForRequest();
538     EXPECT_EQ(cases[i].expected, path_request);
539     EXPECT_EQ(cases[i].inner_expected == NULL, url.inner_url() == NULL);
540     if (url.inner_url() && cases[i].inner_expected)
541       EXPECT_EQ(cases[i].inner_expected, url.inner_url()->PathForRequest());
542   }
543 }
544
545 TEST(GURLTest, EffectiveIntPort) {
546   struct PortTest {
547     const char* spec;
548     int expected_int_port;
549   } port_tests[] = {
550     // http
551     {"http://www.google.com/", 80},
552     {"http://www.google.com:80/", 80},
553     {"http://www.google.com:443/", 443},
554
555     // https
556     {"https://www.google.com/", 443},
557     {"https://www.google.com:443/", 443},
558     {"https://www.google.com:80/", 80},
559
560     // ftp
561     {"ftp://www.google.com/", 21},
562     {"ftp://www.google.com:21/", 21},
563     {"ftp://www.google.com:80/", 80},
564
565     // gopher
566     {"gopher://www.google.com/", 70},
567     {"gopher://www.google.com:70/", 70},
568     {"gopher://www.google.com:80/", 80},
569
570     // file - no port
571     {"file://www.google.com/", PORT_UNSPECIFIED},
572     {"file://www.google.com:443/", PORT_UNSPECIFIED},
573
574     // data - no port
575     {"data:www.google.com:90", PORT_UNSPECIFIED},
576     {"data:www.google.com", PORT_UNSPECIFIED},
577
578     // filesystem - no port
579     {"filesystem:http://www.google.com:90/t/foo", PORT_UNSPECIFIED},
580     {"filesystem:file:///t/foo", PORT_UNSPECIFIED},
581   };
582
583   for (size_t i = 0; i < arraysize(port_tests); i++) {
584     GURL url(port_tests[i].spec);
585     EXPECT_EQ(port_tests[i].expected_int_port, url.EffectiveIntPort());
586   }
587 }
588
589 TEST(GURLTest, IPAddress) {
590   struct IPTest {
591     const char* spec;
592     bool expected_ip;
593   } ip_tests[] = {
594     {"http://www.google.com/", false},
595     {"http://192.168.9.1/", true},
596     {"http://192.168.9.1.2/", false},
597     {"http://192.168.m.1/", false},
598     {"http://2001:db8::1/", false},
599     {"http://[2001:db8::1]/", true},
600     {"", false},
601     {"some random input!", false},
602   };
603
604   for (size_t i = 0; i < arraysize(ip_tests); i++) {
605     GURL url(ip_tests[i].spec);
606     EXPECT_EQ(ip_tests[i].expected_ip, url.HostIsIPAddress());
607   }
608 }
609
610 TEST(GURLTest, HostNoBrackets) {
611   struct TestCase {
612     const char* input;
613     const char* expected_host;
614     const char* expected_plainhost;
615   } cases[] = {
616     {"http://www.google.com", "www.google.com", "www.google.com"},
617     {"http://[2001:db8::1]/", "[2001:db8::1]", "2001:db8::1"},
618     {"http://[::]/", "[::]", "::"},
619
620     // Don't require a valid URL, but don't crash either.
621     {"http://[]/", "[]", ""},
622     {"http://[x]/", "[x]", "x"},
623     {"http://[x/", "[x", "[x"},
624     {"http://x]/", "x]", "x]"},
625     {"http://[/", "[", "["},
626     {"http://]/", "]", "]"},
627     {"", "", ""},
628   };
629   for (size_t i = 0; i < arraysize(cases); i++) {
630     GURL url(cases[i].input);
631     EXPECT_EQ(cases[i].expected_host, url.host());
632     EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBrackets());
633     EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBracketsPiece());
634   }
635 }
636
637 TEST(GURLTest, DomainIs) {
638   GURL url_1("http://google.com/foo");
639   EXPECT_TRUE(url_1.DomainIs("google.com"));
640
641   // Subdomain and port are ignored.
642   GURL url_2("http://www.google.com:99/foo");
643   EXPECT_TRUE(url_2.DomainIs("google.com"));
644
645   // Different top-level domain.
646   GURL url_3("http://www.google.com.cn/foo");
647   EXPECT_FALSE(url_3.DomainIs("google.com"));
648
649   // Different host name.
650   GURL url_4("http://www.iamnotgoogle.com/foo");
651   EXPECT_FALSE(url_4.DomainIs("google.com"));
652
653   // The input must be lower-cased otherwise DomainIs returns false.
654   GURL url_5("http://www.google.com/foo");
655   EXPECT_FALSE(url_5.DomainIs("Google.com"));
656
657   // If the URL is invalid, DomainIs returns false.
658   GURL invalid_url("google.com");
659   EXPECT_FALSE(invalid_url.is_valid());
660   EXPECT_FALSE(invalid_url.DomainIs("google.com"));
661
662   GURL url_with_escape_chars("https://www.,.test");
663   EXPECT_TRUE(url_with_escape_chars.is_valid());
664   EXPECT_EQ(url_with_escape_chars.host(), "www.%2C.test");
665   EXPECT_TRUE(url_with_escape_chars.DomainIs("%2C.test"));
666 }
667
668 TEST(GURLTest, DomainIsTerminatingDotBehavior) {
669   // If the host part ends with a dot, it matches input domains
670   // with or without a dot.
671   GURL url_with_dot("http://www.google.com./foo");
672   EXPECT_TRUE(url_with_dot.DomainIs("google.com"));
673   EXPECT_TRUE(url_with_dot.DomainIs("google.com."));
674   EXPECT_TRUE(url_with_dot.DomainIs(".com"));
675   EXPECT_TRUE(url_with_dot.DomainIs(".com."));
676
677   // But, if the host name doesn't end with a dot and the input
678   // domain does, then it's considered to not match.
679   GURL url_without_dot("http://google.com/foo");
680   EXPECT_FALSE(url_without_dot.DomainIs("google.com."));
681
682   // If the URL ends with two dots, it doesn't match.
683   GURL url_with_two_dots("http://www.google.com../foo");
684   EXPECT_FALSE(url_with_two_dots.DomainIs("google.com"));
685 }
686
687 TEST(GURLTest, DomainIsWithFilesystemScheme) {
688   GURL url_1("filesystem:http://www.google.com:99/foo/");
689   EXPECT_TRUE(url_1.DomainIs("google.com"));
690
691   GURL url_2("filesystem:http://www.iamnotgoogle.com/foo/");
692   EXPECT_FALSE(url_2.DomainIs("google.com"));
693 }
694
695 // Newlines should be stripped from inputs.
696 TEST(GURLTest, Newlines) {
697   // Constructor.
698   GURL url_1(" \t ht\ntp://\twww.goo\rgle.com/as\ndf \n ");
699   EXPECT_EQ("http://www.google.com/asdf", url_1.spec());
700   EXPECT_FALSE(
701       url_1.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
702
703   // Relative path resolver.
704   GURL url_2 = url_1.Resolve(" \n /fo\to\r ");
705   EXPECT_EQ("http://www.google.com/foo", url_2.spec());
706   EXPECT_FALSE(
707       url_2.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
708
709   // Constructor.
710   GURL url_3(" \t ht\ntp://\twww.goo\rgle.com/as\ndf< \n ");
711   EXPECT_EQ("http://www.google.com/asdf%3C", url_3.spec());
712   EXPECT_TRUE(
713       url_3.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
714
715   // Relative path resolver.
716   GURL url_4 = url_1.Resolve(" \n /fo\to<\r ");
717   EXPECT_EQ("http://www.google.com/foo%3C", url_4.spec());
718   EXPECT_TRUE(
719       url_4.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
720
721   // Note that newlines are NOT stripped from ReplaceComponents.
722 }
723
724 TEST(GURLTest, IsStandard) {
725   GURL a("http:foo/bar");
726   EXPECT_TRUE(a.IsStandard());
727
728   GURL b("foo:bar/baz");
729   EXPECT_FALSE(b.IsStandard());
730
731   GURL c("foo://bar/baz");
732   EXPECT_FALSE(c.IsStandard());
733
734   GURL d("cid:bar@baz");
735   EXPECT_FALSE(d.IsStandard());
736 }
737
738 TEST(GURLTest, SchemeIsHTTPOrHTTPS) {
739   EXPECT_TRUE(GURL("http://bar/").SchemeIsHTTPOrHTTPS());
740   EXPECT_TRUE(GURL("HTTPS://BAR").SchemeIsHTTPOrHTTPS());
741   EXPECT_FALSE(GURL("ftp://bar/").SchemeIsHTTPOrHTTPS());
742 }
743
744 TEST(GURLTest, SchemeIsWSOrWSS) {
745   EXPECT_TRUE(GURL("WS://BAR/").SchemeIsWSOrWSS());
746   EXPECT_TRUE(GURL("wss://bar/").SchemeIsWSOrWSS());
747   EXPECT_FALSE(GURL("http://bar/").SchemeIsWSOrWSS());
748 }
749
750 TEST(GURLTest, SchemeIsCryptographic) {
751   EXPECT_TRUE(GURL("https://foo.bar.com/").SchemeIsCryptographic());
752   EXPECT_TRUE(GURL("HTTPS://foo.bar.com/").SchemeIsCryptographic());
753   EXPECT_TRUE(GURL("HtTpS://foo.bar.com/").SchemeIsCryptographic());
754
755   EXPECT_TRUE(GURL("wss://foo.bar.com/").SchemeIsCryptographic());
756   EXPECT_TRUE(GURL("WSS://foo.bar.com/").SchemeIsCryptographic());
757   EXPECT_TRUE(GURL("WsS://foo.bar.com/").SchemeIsCryptographic());
758
759   EXPECT_FALSE(GURL("http://foo.bar.com/").SchemeIsCryptographic());
760   EXPECT_FALSE(GURL("ws://foo.bar.com/").SchemeIsCryptographic());
761 }
762
763 TEST(GURLTest, SchemeIsBlob) {
764   EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsBlob());
765   EXPECT_TRUE(GURL("blob://bar/").SchemeIsBlob());
766   EXPECT_FALSE(GURL("http://bar/").SchemeIsBlob());
767 }
768
769 TEST(GURLTest, ContentAndPathForNonStandardURLs) {
770   struct TestCase {
771     const char* url;
772     const char* expected;
773   } cases[] = {
774       {"null", ""},
775       {"not-a-standard-scheme:this is arbitrary content",
776        "this is arbitrary content"},
777       {"view-source:http://example.com/path", "http://example.com/path"},
778       {"blob:http://example.com/GUID", "http://example.com/GUID"},
779       {"blob://http://example.com/GUID", "//http://example.com/GUID"},
780       {"blob:http://user:password@example.com/GUID",
781        "http://user:password@example.com/GUID"},
782
783       // TODO(mkwst): This seems like a bug. https://crbug.com/513600
784       {"filesystem:http://example.com/path", "/"},
785   };
786
787   for (const auto& test : cases) {
788     GURL url(test.url);
789     EXPECT_EQ(test.expected, url.path()) << test.url;
790     EXPECT_EQ(test.expected, url.GetContent()) << test.url;
791   }
792 }
793
794 TEST(GURLTest, IsAboutBlank) {
795   const std::string kAboutBlankUrls[] = {"about:blank", "about:blank?foo",
796                                          "about:blank/#foo",
797                                          "about:blank?foo#foo"};
798   for (const auto& url : kAboutBlankUrls)
799     EXPECT_TRUE(GURL(url).IsAboutBlank()) << url;
800
801   const std::string kNotAboutBlankUrls[] = {
802       "http:blank",      "about:blan",          "about://blank",
803       "about:blank/foo", "about://:8000/blank", "about://foo:foo@/blank",
804       "foo@about:blank", "foo:bar@about:blank", "about:blank:8000"};
805   for (const auto& url : kNotAboutBlankUrls)
806     EXPECT_FALSE(GURL(url).IsAboutBlank()) << url;
807 }
808
809 TEST(GURLTest, EqualsIgnoringRef) {
810   const struct {
811     const char* url_a;
812     const char* url_b;
813     bool are_equals;
814   } kTestCases[] = {
815       // No ref.
816       {"http://a.com", "http://a.com", true},
817       {"http://a.com", "http://b.com", false},
818
819       // Same Ref.
820       {"http://a.com#foo", "http://a.com#foo", true},
821       {"http://a.com#foo", "http://b.com#foo", false},
822
823       // Different Refs.
824       {"http://a.com#foo", "http://a.com#bar", true},
825       {"http://a.com#foo", "http://b.com#bar", false},
826
827       // One has a ref, the other doesn't.
828       {"http://a.com#foo", "http://a.com", true},
829       {"http://a.com#foo", "http://b.com", false},
830
831       // Empty refs.
832       {"http://a.com#", "http://a.com#", true},
833       {"http://a.com#", "http://a.com", true},
834
835       // URLs that differ only by their last character.
836       {"http://aaa", "http://aab", false},
837       {"http://aaa#foo", "http://aab#foo", false},
838
839       // Different size of the part before the ref.
840       {"http://123#a", "http://123456#a", false},
841
842       // Blob URLs
843       {"blob:http://a.com#foo", "blob:http://a.com#foo", true},
844       {"blob:http://a.com#foo", "blob:http://a.com#bar", true},
845       {"blob:http://a.com#foo", "blob:http://b.com#bar", false},
846
847       // Filesystem URLs
848       {"filesystem:http://a.com#foo", "filesystem:http://a.com#foo", true},
849       {"filesystem:http://a.com#foo", "filesystem:http://a.com#bar", true},
850       {"filesystem:http://a.com#foo", "filesystem:http://b.com#bar", false},
851
852       // Data URLs
853       {"data:text/html,a#foo", "data:text/html,a#bar", true},
854       {"data:text/html,a#foo", "data:text/html,a#foo", true},
855       {"data:text/html,a#foo", "data:text/html,b#foo", false},
856   };
857
858   for (const auto& test_case : kTestCases) {
859     SCOPED_TRACE(testing::Message()
860                  << std::endl
861                  << "url_a = " << test_case.url_a << std::endl
862                  << "url_b = " << test_case.url_b << std::endl);
863     // A versus B.
864     EXPECT_EQ(test_case.are_equals,
865               GURL(test_case.url_a).EqualsIgnoringRef(GURL(test_case.url_b)));
866     // B versus A.
867     EXPECT_EQ(test_case.are_equals,
868               GURL(test_case.url_b).EqualsIgnoringRef(GURL(test_case.url_a)));
869   }
870 }
871
872 TEST(GURLTest, DebugAlias) {
873   GURL url("https://foo.com/bar");
874   DEBUG_ALIAS_FOR_GURL(url_debug_alias, url);
875   EXPECT_STREQ("https://foo.com/bar", url_debug_alias);
876 }
877
878 }  // namespace url