gecko-dev/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js
Mike Conley bd5f8d5d32 Bug 1277644 - Make sure browser_Addons_sample test add-on tests CPOWs when it is supposed to. r=Yoric
browser_Addons_sample is used by the browser_AddonWatcher.js test to make sure
we can properly detect when an add-on consumes a bunch of CPU or does a lot of
CPOW traffic.

There's a race condition in the add-on where what is supposed to be a CPOW
might not always be a CPOW, so when we try to cause a bunch of CPOW
traffic, we don't get the expected performance warnings.

This makes sure that when we try to simulate CPOW usage, we do it
with an actual CPOW.

Additionally, this commit also includes the unpacked source of the
add-on, which before wasn't in the tree. I've also taken the liberty
of bumping the add-on version and signing it.

MozReview-Commit-ID: GICLYpi8Kon

--HG--
extra : rebase_source : bc9537c701335806d4845113910b03fadadb5b77
2016-05-29 12:00:50 -04:00

160 lines
6.1 KiB
JavaScript

/* 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()
});
let freezeThreshold = Preferences.get("browser.addon-watch.freeze-threshold-micros", /* 5 seconds */ 5000000);
let jankThreshold = Preferences.get("browser.addon-watch.jank-threshold-micros", /* 256 ms == 8 frames*/ 256000);
let occurrencesBetweenAlerts = Preferences.get("browser.addon-watch.occurrences-between-alerts", 3);
let delayBetweenAlerts = Preferences.get("browser.addon-watch.delay-between-alerts-ms", 6 * 3600 * 1000 /* 6h */);
let delayBetweenFreezeAlerts = Preferences.get("browser.addon-watch.delay-between-freeze-alerts-ms", 2 * 60 * 1000 /* 2 min */);
let prescriptionDelay = Preferences.get("browser.addon-watch.prescription-delay", 5 * 60 * 1000 /* 5 minutes */);
let highestNumberOfAddonsToReport = Preferences.get("browser.addon-watch.max-simultaneous-reports", 1);
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,
});
});