зеркало из https://github.com/mozilla/gecko-dev.git
Bug 686019 - Add support for testing addon sync in TPS. r=mconnor
This commit is contained in:
Родитель
cdebc6cee7
Коммит
30d1a0559e
|
@ -0,0 +1,50 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* The list of phases mapped to their corresponding profiles. The object
|
||||
* here must be in strict JSON format, as it will get parsed by the Python
|
||||
* testrunner (no single quotes, extra comma's, etc).
|
||||
*/
|
||||
|
||||
var phases = { "phase1": "profile1",
|
||||
"phase2": "profile1",
|
||||
"phase3": "profile1",
|
||||
"phase4": "profile1",
|
||||
"phase5": "profile1" };
|
||||
|
||||
/*
|
||||
* Test phases
|
||||
*/
|
||||
|
||||
Phase('phase1', [
|
||||
[Addons.install, ['unsigned-1.0.xml']],
|
||||
[Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED],
|
||||
[Sync, SYNC_WIPE_SERVER],
|
||||
]);
|
||||
|
||||
Phase('phase2', [
|
||||
[Sync],
|
||||
[Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED],
|
||||
[Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED],
|
||||
[Sync],
|
||||
]);
|
||||
|
||||
Phase('phase3', [
|
||||
[Sync],
|
||||
[Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED],
|
||||
[Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED],
|
||||
[Sync],
|
||||
]);
|
||||
|
||||
Phase('phase4', [
|
||||
[Sync],
|
||||
[Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED],
|
||||
[Addons.uninstall, ['unsigned-xpi@tests.mozilla.org']],
|
||||
[Sync],
|
||||
]);
|
||||
|
||||
Phase('phase5', [
|
||||
[Sync],
|
||||
[Addons.verifyNot, ['unsigned-xpi@tests.mozilla.org']],
|
||||
]);
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<searchresults total_results="1">
|
||||
<addon id="5612">
|
||||
<name>Unsigned Test XPI</name>
|
||||
<type id="1">Extension</type>
|
||||
<guid>unsigned-xpi@tests.mozilla.org</guid>
|
||||
<slug>unsigned-xpi</slug>
|
||||
<version>1.0</version>
|
||||
|
||||
<compatible_applications><application>
|
||||
<name>Firefox</name>
|
||||
<application_id>1</application_id>
|
||||
<min_version>3.6</min_version>
|
||||
<max_version>*</max_version>
|
||||
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
|
||||
</application></compatible_applications>
|
||||
<all_compatible_os><os>ALL</os></all_compatible_os>
|
||||
|
||||
<install os="ALL" size="452">http://127.0.0.1:4567/unsigned-1.0.xpi</install>
|
||||
<created epoch="1252903662">
|
||||
2009-09-14T04:47:42Z
|
||||
</created>
|
||||
<last_updated epoch="1315255329">
|
||||
2011-09-05T20:42:09Z
|
||||
</last_updated>
|
||||
</addon>
|
||||
</searchresults>
|
Двоичный файл не отображается.
|
@ -0,0 +1,252 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Crossweave.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonathan Griffin <jgriffin@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Addon", "STATE_ENABLED", "STATE_DISABLED"];
|
||||
|
||||
const CC = Components.classes;
|
||||
const CI = Components.interfaces;
|
||||
const CU = Components.utils;
|
||||
|
||||
CU.import("resource://gre/modules/AddonManager.jsm");
|
||||
CU.import("resource://gre/modules/AddonRepository.jsm");
|
||||
CU.import("resource://gre/modules/Services.jsm");
|
||||
CU.import("resource://services-sync/async.js");
|
||||
CU.import("resource://services-sync/util.js");
|
||||
CU.import("resource://tps/logger.jsm");
|
||||
var XPIProvider = CU.import("resource://gre/modules/XPIProvider.jsm")
|
||||
.XPIProvider;
|
||||
|
||||
const ADDONSGETURL = 'http://127.0.0.1:4567/';
|
||||
const STATE_ENABLED = 1;
|
||||
const STATE_DISABLED = 2;
|
||||
|
||||
function GetFileAsText(file)
|
||||
{
|
||||
let channel = Services.io.newChannel(file, null, null);
|
||||
let inputStream = channel.open();
|
||||
if (channel instanceof CI.nsIHttpChannel &&
|
||||
channel.responseStatus != 200) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let streamBuf = "";
|
||||
let sis = CC["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(CI.nsIScriptableInputStream);
|
||||
sis.init(inputStream);
|
||||
|
||||
let available;
|
||||
while ((available = sis.available()) != 0) {
|
||||
streamBuf += sis.read(available);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
return streamBuf;
|
||||
}
|
||||
|
||||
function Addon(TPS, id) {
|
||||
this.TPS = TPS;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
Addon.prototype = {
|
||||
_addons_requiring_restart: [],
|
||||
_addons_pending_install: [],
|
||||
|
||||
Delete: function() {
|
||||
// find our addon locally
|
||||
let cb = Async.makeSyncCallback();
|
||||
XPIProvider.getAddonsByTypes(null, cb);
|
||||
let results = Async.waitForSyncCallback(cb);
|
||||
var addon;
|
||||
var id = this.id;
|
||||
results.forEach(function(result) {
|
||||
if (result.id == id) {
|
||||
addon = result;
|
||||
}
|
||||
});
|
||||
Logger.AssertTrue(!!addon, 'could not find addon ' + this.id + ' to uninstall');
|
||||
addon.uninstall();
|
||||
},
|
||||
|
||||
Find: function(state) {
|
||||
let cb = Async.makeSyncCallback();
|
||||
let addon_found = false;
|
||||
var that = this;
|
||||
|
||||
var log_addon = function(addon) {
|
||||
that.addon = addon;
|
||||
Logger.logInfo('addon ' + addon.id + ' found, isActive: ' + addon.isActive);
|
||||
if (state == STATE_ENABLED || state == STATE_DISABLED) {
|
||||
Logger.AssertEqual(addon.isActive,
|
||||
state == STATE_ENABLED ? true : false,
|
||||
"addon " + that.id + " has an incorrect enabled state");
|
||||
}
|
||||
};
|
||||
|
||||
// first look in the list of all addons
|
||||
XPIProvider.getAddonsByTypes(null, cb);
|
||||
let addonlist = Async.waitForSyncCallback(cb);
|
||||
addonlist.forEach(function(addon) {
|
||||
if (addon.id == that.id) {
|
||||
addon_found = true;
|
||||
log_addon.call(that, addon);
|
||||
}
|
||||
});
|
||||
|
||||
if (!addon_found) {
|
||||
// then look in the list of recent installs
|
||||
cb = Async.makeSyncCallback();
|
||||
XPIProvider.getInstallsByTypes(null, cb);
|
||||
addonlist = Async.waitForSyncCallback(cb);
|
||||
for (var i in addonlist) {
|
||||
if (addonlist[i].addon && addonlist[i].addon.id == that.id &&
|
||||
addonlist[i].state == AddonManager.STATE_INSTALLED) {
|
||||
addon_found = true;
|
||||
log_addon.call(that, addonlist[i].addon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return addon_found;
|
||||
},
|
||||
|
||||
Install: function() {
|
||||
// For Install, the id parameter initially passed is really the filename
|
||||
// for the addon's install .xml; we'll read the actual id from the .xml.
|
||||
let url = this.id;
|
||||
|
||||
// set the url used by getAddonsByIDs
|
||||
var prefs = CC["@mozilla.org/preferences-service;1"]
|
||||
.getService(CI.nsIPrefBranch);
|
||||
prefs.setCharPref('extensions.getAddons.get.url', ADDONSGETURL + url);
|
||||
|
||||
// read the XML and find the addon id
|
||||
xml = GetFileAsText(ADDONSGETURL + url);
|
||||
Logger.AssertTrue(xml.indexOf("<guid>") > -1, 'guid not found in ' + url);
|
||||
this.id = xml.substring(xml.indexOf("<guid>") + 6, xml.indexOf("</guid"));
|
||||
Logger.logInfo('addon XML = ' + this.id);
|
||||
|
||||
// find our addon on 'AMO'
|
||||
let cb = Async.makeSyncCallback();
|
||||
AddonRepository.getAddonsByIDs([this.id], {
|
||||
searchSucceeded: cb,
|
||||
searchFailed: cb
|
||||
}, false);
|
||||
|
||||
// Result will be array of addons on searchSucceeded or undefined on
|
||||
// searchFailed.
|
||||
let install_addons = Async.waitForSyncCallback(cb);
|
||||
|
||||
Logger.AssertTrue(install_addons,
|
||||
"no addons found for id " + this.id);
|
||||
Logger.AssertEqual(install_addons.length,
|
||||
1,
|
||||
"multiple addons found for id " + this.id);
|
||||
|
||||
let addon = install_addons[0];
|
||||
Logger.logInfo(JSON.stringify(addon), null, ' ');
|
||||
if (XPIProvider.installRequiresRestart(addon)) {
|
||||
this._addons_requiring_restart.push(addon.id);
|
||||
}
|
||||
|
||||
// Start installing the addon asynchronously; finish up in
|
||||
// onInstallEnded(), onInstallFailed(), or onDownloadFailed().
|
||||
this._addons_pending_install.push(addon.id);
|
||||
this.TPS.StartAsyncOperation();
|
||||
|
||||
Utils.nextTick(function() {
|
||||
let callback = function(aInstall) {
|
||||
addon.install = aInstall;
|
||||
Logger.logInfo("addon install: " + addon.install);
|
||||
Logger.AssertTrue(addon.install,
|
||||
"could not get install object for id " + this.id);
|
||||
addon.install.addListener(this);
|
||||
addon.install.install();
|
||||
};
|
||||
|
||||
AddonManager.getInstallForURL(addon.sourceURI.spec,
|
||||
callback.bind(this),
|
||||
"application/x-xpinstall");
|
||||
}, this);
|
||||
},
|
||||
|
||||
SetState: function(state) {
|
||||
if (!this.Find())
|
||||
return false;
|
||||
this.addon.userDisabled = state == STATE_ENABLED ? false : true;
|
||||
return true;
|
||||
},
|
||||
|
||||
// addon installation callbacks
|
||||
onInstallEnded: function(addon) {
|
||||
try {
|
||||
Logger.logInfo('--------- event observed: addon onInstallEnded');
|
||||
Logger.AssertTrue(addon.addon,
|
||||
"No addon object in addon instance passed to onInstallEnded");
|
||||
Logger.AssertTrue(this._addons_pending_install.indexOf(addon.addon.id) > -1,
|
||||
"onInstallEnded received for unexpected addon " + addon.addon.id);
|
||||
this._addons_pending_install.splice(
|
||||
this._addons_pending_install.indexOf(addon.addon.id),
|
||||
1);
|
||||
}
|
||||
catch(e) {
|
||||
// We can't throw during a callback, as it will just get eaten by
|
||||
// the callback's caller.
|
||||
Utils.nextTick(function() {
|
||||
this.DumpError(e);
|
||||
}, this);
|
||||
return;
|
||||
}
|
||||
this.TPS.FinishAsyncOperation();
|
||||
},
|
||||
|
||||
onInstallFailed: function(addon) {
|
||||
Logger.logInfo('--------- event observed: addon onInstallFailed');
|
||||
Utils.nextTick(function() {
|
||||
this.DumpError('Installation failed for addon ' +
|
||||
(addon.addon && addon.addon.id ? addon.addon.id : 'unknown'));
|
||||
}, this);
|
||||
},
|
||||
|
||||
onDownloadFailed: function(addon) {
|
||||
Logger.logInfo('--------- event observed: addon onDownloadFailed');
|
||||
Utils.nextTick(function() {
|
||||
this.DumpError('Download failed for addon ' +
|
||||
(addon.addon && addon.addon.id ? addon.addon.id : 'unknown'));
|
||||
}, this);
|
||||
},
|
||||
|
||||
};
|
|
@ -48,9 +48,11 @@ const CU = Components.utils;
|
|||
|
||||
CU.import("resource://services-sync/service.js");
|
||||
CU.import("resource://services-sync/constants.js");
|
||||
CU.import("resource://services-sync/async.js");
|
||||
CU.import("resource://services-sync/util.js");
|
||||
CU.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
CU.import("resource://gre/modules/Services.jsm");
|
||||
CU.import("resource://tps/addons.jsm");
|
||||
CU.import("resource://tps/bookmarks.jsm");
|
||||
CU.import("resource://tps/logger.jsm");
|
||||
CU.import("resource://tps/passwords.jsm");
|
||||
|
@ -61,6 +63,8 @@ CU.import("resource://tps/tabs.jsm");
|
|||
|
||||
var hh = CC["@mozilla.org/network/protocol;1?name=http"]
|
||||
.getService(CI.nsIHttpProtocolHandler);
|
||||
var prefs = CC["@mozilla.org/preferences-service;1"]
|
||||
.getService(CI.nsIPrefBranch);
|
||||
|
||||
var mozmillInit = {};
|
||||
CU.import('resource://mozmill/modules/init.js', mozmillInit);
|
||||
|
@ -73,37 +77,16 @@ const ACTION_SYNC = "sync";
|
|||
const ACTION_DELETE = "delete";
|
||||
const ACTION_PRIVATE_BROWSING = "private-browsing";
|
||||
const ACTION_WIPE_SERVER = "wipe-server";
|
||||
const ACTION_SETSTATE = "set-state";
|
||||
const ACTIONS = [ACTION_ADD, ACTION_VERIFY, ACTION_VERIFY_NOT,
|
||||
ACTION_MODIFY, ACTION_SYNC, ACTION_DELETE,
|
||||
ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER];
|
||||
ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER,
|
||||
ACTION_SETSTATE];
|
||||
|
||||
const SYNC_WIPE_SERVER = "wipe-server";
|
||||
const SYNC_RESET_CLIENT = "reset-client";
|
||||
const SYNC_WIPE_CLIENT = "wipe-client";
|
||||
|
||||
function GetFileAsText(file)
|
||||
{
|
||||
let channel = Services.io.newChannel(file, null, null);
|
||||
let inputStream = channel.open();
|
||||
if (channel instanceof CI.nsIHttpChannel &&
|
||||
channel.responseStatus != 200) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let streamBuf = "";
|
||||
let sis = CC["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(CI.nsIScriptableInputStream);
|
||||
sis.init(inputStream);
|
||||
|
||||
let available;
|
||||
while ((available = sis.available()) != 0) {
|
||||
streamBuf += sis.read(available);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
return streamBuf;
|
||||
}
|
||||
|
||||
var TPS =
|
||||
{
|
||||
_waitingForSync: false,
|
||||
|
@ -351,6 +334,33 @@ var TPS =
|
|||
}
|
||||
},
|
||||
|
||||
HandleAddons: function (addons, action, state) {
|
||||
for (var i in addons) {
|
||||
Logger.logInfo("executing action " + action.toUpperCase() +
|
||||
" on addon " + JSON.stringify(addons[i]));
|
||||
var addon = new Addon(this, addons[i]);
|
||||
switch(action) {
|
||||
case ACTION_ADD:
|
||||
addon.Install();
|
||||
break;
|
||||
case ACTION_DELETE:
|
||||
addon.Delete();
|
||||
break;
|
||||
case ACTION_VERIFY:
|
||||
Logger.AssertTrue(addon.Find(state), 'addon ' + addon.id + ' not found');
|
||||
break;
|
||||
case ACTION_VERIFY_NOT:
|
||||
Logger.AssertTrue(!addon.Find(state), 'addon ' + addon.id + " is present, but it shouldn't be");
|
||||
break;
|
||||
case ACTION_SETSTATE:
|
||||
Logger.AssertTrue(addon.SetState(state), 'addon ' + addon.id + ' not found');
|
||||
break;
|
||||
}
|
||||
}
|
||||
Logger.logPass("executing action " + action.toUpperCase() +
|
||||
" on addons");
|
||||
},
|
||||
|
||||
HandleBookmarks: function (bookmarks, action) {
|
||||
try {
|
||||
let items = [];
|
||||
|
@ -460,7 +470,7 @@ var TPS =
|
|||
let phase = this._phaselist["phase" + this._currentPhase];
|
||||
let action = phase[this._currentAction];
|
||||
Logger.logInfo("starting action: " + JSON.stringify(action));
|
||||
action[0].call(this, action[1]);
|
||||
action[0].apply(this, action.slice(1));
|
||||
|
||||
// if we're in an async operation, don't continue on to the next action
|
||||
if (this._operations_pending)
|
||||
|
@ -517,8 +527,6 @@ var TPS =
|
|||
|
||||
// Store account details as prefs so they're accessible to the mozmill
|
||||
// framework.
|
||||
let prefs = CC["@mozilla.org/preferences-service;1"]
|
||||
.getService(CI.nsIPrefBranch);
|
||||
prefs.setCharPref('tps.account.username', this.config.account.username);
|
||||
prefs.setCharPref('tps.account.password', this.config.account.password);
|
||||
prefs.setCharPref('tps.account.passphrase', this.config.account.passphrase);
|
||||
|
@ -634,6 +642,24 @@ var TPS =
|
|||
},
|
||||
};
|
||||
|
||||
var Addons = {
|
||||
install: function Addons__install(addons) {
|
||||
TPS.HandleAddons(addons, ACTION_ADD);
|
||||
},
|
||||
setState: function Addons__setState(addons, state) {
|
||||
TPS.HandleAddons(addons, ACTION_SETSTATE, state);
|
||||
},
|
||||
uninstall: function Addons__uninstall(addons) {
|
||||
TPS.HandleAddons(addons, ACTION_DELETE);
|
||||
},
|
||||
verify: function Addons__verify(addons, state) {
|
||||
TPS.HandleAddons(addons, ACTION_VERIFY, state);
|
||||
},
|
||||
verifyNot: function Addons__verifyNot(addons) {
|
||||
TPS.HandleAddons(addons, ACTION_VERIFY_NOT);
|
||||
},
|
||||
};
|
||||
|
||||
var Bookmarks = {
|
||||
add: function Bookmarks__add(bookmarks) {
|
||||
TPS.HandleBookmarks(bookmarks, ACTION_ADD);
|
||||
|
|
|
@ -38,4 +38,5 @@
|
|||
from firefoxrunner import TPSFirefoxRunner
|
||||
from pulse import TPSPulseMonitor
|
||||
from testrunner import TPSTestRunner
|
||||
from mozhttpd import MozHttpd
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Joel Maher <joel.maher@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import BaseHTTPServer
|
||||
import SimpleHTTPServer
|
||||
import threading
|
||||
import sys
|
||||
import os
|
||||
import urllib
|
||||
import re
|
||||
from urlparse import urlparse
|
||||
from SocketServer import ThreadingMixIn
|
||||
|
||||
DOCROOT = '.'
|
||||
|
||||
class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
||||
allow_reuse_address = True
|
||||
|
||||
class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
def translate_path(self, path):
|
||||
# It appears that the default path is '/' and os.path.join makes the '/'
|
||||
o = urlparse(path)
|
||||
return "%s%s" % ('' if sys.platform == 'win32' else '/', '/'.join([i.strip('/') for i in (DOCROOT, o.path)]))
|
||||
|
||||
# I found on my local network that calls to this were timing out
|
||||
# I believe all of these calls are from log_message
|
||||
def address_string(self):
|
||||
return "a.b.c.d"
|
||||
|
||||
# This produces a LOT of noise
|
||||
def log_message(self, format, *args):
|
||||
pass
|
||||
|
||||
class MozHttpd(object):
|
||||
def __init__(self, host="127.0.0.1", port=8888, docroot='.'):
|
||||
global DOCROOT
|
||||
self.host = host
|
||||
self.port = int(port)
|
||||
DOCROOT = docroot
|
||||
|
||||
def start(self):
|
||||
self.httpd = EasyServer((self.host, self.port), MozRequestHandler)
|
||||
self.server = threading.Thread(target=self.httpd.serve_forever)
|
||||
self.server.setDaemon(True) # don't hang on exit
|
||||
self.server.start()
|
||||
#self.testServer()
|
||||
|
||||
#TODO: figure this out
|
||||
def testServer(self):
|
||||
fileList = os.listdir(DOCROOT)
|
||||
filehandle = urllib.urlopen('http://%s:%s' % (self.host, self.port))
|
||||
data = filehandle.readlines();
|
||||
filehandle.close()
|
||||
|
||||
for line in data:
|
||||
found = False
|
||||
# '@' denotes a symlink and we need to ignore it.
|
||||
webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@')
|
||||
if webline != "":
|
||||
if webline == "Directory listing for":
|
||||
found = True
|
||||
else:
|
||||
for fileName in fileList:
|
||||
if fileName == webline:
|
||||
found = True
|
||||
|
||||
if (found == False):
|
||||
print "NOT FOUND: " + webline.strip()
|
||||
|
||||
def stop(self):
|
||||
if self.httpd:
|
||||
self.httpd.shutdown()
|
||||
|
||||
__del__ = stop
|
||||
|
|
@ -53,7 +53,7 @@ from mozprofile import Profile
|
|||
|
||||
from tps.firefoxrunner import TPSFirefoxRunner
|
||||
from tps.phase import TPSTestPhase
|
||||
|
||||
from tps.mozhttpd import MozHttpd
|
||||
|
||||
class TempFile(object):
|
||||
"""Class for temporary files that delete themselves when garbage-collected.
|
||||
|
@ -397,6 +397,9 @@ class TPSTestRunner(object):
|
|||
testlist = [os.path.basename(self.testfile)]
|
||||
testdir = os.path.dirname(self.testfile)
|
||||
|
||||
self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
|
||||
self.mozhttpd.start()
|
||||
|
||||
# run each test, and save the results
|
||||
for test in testlist:
|
||||
result = self.run_single_test(testdir, test)
|
||||
|
@ -415,6 +418,8 @@ class TPSTestRunner(object):
|
|||
else:
|
||||
self.numfailed += 1
|
||||
|
||||
self.mozhttpd.stop()
|
||||
|
||||
# generate the postdata we'll use to post the results to the db
|
||||
self.postdata = { 'tests': self.results,
|
||||
'os':os_string,
|
||||
|
|
Загрузка…
Ссылка в новой задаче