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 michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: const PREF_DEPRECATION_WARNINGS = "devtools.errorconsole.deprecation_warnings"; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm", this); michael@0: Cu.import("resource://gre/modules/Deprecated.jsm", this); michael@0: michael@0: // Using this named functions to test deprecation and the properly logged michael@0: // callstacks. michael@0: function basicDeprecatedFunction () { michael@0: Deprecated.warning("this method is deprecated.", "http://example.com"); michael@0: return true; michael@0: } michael@0: michael@0: function deprecationFunctionBogusCallstack () { michael@0: Deprecated.warning("this method is deprecated.", "http://example.com", { michael@0: caller: {} michael@0: }); michael@0: return true; michael@0: } michael@0: michael@0: function deprecationFunctionCustomCallstack () { michael@0: // Get the nsIStackFrame that will contain the name of this function. michael@0: function getStack () { michael@0: return Components.stack; michael@0: } michael@0: Deprecated.warning("this method is deprecated.", "http://example.com", michael@0: getStack()); michael@0: return true; michael@0: } michael@0: michael@0: let tests = [ michael@0: // Test deprecation warning without passing the callstack. michael@0: { michael@0: deprecatedFunction: basicDeprecatedFunction, michael@0: expectedObservation: function (aMessage) { michael@0: testAMessage(aMessage); michael@0: ok(aMessage.errorMessage.indexOf("basicDeprecatedFunction") > 0, michael@0: "Callstack is correctly logged."); michael@0: } michael@0: }, michael@0: // Test a reported error when URL to documentation is not passed. michael@0: { michael@0: deprecatedFunction: function () { michael@0: Deprecated.warning("this method is deprecated."); michael@0: return true; michael@0: }, michael@0: expectedObservation: function (aMessage) { michael@0: ok(aMessage.errorMessage.indexOf("must provide a URL") > 0, michael@0: "Deprecation warning logged an empty URL argument."); michael@0: } michael@0: }, michael@0: // Test deprecation with a bogus callstack passed as an argument (it will be michael@0: // replaced with the current call stack). michael@0: { michael@0: deprecatedFunction: deprecationFunctionBogusCallstack, michael@0: expectedObservation: function (aMessage) { michael@0: testAMessage(aMessage); michael@0: ok(aMessage.errorMessage.indexOf("deprecationFunctionBogusCallstack") > 0, michael@0: "Callstack is correctly logged."); michael@0: } michael@0: }, michael@0: // When pref is unset Deprecated.warning should not log anything. michael@0: { michael@0: deprecatedFunction: basicDeprecatedFunction, michael@0: expectedObservation: null, michael@0: // Set pref to false. michael@0: logWarnings: false michael@0: }, michael@0: // Test deprecation with a valid custom callstack passed as an argument. michael@0: { michael@0: deprecatedFunction: deprecationFunctionCustomCallstack, michael@0: expectedObservation: function (aMessage) { michael@0: testAMessage(aMessage); michael@0: ok(aMessage.errorMessage.indexOf("deprecationFunctionCustomCallstack") > 0, michael@0: "Callstack is correctly logged."); michael@0: }, michael@0: // Set pref to true. michael@0: logWarnings: true michael@0: }]; michael@0: michael@0: // Which test are we running now? michael@0: let idx = -1; michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: michael@0: // Check if Deprecated is loaded. michael@0: ok(Deprecated, "Deprecated object exists"); michael@0: michael@0: nextTest(); michael@0: } michael@0: michael@0: // Test Consle Message attributes. michael@0: function testAMessage (aMessage) { michael@0: ok(aMessage.errorMessage.indexOf("DEPRECATION WARNING: " + michael@0: "this method is deprecated.") === 0, michael@0: "Deprecation is correctly logged."); michael@0: ok(aMessage.errorMessage.indexOf("http://example.com") > 0, michael@0: "URL is correctly logged."); michael@0: } michael@0: michael@0: function nextTest() { michael@0: idx++; michael@0: michael@0: if (idx == tests.length) { michael@0: finish(); michael@0: return; michael@0: } michael@0: michael@0: info("Running test #" + idx); michael@0: let test = tests[idx]; michael@0: michael@0: // Deprecation warnings will be logged only when the preference is set. michael@0: if (typeof test.logWarnings !== "undefined") { michael@0: Services.prefs.setBoolPref(PREF_DEPRECATION_WARNINGS, test.logWarnings); michael@0: } michael@0: michael@0: // Create a console listener. michael@0: let consoleListener = { michael@0: observe: function (aMessage) { michael@0: // Ignore unexpected messages. michael@0: if (!(aMessage instanceof Ci.nsIScriptError)) { michael@0: return; michael@0: } michael@0: if (aMessage.errorMessage.indexOf("DEPRECATION WARNING: ") < 0 && michael@0: aMessage.errorMessage.indexOf("must provide a URL") < 0) { michael@0: return; michael@0: } michael@0: ok(aMessage instanceof Ci.nsIScriptError, michael@0: "Deprecation log message is an instance of type nsIScriptError."); michael@0: michael@0: michael@0: if (test.expectedObservation === null) { michael@0: ok(false, "Deprecated warning not expected"); michael@0: } michael@0: else { michael@0: test.expectedObservation(aMessage); michael@0: } michael@0: michael@0: Services.console.unregisterListener(consoleListener); michael@0: executeSoon(nextTest); michael@0: } michael@0: }; michael@0: Services.console.registerListener(consoleListener); michael@0: test.deprecatedFunction(); michael@0: if (test.expectedObservation === null) { michael@0: executeSoon(function() { michael@0: Services.console.unregisterListener(consoleListener); michael@0: executeSoon(nextTest); michael@0: }); michael@0: } michael@0: }