gecko/netwerk/test/unit/test_URIs.js

459 lines
15 KiB
JavaScript

/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Components.utils.import("resource://gre/modules/NetUtil.jsm");
const Ci = Components.interfaces;
// TEST DATA
// ---------
var gTests = [
{ spec: "about:blank",
scheme: "about",
prePath: "about:",
path: "blank",
ref: "",
nsIURL: false, nsINestedURI: true, immutable: true },
{ spec: "about:foobar",
scheme: "about",
prePath: "about:",
path: "foobar",
ref: "",
nsIURL: false, nsINestedURI: false, immutable: true },
{ spec: "chrome://foobar/somedir/somefile.xml",
scheme: "chrome",
prePath: "chrome://foobar",
path: "/somedir/somefile.xml",
ref: "",
nsIURL: true, nsINestedURI: false, immutable: true },
{ spec: "data:text/html;charset=utf-8,<html></html>",
scheme: "data",
prePath: "data:",
path: "text/html;charset=utf-8,<html></html>",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "data:text/plain,hello world",
scheme: "data",
prePath: "data:",
path: "text/plain,hello%20world",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "file://",
scheme: "file",
prePath: "file://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "file:///",
scheme: "file",
prePath: "file://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "file:///myFile.html",
scheme: "file",
prePath: "file://",
path: "/myFile.html",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "ftp://",
scheme: "ftp",
prePath: "ftp://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "ftp:///",
scheme: "ftp",
prePath: "ftp://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "ftp://ftp.mozilla.org/pub/mozilla.org/README",
scheme: "ftp",
prePath: "ftp://ftp.mozilla.org",
path: "/pub/mozilla.org/README",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "ftp://foo:bar@ftp.mozilla.org:100/pub/mozilla.org/README",
scheme: "ftp",
prePath: "ftp://foo:bar@ftp.mozilla.org:100",
path: "/pub/mozilla.org/README",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "gopher://mozilla.org/",
scheme: "gopher",
prePath: "gopher:",
path: "//mozilla.org/",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "http://",
scheme: "http",
prePath: "http://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http:///",
scheme: "http",
prePath: "http://",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://www.example.com/",
scheme: "http",
prePath: "http://www.example.com",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "jar:resource://!/",
scheme: "jar",
prePath: "jar:",
path: "resource:///!/",
ref: "",
nsIURL: true, nsINestedURI: true },
{ spec: "jar:resource://gre/chrome.toolkit.jar!/",
scheme: "jar",
prePath: "jar:",
path: "resource://gre/chrome.toolkit.jar!/",
ref: "",
nsIURL: true, nsINestedURI: true },
{ spec: "mailto:webmaster@mozilla.com",
scheme: "mailto",
prePath: "mailto:",
path: "webmaster@mozilla.com",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "javascript:new Date()",
scheme: "javascript",
prePath: "javascript:",
path: "new%20Date()",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "moz-filedata:123456",
scheme: "moz-filedata",
prePath: "moz-filedata:",
path: "123456",
ref: "",
nsIURL: false, nsINestedURI: false, immutable: true },
{ spec: "place:redirectsMode=2&sort=8&maxResults=10",
scheme: "place",
prePath: "place:",
path: "redirectsMode=2&sort=8&maxResults=10",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "resource://gre/",
scheme: "resource",
prePath: "resource://gre",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "resource://gre/components/",
scheme: "resource",
prePath: "resource://gre",
path: "/components/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "view-source:about:blank",
scheme: "view-source",
prePath: "view-source:",
path: "about:blank",
ref: "",
nsIURL: false, nsINestedURI: true, immutable: true },
{ spec: "view-source:http://www.mozilla.org/",
scheme: "view-source",
prePath: "view-source:",
path: "http://www.mozilla.org/",
ref: "",
nsIURL: false, nsINestedURI: true, immutable: true },
{ spec: "x-external:",
scheme: "x-external",
prePath: "x-external:",
path: "",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "x-external:abc",
scheme: "x-external",
prePath: "x-external:",
path: "abc",
ref: "",
nsIURL: false, nsINestedURI: false },
];
var gHashSuffixes = [
"#",
"#myRef",
"#myRef?a=b",
"#myRef#",
"#myRef#x:yz"
];
// TEST HELPER FUNCTIONS
// ---------------------
function do_info(text, stack) {
if (!stack)
stack = Components.stack.caller;
dump( "\n" +
"TEST-INFO | " + stack.filename + " | [" + stack.name + " : " +
stack.lineNumber + "] " + text + "\n");
}
// Checks that the URIs satisfy equals(), in both possible orderings.
// Also checks URI.equalsExceptRef(), because equal URIs should also be equal
// when we ignore the ref.
//
// The third argument is optional. If the client passes a third argument
// (e.g. todo_check_true), we'll use that in lieu of do_check_true.
function do_check_uri_eq(aURI1, aURI2, aCheckTrueFunc) {
if (!aCheckTrueFunc) {
aCheckTrueFunc = do_check_true;
}
do_info("(uri equals check: '" + aURI1.spec + "' == '" + aURI2.spec + "')");
aCheckTrueFunc(aURI1.equals(aURI2));
do_info("(uri equals check: '" + aURI2.spec + "' == '" + aURI1.spec + "')");
aCheckTrueFunc(aURI2.equals(aURI1));
// (Only take the extra step of testing 'equalsExceptRef' when we expect the
// URIs to really be equal. In 'todo' cases, the URIs may or may not be
// equal when refs are ignored - there's no way of knowing in general.)
if (aCheckTrueFunc == do_check_true) {
do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc);
}
}
// Checks that the URIs satisfy equalsExceptRef(), in both possible orderings.
//
// The third argument is optional. If the client passes a third argument
// (e.g. todo_check_true), we'll use that in lieu of do_check_true.
function do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc) {
if (!aCheckTrueFunc) {
aCheckTrueFunc = do_check_true;
}
do_info("(uri equalsExceptRef check: '" +
aURI1.spec + "' == '" + aURI2.spec + "')");
aCheckTrueFunc(aURI1.equalsExceptRef(aURI2));
do_info("(uri equalsExceptRef check: '" +
aURI2.spec + "' == '" + aURI1.spec + "')");
aCheckTrueFunc(aURI2.equalsExceptRef(aURI1));
}
// Checks that the given property on aURI matches the corresponding property
// in the test bundle (or matches some function of that corresponding property,
// if aTestFunctor is passed in).
function do_check_property(aTest, aURI, aPropertyName, aTestFunctor) {
var expectedVal = aTestFunctor ?
aTestFunctor(aTest[aPropertyName]) :
aTest[aPropertyName];
do_info("testing " + aPropertyName + " of " +
(aTestFunctor ? "modified '" : "'" ) + aTest.spec +
"' is '" + expectedVal + "'");
do_check_eq(aURI[aPropertyName], expectedVal);
}
// Test that a given URI parses correctly into its various components.
function do_test_uri_basic(aTest) {
var URI = NetUtil.newURI(aTest.spec);
// Sanity-check
do_info("testing " + aTest.spec + " equals a clone of itself");
do_check_uri_eq(URI, URI.clone());
do_check_uri_eq(URI, URI.cloneIgnoringRef());
do_info("testing " + aTest.spec + " instanceof nsIURL");
do_check_eq(URI instanceof Ci.nsIURL, aTest.nsIURL);
do_info("testing " + aTest.spec + " instanceof nsINestedURI");
do_check_eq(URI instanceof Ci.nsINestedURI,
aTest.nsINestedURI);
do_info("testing that " + aTest.spec + " throws or returns false " +
"from equals(null)");
// XXXdholbert At some point it'd probably be worth making this behavior
// (throwing vs. returning false) consistent across URI implementations.
var threw = false;
var isEqualToNull;
try {
isEqualToNull = URI.equals(null);
} catch(e) {
threw = true;
}
do_check_true(threw || !isEqualToNull);
// Check the various components
do_check_property(aTest, URI, "scheme");
do_check_property(aTest, URI, "prePath");
do_check_property(aTest, URI, "path");
do_check_property(aTest, URI, "ref");
}
// Test that a given URI parses correctly when we add a given ref to the end
function do_test_uri_with_hash_suffix(aTest, aSuffix) {
do_info("making sure caller is using suffix that starts with '#'");
do_check_eq(aSuffix[0], "#");
var testURI = NetUtil.newURI(aTest.spec + aSuffix);
var origURI = NetUtil.newURI(aTest.spec);
do_info("testing " + aTest.spec + " with '" + aSuffix + "' appended " +
"equals a clone of itself");
do_check_uri_eq(testURI, testURI.clone());
do_info("testing " + aTest.spec +
" doesn't equal self with '" + aSuffix + "' appended");
if (aTest.spec == "file://") {
do_info("TODO: bug 656853");
todo_check_false(origURI.equals(testURI));
return; // bail out early since file:// doesn't handle hash refs at all
}
do_check_false(origURI.equals(testURI));
do_info("testing " + aTest.spec +
" is equalExceptRef to self with '" + aSuffix + "' appended");
do_check_uri_eqExceptRef(origURI, testURI);
do_info("testing cloneIgnoringRef on " + testURI.spec +
" is equal to no-ref version but not equal to ref version");
var cloneNoRef = testURI.cloneIgnoringRef();
if ((aTest.spec == "http://" || aTest.spec == "ftp://") && aSuffix == "#") {
do_info("TODO: bug 657033");
do_check_uri_eq(cloneNoRef, origURI, todo_check_true);
} else {
do_check_uri_eq(cloneNoRef, origURI);
}
do_check_false(cloneNoRef.equals(testURI));
do_check_property(aTest, testURI, "scheme");
do_check_property(aTest, testURI, "prePath");
do_check_property(aTest, testURI, "path",
function(aStr) { return aStr + aSuffix; });
do_check_property(aTest, testURI, "ref",
function(aStr) { return aSuffix.substr(1); });
}
// Tests various ways of setting & clearing a ref on a URI.
function do_test_mutate_ref(aTest, aSuffix) {
do_info("making sure caller is using suffix that starts with '#'");
do_check_eq(aSuffix[0], "#");
var refURIWithSuffix = NetUtil.newURI(aTest.spec + aSuffix);
var refURIWithoutSuffix = NetUtil.newURI(aTest.spec);
var testURI = NetUtil.newURI(aTest.spec);
if (aTest.spec == "file://") {
do_info("TODO: bug 656853");
testURI.ref = aSuffix;
do_check_uri_eq(testURI, refURIWithSuffix, todo_check_true);
return; // bail out early since file:// doesn't handle hash refs at all
}
// First: Try setting .ref to our suffix
do_info("testing that setting .ref on " + aTest.spec +
" to '" + aSuffix + "' does what we expect");
testURI.ref = aSuffix;
do_check_uri_eq(testURI, refURIWithSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
// Now try setting .ref but leave off the initial hash (expect same result)
var suffixLackingHash = aSuffix.substr(1);
if (suffixLackingHash) { // (skip this our suffix was *just* a #)
do_info("testing that setting .ref on " + aTest.spec +
" to '" + suffixLackingHash + "' does what we expect");
testURI.ref = suffixLackingHash;
do_check_uri_eq(testURI, refURIWithSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
}
// Now, clear .ref (should get us back the original spec)
do_info("testing that clearing .ref on " + testURI.spec +
" does what we expect");
testURI.ref = "";
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
// Now try setting .spec directly (including suffix) and then clearing .ref
var specWithSuffix = aTest.spec + aSuffix;
do_info("testing that setting spec to " +
specWithSuffix + " and then clearing ref does what we expect");
testURI.spec = specWithSuffix
testURI.ref = "";
if ((aTest.spec == "http://" || aTest.spec == "ftp://") && aSuffix == "#") {
do_info("TODO: bug 657033");
do_check_uri_eq(testURI, refURIWithoutSuffix, todo_check_true);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix, todo_check_true);
} else {
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
}
// XXX nsIJARURI throws an exception in SetPath(), so skip it for next part.
if (!(testURI instanceof Ci.nsIJARURI)) {
// Now try setting .path directly (including suffix) and then clearing .ref
// (same as above, but with now with .path instead of .spec)
testURI = NetUtil.newURI(aTest.spec);
var pathWithSuffix = aTest.path + aSuffix;
do_info("testing that setting path to " +
pathWithSuffix + " and then clearing ref does what we expect");
testURI.path = pathWithSuffix;
testURI.ref = "";
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
// Also: make sure that clearing .path also clears .ref
testURI.path = pathWithSuffix;
do_info("testing that clearing path from " +
pathWithSuffix + " also clears .ref");
testURI.path = "";
do_check_eq(testURI.ref, "");
}
}
// Tests that normally-mutable properties can't be modified on
// special URIs that are known to be immutable.
function do_test_immutable(aTest) {
do_check_true(aTest.immutable);
var URI = NetUtil.newURI(aTest.spec);
// All the non-readonly attributes on nsIURI.idl:
var propertiesToCheck = ["spec", "scheme", "userPass", "username", "password",
"hostPort", "host", "port", "path", "ref"];
propertiesToCheck.forEach(function(aProperty) {
var threw = false;
try {
URI[aProperty] = "anothervalue";
} catch(e) {
threw = true;
}
do_info("testing that setting '" + aProperty +
"' on immutable URI '" + aTest.spec + "' will throw");
do_check_true(threw);
});
}
// TEST MAIN FUNCTION
// ------------------
function run_test()
{
gTests.forEach(function(aTest) {
// Check basic URI functionality
do_test_uri_basic(aTest);
// Try adding various #-prefixed strings to the ends of the URIs
gHashSuffixes.forEach(function(aSuffix) {
do_test_uri_with_hash_suffix(aTest, aSuffix);
if (!aTest.immutable) {
do_test_mutate_ref(aTest, aSuffix);
}
});
// For URIs that we couldn't mutate above due to them being immutable:
// Now we check that they're actually immutable.
if (aTest.immutable) {
do_test_immutable(aTest);
}
});
}