michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: "use strict"; michael@0: michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: Cu.import("resource:///modules/experiments/Experiments.jsm"); michael@0: michael@0: const FILE_MANIFEST = "experiments.manifest"; michael@0: const SEC_IN_ONE_DAY = 24 * 60 * 60; michael@0: const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000; michael@0: michael@0: let gProfileDir = null; michael@0: let gHttpServer = null; michael@0: let gHttpRoot = null; michael@0: let gReporter = null; michael@0: let gPolicy = null; michael@0: michael@0: function ManifestEntry(data) { michael@0: this.id = data.id || EXPERIMENT1_ID; michael@0: this.xpiURL = data.xpiURL || gHttpRoot + EXPERIMENT1_XPI_NAME; michael@0: this.xpiHash = data.xpiHash || EXPERIMENT1_XPI_SHA1; michael@0: this.appName = data.appName || ["XPCShell"]; michael@0: this.channel = data.appName || ["nightly"]; michael@0: this.startTime = data.startTime || new Date(2010, 0, 1, 12).getTime() / 1000; michael@0: this.endTime = data.endTime || new Date(9001, 0, 1, 12).getTime() / 1000; michael@0: this.maxActiveSeconds = data.maxActiveSeconds || 5 * SEC_IN_ONE_DAY; michael@0: } michael@0: michael@0: function run_test() { michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_task(function* test_setup() { michael@0: loadAddonManager(); michael@0: gProfileDir = do_get_profile(); michael@0: gPolicy = new Experiments.Policy(); michael@0: michael@0: gHttpServer = new HttpServer(); michael@0: gHttpServer.start(-1); michael@0: let port = gHttpServer.identity.primaryPort; michael@0: gHttpRoot = "http://localhost:" + port + "/"; michael@0: gHttpServer.registerDirectory("/", do_get_cwd()); michael@0: do_register_cleanup(() => gHttpServer.stop(() => {})); michael@0: michael@0: gReporter = yield getReporter("json_payload_simple"); michael@0: yield gReporter.collectMeasurements(); michael@0: let payload = yield gReporter.getJSONPayload(true); michael@0: do_register_cleanup(() => gReporter._shutdown()); michael@0: michael@0: patchPolicy(gPolicy, { michael@0: updatechannel: () => "nightly", michael@0: healthReportPayload: () => Promise.resolve(payload), michael@0: }); michael@0: michael@0: Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true); michael@0: Services.prefs.setIntPref(PREF_LOGGING_LEVEL, 0); michael@0: Services.prefs.setBoolPref(PREF_LOGGING_DUMP, true); michael@0: michael@0: let experiments = new Experiments.Experiments(); michael@0: }); michael@0: michael@0: function isApplicable(experiment) { michael@0: let deferred = Promise.defer(); michael@0: experiment.isApplicable().then( michael@0: result => deferred.resolve({ applicable: true, reason: null }), michael@0: reason => deferred.resolve({ applicable: false, reason: reason }) michael@0: ); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: add_task(function* test_startStop() { michael@0: let baseDate = new Date(2014, 5, 1, 12); michael@0: let startDate = futureDate(baseDate, 30 * MS_IN_ONE_DAY); michael@0: let endDate = futureDate(baseDate, 60 * MS_IN_ONE_DAY); michael@0: let manifestData = new ManifestEntry({ michael@0: startTime: dateToSeconds(startDate), michael@0: endTime: dateToSeconds(endDate), michael@0: maxActiveSeconds: 10 * SEC_IN_ONE_DAY, michael@0: }); michael@0: let experiment = new Experiments.ExperimentEntry(gPolicy); michael@0: experiment.initFromManifestData(manifestData); michael@0: michael@0: // We need to associate it with the singleton so the onInstallStarted michael@0: // Addon Manager listener will know about it. michael@0: Experiments.instance()._experiments = new Map(); michael@0: Experiments.instance()._experiments.set(experiment.id, experiment); michael@0: michael@0: let result; michael@0: michael@0: defineNow(gPolicy, baseDate); michael@0: result = yield isApplicable(experiment); michael@0: Assert.equal(result.applicable, false, "Experiment should not be applicable."); michael@0: Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); michael@0: michael@0: let addons = yield getExperimentAddons(); michael@0: Assert.equal(addons.length, 0, "No experiment add-ons are installed."); michael@0: michael@0: defineNow(gPolicy, futureDate(startDate, 5 * MS_IN_ONE_DAY)); michael@0: result = yield isApplicable(experiment); michael@0: Assert.equal(result.applicable, true, "Experiment should now be applicable."); michael@0: Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); michael@0: michael@0: let changes = yield experiment.start(); michael@0: Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed."); michael@0: addons = yield getExperimentAddons(); michael@0: Assert.equal(experiment.enabled, true, "Experiment should now be enabled."); michael@0: Assert.equal(addons.length, 1, "1 experiment add-on is installed."); michael@0: Assert.equal(addons[0].id, experiment._addonId, "The add-on is the one we expect."); michael@0: Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled."); michael@0: Assert.ok(addons[0].isActive, "The add-on is active."); michael@0: michael@0: changes = yield experiment.stop(); michael@0: Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on was uninstalled."); michael@0: addons = yield getExperimentAddons(); michael@0: Assert.equal(experiment.enabled, false, "Experiment should not be enabled."); michael@0: Assert.equal(addons.length, 0, "Experiment should be uninstalled from the Addon Manager."); michael@0: michael@0: changes = yield experiment.start(); michael@0: Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL, "Add-on was installed."); michael@0: addons = yield getExperimentAddons(); michael@0: Assert.equal(experiment.enabled, true, "Experiment should now be enabled."); michael@0: Assert.equal(addons.length, 1, "1 experiment add-on is installed."); michael@0: Assert.equal(addons[0].id, experiment._addonId, "The add-on is the one we expect."); michael@0: Assert.equal(addons[0].userDisabled, false, "The add-on is not userDisabled."); michael@0: Assert.ok(addons[0].isActive, "The add-on is active."); michael@0: michael@0: let result = yield experiment.shouldStop(); michael@0: Assert.equal(result.shouldStop, false, "shouldStop should be false."); michael@0: Assert.equal(experiment.enabled, true, "Experiment should be enabled."); michael@0: addons = yield getExperimentAddons(); michael@0: Assert.equal(addons.length, 1, "Experiment still in add-ons manager."); michael@0: Assert.ok(addons[0].isActive, "The add-on is still active."); michael@0: michael@0: defineNow(gPolicy, futureDate(endDate, MS_IN_ONE_DAY)); michael@0: result = yield experiment.shouldStop(); michael@0: Assert.equal(result.shouldStop, true, "shouldStop should now be true."); michael@0: changes = yield experiment.stop(); michael@0: Assert.equal(changes, experiment.ADDON_CHANGE_UNINSTALL, "Add-on should be uninstalled."); michael@0: Assert.equal(experiment.enabled, false, "Experiment should be disabled."); michael@0: addons = yield getExperimentAddons(); michael@0: Assert.equal(addons.length, 0, "Experiment add-on is uninstalled."); michael@0: michael@0: // Ensure hash validation works. michael@0: // We set an incorrect hash and expect the install to fail. michael@0: experiment._manifestData.xpiHash = "sha1:41014dcc66b4dcedcd973491a1530a32f0517d8a"; michael@0: let errored = false; michael@0: try { michael@0: yield experiment.start(); michael@0: } catch (ex) { michael@0: errored = true; michael@0: } michael@0: Assert.ok(experiment._failedStart, "Experiment failed to start."); michael@0: Assert.ok(errored, "start() threw an exception."); michael@0: michael@0: // Make sure "ignore hashes" mode works. michael@0: gPolicy.ignoreHashes = true; michael@0: let changes = yield experiment.start(); michael@0: Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL); michael@0: yield experiment.stop(); michael@0: gPolicy.ignoreHashes = false; michael@0: });