forked from mirrors/gecko-dev
241 lines
7.9 KiB
JavaScript
241 lines
7.9 KiB
JavaScript
"use strict";
|
|
|
|
const { TelemetryController } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/TelemetryController.sys.mjs"
|
|
);
|
|
const { TelemetryUtils } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/TelemetryUtils.sys.mjs"
|
|
);
|
|
|
|
const CONTENT_CREATED = "ipc:content-created";
|
|
|
|
async function waitForProcessesScalars(
|
|
aProcesses,
|
|
aKeyed,
|
|
aAdditionalCondition = data => true
|
|
) {
|
|
await TestUtils.waitForCondition(() => {
|
|
const scalars = aKeyed
|
|
? Services.telemetry.getSnapshotForKeyedScalars("main", false)
|
|
: Services.telemetry.getSnapshotForScalars("main", false);
|
|
return (
|
|
aProcesses.every(p => Object.keys(scalars).includes(p)) &&
|
|
aAdditionalCondition(scalars)
|
|
);
|
|
});
|
|
}
|
|
|
|
add_task(async function test_setup() {
|
|
// Make sure the newly spawned content processes will have extended Telemetry enabled.
|
|
// Since Telemetry reads the prefs only at process startup, flush all cached
|
|
// and preallocated processes so they pick up the setting.
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
[TelemetryUtils.Preferences.OverridePreRelease, true],
|
|
["dom.ipc.processPrelaunch.enabled", false],
|
|
],
|
|
});
|
|
Services.ppmm.releaseCachedProcesses();
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["dom.ipc.processPrelaunch.enabled", true]],
|
|
});
|
|
|
|
// And take care of the already initialized one as well.
|
|
let canRecordExtended = Services.telemetry.canRecordExtended;
|
|
Services.telemetry.canRecordExtended = true;
|
|
registerCleanupFunction(
|
|
() => (Services.telemetry.canRecordExtended = canRecordExtended)
|
|
);
|
|
});
|
|
|
|
add_task(async function test_recording() {
|
|
let currentPid = gBrowser.selectedBrowser.frameLoader.remoteTab.osPid;
|
|
|
|
// Register test scalars before spawning the content process: the scalar
|
|
// definitions will propagate to it.
|
|
Services.telemetry.registerScalars("telemetry.test.dynamic", {
|
|
pre_content_spawn: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
keyed: false,
|
|
record_on_release: true,
|
|
},
|
|
pre_content_spawn_expiration: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
keyed: false,
|
|
record_on_release: true,
|
|
},
|
|
});
|
|
|
|
Services.telemetry.scalarSet(
|
|
"telemetry.test.dynamic.pre_content_spawn_expiration",
|
|
3
|
|
);
|
|
|
|
let processCreated = TestUtils.topicObserved(CONTENT_CREATED);
|
|
await BrowserTestUtils.withNewTab(
|
|
{ gBrowser, url: "about:blank", forceNewProcess: true },
|
|
async function(browser) {
|
|
// Make sure our new browser is in its own process. The processCreated
|
|
// promise should have already resolved by this point.
|
|
await processCreated;
|
|
let newPid = browser.frameLoader.remoteTab.osPid;
|
|
ok(currentPid != newPid, "The new tab must spawn its own process");
|
|
|
|
// Register test scalars after spawning the content process: the scalar
|
|
// definitions will propagate to it.
|
|
// Also attempt to register again "pre_content_spawn_expiration" and set
|
|
// it to expired.
|
|
Services.telemetry.registerScalars("telemetry.test.dynamic", {
|
|
post_content_spawn: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_BOOLEAN,
|
|
keyed: false,
|
|
record_on_release: false,
|
|
},
|
|
post_content_spawn_keyed: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
keyed: true,
|
|
record_on_release: true,
|
|
},
|
|
pre_content_spawn_expiration: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
keyed: false,
|
|
record_on_release: true,
|
|
expired: true,
|
|
},
|
|
});
|
|
|
|
// Accumulate from the content process into both dynamic scalars.
|
|
await SpecialPowers.spawn(browser, [], async function() {
|
|
Services.telemetry.scalarAdd(
|
|
"telemetry.test.dynamic.pre_content_spawn_expiration",
|
|
1
|
|
);
|
|
Services.telemetry.scalarSet(
|
|
"telemetry.test.dynamic.pre_content_spawn",
|
|
3
|
|
);
|
|
Services.telemetry.scalarSet(
|
|
"telemetry.test.dynamic.post_content_spawn",
|
|
true
|
|
);
|
|
Services.telemetry.keyedScalarSet(
|
|
"telemetry.test.dynamic.post_content_spawn_keyed",
|
|
"testKey",
|
|
3
|
|
);
|
|
});
|
|
}
|
|
);
|
|
|
|
// Wait for the dynamic scalars to appear non-keyed snapshots.
|
|
await waitForProcessesScalars(["dynamic"], true, scalars => {
|
|
// Wait for the scalars set in the content process to be available.
|
|
return "telemetry.test.dynamic.post_content_spawn_keyed" in scalars.dynamic;
|
|
});
|
|
|
|
// Verify the content of the snapshots.
|
|
const scalars = Services.telemetry.getSnapshotForScalars("main", false);
|
|
ok(
|
|
"dynamic" in scalars,
|
|
"The scalars must contain the 'dynamic' process section"
|
|
);
|
|
ok(
|
|
"telemetry.test.dynamic.pre_content_spawn" in scalars.dynamic,
|
|
"Dynamic scalars registered before a process spawns must be present."
|
|
);
|
|
is(
|
|
scalars.dynamic["telemetry.test.dynamic.pre_content_spawn"],
|
|
3,
|
|
"The dynamic scalar must contain the expected value."
|
|
);
|
|
is(
|
|
scalars.dynamic["telemetry.test.dynamic.pre_content_spawn_expiration"],
|
|
3,
|
|
"The dynamic scalar must not be updated after being expired."
|
|
);
|
|
ok(
|
|
"telemetry.test.dynamic.post_content_spawn" in scalars.dynamic,
|
|
"Dynamic scalars registered after a process spawns must be present."
|
|
);
|
|
is(
|
|
scalars.dynamic["telemetry.test.dynamic.post_content_spawn"],
|
|
true,
|
|
"The dynamic scalar must contain the expected value."
|
|
);
|
|
|
|
// Wait for the dynamic scalars to appear in the keyed snapshots.
|
|
await waitForProcessesScalars(["dynamic"], true);
|
|
|
|
const keyedScalars = Services.telemetry.getSnapshotForKeyedScalars(
|
|
"main",
|
|
false
|
|
);
|
|
ok(
|
|
"dynamic" in keyedScalars,
|
|
"The keyed scalars must contain the 'dynamic' process section"
|
|
);
|
|
ok(
|
|
"telemetry.test.dynamic.post_content_spawn_keyed" in keyedScalars.dynamic,
|
|
"Dynamic keyed scalars registered after a process spawns must be present."
|
|
);
|
|
is(
|
|
keyedScalars.dynamic["telemetry.test.dynamic.post_content_spawn_keyed"]
|
|
.testKey,
|
|
3,
|
|
"The dynamic keyed scalar must contain the expected value."
|
|
);
|
|
});
|
|
|
|
add_task(async function test_aggregation() {
|
|
Services.telemetry.clearScalars();
|
|
|
|
// Register test scalars before spawning the content process: the scalar
|
|
// definitions will propagate to it. Also cheat TelemetrySession to put
|
|
// the test scalar in the payload by using "cheattest" instead of "test" in
|
|
// the scalar category name.
|
|
Services.telemetry.registerScalars("telemetry.cheattest.dynamic", {
|
|
test_aggregation: {
|
|
kind: Ci.nsITelemetry.SCALAR_TYPE_COUNT,
|
|
keyed: false,
|
|
record_on_release: true,
|
|
},
|
|
});
|
|
|
|
const SCALAR_FULL_NAME = "telemetry.cheattest.dynamic.test_aggregation";
|
|
Services.telemetry.scalarAdd(SCALAR_FULL_NAME, 1);
|
|
|
|
await BrowserTestUtils.withNewTab(
|
|
{ gBrowser, url: "about:blank", forceNewProcess: true },
|
|
async function(browser) {
|
|
// Accumulate from the content process into both dynamic scalars.
|
|
await SpecialPowers.spawn(browser, [SCALAR_FULL_NAME], async function(
|
|
aName
|
|
) {
|
|
Services.telemetry.scalarAdd(aName, 3);
|
|
});
|
|
}
|
|
);
|
|
|
|
// Wait for the dynamic scalars to appear. Since we're testing that children
|
|
// and parent data get aggregated, we might need to wait a bit more:
|
|
// TelemetryIPCAccumulator.cpp sends batches to the parent process every 2 seconds.
|
|
await waitForProcessesScalars(["dynamic"], false, scalarData => {
|
|
return (
|
|
"dynamic" in scalarData &&
|
|
SCALAR_FULL_NAME in scalarData.dynamic &&
|
|
scalarData.dynamic[SCALAR_FULL_NAME] == 4
|
|
);
|
|
});
|
|
|
|
// Check that the definitions made it to the ping payload.
|
|
const pingData = TelemetryController.getCurrentPingData(true);
|
|
ok(
|
|
"dynamic" in pingData.payload.processes,
|
|
"The ping payload must contain the 'dynamic' process section"
|
|
);
|
|
is(
|
|
pingData.payload.processes.dynamic.scalars[SCALAR_FULL_NAME],
|
|
4,
|
|
"The dynamic scalar must contain the aggregated parent and children data."
|
|
);
|
|
});
|