Bug 1665810 - Add an end-to-end mochitest for DOMEvent markers r=gerald

I created a new test file for testing markers in the parent process. It
can be re-used to test a variety of different markers and their payloads
to ensure they are properly being created, and with relevant information.
The idea here is that this tests the entire pipeline, and excercises the
code as an end user of the profiler would.

Differential Revision: https://phabricator.services.mozilla.com/D92457
This commit is contained in:
Greg Tatum 2020-10-06 13:57:50 +00:00
Родитель c8755d4217
Коммит eb498b98eb
3 изменённых файлов: 73 добавлений и 0 удалений

Просмотреть файл

@ -12,5 +12,6 @@ support-files =
[browser_test_feature_jsallocations.js]
[browser_test_feature_nostacksampling.js]
[browser_test_feature_preferencereads.js]
[browser_test_markers_parent_process.js]
[browser_test_profile_single_frame_page_info.js]
[browser_test_profile_multi_frame_page_info.js]

Просмотреть файл

@ -0,0 +1,40 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
add_task(async function test_markers_parent_process() {
info("Test markers that are generated by the browser's parent process.");
if (!AppConstants.MOZ_GECKO_PROFILER) {
return;
}
info("Start the profiler in nostacksampling mode.");
startProfiler({ features: ["nostacksampling"] });
info("Dispatch a DOMEvent");
window.dispatchEvent(new Event("synthetic"));
info("Stop the profiler and get the profile.");
const profile = await stopAndGetProfile();
const markers = getInflatedMarkerData(profile.threads[0]);
{
const domEventStart = markers.find(
({ phase, data }) =>
phase === INTERVAL_START && data?.eventType === "synthetic"
);
const domEventEnd = markers.find(
({ phase, data }) =>
phase === INTERVAL_END && data?.eventType === "synthetic"
);
ok(domEventStart, "A start DOMEvent was generated");
ok(domEventEnd, "An end DOMEvent was generated");
ok(
domEventEnd.data.latency > 0,
"DOMEvent had a a latency value generated."
);
ok(domEventEnd.data.type === "DOMEvent");
ok(domEventEnd.name === "DOMEvent");
}
// Add more marker tests.
});

Просмотреть файл

@ -6,6 +6,12 @@
* This file contains utilities that can be shared between xpcshell tests and mochitests.
*/
// The marker phases.
const INSTANT = 0;
const INTERVAL = 1;
const INTERVAL_START = 2;
const INTERVAL_END = 3;
// This Services declaration may shadow another from head.js, so define it as
// a var rather than a const.
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
@ -18,6 +24,11 @@ const defaultSettings = {
};
function startProfiler(callersSettings) {
if (Services.profiler.IsActive()) {
throw new Error(
"The profiler must not be active before starting it in a test."
);
}
const settings = Object.assign({}, defaultSettings, callersSettings);
Services.profiler.StartProfiler(
settings.entries,
@ -89,6 +100,27 @@ function getPayloadsOfType(thread, type) {
return results;
}
/**
* Applies the marker schema to create individual objects for each marker
*
* @param {Object} thread The thread from a profile.
* @return {Array} The markers.
*/
function getInflatedMarkerData(thread) {
const { markers, stringTable } = thread;
return markers.data.map(markerTuple => {
const marker = {};
for (const [key, tupleIndex] of Object.entries(markers.schema)) {
marker[key] = markerTuple[tupleIndex];
if (key === "name") {
// Use the string from the string table.
marker[key] = stringTable[marker[key]];
}
}
return marker;
});
}
/**
* It can be helpful to force the profiler to collect a JavaScript sample. This
* function spins on a while loop until at least one more sample is collected.