summaryrefslogtreecommitdiffstats
path: root/comm/mail/base/test/performance/browser_preferences_usage.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/base/test/performance/browser_preferences_usage.js')
-rw-r--r--comm/mail/base/test/performance/browser_preferences_usage.js177
1 files changed, 177 insertions, 0 deletions
diff --git a/comm/mail/base/test/performance/browser_preferences_usage.js b/comm/mail/base/test/performance/browser_preferences_usage.js
new file mode 100644
index 0000000000..e770b12b46
--- /dev/null
+++ b/comm/mail/base/test/performance/browser_preferences_usage.js
@@ -0,0 +1,177 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+if (SpecialPowers.useRemoteSubframes) {
+ requestLongerTimeout(2);
+}
+
+const DEFAULT_PROCESS_COUNT = Services.prefs
+ .getDefaultBranch(null)
+ .getIntPref("dom.ipc.processCount");
+
+/**
+ * A test that checks whether any preference getter from the given list
+ * of stats was called more often than the max parameter.
+ *
+ * @param {Array} stats - an array of [prefName, accessCount] tuples
+ * @param {number} max - the maximum number of times any of the prefs should
+ * have been called.
+ * @param {object} knownProblematicPrefs (optional) - an object that defines
+ * prefs that should be exempt from checking the
+ * maximum access. It looks like the following:
+ *
+ * pref_name: {
+ * min: [Number] the minimum amount of times this should have
+ * been called (to avoid keeping around dead items)
+ * max: [Number] the maximum amount of times this should have
+ * been called (to avoid this creeping up further)
+ * }
+ */
+function checkPrefGetters(stats, max, knownProblematicPrefs = {}) {
+ let getterStats = Object.entries(stats).sort(
+ ([, val1], [, val2]) => val2 - val1
+ );
+
+ // Clone the list to be able to delete entries to check if we
+ // forgot any later on.
+ knownProblematicPrefs = Object.assign({}, knownProblematicPrefs);
+
+ for (let [pref, count] of getterStats) {
+ let prefLimits = knownProblematicPrefs[pref];
+ if (!prefLimits) {
+ Assert.lessOrEqual(
+ count,
+ max,
+ `${pref} should not be accessed more than ${max} times.`
+ );
+ } else {
+ // Still record how much this pref was accessed even if we don't do any real assertions.
+ if (!prefLimits.min && !prefLimits.max) {
+ info(
+ `${pref} should not be accessed more than ${max} times and was accessed ${count} times.`
+ );
+ }
+
+ if (prefLimits.min) {
+ Assert.lessOrEqual(
+ prefLimits.min,
+ count,
+ `${pref} should be accessed at least ${prefLimits.min} times.`
+ );
+ }
+ if (prefLimits.max) {
+ Assert.lessOrEqual(
+ count,
+ prefLimits.max,
+ `${pref} should be accessed at most ${prefLimits.max} times.`
+ );
+ }
+ delete knownProblematicPrefs[pref];
+ }
+ }
+
+ // This pref will be accessed by mozJSComponentLoader when loading modules,
+ // which fails TV runs since they run the test multiple times without restarting.
+ // We just ignore this pref, since it's for testing only anyway.
+ if (knownProblematicPrefs["browser.startup.record"]) {
+ delete knownProblematicPrefs["browser.startup.record"];
+ }
+
+ let unusedPrefs = Object.keys(knownProblematicPrefs);
+ is(
+ unusedPrefs.length,
+ 0,
+ `Should have accessed all known problematic prefs. Remaining: ${unusedPrefs}`
+ );
+}
+
+/**
+ * A helper function to read preference access data
+ * using the Services.prefs.readStats() function.
+ */
+function getPreferenceStats() {
+ let stats = {};
+ Services.prefs.readStats((key, value) => (stats[key] = value));
+ return stats;
+}
+
+add_task(async function debug_only() {
+ ok(AppConstants.DEBUG, "You need to run this test on a debug build.");
+});
+
+// Just checks how many prefs were accessed during startup.
+add_task(async function startup() {
+ let max = 40;
+
+ let knownProblematicPrefs = {
+ // These are all similar values to Firefox, check with the equivalent
+ // file in Firefox.
+ "browser.startup.record": {
+ // This pref is accessed in Nighly and debug builds only.
+ min: 200,
+ max: 400,
+ },
+ "network.loadinfo.skip_type_assertion": {
+ // This is accessed in debug only.
+ },
+ // Bug 944367: All gloda logs are controlled by one pref.
+ "gloda.loglevel": {
+ min: 10,
+ max: 70,
+ },
+ };
+
+ // These preferences are used in PresContext or layout areas and all have a
+ // similar number of errors - probably being loaded in the same component.
+ let prefsUsedInLayout = [
+ "browser.display.auto_quality_min_font_size",
+ "dom.send_after_paint_to_content",
+ "image.animation_mode",
+ "layout.reflow.dumpframebyframecounts",
+ "layout.reflow.dumpframecounts",
+ "layout.reflow.showframecounts",
+ "layout.scrollbar.side",
+ ];
+
+ for (let pref of prefsUsedInLayout) {
+ knownProblematicPrefs[pref] = {
+ min: 60,
+ max: 175,
+ };
+ }
+
+ if (AppConstants.platform == "macosx") {
+ for (let pref of [
+ "font.default.x-western",
+ "font.minimum-size.x-western",
+ "font.name.variable.x-western",
+ "font.size-adjust.cursive.x-western",
+ "font.size-adjust.fantasy.x-western",
+ "font.size-adjust.monospace.x-western",
+ "font.size-adjust.sans-serif.x-western",
+ "font.size-adjust.serif.x-western",
+ "font.size-adjust.system-ui.x-western",
+ "font.size-adjust.variable.x-western",
+ "font.size.cursive.x-western",
+ "font.size.fantasy.x-western",
+ "font.size.monospace.x-western",
+ "font.size.sans-serif.x-western",
+ "font.size.serif.x-western",
+ "font.size.system-ui.x-western",
+ "font.size.variable.x-western",
+ ]) {
+ knownProblematicPrefs[pref] = {
+ min: 0,
+ max: 45,
+ };
+ }
+ }
+
+ let startupRecorder =
+ Cc["@mozilla.org/test/startuprecorder;1"].getService().wrappedJSObject;
+ await startupRecorder.done;
+
+ ok(startupRecorder.data.prefStats, "startupRecorder has prefStats");
+
+ checkPrefGetters(startupRecorder.data.prefStats, max, knownProblematicPrefs);
+});