diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/components/telemetry/tests/browser/browser_DynamicScalars.js | |
parent | Initial commit. (diff) | |
download | firefox-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.js | 243 |
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." + ); +}); |