browser/experiments/test/xpcshell/test_telemetry.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial