summaryrefslogtreecommitdiffstats
path: root/toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js')
-rw-r--r--toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js243
1 files changed, 243 insertions, 0 deletions
diff --git a/toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js b/toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js
new file mode 100644
index 0000000000..74a7e48695
--- /dev/null
+++ b/toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js
@@ -0,0 +1,243 @@
+"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."
+ );
+});