1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 // Run by: cd objdir; make -C netwerk/test/ xpcshell-tests
9 // or: cd objdir; make SOLO_FILE="test_URIs.js" -C netwerk/test/ check-one
11 // See also test_URIs2.js.
13 // Relevant RFCs: 1738, 1808, 2396, 3986 (newer than the code)
14 // http://greenbytes.de/tech/webdav/rfc3986.html#rfc.section.5.4
15 // http://greenbytes.de/tech/tc/uris/
24 pathQueryRef: "blank",
34 pathQueryRef: "foobar",
41 spec: "chrome://foobar/somedir/somefile.xml",
43 prePath: "chrome://foobar",
44 pathQueryRef: "/somedir/somefile.xml",
51 spec: "data:text/html;charset=utf-8,<html></html>",
54 pathQueryRef: "text/html;charset=utf-8,<html></html>",
60 spec: "data:text/html;charset=utf-8,<html>\r\n\t</html>",
63 pathQueryRef: "text/html;charset=utf-8,<html></html>",
69 spec: "data:text/plain,hello%20world",
72 pathQueryRef: "text/plain,hello%20world",
78 spec: "data:text/plain,hello world",
81 pathQueryRef: "text/plain,hello world",
87 spec: "file:///dir/afile",
90 pathQueryRef: "text/plain,2",
92 relativeURI: "data:te\nxt/plain,2",
115 spec: "file:///myFile.html",
118 pathQueryRef: "/myFile.html",
124 spec: "file:///dir/afile",
127 pathQueryRef: "/dir/data/text/plain,2",
129 relativeURI: "data/text/plain,2",
134 spec: "file:///dir/dir2/",
137 pathQueryRef: "/dir/dir2/data/text/plain,2",
139 relativeURI: "data/text/plain,2",
144 spec: "ftp://ftp.mozilla.org/pub/mozilla.org/README",
146 prePath: "ftp://ftp.mozilla.org",
147 pathQueryRef: "/pub/mozilla.org/README",
153 spec: "ftp://foo:bar@ftp.mozilla.org:100/pub/mozilla.org/README",
155 prePath: "ftp://foo:bar@ftp.mozilla.org:100",
159 pathQueryRef: "/pub/mozilla.org/README",
165 spec: "ftp://foo:@ftp.mozilla.org:100/pub/mozilla.org/README",
167 prePath: "ftp://foo@ftp.mozilla.org:100",
171 pathQueryRef: "/pub/mozilla.org/README",
178 spec: "gopher://mozilla.org/",
181 pathQueryRef: "//mozilla.org/",
187 spec: "http://www.example.com/",
189 prePath: "http://www.example.com",
196 spec: "http://www.exa\nmple.com/",
198 prePath: "http://www.example.com",
205 spec: "http://10.32.4.239/",
207 prePath: "http://10.32.4.239",
215 spec: "http://[::192.9.5.5]/ipng",
217 prePath: "http://[::c009:505]",
219 pathQueryRef: "/ipng",
225 spec: "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8888/index.html",
227 prePath: "http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:8888",
228 host: "fedc:ba98:7654:3210:fedc:ba98:7654:3210",
230 pathQueryRef: "/index.html",
236 spec: "http://bar:foo@www.mozilla.org:8080/pub/mozilla.org/README.html",
238 prePath: "http://bar:foo@www.mozilla.org:8080",
242 host: "www.mozilla.org",
243 pathQueryRef: "/pub/mozilla.org/README.html",
249 spec: "jar:resource://!/",
252 pathQueryRef: "resource:///!/",
258 spec: "jar:resource://gre/chrome.toolkit.jar!/",
261 pathQueryRef: "resource://gre/chrome.toolkit.jar!/",
267 spec: "mailto:webmaster@mozilla.com",
270 pathQueryRef: "webmaster@mozilla.com",
276 spec: "javascript:new Date()",
277 scheme: "javascript",
278 prePath: "javascript:",
279 pathQueryRef: "new Date()",
288 pathQueryRef: "123456",
295 spec: "place:sort=8&maxResults=10",
298 pathQueryRef: "sort=8&maxResults=10",
304 spec: "resource://gre/",
306 prePath: "resource://gre",
313 spec: "resource://gre/components/",
315 prePath: "resource://gre",
316 pathQueryRef: "/components/",
322 // Adding more? Consider adding to test_URIs2.js instead, so that neither
323 // test runs for *too* long, risking timeouts on slow platforms.
326 var gHashSuffixes = ["#", "#myRef", "#myRef?a=b", "#myRef#", "#myRef#x:yz"];
328 // TEST HELPER FUNCTIONS
329 // ---------------------
330 function do_info(text, stack) {
332 stack = Components.stack.caller;
349 // Checks that the URIs satisfy equals(), in both possible orderings.
350 // Also checks URI.equalsExceptRef(), because equal URIs should also be equal
351 // when we ignore the ref.
353 // The third argument is optional. If the client passes a third argument
354 // (e.g. todo_check_true), we'll use that in lieu of ok.
355 function do_check_uri_eq(aURI1, aURI2, aCheckTrueFunc = ok) {
356 do_info("(uri equals check: '" + aURI1.spec + "' == '" + aURI2.spec + "')");
357 aCheckTrueFunc(aURI1.equals(aURI2));
358 do_info("(uri equals check: '" + aURI2.spec + "' == '" + aURI1.spec + "')");
359 aCheckTrueFunc(aURI2.equals(aURI1));
361 // (Only take the extra step of testing 'equalsExceptRef' when we expect the
362 // URIs to really be equal. In 'todo' cases, the URIs may or may not be
363 // equal when refs are ignored - there's no way of knowing in general.)
364 if (aCheckTrueFunc == ok) {
365 do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc);
369 // Checks that the URIs satisfy equalsExceptRef(), in both possible orderings.
371 // The third argument is optional. If the client passes a third argument
372 // (e.g. todo_check_true), we'll use that in lieu of ok.
373 function do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc = ok) {
375 "(uri equalsExceptRef check: '" + aURI1.spec + "' == '" + aURI2.spec + "')"
377 aCheckTrueFunc(aURI1.equalsExceptRef(aURI2));
379 "(uri equalsExceptRef check: '" + aURI2.spec + "' == '" + aURI1.spec + "')"
381 aCheckTrueFunc(aURI2.equalsExceptRef(aURI1));
384 // Checks that the given property on aURI matches the corresponding property
385 // in the test bundle (or matches some function of that corresponding property,
386 // if aTestFunctor is passed in).
387 function do_check_property(aTest, aURI, aPropertyName, aTestFunctor) {
388 if (aTest[aPropertyName]) {
389 var expectedVal = aTestFunctor
390 ? aTestFunctor(aTest[aPropertyName])
391 : aTest[aPropertyName];
397 (aTestFunctor ? "modified '" : "'") +
403 Assert.equal(aURI[aPropertyName], expectedVal);
407 // Test that a given URI parses correctly into its various components.
408 function do_test_uri_basic(aTest) {
415 (aTest.relativeURI === undefined ? "(none)" : aTest.relativeURI)
419 URI = NetUtil.newURI(aTest.spec);
421 do_info("Caught error on parse of" + aTest.spec + " Error: " + e.result);
423 Assert.equal(e.result, aTest.result);
429 if (aTest.relativeURI) {
433 relURI = Services.io.newURI(aTest.relativeURI, null, URI);
436 "Caught error on Relative parse of " +
443 if (aTest.relativeFail) {
444 Assert.equal(e.result, aTest.relativeFail);
450 "relURI.pathQueryRef = " +
451 relURI.pathQueryRef +
456 do_info("URI.pathQueryRef now = " + URI.pathQueryRef);
460 do_info("testing " + aTest.spec + " equals a clone of itself");
461 do_check_uri_eq(URI, URI.mutate().finalize());
462 do_check_uri_eqExceptRef(URI, URI.mutate().setRef("").finalize());
463 do_info("testing " + aTest.spec + " instanceof nsIURL");
464 Assert.equal(URI instanceof Ci.nsIURL, aTest.nsIURL);
465 do_info("testing " + aTest.spec + " instanceof nsINestedURI");
466 Assert.equal(URI instanceof Ci.nsINestedURI, aTest.nsINestedURI);
471 " throws or returns false " +
474 // XXXdholbert At some point it'd probably be worth making this behavior
475 // (throwing vs. returning false) consistent across URI implementations.
479 isEqualToNull = URI.equals(null);
483 Assert.ok(threw || !isEqualToNull);
485 // Check the various components
486 do_check_property(aTest, URI, "scheme");
487 do_check_property(aTest, URI, "prePath");
488 do_check_property(aTest, URI, "pathQueryRef");
489 do_check_property(aTest, URI, "query");
490 do_check_property(aTest, URI, "ref");
491 do_check_property(aTest, URI, "port");
492 do_check_property(aTest, URI, "username");
493 do_check_property(aTest, URI, "password");
494 do_check_property(aTest, URI, "host");
495 do_check_property(aTest, URI, "specIgnoringRef");
496 if ("hasRef" in aTest) {
497 do_info("testing hasref: " + aTest.hasRef + " vs " + URI.hasRef);
498 Assert.equal(aTest.hasRef, URI.hasRef);
502 // Test that a given URI parses correctly when we add a given ref to the end
503 function do_test_uri_with_hash_suffix(aTest, aSuffix) {
504 do_info("making sure caller is using suffix that starts with '#'");
505 Assert.equal(aSuffix[0], "#");
507 var origURI = NetUtil.newURI(aTest.spec);
510 if (aTest.relativeURI) {
512 origURI = Services.io.newURI(aTest.relativeURI, null, origURI);
515 "Caught error on Relative parse of " +
525 testURI = Services.io.newURI(aSuffix, null, origURI);
528 "Caught error adding suffix to " +
540 testURI = NetUtil.newURI(aTest.spec + aSuffix);
549 "equals a clone of itself"
551 do_check_uri_eq(testURI, testURI.mutate().finalize());
556 " doesn't equal self with '" +
561 Assert.ok(!origURI.equals(testURI));
566 " is equalExceptRef to self with '" +
570 do_check_uri_eqExceptRef(origURI, testURI);
572 Assert.equal(testURI.hasRef, true);
575 // These tests fail if origURI has a ref
577 "testing setRef('') on " +
579 " is equal to no-ref version but not equal to ref version"
581 var cloneNoRef = testURI.mutate().setRef("").finalize(); // we used to clone here.
582 do_info("cloneNoRef: " + cloneNoRef.spec + " hasRef: " + cloneNoRef.hasRef);
583 do_info("testURI: " + testURI.spec + " hasRef: " + testURI.hasRef);
584 do_check_uri_eq(cloneNoRef, origURI);
585 Assert.ok(!cloneNoRef.equals(testURI));
588 "testing cloneWithNewRef on " +
590 " with an empty ref is equal to no-ref version but not equal to ref version"
592 var cloneNewRef = testURI.mutate().setRef("").finalize();
593 do_check_uri_eq(cloneNewRef, origURI);
594 do_check_uri_eq(cloneNewRef, cloneNoRef);
595 Assert.ok(!cloneNewRef.equals(testURI));
598 "testing cloneWithNewRef on " +
600 " with the same new ref is equal to ref version and not equal to no-ref version"
602 cloneNewRef = origURI.mutate().setRef(aSuffix).finalize();
603 do_check_uri_eq(cloneNewRef, testURI);
604 Assert.ok(cloneNewRef.equals(testURI));
607 do_check_property(aTest, testURI, "scheme");
608 do_check_property(aTest, testURI, "prePath");
610 // These don't work if it's a ref already because '+' doesn't give the right result
611 do_check_property(aTest, testURI, "pathQueryRef", function (aStr) {
612 return aStr + aSuffix;
614 do_check_property(aTest, testURI, "ref", function (aStr) {
615 return aSuffix.substr(1);
620 // Tests various ways of setting & clearing a ref on a URI.
621 function do_test_mutate_ref(aTest, aSuffix) {
622 do_info("making sure caller is using suffix that starts with '#'");
623 Assert.equal(aSuffix[0], "#");
625 var refURIWithSuffix = NetUtil.newURI(aTest.spec + aSuffix);
626 var refURIWithoutSuffix = NetUtil.newURI(aTest.spec);
628 var testURI = NetUtil.newURI(aTest.spec);
630 // First: Try setting .ref to our suffix
632 "testing that setting .ref on " +
636 "' does what we expect"
638 testURI = testURI.mutate().setRef(aSuffix).finalize();
639 do_check_uri_eq(testURI, refURIWithSuffix);
640 do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
642 // Now try setting .ref but leave off the initial hash (expect same result)
643 var suffixLackingHash = aSuffix.substr(1);
644 if (suffixLackingHash) {
645 // (skip this our suffix was *just* a #)
647 "testing that setting .ref on " +
651 "' does what we expect"
653 testURI = testURI.mutate().setRef(suffixLackingHash).finalize();
654 do_check_uri_eq(testURI, refURIWithSuffix);
655 do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
658 // Now, clear .ref (should get us back the original spec)
660 "testing that clearing .ref on " + testURI.spec + " does what we expect"
662 testURI = testURI.mutate().setRef("").finalize();
663 do_check_uri_eq(testURI, refURIWithoutSuffix);
664 do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
666 if (!aTest.relativeURI) {
667 // TODO: These tests don't work as-is for relative URIs.
669 // Now try setting .spec directly (including suffix) and then clearing .ref
670 var specWithSuffix = aTest.spec + aSuffix;
672 "testing that setting spec to " +
674 " and then clearing ref does what we expect"
677 testURI = testURI.mutate().setSpec(specWithSuffix).setRef("").finalize();
678 do_check_uri_eq(testURI, refURIWithoutSuffix);
679 do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
681 // XXX nsIJARURI throws an exception in SetPath(), so skip it for next part.
682 if (!(testURI instanceof Ci.nsIJARURI)) {
683 // Now try setting .pathQueryRef directly (including suffix) and then clearing .ref
684 // (same as above, but with now with .pathQueryRef instead of .spec)
685 testURI = NetUtil.newURI(aTest.spec);
687 var pathWithSuffix = aTest.pathQueryRef + aSuffix;
689 "testing that setting path to " +
691 " and then clearing ref does what we expect"
695 .setPathQueryRef(pathWithSuffix)
698 do_check_uri_eq(testURI, refURIWithoutSuffix);
699 do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
701 // Also: make sure that clearing .pathQueryRef also clears .ref
702 testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
704 "testing that clearing path from " +
708 testURI = testURI.mutate().setPathQueryRef("").finalize();
709 Assert.equal(testURI.ref, "");
714 // Check that changing nested/about URIs works correctly.
715 add_task(function check_nested_mutations() {
717 let uri1 = Services.io.newURI("about:blank#");
718 let uri2 = Services.io.newURI("about:blank");
719 let uri3 = uri1.mutate().setRef("").finalize();
720 do_check_uri_eq(uri3, uri2);
721 uri3 = uri2.mutate().setRef("#").finalize();
722 do_check_uri_eq(uri3, uri1);
724 uri1 = Services.io.newURI("about:blank?something");
725 uri2 = Services.io.newURI("about:blank");
726 uri3 = uri1.mutate().setQuery("").finalize();
727 do_check_uri_eq(uri3, uri2);
728 uri3 = uri2.mutate().setQuery("something").finalize();
729 do_check_uri_eq(uri3, uri1);
731 uri1 = Services.io.newURI("about:blank?query#ref");
732 uri2 = Services.io.newURI("about:blank");
733 uri3 = uri1.mutate().setPathQueryRef("blank").finalize();
734 do_check_uri_eq(uri3, uri2);
735 uri3 = uri2.mutate().setPathQueryRef("blank?query#ref").finalize();
736 do_check_uri_eq(uri3, uri1);
739 uri1 = Services.io.newURI("view-source:http://example.com/path#");
740 uri2 = Services.io.newURI("view-source:http://example.com/path");
741 uri3 = uri1.mutate().setRef("").finalize();
742 do_check_uri_eq(uri3, uri2);
743 uri3 = uri2.mutate().setRef("#").finalize();
744 do_check_uri_eq(uri3, uri1);
746 uri1 = Services.io.newURI("view-source:http://example.com/path?something");
747 uri2 = Services.io.newURI("view-source:http://example.com/path");
748 uri3 = uri1.mutate().setQuery("").finalize();
749 do_check_uri_eq(uri3, uri2);
750 uri3 = uri2.mutate().setQuery("something").finalize();
751 do_check_uri_eq(uri3, uri1);
753 uri1 = Services.io.newURI("view-source:http://example.com/path?query#ref");
754 uri2 = Services.io.newURI("view-source:http://example.com/path");
755 uri3 = uri1.mutate().setPathQueryRef("path").finalize();
756 do_check_uri_eq(uri3, uri2);
757 uri3 = uri2.mutate().setPathQueryRef("path?query#ref").finalize();
758 do_check_uri_eq(uri3, uri1);
760 uri1 = Services.io.newURI("view-source:about:blank#");
761 uri2 = Services.io.newURI("view-source:about:blank");
762 uri3 = uri1.mutate().setRef("").finalize();
763 do_check_uri_eq(uri3, uri2);
764 uri3 = uri2.mutate().setRef("#").finalize();
765 do_check_uri_eq(uri3, uri1);
767 uri1 = Services.io.newURI("view-source:about:blank?something");
768 uri2 = Services.io.newURI("view-source:about:blank");
769 uri3 = uri1.mutate().setQuery("").finalize();
770 do_check_uri_eq(uri3, uri2);
771 uri3 = uri2.mutate().setQuery("something").finalize();
772 do_check_uri_eq(uri3, uri1);
774 uri1 = Services.io.newURI("view-source:about:blank?query#ref");
775 uri2 = Services.io.newURI("view-source:about:blank");
776 uri3 = uri1.mutate().setPathQueryRef("blank").finalize();
777 do_check_uri_eq(uri3, uri2);
778 uri3 = uri2.mutate().setPathQueryRef("blank?query#ref").finalize();
779 do_check_uri_eq(uri3, uri1);
782 add_task(function check_space_escaping() {
783 let uri = Services.io.newURI("data:text/plain,hello%20world#space hash");
784 Assert.equal(uri.spec, "data:text/plain,hello%20world#space%20hash");
785 uri = Services.io.newURI("data:text/plain,hello%20world#space%20hash");
786 Assert.equal(uri.spec, "data:text/plain,hello%20world#space%20hash");
787 uri = Services.io.newURI("data:text/plain,hello world#space%20hash");
788 Assert.equal(uri.spec, "data:text/plain,hello world#space%20hash");
789 uri = Services.io.newURI("data:text/plain,hello world#space hash");
790 Assert.equal(uri.spec, "data:text/plain,hello world#space%20hash");
791 uri = Services.io.newURI("http://example.com/test path#test path");
792 uri = Services.io.newURI("http://example.com/test%20path#test%20path");
795 add_task(function check_schemeIsNull() {
796 let uri = Services.io.newURI("data:text/plain,aaa");
797 Assert.ok(!uri.schemeIs(null));
798 uri = Services.io.newURI("http://example.com");
799 Assert.ok(!uri.schemeIs(null));
800 uri = Services.io.newURI("dummyscheme://example.com");
801 Assert.ok(!uri.schemeIs(null));
802 uri = Services.io.newURI("jar:resource://gre/chrome.toolkit.jar!/");
803 Assert.ok(!uri.schemeIs(null));
804 uri = Services.io.newURI("moz-icon://.unknown?size=32");
805 Assert.ok(!uri.schemeIs(null));
808 // Check that characters in the query of moz-extension aren't improperly unescaped (Bug 1547882)
809 add_task(function check_mozextension_query() {
810 let uri = Services.io.newURI(
811 "moz-extension://a7d1572e-3beb-4d93-a920-c408fa09e8ea/_source/holding.html"
815 .setQuery("u=https%3A%2F%2Fnews.ycombinator.com%2F")
817 Assert.equal(uri.query, "u=https%3A%2F%2Fnews.ycombinator.com%2F");
818 uri = Services.io.newURI(
819 "moz-extension://a7d1572e-3beb-4d93-a920-c408fa09e8ea/_source/holding.html?u=https%3A%2F%2Fnews.ycombinator.com%2F"
823 "moz-extension://a7d1572e-3beb-4d93-a920-c408fa09e8ea/_source/holding.html?u=https%3A%2F%2Fnews.ycombinator.com%2F"
825 Assert.equal(uri.query, "u=https%3A%2F%2Fnews.ycombinator.com%2F");
828 add_task(function check_resolve() {
829 let base = Services.io.newURI("http://example.com");
830 let uri = Services.io.newURI("tel::+371 27028456", "utf-8", base);
831 Assert.equal(uri.spec, "tel::+371 27028456");
834 add_task(function test_extra_protocols() {
836 let url = Services.io.newURI("dweb://example.com/test");
837 Assert.equal(url.host, "example.com");
840 url = Services.io.newURI(
841 "dat://41f8a987cfeba80a037e51cc8357d513b62514de36f2f9b3d3eeec7a8fb3b5a5/"
845 "41f8a987cfeba80a037e51cc8357d513b62514de36f2f9b3d3eeec7a8fb3b5a5"
847 url = Services.io.newURI("dat://example.com/test");
848 Assert.equal(url.host, "example.com");
851 url = Services.io.newURI(
852 "ipfs://bafybeiccfclkdtucu6y4yc5cpr6y3yuinr67svmii46v5cfcrkp47ihehy/frontend/license.txt"
854 Assert.equal(url.scheme, "ipfs");
857 "bafybeiccfclkdtucu6y4yc5cpr6y3yuinr67svmii46v5cfcrkp47ihehy"
859 Assert.equal(url.filePath, "/frontend/license.txt");
862 url = Services.io.newURI("ipns://peerdium.gozala.io/index.html");
863 Assert.equal(url.scheme, "ipns");
864 Assert.equal(url.host, "peerdium.gozala.io");
865 Assert.equal(url.filePath, "/index.html");
868 url = Services.io.newURI("ssb://scuttlebutt.nz/index.html");
869 Assert.equal(url.scheme, "ssb");
870 Assert.equal(url.host, "scuttlebutt.nz");
871 Assert.equal(url.filePath, "/index.html");
874 url = Services.io.newURI(
875 "wtp://951ead31d09e4049fc1f21f137e233dd0589fcbd/blog/vim-tips/"
877 Assert.equal(url.scheme, "wtp");
878 Assert.equal(url.host, "951ead31d09e4049fc1f21f137e233dd0589fcbd");
879 Assert.equal(url.filePath, "/blog/vim-tips/");
882 // TEST MAIN FUNCTION
883 // ------------------
884 add_task(function mainTest() {
885 // UTF-8 check - From bug 622981
887 let base = Services.io.newURI("http://example.org/xenia?");
888 let resolved = Services.io.newURI("?x", null, base);
889 let expected = Services.io.newURI("http://example.org/xenia?x");
891 "Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec
893 Assert.ok(resolved.equals(expected));
895 // UTF-8 character "è"
896 // Bug 622981 was triggered by an empty query string
897 base = Services.io.newURI("http://example.org/xènia?");
898 resolved = Services.io.newURI("?x", null, base);
899 expected = Services.io.newURI("http://example.org/xènia?x");
901 "Bug 662981: UTF8 - comparing " + resolved.spec + " and " + expected.spec
903 Assert.ok(resolved.equals(expected));
905 gTests.forEach(function (aTest) {
906 // Check basic URI functionality
907 do_test_uri_basic(aTest);
910 // Try adding various #-prefixed strings to the ends of the URIs
911 gHashSuffixes.forEach(function (aSuffix) {
912 do_test_uri_with_hash_suffix(aTest, aSuffix);
913 if (!aTest.immutable) {
914 do_test_mutate_ref(aTest, aSuffix);
918 // For URIs that we couldn't mutate above due to them being immutable:
919 // Now we check that they're actually immutable.
920 if (aTest.immutable) {
921 Assert.ok(aTest.immutable);
927 function check_round_trip_serialization(spec) {
928 dump(`checking ${spec}\n`);
929 let uri = Services.io.newURI(spec);
930 let str = serialize_to_escaped_string(uri);
931 let other = deserialize_from_escaped_string(str).QueryInterface(Ci.nsIURI);
932 equal(other.spec, uri.spec);
935 add_task(function test_iconURI_serialization() {
936 // URIs taken from test_moz_icon_uri.js
939 "moz-icon://foo.html?contentType=bar&size=button&state=normal",
940 "moz-icon://foo.html?size=3",
941 "moz-icon://stock/foo",
942 "moz-icon:file://foo.txt",
943 "moz-icon://file://foo.txt",
946 tests.forEach(str => check_round_trip_serialization(str));
949 add_task(function test_jarURI_serialization() {
950 check_round_trip_serialization("jar:http://example.com/bar.jar!/");
953 add_task(async function round_trip_invalid_ace_label() {
954 // This is well-formed punycode, but an invalid ACE label due to hyphens in
955 // positions 3 & 4 and trailing hyphen. (Punycode-decode yields "xn--d淾-")
956 let uri = Services.io.newURI("http://xn--xn--d--fg4n/");
957 Assert.equal(uri.spec, "http://xn--xn--d--fg4n/");
959 // Entirely invalid punycode will throw a MALFORMED error.
960 Assert.throws(() => {
961 uri = Services.io.newURI("http://a.b.c.XN--pokxncvks");
962 }, /NS_ERROR_MALFORMED_URI/);