summaryrefslogtreecommitdiffstats
path: root/toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js')
-rw-r--r--toolkit/components/telemetry/tests/unit/test_TelemetrySession_abortedSessionQueued.js197
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();
+});