Bug 512319 Add option to allow mochitest to use external web server patch=jmaher r=ted

This commit is contained in:
Joel Maher 2009-11-25 17:04:02 -08:00
Родитель 14e15631fb
Коммит 3dcbe17432
3 изменённых файлов: 123 добавлений и 81 удалений

Просмотреть файл

@ -102,6 +102,8 @@ UNIXISH = not IS_WIN32 and not IS_MAC
#expand IS_DEBUG_BUILD = __IS_DEBUG_BUILD__ #expand IS_DEBUG_BUILD = __IS_DEBUG_BUILD__
#expand CRASHREPORTER = __CRASHREPORTER__ == 1 #expand CRASHREPORTER = __CRASHREPORTER__ == 1
DEFAULT_WEB_SERVER = "localhost:8888"
########### ###########
# LOGGING # # LOGGING #
########### ###########
@ -172,7 +174,7 @@ class Location:
self.options = options self.options = options
def readLocations(locationsPath = "server-locations.txt"): def readLocations(locationsPath = "server-locations.txt", remoteServer = DEFAULT_WEB_SERVER):
""" """
Reads the locations at which the Mochitest HTTP server is available from Reads the locations at which the Mochitest HTTP server is available from
server-locations.txt. server-locations.txt.
@ -209,18 +211,22 @@ def readLocations(locationsPath = "server-locations.txt"):
if not match: if not match:
raise SyntaxError(lineno) raise SyntaxError(lineno)
host = match.group("host")
port = match.group("port")
options = match.group("options") options = match.group("options")
if options: if options:
options = options.split(",") options = options.split(",")
if "primary" in options: if "primary" in options:
if seenPrimary: if seenPrimary:
raise SyntaxError(lineno, "multiple primary locations") raise SyntaxError(lineno, "multiple primary locations")
#we can have only 1 primary, make it the remoteServer
host, port = remoteServer.split(':')
seenPrimary = True seenPrimary = True
else: else:
options = [] options = []
locations.append(Location(match.group("scheme"), match.group("host"), locations.append(Location(match.group("scheme"), host, port, options))
match.group("port"), options))
if not seenPrimary: if not seenPrimary:
raise SyntaxError(lineno + 1, "missing primary location") raise SyntaxError(lineno + 1, "missing primary location")
@ -228,13 +234,14 @@ def readLocations(locationsPath = "server-locations.txt"):
return locations return locations
def initializeProfile(profileDir, extraPrefs = []): def initializeProfile(profileDir, extraPrefs = [], webServer = DEFAULT_WEB_SERVER):
"Sets up the standard testing profile." "Sets up the standard testing profile."
# Start with a clean slate. # Start with a clean slate.
shutil.rmtree(profileDir, True) shutil.rmtree(profileDir, True)
os.mkdir(profileDir) os.mkdir(profileDir)
remoteIP = webServer.split(':')[0]
prefs = [] prefs = []
part = """\ part = """\
@ -263,7 +270,7 @@ user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482
user_pref("media.cache_size", 100); user_pref("media.cache_size", 100);
user_pref("security.warn_viewing_mixed", false); user_pref("security.warn_viewing_mixed", false);
user_pref("geo.wifi.uri", "http://localhost:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs"); user_pref("geo.wifi.uri", "http://example.com/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
user_pref("geo.wifi.testing", true); user_pref("geo.wifi.testing", true);
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
@ -271,15 +278,15 @@ user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
// Make url-classifier updates so rare that they won't affect tests // Make url-classifier updates so rare that they won't affect tests
user_pref("urlclassifier.updateinterval", 172800); user_pref("urlclassifier.updateinterval", 172800);
// Point the url-classifier to the local testing server for fast failures // Point the url-classifier to the local testing server for fast failures
user_pref("browser.safebrowsing.provider.0.gethashURL", "http://localhost:8888/safebrowsing-dummy/gethash"); user_pref("browser.safebrowsing.provider.0.gethashURL", "http://example.com/safebrowsing-dummy/gethash");
user_pref("browser.safebrowsing.provider.0.keyURL", "http://localhost:8888/safebrowsing-dummy/newkey"); user_pref("browser.safebrowsing.provider.0.keyURL", "http://example.com/safebrowsing-dummy/newkey");
user_pref("browser.safebrowsing.provider.0.lookupURL", "http://localhost:8888/safebrowsing-dummy/lookup"); user_pref("browser.safebrowsing.provider.0.lookupURL", "http://example.com/safebrowsing-dummy/lookup");
user_pref("browser.safebrowsing.provider.0.updateURL", "http://localhost:8888/safebrowsing-dummy/update"); user_pref("browser.safebrowsing.provider.0.updateURL", "http://example.com/safebrowsing-dummy/update");
""" """
prefs.append(part) prefs.append(part)
locations = readLocations() locations = readLocations(remoteServer=webServer)
# Grant God-power to all the privileged servers on which tests run. # Grant God-power to all the privileged servers on which tests run.
privileged = filter(lambda loc: "privileged" in loc.options, locations) privileged = filter(lambda loc: "privileged" in loc.options, locations)
@ -303,7 +310,7 @@ user_pref("capability.principal.codebase.p%(i)d.subjectName", "");
pacURL = """data:text/plain, pacURL = """data:text/plain,
function FindProxyForURL(url, host) function FindProxyForURL(url, host)
{ {
var origins = [%(origins)s]; var origins = ['http://%(remote)s:8888', %(origins)s];
var regex = new RegExp('^([a-z][-a-z0-9+.]*)' + var regex = new RegExp('^([a-z][-a-z0-9+.]*)' +
'://' + '://' +
'(?:[^/@]*@)?' + '(?:[^/@]*@)?' +
@ -324,11 +331,11 @@ function FindProxyForURL(url, host)
if (origins.indexOf(origin) < 0) if (origins.indexOf(origin) < 0)
return 'DIRECT'; return 'DIRECT';
if (isHttp) if (isHttp)
return 'PROXY 127.0.0.1:8888'; return 'PROXY %(remote)s:8888';
if (isHttps) if (isHttps)
return 'PROXY 127.0.0.1:4443'; return 'PROXY %(remote)s:4443';
return 'DIRECT'; return 'DIRECT';
}""" % { "origins": origins } }""" % { "origins": origins, "remote":remoteIP }
pacURL = "".join(pacURL.splitlines()) pacURL = "".join(pacURL.splitlines())
part = """ part = """

Просмотреть файл

@ -54,16 +54,13 @@ import urllib2
import commands import commands
import automation import automation
from automationutils import * from automationutils import *
import tempfile
# Path to the test script on the server # Path to the test script on the server
TEST_SERVER_HOST = "localhost:8888"
TEST_PATH = "/tests/" TEST_PATH = "/tests/"
CHROME_PATH = "/redirect.html"; CHROME_PATH = "/redirect.html";
A11Y_PATH = "/redirect-a11y.html" A11Y_PATH = "/redirect-a11y.html"
TESTS_URL = "http://" + TEST_SERVER_HOST + TEST_PATH
CHROMETESTS_URL = "http://" + TEST_SERVER_HOST + CHROME_PATH
A11YTESTS_URL = "http://" + TEST_SERVER_HOST + A11Y_PATH
SERVER_SHUTDOWN_URL = "http://" + TEST_SERVER_HOST + "/server/shutdown"
# main browser chrome URL, same as browser.chromeURL pref # main browser chrome URL, same as browser.chromeURL pref
#ifdef MOZ_SUITE #ifdef MOZ_SUITE
BROWSER_CHROME_URL = "chrome://navigator/content/navigator.xul" BROWSER_CHROME_URL = "chrome://navigator/content/navigator.xul"
@ -83,9 +80,6 @@ oldcwd = os.getcwd()
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0]))) SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
os.chdir(SCRIPT_DIRECTORY) os.chdir(SCRIPT_DIRECTORY)
PROFILE_DIRECTORY = os.path.abspath("./mochitesttestingprofile")
LEAK_REPORT_FILE = os.path.join(PROFILE_DIRECTORY, "runtests_leaks.log")
####################### #######################
# COMMANDLINE OPTIONS # # COMMANDLINE OPTIONS #
@ -228,6 +222,20 @@ class MochitestOptions(optparse.OptionParser):
help = "copy specified files/dirs to testing profile") help = "copy specified files/dirs to testing profile")
defaults["extraProfileFiles"] = [] defaults["extraProfileFiles"] = []
self.add_option("--remote-webserver", action = "store",
type = "string", dest = "remoteWebServer",
help = "ip address where the remote web server is hosted at")
defaults["remoteWebServer"] = None
self.add_option("--profile-path", action = "store",
type = "string", dest = "profilePath",
help = "directory where the profile will be stored")
defaults["profilePath"] = tempfile.mkdtemp()
self.add_option("--setup-only", action = "store_true",
dest = "setupOnly", help = "only setup the profile, do not run tests")
defaults["setupOnly"] = False
# -h, --help are automatically handled by OptionParser # -h, --help are automatically handled by OptionParser
self.set_defaults(**defaults) self.set_defaults(**defaults)
@ -253,6 +261,8 @@ class MochitestServer:
self._closeWhenDone = options.closeWhenDone self._closeWhenDone = options.closeWhenDone
self._utilityPath = options.utilityPath self._utilityPath = options.utilityPath
self._xrePath = options.xrePath self._xrePath = options.xrePath
self._shutdownPath = "http://" + options.webServer + "/server/shutdown"
self._profilePath = options.profilePath
def start(self): def start(self):
"Run the Mochitest server, returning the process ID of the server." "Run the Mochitest server, returning the process ID of the server."
@ -265,6 +275,7 @@ class MochitestServer:
args = ["-g", self._xrePath, args = ["-g", self._xrePath,
"-v", "170", "-v", "170",
"-f", "./" + "httpd.js", "-f", "./" + "httpd.js",
"-e", "const _PROFILE_PATH = '" + self._profilePath + "'",
"-f", "./" + "server.js"] "-f", "./" + "server.js"]
xpcshell = os.path.join(self._utilityPath, xpcshell = os.path.join(self._utilityPath,
@ -280,7 +291,7 @@ class MochitestServer:
def ensureReady(self, timeout): def ensureReady(self, timeout):
assert timeout >= 0 assert timeout >= 0
aliveFile = os.path.join(PROFILE_DIRECTORY, "server_alive.txt") aliveFile = os.path.join(self._profilePath, "server_alive.txt")
i = 0 i = 0
while i < timeout: while i < timeout:
if os.path.exists(aliveFile): if os.path.exists(aliveFile):
@ -294,7 +305,7 @@ class MochitestServer:
def stop(self): def stop(self):
try: try:
c = urllib2.urlopen(SERVER_SHUTDOWN_URL) c = urllib2.urlopen(self._shutdownPath)
c.read() c.read()
c.close() c.close()
self._process.wait() self._process.wait()
@ -332,6 +343,8 @@ def main():
# allow relative paths # allow relative paths
options.xrePath = getFullPath(options.xrePath) options.xrePath = getFullPath(options.xrePath)
options.profilePath = getFullPath(options.profilePath)
options.app = getFullPath(options.app) options.app = getFullPath(options.app)
if not os.path.exists(options.app): if not os.path.exists(options.app):
msg = """\ msg = """\
@ -345,6 +358,13 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
if options.symbolsPath: if options.symbolsPath:
options.symbolsPath = getFullPath(options.symbolsPath) options.symbolsPath = getFullPath(options.symbolsPath)
if (options.remoteWebServer):
if (len(options.remoteWebServer.split(':')) == 1):
options.remoteWebServer += ":8888"
options.webServer = options.remoteWebServer
else:
options.webServer = "localhost:8888"
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs, debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
options.debuggerInteractive); options.debuggerInteractive);
@ -362,9 +382,13 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
sys.exit(1) sys.exit(1)
browserEnv[v[:ix]] = v[ix + 1:] browserEnv[v[:ix]] = v[ix + 1:]
automation.initializeProfile(PROFILE_DIRECTORY, options.extraPrefs) automation.initializeProfile(options.profilePath, options.extraPrefs, options.webServer)
manifest = addChromeToProfile(options) manifest = addChromeToProfile(options)
copyExtraFilesToProfile(options) copyExtraFilesToProfile(options)
if (options.setupOnly):
return
if (not options.remoteWebServer):
server = MochitestServer(options) server = MochitestServer(options)
server.start() server.start()
@ -388,14 +412,14 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
# file logs, if activated. # file logs, if activated.
# <http://mochikit.com/doc/html/MochiKit/Logging.html> # <http://mochikit.com/doc/html/MochiKit/Logging.html>
testURL = TESTS_URL + options.testPath testURL = "http://" + options.webServer + "/tests/" + options.testPath
urlOpts = [] urlOpts = []
if options.chrome: if options.chrome:
testURL = CHROMETESTS_URL testURL = "http://" + options.webServer + CHROME_PATH
if options.testPath: if options.testPath:
urlOpts.append("testPath=" + encodeURIComponent(options.testPath)) urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
elif options.a11y: elif options.a11y:
testURL = A11YTESTS_URL testURL = "http://" + options.webServer + A11Y_PATH
if options.testPath: if options.testPath:
urlOpts.append("testPath=" + encodeURIComponent(options.testPath)) urlOpts.append("testPath=" + encodeURIComponent(options.testPath))
elif options.browserChrome: elif options.browserChrome:
@ -428,17 +452,19 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
if len(urlOpts) > 0: if len(urlOpts) > 0:
testURL += "?" + "&".join(urlOpts) testURL += "?" + "&".join(urlOpts)
browserEnv["XPCOM_MEM_BLOAT_LOG"] = LEAK_REPORT_FILE leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log")
browserEnv["XPCOM_MEM_BLOAT_LOG"] = leak_report_file
if options.fatalAssertions: if options.fatalAssertions:
browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort" browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
try:
# run once with -silent to let the extension manager do its thing # run once with -silent to let the extension manager do its thing
# and then exit the app # and then exit the app
automation.log.info("INFO | runtests.py | Performing extension manager registration: start.\n") automation.log.info("INFO | runtests.py | Performing extension manager registration: start.\n")
# Don't care about this |status|: |runApp()| reporting it should be enough. # Don't care about this |status|: |runApp()| reporting it should be enough.
status = automation.runApp(None, browserEnv, options.app, status = automation.runApp(None, browserEnv, options.app,
PROFILE_DIRECTORY, ["-silent"], options.profilePath, ["-silent"],
utilityPath = options.utilityPath, utilityPath = options.utilityPath,
xrePath = options.xrePath, xrePath = options.xrePath,
symbolsPath=options.symbolsPath) symbolsPath=options.symbolsPath)
@ -447,8 +473,8 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
# Remove the leak detection file so it can't "leak" to the tests run. # Remove the leak detection file so it can't "leak" to the tests run.
# The file is not there if leak logging was not enabled in the application build. # The file is not there if leak logging was not enabled in the application build.
if os.path.exists(LEAK_REPORT_FILE): if os.path.exists(leak_report_file):
os.remove(LEAK_REPORT_FILE) os.remove(leak_report_file)
# then again to actually run mochitest # then again to actually run mochitest
if options.timeout: if options.timeout:
@ -459,7 +485,7 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
timeout = 330.0 # default JS harness timeout is 300 seconds timeout = 330.0 # default JS harness timeout is 300 seconds
automation.log.info("INFO | runtests.py | Running tests: start.\n") automation.log.info("INFO | runtests.py | Running tests: start.\n")
status = automation.runApp(testURL, browserEnv, options.app, status = automation.runApp(testURL, browserEnv, options.app,
PROFILE_DIRECTORY, options.browserArgs, options.profilePath, options.browserArgs,
runSSLTunnel = True, runSSLTunnel = True,
utilityPath = options.utilityPath, utilityPath = options.utilityPath,
xrePath = options.xrePath, xrePath = options.xrePath,
@ -468,14 +494,18 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
symbolsPath=options.symbolsPath, symbolsPath=options.symbolsPath,
timeout = timeout) timeout = timeout)
if (not options.remoteWebServer):
# Server's no longer needed, and perhaps more importantly, anything it might # Server's no longer needed, and perhaps more importantly, anything it might
# spew to console shouldn't disrupt the leak information table we print next. # spew to console shouldn't disrupt the leak information table we print next.
server.stop() server.stop()
processLeakLog(LEAK_REPORT_FILE, options.leakThreshold) processLeakLog(leak_report_file, options.leakThreshold)
automation.log.info("\nINFO | runtests.py | Running tests: end.") automation.log.info("\nINFO | runtests.py | Running tests: end.")
finally:
# delete the profile and manifest # delete the profile and manifest
if (options.profilePath):
shutil.rmtree(options.profilePath)
os.remove(manifest) os.remove(manifest)
# hanging due to non-halting threads is no fun; assume we hit the errors we # hanging due to non-halting threads is no fun; assume we hit the errors we
@ -508,7 +538,7 @@ def makeTestConfig(options):
"logPath": logFile, "logPath": logFile,
"testPath": testPath} "testPath": testPath}
config = open(os.path.join(PROFILE_DIRECTORY, "testConfig.js"), "w") config = open(os.path.join(options.profilePath, "testConfig.js"), "w")
config.write(content) config.write(content)
config.close() config.close()
@ -516,7 +546,7 @@ def makeTestConfig(options):
def addChromeToProfile(options): def addChromeToProfile(options):
"Adds MochiKit chrome tests to the profile." "Adds MochiKit chrome tests to the profile."
chromedir = os.path.join(PROFILE_DIRECTORY, "chrome") chromedir = os.path.join(options.profilePath, "chrome")
os.mkdir(chromedir) os.mkdir(chromedir)
chrome = [] chrome = []
@ -536,7 +566,7 @@ toolbar#nav-bar {
# write userChrome.css # write userChrome.css
chromeFile = open(os.path.join(PROFILE_DIRECTORY, "userChrome.css"), "a") chromeFile = open(os.path.join(options.profilePath, "userChrome.css"), "a")
chromeFile.write("".join(chrome)) chromeFile.write("".join(chrome))
chromeFile.close() chromeFile.close()
@ -563,7 +593,7 @@ def copyExtraFilesToProfile(options):
"Copy extra files or dirs specified on the command line to the testing profile." "Copy extra files or dirs specified on the command line to the testing profile."
for f in options.extraProfileFiles: for f in options.extraProfileFiles:
abspath = getFullPath(f) abspath = getFullPath(f)
dest = os.path.join(PROFILE_DIRECTORY, os.path.basename(abspath)) dest = os.path.join(options.profilePath, os.path.basename(abspath))
if os.path.isdir(abspath): if os.path.isdir(abspath):
shutil.copytree(abspath, dest) shutil.copytree(abspath, dest)
else: else:

Просмотреть файл

@ -157,8 +157,13 @@ function runServer()
.createInstance(Ci.nsIFileOutputStream); .createInstance(Ci.nsIFileOutputStream);
var serverAlive = Cc["@mozilla.org/file/local;1"] var serverAlive = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile); .createInstance(Ci.nsILocalFile);
if (typeof(_PROFILE_PATH) == "undefined") {
serverAlive.initWithFile(serverBasePath); serverAlive.initWithFile(serverBasePath);
serverAlive.append("mochitesttestingprofile"); serverAlive.append("mochitesttestingprofile");
} else {
serverAlive.initWithPath(_PROFILE_PATH);
}
// If we're running outside of the test harness, there might // If we're running outside of the test harness, there might
// not be a test profile directory present // not be a test profile directory present