зеркало из https://github.com/mozilla/gecko-dev.git
Bug 551716: Need a way to remote-kill studies. r+a=dtownsend DONTBUILD
This commit is contained in:
Родитель
0f59bb3f99
Коммит
345ecc4580
|
@ -176,8 +176,6 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
_init: function(logRepo, fileGetterFunction) {
|
||||
this._logger = logRepo.getLogger("TestPilot.Loader");
|
||||
this._expLogger = logRepo.getLogger("TestPilot.RemoteCode");
|
||||
this._studyResults = [];
|
||||
this._legacyStudies = [];
|
||||
let prefs = require("preferences-service");
|
||||
this._baseUrl = prefs.get(BASE_URL_PREF, "");
|
||||
if (fileGetterFunction != undefined) {
|
||||
|
@ -187,7 +185,6 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
}
|
||||
this._logger.trace("About to instantiate jar store.");
|
||||
this._jarStore = new JarStore();
|
||||
this._experimentFileNames = [];
|
||||
let self = this;
|
||||
this._logger.trace("About to instantiate cuddlefish loader.");
|
||||
this._refreshLoader();
|
||||
|
@ -217,6 +214,11 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
[self._jarStore, Cuddlefish.parentLoader.fs]),
|
||||
console: this._expLogger
|
||||
});
|
||||
|
||||
// Clear all of our lists of studies/surveys/results when refreshing loader
|
||||
this._studyResults = [];
|
||||
this._legacyStudies = [];
|
||||
this._experimentFileNames = [];
|
||||
},
|
||||
|
||||
getLocalizedStudyInfo: function(studiesIndex) {
|
||||
|
@ -260,13 +262,35 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
this._studyResults = data.results;
|
||||
this._legacyStudies = data.legacy;
|
||||
|
||||
/* Go through each record indicated in index.json for our locale;
|
||||
* download the specified .jar file (replacing any version on disk)
|
||||
|
||||
/* Look in the "maintain_experiments" section of the index file. Experiments
|
||||
* listed here should be run IF we alrady have the code present on disk, but should
|
||||
* not be downloaded if we don't already have them.
|
||||
*/
|
||||
if (data.maintain_experiments) {
|
||||
this._logger.trace(data.maintain_experiments.length + " files to maintain.\n");
|
||||
for each (let studyFile in data.maintain_experiments) {
|
||||
this._experimentFileNames.push(studyFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look in the "new_experiments" section of the index file for new jar files
|
||||
* to download. Go through each record indicated in index.json, look up the
|
||||
* .jar file specified for our locale, and download it (replacing any version
|
||||
* on disk)
|
||||
*/
|
||||
let jarFiles = this.getLocalizedStudyInfo(data.new_experiments);
|
||||
let numFilesToDload = jarFiles.length;
|
||||
this._logger.trace(numFilesToDload + " files to download.\n");
|
||||
let self = this;
|
||||
|
||||
if (numFilesToDload == 0) {
|
||||
this._logger.trace("Num files to download is 0, bailing\n");
|
||||
// nothing has changed --> callback false
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
for each (let j in jarFiles) {
|
||||
let filename = j.jarfile;
|
||||
let hash = j.hash;
|
||||
|
@ -310,6 +334,13 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
this._studyResults = data.results;
|
||||
this._legacyStudies = data.legacy;
|
||||
|
||||
// Studies to be maintained:
|
||||
if (data.maintain_experiments) {
|
||||
for each (let studyFile in data.maintain_experiments) {
|
||||
this._experimentFileNames.push(studyFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Read names of experiment modules from index.
|
||||
let jarFiles = this.getLocalizedStudyInfo(data.new_experiments);
|
||||
for each (let j in jarFiles) {
|
||||
|
@ -447,9 +478,11 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
let url = resolveUrl(self._baseUrl, indexFileName);
|
||||
self._fileGetter(url, function onDone(data) {
|
||||
if (data) {
|
||||
self._logger.trace("Index file updated on server.\n");
|
||||
self._executeFreshIndexFile(data, callback);
|
||||
// cache index file contents so we can read them later if we can't get online.
|
||||
self._cacheIndexFile(data);
|
||||
// executeFreshIndexFile will call the callback.
|
||||
} else {
|
||||
self._logger.info("Could not download index.json, using cached version.");
|
||||
let data = self._loadCachedIndexFile();
|
||||
|
@ -501,4 +534,3 @@ exports.RemoteExperimentLoader.prototype = {
|
|||
|
||||
// TODO but once the study is expired, should delete the jar for it and
|
||||
// just load the LegacyStudy version.
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@ var Ci = Components.interfaces;
|
|||
var testsRun = 0;
|
||||
var testsPassed = 0;
|
||||
|
||||
function base64decode(data) {
|
||||
// base64 encode/decode is built into window object, but we're in a module so we
|
||||
// need to fetch a window reference first:
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
let window = wm.getMostRecentWindow("navigator:browser");
|
||||
return window.atob(data);
|
||||
}
|
||||
|
||||
function cheapAssertEqual(a, b, errorMsg) {
|
||||
testsRun += 1;
|
||||
if (a == b) {
|
||||
|
@ -249,7 +258,7 @@ function testRemoteLoader() {
|
|||
}
|
||||
};
|
||||
|
||||
let remoteLoader = new remoteLoaderModule.RemoteExperimentLoader(getFileFunc);
|
||||
let remoteLoader = new remoteLoaderModule.RemoteExperimentLoader(stubLogger, getFileFunc);
|
||||
|
||||
remoteLoader.checkForUpdates(function(success) {
|
||||
if (success) {
|
||||
|
@ -291,6 +300,14 @@ function testRemotelyLoadTabsExperiment() {
|
|||
// (~/testpilot/website/testcases/tab-open-close/tabs_experiment.js)
|
||||
}
|
||||
|
||||
let stubLogger = {
|
||||
getLogger: function() { return {trace: function(str) {dump("Trace: " + str +"\n");},
|
||||
warn: function(str) {dump("Warn: " + str +"\n");},
|
||||
info: function(str) {dump("Info: " + str +"\n");},
|
||||
debug: function(str) {dump("Debug: " + str +"\n");}};}
|
||||
};
|
||||
|
||||
|
||||
function testRemoteLoaderIndexCache() {
|
||||
var Cuddlefish = {};
|
||||
Cu.import("resource://testpilot/modules/lib/cuddlefish.js",
|
||||
|
@ -303,17 +320,17 @@ function testRemoteLoaderIndexCache() {
|
|||
callback(null);
|
||||
};
|
||||
|
||||
let stubLogger = {
|
||||
getLogger: function() { return {trace: function() {},
|
||||
warn: function() {},
|
||||
info: function() {},
|
||||
debug: function() {}};}
|
||||
};
|
||||
|
||||
let remoteLoader = new remoteLoaderModule.RemoteExperimentLoader(stubLogger, getFileFunc);
|
||||
let data = "Foo bar baz quux";
|
||||
remoteLoader._cacheIndexFile(data);
|
||||
cheapAssertEqual(remoteLoader._loadCachedIndexFile(), data);
|
||||
|
||||
// Clean up by killing the file so we don't break Test Pilot so bad
|
||||
dump("Killing the mungled index file.\n");
|
||||
let indexFile = remoteLoader.cachedIndexNsiFile;
|
||||
if (indexFile.exists()) {
|
||||
indexFile.remove(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -532,13 +549,17 @@ function testRecurringStudyStateChange() {
|
|||
|
||||
|
||||
function runAllTests() {
|
||||
testTheDataStore();
|
||||
testFirefoxVersionCheck();
|
||||
testStringSanitizer();
|
||||
testsRun = 0;
|
||||
testsPassed = 0;
|
||||
|
||||
//testTheDataStore();
|
||||
//testFirefoxVersionCheck();
|
||||
//testStringSanitizer();
|
||||
//testTheCuddlefishPreferencesFilesystem();
|
||||
//testRemoteLoader();
|
||||
testRemoteLoaderIndexCache();
|
||||
testRecurringStudyStateChange();
|
||||
//testRemoteLoaderIndexCache();
|
||||
//testRecurringStudyStateChange();
|
||||
testKillSwitch();
|
||||
dump("TESTING COMPLETE. " + testsPassed + " out of " + testsRun +
|
||||
" tests passed.");
|
||||
}
|
||||
|
@ -551,4 +572,123 @@ function runAllTests() {
|
|||
|
||||
// Test that every observer that is installed gets uninstalled.
|
||||
|
||||
// Test that the observer is writing to the data store correctly.
|
||||
// Test that the observer is writing to the data store correctly.
|
||||
|
||||
function testKillSwitch() {
|
||||
var Cuddlefish = {};
|
||||
Cu.import("resource://testpilot/modules/lib/cuddlefish.js",
|
||||
Cuddlefish);
|
||||
let cfl = new Cuddlefish.Loader({rootPaths: ["resource://testpilot/modules/",
|
||||
"resource://testpilot/modules/lib/"]});
|
||||
let remoteLoaderModule = cfl.require("remote-experiment-loader");
|
||||
|
||||
var indexJson1 = '{"new_experiments": [{"default": {"name": "Foo Study", '
|
||||
+ '"jarfile": "foo.jar", "studyfile": "foo.js",'
|
||||
+ '"hash": "19f32c805f93697e1b180a782bc7a8c7575f32138008d2617e9843a9bde14b38"}}]}';
|
||||
|
||||
var indexJson2 = '{"new_experiments": [], "maintain_experiments": ["foo.js"]}';
|
||||
var indexJson3 = '{"new_experiments": []}';
|
||||
|
||||
var indexJson = indexJson1;
|
||||
|
||||
var theRemoteFile = "exports.foo = function(x, y) { return x * y; }";
|
||||
|
||||
let getFileFunc = function(url, callback) {
|
||||
if (url.indexOf("index.json") > -1 || url.indexOf("index-dev.json") > -1) {
|
||||
if (indexJson != "") {
|
||||
callback(indexJson);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
} else if (url.indexOf("foo.jar") > -1) {
|
||||
// Binary file (got this by base64encoding foo.jar):
|
||||
callback(base64decode(
|
||||
'UEsDBBQACAAIAFd2Pj4AAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAAA' +
|
||||
'AFBLAwQUAAgACABXdj4+AAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7R' +
|
||||
'DUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAmY6RnEGxkpaDgWFOSkKnjmJetp8nLxcgEAUEsHCPlAfs88' +
|
||||
'AAAAPAAAAFBLAwQUAAgACAA1dj4+AAAAAAAAAAAAAAAABgAAAGZvby5qc0utKMgvKinWS8vPV7BVSCvN' +
|
||||
'Sy7JzM/TqNBRqNRUqFYoSi0pLcpTqFDQUqi0Vqi1BgBQSwcIGwhXqzEAAAAvAAAAUEsBAhQAFAAIAAgA' +
|
||||
'V3Y+PgAAAAACAAAAAAAAAAkABAAAAAAAAAAAAAAAAAAAAE1FVEEtSU5GL/7KAABQSwECFAAUAAgACABX' +
|
||||
'dj4++UB+zzwAAAA8AAAAFAAAAAAAAAAAAAAAAAA9AAAATUVUQS1JTkYvTUFOSUZFU1QuTUZQSwECFAAU' +
|
||||
'AAgACAA1dj4+GwhXqzEAAAAvAAAABgAAAAAAAAAAAAAAAAC7AAAAZm9vLmpzUEsFBgAAAAADAAMAsQAA' +
|
||||
'ACABAAAAAA=='));
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
};
|
||||
|
||||
let remoteLoader = new remoteLoaderModule.RemoteExperimentLoader(stubLogger, getFileFunc);
|
||||
|
||||
function clearIndexFileCache() {
|
||||
// TODO this needs to go in a teardown
|
||||
dump("Killing the mungled index file.\n");
|
||||
let indexFile = remoteLoader.cachedIndexNsiFile;
|
||||
if (indexFile.exists()) {
|
||||
indexFile.remove(false);
|
||||
}
|
||||
}
|
||||
|
||||
dump("Preparing To Test Kill Switch!!!\n");
|
||||
remoteLoader.checkForUpdates(function(hasChanges) {
|
||||
if (hasChanges) {
|
||||
dump("Testing that foo study is loaded.\n");
|
||||
let exp = remoteLoader.getExperiments();
|
||||
let count = 0;
|
||||
for (let i in exp) {
|
||||
count += 1;
|
||||
}
|
||||
cheapAssertEqual(count, 1, "Supposed to find one file.");
|
||||
let fooModule = exp["foo.js"];
|
||||
cheapAssertEqual(fooModule.foo(3, 4), 12, "Supposed to load the foo module.\n");
|
||||
} else {
|
||||
cheapAssertFail("checkForUpdates is supposed to find changes.");
|
||||
}
|
||||
|
||||
/* Now we change the index file and call checkForUpdates again... test that:
|
||||
* a. with indexJson2, the Foo Study continues to run.
|
||||
* b. with indexJson3, the Foo Study stops immediately.
|
||||
* */
|
||||
clearIndexFileCache();
|
||||
indexJson = indexJson2;
|
||||
dump("Preparing to check for updates 2nd time.\n");
|
||||
remoteLoader.checkForUpdates( function(hasChanges) {
|
||||
dump("in the callback for check for updates 2nd time.\n");
|
||||
if (hasChanges) {
|
||||
dump("checkforUpdates 2nd time - has changes.\n");
|
||||
} else {
|
||||
dump("checkforUpdates 2nd time - does not have changes.\n");
|
||||
}
|
||||
|
||||
dump("Testing that foo study is loaded. (2nd time)\n");
|
||||
let exp = remoteLoader.getExperiments();
|
||||
let count = 0;
|
||||
for (let i in exp) {
|
||||
count += 1;
|
||||
}
|
||||
cheapAssertEqual(count, 1, "Supposed to find one file (2nd time).");
|
||||
let fooModule = exp["foo.js"];
|
||||
cheapAssertEqual(fooModule.foo(3, 4), 12, "Supposed to load the foo module (2).\n");
|
||||
|
||||
|
||||
clearIndexFileCache();
|
||||
indexJson = indexJson3;
|
||||
remoteLoader.checkForUpdates( function(hasChanges) {
|
||||
if (hasChanges) {
|
||||
dump("checkForUpdates 3rd time - has changes.\n");
|
||||
} else {
|
||||
dump("checkForUpdates 3rd time - has no changes.\n");
|
||||
}
|
||||
|
||||
dump("Testing that foo study is NOT loaded. (3rd time)\n");
|
||||
let exp = remoteLoader.getExperiments();
|
||||
let count = 0;
|
||||
for (let i in exp) {
|
||||
count += 1;
|
||||
}
|
||||
cheapAssertEqual(count, 0, "File should be killed!\n");
|
||||
|
||||
clearIndexFileCache();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Загрузка…
Ссылка в новой задаче