1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/experiments/test/xpcshell/test_disableExperiments.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,189 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +"use strict"; 1.8 + 1.9 +Cu.import("resource://testing-common/httpd.js"); 1.10 +Cu.import("resource://testing-common/AddonManagerTesting.jsm"); 1.11 + 1.12 +XPCOMUtils.defineLazyModuleGetter(this, "Experiments", 1.13 + "resource:///modules/experiments/Experiments.jsm"); 1.14 + 1.15 +const FILE_MANIFEST = "experiments.manifest"; 1.16 +const MANIFEST_HANDLER = "manifests/handler"; 1.17 + 1.18 +const SEC_IN_ONE_DAY = 24 * 60 * 60; 1.19 +const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; 1.20 + 1.21 +let gProfileDir = null; 1.22 +let gHttpServer = null; 1.23 +let gHttpRoot = null; 1.24 +let gDataRoot = null; 1.25 +let gReporter = null; 1.26 +let gPolicy = null; 1.27 +let gManifestObject = null; 1.28 +let gManifestHandlerURI = null; 1.29 + 1.30 +function run_test() { 1.31 + run_next_test(); 1.32 +} 1.33 + 1.34 +add_task(function* test_setup() { 1.35 + loadAddonManager(); 1.36 + gProfileDir = do_get_profile(); 1.37 + 1.38 + gHttpServer = new HttpServer(); 1.39 + gHttpServer.start(-1); 1.40 + let port = gHttpServer.identity.primaryPort; 1.41 + gHttpRoot = "http://localhost:" + port + "/"; 1.42 + gDataRoot = gHttpRoot + "data/"; 1.43 + gManifestHandlerURI = gHttpRoot + MANIFEST_HANDLER; 1.44 + gHttpServer.registerDirectory("/data/", do_get_cwd()); 1.45 + gHttpServer.registerPathHandler("/" + MANIFEST_HANDLER, (request, response) => { 1.46 + response.setStatusLine(null, 200, "OK"); 1.47 + response.write(JSON.stringify(gManifestObject)); 1.48 + response.processAsync(); 1.49 + response.finish(); 1.50 + }); 1.51 + do_register_cleanup(() => gHttpServer.stop(() => {})); 1.52 + 1.53 + disableCertificateChecks(); 1.54 + 1.55 + Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); 1.56 + Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); 1.57 + Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); 1.58 + Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI); 1.59 + Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0); 1.60 + 1.61 + gReporter = yield getReporter("json_payload_simple"); 1.62 + yield gReporter.collectMeasurements(); 1.63 + let payload = yield gReporter.getJSONPayload(true); 1.64 + do_register_cleanup(() => gReporter._shutdown()); 1.65 + 1.66 + gPolicy = new Experiments.Policy(); 1.67 + patchPolicy(gPolicy, { 1.68 + updatechannel: () => "nightly", 1.69 + healthReportPayload: () => Promise.resolve(payload), 1.70 + oneshotTimer: (callback, timeout, thisObj, name) => {}, 1.71 + }); 1.72 +}); 1.73 + 1.74 +// Test disabling the feature stops current and future experiments. 1.75 + 1.76 +add_task(function* test_disableExperiments() { 1.77 + const OBSERVER_TOPIC = "experiments-changed"; 1.78 + let observerFireCount = 0; 1.79 + let expectedObserverFireCount = 0; 1.80 + let observer = () => ++observerFireCount; 1.81 + Services.obs.addObserver(observer, OBSERVER_TOPIC, false); 1.82 + 1.83 + // Dates the following tests are based on. 1.84 + 1.85 + let baseDate = new Date(2014, 5, 1, 12); 1.86 + let startDate1 = futureDate(baseDate, 50 * MS_IN_ONE_DAY); 1.87 + let endDate1 = futureDate(baseDate, 100 * MS_IN_ONE_DAY); 1.88 + let startDate2 = futureDate(baseDate, 150 * MS_IN_ONE_DAY); 1.89 + let endDate2 = futureDate(baseDate, 200 * MS_IN_ONE_DAY); 1.90 + 1.91 + // The manifest data we test with. 1.92 + 1.93 + gManifestObject = { 1.94 + "version": 1, 1.95 + experiments: [ 1.96 + { 1.97 + id: EXPERIMENT2_ID, 1.98 + xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, 1.99 + xpiHash: EXPERIMENT2_XPI_SHA1, 1.100 + startTime: dateToSeconds(startDate2), 1.101 + endTime: dateToSeconds(endDate2), 1.102 + maxActiveSeconds: 10 * SEC_IN_ONE_DAY, 1.103 + appName: ["XPCShell"], 1.104 + channel: ["nightly"], 1.105 + }, 1.106 + { 1.107 + id: EXPERIMENT1_ID, 1.108 + xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, 1.109 + xpiHash: EXPERIMENT1_XPI_SHA1, 1.110 + startTime: dateToSeconds(startDate1), 1.111 + endTime: dateToSeconds(endDate1), 1.112 + maxActiveSeconds: 10 * SEC_IN_ONE_DAY, 1.113 + appName: ["XPCShell"], 1.114 + channel: ["nightly"], 1.115 + }, 1.116 + ], 1.117 + }; 1.118 + 1.119 + let experiments = new Experiments.Experiments(gPolicy); 1.120 + 1.121 + // Trigger update, clock set to before any activation. 1.122 + // Use updateManifest() to provide for coverage of that path. 1.123 + 1.124 + let now = baseDate; 1.125 + defineNow(gPolicy, now); 1.126 + 1.127 + yield experiments.updateManifest(); 1.128 + Assert.equal(observerFireCount, ++expectedObserverFireCount, 1.129 + "Experiments observer should have been called."); 1.130 + let list = yield experiments.getExperiments(); 1.131 + Assert.equal(list.length, 0, "Experiment list should be empty."); 1.132 + let addons = yield getExperimentAddons(); 1.133 + Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are installed."); 1.134 + 1.135 + // Trigger update, clock set for experiment 1 to start. 1.136 + 1.137 + now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); 1.138 + defineNow(gPolicy, now); 1.139 + 1.140 + yield experiments.updateManifest(); 1.141 + Assert.equal(observerFireCount, ++expectedObserverFireCount, 1.142 + "Experiments observer should have been called."); 1.143 + 1.144 + list = yield experiments.getExperiments(); 1.145 + Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); 1.146 + Assert.equal(list[0].active, true, "Experiment should be active."); 1.147 + addons = yield getExperimentAddons(); 1.148 + Assert.equal(addons.length, 1, "An experiment add-on was installed."); 1.149 + 1.150 + // Disable the experiments feature. Check that we stop the running experiment. 1.151 + 1.152 + Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, false); 1.153 + yield experiments._mainTask; 1.154 + 1.155 + Assert.equal(observerFireCount, ++expectedObserverFireCount, 1.156 + "Experiments observer should have been called."); 1.157 + 1.158 + list = yield experiments.getExperiments(); 1.159 + Assert.equal(list.length, 1, "Experiment list should have 1 entry."); 1.160 + Assert.equal(list[0].active, false, "Experiment entry should not be active."); 1.161 + addons = yield getExperimentAddons(); 1.162 + Assert.equal(addons.length, 0, "The experiment add-on should be uninstalled."); 1.163 + 1.164 + // Trigger update, clock set for experiment 2 to start. Verify we don't start it. 1.165 + 1.166 + now = startDate2; 1.167 + defineNow(gPolicy, now); 1.168 + 1.169 + try { 1.170 + yield experiments.updateManifest(); 1.171 + } catch (e if e.message == "experiments are disabled") { 1.172 + // This exception is expected. 1.173 + } 1.174 + 1.175 + experiments.notify(); 1.176 + yield experiments._mainTask; 1.177 + 1.178 + Assert.equal(observerFireCount, expectedObserverFireCount, 1.179 + "Experiments observer should not have been called."); 1.180 + 1.181 + list = yield experiments.getExperiments(); 1.182 + Assert.equal(list.length, 1, "Experiment list should still have 1 entry."); 1.183 + Assert.equal(list[0].active, false, "Experiment entry should not be active."); 1.184 + addons = yield getExperimentAddons(); 1.185 + Assert.equal(addons.length, 0, "There should still be no experiment add-on installed."); 1.186 + 1.187 + // Cleanup. 1.188 + 1.189 + Services.obs.removeObserver(observer, OBSERVER_TOPIC); 1.190 + yield experiments.uninit(); 1.191 + yield removeCacheFile(); 1.192 +});