diff options
Diffstat (limited to 'comm/mail/base/test/performance/browser_preferences_usage.js')
-rw-r--r-- | comm/mail/base/test/performance/browser_preferences_usage.js | 177 |
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); +}); |