Bug 1890689 Don't pretend to pre-buffer with DynamicResampler r=pehrsons
[gecko.git] / browser / modules / test / unit / test_InstallationTelemetry.js
blob4bb9acbd75f0166c7f4274b9f533d4709e77a58b
1 /* Any copyright is dedicated to the Public Domain.
2  * http://creativecommons.org/publicdomain/zero/1.0/
3  */
4 "use strict";
6 const { AppConstants } = ChromeUtils.importESModule(
7   "resource://gre/modules/AppConstants.sys.mjs"
8 );
9 const { BrowserUsageTelemetry } = ChromeUtils.importESModule(
10   "resource:///modules/BrowserUsageTelemetry.sys.mjs"
12 const { TelemetryTestUtils } = ChromeUtils.importESModule(
13   "resource://testing-common/TelemetryTestUtils.sys.mjs"
15 ChromeUtils.defineESModuleGetters(this, {
16   FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
17 });
19 const TIMESTAMP_PREF = "app.installation.timestamp";
21 function encodeUtf16(str) {
22   const buf = new ArrayBuffer(str.length * 2);
23   const utf16 = new Uint16Array(buf);
24   for (let i = 0; i < str.length; i++) {
25     utf16[i] = str.charCodeAt(i);
26   }
27   return new Uint8Array(buf);
30 // Returns Promise
31 function writeJsonUtf16(fileName, obj) {
32   const str = JSON.stringify(obj);
33   return IOUtils.write(fileName, encodeUtf16(str));
36 async function runReport(
37   dataFile,
38   installType,
39   { clearTS, setTS, assertRejects, expectExtra, expectTS, msixPrefixes }
40 ) {
41   // Setup timestamp
42   if (clearTS) {
43     Services.prefs.clearUserPref(TIMESTAMP_PREF);
44   }
45   if (typeof setTS == "string") {
46     Services.prefs.setStringPref(TIMESTAMP_PREF, setTS);
47   }
49   // Init events
50   Services.telemetry.clearEvents();
52   // Exercise reportInstallationTelemetry
53   if (typeof assertRejects != "undefined") {
54     await Assert.rejects(
55       BrowserUsageTelemetry.reportInstallationTelemetry(dataFile),
56       assertRejects
57     );
58   } else if (!msixPrefixes) {
59     await BrowserUsageTelemetry.reportInstallationTelemetry(dataFile);
60   } else {
61     await BrowserUsageTelemetry.reportInstallationTelemetry(
62       dataFile,
63       msixPrefixes
64     );
65   }
67   // Check events
68   TelemetryTestUtils.assertEvents(
69     expectExtra
70       ? [{ object: installType, value: null, extra: expectExtra }]
71       : [],
72     { category: "installation", method: "first_seen" }
73   );
75   // Check timestamp
76   if (typeof expectTS == "string") {
77     Assert.equal(expectTS, Services.prefs.getStringPref(TIMESTAMP_PREF));
78   }
81 let condition = {
82   skip_if: () =>
83     AppConstants.platform !== "win" ||
84     !Services.sysinfo.getProperty("hasWinPackageId"),
86 add_task(condition, async function testInstallationTelemetryMSIX() {
87   // Unfortunately, we have no way to inject different installation ping data
88   // into the system in a way that doesn't just completely override the code
89   // under test - so other than a basic test of the happy path, there's
90   // nothing we can do here.
91   let msixExtra = {
92     version: AppConstants.MOZ_APP_VERSION,
93     build_id: AppConstants.MOZ_BULIDID,
94     admin_user: "false",
95     from_msi: "false",
96     silent: "false",
97     default_path: "true",
98     install_existed: "false",
99     other_inst: "false",
100     other_msix_inst: "false",
101     profdir_existed: "false",
102   };
104   await runReport("fake", "msix", {
105     expectExtra: msixExtra,
106   });
108 condition = {
109   skip_if: () =>
110     AppConstants.platform === "win" &&
111     Services.sysinfo.getProperty("hasWinPackageId"),
113 add_task(condition, async function testInstallationTelemetry() {
114   let dataFilePath = await IOUtils.createUniqueFile(
115     Services.dirsvc.get("TmpD", Ci.nsIFile).path,
116     "installation-telemetry-test-data" + Math.random() + ".json"
117   );
118   let dataFile = new FileUtils.File(dataFilePath);
120   registerCleanupFunction(async () => {
121     try {
122       await IOUtils.remove(dataFilePath);
123     } catch (ex) {
124       // Ignore remove failure, file may not exist by now
125     }
127     Services.prefs.clearUserPref(TIMESTAMP_PREF);
128   });
130   // Test with normal stub data
131   let stubData = {
132     version: "99.0abc",
133     build_id: "123",
134     installer_type: "stub",
135     admin_user: true,
136     install_existed: false,
137     profdir_existed: false,
138     install_timestamp: "0",
139   };
140   let stubExtra = {
141     version: "99.0abc",
142     build_id: "123",
143     admin_user: "true",
144     install_existed: "false",
145     other_inst: "false",
146     other_msix_inst: "false",
147     profdir_existed: "false",
148   };
150   await writeJsonUtf16(dataFilePath, stubData);
151   await runReport(dataFile, "stub", {
152     clearTS: true,
153     expectExtra: stubExtra,
154     expectTS: "0",
155   });
157   // Check that it doesn't generate another event when the timestamp is unchanged
158   await runReport(dataFile, "stub", { expectTS: "0" });
160   // New timestamp
161   stubData.install_timestamp = "1";
162   await writeJsonUtf16(dataFilePath, stubData);
163   await runReport(dataFile, "stub", {
164     expectExtra: stubExtra,
165     expectTS: "1",
166   });
168   // Test with normal full data
169   let fullData = {
170     version: "99.0abc",
171     build_id: "123",
172     installer_type: "full",
173     admin_user: false,
174     install_existed: true,
175     profdir_existed: true,
176     silent: false,
177     from_msi: false,
178     default_path: true,
180     install_timestamp: "1",
181   };
182   let fullExtra = {
183     version: "99.0abc",
184     build_id: "123",
185     admin_user: "false",
186     install_existed: "true",
187     other_inst: "false",
188     other_msix_inst: "false",
189     profdir_existed: "true",
190     silent: "false",
191     from_msi: "false",
192     default_path: "true",
193   };
195   await writeJsonUtf16(dataFilePath, fullData);
196   await runReport(dataFile, "full", {
197     clearTS: true,
198     expectExtra: fullExtra,
199     expectTS: "1",
200   });
202   // Check that it doesn't generate another event when the timestamp is unchanged
203   await runReport(dataFile, "full", { expectTS: "1" });
205   // New timestamp and a check to make sure we can find installed MSIX packages
206   // by overriding the prefixes a bit further down.
207   fullData.install_timestamp = "2";
208   // This check only works on Windows
209   if (AppConstants.platform == "win") {
210     fullExtra.other_msix_inst = "true";
211   }
212   await writeJsonUtf16(dataFilePath, fullData);
213   await runReport(dataFile, "full", {
214     expectExtra: fullExtra,
215     expectTS: "2",
216     msixPrefixes: ["Microsoft"],
217   });
219   // Missing field
220   delete fullData.install_existed;
221   fullData.install_timestamp = "3";
222   await writeJsonUtf16(dataFilePath, fullData);
223   await runReport(dataFile, "full", { assertRejects: /install_existed/ });
225   // Malformed JSON
226   await IOUtils.write(dataFilePath, encodeUtf16("hello"));
227   await runReport(dataFile, "stub", {
228     assertRejects: /unexpected character/,
229   });
231   // Missing file, should return with no exception
232   await IOUtils.remove(dataFilePath);
233   await runReport(dataFile, "stub", { setTS: "3", expectTS: "3" });