Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
4 "use strict";
6 Cu.import("resource://testing-common/httpd.js");
7 Cu.import("resource://gre/modules/TelemetryLog.jsm");
8 let bsp = Cu.import("resource:///modules/experiments/Experiments.jsm");
11 const FILE_MANIFEST = "experiments.manifest";
12 const MANIFEST_HANDLER = "manifests/handler";
14 const SEC_IN_ONE_DAY = 24 * 60 * 60;
15 const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
18 let gProfileDir = null;
19 let gHttpServer = null;
20 let gHttpRoot = null;
21 let gDataRoot = null;
22 let gReporter = null;
23 let gPolicy = null;
24 let gManifestObject = null;
25 let gManifestHandlerURI = null;
27 const TLOG = bsp.TELEMETRY_LOG;
29 let gGlobalScope = this;
30 function loadAddonManager() {
31 let ns = {};
32 Cu.import("resource://gre/modules/Services.jsm", ns);
33 let head = "../../../../toolkit/mozapps/extensions/test/xpcshell/head_addons.js";
34 let file = do_get_file(head);
35 let uri = ns.Services.io.newFileURI(file);
36 ns.Services.scriptloader.loadSubScript(uri.spec, gGlobalScope);
37 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
38 startupManager();
39 }
41 function checkEvent(event, id, data)
42 {
43 do_print("Checking message " + id);
44 Assert.equal(event[0], id, "id should match");
45 Assert.ok(event[1] > 0, "timestamp should be greater than 0");
47 if (data === undefined) {
48 Assert.equal(event.length, 2, "event array should have 2 entries");
49 } else {
50 Assert.equal(event.length, data.length + 2, "event entry count should match expected count");
51 for (var i = 0; i < data.length; ++i) {
52 Assert.equal(typeof(event[i + 2]), "string", "event entry should be a string");
53 Assert.equal(event[i + 2], data[i], "event entry should match expected entry");
54 }
55 }
56 }
58 function run_test() {
59 run_next_test();
60 }
62 add_task(function* test_setup() {
63 loadAddonManager();
64 gProfileDir = do_get_profile();
66 gHttpServer = new HttpServer();
67 gHttpServer.start(-1);
68 let port = gHttpServer.identity.primaryPort;
69 gHttpRoot = "http://localhost:" + port + "/";
70 gDataRoot = gHttpRoot + "data/";
71 gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER;
72 gHttpServer.registerDirectory("/data/", do_get_cwd());
73 gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => {
74 response.setStatusLine(null, 200, "OK");
75 response.write(JSON.stringify(gManifestObject));
76 response.processAsync();
77 response.finish();
78 });
79 do_register_cleanup(() => gHttpServer.stop(() => {}));
81 disableCertificateChecks();
83 Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true);
84 Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0);
85 Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true);
86 Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI);
87 Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0);
89 gReporter = yield getReporter("json_payload_simple");
90 yield gReporter.collectMeasurements();
91 let payload = yield gReporter.getJSONPayload(true);
92 do_register_cleanup(() => gReporter._shutdown());
94 gPolicy = new Experiments.Policy();
95 let dummyTimer = { cancel: () => {}, clear: () => {} };
96 patchPolicy(gPolicy, {
97 updatechannel: () => "nightly",
98 healthReportPayload: () => Promise.resolve(payload),
99 oneshotTimer: (callback, timeout, thisObj, name) => dummyTimer,
100 });
102 yield removeCacheFile();
103 });
105 // Test basic starting and stopping of experiments.
107 add_task(function* test_telemetryBasics() {
108 // Check TelemetryLog instead of TelemetryPing.getPayload().log because
109 // TelemetryPing gets Experiments.instance() and side-effects log entries.
111 const OBSERVER_TOPIC = "experiments-changed";
112 let observerFireCount = 0;
113 let expectedLogLength = 0;
115 // Dates the following tests are based on.
117 let baseDate = new Date(2014, 5, 1, 12);
118 let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY);
119 let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY);
120 let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY);
121 let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY);
123 // The manifest data we test with.
125 gManifestObject = {
126 "version": 1,
127 experiments: [
128 {
129 id: EXPERIMENT1_ID,
130 xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME,
131 xpiHash: EXPERIMENT1_XPI_SHA1,
132 startTime: dateToSeconds(startDate1),
133 endTime: dateToSeconds(endDate1),
134 maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
135 appName: ["XPCShell"],
136 channel: ["nightly"],
137 },
138 {
139 id: EXPERIMENT2_ID,
140 xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME,
141 xpiHash: EXPERIMENT2_XPI_SHA1,
142 startTime: dateToSeconds(startDate2),
143 endTime: dateToSeconds(endDate2),
144 maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
145 appName: ["XPCShell"],
146 channel: ["nightly"],
147 },
148 ],
149 };
151 // Data to compare the result of Experiments.getExperiments() against.
153 let experimentListData = [
154 {
155 id: EXPERIMENT2_ID,
156 name: "Test experiment 2",
157 description: "And yet another experiment that experiments experimentally.",
158 },
159 {
160 id: EXPERIMENT1_ID,
161 name: EXPERIMENT1_NAME,
162 description: "Yet another experiment that experiments experimentally.",
163 },
164 ];
166 let experiments = new Experiments.Experiments(gPolicy);
168 // Trigger update, clock set to before any activation.
169 // Use updateManifest() to provide for coverage of that path.
171 let now = baseDate;
172 defineNow(gPolicy, now);
174 yield experiments.updateManifest();
175 let list = yield experiments.getExperiments();
176 Assert.equal(list.length, 0, "Experiment list should be empty.");
178 expectedLogLength += 2;
179 let log = TelemetryLog.entries();
180 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
181 checkEvent(log[log.length-2], TLOG.ACTIVATION_KEY,
182 [TLOG.ACTIVATION.REJECTED, EXPERIMENT1_ID, "startTime"]);
183 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
184 [TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]);
186 // Trigger update, clock set for experiment 1 to start.
188 now = futureDate(startDate1, 5 * MS_IN_ONE_DAY);
189 defineNow(gPolicy, now);
191 yield experiments.updateManifest();
192 list = yield experiments.getExperiments();
193 Assert.equal(list.length, 1, "Experiment list should have 1 entry now.");
195 expectedLogLength += 1;
196 log = TelemetryLog.entries();
197 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries. Got " + log.toSource());
198 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
199 [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT1_ID]);
201 // Trigger update, clock set for experiment 1 to stop.
203 now = futureDate(endDate1, 1000);
204 defineNow(gPolicy, now);
206 yield experiments.updateManifest();
207 list = yield experiments.getExperiments();
208 Assert.equal(list.length, 1, "Experiment list should have 1 entry.");
210 expectedLogLength += 2;
211 log = TelemetryLog.entries();
212 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
213 checkEvent(log[log.length-2], TLOG.TERMINATION_KEY,
214 [TLOG.TERMINATION.EXPIRED, EXPERIMENT1_ID]);
215 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
216 [TLOG.ACTIVATION.REJECTED, EXPERIMENT2_ID, "startTime"]);
218 // Trigger update, clock set for experiment 2 to start with invalid hash.
220 now = startDate2;
221 defineNow(gPolicy, now);
222 gManifestObject.experiments[1].xpiHash = "sha1:0000000000000000000000000000000000000000";
224 yield experiments.updateManifest();
225 list = yield experiments.getExperiments();
226 Assert.equal(list.length, 1, "Experiment list should have 1 entries.");
228 expectedLogLength += 1;
229 log = TelemetryLog.entries();
230 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
231 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
232 [TLOG.ACTIVATION.INSTALL_FAILURE, EXPERIMENT2_ID]);
234 // Trigger update, clock set for experiment 2 to properly start now.
236 now = futureDate(now, MS_IN_ONE_DAY);
237 defineNow(gPolicy, now);
238 gManifestObject.experiments[1].xpiHash = EXPERIMENT2_XPI_SHA1;
240 yield experiments.updateManifest();
241 list = yield experiments.getExperiments();
242 Assert.equal(list.length, 2, "Experiment list should have 2 entries.");
244 expectedLogLength += 1;
245 log = TelemetryLog.entries();
246 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
247 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
248 [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT2_ID]);
250 // Fake user uninstall of experiment via add-on manager.
252 now = futureDate(now, MS_IN_ONE_DAY);
253 defineNow(gPolicy, now);
255 yield experiments.disableExperiment(TLOG.TERMINATION.ADDON_UNINSTALLED);
256 list = yield experiments.getExperiments();
257 Assert.equal(list.length, 2, "Experiment list should have 2 entries.");
259 expectedLogLength += 1;
260 log = TelemetryLog.entries();
261 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
262 checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
263 [TLOG.TERMINATION.ADDON_UNINSTALLED, EXPERIMENT2_ID]);
265 // Trigger update with experiment 1a ready to start.
267 now = futureDate(now, MS_IN_ONE_DAY);
268 defineNow(gPolicy, now);
269 gManifestObject.experiments[0].id = EXPERIMENT3_ID;
270 gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY));
272 yield experiments.updateManifest();
273 list = yield experiments.getExperiments();
274 Assert.equal(list.length, 3, "Experiment list should have 3 entries.");
276 expectedLogLength += 1;
277 log = TelemetryLog.entries();
278 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
279 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
280 [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT3_ID]);
282 // Trigger disable of an experiment via the API.
284 now = futureDate(now, MS_IN_ONE_DAY);
285 defineNow(gPolicy, now);
287 yield experiments.disableExperiment(TLOG.TERMINATION.FROM_API);
288 list = yield experiments.getExperiments();
289 Assert.equal(list.length, 3, "Experiment list should have 3 entries.");
291 expectedLogLength += 1;
292 log = TelemetryLog.entries();
293 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
294 checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
295 [TLOG.TERMINATION.FROM_API, EXPERIMENT3_ID]);
297 // Trigger update with experiment 1a ready to start.
299 now = futureDate(now, MS_IN_ONE_DAY);
300 defineNow(gPolicy, now);
301 gManifestObject.experiments[0].id = EXPERIMENT4_ID;
302 gManifestObject.experiments[0].endTime = dateToSeconds(futureDate(now, 50 * MS_IN_ONE_DAY));
304 yield experiments.updateManifest();
305 list = yield experiments.getExperiments();
306 Assert.equal(list.length, 4, "Experiment list should have 4 entries.");
308 expectedLogLength += 1;
309 log = TelemetryLog.entries();
310 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
311 checkEvent(log[log.length-1], TLOG.ACTIVATION_KEY,
312 [TLOG.ACTIVATION.ACTIVATED, EXPERIMENT4_ID]);
314 // Trigger experiment termination by something other than expiry via the manifest.
316 now = futureDate(now, MS_IN_ONE_DAY);
317 defineNow(gPolicy, now);
318 gManifestObject.experiments[0].os = "Plan9";
320 yield experiments.updateManifest();
321 list = yield experiments.getExperiments();
322 Assert.equal(list.length, 4, "Experiment list should have 4 entries.");
324 expectedLogLength += 1;
325 log = TelemetryLog.entries();
326 Assert.equal(log.length, expectedLogLength, "Telemetry log should have " + expectedLogLength + " entries.");
327 checkEvent(log[log.length-1], TLOG.TERMINATION_KEY,
328 [TLOG.TERMINATION.RECHECK, EXPERIMENT4_ID, "os"]);
330 // Cleanup.
332 yield experiments.uninit();
333 yield removeCacheFile();
334 });