gecko-dev/tools/profiler/tests/xpcshell/test_feature_mainthreadio.js

128 строки
4.1 KiB
JavaScript

/* 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/. */
const { FileUtils } = ChromeUtils.import(
"resource://gre/modules/FileUtils.jsm"
);
/**
* Test that the IOInterposer is working correctly to capture main thread IO.
*
* This test should not run on release or beta, as the IOInterposer is wrapped in
* an ifdef.
*/
add_task(async () => {
if (!AppConstants.MOZ_GECKO_PROFILER) {
return;
}
// Let the test harness settle, in order to avoid extraneous FileIO operations. This
// helps avoid false positives that we are actually triggering FileIO.
await wait(10);
{
const filename = "profiler-mainthreadio-test-firstrun";
const payloads = await startProfilerAndgetFileIOPayloads(
["mainthreadio"],
filename
);
greater(
payloads.length,
0,
"FileIO markers were found when using the mainthreadio feature on the profiler."
);
// It would be better to check on the filename, but Linux does not currently include
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
// ok(hasWritePayload(payloads, filename),
// "A FileIO marker is found when using the mainthreadio feature on the profiler.");
}
{
const filename = "profiler-mainthreadio-test-no-instrumentation";
const payloads = await startProfilerAndgetFileIOPayloads([], filename);
equal(
payloads.length,
0,
"No FileIO markers are found when the mainthreadio feature is not turned on " +
"in the profiler."
);
}
{
const filename = "profiler-mainthreadio-test-secondrun";
const payloads = await startProfilerAndgetFileIOPayloads(
["mainthreadio"],
filename
);
greater(
payloads.length,
0,
"FileIO markers were found when re-starting the mainthreadio feature on the " +
"profiler."
);
// It would be better to check on the filename, but Linux does not currently include
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
// ok(hasWritePayload(payloads, filename),
// "Re-enabling the mainthreadio re-installs the interposer, and we can capture " +
// "another FileIO payload.");
}
});
/**
* Start the profiler and get FileIO payloads.
* @param {Array} features The list of profiler features
* @param {string} filename A filename to trigger a write operation
*/
async function startProfilerAndgetFileIOPayloads(features, filename) {
const entries = 10000;
const interval = 10;
const threads = [];
Services.profiler.StartProfiler(entries, interval, features, threads);
const file = FileUtils.getFile("TmpD", [filename]);
if (file.exists()) {
console.warn(
"This test is triggering FileIO by writing to a file. However, the test found an " +
"existing file at the location it was trying to write to. This could happen " +
"because a previous run of the test failed to clean up after itself. This test " +
" will now clean up that file before running the test again."
);
file.remove(false);
}
const outputStream = FileUtils.openSafeFileOutputStream(file);
const data = "Test data.";
outputStream.write(data, data.length);
FileUtils.closeSafeFileOutputStream(outputStream);
file.remove(false);
// Wait for the profiler to collect a sample.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1529053
await wait(500);
// Pause the profiler as we don't need to collect more samples as we retrieve
// and serialize the profile.
Services.profiler.Pause();
const profile = await Services.profiler.getProfileDataAsync();
Services.profiler.StopProfiler();
return getPayloadsOfTypeFromAllThreads(profile, "FileIO");
}
/**
* See if a list of payloads has a write operation from a file.
*
* @param {Array<Object>} payloads The payloads captured from the profiler.
* @param {string} filename The filename used to test a write operation.
*/
function hasWritePayload(payloads, filename) {
return payloads.some(payload => payload.filename.endsWith(filename));
}