diff options
Diffstat (limited to 'toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js')
-rw-r--r-- | toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js b/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js new file mode 100644 index 000000000..b4e80faa7 --- /dev/null +++ b/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js @@ -0,0 +1,151 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests for AddonWatcher.jsm + +"use strict"; + +requestLongerTimeout(2); + +Cu.import("resource://gre/modules/Promise.jsm", this); +Cu.import("resource://gre/modules/AddonManager.jsm", this); +Cu.import("resource://gre/modules/Services.jsm", this); + +const ADDON_URL = "http://example.com/browser/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample.xpi"; +const ADDON_ID = "addonwatcher-test@mozilla.com"; + +add_task(function* init() { + info("Installing test add-on"); + let installer = yield new Promise(resolve => AddonManager.getInstallForURL(ADDON_URL, resolve, "application/x-xpinstall")); + if (installer.error) { + throw installer.error; + } + let installed = new Promise((resolve, reject) => installer.addListener({ + onInstallEnded: (_, addon) => resolve(addon), + onInstallFailed: reject, + onDownloadFailed: reject + })); + + // We also need to wait for the add-on to report that it's ready + // to be used in the test. + let ready = TestUtils.topicObserved("test-addonwatcher-ready"); + installer.install(); + + info("Waiting for installation to terminate"); + let addon = yield installed; + + yield ready; + + registerCleanupFunction(() => { + info("Uninstalling test add-on"); + addon.uninstall() + }); + + Preferences.set("browser.addon-watch.warmup-ms", 0); + Preferences.set("browser.addon-watch.freeze-threshold-micros", 0); + Preferences.set("browser.addon-watch.jank-threshold-micros", 0); + Preferences.set("browser.addon-watch.occurrences-between-alerts", 0); + Preferences.set("browser.addon-watch.delay-between-alerts-ms", 0); + Preferences.set("browser.addon-watch.delay-between-freeze-alerts-ms", 0); + Preferences.set("browser.addon-watch.max-simultaneous-reports", 10000); + Preferences.set("browser.addon-watch.deactivate-after-idle-ms", 100000000); + registerCleanupFunction(() => { + for (let k of [ + "browser.addon-watch.warmup-ms", + "browser.addon-watch.freeze-threshold-micros", + "browser.addon-watch.jank-threshold-micros", + "browser.addon-watch.occurrences-between-alerts", + "browser.addon-watch.delay-between-alerts-ms", + "browser.addon-watch.delay-between-freeze-alerts-ms", + "browser.addon-watch.max-simultaneous-reports", + "browser.addon-watch.deactivate-after-idle-ms" + ]) { + Preferences.reset(k); + } + }); + + let oldCanRecord = Services.telemetry.canRecordExtended; + Services.telemetry.canRecordExtended = true; + AddonWatcher.init(); + + registerCleanupFunction(function () { + AddonWatcher.paused = true; + Services.telemetry.canRecordExtended = oldCanRecord; + }); +}); + +// Utility function to burn some resource, trigger a reaction of the add-on watcher +// and check both its notification and telemetry. +let burn_rubber = Task.async(function*({histogramName, topic, expectedMinSum}) { + let detected = false; + let observer = (_, topic, id) => { + Assert.equal(id, ADDON_ID, "The add-on watcher has detected the misbehaving addon"); + detected = true; + }; + + try { + info("Preparing add-on watcher"); + + Services.obs.addObserver(observer, AddonWatcher.TOPIC_SLOW_ADDON_DETECTED, false); + + let histogram = Services.telemetry.getKeyedHistogramById(histogramName); + histogram.clear(); + let snap1 = histogram.snapshot(ADDON_ID); + Assert.equal(snap1.sum, 0, `Histogram ${histogramName} is initially empty for the add-on`); + + let histogramUpdated = false; + do { + info(`Burning some CPU with ${topic}. This should cause an add-on watcher notification`); + yield new Promise(resolve => setTimeout(resolve, 100)); + Services.obs.notifyObservers(null, topic, ""); + yield new Promise(resolve => setTimeout(resolve, 100)); + + let snap2 = histogram.snapshot(ADDON_ID); + histogramUpdated = snap2.sum > 0; + info(`For the moment, histogram ${histogramName} shows ${snap2.sum} => ${histogramUpdated}`); + info(`For the moment, we have ${detected?"":"NOT "}detected the slow add-on`); + } while (!histogramUpdated || !detected); + + let snap3 = histogram.snapshot(ADDON_ID); + Assert.ok(snap3.sum >= expectedMinSum, `Histogram ${histogramName} recorded a gravity of ${snap3.sum}, expecting at least ${expectedMinSum}.`); + } finally { + Services.obs.removeObserver(observer, AddonWatcher.TOPIC_SLOW_ADDON_DETECTED); + } +}); + +// Test that burning CPU will cause the add-on watcher to notice that +// the add-on is misbehaving. +add_task(function* test_burn_CPU() { + yield burn_rubber({ + histogramName: "PERF_MONITORING_SLOW_ADDON_JANK_US", + topic: "test-addonwatcher-burn-some-cpu", + expectedMinSum: 7, + }); +}); + +// Test that burning content CPU will cause the add-on watcher to notice that +// the add-on is misbehaving. +/* +Blocked by bug 1227283. +add_task(function* test_burn_content_CPU() { + yield burn_rubber({ + histogramName: "PERF_MONITORING_SLOW_ADDON_JANK_US", + topic: "test-addonwatcher-burn-some-content-cpu", + expectedMinSum: 7, + }); +}); +*/ + +// Test that burning CPOW will cause the add-on watcher to notice that +// the add-on is misbehaving. +add_task(function* test_burn_CPOW() { + if (!gMultiProcessBrowser) { + info("This is a single-process Firefox, we can't test for CPOW"); + return; + } + yield burn_rubber({ + histogramName: "PERF_MONITORING_SLOW_ADDON_CPOW_US", + topic: "test-addonwatcher-burn-some-cpow", + expectedMinSum: 400, + }); +}); |