diff options
Diffstat (limited to 'netwerk/test/unit/test_URIs2.js')
-rw-r--r-- | netwerk/test/unit/test_URIs2.js | 693 |
1 files changed, 693 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_URIs2.js b/netwerk/test/unit/test_URIs2.js new file mode 100644 index 000000000..201473f58 --- /dev/null +++ b/netwerk/test/unit/test_URIs2.js @@ -0,0 +1,693 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +Components.utils.import("resource://gre/modules/NetUtil.jsm"); + +var gIoService = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + + +// Run by: cd objdir; make -C netwerk/test/ xpcshell-tests +// or: cd objdir; make SOLO_FILE="test_URIs2.js" -C netwerk/test/ check-one + +// This is a clone of test_URIs.js, with a different set of test data in gTests. +// The original test data in test_URIs.js was split between test_URIs and test_URIs2.js +// because test_URIs.js was running for too long on slow platforms, causing +// intermittent timeouts. + +// Relevant RFCs: 1738, 1808, 2396, 3986 (newer than the code) +// http://greenbytes.de/tech/webdav/rfc3986.html#rfc.section.5.4 +// http://greenbytes.de/tech/tc/uris/ + +// TEST DATA +// --------- +var gTests = [ + { 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 }, + { spec: "http://www2.example.com/", + relativeURI: "a/b/c/d", + scheme: "http", + prePath: "http://www2.example.com", + path: "/a/b/c/d", + ref: "", + nsIURL: true, nsINestedURI: false }, + // relative URL testcases from http://greenbytes.de/tech/webdav/rfc3986.html#rfc.section.5.4 + { spec: "http://a/b/c/d;p?q", + relativeURI: "g:h", + scheme: "g", + prePath: "g:", + path: "h", + ref: "", + nsIURL: false, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g", + scheme: "http", + prePath: "http://a", + path: "/b/c/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "./g", + scheme: "http", + prePath: "http://a", + path: "/b/c/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g/", + scheme: "http", + prePath: "http://a", + path: "/b/c/g/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "/g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "?y", + scheme: "http", + prePath: "http://a", + path: "/b/c/d;p?y", + ref: "",// fix + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g?y", + scheme: "http", + prePath: "http://a", + path: "/b/c/g?y", + ref: "",// fix + specIgnoringRef: "http://a/b/c/g?y", + hasRef: false, + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "#s", + scheme: "http", + prePath: "http://a", + path: "/b/c/d;p?q#s", + ref: "s",// fix + specIgnoringRef: "http://a/b/c/d;p?q", + hasRef: true, + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g#s", + scheme: "http", + prePath: "http://a", + path: "/b/c/g#s", + ref: "s", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g?y#s", + scheme: "http", + prePath: "http://a", + path: "/b/c/g?y#s", + ref: "s", + nsIURL: true, nsINestedURI: false }, + /* + Bug xxxxxx - we return a path of b/c/;x + { spec: "http://a/b/c/d;p?q", + relativeURI: ";x", + scheme: "http", + prePath: "http://a", + path: "/b/c/d;x", + ref: "", + nsIURL: true, nsINestedURI: false }, + */ + { spec: "http://a/b/c/d;p?q", + relativeURI: "g;x", + scheme: "http", + prePath: "http://a", + path: "/b/c/g;x", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g;x?y#s", + scheme: "http", + prePath: "http://a", + path: "/b/c/g;x?y#s", + ref: "s", + nsIURL: true, nsINestedURI: false }, + /* + Can't easily specify a relative URI of "" to the test code + { spec: "http://a/b/c/d;p?q", + relativeURI: "", + scheme: "http", + prePath: "http://a", + path: "/b/c/d", + ref: "", + nsIURL: true, nsINestedURI: false }, + */ + { spec: "http://a/b/c/d;p?q", + relativeURI: ".", + scheme: "http", + prePath: "http://a", + path: "/b/c/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "./", + scheme: "http", + prePath: "http://a", + path: "/b/c/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "..", + scheme: "http", + prePath: "http://a", + path: "/b/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../", + scheme: "http", + prePath: "http://a", + path: "/b/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../g", + scheme: "http", + prePath: "http://a", + path: "/b/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../..", + scheme: "http", + prePath: "http://a", + path: "/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../../", + scheme: "http", + prePath: "http://a", + path: "/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../../g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + + // abnormal examples + { spec: "http://a/b/c/d;p?q", + relativeURI: "../../../g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "../../../../g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + + // coalesce + { spec: "http://a/b/c/d;p?q", + relativeURI: "/./g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "/../g", + scheme: "http", + prePath: "http://a", + path: "/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g.", + scheme: "http", + prePath: "http://a", + path: "/b/c/g.", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: ".g", + scheme: "http", + prePath: "http://a", + path: "/b/c/.g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g..", + scheme: "http", + prePath: "http://a", + path: "/b/c/g..", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "..g", + scheme: "http", + prePath: "http://a", + path: "/b/c/..g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: ".", + scheme: "http", + prePath: "http://a", + path: "/b/c/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "./../g", + scheme: "http", + prePath: "http://a", + path: "/b/g", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "./g/.", + scheme: "http", + prePath: "http://a", + path: "/b/c/g/", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g/./h", + scheme: "http", + prePath: "http://a", + path: "/b/c/g/h", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g/../h", + scheme: "http", + prePath: "http://a", + path: "/b/c/h", + ref: "",// fix + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g;x=1/./y", + scheme: "http", + prePath: "http://a", + path: "/b/c/g;x=1/y", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "http://a/b/c/d;p?q", + relativeURI: "g;x=1/../y", + scheme: "http", + prePath: "http://a", + path: "/b/c/y", + ref: "", + nsIURL: true, nsINestedURI: false }, + // protocol-relative http://tools.ietf.org/html/rfc3986#section-4.2 + { spec: "http://www2.example.com/", + relativeURI: "//www3.example2.com/bar", + scheme: "http", + prePath: "http://www3.example2.com", + path: "/bar", + ref: "", + nsIURL: true, nsINestedURI: false }, + { spec: "https://www2.example.com/", + relativeURI: "//www3.example2.com/bar", + scheme: "https", + prePath: "https://www3.example2.com", + path: "/bar", + ref: "", + nsIURL: true, 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) { + if (aTest[aPropertyName]) { + 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; + + do_info("Basic tests for " + aTest.spec + " relative URI: " + aTest.relativeURI); + + try { + URI = NetUtil.newURI(aTest.spec); + } catch(e) { + do_info("Caught error on parse of" + aTest.spec + " Error: " + e.result); + if (aTest.fail) { + do_check_eq(e.result, aTest.result); + return; + } + do_throw(e.result); + } + + if (aTest.relativeURI) { + var relURI; + + try { + relURI = gIoService.newURI(aTest.relativeURI, null, URI); + } catch (e) { + do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result); + if (aTest.relativeFail) { + do_check_eq(e.result, aTest.relativeFail); + return; + } + do_throw(e.result); + } + do_info("relURI.path = " + relURI.path + ", was " + URI.path); + URI = relURI; + do_info("URI.path now = " + URI.path); + } + + // Sanity-check + do_info("testing " + aTest.spec + " equals a clone of itself"); + do_check_uri_eq(URI, URI.clone()); + do_check_uri_eqExceptRef(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"); + do_check_property(aTest, URI, "port"); + do_check_property(aTest, URI, "username"); + do_check_property(aTest, URI, "password"); + do_check_property(aTest, URI, "host"); + do_check_property(aTest, URI, "specIgnoringRef"); + if ("hasRef" in aTest) { + do_info("testing hasref: " + aTest.hasRef + " vs " + URI.hasRef); + do_check_eq(aTest.hasRef, URI.hasRef); + } +} + +// 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 origURI = NetUtil.newURI(aTest.spec); + var testURI; + + if (aTest.relativeURI) { + try { + origURI = gIoService.newURI(aTest.relativeURI, null, origURI); + } catch (e) { + do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result); + return; + } + try { + testURI = gIoService.newURI(aSuffix, null, origURI); + } catch (e) { + do_info("Caught error adding suffix to " + aTest.spec + " + " + aTest.relativeURI + ", suffix " + aSuffix + " Error: " + e.result); + return; + } + } else { + testURI = NetUtil.newURI(aTest.spec + aSuffix); + } + + 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"); + + 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_check_eq(testURI.hasRef, true); + + if (!origURI.ref) { + // These tests fail if origURI has a ref + do_info("testing cloneIgnoringRef on " + testURI.spec + + " is equal to no-ref version but not equal to ref version"); + var cloneNoRef = testURI.cloneIgnoringRef(); + do_check_uri_eq(cloneNoRef, origURI); + do_check_false(cloneNoRef.equals(testURI)); + } + + do_check_property(aTest, testURI, "scheme"); + do_check_property(aTest, testURI, "prePath"); + if (!origURI.ref) { + // These don't work if it's a ref already because '+' doesn't give the right result + 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); + + // 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); + + if (!aTest.relativeURI) { + // TODO: These tests don't work as-is for relative URIs. + + // 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 = ""; + 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() +{ + // UTF-8 check - From bug 622981 + // ASCII + let base = gIoService.newURI("http://example.org/xenia?", null, null); + let resolved = gIoService.newURI("?x", null, base); + let expected = gIoService.newURI("http://example.org/xenia?x", + null, null); + do_info("Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec); + do_check_true(resolved.equals(expected)); + + // UTF-8 character "è" + // Bug 622981 was triggered by an empty query string + base = gIoService.newURI("http://example.org/xènia?", null, null); + resolved = gIoService.newURI("?x", null, base); + expected = gIoService.newURI("http://example.org/xènia?x", + null, null); + do_info("Bug 662981: UTF8 - comparing " + resolved.spec + " and " + expected.spec); + do_check_true(resolved.equals(expected)); + + gTests.forEach(function(aTest) { + // Check basic URI functionality + do_test_uri_basic(aTest); + + if (!aTest.fail) { + // 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); + } + } + }); +} |