michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: Cu.import("resource://gre/modules/Log.jsm"); michael@0: Cu.import("resource://services-common/utils.js"); michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: Cu.import("resource://testing-common/services-common/logging.js"); michael@0: michael@0: let btoa = Cu.import("resource://gre/modules/Log.jsm").btoa; michael@0: let atob = Cu.import("resource://gre/modules/Log.jsm").atob; michael@0: michael@0: function do_check_empty(obj) { michael@0: do_check_attribute_count(obj, 0); michael@0: } michael@0: michael@0: function do_check_attribute_count(obj, c) { michael@0: do_check_eq(c, Object.keys(obj).length); michael@0: } michael@0: michael@0: function do_check_throws(aFunc, aResult, aStack) { michael@0: if (!aStack) { michael@0: try { michael@0: // We might not have a 'Components' object. michael@0: aStack = Components.stack.caller; michael@0: } catch (e) {} michael@0: } michael@0: michael@0: try { michael@0: aFunc(); michael@0: } catch (e) { michael@0: do_check_eq(e.result, aResult, aStack); michael@0: return; michael@0: } michael@0: do_throw("Expected result " + aResult + ", none thrown.", aStack); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Test whether specified function throws exception with expected michael@0: * result. michael@0: * michael@0: * @param func michael@0: * Function to be tested. michael@0: * @param message michael@0: * Message of expected exception. null for no throws. michael@0: */ michael@0: function do_check_throws_message(aFunc, aResult) { michael@0: try { michael@0: aFunc(); michael@0: } catch (e) { michael@0: do_check_eq(e.message, aResult); michael@0: return; michael@0: } michael@0: do_throw("Expected an error, none thrown."); michael@0: } michael@0: michael@0: /** michael@0: * Print some debug message to the console. All arguments will be printed, michael@0: * separated by spaces. michael@0: * michael@0: * @param [arg0, arg1, arg2, ...] michael@0: * Any number of arguments to print out michael@0: * @usage _("Hello World") -> prints "Hello World" michael@0: * @usage _(1, 2, 3) -> prints "1 2 3" michael@0: */ michael@0: let _ = function(some, debug, text, to) print(Array.slice(arguments).join(" ")); michael@0: michael@0: function httpd_setup (handlers, port=-1) { michael@0: let server = new HttpServer(); michael@0: for (let path in handlers) { michael@0: server.registerPathHandler(path, handlers[path]); michael@0: } michael@0: try { michael@0: server.start(port); michael@0: } catch (ex) { michael@0: _("=========================================="); michael@0: _("Got exception starting HTTP server on port " + port); michael@0: _("Error: " + CommonUtils.exceptionStr(ex)); michael@0: _("Is there a process already listening on port " + port + "?"); michael@0: _("=========================================="); michael@0: do_throw(ex); michael@0: } michael@0: michael@0: // Set the base URI for convenience. michael@0: let i = server.identity; michael@0: server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort; michael@0: michael@0: return server; michael@0: } michael@0: michael@0: function httpd_handler(statusCode, status, body) { michael@0: return function handler(request, response) { michael@0: _("Processing request"); michael@0: // Allow test functions to inspect the request. michael@0: request.body = readBytesFromInputStream(request.bodyInputStream); michael@0: handler.request = request; michael@0: michael@0: response.setStatusLine(request.httpVersion, statusCode, status); michael@0: if (body) { michael@0: response.bodyOutputStream.write(body, body.length); michael@0: } michael@0: }; michael@0: } michael@0: michael@0: /* michael@0: * Read bytes string from an nsIInputStream. If 'count' is omitted, michael@0: * all available input is read. michael@0: */ michael@0: function readBytesFromInputStream(inputStream, count) { michael@0: return CommonUtils.readBytesFromInputStream(inputStream, count); michael@0: } michael@0: michael@0: /* michael@0: * Ensure exceptions from inside callbacks leads to test failures. michael@0: */ michael@0: function ensureThrows(func) { michael@0: return function() { michael@0: try { michael@0: func.apply(this, arguments); michael@0: } catch (ex) { michael@0: do_throw(ex); michael@0: } michael@0: }; michael@0: } michael@0: michael@0: /** michael@0: * Proxy auth helpers. michael@0: */ michael@0: michael@0: /** michael@0: * Fake a PAC to prompt a channel replacement. michael@0: */ michael@0: let PACSystemSettings = { michael@0: CID: Components.ID("{5645d2c1-d6d8-4091-b117-fe7ee4027db7}"), michael@0: contractID: "@mozilla.org/system-proxy-settings;1", michael@0: michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory, michael@0: Ci.nsISystemProxySettings]), michael@0: michael@0: createInstance: function createInstance(outer, iid) { michael@0: if (outer) { michael@0: throw Cr.NS_ERROR_NO_AGGREGATION; michael@0: } michael@0: return this.QueryInterface(iid); michael@0: }, michael@0: michael@0: lockFactory: function lockFactory(lock) { michael@0: throw Cr.NS_ERROR_NOT_IMPLEMENTED; michael@0: }, michael@0: michael@0: // Replace this URI for each test to avoid caching. We want to ensure that michael@0: // each test gets a completely fresh setup. michael@0: mainThreadOnly: true, michael@0: PACURI: null, michael@0: getProxyForURI: function getProxyForURI(aURI) { michael@0: throw Cr.NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: }; michael@0: michael@0: function installFakePAC() { michael@0: _("Installing fake PAC."); michael@0: Cm.nsIComponentRegistrar michael@0: .registerFactory(PACSystemSettings.CID, michael@0: "Fake system proxy-settings", michael@0: PACSystemSettings.contractID, michael@0: PACSystemSettings); michael@0: } michael@0: michael@0: function uninstallFakePAC() { michael@0: _("Uninstalling fake PAC."); michael@0: let CID = PACSystemSettings.CID; michael@0: Cm.nsIComponentRegistrar.unregisterFactory(CID, PACSystemSettings); michael@0: } michael@0: michael@0: // Many tests do service.startOver() and don't expect the provider type to michael@0: // change (whereas by default, a startOver will do exactly that so FxA is michael@0: // subsequently used). The tests that know how to deal with michael@0: // the Firefox Accounts identity hack things to ensure that still works. michael@0: function ensureStartOverKeepsIdentity() { michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", true); michael@0: do_register_cleanup(function() { michael@0: Services.prefs.clearUserPref("services.sync-testing.startOverKeepIdentity"); michael@0: }); michael@0: } michael@0: ensureStartOverKeepsIdentity();