Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / test / unit / test_standardurl.js
blobdd15ac512108b1dcd39fe31a7a517f97294860ea
1 "use strict";
3 const gPrefs = Services.prefs;
5 function symmetricEquality(expect, a, b) {
6 /* Use if/else instead of |do_check_eq(expect, a.spec == b.spec)| so
7 that we get the specs output on the console if the check fails.
8 */
9 if (expect) {
10 /* Check all the sub-pieces too, since that can help with
11 debugging cases when equals() returns something unexpected */
12 /* We don't check port in the loop, because it can be defaulted in
13 some cases. */
15 "spec",
16 "prePath",
17 "scheme",
18 "userPass",
19 "username",
20 "password",
21 "hostPort",
22 "host",
23 "pathQueryRef",
24 "filePath",
25 "query",
26 "ref",
27 "directory",
28 "fileName",
29 "fileBaseName",
30 "fileExtension",
31 ].map(function (prop) {
32 dump("Testing '" + prop + "'\n");
33 Assert.equal(a[prop], b[prop]);
34 });
35 } else {
36 Assert.notEqual(a.spec, b.spec);
38 Assert.equal(expect, a.equals(b));
39 Assert.equal(expect, b.equals(a));
42 function stringToURL(str) {
43 return Cc["@mozilla.org/network/standard-url-mutator;1"]
44 .createInstance(Ci.nsIStandardURLMutator)
45 .init(Ci.nsIStandardURL.URLTYPE_AUTHORITY, 80, str, "UTF-8", null)
46 .finalize()
47 .QueryInterface(Ci.nsIURL);
50 function pairToURLs(pair) {
51 Assert.equal(pair.length, 2);
52 return pair.map(stringToURL);
55 add_test(function test_setEmptyPath() {
56 var pairs = [
57 ["http://example.com", "http://example.com/tests/dom/tests"],
58 ["http://example.com:80", "http://example.com/tests/dom/tests"],
59 ["http://example.com:80/", "http://example.com/tests/dom/test"],
60 ["http://example.com/", "http://example.com/tests/dom/tests"],
61 ["http://example.com/a", "http://example.com/tests/dom/tests"],
62 ["http://example.com:80/a", "http://example.com/tests/dom/tests"],
63 ].map(pairToURLs);
65 for (var [provided, target] of pairs) {
66 symmetricEquality(false, target, provided);
68 provided = provided.mutate().setPathQueryRef("").finalize();
69 target = target.mutate().setPathQueryRef("").finalize();
71 Assert.equal(provided.spec, target.spec);
72 symmetricEquality(true, target, provided);
74 run_next_test();
75 });
77 add_test(function test_setQuery() {
78 var pairs = [
79 ["http://example.com", "http://example.com/?foo"],
80 ["http://example.com/bar", "http://example.com/bar?foo"],
81 ["http://example.com#bar", "http://example.com/?foo#bar"],
82 ["http://example.com/#bar", "http://example.com/?foo#bar"],
83 ["http://example.com/?longerthanfoo#bar", "http://example.com/?foo#bar"],
84 ["http://example.com/?longerthanfoo", "http://example.com/?foo"],
85 /* And one that's nonempty but shorter than "foo" */
86 ["http://example.com/?f#bar", "http://example.com/?foo#bar"],
87 ["http://example.com/?f", "http://example.com/?foo"],
88 ].map(pairToURLs);
90 for (var [provided, target] of pairs) {
91 symmetricEquality(false, provided, target);
93 provided = provided
94 .mutate()
95 .setQuery("foo")
96 .finalize()
97 .QueryInterface(Ci.nsIURL);
99 Assert.equal(provided.spec, target.spec);
100 symmetricEquality(true, provided, target);
103 [provided, target] = [
104 "http://example.com/#",
105 "http://example.com/?foo#bar",
106 ].map(stringToURL);
107 symmetricEquality(false, provided, target);
108 provided = provided
109 .mutate()
110 .setQuery("foo")
111 .finalize()
112 .QueryInterface(Ci.nsIURL);
113 symmetricEquality(false, provided, target);
115 var newProvided = Services.io
116 .newURI("#bar", null, provided)
117 .QueryInterface(Ci.nsIURL);
119 Assert.equal(newProvided.spec, target.spec);
120 symmetricEquality(true, newProvided, target);
121 run_next_test();
124 add_test(function test_setRef() {
125 var tests = [
126 ["http://example.com", "", "http://example.com/"],
127 ["http://example.com:80", "", "http://example.com:80/"],
128 ["http://example.com:80/", "", "http://example.com:80/"],
129 ["http://example.com/", "", "http://example.com/"],
130 ["http://example.com/a", "", "http://example.com/a"],
131 ["http://example.com:80/a", "", "http://example.com:80/a"],
133 ["http://example.com", "x", "http://example.com/#x"],
134 ["http://example.com:80", "x", "http://example.com:80/#x"],
135 ["http://example.com:80/", "x", "http://example.com:80/#x"],
136 ["http://example.com/", "x", "http://example.com/#x"],
137 ["http://example.com/a", "x", "http://example.com/a#x"],
138 ["http://example.com:80/a", "x", "http://example.com:80/a#x"],
140 ["http://example.com", "xx", "http://example.com/#xx"],
141 ["http://example.com:80", "xx", "http://example.com:80/#xx"],
142 ["http://example.com:80/", "xx", "http://example.com:80/#xx"],
143 ["http://example.com/", "xx", "http://example.com/#xx"],
144 ["http://example.com/a", "xx", "http://example.com/a#xx"],
145 ["http://example.com:80/a", "xx", "http://example.com:80/a#xx"],
148 "http://example.com",
149 "xxxxxxxxxxxxxx",
150 "http://example.com/#xxxxxxxxxxxxxx",
153 "http://example.com:80",
154 "xxxxxxxxxxxxxx",
155 "http://example.com:80/#xxxxxxxxxxxxxx",
158 "http://example.com:80/",
159 "xxxxxxxxxxxxxx",
160 "http://example.com:80/#xxxxxxxxxxxxxx",
163 "http://example.com/",
164 "xxxxxxxxxxxxxx",
165 "http://example.com/#xxxxxxxxxxxxxx",
168 "http://example.com/a",
169 "xxxxxxxxxxxxxx",
170 "http://example.com/a#xxxxxxxxxxxxxx",
173 "http://example.com:80/a",
174 "xxxxxxxxxxxxxx",
175 "http://example.com:80/a#xxxxxxxxxxxxxx",
179 for (var [before, ref, result] of tests) {
180 /* Test1: starting with empty ref */
181 var a = stringToURL(before);
182 a = a.mutate().setRef(ref).finalize().QueryInterface(Ci.nsIURL);
183 var b = stringToURL(result);
185 Assert.equal(a.spec, b.spec);
186 Assert.equal(ref, b.ref);
187 symmetricEquality(true, a, b);
189 /* Test2: starting with non-empty */
190 a = a.mutate().setRef("yyyy").finalize().QueryInterface(Ci.nsIURL);
191 var c = stringToURL(before);
192 c = c.mutate().setRef("yyyy").finalize().QueryInterface(Ci.nsIURL);
193 symmetricEquality(true, a, c);
195 /* Test3: reset the ref */
196 a = a.mutate().setRef("").finalize().QueryInterface(Ci.nsIURL);
197 symmetricEquality(true, a, stringToURL(before));
199 /* Test4: verify again after reset */
200 a = a.mutate().setRef(ref).finalize().QueryInterface(Ci.nsIURL);
201 symmetricEquality(true, a, b);
203 run_next_test();
206 // Bug 960014 - Make nsStandardURL::SetHost less magical around IPv6
207 add_test(function test_ipv6() {
208 var url = stringToURL("http://example.com");
209 url = url.mutate().setHost("[2001::1]").finalize();
210 Assert.equal(url.host, "2001::1");
212 url = stringToURL("http://example.com");
213 url = url.mutate().setHostPort("[2001::1]:30").finalize();
214 Assert.equal(url.host, "2001::1");
215 Assert.equal(url.port, 30);
216 Assert.equal(url.hostPort, "[2001::1]:30");
218 url = stringToURL("http://example.com");
219 url = url.mutate().setHostPort("2001:1").finalize();
220 Assert.equal(url.host, "0.0.7.209");
221 Assert.equal(url.port, 1);
222 Assert.equal(url.hostPort, "0.0.7.209:1");
223 run_next_test();
226 add_test(function test_ipv6_fail() {
227 var url = stringToURL("http://example.com");
229 Assert.throws(
230 () => {
231 url = url.mutate().setHost("2001::1").finalize();
233 /NS_ERROR_MALFORMED_URI/,
234 "missing brackets"
236 Assert.throws(
237 () => {
238 url = url.mutate().setHost("[2001::1]:20").finalize();
240 /NS_ERROR_MALFORMED_URI/,
241 "url.host with port"
243 Assert.throws(
244 () => {
245 url = url.mutate().setHost("[2001::1").finalize();
247 /NS_ERROR_MALFORMED_URI/,
248 "missing last bracket"
250 Assert.throws(
251 () => {
252 url = url.mutate().setHost("2001::1]").finalize();
254 /NS_ERROR_MALFORMED_URI/,
255 "missing first bracket"
257 Assert.throws(
258 () => {
259 url = url.mutate().setHost("2001[::1]").finalize();
261 /NS_ERROR_MALFORMED_URI/,
262 "bad bracket position"
264 Assert.throws(
265 () => {
266 url = url.mutate().setHost("[]").finalize();
268 /NS_ERROR_MALFORMED_URI/,
269 "empty IPv6 address"
271 Assert.throws(
272 () => {
273 url = url.mutate().setHost("[hello]").finalize();
275 /NS_ERROR_MALFORMED_URI/,
276 "bad IPv6 address"
278 Assert.throws(
279 () => {
280 url = url.mutate().setHost("[192.168.1.1]").finalize();
282 /NS_ERROR_MALFORMED_URI/,
283 "bad IPv6 address"
285 Assert.throws(
286 () => {
287 url = url.mutate().setHostPort("2001::1").finalize();
289 /NS_ERROR_MALFORMED_URI/,
290 "missing brackets"
292 Assert.throws(
293 () => {
294 url = url.mutate().setHostPort("[2001::1]30").finalize();
296 /NS_ERROR_MALFORMED_URI/,
297 "missing : after IP"
299 Assert.throws(
300 () => {
301 url = url.mutate().setHostPort("[2001:1]").finalize();
303 /NS_ERROR_MALFORMED_URI/,
304 "bad IPv6 address"
306 Assert.throws(
307 () => {
308 url = url.mutate().setHostPort("[2001:1]10").finalize();
310 /NS_ERROR_MALFORMED_URI/,
311 "bad IPv6 address"
313 Assert.throws(
314 () => {
315 url = url.mutate().setHostPort("[2001:1]10:20").finalize();
317 /NS_ERROR_MALFORMED_URI/,
318 "bad IPv6 address"
320 Assert.throws(
321 () => {
322 url = url.mutate().setHostPort("[2001:1]:10:20").finalize();
324 /NS_ERROR_MALFORMED_URI/,
325 "bad IPv6 address"
327 Assert.throws(
328 () => {
329 url = url.mutate().setHostPort("[2001:1").finalize();
331 /NS_ERROR_MALFORMED_URI/,
332 "bad IPv6 address"
334 Assert.throws(
335 () => {
336 url = url.mutate().setHostPort("2001]:1").finalize();
338 /NS_ERROR_MALFORMED_URI/,
339 "bad IPv6 address"
341 Assert.throws(
342 () => {
343 url = url.mutate().setHostPort("2001:1]").finalize();
345 /NS_ERROR_MALFORMED_URI/,
346 "bad IPv6 address"
348 Assert.throws(
349 () => {
350 url = url.mutate().setHostPort("").finalize();
352 /NS_ERROR_UNEXPECTED/,
353 "Empty hostPort should fail"
356 // These checks used to fail, but now don't (see bug 1433958 comment 57)
357 url = url.mutate().setHostPort("[2001::1]:").finalize();
358 Assert.equal(url.spec, "http://[2001::1]/");
359 url = url.mutate().setHostPort("[2002::1]:bad").finalize();
360 Assert.equal(url.spec, "http://[2002::1]/");
362 run_next_test();
365 add_test(function test_clearedSpec() {
366 var url = stringToURL("http://example.com/path");
367 Assert.throws(
368 () => {
369 url = url.mutate().setSpec("http: example").finalize();
371 /NS_ERROR_MALFORMED_URI/,
372 "set bad spec"
374 Assert.throws(
375 () => {
376 url = url.mutate().setSpec("").finalize();
378 /NS_ERROR_MALFORMED_URI/,
379 "set empty spec"
381 Assert.equal(url.spec, "http://example.com/path");
382 url = url
383 .mutate()
384 .setHost("allizom.org")
385 .finalize()
386 .QueryInterface(Ci.nsIURL);
388 var ref = stringToURL("http://allizom.org/path");
389 symmetricEquality(true, url, ref);
390 run_next_test();
393 add_test(function test_escapeBrackets() {
394 // Query
395 var url = stringToURL("http://example.com/?a[x]=1");
396 Assert.equal(url.spec, "http://example.com/?a[x]=1");
398 url = stringToURL("http://example.com/?a%5Bx%5D=1");
399 Assert.equal(url.spec, "http://example.com/?a%5Bx%5D=1");
401 url = stringToURL("http://[2001::1]/?a[x]=1");
402 Assert.equal(url.spec, "http://[2001::1]/?a[x]=1");
404 url = stringToURL("http://[2001::1]/?a%5Bx%5D=1");
405 Assert.equal(url.spec, "http://[2001::1]/?a%5Bx%5D=1");
407 // Path
408 url = stringToURL("http://example.com/brackets[x]/test");
409 Assert.equal(url.spec, "http://example.com/brackets[x]/test");
411 url = stringToURL("http://example.com/a%5Bx%5D/test");
412 Assert.equal(url.spec, "http://example.com/a%5Bx%5D/test");
413 run_next_test();
416 add_test(function test_escapeQuote() {
417 var url = stringToURL("http://example.com/#'");
418 Assert.equal(url.spec, "http://example.com/#'");
419 Assert.equal(url.ref, "'");
420 url = url.mutate().setRef("test'test").finalize();
421 Assert.equal(url.spec, "http://example.com/#test'test");
422 Assert.equal(url.ref, "test'test");
423 run_next_test();
426 add_test(function test_apostropheEncoding() {
427 // For now, single quote is escaped everywhere _except_ the path.
428 // This policy is controlled by the bitmask in nsEscape.cpp::EscapeChars[]
429 var url = stringToURL("http://example.com/dir'/file'.ext'");
430 Assert.equal(url.spec, "http://example.com/dir'/file'.ext'");
431 run_next_test();
434 add_test(function test_accentEncoding() {
435 var url = stringToURL("http://example.com/?hello=`");
436 Assert.equal(url.spec, "http://example.com/?hello=`");
437 Assert.equal(url.query, "hello=`");
439 url = stringToURL("http://example.com/?hello=%2C");
440 Assert.equal(url.spec, "http://example.com/?hello=%2C");
441 Assert.equal(url.query, "hello=%2C");
442 run_next_test();
445 add_test(
446 { skip_if: () => AppConstants.MOZ_APP_NAME == "thunderbird" },
447 function test_percentDecoding() {
448 var url = stringToURL("http://%70%61%73%74%65%62%69%6E.com");
449 Assert.equal(url.spec, "http://pastebin.com/");
451 // Disallowed hostname characters are rejected even when percent encoded
452 Assert.throws(
453 () => {
454 url = stringToURL("http://example.com%0a%23.google.com/");
456 /NS_ERROR_MALFORMED_URI/,
457 "invalid characters are not allowed"
459 run_next_test();
463 add_test(function test_hugeStringThrows() {
464 let prefs = Services.prefs;
465 let maxLen = prefs.getIntPref("network.standard-url.max-length");
466 let url = stringToURL("http://test:test@example.com");
468 let hugeString = new Array(maxLen + 1).fill("a").join("");
469 let setters = [
470 { method: "setSpec", qi: Ci.nsIURIMutator },
471 { method: "setUsername", qi: Ci.nsIURIMutator },
472 { method: "setPassword", qi: Ci.nsIURIMutator },
473 { method: "setFilePath", qi: Ci.nsIURIMutator },
474 { method: "setHostPort", qi: Ci.nsIURIMutator },
475 { method: "setHost", qi: Ci.nsIURIMutator },
476 { method: "setUserPass", qi: Ci.nsIURIMutator },
477 { method: "setPathQueryRef", qi: Ci.nsIURIMutator },
478 { method: "setQuery", qi: Ci.nsIURIMutator },
479 { method: "setRef", qi: Ci.nsIURIMutator },
480 { method: "setScheme", qi: Ci.nsIURIMutator },
481 { method: "setFileName", qi: Ci.nsIURLMutator },
482 { method: "setFileExtension", qi: Ci.nsIURLMutator },
483 { method: "setFileBaseName", qi: Ci.nsIURLMutator },
486 for (let prop of setters) {
487 Assert.throws(
488 () =>
489 (url = url
490 .mutate()
491 .QueryInterface(prop.qi)
492 [prop.method](hugeString)
493 .finalize()),
494 /NS_ERROR_MALFORMED_URI/,
495 `Passing a huge string to "${prop.method}" should throw`
499 run_next_test();
502 add_test(function test_verticalBar() {
503 var url = Services.io.newURI("file:///w|m");
504 Assert.equal(url.spec, "file:///w|m");
506 url = Services.io.newURI("file:///w||m");
507 Assert.equal(url.spec, "file:///w||m");
509 url = Services.io.newURI("file:///w|/m");
510 Assert.equal(url.spec, "file:///w:/m");
512 url = Services.io.newURI("file:C|/m/");
513 Assert.equal(url.spec, "file:///C:/m/");
515 url = Services.io.newURI("file:C||/m/");
516 Assert.equal(url.spec, "file:///C||/m/");
518 run_next_test();
521 add_test(function test_pathPercentEncodedDot() {
522 var url = stringToURL("http://example.com/hello/%2e%2E/%2e");
523 Assert.equal(url.spec, "http://example.com/");
524 Assert.equal(url.directory, "/");
525 Assert.equal(url.fileName, "");
526 Assert.equal(url.fileBaseName, "");
527 Assert.equal(url.fileExtension, "");
529 url = stringToURL("http://example.com/hello/%2e%2E/%");
530 Assert.equal(url.spec, "http://example.com/%");
531 Assert.equal(url.directory, "/");
532 Assert.equal(url.fileName, "%");
533 Assert.equal(url.fileBaseName, "%");
534 Assert.equal(url.fileExtension, "");
536 url = stringToURL("http://example.com/hello/%2e%2E/%2");
537 Assert.equal(url.spec, "http://example.com/%2");
538 Assert.equal(url.directory, "/");
539 Assert.equal(url.fileName, "%2");
540 Assert.equal(url.fileBaseName, "%2");
541 Assert.equal(url.fileExtension, "");
543 url = stringToURL("http://example.com/hello/%2e%2E/%#");
544 Assert.equal(url.spec, "http://example.com/%#");
545 Assert.equal(url.directory, "/");
546 Assert.equal(url.fileName, "%");
547 Assert.equal(url.fileBaseName, "%");
548 Assert.equal(url.fileExtension, "");
550 url = stringToURL("http://example.com/hello/%2e%2E/%2?");
551 Assert.equal(url.spec, "http://example.com/%2?");
552 Assert.equal(url.directory, "/");
553 Assert.equal(url.fileName, "%2");
554 Assert.equal(url.fileBaseName, "%2");
555 Assert.equal(url.fileExtension, "");
557 url = stringToURL("http://example.com/hello/%2e/");
558 Assert.equal(url.spec, "http://example.com/hello/");
559 Assert.equal(url.directory, "/hello/");
560 Assert.equal(url.fileName, "");
561 Assert.equal(url.fileBaseName, "");
562 Assert.equal(url.fileExtension, "");
564 url = stringToURL("http://example.com/%2e");
565 Assert.equal(url.spec, "http://example.com/");
566 Assert.equal(url.directory, "/");
567 Assert.equal(url.fileName, "");
568 Assert.equal(url.fileBaseName, "");
569 Assert.equal(url.fileExtension, "");
571 url = stringToURL("http://example.com/.%2e");
572 Assert.equal(url.spec, "http://example.com/");
573 Assert.equal(url.directory, "/");
574 Assert.equal(url.fileName, "");
575 Assert.equal(url.fileBaseName, "");
576 Assert.equal(url.fileExtension, "");
578 url = stringToURL("http://example.com/%2e.");
579 Assert.equal(url.spec, "http://example.com/");
580 Assert.equal(url.directory, "/");
581 Assert.equal(url.fileName, "");
582 Assert.equal(url.fileBaseName, "");
583 Assert.equal(url.fileExtension, "");
585 url = stringToURL("http://example.com/%2e%2e");
586 Assert.equal(url.spec, "http://example.com/");
587 Assert.equal(url.directory, "/");
588 Assert.equal(url.fileName, "");
589 Assert.equal(url.fileBaseName, "");
590 Assert.equal(url.fileExtension, "");
592 url = stringToURL("http://example.com/%2e%2e%2e");
593 Assert.equal(url.spec, "http://example.com/%2e%2e%2e");
594 Assert.equal(url.directory, "/");
595 Assert.equal(url.fileName, "%2e%2e%2e");
596 Assert.equal(url.fileBaseName, "%2e%2e%2e");
597 Assert.equal(url.fileExtension, "");
599 url = stringToURL("http://example.com/%2e%2e%2e%2e");
600 Assert.equal(url.spec, "http://example.com/%2e%2e%2e%2e");
601 Assert.equal(url.directory, "/");
602 Assert.equal(url.fileName, "%2e%2e%2e%2e");
603 Assert.equal(url.fileBaseName, "%2e%2e%2e%2e");
604 Assert.equal(url.fileExtension, "");
606 url = stringToURL("http://example.com/hello/%2e%2");
607 Assert.equal(url.spec, "http://example.com/hello/%2e%2");
608 Assert.equal(url.directory, "/hello/");
609 Assert.equal(url.fileName, "%2e%2");
610 Assert.equal(url.fileBaseName, "%2e%2");
611 Assert.equal(url.fileExtension, "");
613 url = stringToURL("http://example.com/hello/%2e./%2e%2e/.%2e/%2e.bar");
614 Assert.equal(url.spec, "http://example.com/%2e.bar");
615 Assert.equal(url.directory, "/");
616 Assert.equal(url.fileName, "%2e.bar");
617 Assert.equal(url.fileBaseName, "%2e");
618 Assert.equal(url.fileExtension, "bar");
620 url = stringToURL("http://example.com/%2eX/X%2e/%2eX");
621 Assert.equal(url.spec, "http://example.com/%2eX/X%2e/%2eX");
622 Assert.equal(url.directory, "/%2eX/X%2e/");
623 Assert.equal(url.fileName, "%2eX");
624 Assert.equal(url.fileBaseName, "%2eX");
625 Assert.equal(url.fileExtension, "");
627 run_next_test();
630 add_test(function test_filterWhitespace() {
631 let url = stringToURL(
632 " \r\n\th\nt\rt\tp://ex\r\n\tample.com/path\r\n\t/\r\n\tto the/fil\r\n\te.e\r\n\txt?que\r\n\try#ha\r\n\tsh \r\n\t "
634 Assert.equal(
635 url.spec,
636 "http://example.com/path/to%20the/file.ext?query#hash"
639 // These setters should filter \r\n\t.
640 url = stringToURL("http://test.com/path?query#hash");
641 url = url.mutate().setFilePath("pa\r\n\tth").finalize();
642 Assert.equal(url.spec, "http://test.com/path?query#hash");
643 url = url.mutate().setQuery("que\r\n\try").finalize();
644 Assert.equal(url.spec, "http://test.com/path?query#hash");
645 url = url.mutate().setRef("ha\r\n\tsh").finalize();
646 Assert.equal(url.spec, "http://test.com/path?query#hash");
647 url = url
648 .mutate()
649 .QueryInterface(Ci.nsIURLMutator)
650 .setFileName("fi\r\n\tle.name")
651 .finalize();
652 Assert.equal(url.spec, "http://test.com/fi%0D%0A%09le.name?query#hash");
654 run_next_test();
657 add_test(function test_backslashReplacement() {
658 var url = stringToURL(
659 "http:\\\\test.com\\path/to\\file?query\\backslash#hash\\"
661 Assert.equal(
662 url.spec,
663 "http://test.com/path/to/file?query\\backslash#hash\\"
666 url = stringToURL("http:\\\\test.com\\example.org/path\\to/file");
667 Assert.equal(url.spec, "http://test.com/example.org/path/to/file");
668 Assert.equal(url.host, "test.com");
669 Assert.equal(url.pathQueryRef, "/example.org/path/to/file");
671 run_next_test();
674 add_test(function test_authority_host() {
675 Assert.throws(
676 () => {
677 stringToURL("http:");
679 /NS_ERROR_MALFORMED_URI/,
680 "TYPE_AUTHORITY should have host"
682 Assert.throws(
683 () => {
684 stringToURL("http:///");
686 /NS_ERROR_MALFORMED_URI/,
687 "TYPE_AUTHORITY should have host"
690 run_next_test();
693 add_test(function test_trim_C0_and_space() {
694 var url = stringToURL(
695 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://example.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f "
697 Assert.equal(url.spec, "http://example.com/");
698 url = url
699 .mutate()
700 .setSpec(
701 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://test.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f "
703 .finalize();
704 Assert.equal(url.spec, "http://test.com/");
705 Assert.throws(
706 () => {
707 url = url
708 .mutate()
709 .setSpec(
710 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 "
712 .finalize();
714 /NS_ERROR_MALFORMED_URI/,
715 "set empty spec"
717 run_next_test();
720 // This tests that C0-and-space characters in the path, query and ref are
721 // percent encoded.
722 add_test(function test_encode_C0_and_space() {
723 function toHex(d) {
724 var hex = d.toString(16);
725 if (hex.length == 1) {
726 hex = "0" + hex;
728 return hex.toUpperCase();
731 for (var i = 0x0; i <= 0x20; i++) {
732 // These characters get filtered - they are not encoded.
733 if (
734 String.fromCharCode(i) == "\r" ||
735 String.fromCharCode(i) == "\n" ||
736 String.fromCharCode(i) == "\t"
738 continue;
740 let url = stringToURL(
741 "http://example.com/pa" +
742 String.fromCharCode(i) +
743 "th?qu" +
744 String.fromCharCode(i) +
745 "ery#ha" +
746 String.fromCharCode(i) +
747 "sh"
749 Assert.equal(
750 url.spec,
751 "http://example.com/pa%" +
752 toHex(i) +
753 "th?qu%" +
754 toHex(i) +
755 "ery#ha%" +
756 toHex(i) +
757 "sh"
761 // Additionally, we need to check the setters.
762 let url = stringToURL("http://example.com/path?query#hash");
763 url = url.mutate().setFilePath("pa\0th").finalize();
764 Assert.equal(url.spec, "http://example.com/pa%00th?query#hash");
765 url = url.mutate().setQuery("qu\0ery").finalize();
766 Assert.equal(url.spec, "http://example.com/pa%00th?qu%00ery#hash");
767 url = url.mutate().setRef("ha\0sh").finalize();
768 Assert.equal(url.spec, "http://example.com/pa%00th?qu%00ery#ha%00sh");
769 url = url
770 .mutate()
771 .QueryInterface(Ci.nsIURLMutator)
772 .setFileName("fi\0le.name")
773 .finalize();
774 Assert.equal(url.spec, "http://example.com/fi%00le.name?qu%00ery#ha%00sh");
776 run_next_test();
779 add_test(function test_ipv4Normalize() {
780 var localIPv4s = [
781 "http://127.0.0.1",
782 "http://127.0.1",
783 "http://127.1",
784 "http://2130706433",
785 "http://0177.00.00.01",
786 "http://0177.00.01",
787 "http://0177.01",
788 "http://00000000000000000000000000177.0000000.0000000.0001",
789 "http://000000177.0000001",
790 "http://017700000001",
791 "http://0x7f.0x00.0x00.0x01",
792 "http://0x7f.0x01",
793 "http://0x7f000001",
794 "http://0x007f.0x0000.0x0000.0x0001",
795 "http://000177.0.00000.0x0001",
796 "http://127.0.0.1.",
797 ].map(stringToURL);
799 let url;
800 for (url of localIPv4s) {
801 Assert.equal(url.spec, "http://127.0.0.1/");
804 // These should treated as a domain instead of an IPv4.
805 var nonIPv4s = [
806 "http://2+3/",
807 "http://0.0.0.-1/",
808 "http://1.2.3.4../",
809 "resource://123/",
810 "resource://4294967296/",
812 var spec;
813 for (spec of nonIPv4s) {
814 url = stringToURL(spec);
815 Assert.equal(url.spec, spec);
818 url = stringToURL("resource://path/to/resource/");
819 url = url.mutate().setHost("123").finalize();
820 Assert.equal(url.host, "123");
822 run_next_test();
825 add_test(function test_invalidHostChars() {
826 var url = stringToURL("http://example.org/");
827 for (let i = 0; i <= 0x20; i++) {
828 // These characters get filtered.
829 if (
830 String.fromCharCode(i) == "\r" ||
831 String.fromCharCode(i) == "\n" ||
832 String.fromCharCode(i) == "\t"
834 continue;
836 Assert.throws(
837 () => {
838 url = url
839 .mutate()
840 .setHost("a" + String.fromCharCode(i) + "b")
841 .finalize();
843 /NS_ERROR_MALFORMED_URI/,
844 "Trying to set hostname containing char code: " + i
847 for (let c of '@[]*<>|:"') {
848 Assert.throws(
849 () => {
850 url = url
851 .mutate()
852 .setHost("a" + c)
853 .finalize();
855 /NS_ERROR_MALFORMED_URI/,
856 "Trying to set hostname containing char: " + c
860 // It also can't contain /, \, #, ?, but we treat these characters as
861 // hostname separators, so there is no way to set them and fail.
862 run_next_test();
865 add_test(function test_normalize_ipv6() {
866 var url = stringToURL("http://example.com");
867 url = url.mutate().setHost("[::192.9.5.5]").finalize();
868 Assert.equal(url.spec, "http://[::c009:505]/");
870 run_next_test();
873 add_test(function test_emptyPassword() {
874 var url = stringToURL("http://a:@example.com");
875 Assert.equal(url.spec, "http://a@example.com/");
876 url = url.mutate().setPassword("pp").finalize();
877 Assert.equal(url.spec, "http://a:pp@example.com/");
878 url = url.mutate().setPassword("").finalize();
879 Assert.equal(url.spec, "http://a@example.com/");
880 url = url.mutate().setUserPass("xxx:").finalize();
881 Assert.equal(url.spec, "http://xxx@example.com/");
882 url = url.mutate().setPassword("zzzz").finalize();
883 Assert.equal(url.spec, "http://xxx:zzzz@example.com/");
884 url = url.mutate().setUserPass("xxxxx:yyyyyy").finalize();
885 Assert.equal(url.spec, "http://xxxxx:yyyyyy@example.com/");
886 url = url.mutate().setUserPass("z:").finalize();
887 Assert.equal(url.spec, "http://z@example.com/");
888 url = url.mutate().setPassword("ppppppppppp").finalize();
889 Assert.equal(url.spec, "http://z:ppppppppppp@example.com/");
891 url = stringToURL("http://example.com");
892 url = url.mutate().setPassword("").finalize(); // Still empty. Should work.
893 Assert.equal(url.spec, "http://example.com/");
895 run_next_test();
898 add_test(function test_emptyUser() {
899 let url = stringToURL("http://:a@example.com/path/to/something?query#hash");
900 Assert.equal(url.spec, "http://:a@example.com/path/to/something?query#hash");
901 url = stringToURL("http://:@example.com/path/to/something?query#hash");
902 Assert.equal(url.spec, "http://example.com/path/to/something?query#hash");
904 const kurl = stringToURL(
905 "http://user:pass@example.com:8888/path/to/something?query#hash"
907 url = kurl.mutate().setUsername("").finalize();
908 Assert.equal(
909 url.spec,
910 "http://:pass@example.com:8888/path/to/something?query#hash"
912 Assert.equal(url.host, "example.com");
913 Assert.equal(url.hostPort, "example.com:8888");
914 Assert.equal(url.filePath, "/path/to/something");
915 Assert.equal(url.query, "query");
916 Assert.equal(url.ref, "hash");
917 url = kurl.mutate().setUserPass(":pass1").finalize();
918 Assert.equal(
919 url.spec,
920 "http://:pass1@example.com:8888/path/to/something?query#hash"
922 Assert.equal(url.host, "example.com");
923 Assert.equal(url.hostPort, "example.com:8888");
924 Assert.equal(url.filePath, "/path/to/something");
925 Assert.equal(url.query, "query");
926 Assert.equal(url.ref, "hash");
927 url = url.mutate().setUsername("user2").finalize();
928 Assert.equal(
929 url.spec,
930 "http://user2:pass1@example.com:8888/path/to/something?query#hash"
932 Assert.equal(url.host, "example.com");
933 url = url.mutate().setUserPass(":pass234").finalize();
934 Assert.equal(
935 url.spec,
936 "http://:pass234@example.com:8888/path/to/something?query#hash"
938 Assert.equal(url.host, "example.com");
939 url = url.mutate().setUserPass("").finalize();
940 Assert.equal(
941 url.spec,
942 "http://example.com:8888/path/to/something?query#hash"
944 Assert.equal(url.host, "example.com");
945 url = url.mutate().setPassword("pa").finalize();
946 Assert.equal(
947 url.spec,
948 "http://:pa@example.com:8888/path/to/something?query#hash"
950 Assert.equal(url.host, "example.com");
951 url = url.mutate().setUserPass("user:pass").finalize();
952 symmetricEquality(true, url.QueryInterface(Ci.nsIURL), kurl);
954 url = stringToURL("http://example.com:8888/path/to/something?query#hash");
955 url = url.mutate().setPassword("pass").finalize();
956 Assert.equal(
957 url.spec,
958 "http://:pass@example.com:8888/path/to/something?query#hash"
960 url = url.mutate().setUsername("").finalize();
961 Assert.equal(
962 url.spec,
963 "http://:pass@example.com:8888/path/to/something?query#hash"
966 url = stringToURL("http://example.com:8888");
967 url = url.mutate().setUsername("user").finalize();
968 url = url.mutate().setUsername("").finalize();
969 Assert.equal(url.spec, "http://example.com:8888/");
971 url = stringToURL("http://:pass@example.com");
972 Assert.equal(url.spec, "http://:pass@example.com/");
973 url = url.mutate().setPassword("").finalize();
974 Assert.equal(url.spec, "http://example.com/");
975 url = url.mutate().setUserPass("user:pass").finalize();
976 Assert.equal(url.spec, "http://user:pass@example.com/");
977 Assert.equal(url.host, "example.com");
978 url = url.mutate().setUserPass("u:p").finalize();
979 Assert.equal(url.spec, "http://u:p@example.com/");
980 Assert.equal(url.host, "example.com");
981 url = url.mutate().setUserPass("u1:p23").finalize();
982 Assert.equal(url.spec, "http://u1:p23@example.com/");
983 Assert.equal(url.host, "example.com");
984 url = url.mutate().setUsername("u").finalize();
985 Assert.equal(url.spec, "http://u:p23@example.com/");
986 Assert.equal(url.host, "example.com");
987 url = url.mutate().setPassword("p").finalize();
988 Assert.equal(url.spec, "http://u:p@example.com/");
989 Assert.equal(url.host, "example.com");
991 url = url.mutate().setUserPass("u2:p2").finalize();
992 Assert.equal(url.spec, "http://u2:p2@example.com/");
993 Assert.equal(url.host, "example.com");
994 url = url.mutate().setUserPass("u23:p23").finalize();
995 Assert.equal(url.spec, "http://u23:p23@example.com/");
996 Assert.equal(url.host, "example.com");
998 run_next_test();
1001 registerCleanupFunction(function () {
1002 gPrefs.clearUserPref("network.standard-url.punycode-host");
1005 add_test(function test_idna_host() {
1006 // See bug 945240 - this test makes sure that URLs return a punycode hostname
1007 let url = stringToURL(
1008 "http://user:password@ält.example.org:8080/path?query#etc"
1010 equal(url.host, "xn--lt-uia.example.org");
1011 equal(url.hostPort, "xn--lt-uia.example.org:8080");
1012 equal(url.prePath, "http://user:password@xn--lt-uia.example.org:8080");
1013 equal(
1014 url.spec,
1015 "http://user:password@xn--lt-uia.example.org:8080/path?query#etc"
1017 equal(
1018 url.specIgnoringRef,
1019 "http://user:password@xn--lt-uia.example.org:8080/path?query"
1021 equal(
1023 .QueryInterface(Ci.nsISensitiveInfoHiddenURI)
1024 .getSensitiveInfoHiddenSpec(),
1025 "http://user:****@xn--lt-uia.example.org:8080/path?query#etc"
1028 equal(url.displayHost, "ält.example.org");
1029 equal(url.displayHostPort, "ält.example.org:8080");
1030 equal(
1031 url.displaySpec,
1032 "http://user:password@ält.example.org:8080/path?query#etc"
1035 equal(url.asciiHost, "xn--lt-uia.example.org");
1036 equal(url.asciiHostPort, "xn--lt-uia.example.org:8080");
1037 equal(
1038 url.asciiSpec,
1039 "http://user:password@xn--lt-uia.example.org:8080/path?query#etc"
1042 url = url.mutate().setRef("").finalize(); // SetRef calls InvalidateCache()
1043 equal(
1044 url.spec,
1045 "http://user:password@xn--lt-uia.example.org:8080/path?query"
1047 equal(
1048 url.displaySpec,
1049 "http://user:password@ält.example.org:8080/path?query"
1051 equal(
1052 url.asciiSpec,
1053 "http://user:password@xn--lt-uia.example.org:8080/path?query"
1056 url = stringToURL("http://user:password@www.ält.com:8080/path?query#etc");
1057 url = url.mutate().setRef("").finalize();
1058 equal(url.spec, "http://user:password@www.xn--lt-uia.com:8080/path?query");
1060 run_next_test();
1063 add_test(
1064 { skip_if: () => AppConstants.MOZ_APP_NAME == "thunderbird" },
1065 function test_bug1517025() {
1066 Assert.throws(
1067 () => {
1068 stringToURL("https://b%9a/");
1070 /NS_ERROR_MALFORMED_URI/,
1071 "bad URI"
1074 Assert.throws(
1075 () => {
1076 stringToURL("https://b%9ª/");
1078 /NS_ERROR_MALFORMED_URI/,
1079 "bad URI"
1082 let base = stringToURL(
1083 "https://bug1517025.bmoattachments.org/attachment.cgi?id=9033787"
1085 Assert.throws(
1086 () => {
1087 Services.io.newURI("/\\b%9ª", "windows-1252", base);
1089 /NS_ERROR_MALFORMED_URI/,
1090 "bad URI"
1093 run_next_test();
1097 add_task(async function test_emptyHostWithURLType() {
1098 let makeURL = (str, type) => {
1099 return Cc["@mozilla.org/network/standard-url-mutator;1"]
1100 .createInstance(Ci.nsIStandardURLMutator)
1101 .init(type, 80, str, "UTF-8", null)
1102 .finalize()
1103 .QueryInterface(Ci.nsIURL);
1106 let url = makeURL("http://foo.com/bar/", Ci.nsIStandardURL.URLTYPE_AUTHORITY);
1107 Assert.throws(
1108 () => url.mutate().setHost("").finalize().spec,
1109 /NS_ERROR_UNEXPECTED/,
1110 "Empty host is not allowed for URLTYPE_AUTHORITY"
1113 url = makeURL("http://user@foo.com/bar/", Ci.nsIStandardURL.URLTYPE_STANDARD);
1114 Assert.throws(
1115 () => url.mutate().setHost("").finalize().spec,
1116 /NS_ERROR_MALFORMED_URI/,
1117 "Setting an empty host should throw if there is a username present"
1120 url = makeURL(
1121 "http://:password@foo.com/bar/",
1122 Ci.nsIStandardURL.URLTYPE_STANDARD
1124 Assert.throws(
1125 () => url.mutate().setHost("").finalize().spec,
1126 /NS_ERROR_MALFORMED_URI/,
1127 "Setting an empty host should throw if there is a password present"
1130 url = makeURL("http://foo.com:123/bar/", Ci.nsIStandardURL.URLTYPE_STANDARD);
1131 Assert.throws(
1132 () => url.mutate().setHost("").finalize().spec,
1133 /NS_ERROR_MALFORMED_URI/,
1134 "Setting an empty host should throw if there is a port present"
1137 url = makeURL("http://foo.com/bar/", Ci.nsIStandardURL.URLTYPE_STANDARD);
1138 Assert.equal(url.mutate().setHost("").finalize().spec, "http:///bar/");
1140 url = makeURL("http://foo.com/bar/", Ci.nsIStandardURL.URLTYPE_NO_AUTHORITY);
1141 equal(
1142 url.spec,
1143 "http:///bar/",
1144 "Host is removed when parsing URLTYPE_NO_AUTHORITY"
1146 equal(
1147 url.mutate().setHost("").finalize().spec,
1148 "http:///bar/",
1149 "Setting an empty host does nothing for URLTYPE_NO_AUTHORITY"
1151 Assert.throws(
1152 () => url.mutate().setHost("something").finalize().spec,
1153 /NS_ERROR_UNEXPECTED/,
1154 "Setting a non-empty host is not allowed for URLTYPE_NO_AUTHORITY"
1156 equal(
1157 url.mutate().setHost("#j").finalize().spec,
1158 "http:///bar/",
1159 "Setting a pseudo-empty host does nothing for URLTYPE_NO_AUTHORITY"
1162 url = makeURL(
1163 "http://example.org:123/foo?bar#baz",
1164 Ci.nsIStandardURL.URLTYPE_AUTHORITY
1166 Assert.throws(
1167 () => url.mutate().setHost("#j").finalize().spec,
1168 /NS_ERROR_UNEXPECTED/,
1169 "A pseudo-empty host is not allowed for URLTYPE_AUTHORITY"
1173 add_task(async function test_fuzz() {
1174 let makeURL = str => {
1175 return (
1176 Cc["@mozilla.org/network/standard-url-mutator;1"]
1177 .createInstance(Ci.nsIStandardURLMutator)
1178 .QueryInterface(Ci.nsIURIMutator)
1179 // .init(type, 80, str, "UTF-8", null)
1180 .setSpec(str)
1181 .finalize()
1182 .QueryInterface(Ci.nsIURL)
1186 Assert.throws(() => {
1187 let url = makeURL("/");
1188 url.mutate().setHost("(").finalize();
1189 }, /NS_ERROR_MALFORMED_URI/);
1192 add_task(async function test_bug1648493() {
1193 let url = stringToURL("https://example.com/");
1194 url = url.mutate().setScheme("file").finalize();
1195 url = url.mutate().setScheme("resource").finalize();
1196 url = url.mutate().setPassword("ê").finalize();
1197 url = url.mutate().setUsername("ç").finalize();
1198 url = url.mutate().setScheme("t").finalize();
1199 equal(url.spec, "t://%C3%83%C2%A7:%C3%83%C2%AA@example.com/");
1200 equal(url.username, "%C3%83%C2%A7");
1203 add_task(async function test_bug1873976() {
1204 let url = Services.io.newURI("file:.");
1205 equal(url.spec, "file:///");
1208 add_task(async function test_bug1890346() {
1209 let url = Services.io.newURI("file:..?/..");
1210 equal(url.spec, "file:///?/..");
1213 add_task(async function test_bug1914141() {
1214 equal(Services.io.isValidHostname("example.com"), true);
1215 equal(Services.io.isValidHostname("example.0"), false);
1217 equal(Services.io.isValidHostname("192.168.0.1"), true);
1218 equal(Services.io.isValidHostname("192.168.0"), true);
1219 equal(Services.io.isValidHostname("1.192.168.0.1"), false);
1220 equal(Services.io.isValidHostname("invalid.192.168.0.1"), false);
1222 equal(Services.io.isValidHostname("::1"), true);
1223 equal(Services.io.isValidHostname("abcd::zz::00"), false);
1224 equal(Services.io.isValidHostname("zzzz::1.2.3.4"), false);
1226 equal(Services.io.isValidHostname("::1.2.3.4"), true);