gurl_unittest.cc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  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. #include "url/gurl.h"
  5. #include <stddef.h>
  6. #include "base/strings/string_number_conversions.h"
  7. #include "base/strings/utf_string_conversions.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. #include "url/gurl_abstract_tests.h"
  10. #include "url/origin.h"
  11. #include "url/url_canon.h"
  12. #include "url/url_test_utils.h"
  13. namespace url {
  14. namespace {
  15. // Returns the canonicalized string for the given URL string for the
  16. // GURLTest.Types test.
  17. std::string TypesTestCase(const char* src) {
  18. GURL gurl(src);
  19. return gurl.possibly_invalid_spec();
  20. }
  21. } // namespace
  22. // Different types of URLs should be handled differently, and handed off to
  23. // different canonicalizers.
  24. TEST(GURLTest, Types) {
  25. // URLs with unknown schemes should be treated as path URLs, even when they
  26. // have things like "://".
  27. EXPECT_EQ("something:///HOSTNAME.com/",
  28. TypesTestCase("something:///HOSTNAME.com/"));
  29. // Conversely, URLs with known schemes should always trigger standard URL
  30. // handling.
  31. EXPECT_EQ("http://hostname.com/", TypesTestCase("http:HOSTNAME.com"));
  32. EXPECT_EQ("http://hostname.com/", TypesTestCase("http:/HOSTNAME.com"));
  33. EXPECT_EQ("http://hostname.com/", TypesTestCase("http://HOSTNAME.com"));
  34. EXPECT_EQ("http://hostname.com/", TypesTestCase("http:///HOSTNAME.com"));
  35. #ifdef WIN32
  36. // URLs that look like Windows absolute path specs.
  37. EXPECT_EQ("file:///C:/foo.txt", TypesTestCase("c:\\foo.txt"));
  38. EXPECT_EQ("file:///Z:/foo.txt", TypesTestCase("Z|foo.txt"));
  39. EXPECT_EQ("file://server/foo.txt", TypesTestCase("\\\\server\\foo.txt"));
  40. EXPECT_EQ("file://server/foo.txt", TypesTestCase("//server/foo.txt"));
  41. #endif
  42. }
  43. // Test the basic creation and querying of components in a GURL. We assume that
  44. // the parser is already tested and works, so we are mostly interested if the
  45. // object does the right thing with the results.
  46. TEST(GURLTest, Components) {
  47. GURL empty_url(u"");
  48. EXPECT_TRUE(empty_url.is_empty());
  49. EXPECT_FALSE(empty_url.is_valid());
  50. GURL url(u"http://user:pass@google.com:99/foo;bar?q=a#ref");
  51. EXPECT_FALSE(url.is_empty());
  52. EXPECT_TRUE(url.is_valid());
  53. EXPECT_TRUE(url.SchemeIs("http"));
  54. EXPECT_FALSE(url.SchemeIsFile());
  55. // This is the narrow version of the URL, which should match the wide input.
  56. EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url.spec());
  57. EXPECT_EQ("http", url.scheme());
  58. EXPECT_EQ("user", url.username());
  59. EXPECT_EQ("pass", url.password());
  60. EXPECT_EQ("google.com", url.host());
  61. EXPECT_EQ("99", url.port());
  62. EXPECT_EQ(99, url.IntPort());
  63. EXPECT_EQ("/foo;bar", url.path());
  64. EXPECT_EQ("q=a", url.query());
  65. EXPECT_EQ("ref", url.ref());
  66. // Test parsing userinfo with special characters.
  67. GURL url_special_pass("http://user:%40!$&'()*+,;=:@google.com:12345");
  68. EXPECT_TRUE(url_special_pass.is_valid());
  69. // GURL canonicalizes some delimiters.
  70. EXPECT_EQ("%40!$&%27()*+,%3B%3D%3A", url_special_pass.password());
  71. EXPECT_EQ("google.com", url_special_pass.host());
  72. EXPECT_EQ("12345", url_special_pass.port());
  73. }
  74. TEST(GURLTest, Empty) {
  75. GURL url;
  76. EXPECT_FALSE(url.is_valid());
  77. EXPECT_EQ("", url.spec());
  78. EXPECT_EQ("", url.scheme());
  79. EXPECT_EQ("", url.username());
  80. EXPECT_EQ("", url.password());
  81. EXPECT_EQ("", url.host());
  82. EXPECT_EQ("", url.port());
  83. EXPECT_EQ(PORT_UNSPECIFIED, url.IntPort());
  84. EXPECT_EQ("", url.path());
  85. EXPECT_EQ("", url.query());
  86. EXPECT_EQ("", url.ref());
  87. }
  88. TEST(GURLTest, Copy) {
  89. GURL url(u"http://user:pass@google.com:99/foo;bar?q=a#ref");
  90. GURL url2(url);
  91. EXPECT_TRUE(url2.is_valid());
  92. EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
  93. EXPECT_EQ("http", url2.scheme());
  94. EXPECT_EQ("user", url2.username());
  95. EXPECT_EQ("pass", url2.password());
  96. EXPECT_EQ("google.com", url2.host());
  97. EXPECT_EQ("99", url2.port());
  98. EXPECT_EQ(99, url2.IntPort());
  99. EXPECT_EQ("/foo;bar", url2.path());
  100. EXPECT_EQ("q=a", url2.query());
  101. EXPECT_EQ("ref", url2.ref());
  102. // Copying of invalid URL should be invalid
  103. GURL invalid;
  104. GURL invalid2(invalid);
  105. EXPECT_FALSE(invalid2.is_valid());
  106. EXPECT_EQ("", invalid2.spec());
  107. EXPECT_EQ("", invalid2.scheme());
  108. EXPECT_EQ("", invalid2.username());
  109. EXPECT_EQ("", invalid2.password());
  110. EXPECT_EQ("", invalid2.host());
  111. EXPECT_EQ("", invalid2.port());
  112. EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
  113. EXPECT_EQ("", invalid2.path());
  114. EXPECT_EQ("", invalid2.query());
  115. EXPECT_EQ("", invalid2.ref());
  116. }
  117. TEST(GURLTest, Assign) {
  118. GURL url(u"http://user:pass@google.com:99/foo;bar?q=a#ref");
  119. GURL url2;
  120. url2 = url;
  121. EXPECT_TRUE(url2.is_valid());
  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. // Assignment of invalid URL should be invalid
  133. GURL invalid;
  134. GURL invalid2;
  135. 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. // This is a regression test for http://crbug.com/309975.
  149. TEST(GURLTest, SelfAssign) {
  150. GURL a("filesystem:http://example.com/temporary/");
  151. // This should not crash.
  152. a = *&a; // The *& defeats Clang's -Wself-assign warning.
  153. }
  154. TEST(GURLTest, CopyFileSystem) {
  155. GURL url(u"filesystem:https://user:pass@google.com:99/t/foo;bar?q=a#ref");
  156. GURL url2(url);
  157. EXPECT_TRUE(url2.is_valid());
  158. EXPECT_EQ("filesystem:https://google.com:99/t/foo;bar?q=a#ref", url2.spec());
  159. EXPECT_EQ("filesystem", url2.scheme());
  160. EXPECT_EQ("", url2.username());
  161. EXPECT_EQ("", url2.password());
  162. EXPECT_EQ("", url2.host());
  163. EXPECT_EQ("", url2.port());
  164. EXPECT_EQ(PORT_UNSPECIFIED, url2.IntPort());
  165. EXPECT_EQ("/foo;bar", url2.path());
  166. EXPECT_EQ("q=a", url2.query());
  167. EXPECT_EQ("ref", url2.ref());
  168. const GURL* inner = url2.inner_url();
  169. ASSERT_TRUE(inner);
  170. EXPECT_EQ("https", inner->scheme());
  171. EXPECT_EQ("", inner->username());
  172. EXPECT_EQ("", inner->password());
  173. EXPECT_EQ("google.com", inner->host());
  174. EXPECT_EQ("99", inner->port());
  175. EXPECT_EQ(99, inner->IntPort());
  176. EXPECT_EQ("/t", inner->path());
  177. EXPECT_EQ("", inner->query());
  178. EXPECT_EQ("", inner->ref());
  179. }
  180. TEST(GURLTest, IsValid) {
  181. const char* valid_cases[] = {
  182. "http://google.com",
  183. "unknown://google.com",
  184. "http://user:pass@google.com",
  185. "http://google.com:12345",
  186. "http://google.com:0", // 0 is a valid port
  187. "http://google.com/path",
  188. "http://google.com//path",
  189. "http://google.com?k=v#fragment",
  190. "http://user:pass@google.com:12345/path?k=v#fragment",
  191. "http:/path",
  192. "http:path",
  193. };
  194. for (size_t i = 0; i < std::size(valid_cases); i++) {
  195. EXPECT_TRUE(GURL(valid_cases[i]).is_valid())
  196. << "Case: " << valid_cases[i];
  197. }
  198. const char* invalid_cases[] = {
  199. "http://?k=v",
  200. "http:://google.com",
  201. "http//google.com",
  202. "http://google.com:12three45",
  203. "file://server:123", // file: URLs cannot have a port
  204. "file://server:0",
  205. "://google.com",
  206. "path",
  207. };
  208. for (size_t i = 0; i < std::size(invalid_cases); i++) {
  209. EXPECT_FALSE(GURL(invalid_cases[i]).is_valid())
  210. << "Case: " << invalid_cases[i];
  211. }
  212. }
  213. TEST(GURLTest, ExtraSlashesBeforeAuthority) {
  214. // According to RFC3986, the hierarchical part for URI with an authority
  215. // must use only two slashes; GURL intentionally just ignores extra slashes
  216. // if there are more than 2, and parses the following part as an authority.
  217. GURL url("http:///host");
  218. EXPECT_EQ("host", url.host());
  219. EXPECT_EQ("/", url.path());
  220. }
  221. // Given invalid URLs, we should still get most of the components.
  222. TEST(GURLTest, ComponentGettersWorkEvenForInvalidURL) {
  223. constexpr struct InvalidURLTestExpectations {
  224. const char* url;
  225. const char* spec;
  226. const char* scheme;
  227. const char* host;
  228. const char* port;
  229. const char* path;
  230. // Extend as needed...
  231. } expectations[] = {
  232. {
  233. "http:google.com:foo",
  234. "http://google.com:foo/",
  235. "http",
  236. "google.com",
  237. "foo",
  238. "/",
  239. },
  240. {
  241. "https:google.com:foo",
  242. "https://google.com:foo/",
  243. "https",
  244. "google.com",
  245. "foo",
  246. "/",
  247. },
  248. };
  249. for (const auto& e : expectations) {
  250. const GURL url(e.url);
  251. EXPECT_FALSE(url.is_valid());
  252. EXPECT_EQ(e.spec, url.possibly_invalid_spec());
  253. EXPECT_EQ(e.scheme, url.scheme());
  254. EXPECT_EQ("", url.username());
  255. EXPECT_EQ("", url.password());
  256. EXPECT_EQ(e.host, url.host());
  257. EXPECT_EQ(e.port, url.port());
  258. EXPECT_EQ(PORT_INVALID, url.IntPort());
  259. EXPECT_EQ(e.path, url.path());
  260. EXPECT_EQ("", url.query());
  261. EXPECT_EQ("", url.ref());
  262. }
  263. }
  264. TEST(GURLTest, Resolve) {
  265. // The tricky cases for relative URL resolving are tested in the
  266. // canonicalizer unit test. Here, we just test that the GURL integration
  267. // works properly.
  268. struct ResolveCase {
  269. const char* base;
  270. const char* relative;
  271. bool expected_valid;
  272. const char* expected;
  273. } resolve_cases[] = {
  274. {"http://www.google.com/", "foo.html", true,
  275. "http://www.google.com/foo.html"},
  276. {"http://www.google.com/foo/", "bar", true,
  277. "http://www.google.com/foo/bar"},
  278. {"http://www.google.com/foo/", "/bar", true, "http://www.google.com/bar"},
  279. {"http://www.google.com/foo", "bar", true, "http://www.google.com/bar"},
  280. {"http://www.google.com/", "http://images.google.com/foo.html", true,
  281. "http://images.google.com/foo.html"},
  282. {"http://www.google.com/", "http://images.\tgoogle.\ncom/\rfoo.html",
  283. true, "http://images.google.com/foo.html"},
  284. {"http://www.google.com/blah/bloo?c#d", "../../../hello/./world.html?a#b",
  285. true, "http://www.google.com/hello/world.html?a#b"},
  286. {"http://www.google.com/foo#bar", "#com", true,
  287. "http://www.google.com/foo#com"},
  288. {"http://www.google.com/", "Https:images.google.com", true,
  289. "https://images.google.com/"},
  290. // A non-standard base can be replaced with a standard absolute URL.
  291. {"data:blahblah", "http://google.com/", true, "http://google.com/"},
  292. {"data:blahblah", "http:google.com", true, "http://google.com/"},
  293. {"data:blahblah", "https:google.com", true, "https://google.com/"},
  294. // Filesystem URLs have different paths to test.
  295. {"filesystem:http://www.google.com/type/", "foo.html", true,
  296. "filesystem:http://www.google.com/type/foo.html"},
  297. {"filesystem:http://www.google.com/type/", "../foo.html", true,
  298. "filesystem:http://www.google.com/type/foo.html"},
  299. // https://crbug.com/530123 - scheme validation (e.g. are "10.0.0.7:"
  300. // or "x1:" valid schemes) when deciding if |relative| is an absolute url.
  301. {"file:///some/dir/ip-relative.html", "10.0.0.7:8080/foo.html", true,
  302. "file:///some/dir/10.0.0.7:8080/foo.html"},
  303. {"file:///some/dir/", "1://host", true, "file:///some/dir/1://host"},
  304. {"file:///some/dir/", "x1://host", true, "x1://host"},
  305. {"file:///some/dir/", "X1://host", true, "x1://host"},
  306. {"file:///some/dir/", "x.://host", true, "x.://host"},
  307. {"file:///some/dir/", "x+://host", true, "x+://host"},
  308. {"file:///some/dir/", "x-://host", true, "x-://host"},
  309. {"file:///some/dir/", "x!://host", true, "file:///some/dir/x!://host"},
  310. {"file:///some/dir/", "://host", true, "file:///some/dir/://host"},
  311. };
  312. for (size_t i = 0; i < std::size(resolve_cases); i++) {
  313. // 8-bit code path.
  314. GURL input(resolve_cases[i].base);
  315. GURL output = input.Resolve(resolve_cases[i].relative);
  316. EXPECT_EQ(resolve_cases[i].expected_valid, output.is_valid()) << i;
  317. EXPECT_EQ(resolve_cases[i].expected, output.spec()) << i;
  318. EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
  319. // Wide code path.
  320. GURL inputw(base::UTF8ToUTF16(resolve_cases[i].base));
  321. GURL outputw =
  322. input.Resolve(base::UTF8ToUTF16(resolve_cases[i].relative));
  323. EXPECT_EQ(resolve_cases[i].expected_valid, outputw.is_valid()) << i;
  324. EXPECT_EQ(resolve_cases[i].expected, outputw.spec()) << i;
  325. EXPECT_EQ(outputw.SchemeIsFileSystem(), outputw.inner_url() != NULL);
  326. }
  327. }
  328. TEST(GURLTest, GetOrigin) {
  329. struct TestCase {
  330. const char* input;
  331. const char* expected;
  332. } cases[] = {
  333. {"http://www.google.com", "http://www.google.com/"},
  334. {"javascript:window.alert(\"hello,world\");", ""},
  335. {"http://user:pass@www.google.com:21/blah#baz",
  336. "http://www.google.com:21/"},
  337. {"http://user@www.google.com", "http://www.google.com/"},
  338. {"http://:pass@www.google.com", "http://www.google.com/"},
  339. {"http://:@www.google.com", "http://www.google.com/"},
  340. {"filesystem:http://www.google.com/temp/foo?q#b",
  341. "http://www.google.com/"},
  342. {"filesystem:http://user:pass@google.com:21/blah#baz",
  343. "http://google.com:21/"},
  344. {"blob:null/guid-goes-here", ""},
  345. {"blob:http://origin/guid-goes-here", "" /* should be http://origin/ */},
  346. };
  347. for (size_t i = 0; i < std::size(cases); i++) {
  348. GURL url(cases[i].input);
  349. GURL origin = url.DeprecatedGetOriginAsURL();
  350. EXPECT_EQ(cases[i].expected, origin.spec());
  351. }
  352. }
  353. TEST(GURLTest, GetAsReferrer) {
  354. struct TestCase {
  355. const char* input;
  356. const char* expected;
  357. } cases[] = {
  358. {"http://www.google.com", "http://www.google.com/"},
  359. {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/blah"},
  360. {"http://user@www.google.com", "http://www.google.com/"},
  361. {"http://:pass@www.google.com", "http://www.google.com/"},
  362. {"http://:@www.google.com", "http://www.google.com/"},
  363. {"http://www.google.com/temp/foo?q#b", "http://www.google.com/temp/foo?q"},
  364. {"not a url", ""},
  365. {"unknown-scheme://foo.html", ""},
  366. {"file:///tmp/test.html", ""},
  367. {"https://www.google.com", "https://www.google.com/"},
  368. };
  369. for (size_t i = 0; i < std::size(cases); i++) {
  370. GURL url(cases[i].input);
  371. GURL origin = url.GetAsReferrer();
  372. EXPECT_EQ(cases[i].expected, origin.spec());
  373. }
  374. }
  375. TEST(GURLTest, GetWithEmptyPath) {
  376. struct TestCase {
  377. const char* input;
  378. const char* expected;
  379. } cases[] = {
  380. {"http://www.google.com", "http://www.google.com/"},
  381. {"javascript:window.alert(\"hello, world\");", ""},
  382. {"http://www.google.com/foo/bar.html?baz=22", "http://www.google.com/"},
  383. {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
  384. {"filesystem:file:///temporary/bar.html?baz=22", "filesystem:file:///temporary/"},
  385. };
  386. for (size_t i = 0; i < std::size(cases); i++) {
  387. GURL url(cases[i].input);
  388. GURL empty_path = url.GetWithEmptyPath();
  389. EXPECT_EQ(cases[i].expected, empty_path.spec());
  390. }
  391. }
  392. TEST(GURLTest, GetWithoutFilename) {
  393. struct TestCase {
  394. const char* input;
  395. const char* expected;
  396. } cases[] = {
  397. // Common Standard URLs.
  398. {"https://www.google.com", "https://www.google.com/"},
  399. {"https://www.google.com/", "https://www.google.com/"},
  400. {"https://www.google.com/maps.htm", "https://www.google.com/"},
  401. {"https://www.google.com/maps/", "https://www.google.com/maps/"},
  402. {"https://www.google.com/index.html", "https://www.google.com/"},
  403. {"https://www.google.com/index.html?q=maps", "https://www.google.com/"},
  404. {"https://www.google.com/index.html#maps/", "https://www.google.com/"},
  405. {"https://foo:bar@www.google.com/maps.htm", "https://foo:bar@www.google.com/"},
  406. {"https://www.google.com/maps/au/index.html", "https://www.google.com/maps/au/"},
  407. {"https://www.google.com/maps/au/north", "https://www.google.com/maps/au/"},
  408. {"https://www.google.com/maps/au/north/", "https://www.google.com/maps/au/north/"},
  409. {"https://www.google.com/maps/au/index.html?q=maps#fragment/", "https://www.google.com/maps/au/"},
  410. {"http://www.google.com:8000/maps/au/index.html?q=maps#fragment/", "http://www.google.com:8000/maps/au/"},
  411. {"https://www.google.com/maps/au/north/?q=maps#fragment", "https://www.google.com/maps/au/north/"},
  412. {"https://www.google.com/maps/au/north?q=maps#fragment", "https://www.google.com/maps/au/"},
  413. // Less common standard URLs.
  414. {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
  415. {"file:///temporary/bar.html?baz=22","file:///temporary/"},
  416. {"ftp://foo/test/index.html", "ftp://foo/test/"},
  417. {"gopher://foo/test/index.html", "gopher://foo/test/"},
  418. {"ws://foo/test/index.html", "ws://foo/test/"},
  419. // Non-standard, hierarchical URLs.
  420. {"chrome://foo/bar.html", "chrome://foo/"},
  421. {"httpa://foo/test/index.html", "httpa://foo/test/"},
  422. // Non-standard, non-hierarchical URLs.
  423. {"blob:https://foo.bar/test/index.html", ""},
  424. {"about:blank", ""},
  425. {"data:foobar", ""},
  426. {"scheme:opaque_data", ""},
  427. // Invalid URLs.
  428. {"foobar", ""},
  429. };
  430. for (size_t i = 0; i < std::size(cases); i++) {
  431. GURL url(cases[i].input);
  432. GURL without_filename = url.GetWithoutFilename();
  433. EXPECT_EQ(cases[i].expected, without_filename.spec()) << i;
  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. using ApplyReplacementsFunc = GURL(const GURL&);
  442. const char* base;
  443. ApplyReplacementsFunc* apply_replacements;
  444. const char* expected;
  445. } replace_cases[] = {
  446. {.base = "http://www.google.com/foo/bar.html?foo#bar",
  447. .apply_replacements =
  448. +[](const GURL& url) {
  449. GURL::Replacements replacements;
  450. replacements.SetPathStr("/");
  451. replacements.ClearQuery();
  452. replacements.ClearRef();
  453. return url.ReplaceComponents(replacements);
  454. },
  455. .expected = "http://www.google.com/"},
  456. {.base = "http://www.google.com/foo/bar.html?foo#bar",
  457. .apply_replacements =
  458. +[](const GURL& url) {
  459. GURL::Replacements replacements;
  460. replacements.SetSchemeStr("javascript");
  461. replacements.ClearUsername();
  462. replacements.ClearPassword();
  463. replacements.ClearHost();
  464. replacements.ClearPort();
  465. replacements.SetPathStr("window.open('foo');");
  466. replacements.ClearQuery();
  467. replacements.ClearRef();
  468. return url.ReplaceComponents(replacements);
  469. },
  470. .expected = "javascript:window.open('foo');"},
  471. {.base = "file:///C:/foo/bar.txt",
  472. .apply_replacements =
  473. +[](const GURL& url) {
  474. GURL::Replacements replacements;
  475. replacements.SetSchemeStr("http");
  476. replacements.SetHostStr("www.google.com");
  477. replacements.SetPortStr("99");
  478. replacements.SetPathStr("/foo");
  479. replacements.SetQueryStr("search");
  480. replacements.SetRefStr("ref");
  481. return url.ReplaceComponents(replacements);
  482. },
  483. .expected = "http://www.google.com:99/foo?search#ref"},
  484. #ifdef WIN32
  485. {.base = "http://www.google.com/foo/bar.html?foo#bar",
  486. .apply_replacements =
  487. +[](const GURL& url) {
  488. GURL::Replacements replacements;
  489. replacements.SetSchemeStr("file");
  490. replacements.ClearUsername();
  491. replacements.ClearPassword();
  492. replacements.ClearHost();
  493. replacements.ClearPort();
  494. replacements.SetPathStr("c:\\");
  495. replacements.ClearQuery();
  496. replacements.ClearRef();
  497. return url.ReplaceComponents(replacements);
  498. },
  499. .expected = "file:///C:/"},
  500. #endif
  501. {.base = "filesystem:http://www.google.com/foo/bar.html?foo#bar",
  502. .apply_replacements =
  503. +[](const GURL& url) {
  504. GURL::Replacements replacements;
  505. replacements.SetPathStr("/");
  506. replacements.ClearQuery();
  507. replacements.ClearRef();
  508. return url.ReplaceComponents(replacements);
  509. },
  510. .expected = "filesystem:http://www.google.com/foo/"},
  511. // Lengthen the URL instead of shortening it, to test creation of
  512. // inner_url.
  513. {.base = "filesystem:http://www.google.com/foo/",
  514. .apply_replacements =
  515. +[](const GURL& url) {
  516. GURL::Replacements replacements;
  517. replacements.SetPathStr("bar.html");
  518. replacements.SetQueryStr("foo");
  519. replacements.SetRefStr("bar");
  520. return url.ReplaceComponents(replacements);
  521. },
  522. .expected = "filesystem:http://www.google.com/foo/bar.html?foo#bar"},
  523. };
  524. for (const ReplaceCase& c : replace_cases) {
  525. GURL output = c.apply_replacements(GURL(c.base));
  526. EXPECT_EQ(c.expected, output.spec());
  527. EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
  528. if (output.SchemeIsFileSystem()) {
  529. // TODO(mmenke): inner_url()->spec() is currently the same as the spec()
  530. // for the GURL itself. This should be fixed.
  531. // See https://crbug.com/619596
  532. EXPECT_EQ(c.expected, output.inner_url()->spec());
  533. }
  534. }
  535. }
  536. TEST(GURLTest, ClearFragmentOnDataUrl) {
  537. // http://crbug.com/291747 - a data URL may legitimately have trailing
  538. // whitespace in the spec after the ref is cleared. Test this does not trigger
  539. // the Parsed importing validation DCHECK in GURL.
  540. GURL url(" data: one # two ");
  541. EXPECT_TRUE(url.is_valid());
  542. // By default the trailing whitespace will have been stripped.
  543. EXPECT_EQ("data: one #%20two", url.spec());
  544. // Clear the URL's ref and observe the trailing whitespace.
  545. GURL::Replacements repl;
  546. repl.ClearRef();
  547. GURL url_no_ref = url.ReplaceComponents(repl);
  548. EXPECT_TRUE(url_no_ref.is_valid());
  549. EXPECT_EQ("data: one ", url_no_ref.spec());
  550. // Importing a parsed URL via this constructor overload will retain trailing
  551. // whitespace.
  552. GURL import_url(url_no_ref.spec(),
  553. url_no_ref.parsed_for_possibly_invalid_spec(),
  554. url_no_ref.is_valid());
  555. EXPECT_TRUE(import_url.is_valid());
  556. EXPECT_EQ(url_no_ref, import_url);
  557. EXPECT_EQ("data: one ", import_url.spec());
  558. EXPECT_EQ(" one ", import_url.path());
  559. // For completeness, test that re-parsing the same URL rather than importing
  560. // it trims the trailing whitespace.
  561. GURL reparsed_url(url_no_ref.spec());
  562. EXPECT_TRUE(reparsed_url.is_valid());
  563. EXPECT_EQ("data: one", reparsed_url.spec());
  564. }
  565. TEST(GURLTest, PathForRequest) {
  566. struct TestCase {
  567. const char* input;
  568. const char* expected;
  569. const char* inner_expected;
  570. } cases[] = {
  571. {"http://www.google.com", "/", nullptr},
  572. {"http://www.google.com/", "/", nullptr},
  573. {"http://www.google.com/foo/bar.html?baz=22", "/foo/bar.html?baz=22",
  574. nullptr},
  575. {"http://www.google.com/foo/bar.html#ref", "/foo/bar.html", nullptr},
  576. {"http://www.google.com/foo/bar.html?query#ref", "/foo/bar.html?query",
  577. nullptr},
  578. {"filesystem:http://www.google.com/temporary/foo/bar.html?query#ref",
  579. "/foo/bar.html?query", "/temporary"},
  580. {"filesystem:http://www.google.com/temporary/foo/bar.html?query",
  581. "/foo/bar.html?query", "/temporary"},
  582. };
  583. for (size_t i = 0; i < std::size(cases); i++) {
  584. GURL url(cases[i].input);
  585. EXPECT_EQ(cases[i].expected, url.PathForRequest());
  586. EXPECT_EQ(cases[i].expected, url.PathForRequestPiece());
  587. EXPECT_EQ(cases[i].inner_expected == NULL, url.inner_url() == NULL);
  588. if (url.inner_url() && cases[i].inner_expected) {
  589. EXPECT_EQ(cases[i].inner_expected, url.inner_url()->PathForRequest());
  590. EXPECT_EQ(cases[i].inner_expected,
  591. url.inner_url()->PathForRequestPiece());
  592. }
  593. }
  594. }
  595. TEST(GURLTest, EffectiveIntPort) {
  596. struct PortTest {
  597. const char* spec;
  598. int expected_int_port;
  599. } port_tests[] = {
  600. // http
  601. {"http://www.google.com/", 80},
  602. {"http://www.google.com:80/", 80},
  603. {"http://www.google.com:443/", 443},
  604. // https
  605. {"https://www.google.com/", 443},
  606. {"https://www.google.com:443/", 443},
  607. {"https://www.google.com:80/", 80},
  608. // ftp
  609. {"ftp://www.google.com/", 21},
  610. {"ftp://www.google.com:21/", 21},
  611. {"ftp://www.google.com:80/", 80},
  612. // file - no port
  613. {"file://www.google.com/", PORT_UNSPECIFIED},
  614. {"file://www.google.com:443/", PORT_UNSPECIFIED},
  615. // data - no port
  616. {"data:www.google.com:90", PORT_UNSPECIFIED},
  617. {"data:www.google.com", PORT_UNSPECIFIED},
  618. // filesystem - no port
  619. {"filesystem:http://www.google.com:90/t/foo", PORT_UNSPECIFIED},
  620. {"filesystem:file:///t/foo", PORT_UNSPECIFIED},
  621. };
  622. for (size_t i = 0; i < std::size(port_tests); i++) {
  623. GURL url(port_tests[i].spec);
  624. EXPECT_EQ(port_tests[i].expected_int_port, url.EffectiveIntPort());
  625. }
  626. }
  627. TEST(GURLTest, IPAddress) {
  628. struct IPTest {
  629. const char* spec;
  630. bool expected_ip;
  631. } ip_tests[] = {
  632. {"http://www.google.com/", false},
  633. {"http://192.168.9.1/", true},
  634. {"http://192.168.9.1.2/", false},
  635. {"http://192.168.m.1/", false},
  636. {"http://2001:db8::1/", false},
  637. {"http://[2001:db8::1]/", true},
  638. {"", false},
  639. {"some random input!", false},
  640. };
  641. for (size_t i = 0; i < std::size(ip_tests); i++) {
  642. GURL url(ip_tests[i].spec);
  643. EXPECT_EQ(ip_tests[i].expected_ip, url.HostIsIPAddress());
  644. }
  645. }
  646. TEST(GURLTest, HostNoBrackets) {
  647. struct TestCase {
  648. const char* input;
  649. const char* expected_host;
  650. const char* expected_plainhost;
  651. } cases[] = {
  652. {"http://www.google.com", "www.google.com", "www.google.com"},
  653. {"http://[2001:db8::1]/", "[2001:db8::1]", "2001:db8::1"},
  654. {"http://[::]/", "[::]", "::"},
  655. // Don't require a valid URL, but don't crash either.
  656. {"http://[]/", "[]", ""},
  657. {"http://[x]/", "[x]", "x"},
  658. {"http://[x/", "[x", "[x"},
  659. {"http://x]/", "x]", "x]"},
  660. {"http://[/", "[", "["},
  661. {"http://]/", "]", "]"},
  662. {"", "", ""},
  663. };
  664. for (size_t i = 0; i < std::size(cases); i++) {
  665. GURL url(cases[i].input);
  666. EXPECT_EQ(cases[i].expected_host, url.host());
  667. EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBrackets());
  668. EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBracketsPiece());
  669. }
  670. }
  671. TEST(GURLTest, DomainIs) {
  672. GURL url_1("http://google.com/foo");
  673. EXPECT_TRUE(url_1.DomainIs("google.com"));
  674. // Subdomain and port are ignored.
  675. GURL url_2("http://www.google.com:99/foo");
  676. EXPECT_TRUE(url_2.DomainIs("google.com"));
  677. // Different top-level domain.
  678. GURL url_3("http://www.google.com.cn/foo");
  679. EXPECT_FALSE(url_3.DomainIs("google.com"));
  680. // Different host name.
  681. GURL url_4("http://www.iamnotgoogle.com/foo");
  682. EXPECT_FALSE(url_4.DomainIs("google.com"));
  683. // The input must be lower-cased otherwise DomainIs returns false.
  684. GURL url_5("http://www.google.com/foo");
  685. EXPECT_FALSE(url_5.DomainIs("Google.com"));
  686. // If the URL is invalid, DomainIs returns false.
  687. GURL invalid_url("google.com");
  688. EXPECT_FALSE(invalid_url.is_valid());
  689. EXPECT_FALSE(invalid_url.DomainIs("google.com"));
  690. GURL url_with_escape_chars("https://www.,.test");
  691. EXPECT_TRUE(url_with_escape_chars.is_valid());
  692. EXPECT_EQ(url_with_escape_chars.host(), "www.%2C.test");
  693. EXPECT_TRUE(url_with_escape_chars.DomainIs("%2C.test"));
  694. }
  695. TEST(GURLTest, DomainIsTerminatingDotBehavior) {
  696. // If the host part ends with a dot, it matches input domains
  697. // with or without a dot.
  698. GURL url_with_dot("http://www.google.com./foo");
  699. EXPECT_TRUE(url_with_dot.DomainIs("google.com"));
  700. EXPECT_TRUE(url_with_dot.DomainIs("google.com."));
  701. EXPECT_TRUE(url_with_dot.DomainIs(".com"));
  702. EXPECT_TRUE(url_with_dot.DomainIs(".com."));
  703. // But, if the host name doesn't end with a dot and the input
  704. // domain does, then it's considered to not match.
  705. GURL url_without_dot("http://google.com/foo");
  706. EXPECT_FALSE(url_without_dot.DomainIs("google.com."));
  707. // If the URL ends with two dots, it doesn't match.
  708. GURL url_with_two_dots("http://www.google.com../foo");
  709. EXPECT_FALSE(url_with_two_dots.DomainIs("google.com"));
  710. }
  711. TEST(GURLTest, DomainIsWithFilesystemScheme) {
  712. GURL url_1("filesystem:http://www.google.com:99/foo/");
  713. EXPECT_TRUE(url_1.DomainIs("google.com"));
  714. GURL url_2("filesystem:http://www.iamnotgoogle.com/foo/");
  715. EXPECT_FALSE(url_2.DomainIs("google.com"));
  716. }
  717. // Newlines should be stripped from inputs.
  718. TEST(GURLTest, Newlines) {
  719. // Constructor.
  720. GURL url_1(" \t ht\ntp://\twww.goo\rgle.com/as\ndf \n ");
  721. EXPECT_EQ("http://www.google.com/asdf", url_1.spec());
  722. EXPECT_FALSE(
  723. url_1.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
  724. // Relative path resolver.
  725. GURL url_2 = url_1.Resolve(" \n /fo\to\r ");
  726. EXPECT_EQ("http://www.google.com/foo", url_2.spec());
  727. EXPECT_FALSE(
  728. url_2.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
  729. // Constructor.
  730. GURL url_3(" \t ht\ntp://\twww.goo\rgle.com/as\ndf< \n ");
  731. EXPECT_EQ("http://www.google.com/asdf%3C", url_3.spec());
  732. EXPECT_TRUE(
  733. url_3.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
  734. // Relative path resolver.
  735. GURL url_4 = url_1.Resolve(" \n /fo\to<\r ");
  736. EXPECT_EQ("http://www.google.com/foo%3C", url_4.spec());
  737. EXPECT_TRUE(
  738. url_4.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
  739. // Note that newlines are NOT stripped from ReplaceComponents.
  740. }
  741. TEST(GURLTest, IsStandard) {
  742. GURL a("http:foo/bar");
  743. EXPECT_TRUE(a.IsStandard());
  744. GURL b("foo:bar/baz");
  745. EXPECT_FALSE(b.IsStandard());
  746. GURL c("foo://bar/baz");
  747. EXPECT_FALSE(c.IsStandard());
  748. GURL d("cid:bar@baz");
  749. EXPECT_FALSE(d.IsStandard());
  750. }
  751. TEST(GURLTest, SchemeIsHTTPOrHTTPS) {
  752. EXPECT_TRUE(GURL("http://bar/").SchemeIsHTTPOrHTTPS());
  753. EXPECT_TRUE(GURL("HTTPS://BAR").SchemeIsHTTPOrHTTPS());
  754. EXPECT_FALSE(GURL("ftp://bar/").SchemeIsHTTPOrHTTPS());
  755. }
  756. TEST(GURLTest, SchemeIsWSOrWSS) {
  757. EXPECT_TRUE(GURL("WS://BAR/").SchemeIsWSOrWSS());
  758. EXPECT_TRUE(GURL("wss://bar/").SchemeIsWSOrWSS());
  759. EXPECT_FALSE(GURL("http://bar/").SchemeIsWSOrWSS());
  760. }
  761. TEST(GURLTest, SchemeIsCryptographic) {
  762. EXPECT_TRUE(GURL("https://foo.bar.com/").SchemeIsCryptographic());
  763. EXPECT_TRUE(GURL("HTTPS://foo.bar.com/").SchemeIsCryptographic());
  764. EXPECT_TRUE(GURL("HtTpS://foo.bar.com/").SchemeIsCryptographic());
  765. EXPECT_TRUE(GURL("wss://foo.bar.com/").SchemeIsCryptographic());
  766. EXPECT_TRUE(GURL("WSS://foo.bar.com/").SchemeIsCryptographic());
  767. EXPECT_TRUE(GURL("WsS://foo.bar.com/").SchemeIsCryptographic());
  768. EXPECT_FALSE(GURL("http://foo.bar.com/").SchemeIsCryptographic());
  769. EXPECT_FALSE(GURL("ws://foo.bar.com/").SchemeIsCryptographic());
  770. }
  771. TEST(GURLTest, SchemeIsCryptographicStatic) {
  772. EXPECT_TRUE(GURL::SchemeIsCryptographic("https"));
  773. EXPECT_TRUE(GURL::SchemeIsCryptographic("wss"));
  774. EXPECT_FALSE(GURL::SchemeIsCryptographic("http"));
  775. EXPECT_FALSE(GURL::SchemeIsCryptographic("ws"));
  776. EXPECT_FALSE(GURL::SchemeIsCryptographic("ftp"));
  777. }
  778. TEST(GURLTest, SchemeIsBlob) {
  779. EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsBlob());
  780. EXPECT_TRUE(GURL("blob://bar/").SchemeIsBlob());
  781. EXPECT_FALSE(GURL("http://bar/").SchemeIsBlob());
  782. }
  783. TEST(GURLTest, SchemeIsLocal) {
  784. EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsLocal());
  785. EXPECT_TRUE(GURL("blob://bar/").SchemeIsLocal());
  786. EXPECT_TRUE(GURL("DATA:TEXT/HTML,BAR").SchemeIsLocal());
  787. EXPECT_TRUE(GURL("data:text/html,bar").SchemeIsLocal());
  788. EXPECT_TRUE(GURL("ABOUT:BAR").SchemeIsLocal());
  789. EXPECT_TRUE(GURL("about:bar").SchemeIsLocal());
  790. EXPECT_TRUE(GURL("FILESYSTEM:HTTP://FOO.EXAMPLE/BAR").SchemeIsLocal());
  791. EXPECT_TRUE(GURL("filesystem:http://foo.example/bar").SchemeIsLocal());
  792. EXPECT_FALSE(GURL("http://bar/").SchemeIsLocal());
  793. EXPECT_FALSE(GURL("file:///bar").SchemeIsLocal());
  794. }
  795. // Tests that the 'content' of the URL is properly extracted. This can be
  796. // complex in cases such as multiple schemes (view-source:http:) or for
  797. // javascript URLs. See GURL::GetContent for more details.
  798. TEST(GURLTest, ContentForNonStandardURLs) {
  799. struct TestCase {
  800. const char* url;
  801. const char* expected;
  802. } cases[] = {
  803. {"null", ""},
  804. {"not-a-standard-scheme:this is arbitrary content",
  805. "this is arbitrary content"},
  806. // When there are multiple schemes, only the first is excluded from the
  807. // content. Note also that for e.g. 'http://', the '//' is part of the
  808. // content not the scheme.
  809. {"view-source:http://example.com/path", "http://example.com/path"},
  810. {"blob:http://example.com/GUID", "http://example.com/GUID"},
  811. {"blob://http://example.com/GUID", "//http://example.com/GUID"},
  812. {"blob:http://user:password@example.com/GUID",
  813. "http://user:password@example.com/GUID"},
  814. // The octothorpe character ('#') marks the end of the URL content, and
  815. // the start of the fragment. It should not be included in the content.
  816. {"http://www.example.com/GUID#ref", "www.example.com/GUID"},
  817. {"http://me:secret@example.com/GUID/#ref", "me:secret@example.com/GUID/"},
  818. {"data:text/html,Question?<div style=\"color: #bad\">idea</div>",
  819. "text/html,Question?%3Cdiv%20style=%22color:%20"},
  820. // TODO(mkwst): This seems like a bug. https://crbug.com/513600
  821. {"filesystem:http://example.com/path", "/"},
  822. // Javascript URLs include '#' symbols in their content.
  823. {"javascript:#", "#"},
  824. {"javascript:alert('#');", "alert('#');"},
  825. };
  826. for (const auto& test : cases) {
  827. GURL url(test.url);
  828. EXPECT_EQ(test.expected, url.GetContent()) << test.url;
  829. EXPECT_EQ(test.expected, url.GetContentPiece()) << test.url;
  830. }
  831. }
  832. // Tests that the URL path is properly extracted for unusual URLs. This can be
  833. // complex in cases such as multiple schemes (view-source:http:) or when
  834. // octothorpes ('#') are involved.
  835. TEST(GURLTest, PathForNonStandardURLs) {
  836. struct TestCase {
  837. const char* url;
  838. const char* expected;
  839. } cases[] = {
  840. {"null", ""},
  841. {"not-a-standard-scheme:this is arbitrary content",
  842. "this is arbitrary content"},
  843. {"view-source:http://example.com/path", "http://example.com/path"},
  844. {"blob:http://example.com/GUID", "http://example.com/GUID"},
  845. {"blob://http://example.com/GUID", "//http://example.com/GUID"},
  846. {"blob:http://user:password@example.com/GUID",
  847. "http://user:password@example.com/GUID"},
  848. {"http://www.example.com/GUID#ref", "/GUID"},
  849. {"http://me:secret@example.com/GUID/#ref", "/GUID/"},
  850. {"data:text/html,Question?<div style=\"color: #bad\">idea</div>",
  851. "text/html,Question"},
  852. // TODO(mkwst): This seems like a bug. https://crbug.com/513600
  853. {"filesystem:http://example.com/path", "/"},
  854. };
  855. for (const auto& test : cases) {
  856. GURL url(test.url);
  857. EXPECT_EQ(test.expected, url.path()) << test.url;
  858. }
  859. }
  860. TEST(GURLTest, EqualsIgnoringRef) {
  861. const struct {
  862. const char* url_a;
  863. const char* url_b;
  864. bool are_equals;
  865. } kTestCases[] = {
  866. // No ref.
  867. {"http://a.com", "http://a.com", true},
  868. {"http://a.com", "http://b.com", false},
  869. // Same Ref.
  870. {"http://a.com#foo", "http://a.com#foo", true},
  871. {"http://a.com#foo", "http://b.com#foo", false},
  872. // Different Refs.
  873. {"http://a.com#foo", "http://a.com#bar", true},
  874. {"http://a.com#foo", "http://b.com#bar", false},
  875. // One has a ref, the other doesn't.
  876. {"http://a.com#foo", "http://a.com", true},
  877. {"http://a.com#foo", "http://b.com", false},
  878. // Empty refs.
  879. {"http://a.com#", "http://a.com#", true},
  880. {"http://a.com#", "http://a.com", true},
  881. // URLs that differ only by their last character.
  882. {"http://aaa", "http://aab", false},
  883. {"http://aaa#foo", "http://aab#foo", false},
  884. // Different size of the part before the ref.
  885. {"http://123#a", "http://123456#a", false},
  886. // Blob URLs
  887. {"blob:http://a.com#foo", "blob:http://a.com#foo", true},
  888. {"blob:http://a.com#foo", "blob:http://a.com#bar", true},
  889. {"blob:http://a.com#foo", "blob:http://b.com#bar", false},
  890. // Filesystem URLs
  891. {"filesystem:http://a.com#foo", "filesystem:http://a.com#foo", true},
  892. {"filesystem:http://a.com#foo", "filesystem:http://a.com#bar", true},
  893. {"filesystem:http://a.com#foo", "filesystem:http://b.com#bar", false},
  894. // Data URLs
  895. {"data:text/html,a#foo", "data:text/html,a#bar", true},
  896. {"data:text/html,a#foo", "data:text/html,a#foo", true},
  897. {"data:text/html,a#foo", "data:text/html,b#foo", false},
  898. };
  899. for (const auto& test_case : kTestCases) {
  900. SCOPED_TRACE(testing::Message()
  901. << std::endl
  902. << "url_a = " << test_case.url_a << std::endl
  903. << "url_b = " << test_case.url_b << std::endl);
  904. // A versus B.
  905. EXPECT_EQ(test_case.are_equals,
  906. GURL(test_case.url_a).EqualsIgnoringRef(GURL(test_case.url_b)));
  907. // B versus A.
  908. EXPECT_EQ(test_case.are_equals,
  909. GURL(test_case.url_b).EqualsIgnoringRef(GURL(test_case.url_a)));
  910. }
  911. }
  912. TEST(GURLTest, DebugAlias) {
  913. GURL url("https://foo.com/bar");
  914. DEBUG_ALIAS_FOR_GURL(url_debug_alias, url);
  915. EXPECT_STREQ("https://foo.com/bar", url_debug_alias);
  916. }
  917. TEST(GURLTest, InvalidHost) {
  918. // This contains an invalid percent escape (%T%) and also a valid
  919. // percent escape that's not 7-bit ascii (%ae), so that the unescaped
  920. // host contains both an invalid percent escape and invalid UTF-8.
  921. GURL url("http://%T%Ae");
  922. EXPECT_FALSE(url.is_valid());
  923. EXPECT_TRUE(url.SchemeIs(url::kHttpScheme));
  924. // The invalid percent escape becomes an escaped percent sign (%25), and the
  925. // invalid UTF-8 character becomes REPLACEMENT CHARACTER' (U+FFFD) encoded as
  926. // UTF-8.
  927. EXPECT_EQ(url.host_piece(), "%25t%EF%BF%BD");
  928. }
  929. TEST(GURLTest, PortZero) {
  930. GURL port_zero_url("http://127.0.0.1:0/blah");
  931. // https://url.spec.whatwg.org/#port-state says that the port 1) consists of
  932. // ASCII digits (this excludes negative numbers) and 2) cannot be greater than
  933. // 2^16-1. This means that port=0 should be valid.
  934. EXPECT_TRUE(port_zero_url.is_valid());
  935. EXPECT_EQ("0", port_zero_url.port());
  936. EXPECT_EQ("127.0.0.1", port_zero_url.host());
  937. EXPECT_EQ("http", port_zero_url.scheme());
  938. // https://crbug.com/1065532: SchemeHostPort would previously incorrectly
  939. // consider port=0 to be invalid.
  940. SchemeHostPort scheme_host_port(port_zero_url);
  941. EXPECT_TRUE(scheme_host_port.IsValid());
  942. EXPECT_EQ(port_zero_url.scheme(), scheme_host_port.scheme());
  943. EXPECT_EQ(port_zero_url.host(), scheme_host_port.host());
  944. EXPECT_EQ(port_zero_url.port(),
  945. base::NumberToString(scheme_host_port.port()));
  946. // https://crbug.com/1065532: The SchemeHostPort problem above would lead to
  947. // bizarre results below - resolved origin would incorrectly be returned as an
  948. // opaque origin derived from |another_origin|.
  949. url::Origin another_origin = url::Origin::Create(GURL("http://other.com"));
  950. url::Origin resolved_origin =
  951. url::Origin::Resolve(port_zero_url, another_origin);
  952. EXPECT_FALSE(resolved_origin.opaque());
  953. EXPECT_EQ(port_zero_url.scheme(), resolved_origin.scheme());
  954. EXPECT_EQ(port_zero_url.host(), resolved_origin.host());
  955. EXPECT_EQ(port_zero_url.port(), base::NumberToString(resolved_origin.port()));
  956. // port=0 and default HTTP port are different.
  957. GURL default_port("http://127.0.0.1/foo");
  958. EXPECT_EQ(0, SchemeHostPort(port_zero_url).port());
  959. EXPECT_EQ(80, SchemeHostPort(default_port).port());
  960. url::Origin default_port_origin = url::Origin::Create(default_port);
  961. EXPECT_FALSE(default_port_origin.IsSameOriginWith(resolved_origin));
  962. }
  963. class GURLTestTraits {
  964. public:
  965. using UrlType = GURL;
  966. static UrlType CreateUrlFromString(base::StringPiece s) { return GURL(s); }
  967. static bool IsAboutBlank(const UrlType& url) { return url.IsAboutBlank(); }
  968. static bool IsAboutSrcdoc(const UrlType& url) { return url.IsAboutSrcdoc(); }
  969. // Only static members.
  970. GURLTestTraits() = delete;
  971. };
  972. INSTANTIATE_TYPED_TEST_SUITE_P(GURL, AbstractUrlTest, GURLTestTraits);
  973. } // namespace url