diff options
Diffstat (limited to 'toolkit/components/places/tests/unit/test_null_interfaces.js')
-rw-r--r-- | toolkit/components/places/tests/unit/test_null_interfaces.js | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/unit/test_null_interfaces.js b/toolkit/components/places/tests/unit/test_null_interfaces.js new file mode 100644 index 0000000000..2ee7ffdc57 --- /dev/null +++ b/toolkit/components/places/tests/unit/test_null_interfaces.js @@ -0,0 +1,105 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 489872 to make sure passing nulls to nsNavHistory doesn't crash. + */ + +// Make an array of services to test, each specifying a class id, interface +// and an array of function names that don't throw when passed nulls +var testServices = [ + [ + "browser/nav-history-service;1", + ["nsINavHistoryService"], + [ + "queryStringToQuery", + "removePagesByTimeframe", + "removePagesFromHost", + "getObservers", + ], + ], + [ + "browser/nav-bookmarks-service;1", + ["nsINavBookmarksService"], + ["createFolder", "getObservers"], + ], + ["browser/favicon-service;1", ["nsIFaviconService"], []], + ["browser/tagging-service;1", ["nsITaggingService"], []], +]; +info(testServices.join("\n")); + +function run_test() { + for (let [cid, ifaces, nothrow] of testServices) { + info(`Running test with ${cid} ${ifaces.join(", ")} ${nothrow}`); + let s = Cc["@mozilla.org/" + cid].getService(Ci.nsISupports); + for (let iface of ifaces) { + s.QueryInterface(Ci[iface]); + } + + let okName = function(name) { + info(`Checking if function is okay to test: ${name}`); + let func = s[name]; + + let mesg = ""; + if (typeof func != "function") { + mesg = "Not a function!"; + } else if (!func.length) { + mesg = "No args needed!"; + } else if (name == "QueryInterface") { + mesg = "Ignore QI!"; + } + + if (mesg) { + info(`${mesg} Skipping: ${name}`); + return false; + } + + return true; + }; + + info(`Generating an array of functions to test service: ${s}`); + for (let n of Object.keys(s) + .filter(i => okName(i)) + .sort()) { + info(`\nTesting ${ifaces.join(", ")} function with null args: ${n}`); + + let func = s[n]; + let num = func.length; + info(`Generating array of nulls for #args: ${num}`); + let args = Array(num).fill(null); + + let tryAgain = true; + while (tryAgain) { + try { + info(`Calling with args: ${JSON.stringify(args)}`); + func.apply(s, args); + + info( + `The function did not throw! Is it one of the nothrow? ${nothrow}` + ); + Assert.notEqual(nothrow.indexOf(n), -1); + + info("Must have been an expected nothrow, so no need to try again"); + tryAgain = false; + } catch (ex) { + if (ex.result == Cr.NS_ERROR_ILLEGAL_VALUE) { + info(`Caught an expected exception: ${ex.name}`); + info("Moving on to the next test.."); + tryAgain = false; + } else if (ex.result == Cr.NS_ERROR_XPC_NEED_OUT_OBJECT) { + let pos = Number(ex.message.match(/object arg (\d+)/)[1]); + info(`Function call expects an out object at ${pos}`); + args[pos] = {}; + } else if (ex.result == Cr.NS_ERROR_NOT_IMPLEMENTED) { + info(`Method not implemented exception: ${ex.name}`); + info("Moving on to the next test.."); + tryAgain = false; + } else { + throw ex; + } + } + } + } + } +} |