зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1356271 - add a test to measure how many layout flushes it takes for a simple location bar search. r=florian
MozReview-Commit-ID: GFDvSIn53Zh --HG-- extra : rebase_source : 63e1b8421dbbc320e3eaf39822ef3fd8b1069211 extra : source : fdea4300bc5dabf5d1bb2b77a419bac489a56b6d
This commit is contained in:
Родитель
5f9f0cd7f2
Коммит
9d127d0c7f
|
@ -14,6 +14,8 @@ skip-if = !debug
|
|||
[browser_tabopen_squeeze_reflows.js]
|
||||
[browser_tabswitch_reflows.js]
|
||||
[browser_toolbariconcolor_restyles.js]
|
||||
[browser_urlbar_search_reflows.js]
|
||||
skip-if = (os == 'linux') || (os == 'mac' && !debug) # Disabled on Linux and OS X opt due to frequent failures. Bug 1385932 and Bug 1384582
|
||||
[browser_windowclose_reflows.js]
|
||||
[browser_windowopen_reflows.js]
|
||||
skip-if = os == 'linux' # Disabled due to frequent failures. Bug 1380465.
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
"use strict";
|
||||
|
||||
// There are a _lot_ of reflows in this test, and processing them takes
|
||||
// time. On slower builds, we need to boost our allowed test time.
|
||||
requestLongerTimeout(5);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
|
||||
/**
|
||||
* WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
|
||||
* is a whitelist that should slowly go away as we improve the performance of
|
||||
* the front-end. Instead of adding more reflows to the whitelist, you should
|
||||
* be modifying your code to avoid the reflow.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
|
||||
* for tips on how to do that.
|
||||
*/
|
||||
|
||||
/* These reflows happen only the first time the awesomebar panel opens. */
|
||||
const EXPECTED_REFLOWS_FIRST_OPEN = [
|
||||
// Bug 1357054
|
||||
{
|
||||
stack: [
|
||||
"_rebuild@chrome://browser/content/search/search.xml",
|
||||
"set_popup@chrome://browser/content/search/search.xml",
|
||||
"enableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
|
||||
"_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
|
||||
"urlbar_XBL_Constructor/<@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 1, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustSiteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_siteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustSiteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 9, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"onxblpopupshown@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 5, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_siteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 6, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 390, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1359989
|
||||
{
|
||||
stack: [
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/* These reflows happen everytime the awesomebar panel opens. */
|
||||
const EXPECTED_REFLOWS_SECOND_OPEN = [
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"onxblpopupshown@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 444, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1384256
|
||||
{
|
||||
stack: [
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1359989
|
||||
{
|
||||
stack: [
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves once the AwesomeBar popup for a particular
|
||||
* window has appeared after having done a search for its input text.
|
||||
*
|
||||
* @param win (browser window)
|
||||
* The window to do the search in.
|
||||
* @returns Promise
|
||||
*/
|
||||
async function promiseAutocompleteResultPopup(win) {
|
||||
let URLBar = win.gURLBar;
|
||||
URLBar.controller.startSearch(URLBar.value);
|
||||
await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return URLBar.controller.searchStatus >=
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
|
||||
});
|
||||
let matchCount = URLBar.popup._matchCount;
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return URLBar.popup.richlistbox.childNodes.length == matchCount;
|
||||
});
|
||||
|
||||
URLBar.controller.stopSearch();
|
||||
// There are several setTimeout(fn, 0); calls inside autocomplete.xml
|
||||
// that we need to wait for. Since those have higher priority than
|
||||
// idle callbacks, we can be sure they will have run once this
|
||||
// idle callback is called. The timeout seems to be required in
|
||||
// automation - presumably because the machines can be pretty busy
|
||||
// especially if it's GC'ing from previous tests.
|
||||
await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
|
||||
|
||||
let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
|
||||
await hiddenPromise;
|
||||
}
|
||||
|
||||
const SEARCH_TERM = "urlbar-reflows";
|
||||
|
||||
add_task(async function setup() {
|
||||
const NUM_VISITS = 10;
|
||||
let visits = [];
|
||||
|
||||
for (let i = 0; i < NUM_VISITS; ++i) {
|
||||
visits.push({
|
||||
uri: `http://example.com/urlbar-reflows-${i}`,
|
||||
title: `Reflow test for URL bar entry #${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
await PlacesTestUtils.addVisits(visits);
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesTestUtils.clearHistory();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that there are no unexpected
|
||||
* uninterruptible reflows when typing into the URL bar
|
||||
* with the default values in Places.
|
||||
*/
|
||||
add_task(async function() {
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await ensureNoPreloadedBrowser(win);
|
||||
|
||||
let URLBar = win.gURLBar;
|
||||
let popup = URLBar.popup;
|
||||
|
||||
URLBar.focus();
|
||||
URLBar.value = SEARCH_TERM;
|
||||
let testFn = async function(dirtyFrameFn) {
|
||||
let oldInvalidate = popup.invalidate.bind(popup);
|
||||
let oldResultsAdded = popup.onResultsAdded.bind(popup);
|
||||
|
||||
// We need to invalidate the frame tree outside of the normal
|
||||
// mechanism since invalidations and result additions to the
|
||||
// URL bar occur without firing JS events (which is how we
|
||||
// normally know to dirty the frame tree).
|
||||
popup.invalidate = (reason) => {
|
||||
dirtyFrameFn();
|
||||
oldInvalidate(reason);
|
||||
};
|
||||
|
||||
popup.onResultsAdded = () => {
|
||||
dirtyFrameFn();
|
||||
oldResultsAdded();
|
||||
};
|
||||
|
||||
await promiseAutocompleteResultPopup(win);
|
||||
};
|
||||
|
||||
await withReflowObserver(testFn, EXPECTED_REFLOWS_FIRST_OPEN, win);
|
||||
|
||||
await withReflowObserver(testFn, EXPECTED_REFLOWS_SECOND_OPEN, win);
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
|
@ -5,6 +5,10 @@
|
|||
* @param testFn (async function)
|
||||
* The async function that will exercise the browser activity that is
|
||||
* being tested for reflows.
|
||||
*
|
||||
* The testFn will be passed a single argument, which is a frame dirtying
|
||||
* function that can be called if the test needs to trigger frame
|
||||
* dirtying outside of the normal mechanism.
|
||||
* @param expectedReflows (Array, optional)
|
||||
* An Array of Objects representing reflows.
|
||||
*
|
||||
|
@ -121,7 +125,7 @@ async function withReflowObserver(testFn, expectedReflows = [], win = window) {
|
|||
|
||||
try {
|
||||
dirtyFrameFn();
|
||||
await testFn();
|
||||
await testFn(dirtyFrameFn);
|
||||
} finally {
|
||||
for (let remainder of expectedReflows) {
|
||||
Assert.ok(false,
|
||||
|
|
Загрузка…
Ссылка в новой задаче