Bug 1146304 - Touch slider bar or tap forward button, the video got stuck 1s then...
[gecko.git] / netwerk / test / unit / test_URIs.js
blobebf4965497736c04f8e5b9fdba13006f46b83fbc
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 Components.utils.import("resource://gre/modules/NetUtil.jsm");
4 var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
5                            .getService(Components.interfaces.nsIIOService);
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/
17 // TEST DATA
18 // ---------
19 var gTests = [
20   { spec:    "about:blank",
21     scheme:  "about",
22     prePath: "about:",
23     path:    "blank",
24     ref:     "",
25     nsIURL:  false, nsINestedURI: true, immutable: true },
26   { spec:    "about:foobar",
27     scheme:  "about",
28     prePath: "about:",
29     path:    "foobar",
30     ref:     "",
31     nsIURL:  false, nsINestedURI: false, immutable: true },
32   { spec:    "chrome://foobar/somedir/somefile.xml",
33     scheme:  "chrome",
34     prePath: "chrome://foobar",
35     path:    "/somedir/somefile.xml",
36     ref:     "",
37     nsIURL:  true, nsINestedURI: false, immutable: true },
38   { spec:    "data:text/html;charset=utf-8,<html></html>",
39     scheme:  "data",
40     prePath: "data:",
41     path:    "text/html;charset=utf-8,<html></html>",
42     ref:     "",
43     nsIURL:  false, nsINestedURI: false },
44   { spec:    "data:text/html;charset=utf-8,<html>\r\n\t</html>",
45     scheme:  "data",
46     prePath: "data:",
47     path:    "text/html;charset=utf-8,<html></html>",
48     ref:     "",
49     nsIURL:  false, nsINestedURI: false },
50   { spec:    "data:text/plain,hello world",
51     scheme:  "data",
52     prePath: "data:",
53     path:    "text/plain,hello%20world",
54     ref:     "",
55     nsIURL:  false, nsINestedURI: false },
56   { spec:    "file:///dir/afile",
57     scheme:  "data",
58     prePath: "data:",
59     path:    "text/plain,2",
60     ref:     "",
61     relativeURI: "data:te\nxt/plain,2",
62     nsIURL:  false, nsINestedURI: false },
63   { spec:    "file://",
64     scheme:  "file",
65     prePath: "file://",
66     path:    "/",
67     ref:     "",
68     nsIURL:  true, nsINestedURI: false },
69   { spec:    "file:///",
70     scheme:  "file",
71     prePath: "file://",
72     path:    "/",
73     ref:     "",
74     nsIURL:  true, nsINestedURI: false },
75   { spec:    "file:///myFile.html",
76     scheme:  "file",
77     prePath: "file://",
78     path:    "/myFile.html",
79     ref:     "",
80     nsIURL:  true, nsINestedURI: false },
81   { spec:    "file:///dir/afile",
82     scheme:  "file",
83     prePath: "file://",
84     path:    "/dir/data/text/plain,2",
85     ref:     "",
86     relativeURI: "data/text/plain,2",
87     nsIURL:  true, nsINestedURI: false },
88   { spec:    "file:///dir/dir2/",
89     scheme:  "file",
90     prePath: "file://",
91     path:    "/dir/dir2/data/text/plain,2",
92     ref:     "",
93     relativeURI: "data/text/plain,2",
94     nsIURL:  true, nsINestedURI: false },
95   { spec:    "ftp://",
96     scheme:  "ftp",
97     prePath: "ftp://",
98     path:    "/",
99     ref:     "",
100     nsIURL:  true, nsINestedURI: false },
101   { spec:    "ftp:///",
102     scheme:  "ftp",
103     prePath: "ftp://",
104     path:    "/",
105     ref:     "",
106     nsIURL:  true, nsINestedURI: false },
107   { spec:    "ftp://ftp.mozilla.org/pub/mozilla.org/README",
108     scheme:  "ftp",
109     prePath: "ftp://ftp.mozilla.org",
110     path:    "/pub/mozilla.org/README",
111     ref:     "",
112     nsIURL:  true, nsINestedURI: false },
113   { spec:    "ftp://foo:bar@ftp.mozilla.org:100/pub/mozilla.org/README",
114     scheme:  "ftp",
115     prePath: "ftp://foo:bar@ftp.mozilla.org:100",
116     port:    100,
117     username: "foo",
118     password: "bar",
119     path:    "/pub/mozilla.org/README",
120     ref:     "",
121     nsIURL:  true, nsINestedURI: false },
122   { spec:    "ftp://foo:@ftp.mozilla.org:100/pub/mozilla.org/README",
123     scheme:  "ftp",
124     prePath: "ftp://foo:@ftp.mozilla.org:100",
125     port:    100,
126     username: "foo",
127     password: "",
128     path:    "/pub/mozilla.org/README",
129     ref:     "",
130     nsIURL:  true, nsINestedURI: false },
131   //Bug 706249
132   { spec:    "http:x:@",
133     scheme:  "http",
134     prePath: "http://x:@",
135     username: "x",
136     password: "",
137     path:    "",
138     ref:     "",
139     nsIURL:  true, nsINestedURI: false },
140   { spec:    "gopher://mozilla.org/",
141     scheme:  "gopher",
142     prePath: "gopher:",
143     path:    "//mozilla.org/",
144     ref:     "",
145     nsIURL:  false, nsINestedURI: false },
146   { spec:    "http://",
147     scheme:  "http",
148     prePath: "http://",
149     path:    "/",
150     ref:     "",
151     nsIURL:  true, nsINestedURI: false },
152   { spec:    "http:///",
153     scheme:  "http",
154     prePath: "http://",
155     path:    "/",
156     ref:     "",
157     nsIURL:  true, nsINestedURI: false },
158   { spec:    "http://www.example.com/",
159     scheme:  "http",
160     prePath: "http://www.example.com",
161     path:    "/",
162     ref:     "",
163     nsIURL:  true, nsINestedURI: false },
164   { spec:    "http://www.exa\nmple.com/",
165     scheme:  "http",
166     prePath: "http://www.example.com",
167     path:    "/",
168     ref:     "",
169     nsIURL:  true, nsINestedURI: false },
170   { spec:    "http://10.32.4.239/",
171     scheme:  "http",
172     prePath: "http://10.32.4.239",
173     host:    "10.32.4.239",
174     path:    "/",
175     ref:     "",
176     nsIURL:  true, nsINestedURI: false },
177   { spec:    "http://[::192.9.5.5]/ipng",
178     scheme:  "http",
179     prePath: "http://[::192.9.5.5]",
180     host:    "::192.9.5.5",
181     path:    "/ipng",
182     ref:     "",
183     nsIURL:  true, nsINestedURI: false },
184   { spec:    "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8888/index.html",
185     scheme:  "http",
186     prePath: "http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:8888",
187     host:    "fedc:ba98:7654:3210:fedc:ba98:7654:3210",
188     port:    8888,
189     path:    "/index.html",
190     ref:     "",
191     nsIURL:  true, nsINestedURI: false },
192   { spec:    "http://bar:foo@www.mozilla.org:8080/pub/mozilla.org/README.html",
193     scheme:  "http",
194     prePath: "http://bar:foo@www.mozilla.org:8080",
195     port:    8080,
196     username: "bar",
197     password: "foo",
198     host:    "www.mozilla.org",
199     path:    "/pub/mozilla.org/README.html",
200     ref:     "",
201     nsIURL:  true, nsINestedURI: false },
202   { spec:    "jar:resource://!/",
203     scheme:  "jar",
204     prePath: "jar:",
205     path:    "resource:///!/",
206     ref:     "",
207     nsIURL:  true, nsINestedURI: true },
208   { spec:    "jar:resource://gre/chrome.toolkit.jar!/",
209     scheme:  "jar",
210     prePath: "jar:",
211     path:    "resource://gre/chrome.toolkit.jar!/",
212     ref:     "",
213     nsIURL:  true, nsINestedURI: true },
214   { spec:    "mailto:webmaster@mozilla.com",
215     scheme:  "mailto",
216     prePath: "mailto:",
217     path:    "webmaster@mozilla.com",
218     ref:     "",
219     nsIURL:  false, nsINestedURI: false },
220   { spec:    "javascript:new Date()",
221     scheme:  "javascript",
222     prePath: "javascript:",
223     path:    "new%20Date()",
224     ref:     "",
225     nsIURL:  false, nsINestedURI: false },
226   { spec:    "blob:123456",
227     scheme:  "blob",
228     prePath: "blob:",
229     path:    "123456",
230     ref:     "",
231     nsIURL:  false, nsINestedURI: false, immutable: true },
232   { spec:    "place:sort=8&maxResults=10",
233     scheme:  "place",
234     prePath: "place:",
235     path:    "sort=8&maxResults=10",
236     ref:     "",
237     nsIURL:  false, nsINestedURI: false },
238   { spec:    "resource://gre/",
239     scheme:  "resource",
240     prePath: "resource://gre",
241     path:    "/",
242     ref:     "",
243     nsIURL:  true, nsINestedURI: false },
244   { spec:    "resource://gre/components/",
245     scheme:  "resource",
246     prePath: "resource://gre",
247     path:    "/components/",
248     ref:     "",
249     nsIURL:  true, nsINestedURI: false },
250   { spec:    "view-source:about:blank",
251     scheme:  "view-source",
252     prePath: "view-source:",
253     path:    "about:blank",
254     ref:     "",
255     nsIURL:  false, nsINestedURI: true, immutable: true },
256   { spec:    "view-source:http://www.mozilla.org/",
257     scheme:  "view-source",
258     prePath: "view-source:",
259     path:    "http://www.mozilla.org/",
260     ref:     "",
261     nsIURL:  false, nsINestedURI: true, immutable: true },
262   { spec:    "x-external:",
263     scheme:  "x-external",
264     prePath: "x-external:",
265     path:    "",
266     ref:     "",
267     nsIURL:  false, nsINestedURI: false },
268   { spec:    "x-external:abc",
269     scheme:  "x-external",
270     prePath: "x-external:",
271     path:    "abc",
272     ref:     "",
273     nsIURL:  false, nsINestedURI: false },
274   { spec:    "http://www2.example.com/",
275     relativeURI: "a/b/c/d",
276     scheme:  "http",
277     prePath: "http://www2.example.com",
278     path:    "/a/b/c/d",
279     ref:     "",
280     nsIURL:  true, nsINestedURI: false },
282     // Adding more? Consider adding to test_URIs2.js instead, so that neither
283     // test runs for *too* long, risking timeouts on slow platforms.
286 var gHashSuffixes = [
287   "#",
288   "#myRef",
289   "#myRef?a=b",
290   "#myRef#",
291   "#myRef#x:yz"
294 // TEST HELPER FUNCTIONS
295 // ---------------------
296 function do_info(text, stack) {
297   if (!stack)
298     stack = Components.stack.caller;
300   dump( "\n" +
301        "TEST-INFO | " + stack.filename + " | [" + stack.name + " : " +
302        stack.lineNumber + "] " + text + "\n");
305 // Checks that the URIs satisfy equals(), in both possible orderings.
306 // Also checks URI.equalsExceptRef(), because equal URIs should also be equal
307 // when we ignore the ref.
308 // 
309 // The third argument is optional. If the client passes a third argument
310 // (e.g. todo_check_true), we'll use that in lieu of do_check_true.
311 function do_check_uri_eq(aURI1, aURI2, aCheckTrueFunc) {
312   if (!aCheckTrueFunc) {
313     aCheckTrueFunc = do_check_true;
314   }
316   do_info("(uri equals check: '" + aURI1.spec + "' == '" + aURI2.spec + "')");
317   aCheckTrueFunc(aURI1.equals(aURI2));
318   do_info("(uri equals check: '" + aURI2.spec + "' == '" + aURI1.spec + "')");
319   aCheckTrueFunc(aURI2.equals(aURI1));
321   // (Only take the extra step of testing 'equalsExceptRef' when we expect the
322   // URIs to really be equal.  In 'todo' cases, the URIs may or may not be
323   // equal when refs are ignored - there's no way of knowing in general.)
324   if (aCheckTrueFunc == do_check_true) {
325     do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc);
326   }
329 // Checks that the URIs satisfy equalsExceptRef(), in both possible orderings.
331 // The third argument is optional. If the client passes a third argument
332 // (e.g. todo_check_true), we'll use that in lieu of do_check_true.
333 function do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc) {
334   if (!aCheckTrueFunc) {
335     aCheckTrueFunc = do_check_true;
336   }
338   do_info("(uri equalsExceptRef check: '" +
339           aURI1.spec + "' == '" + aURI2.spec + "')");
340   aCheckTrueFunc(aURI1.equalsExceptRef(aURI2));
341   do_info("(uri equalsExceptRef check: '" +
342           aURI2.spec + "' == '" + aURI1.spec + "')");
343   aCheckTrueFunc(aURI2.equalsExceptRef(aURI1));
346 // Checks that the given property on aURI matches the corresponding property
347 // in the test bundle (or matches some function of that corresponding property,
348 // if aTestFunctor is passed in).
349 function do_check_property(aTest, aURI, aPropertyName, aTestFunctor) {
350   if (aTest[aPropertyName]) {
351     var expectedVal = aTestFunctor ?
352                       aTestFunctor(aTest[aPropertyName]) :
353                       aTest[aPropertyName];
355     do_info("testing " + aPropertyName + " of " +
356             (aTestFunctor ? "modified '" : "'" ) + aTest.spec +
357             "' is '" + expectedVal + "'");
358     do_check_eq(aURI[aPropertyName], expectedVal);
359   }
362 // Test that a given URI parses correctly into its various components.
363 function do_test_uri_basic(aTest) {
364   var URI;
366   do_info("Basic tests for " + aTest.spec + " relative URI: " + aTest.relativeURI);
368   try {
369     URI = NetUtil.newURI(aTest.spec);
370   } catch(e) {
371     do_info("Caught error on parse of" + aTest.spec + " Error: " + e.result);
372     if (aTest.fail) {
373       do_check_eq(e.result, aTest.result);
374       return;
375     }
376     do_throw(e.result);
377   }
379   if (aTest.relativeURI) {
380     var relURI;
382     try {
383       relURI = gIoService.newURI(aTest.relativeURI, null, URI);
384     } catch (e) {
385       do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result);
386       if (aTest.relativeFail) {
387         do_check_eq(e.result, aTest.relativeFail);
388         return;
389       }
390       do_throw(e.result);
391     }
392     do_info("relURI.path = " + relURI.path + ", was " + URI.path);
393     URI = relURI;
394     do_info("URI.path now = " + URI.path);
395   }
397   // Sanity-check
398   do_info("testing " + aTest.spec + " equals a clone of itself");
399   do_check_uri_eq(URI, URI.clone());
400   do_check_uri_eqExceptRef(URI, URI.cloneIgnoringRef());
401   do_info("testing " + aTest.spec + " instanceof nsIURL");
402   do_check_eq(URI instanceof Ci.nsIURL, aTest.nsIURL);
403   do_info("testing " + aTest.spec + " instanceof nsINestedURI");
404   do_check_eq(URI instanceof Ci.nsINestedURI,
405               aTest.nsINestedURI);
407   do_info("testing that " + aTest.spec + " throws or returns false " +
408           "from equals(null)");
409   // XXXdholbert At some point it'd probably be worth making this behavior
410   // (throwing vs. returning false) consistent across URI implementations.
411   var threw = false;
412   var isEqualToNull;
413   try {
414     isEqualToNull = URI.equals(null);
415   } catch(e) {
416     threw = true;
417   }
418   do_check_true(threw || !isEqualToNull);
421   // Check the various components
422   do_check_property(aTest, URI, "scheme");
423   do_check_property(aTest, URI, "prePath");
424   do_check_property(aTest, URI, "path");
425   do_check_property(aTest, URI, "ref");
426   do_check_property(aTest, URI, "port");
427   do_check_property(aTest, URI, "username");
428   do_check_property(aTest, URI, "password");
429   do_check_property(aTest, URI, "host");
430   do_check_property(aTest, URI, "specIgnoringRef");
431   if ("hasRef" in aTest) {
432     do_info("testing hasref: " + aTest.hasRef + " vs " + URI.hasRef);
433     do_check_eq(aTest.hasRef, URI.hasRef);
434   }
437 // Test that a given URI parses correctly when we add a given ref to the end
438 function do_test_uri_with_hash_suffix(aTest, aSuffix) {
439   do_info("making sure caller is using suffix that starts with '#'");
440   do_check_eq(aSuffix[0], "#");
442   var origURI = NetUtil.newURI(aTest.spec);
443   var testURI;
445   if (aTest.relativeURI) {
446     try {
447       origURI = gIoService.newURI(aTest.relativeURI, null, origURI);
448     } catch (e) {
449       do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result);
450       return;
451     }
452     try {
453       testURI = gIoService.newURI(aSuffix, null, origURI);
454     } catch (e) {
455       do_info("Caught error adding suffix to " + aTest.spec + " + " + aTest.relativeURI + ", suffix " + aSuffix + " Error: " + e.result);
456       return;
457     }
458   } else {
459     testURI = NetUtil.newURI(aTest.spec + aSuffix);
460   }
462   do_info("testing " + aTest.spec + " with '" + aSuffix + "' appended " +
463            "equals a clone of itself");
464   do_check_uri_eq(testURI, testURI.clone());
466   do_info("testing " + aTest.spec +
467           " doesn't equal self with '" + aSuffix + "' appended");
469   do_check_false(origURI.equals(testURI));
471   do_info("testing " + aTest.spec +
472           " is equalExceptRef to self with '" + aSuffix + "' appended");
473   do_check_uri_eqExceptRef(origURI, testURI);
475   do_check_eq(testURI.hasRef, true);
477   if (!origURI.ref) {
478     // These tests fail if origURI has a ref
479     do_info("testing cloneIgnoringRef on " + testURI.spec +
480             " is equal to no-ref version but not equal to ref version");
481     var cloneNoRef = testURI.cloneIgnoringRef();
482     do_check_uri_eq(cloneNoRef, origURI);
483     do_check_false(cloneNoRef.equals(testURI));
484   }
486   do_check_property(aTest, testURI, "scheme");
487   do_check_property(aTest, testURI, "prePath");
488   if (!origURI.ref) {
489     // These don't work if it's a ref already because '+' doesn't give the right result
490     do_check_property(aTest, testURI, "path",
491                       function(aStr) { return aStr + aSuffix; });
492     do_check_property(aTest, testURI, "ref",
493                       function(aStr) { return aSuffix.substr(1); });
494   }
497 // Tests various ways of setting & clearing a ref on a URI.
498 function do_test_mutate_ref(aTest, aSuffix) {
499   do_info("making sure caller is using suffix that starts with '#'");
500   do_check_eq(aSuffix[0], "#");
502   var refURIWithSuffix    = NetUtil.newURI(aTest.spec + aSuffix);
503   var refURIWithoutSuffix = NetUtil.newURI(aTest.spec);
505   var testURI             = NetUtil.newURI(aTest.spec);
507   // First: Try setting .ref to our suffix
508   do_info("testing that setting .ref on " + aTest.spec +
509           " to '" + aSuffix + "' does what we expect");
510   testURI.ref = aSuffix;
511   do_check_uri_eq(testURI, refURIWithSuffix);
512   do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
514   // Now try setting .ref but leave off the initial hash (expect same result)
515   var suffixLackingHash = aSuffix.substr(1);
516   if (suffixLackingHash) { // (skip this our suffix was *just* a #)
517     do_info("testing that setting .ref on " + aTest.spec +
518             " to '" + suffixLackingHash + "' does what we expect");
519     testURI.ref = suffixLackingHash;
520     do_check_uri_eq(testURI, refURIWithSuffix);
521     do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
522   }
524   // Now, clear .ref (should get us back the original spec)
525   do_info("testing that clearing .ref on " + testURI.spec +
526           " does what we expect");
527   testURI.ref = "";
528   do_check_uri_eq(testURI, refURIWithoutSuffix);
529   do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
531   if (!aTest.relativeURI) {
532     // TODO: These tests don't work as-is for relative URIs.
534     // Now try setting .spec directly (including suffix) and then clearing .ref
535     var specWithSuffix = aTest.spec + aSuffix;
536     do_info("testing that setting spec to " +
537             specWithSuffix + " and then clearing ref does what we expect");
538     testURI.spec = specWithSuffix;
539     testURI.ref = "";
540     do_check_uri_eq(testURI, refURIWithoutSuffix);
541     do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
543     // XXX nsIJARURI throws an exception in SetPath(), so skip it for next part.
544     if (!(testURI instanceof Ci.nsIJARURI)) {
545       // Now try setting .path directly (including suffix) and then clearing .ref
546       // (same as above, but with now with .path instead of .spec)
547       testURI = NetUtil.newURI(aTest.spec);
549       var pathWithSuffix = aTest.path + aSuffix;
550       do_info("testing that setting path to " +
551               pathWithSuffix + " and then clearing ref does what we expect");
552       testURI.path = pathWithSuffix;
553       testURI.ref = "";
554       do_check_uri_eq(testURI, refURIWithoutSuffix);
555       do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
557       // Also: make sure that clearing .path also clears .ref
558       testURI.path = pathWithSuffix;
559       do_info("testing that clearing path from " + 
560               pathWithSuffix + " also clears .ref");
561       testURI.path = "";
562       do_check_eq(testURI.ref, "");
563     }
564   }
567 // Tests that normally-mutable properties can't be modified on
568 // special URIs that are known to be immutable.
569 function do_test_immutable(aTest) {
570   do_check_true(aTest.immutable);
572   var URI = NetUtil.newURI(aTest.spec);
573   // All the non-readonly attributes on nsIURI.idl:
574   var propertiesToCheck = ["spec", "scheme", "userPass", "username", "password",
575                            "hostPort", "host", "port", "path", "ref"];
577   propertiesToCheck.forEach(function(aProperty) {
578     var threw = false;
579     try {
580       URI[aProperty] = "anothervalue";
581     } catch(e) {
582       threw = true;
583     }
585     do_info("testing that setting '" + aProperty +
586             "' on immutable URI '" + aTest.spec + "' will throw");
587     do_check_true(threw);
588   });
592 // TEST MAIN FUNCTION
593 // ------------------
594 function run_test()
596   // UTF-8 check - From bug 622981
597   // ASCII
598   let base = gIoService.newURI("http://example.org/xenia?", null, null);
599   let resolved = gIoService.newURI("?x", null, base);
600   let expected = gIoService.newURI("http://example.org/xenia?x",
601                                   null, null);
602   do_info("Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec);
603   do_check_true(resolved.equals(expected));
605   // UTF-8 character "è"
606   // Bug 622981 was triggered by an empty query string
607   base = gIoService.newURI("http://example.org/xènia?", null, null);
608   resolved = gIoService.newURI("?x", null, base);
609   expected = gIoService.newURI("http://example.org/xènia?x",
610                               null, null);
611   do_info("Bug 662981: UTF8 - comparing " + resolved.spec + " and " + expected.spec);
612   do_check_true(resolved.equals(expected));
614   gTests.forEach(function(aTest) {
615     // Check basic URI functionality
616     do_test_uri_basic(aTest);
618     if (!aTest.fail) {
619       // Try adding various #-prefixed strings to the ends of the URIs
620       gHashSuffixes.forEach(function(aSuffix) {
621           do_test_uri_with_hash_suffix(aTest, aSuffix);
622           if (!aTest.immutable) {
623             do_test_mutate_ref(aTest, aSuffix);
624           }
625         });
627       // For URIs that we couldn't mutate above due to them being immutable:
628       // Now we check that they're actually immutable.
629       if (aTest.immutable) {
630         do_test_immutable(aTest);
631       }
632     }
633   });