diff --git a/dom/tests/unit/test_geolocation_reset_accuracy.js b/dom/tests/unit/test_geolocation_reset_accuracy.js index 75272ab7a04..abeee6e0351 100644 --- a/dom/tests/unit/test_geolocation_reset_accuracy.js +++ b/dom/tests/unit/test_geolocation_reset_accuracy.js @@ -97,6 +97,7 @@ function run_test() function stop_high_accuracy_watch() { geolocation.clearWatch(watchID2); check_results(); + do_test_finished(); } function check_results() diff --git a/toolkit/components/telemetry/TelemetryController.jsm b/toolkit/components/telemetry/TelemetryController.jsm index 750fbae6e92..fd9055383c6 100644 --- a/toolkit/components/telemetry/TelemetryController.jsm +++ b/toolkit/components/telemetry/TelemetryController.jsm @@ -155,6 +155,13 @@ this.TelemetryController = Object.freeze({ return Impl.setupTelemetry(true); }, + /** + * Used only for testing purposes. + */ + setupContent: function() { + return Impl.setupContentTelemetry(true); + }, + /** * Send a notification. */ @@ -689,6 +696,21 @@ let Impl = { return this._delayedInitTaskDeferred.promise; }, + /** + * This triggers basic telemetry initialization for content processes. + * @param {Boolean} [testing=false] True if we are in test mode, false otherwise. + */ + setupContentTelemetry: function (testing = false) { + this._testMode = testing; + + // We call |enableTelemetryRecording| here to make sure that Telemetry.canRecord* flags + // are in sync between chrome and content processes. + if (!this.enableTelemetryRecording()) { + this._log.trace("setupContentTelemetry - Content process recording disabled."); + return; + } + }, + // Do proper shutdown waiting and cleanup. _cleanupOnShutdown: Task.async(function*() { if (!this._initialized) { @@ -760,13 +782,8 @@ let Impl = { // profile-after-change is only registered for chrome processes. return this.setupTelemetry(); case "app-startup": - // app-startup is only registered for content processes. We call - // |enableTelemetryRecording| here to make sure that Telemetry.canRecord* flags - // are in sync between chrome and content processes. - if (!this.enableTelemetryRecording()) { - this._log.trace("observe - Content process recording disabled."); - return; - } + // app-startup is only registered for content processes. + return this.setupContentTelemetry(); break; } }, diff --git a/toolkit/components/telemetry/TelemetrySession.jsm b/toolkit/components/telemetry/TelemetrySession.jsm index d4a16cd2aaa..e66640452f3 100644 --- a/toolkit/components/telemetry/TelemetrySession.jsm +++ b/toolkit/components/telemetry/TelemetrySession.jsm @@ -58,7 +58,7 @@ const MIN_SUBSESSION_LENGTH_MS = 10 * 60 * 1000; #expand const HISTOGRAMS_FILE_VERSION = "__HISTOGRAMS_FILE_VERSION__"; const LOGGER_NAME = "Toolkit.Telemetry"; -const LOGGER_PREFIX = "TelemetrySession::"; +const LOGGER_PREFIX = "TelemetrySession" + (IS_CONTENT_PROCESS ? "#content::" : "::"); const PREF_BRANCH = "toolkit.telemetry."; const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID"; @@ -775,7 +775,7 @@ this.TelemetrySession = Object.freeze({ let Impl = { _histograms: {}, _initialized: false, - _log: null, + _logger: null, _prevValues: {}, // Regex that matches histograms we care about during startup. // Keep this in sync with gen-histogram-bucket-ranges.py. @@ -817,6 +817,13 @@ let Impl = { // Used to serialize session state writes to disk. _stateSaveSerializer: new SaveSerializer(), + get _log() { + if (!this._logger) { + this._logger = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, LOGGER_PREFIX); + } + return this._logger; + }, + /** * Gets a series of simple measurements (counters). At the moment, this * only returns startup data from nsIAppStartup.getStartupInfo(). @@ -1415,10 +1422,6 @@ let Impl = { */ setupChromeProcess: function setupChromeProcess(testing) { this._initStarted = true; - if (testing && !this._log) { - this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, LOGGER_PREFIX); - } - this._log.trace("setupChromeProcess"); if (this._delayedInitTask) { @@ -1718,10 +1721,6 @@ let Impl = { * This observer drives telemetry. */ observe: function (aSubject, aTopic, aData) { - if (!this._log) { - this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, LOGGER_PREFIX); - } - // Prevent the cycle collector begin topic from cluttering the log. if (aTopic != TOPIC_CYCLE_COLLECTOR_BEGIN) { this._log.trace("observe - " + aTopic + " notified."); diff --git a/toolkit/components/telemetry/tests/unit/head.js b/toolkit/components/telemetry/tests/unit/head.js index ec315b83d28..e2a353d2229 100644 --- a/toolkit/components/telemetry/tests/unit/head.js +++ b/toolkit/components/telemetry/tests/unit/head.js @@ -186,12 +186,14 @@ function promiseRejects(promise) { return promise.then(() => false, () => true); } -// Set logging preferences for all the tests. -Services.prefs.setCharPref("toolkit.telemetry.log.level", "Trace"); -TelemetryController.initLogging(); +if (runningInParent) { + // Set logging preferences for all the tests. + Services.prefs.setCharPref("toolkit.telemetry.log.level", "Trace"); + // Telemetry archiving should be on. + Services.prefs.setBoolPref("toolkit.telemetry.archive.enabled", true); +} -// Telemetry archiving should be on. -Services.prefs.setBoolPref("toolkit.telemetry.archive.enabled", true); +TelemetryController.initLogging(); // Avoid timers interrupting test behavior. fakeSchedulerTimer(() => {}, () => {}); diff --git a/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js b/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js new file mode 100644 index 00000000000..2c29c567bf0 --- /dev/null +++ b/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js @@ -0,0 +1,89 @@ + +Cu.import("resource://gre/modules/TelemetryController.jsm", this); +Cu.import("resource://gre/modules/TelemetrySession.jsm", this); +Cu.import("resource://gre/modules/PromiseUtils.jsm", this); + +const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); + +const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload"; + +const PLATFORM_VERSION = "1.9.2"; +const APP_VERSION = "1"; +const APP_ID = "xpcshell@tests.mozilla.org"; +const APP_NAME = "XPCShell"; + +function run_child_test() { + // Setup histograms with some fixed values. + let flagHist = Telemetry.getHistogramById("TELEMETRY_TEST_FLAG"); + flagHist.add(1); + let countHist = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT"); + countHist.add(); + countHist.add(); + + let flagKeyed = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_FLAG"); + flagKeyed.add("a", 1); + flagKeyed.add("b", 1); + let countKeyed = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_COUNT"); + countKeyed.add("a"); + countKeyed.add("b"); + countKeyed.add("b"); + + // Check payload values. + const payload = TelemetrySession.getPayload("test-ping"); + check_histogram_values(payload); +} + +function check_histogram_values(payload) { + const hs = payload.histograms; + Assert.ok("TELEMETRY_TEST_COUNT" in hs, "Should have count test histogram."); + Assert.ok("TELEMETRY_TEST_FLAG" in hs, "Should have flag test histogram."); + Assert.equal(hs["TELEMETRY_TEST_COUNT"].sum, 2, + "Count test histogram should have the right value."); + Assert.equal(hs["TELEMETRY_TEST_FLAG"].sum, 1, + "Flag test histogram should have the right value."); + + const kh = payload.keyedHistograms; + Assert.ok("TELEMETRY_TEST_KEYED_COUNT" in kh, "Should have keyed count test histogram."); + Assert.ok("TELEMETRY_TEST_KEYED_FLAG" in kh, "Should have keyed flag test histogram."); + Assert.equal(kh["TELEMETRY_TEST_KEYED_COUNT"]["a"].sum, 1, + "Keyed count test histogram should have the right value."); + Assert.equal(kh["TELEMETRY_TEST_KEYED_COUNT"]["b"].sum, 2, + "Keyed count test histogram should have the right value."); + Assert.equal(kh["TELEMETRY_TEST_KEYED_FLAG"]["a"].sum, 1, + "Keyed flag test histogram should have the right value."); + Assert.equal(kh["TELEMETRY_TEST_KEYED_FLAG"]["b"].sum, 1, + "Keyed flag test histogram should have the right value."); +} + +add_task(function*() { + if (!runningInParent) { + TelemetryController.setupContent(); + run_child_test(); + return; + } + + // Setup. + do_get_profile(true); + loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION); + Services.prefs.setBoolPref("toolkit.telemetry.enabled", true); + yield TelemetryController.setup(); + yield TelemetrySession.setup(); + + // Run test in child and wait until it is finished. + yield run_test_in_child("test_ChildHistograms.js"); + + // Gather payload from child. + let promiseMessage = do_await_remote_message(MESSAGE_TELEMETRY_PAYLOAD); + TelemetrySession.requestChildPayloads(); + yield promiseMessage; + + // Check child payload. + const payload = TelemetrySession.getPayload("test-ping"); + Assert.ok("childPayloads" in payload, "Should have child payloads."); + Assert.equal(payload.childPayloads.length, 1, "Should have received one child payload so far."); + Assert.ok("histograms" in payload.childPayloads[0], "Child payload should have histograms."); + Assert.ok("keyedHistograms" in payload.childPayloads[0], "Child payload should have keyed histograms."); + check_histogram_values(payload.childPayloads[0]); + + do_test_finished(); +}); diff --git a/toolkit/components/telemetry/tests/unit/xpcshell.ini b/toolkit/components/telemetry/tests/unit/xpcshell.ini index 03ad74a8b0a..219cda4ab2c 100644 --- a/toolkit/components/telemetry/tests/unit/xpcshell.ini +++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini @@ -50,3 +50,5 @@ skip-if = os == "android" # Disabled due to intermittent orange on Android skip-if = android_version == "18" [test_ThreadHangStats.js] run-sequentially = Bug 1046307, test can fail intermittently when CPU load is high +[test_ChildHistograms.js] +skip-if = os == "android"