1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/experiments/test/xpcshell/test_cache.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,259 @@ 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 +XPCOMUtils.defineLazyModuleGetter(this, "Experiments", 1.11 + "resource:///modules/experiments/Experiments.jsm"); 1.12 + 1.13 +const FILE_MANIFEST = "experiments.manifest"; 1.14 +const MANIFEST_HANDLER = "manifests/handler"; 1.15 + 1.16 +const SEC_IN_ONE_DAY = 24 * 60 * 60; 1.17 +const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; 1.18 + 1.19 +let gProfileDir = null; 1.20 +let gHttpServer = null; 1.21 +let gHttpRoot = null; 1.22 +let gDataRoot = null; 1.23 +let gReporter = null; 1.24 +let gPolicy = null; 1.25 +let gManifestObject = null; 1.26 +let gManifestHandlerURI = null; 1.27 +let gTimerScheduleOffset = -1; 1.28 + 1.29 +function run_test() { 1.30 + run_next_test(); 1.31 +} 1.32 + 1.33 +add_task(function* test_setup() { 1.34 + loadAddonManager(); 1.35 + gProfileDir = do_get_profile(); 1.36 + yield removeCacheFile(); 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: () => {}, 1.70 + oneshotTimer: (callback, timeout, thisObj, name) => gTimerScheduleOffset = timeout, 1.71 + }); 1.72 +}); 1.73 + 1.74 +function checkExperimentListsEqual(list, list2) { 1.75 + Assert.equal(list.length, list2.length, "Lists should have the same length.") 1.76 + 1.77 + for (let i=0; i<list.length; ++i) { 1.78 + for (let k of Object.keys(list[i])) { 1.79 + Assert.equal(list[i][k], list2[i][k], 1.80 + "Field '" + k + "' should match for list entry " + i + "."); 1.81 + } 1.82 + } 1.83 +} 1.84 + 1.85 +function checkExperimentSerializations(experimentEntryIterator) { 1.86 + for (let experiment of experimentEntryIterator) { 1.87 + let experiment2 = new Experiments.ExperimentEntry(gPolicy); 1.88 + let jsonStr = JSON.stringify(experiment.toJSON()); 1.89 + Assert.ok(experiment2.initFromCacheData(JSON.parse(jsonStr)), 1.90 + "Should have initialized successfully from JSON serialization."); 1.91 + Assert.equal(JSON.stringify(experiment), JSON.stringify(experiment2), 1.92 + "Object stringifications should match."); 1.93 + } 1.94 +} 1.95 + 1.96 +// Set up an experiments instance and check if it is properly restored from cache. 1.97 + 1.98 +add_task(function* test_cache() { 1.99 + // The manifest data we test with. 1.100 + 1.101 + gManifestObject = { 1.102 + "version": 1, 1.103 + experiments: [ 1.104 + { 1.105 + id: EXPERIMENT1_ID, 1.106 + xpiURL: gDataRoot + EXPERIMENT1_XPI_NAME, 1.107 + xpiHash: EXPERIMENT1_XPI_SHA1, 1.108 + maxActiveSeconds: 10 * SEC_IN_ONE_DAY, 1.109 + appName: ["XPCShell"], 1.110 + channel: ["nightly"], 1.111 + }, 1.112 + { 1.113 + id: EXPERIMENT2_ID, 1.114 + xpiURL: gDataRoot + EXPERIMENT2_XPI_NAME, 1.115 + xpiHash: EXPERIMENT2_XPI_SHA1, 1.116 + maxActiveSeconds: 10 * SEC_IN_ONE_DAY, 1.117 + appName: ["XPCShell"], 1.118 + channel: ["nightly"], 1.119 + }, 1.120 + { 1.121 + id: EXPERIMENT3_ID, 1.122 + xpiURL: "https://inval.id/foo.xpi", 1.123 + xpiHash: "sha1:0000000000000000000000000000000000000000", 1.124 + maxActiveSeconds: 10 * SEC_IN_ONE_DAY, 1.125 + appName: ["XPCShell"], 1.126 + channel: ["nightly"], 1.127 + }, 1.128 + ], 1.129 + }; 1.130 + 1.131 + // Setup dates for the experiments. 1.132 + 1.133 + let baseDate = new Date(2014, 5, 1, 12); 1.134 + let startDates = []; 1.135 + let endDates = []; 1.136 + 1.137 + for (let i=0; i<gManifestObject.experiments.length; ++i) { 1.138 + let experiment = gManifestObject.experiments[i]; 1.139 + startDates.push(futureDate(baseDate, (50 + (150 * i)) * MS_IN_ONE_DAY)); 1.140 + endDates .push(futureDate(startDates[i], 50 * MS_IN_ONE_DAY)); 1.141 + experiment.startTime = dateToSeconds(startDates[i]); 1.142 + experiment.endTime = dateToSeconds(endDates[i]); 1.143 + } 1.144 + 1.145 + // Data to compare the result of Experiments.getExperiments() against. 1.146 + 1.147 + let experimentListData = [ 1.148 + { 1.149 + id: EXPERIMENT2_ID, 1.150 + name: "Test experiment 2", 1.151 + description: "And yet another experiment that experiments experimentally.", 1.152 + }, 1.153 + { 1.154 + id: EXPERIMENT1_ID, 1.155 + name: EXPERIMENT1_NAME, 1.156 + description: "Yet another experiment that experiments experimentally.", 1.157 + }, 1.158 + ]; 1.159 + 1.160 + // Trigger update & re-init, clock set to before any activation. 1.161 + 1.162 + let now = baseDate; 1.163 + defineNow(gPolicy, now); 1.164 + 1.165 + let experiments = new Experiments.Experiments(gPolicy); 1.166 + yield experiments.updateManifest(); 1.167 + let list = yield experiments.getExperiments(); 1.168 + Assert.equal(list.length, 0, "Experiment list should be empty."); 1.169 + checkExperimentSerializations(experiments._experiments.values()); 1.170 + 1.171 + yield experiments.uninit(); 1.172 + experiments = new Experiments.Experiments(gPolicy); 1.173 + 1.174 + yield experiments._run(); 1.175 + list = yield experiments.getExperiments(); 1.176 + Assert.equal(list.length, 0, "Experiment list should be empty."); 1.177 + checkExperimentSerializations(experiments._experiments.values()); 1.178 + 1.179 + // Re-init, clock set for experiment 1 to start. 1.180 + 1.181 + now = futureDate(startDates[0], 5 * MS_IN_ONE_DAY); 1.182 + defineNow(gPolicy, now); 1.183 + 1.184 + yield experiments.uninit(); 1.185 + experiments = new Experiments.Experiments(gPolicy); 1.186 + yield experiments._run(); 1.187 + 1.188 + list = yield experiments.getExperiments(); 1.189 + Assert.equal(list.length, 1, "Experiment list should have 1 entry now."); 1.190 + 1.191 + experimentListData[1].active = true; 1.192 + experimentListData[1].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; 1.193 + checkExperimentListsEqual(experimentListData.slice(1), list); 1.194 + checkExperimentSerializations(experiments._experiments.values()); 1.195 + 1.196 + let branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); 1.197 + Assert.strictEqual(branch, null); 1.198 + 1.199 + yield experiments.setExperimentBranch(EXPERIMENT1_ID, "testbranch"); 1.200 + branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); 1.201 + Assert.strictEqual(branch, "testbranch"); 1.202 + 1.203 + // Re-init, clock set for experiment 1 to stop. 1.204 + 1.205 + now = futureDate(now, 20 * MS_IN_ONE_DAY); 1.206 + defineNow(gPolicy, now); 1.207 + 1.208 + yield experiments.uninit(); 1.209 + experiments = new Experiments.Experiments(gPolicy); 1.210 + yield experiments._run(); 1.211 + 1.212 + list = yield experiments.getExperiments(); 1.213 + Assert.equal(list.length, 1, "Experiment list should have 1 entry."); 1.214 + 1.215 + experimentListData[1].active = false; 1.216 + experimentListData[1].endDate = now.getTime(); 1.217 + checkExperimentListsEqual(experimentListData.slice(1), list); 1.218 + checkExperimentSerializations(experiments._experiments.values()); 1.219 + 1.220 + branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); 1.221 + Assert.strictEqual(branch, "testbranch"); 1.222 + 1.223 + // Re-init, clock set for experiment 2 to start. 1.224 + 1.225 + now = futureDate(startDates[1], 20 * MS_IN_ONE_DAY); 1.226 + defineNow(gPolicy, now); 1.227 + 1.228 + yield experiments.uninit(); 1.229 + experiments = new Experiments.Experiments(gPolicy); 1.230 + yield experiments._run(); 1.231 + 1.232 + list = yield experiments.getExperiments(); 1.233 + Assert.equal(list.length, 2, "Experiment list should have 2 entries."); 1.234 + 1.235 + experimentListData[0].active = true; 1.236 + experimentListData[0].endDate = now.getTime() + 10 * MS_IN_ONE_DAY; 1.237 + checkExperimentListsEqual(experimentListData, list); 1.238 + checkExperimentSerializations(experiments._experiments.values()); 1.239 + 1.240 + // Re-init, clock set for experiment 2 to stop. 1.241 + 1.242 + now = futureDate(now, 20 * MS_IN_ONE_DAY); 1.243 + defineNow(gPolicy, now); 1.244 + 1.245 + yield experiments.uninit(); 1.246 + experiments = new Experiments.Experiments(gPolicy); 1.247 + yield experiments._run(); 1.248 + 1.249 + list = yield experiments.getExperiments(); 1.250 + Assert.equal(list.length, 2, "Experiment list should have 2 entries."); 1.251 + 1.252 + experimentListData[0].active = false; 1.253 + experimentListData[0].endDate = now.getTime(); 1.254 + checkExperimentListsEqual(experimentListData, list); 1.255 + checkExperimentSerializations(experiments._experiments.values()); 1.256 + 1.257 + // Cleanup. 1.258 + 1.259 + yield experiments._toggleExperimentsEnabled(false); 1.260 + yield experiments.uninit(); 1.261 + yield removeCacheFile(); 1.262 +});