diff options
Diffstat (limited to 'toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js')
-rw-r--r-- | toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js b/toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js new file mode 100644 index 0000000000..80807469fc --- /dev/null +++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js @@ -0,0 +1,197 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +/** + * This file only contains the |test_abortedSessionQueued| test. This needs + * to be in a separate, stand-alone file since we're initializing Telemetry + * twice, in a non-standard way to simulate incorrect shutdowns. Doing this + * in other files might interfere with the other tests. + */ + +const { TelemetryStorage } = ChromeUtils.importESModule( + "resource://gre/modules/TelemetryStorage.sys.mjs" +); + +const DATAREPORTING_DIR = "datareporting"; +const ABORTED_PING_FILE_NAME = "aborted-session-ping"; +const ABORTED_SESSION_UPDATE_INTERVAL_MS = 5 * 60 * 1000; + +const PING_TYPE_MAIN = "main"; +const REASON_ABORTED_SESSION = "aborted-session"; +const TEST_PING_TYPE = "test-ping-type"; + +ChromeUtils.defineLazyGetter(this, "DATAREPORTING_PATH", function () { + return PathUtils.join(PathUtils.profileDir, DATAREPORTING_DIR); +}); + +function sendPing() { + if (PingServer.started) { + TelemetrySend.setServer("http://localhost:" + PingServer.port); + } else { + TelemetrySend.setServer("http://doesnotexist"); + } + + let options = { + addClientId: true, + addEnvironment: true, + }; + return TelemetryController.submitExternalPing(TEST_PING_TYPE, {}, options); +} + +add_task(async function test_setup() { + do_get_profile(); + PingServer.start(); + Services.prefs.setCharPref( + TelemetryUtils.Preferences.Server, + "http://localhost:" + PingServer.port + ); +}); + +add_task(async function test_abortedSessionQueued() { + const ABORTED_FILE = PathUtils.join( + DATAREPORTING_PATH, + ABORTED_PING_FILE_NAME + ); + + // Make sure the aborted sessions directory does not exist to test its creation. + await IOUtils.remove(DATAREPORTING_PATH, { + ignoreAbsent: true, + recursive: true, + }); + + let schedulerTickCallback = null; + let now = new Date(2040, 1, 1, 0, 0, 0); + fakeNow(now); + // Fake scheduler functions to control aborted-session flow in tests. + fakeSchedulerTimer( + callback => (schedulerTickCallback = callback), + () => {} + ); + await TelemetryController.testReset(); + + Assert.ok( + await IOUtils.exists(DATAREPORTING_PATH), + "Telemetry must create the aborted session directory when starting." + ); + + // Fake now again so that the scheduled aborted-session save takes place. + now = futureDate(now, ABORTED_SESSION_UPDATE_INTERVAL_MS); + fakeNow(now); + // The first aborted session checkpoint must take place right after the initialisation. + Assert.ok(!!schedulerTickCallback); + // Execute one scheduler tick. + await schedulerTickCallback(); + // Check that the aborted session is due at the correct time. + Assert.ok( + await IOUtils.exists(ABORTED_FILE), + "There must be an aborted session ping." + ); + + await TelemetryStorage.testClearPendingPings(); + PingServer.clearRequests(); + await TelemetryController.testReset(); + + Assert.ok( + !(await IOUtils.exists(ABORTED_FILE)), + "The aborted session ping must be removed from the aborted session ping directory." + ); + + // Restarting Telemetry again to trigger sending pings in TelemetrySend. + await TelemetryController.testReset(); + + // We should have received an aborted-session ping. + const receivedPing = await PingServer.promiseNextPing(); + Assert.equal( + receivedPing.type, + PING_TYPE_MAIN, + "Should have the correct type" + ); + Assert.equal( + receivedPing.payload.info.reason, + REASON_ABORTED_SESSION, + "Ping should have the correct reason" + ); + + await TelemetryController.testShutdown(); +}); + +/* + * An aborted-session ping might have been written when Telemetry upload was disabled and + * the profile had a canary client ID. + * These pings should not be sent out at a later point when Telemetry is enabled again. + */ +add_task(async function test_abortedSession_canary_clientid() { + const ABORTED_FILE = PathUtils.join( + DATAREPORTING_PATH, + ABORTED_PING_FILE_NAME + ); + + // Make sure the aborted sessions directory does not exist to test its creation. + await IOUtils.remove(DATAREPORTING_PATH, { + ignoreAbsent: true, + recursive: true, + }); + + let schedulerTickCallback = null; + let now = new Date(2040, 1, 1, 0, 0, 0); + fakeNow(now); + // Fake scheduler functions to control aborted-session flow in tests. + fakeSchedulerTimer( + callback => (schedulerTickCallback = callback), + () => {} + ); + await TelemetryController.testReset(); + + Assert.ok( + await IOUtils.exists(DATAREPORTING_PATH), + "Telemetry must create the aborted session directory when starting." + ); + + // Fake now again so that the scheduled aborted-session save takes place. + now = futureDate(now, ABORTED_SESSION_UPDATE_INTERVAL_MS); + fakeNow(now); + // The first aborted session checkpoint must take place right after the initialisation. + Assert.ok(!!schedulerTickCallback); + // Execute one scheduler tick. + await schedulerTickCallback(); + // Check that the aborted session is due at the correct time. + Assert.ok( + await IOUtils.exists(ABORTED_FILE), + "There must be an aborted session ping." + ); + + // Set clientID in aborted-session ping to canary value + let abortedPing = await IOUtils.readJSON(ABORTED_FILE); + abortedPing.clientId = TelemetryUtils.knownClientID; + await IOUtils.writeJSON(ABORTED_FILE, abortedPing); + + await TelemetryStorage.testClearPendingPings(); + PingServer.clearRequests(); + await TelemetryController.testReset(); + + Assert.ok( + !(await IOUtils.exists(ABORTED_FILE)), + "The aborted session ping must be removed from the aborted session ping directory." + ); + + // Restarting Telemetry again to trigger sending pings in TelemetrySend. + await TelemetryController.testReset(); + + // Trigger a test ping, so we can verify the server received something. + sendPing(); + + // We should have received an aborted-session ping. + const receivedPing = await PingServer.promiseNextPing(); + Assert.equal( + receivedPing.type, + TEST_PING_TYPE, + "Should have received test ping" + ); + + await TelemetryController.testShutdown(); +}); + +add_task(async function stopServer() { + await PingServer.stop(); +}); |