зеркало из https://github.com/mozilla/gecko-dev.git
Bug 822875 - Make TPS .py files use 4-space indent, r=jgriffin
This commit is contained in:
Родитель
e23d811ae6
Коммит
7939b690c0
|
@ -12,88 +12,88 @@ from threading import RLock
|
|||
from tps import TPSTestRunner
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("--mobile",
|
||||
action = "store_true", dest = "mobile",
|
||||
default = False,
|
||||
help = "run with mobile settings")
|
||||
parser.add_option("--testfile",
|
||||
action = "store", type = "string", dest = "testfile",
|
||||
default = '../../services/sync/tests/tps/test_sync.js',
|
||||
help = "path to the test file to run "
|
||||
"[default: %default]")
|
||||
parser.add_option("--logfile",
|
||||
action = "store", type = "string", dest = "logfile",
|
||||
default = 'tps.log',
|
||||
help = "path to the log file [default: %default]")
|
||||
parser.add_option("--resultfile",
|
||||
action = "store", type = "string", dest = "resultfile",
|
||||
default = 'tps_result.json',
|
||||
help = "path to the result file [default: %default]")
|
||||
parser.add_option("--binary",
|
||||
action = "store", type = "string", dest = "binary",
|
||||
default = None,
|
||||
help = "path to the Firefox binary, specified either as "
|
||||
"a local file or a url; if omitted, the PATH "
|
||||
"will be searched;")
|
||||
parser.add_option("--configfile",
|
||||
action = "store", type = "string", dest = "configfile",
|
||||
default = None,
|
||||
help = "path to the config file to use "
|
||||
"[default: %default]")
|
||||
parser.add_option("--pulsefile",
|
||||
action = "store", type = "string", dest = "pulsefile",
|
||||
default = None,
|
||||
help = "path to file containing a pulse message in "
|
||||
"json format that you want to inject into the monitor")
|
||||
parser.add_option("--ignore-unused-engines",
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest="ignore_unused_engines",
|
||||
help="If defined, don't load unused engines in individual tests."
|
||||
" Has no effect for pulse monitor.")
|
||||
(options, args) = parser.parse_args()
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("--mobile",
|
||||
action = "store_true", dest = "mobile",
|
||||
default = False,
|
||||
help = "run with mobile settings")
|
||||
parser.add_option("--testfile",
|
||||
action = "store", type = "string", dest = "testfile",
|
||||
default = '../../services/sync/tests/tps/test_sync.js',
|
||||
help = "path to the test file to run "
|
||||
"[default: %default]")
|
||||
parser.add_option("--logfile",
|
||||
action = "store", type = "string", dest = "logfile",
|
||||
default = 'tps.log',
|
||||
help = "path to the log file [default: %default]")
|
||||
parser.add_option("--resultfile",
|
||||
action = "store", type = "string", dest = "resultfile",
|
||||
default = 'tps_result.json',
|
||||
help = "path to the result file [default: %default]")
|
||||
parser.add_option("--binary",
|
||||
action = "store", type = "string", dest = "binary",
|
||||
default = None,
|
||||
help = "path to the Firefox binary, specified either as "
|
||||
"a local file or a url; if omitted, the PATH "
|
||||
"will be searched;")
|
||||
parser.add_option("--configfile",
|
||||
action = "store", type = "string", dest = "configfile",
|
||||
default = None,
|
||||
help = "path to the config file to use "
|
||||
"[default: %default]")
|
||||
parser.add_option("--pulsefile",
|
||||
action = "store", type = "string", dest = "pulsefile",
|
||||
default = None,
|
||||
help = "path to file containing a pulse message in "
|
||||
"json format that you want to inject into the monitor")
|
||||
parser.add_option("--ignore-unused-engines",
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest="ignore_unused_engines",
|
||||
help="If defined, don't load unused engines in individual tests."
|
||||
" Has no effect for pulse monitor.")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
configfile = options.configfile
|
||||
if configfile is None:
|
||||
if os.environ.get('VIRTUAL_ENV'):
|
||||
configfile = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||
if configfile is None or not os.access(configfile, os.F_OK):
|
||||
raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
|
||||
"specify a config file using the --configfile option")
|
||||
configfile = options.configfile
|
||||
if configfile is None:
|
||||
if os.environ.get('VIRTUAL_ENV'):
|
||||
configfile = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||
if configfile is None or not os.access(configfile, os.F_OK):
|
||||
raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
|
||||
"specify a config file using the --configfile option")
|
||||
|
||||
# load the config file
|
||||
f = open(configfile, 'r')
|
||||
configcontent = f.read()
|
||||
f.close()
|
||||
config = json.loads(configcontent)
|
||||
# load the config file
|
||||
f = open(configfile, 'r')
|
||||
configcontent = f.read()
|
||||
f.close()
|
||||
config = json.loads(configcontent)
|
||||
|
||||
rlock = RLock()
|
||||
rlock = RLock()
|
||||
|
||||
print 'using result file', options.resultfile
|
||||
print 'using result file', options.resultfile
|
||||
|
||||
extensionDir = config.get("extensiondir")
|
||||
if not extensionDir or extensionDir == '__EXTENSIONDIR__':
|
||||
extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps")
|
||||
else:
|
||||
if sys.platform == 'win32':
|
||||
# replace msys-style paths with proper Windows paths
|
||||
import re
|
||||
m = re.match('^\/\w\/', extensionDir)
|
||||
if m:
|
||||
extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
|
||||
extensionDir = extensionDir.replace("/", "\\")
|
||||
extensionDir = config.get("extensiondir")
|
||||
if not extensionDir or extensionDir == '__EXTENSIONDIR__':
|
||||
extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps", "extensions")
|
||||
else:
|
||||
if sys.platform == 'win32':
|
||||
# replace msys-style paths with proper Windows paths
|
||||
import re
|
||||
m = re.match('^\/\w\/', extensionDir)
|
||||
if m:
|
||||
extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
|
||||
extensionDir = extensionDir.replace("/", "\\")
|
||||
|
||||
TPS = TPSTestRunner(extensionDir,
|
||||
testfile=options.testfile,
|
||||
logfile=options.logfile,
|
||||
binary=options.binary,
|
||||
config=config,
|
||||
rlock=rlock,
|
||||
mobile=options.mobile,
|
||||
resultfile=options.resultfile,
|
||||
ignore_unused_engines=options.ignore_unused_engines)
|
||||
TPS.run_tests()
|
||||
TPS = TPSTestRunner(extensionDir,
|
||||
testfile=options.testfile,
|
||||
logfile=options.logfile,
|
||||
binary=options.binary,
|
||||
config=config,
|
||||
rlock=rlock,
|
||||
mobile=options.mobile,
|
||||
resultfile=options.resultfile,
|
||||
ignore_unused_engines=options.ignore_unused_engines)
|
||||
TPS.run_tests()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
|
@ -14,81 +14,81 @@ from mozrunner import FirefoxRunner
|
|||
|
||||
class TPSFirefoxRunner(object):
|
||||
|
||||
PROCESS_TIMEOUT = 240
|
||||
|
||||
def __init__(self, binary):
|
||||
if binary is not None and ('http://' in binary or 'ftp://' in binary):
|
||||
self.url = binary
|
||||
self.binary = None
|
||||
else:
|
||||
self.url = None
|
||||
self.binary = binary
|
||||
self.runner = None
|
||||
self.installdir = None
|
||||
|
||||
def __del__(self):
|
||||
if self.installdir:
|
||||
shutil.rmtree(self.installdir, True)
|
||||
|
||||
def download_url(self, url, dest=None):
|
||||
h = httplib2.Http()
|
||||
resp, content = h.request(url, "GET")
|
||||
if dest == None:
|
||||
dest = os.path.basename(url)
|
||||
|
||||
local = open(dest, 'wb')
|
||||
local.write(content)
|
||||
local.close()
|
||||
return dest
|
||||
|
||||
def download_build(self, installdir='downloadedbuild', appname='firefox'):
|
||||
self.installdir = os.path.abspath(installdir)
|
||||
buildName = os.path.basename(self.url)
|
||||
pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
buildName)
|
||||
|
||||
# delete the build if it already exists
|
||||
if os.access(pathToBuild, os.F_OK):
|
||||
os.remove(pathToBuild)
|
||||
|
||||
# download the build
|
||||
print "downloading build"
|
||||
self.download_url(self.url, pathToBuild)
|
||||
|
||||
# install the build
|
||||
print "installing %s" % pathToBuild
|
||||
shutil.rmtree(self.installdir, True)
|
||||
binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
|
||||
|
||||
# remove the downloaded archive
|
||||
os.remove(pathToBuild)
|
||||
|
||||
return binary
|
||||
|
||||
def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
|
||||
"""Runs the given FirefoxRunner with the given Profile, waits
|
||||
for completion, then returns the process exit code
|
||||
"""
|
||||
if profile is None:
|
||||
profile = Profile()
|
||||
self.profile = profile
|
||||
|
||||
if self.binary is None and self.url:
|
||||
self.binary = self.download_build()
|
||||
|
||||
if self.runner is None:
|
||||
self.runner = FirefoxRunner(self.profile, binary=self.binary)
|
||||
|
||||
self.runner.profile = self.profile
|
||||
|
||||
if env is not None:
|
||||
self.runner.env.update(env)
|
||||
|
||||
if args is not None:
|
||||
self.runner.cmdargs = copy.copy(args)
|
||||
|
||||
self.runner.start()
|
||||
|
||||
status = self.runner.process_handler.waitForFinish(timeout=timeout)
|
||||
|
||||
return status
|
||||
PROCESS_TIMEOUT = 240
|
||||
|
||||
def __init__(self, binary):
|
||||
if binary is not None and ('http://' in binary or 'ftp://' in binary):
|
||||
self.url = binary
|
||||
self.binary = None
|
||||
else:
|
||||
self.url = None
|
||||
self.binary = binary
|
||||
self.runner = None
|
||||
self.installdir = None
|
||||
|
||||
def __del__(self):
|
||||
if self.installdir:
|
||||
shutil.rmtree(self.installdir, True)
|
||||
|
||||
def download_url(self, url, dest=None):
|
||||
h = httplib2.Http()
|
||||
resp, content = h.request(url, "GET")
|
||||
if dest == None:
|
||||
dest = os.path.basename(url)
|
||||
|
||||
local = open(dest, 'wb')
|
||||
local.write(content)
|
||||
local.close()
|
||||
return dest
|
||||
|
||||
def download_build(self, installdir='downloadedbuild', appname='firefox'):
|
||||
self.installdir = os.path.abspath(installdir)
|
||||
buildName = os.path.basename(self.url)
|
||||
pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
buildName)
|
||||
|
||||
# delete the build if it already exists
|
||||
if os.access(pathToBuild, os.F_OK):
|
||||
os.remove(pathToBuild)
|
||||
|
||||
# download the build
|
||||
print "downloading build"
|
||||
self.download_url(self.url, pathToBuild)
|
||||
|
||||
# install the build
|
||||
print "installing %s" % pathToBuild
|
||||
shutil.rmtree(self.installdir, True)
|
||||
binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
|
||||
|
||||
# remove the downloaded archive
|
||||
os.remove(pathToBuild)
|
||||
|
||||
return binary
|
||||
|
||||
def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
|
||||
"""Runs the given FirefoxRunner with the given Profile, waits
|
||||
for completion, then returns the process exit code
|
||||
"""
|
||||
if profile is None:
|
||||
profile = Profile()
|
||||
self.profile = profile
|
||||
|
||||
if self.binary is None and self.url:
|
||||
self.binary = self.download_build()
|
||||
|
||||
if self.runner is None:
|
||||
self.runner = FirefoxRunner(self.profile, binary=self.binary)
|
||||
|
||||
self.runner.profile = self.profile
|
||||
|
||||
if env is not None:
|
||||
self.runner.env.update(env)
|
||||
|
||||
if args is not None:
|
||||
self.runner.cmdargs = copy.copy(args)
|
||||
|
||||
self.runner.start()
|
||||
|
||||
status = self.runner.process_handler.waitForFinish(timeout=timeout)
|
||||
|
||||
return status
|
||||
|
|
|
@ -18,10 +18,10 @@ 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 '/'
|
||||
# It appears that the default path is '/' and os.path.join makes the '/'
|
||||
o = urlparse(path)
|
||||
|
||||
sep = '/'
|
||||
|
@ -92,9 +92,9 @@ class MozHttpd(object):
|
|||
for fileName in fileList:
|
||||
if fileName == webline:
|
||||
found = True
|
||||
|
||||
|
||||
if (found == False):
|
||||
print "NOT FOUND: " + webline.strip()
|
||||
print "NOT FOUND: " + webline.strip()
|
||||
|
||||
def stop(self):
|
||||
if self.httpd:
|
||||
|
@ -102,4 +102,3 @@ class MozHttpd(object):
|
|||
self.httpd.server_close()
|
||||
|
||||
__del__ = stop
|
||||
|
||||
|
|
|
@ -6,71 +6,70 @@ import re
|
|||
|
||||
class TPSTestPhase(object):
|
||||
|
||||
lineRe = re.compile(
|
||||
r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
|
||||
lineRe = re.compile(
|
||||
r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
|
||||
|
||||
def __init__(self, phase, profile, testname, testpath, logfile, env,
|
||||
firefoxRunner, logfn, ignore_unused_engines=False):
|
||||
self.phase = phase
|
||||
self.profile = profile
|
||||
self.testname = str(testname) # this might be passed in as unicode
|
||||
self.testpath = testpath
|
||||
self.logfile = logfile
|
||||
self.env = env
|
||||
self.firefoxRunner = firefoxRunner
|
||||
self.log = logfn
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self._status = None
|
||||
self.errline = ''
|
||||
def __init__(self, phase, profile, testname, testpath, logfile, env,
|
||||
firefoxRunner, logfn, ignore_unused_engines=False):
|
||||
self.phase = phase
|
||||
self.profile = profile
|
||||
self.testname = str(testname) # this might be passed in as unicode
|
||||
self.testpath = testpath
|
||||
self.logfile = logfile
|
||||
self.env = env
|
||||
self.firefoxRunner = firefoxRunner
|
||||
self.log = logfn
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self._status = None
|
||||
self.errline = ''
|
||||
|
||||
@property
|
||||
def phasenum(self):
|
||||
match = re.match('.*?(\d+)', self.phase)
|
||||
if match:
|
||||
return match.group(1)
|
||||
@property
|
||||
def phasenum(self):
|
||||
match = re.match('.*?(\d+)', self.phase)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
return self._status if self._status else 'unknown'
|
||||
@property
|
||||
def status(self):
|
||||
return self._status if self._status else 'unknown'
|
||||
|
||||
def run(self):
|
||||
# launch Firefox
|
||||
args = [ '-tps', self.testpath,
|
||||
'-tpsphase', self.phasenum,
|
||||
'-tpslogfile', self.logfile ]
|
||||
def run(self):
|
||||
# launch Firefox
|
||||
args = [ '-tps', self.testpath,
|
||||
'-tpsphase', self.phasenum,
|
||||
'-tpslogfile', self.logfile ]
|
||||
|
||||
if self.ignore_unused_engines:
|
||||
args.append('--ignore-unused-engines')
|
||||
if self.ignore_unused_engines:
|
||||
args.append('--ignore-unused-engines')
|
||||
|
||||
self.log("\nlaunching Firefox for phase %s with args %s\n" %
|
||||
(self.phase, str(args)))
|
||||
self.firefoxRunner.run(env=self.env,
|
||||
args=args,
|
||||
profile=self.profile)
|
||||
self.log("\nlaunching Firefox for phase %s with args %s\n" %
|
||||
(self.phase, str(args)))
|
||||
self.firefoxRunner.run(env=self.env,
|
||||
args=args,
|
||||
profile=self.profile)
|
||||
|
||||
# parse the logfile and look for results from the current test phase
|
||||
found_test = False
|
||||
f = open(self.logfile, 'r')
|
||||
for line in f:
|
||||
# parse the logfile and look for results from the current test phase
|
||||
found_test = False
|
||||
f = open(self.logfile, 'r')
|
||||
for line in f:
|
||||
|
||||
# skip to the part of the log file that deals with the test we're running
|
||||
if not found_test:
|
||||
if line.find("Running test %s" % self.testname) > -1:
|
||||
found_test = True
|
||||
else:
|
||||
continue
|
||||
# skip to the part of the log file that deals with the test we're running
|
||||
if not found_test:
|
||||
if line.find("Running test %s" % self.testname) > -1:
|
||||
found_test = True
|
||||
else:
|
||||
continue
|
||||
|
||||
# look for the status of the current phase
|
||||
match = self.lineRe.match(line)
|
||||
if match:
|
||||
if match.group("matchphase") == self.phasenum:
|
||||
self._status = match.group("matchstatus")
|
||||
break
|
||||
# look for the status of the current phase
|
||||
match = self.lineRe.match(line)
|
||||
if match:
|
||||
if match.group("matchphase") == self.phasenum:
|
||||
self._status = match.group("matchstatus")
|
||||
break
|
||||
|
||||
# set the status to FAIL if there is TPS error
|
||||
if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
|
||||
self._status = "FAIL"
|
||||
self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
|
||||
|
||||
f.close()
|
||||
# set the status to FAIL if there is TPS error
|
||||
if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
|
||||
self._status = "FAIL"
|
||||
self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
|
||||
|
||||
f.close()
|
||||
|
|
|
@ -18,413 +18,413 @@ from tps.phase import TPSTestPhase
|
|||
from tps.mozhttpd import MozHttpd
|
||||
|
||||
class TempFile(object):
|
||||
"""Class for temporary files that delete themselves when garbage-collected.
|
||||
"""
|
||||
"""Class for temporary files that delete themselves when garbage-collected.
|
||||
"""
|
||||
|
||||
def __init__(self, prefix=None):
|
||||
self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
|
||||
def __init__(self, prefix=None):
|
||||
self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
|
||||
|
||||
def write(self, data):
|
||||
if self.fd:
|
||||
os.write(self.fd, data)
|
||||
def write(self, data):
|
||||
if self.fd:
|
||||
os.write(self.fd, data)
|
||||
|
||||
def close(self):
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
def close(self):
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
|
||||
def cleanup(self):
|
||||
if self.fd:
|
||||
self.close()
|
||||
if os.access(self.filename, os.F_OK):
|
||||
os.remove(self.filename)
|
||||
def cleanup(self):
|
||||
if self.fd:
|
||||
self.close()
|
||||
if os.access(self.filename, os.F_OK):
|
||||
os.remove(self.filename)
|
||||
|
||||
__del__ = cleanup
|
||||
__del__ = cleanup
|
||||
|
||||
class TPSTestRunner(object):
|
||||
|
||||
default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
|
||||
'GNOME_DISABLE_CRASH_DIALOG': '1',
|
||||
'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
|
||||
'MOZ_NO_REMOTE': '1',
|
||||
'XPCOM_DEBUG_BREAK': 'warn',
|
||||
}
|
||||
default_preferences = { 'app.update.enabled' : False,
|
||||
'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
|
||||
'extensions.update.enabled' : False,
|
||||
'extensions.update.notifyUser' : False,
|
||||
'browser.shell.checkDefaultBrowser' : False,
|
||||
'browser.tabs.warnOnClose' : False,
|
||||
'browser.warnOnQuit': False,
|
||||
'browser.sessionstore.resume_from_crash': False,
|
||||
'services.sync.addons.ignoreRepositoryChecking': True,
|
||||
'services.sync.firstSync': 'notReady',
|
||||
'services.sync.lastversion': '1.0',
|
||||
'services.sync.log.rootLogger': 'Trace',
|
||||
'services.sync.log.logger.engine.addons': 'Trace',
|
||||
'services.sync.log.logger.service.main': 'Trace',
|
||||
'services.sync.log.logger.engine.bookmarks': 'Trace',
|
||||
'services.sync.log.appender.console': 'Trace',
|
||||
'services.sync.log.appender.debugLog.enabled': True,
|
||||
'toolkit.startup.max_resumed_crashes': -1,
|
||||
'browser.dom.window.dump.enabled': True,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
'extensions.update.notifyUser' : False,
|
||||
}
|
||||
syncVerRe = re.compile(
|
||||
r"Sync version: (?P<syncversion>.*)\n")
|
||||
ffVerRe = re.compile(
|
||||
r"Firefox version: (?P<ffver>.*)\n")
|
||||
ffDateRe = re.compile(
|
||||
r"Firefox builddate: (?P<ffdate>.*)\n")
|
||||
default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
|
||||
'GNOME_DISABLE_CRASH_DIALOG': '1',
|
||||
'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
|
||||
'MOZ_NO_REMOTE': '1',
|
||||
'XPCOM_DEBUG_BREAK': 'warn',
|
||||
}
|
||||
default_preferences = { 'app.update.enabled' : False,
|
||||
'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
|
||||
'extensions.update.enabled' : False,
|
||||
'extensions.update.notifyUser' : False,
|
||||
'browser.shell.checkDefaultBrowser' : False,
|
||||
'browser.tabs.warnOnClose' : False,
|
||||
'browser.warnOnQuit': False,
|
||||
'browser.sessionstore.resume_from_crash': False,
|
||||
'services.sync.addons.ignoreRepositoryChecking': True,
|
||||
'services.sync.firstSync': 'notReady',
|
||||
'services.sync.lastversion': '1.0',
|
||||
'services.sync.log.rootLogger': 'Trace',
|
||||
'services.sync.log.logger.engine.addons': 'Trace',
|
||||
'services.sync.log.logger.service.main': 'Trace',
|
||||
'services.sync.log.logger.engine.bookmarks': 'Trace',
|
||||
'services.sync.log.appender.console': 'Trace',
|
||||
'services.sync.log.appender.debugLog.enabled': True,
|
||||
'toolkit.startup.max_resumed_crashes': -1,
|
||||
'browser.dom.window.dump.enabled': True,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
'extensions.update.notifyUser' : False,
|
||||
}
|
||||
syncVerRe = re.compile(
|
||||
r"Sync version: (?P<syncversion>.*)\n")
|
||||
ffVerRe = re.compile(
|
||||
r"Firefox version: (?P<ffver>.*)\n")
|
||||
ffDateRe = re.compile(
|
||||
r"Firefox builddate: (?P<ffdate>.*)\n")
|
||||
|
||||
def __init__(self, extensionDir,
|
||||
testfile="sync.test",
|
||||
binary=None, config=None, rlock=None, mobile=False,
|
||||
logfile="tps.log", resultfile="tps_result.json",
|
||||
ignore_unused_engines=False):
|
||||
self.extensions = []
|
||||
self.testfile = testfile
|
||||
self.logfile = os.path.abspath(logfile)
|
||||
self.resultfile = resultfile
|
||||
self.binary = binary
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self.config = config if config else {}
|
||||
self.repo = None
|
||||
self.changeset = None
|
||||
self.branch = None
|
||||
self.numfailed = 0
|
||||
self.numpassed = 0
|
||||
self.nightly = False
|
||||
self.rlock = rlock
|
||||
self.mobile = mobile
|
||||
self.tpsxpi = None
|
||||
self.firefoxRunner = None
|
||||
self.extensionDir = extensionDir
|
||||
self.productversion = None
|
||||
self.addonversion = None
|
||||
self.postdata = {}
|
||||
self.errorlogs = {}
|
||||
def __init__(self, extensionDir,
|
||||
testfile="sync.test",
|
||||
binary=None, config=None, rlock=None, mobile=False,
|
||||
logfile="tps.log", resultfile="tps_result.json",
|
||||
ignore_unused_engines=False):
|
||||
self.extensions = []
|
||||
self.testfile = testfile
|
||||
self.logfile = os.path.abspath(logfile)
|
||||
self.resultfile = resultfile
|
||||
self.binary = binary
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self.config = config if config else {}
|
||||
self.repo = None
|
||||
self.changeset = None
|
||||
self.branch = None
|
||||
self.numfailed = 0
|
||||
self.numpassed = 0
|
||||
self.nightly = False
|
||||
self.rlock = rlock
|
||||
self.mobile = mobile
|
||||
self.tpsxpi = None
|
||||
self.firefoxRunner = None
|
||||
self.extensionDir = extensionDir
|
||||
self.productversion = None
|
||||
self.addonversion = None
|
||||
self.postdata = {}
|
||||
self.errorlogs = {}
|
||||
|
||||
@property
|
||||
def mobile(self):
|
||||
return self._mobile
|
||||
@property
|
||||
def mobile(self):
|
||||
return self._mobile
|
||||
|
||||
@mobile.setter
|
||||
def mobile(self, value):
|
||||
self._mobile = value
|
||||
self.synctype = 'desktop' if not self._mobile else 'mobile'
|
||||
@mobile.setter
|
||||
def mobile(self, value):
|
||||
self._mobile = value
|
||||
self.synctype = 'desktop' if not self._mobile else 'mobile'
|
||||
|
||||
def log(self, msg, printToConsole=False):
|
||||
"""Appends a string to the logfile"""
|
||||
def log(self, msg, printToConsole=False):
|
||||
"""Appends a string to the logfile"""
|
||||
|
||||
f = open(self.logfile, 'a')
|
||||
f.write(msg)
|
||||
f.close()
|
||||
if printToConsole:
|
||||
print msg
|
||||
f = open(self.logfile, 'a')
|
||||
f.write(msg)
|
||||
f.close()
|
||||
if printToConsole:
|
||||
print msg
|
||||
|
||||
def writeToResultFile(self, postdata, body=None,
|
||||
sendTo=['crossweave@mozilla.com']):
|
||||
"""Writes results to test file"""
|
||||
def writeToResultFile(self, postdata, body=None,
|
||||
sendTo=['crossweave@mozilla.com']):
|
||||
"""Writes results to test file"""
|
||||
|
||||
results = {'results': []}
|
||||
results = {'results': []}
|
||||
|
||||
if os.access(self.resultfile, os.F_OK):
|
||||
f = open(self.resultfile, 'r')
|
||||
results = json.loads(f.read())
|
||||
f.close()
|
||||
if os.access(self.resultfile, os.F_OK):
|
||||
f = open(self.resultfile, 'r')
|
||||
results = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
f = open(self.resultfile, 'w')
|
||||
if body is not None:
|
||||
postdata['body'] = body
|
||||
if self.numpassed is not None:
|
||||
postdata['numpassed'] = self.numpassed
|
||||
if self.numfailed is not None:
|
||||
postdata['numfailed'] = self.numfailed
|
||||
if self.firefoxRunner and self.firefoxRunner.url:
|
||||
postdata['firefoxrunnerurl'] = self.firefoxRunner.url
|
||||
f = open(self.resultfile, 'w')
|
||||
if body is not None:
|
||||
postdata['body'] = body
|
||||
if self.numpassed is not None:
|
||||
postdata['numpassed'] = self.numpassed
|
||||
if self.numfailed is not None:
|
||||
postdata['numfailed'] = self.numfailed
|
||||
if self.firefoxRunner and self.firefoxRunner.url:
|
||||
postdata['firefoxrunnerurl'] = self.firefoxRunner.url
|
||||
|
||||
postdata['sendTo'] = sendTo
|
||||
results['results'].append(postdata)
|
||||
f.write(json.dumps(results, indent=2))
|
||||
f.close()
|
||||
postdata['sendTo'] = sendTo
|
||||
results['results'].append(postdata)
|
||||
f.write(json.dumps(results, indent=2))
|
||||
f.close()
|
||||
|
||||
def _zip_add_file(self, zip, file, rootDir):
|
||||
zip.write(os.path.join(rootDir, file), file)
|
||||
def _zip_add_file(self, zip, file, rootDir):
|
||||
zip.write(os.path.join(rootDir, file), file)
|
||||
|
||||
def _zip_add_dir(self, zip, dir, rootDir):
|
||||
try:
|
||||
zip.write(os.path.join(rootDir, dir), dir)
|
||||
except:
|
||||
# on some OS's, adding directory entries doesn't seem to work
|
||||
pass
|
||||
for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
|
||||
for f in files:
|
||||
zip.write(os.path.join(root, f), os.path.join(dir, f))
|
||||
|
||||
def run_single_test(self, testdir, testname):
|
||||
testpath = os.path.join(testdir, testname)
|
||||
self.log("Running test %s\n" % testname)
|
||||
|
||||
# Create a random account suffix that is used when creating test
|
||||
# accounts on a staging server.
|
||||
account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
|
||||
for i in range(1,6)])}
|
||||
self.config['account'].update(account_suffix)
|
||||
|
||||
# Read and parse the test file, merge it with the contents of the config
|
||||
# file, and write the combined output to a temporary file.
|
||||
f = open(testpath, 'r')
|
||||
testcontent = f.read()
|
||||
f.close()
|
||||
try:
|
||||
test = json.loads(testcontent)
|
||||
except:
|
||||
test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
|
||||
|
||||
testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
|
||||
testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
|
||||
|
||||
tmpfile = TempFile(prefix='tps_test_')
|
||||
tmpfile.write(testcontent)
|
||||
tmpfile.close()
|
||||
|
||||
# generate the profiles defined in the test, and a list of test phases
|
||||
profiles = {}
|
||||
phaselist = []
|
||||
for phase in test:
|
||||
profilename = test[phase]
|
||||
|
||||
# create the profile if necessary
|
||||
if not profilename in profiles:
|
||||
profiles[profilename] = Profile(preferences = self.preferences,
|
||||
addons = self.extensions)
|
||||
|
||||
# create the test phase
|
||||
phaselist.append(TPSTestPhase(
|
||||
phase,
|
||||
profiles[profilename],
|
||||
testname,
|
||||
tmpfile.filename,
|
||||
self.logfile,
|
||||
self.env,
|
||||
self.firefoxRunner,
|
||||
self.log,
|
||||
ignore_unused_engines=self.ignore_unused_engines))
|
||||
|
||||
# sort the phase list by name
|
||||
phaselist = sorted(phaselist, key=lambda phase: phase.phase)
|
||||
|
||||
# run each phase in sequence, aborting at the first failure
|
||||
for phase in phaselist:
|
||||
phase.run()
|
||||
|
||||
# if a failure occurred, dump the entire sync log into the test log
|
||||
if phase.status != "PASS":
|
||||
for profile in profiles:
|
||||
self.log("\nDumping sync log for profile %s\n" % profiles[profile].profile)
|
||||
for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
|
||||
for f in files:
|
||||
weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
|
||||
if os.access(weavelog, os.F_OK):
|
||||
with open(weavelog, 'r') as fh:
|
||||
for line in fh:
|
||||
possible_time = line[0:13]
|
||||
if len(possible_time) == 13 and possible_time.isdigit():
|
||||
time_ms = int(possible_time)
|
||||
formatted = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time_ms / 1000))
|
||||
self.log('%s.%03d %s' % (
|
||||
formatted, time_ms % 1000, line[14:] ))
|
||||
else:
|
||||
self.log(line)
|
||||
break;
|
||||
|
||||
# grep the log for FF and sync versions
|
||||
f = open(self.logfile)
|
||||
logdata = f.read()
|
||||
match = self.syncVerRe.search(logdata)
|
||||
sync_version = match.group("syncversion") if match else 'unknown'
|
||||
match = self.ffVerRe.search(logdata)
|
||||
firefox_version = match.group("ffver") if match else 'unknown'
|
||||
match = self.ffDateRe.search(logdata)
|
||||
firefox_builddate = match.group("ffdate") if match else 'unknown'
|
||||
f.close()
|
||||
if phase.status == 'PASS':
|
||||
logdata = ''
|
||||
else:
|
||||
# we only care about the log data for this specific test
|
||||
logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
|
||||
|
||||
result = {
|
||||
'PASS': lambda x: ('TEST-PASS', ''),
|
||||
'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
|
||||
'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
|
||||
} [phase.status](phase.errline)
|
||||
logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
|
||||
|
||||
try:
|
||||
repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
|
||||
except:
|
||||
repoinfo = {}
|
||||
apprepo = repoinfo.get('application_repository', '')
|
||||
appchangeset = repoinfo.get('application_changeset', '')
|
||||
|
||||
# save logdata to a temporary file for posting to the db
|
||||
tmplogfile = None
|
||||
if logdata:
|
||||
tmplogfile = TempFile(prefix='tps_log_')
|
||||
tmplogfile.write(logdata)
|
||||
tmplogfile.close()
|
||||
self.errorlogs[testname] = tmplogfile
|
||||
|
||||
resultdata = ({ "productversion": { "version": firefox_version,
|
||||
"buildid": firefox_builddate,
|
||||
"builddate": firefox_builddate[0:8],
|
||||
"product": "Firefox",
|
||||
"repository": apprepo,
|
||||
"changeset": appchangeset,
|
||||
},
|
||||
"addonversion": { "version": sync_version,
|
||||
"product": "Firefox Sync" },
|
||||
"name": testname,
|
||||
"message": result[1],
|
||||
"state": result[0],
|
||||
"logdata": logdata
|
||||
})
|
||||
|
||||
self.log(logstr, True)
|
||||
for phase in phaselist:
|
||||
print "\t%s: %s" % (phase.phase, phase.status)
|
||||
if phase.status == 'FAIL':
|
||||
break
|
||||
|
||||
return resultdata
|
||||
|
||||
def run_tests(self):
|
||||
# delete the logfile if it already exists
|
||||
if os.access(self.logfile, os.F_OK):
|
||||
os.remove(self.logfile)
|
||||
|
||||
# Make a copy of the default env variables and preferences, and update
|
||||
# them for mobile settings if needed.
|
||||
self.env = self.default_env.copy()
|
||||
self.preferences = self.default_preferences.copy()
|
||||
if self.mobile:
|
||||
self.preferences.update({'services.sync.client.type' : 'mobile'})
|
||||
|
||||
# Acquire a lock to make sure no other threads are running tests
|
||||
# at the same time.
|
||||
if self.rlock:
|
||||
self.rlock.acquire()
|
||||
|
||||
try:
|
||||
# Create the Firefox runner, which will download and install the
|
||||
# build, as needed.
|
||||
if not self.firefoxRunner:
|
||||
self.firefoxRunner = TPSFirefoxRunner(self.binary)
|
||||
|
||||
# now, run the test group
|
||||
self.run_test_group()
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.numpassed = 0
|
||||
self.numfailed = 1
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
try:
|
||||
|
||||
if self.numfailed > 0 or self.numpassed == 0:
|
||||
To = self.config['email'].get('notificationlist')
|
||||
else:
|
||||
To = self.config['email'].get('passednotificationlist')
|
||||
self.writeToResultFile(self.postdata,
|
||||
sendTo=To)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
def _zip_add_dir(self, zip, dir, rootDir):
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
zip.write(os.path.join(rootDir, dir), dir)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
# on some OS's, adding directory entries doesn't seem to work
|
||||
pass
|
||||
for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
|
||||
for f in files:
|
||||
zip.write(os.path.join(root, f), os.path.join(dir, f))
|
||||
|
||||
# release our lock
|
||||
if self.rlock:
|
||||
self.rlock.release()
|
||||
def run_single_test(self, testdir, testname):
|
||||
testpath = os.path.join(testdir, testname)
|
||||
self.log("Running test %s\n" % testname)
|
||||
|
||||
# dump out a summary of test results
|
||||
print 'Test Summary\n'
|
||||
for test in self.postdata.get('tests', {}):
|
||||
print '%s | %s | %s' % (test['state'], test['name'], test['message'])
|
||||
# Create a random account suffix that is used when creating test
|
||||
# accounts on a staging server.
|
||||
account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
|
||||
for i in range(1,6)])}
|
||||
self.config['account'].update(account_suffix)
|
||||
|
||||
def run_test_group(self):
|
||||
self.results = []
|
||||
self.extensions = []
|
||||
# Read and parse the test file, merge it with the contents of the config
|
||||
# file, and write the combined output to a temporary file.
|
||||
f = open(testpath, 'r')
|
||||
testcontent = f.read()
|
||||
f.close()
|
||||
try:
|
||||
test = json.loads(testcontent)
|
||||
except:
|
||||
test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
|
||||
|
||||
# set the OS we're running on
|
||||
os_string = platform.uname()[2] + " " + platform.uname()[3]
|
||||
if os_string.find("Darwin") > -1:
|
||||
os_string = "Mac OS X " + platform.mac_ver()[0]
|
||||
if platform.uname()[0].find("Linux") > -1:
|
||||
os_string = "Linux " + platform.uname()[5]
|
||||
if platform.uname()[0].find("Win") > -1:
|
||||
os_string = "Windows " + platform.uname()[3]
|
||||
testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
|
||||
testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
|
||||
|
||||
# reset number of passed/failed tests
|
||||
self.numpassed = 0
|
||||
self.numfailed = 0
|
||||
tmpfile = TempFile(prefix='tps_test_')
|
||||
tmpfile.write(testcontent)
|
||||
tmpfile.close()
|
||||
|
||||
# build our tps.xpi extension
|
||||
self.extensions.append(os.path.join(self.extensionDir, 'tps'))
|
||||
self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
|
||||
# generate the profiles defined in the test, and a list of test phases
|
||||
profiles = {}
|
||||
phaselist = []
|
||||
for phase in test:
|
||||
profilename = test[phase]
|
||||
|
||||
# build the test list
|
||||
try:
|
||||
f = open(self.testfile)
|
||||
jsondata = f.read()
|
||||
f.close()
|
||||
testfiles = json.loads(jsondata)
|
||||
testlist = testfiles['tests']
|
||||
except ValueError:
|
||||
testlist = [os.path.basename(self.testfile)]
|
||||
testdir = os.path.dirname(self.testfile)
|
||||
# create the profile if necessary
|
||||
if not profilename in profiles:
|
||||
profiles[profilename] = Profile(preferences = self.preferences,
|
||||
addons = self.extensions)
|
||||
|
||||
self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
|
||||
self.mozhttpd.start()
|
||||
# create the test phase
|
||||
phaselist.append(TPSTestPhase(
|
||||
phase,
|
||||
profiles[profilename],
|
||||
testname,
|
||||
tmpfile.filename,
|
||||
self.logfile,
|
||||
self.env,
|
||||
self.firefoxRunner,
|
||||
self.log,
|
||||
ignore_unused_engines=self.ignore_unused_engines))
|
||||
|
||||
# run each test, and save the results
|
||||
for test in testlist:
|
||||
result = self.run_single_test(testdir, test)
|
||||
# sort the phase list by name
|
||||
phaselist = sorted(phaselist, key=lambda phase: phase.phase)
|
||||
|
||||
if not self.productversion:
|
||||
self.productversion = result['productversion']
|
||||
if not self.addonversion:
|
||||
self.addonversion = result['addonversion']
|
||||
# run each phase in sequence, aborting at the first failure
|
||||
for phase in phaselist:
|
||||
phase.run()
|
||||
|
||||
self.results.append({'state': result['state'],
|
||||
'name': result['name'],
|
||||
'message': result['message'],
|
||||
'logdata': result['logdata']})
|
||||
if result['state'] == 'TEST-PASS':
|
||||
self.numpassed += 1
|
||||
else:
|
||||
self.numfailed += 1
|
||||
# if a failure occurred, dump the entire sync log into the test log
|
||||
if phase.status != "PASS":
|
||||
for profile in profiles:
|
||||
self.log("\nDumping sync log for profile %s\n" % profiles[profile].profile)
|
||||
for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
|
||||
for f in files:
|
||||
weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
|
||||
if os.access(weavelog, os.F_OK):
|
||||
with open(weavelog, 'r') as fh:
|
||||
for line in fh:
|
||||
possible_time = line[0:13]
|
||||
if len(possible_time) == 13 and possible_time.isdigit():
|
||||
time_ms = int(possible_time)
|
||||
formatted = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time_ms / 1000))
|
||||
self.log('%s.%03d %s' % (
|
||||
formatted, time_ms % 1000, line[14:] ))
|
||||
else:
|
||||
self.log(line)
|
||||
break;
|
||||
|
||||
self.mozhttpd.stop()
|
||||
# grep the log for FF and sync versions
|
||||
f = open(self.logfile)
|
||||
logdata = f.read()
|
||||
match = self.syncVerRe.search(logdata)
|
||||
sync_version = match.group("syncversion") if match else 'unknown'
|
||||
match = self.ffVerRe.search(logdata)
|
||||
firefox_version = match.group("ffver") if match else 'unknown'
|
||||
match = self.ffDateRe.search(logdata)
|
||||
firefox_builddate = match.group("ffdate") if match else 'unknown'
|
||||
f.close()
|
||||
if phase.status == 'PASS':
|
||||
logdata = ''
|
||||
else:
|
||||
# we only care about the log data for this specific test
|
||||
logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
|
||||
|
||||
# generate the postdata we'll use to post the results to the db
|
||||
self.postdata = { 'tests': self.results,
|
||||
'os':os_string,
|
||||
'testtype': 'crossweave',
|
||||
'productversion': self.productversion,
|
||||
'addonversion': self.addonversion,
|
||||
'synctype': self.synctype,
|
||||
}
|
||||
result = {
|
||||
'PASS': lambda x: ('TEST-PASS', ''),
|
||||
'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
|
||||
'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
|
||||
} [phase.status](phase.errline)
|
||||
logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
|
||||
|
||||
try:
|
||||
repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
|
||||
except:
|
||||
repoinfo = {}
|
||||
apprepo = repoinfo.get('application_repository', '')
|
||||
appchangeset = repoinfo.get('application_changeset', '')
|
||||
|
||||
# save logdata to a temporary file for posting to the db
|
||||
tmplogfile = None
|
||||
if logdata:
|
||||
tmplogfile = TempFile(prefix='tps_log_')
|
||||
tmplogfile.write(logdata)
|
||||
tmplogfile.close()
|
||||
self.errorlogs[testname] = tmplogfile
|
||||
|
||||
resultdata = ({ "productversion": { "version": firefox_version,
|
||||
"buildid": firefox_builddate,
|
||||
"builddate": firefox_builddate[0:8],
|
||||
"product": "Firefox",
|
||||
"repository": apprepo,
|
||||
"changeset": appchangeset,
|
||||
},
|
||||
"addonversion": { "version": sync_version,
|
||||
"product": "Firefox Sync" },
|
||||
"name": testname,
|
||||
"message": result[1],
|
||||
"state": result[0],
|
||||
"logdata": logdata
|
||||
})
|
||||
|
||||
self.log(logstr, True)
|
||||
for phase in phaselist:
|
||||
print "\t%s: %s" % (phase.phase, phase.status)
|
||||
if phase.status == 'FAIL':
|
||||
break
|
||||
|
||||
return resultdata
|
||||
|
||||
def run_tests(self):
|
||||
# delete the logfile if it already exists
|
||||
if os.access(self.logfile, os.F_OK):
|
||||
os.remove(self.logfile)
|
||||
|
||||
# Make a copy of the default env variables and preferences, and update
|
||||
# them for mobile settings if needed.
|
||||
self.env = self.default_env.copy()
|
||||
self.preferences = self.default_preferences.copy()
|
||||
if self.mobile:
|
||||
self.preferences.update({'services.sync.client.type' : 'mobile'})
|
||||
|
||||
# Acquire a lock to make sure no other threads are running tests
|
||||
# at the same time.
|
||||
if self.rlock:
|
||||
self.rlock.acquire()
|
||||
|
||||
try:
|
||||
# Create the Firefox runner, which will download and install the
|
||||
# build, as needed.
|
||||
if not self.firefoxRunner:
|
||||
self.firefoxRunner = TPSFirefoxRunner(self.binary)
|
||||
|
||||
# now, run the test group
|
||||
self.run_test_group()
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.numpassed = 0
|
||||
self.numfailed = 1
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
try:
|
||||
|
||||
if self.numfailed > 0 or self.numpassed == 0:
|
||||
To = self.config['email'].get('notificationlist')
|
||||
else:
|
||||
To = self.config['email'].get('passednotificationlist')
|
||||
self.writeToResultFile(self.postdata,
|
||||
sendTo=To)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
# release our lock
|
||||
if self.rlock:
|
||||
self.rlock.release()
|
||||
|
||||
# dump out a summary of test results
|
||||
print 'Test Summary\n'
|
||||
for test in self.postdata.get('tests', {}):
|
||||
print '%s | %s | %s' % (test['state'], test['name'], test['message'])
|
||||
|
||||
def run_test_group(self):
|
||||
self.results = []
|
||||
self.extensions = []
|
||||
|
||||
# set the OS we're running on
|
||||
os_string = platform.uname()[2] + " " + platform.uname()[3]
|
||||
if os_string.find("Darwin") > -1:
|
||||
os_string = "Mac OS X " + platform.mac_ver()[0]
|
||||
if platform.uname()[0].find("Linux") > -1:
|
||||
os_string = "Linux " + platform.uname()[5]
|
||||
if platform.uname()[0].find("Win") > -1:
|
||||
os_string = "Windows " + platform.uname()[3]
|
||||
|
||||
# reset number of passed/failed tests
|
||||
self.numpassed = 0
|
||||
self.numfailed = 0
|
||||
|
||||
# build our tps.xpi extension
|
||||
self.extensions.append(os.path.join(self.extensionDir, 'tps'))
|
||||
self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
|
||||
|
||||
# build the test list
|
||||
try:
|
||||
f = open(self.testfile)
|
||||
jsondata = f.read()
|
||||
f.close()
|
||||
testfiles = json.loads(jsondata)
|
||||
testlist = testfiles['tests']
|
||||
except ValueError:
|
||||
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)
|
||||
|
||||
if not self.productversion:
|
||||
self.productversion = result['productversion']
|
||||
if not self.addonversion:
|
||||
self.addonversion = result['addonversion']
|
||||
|
||||
self.results.append({'state': result['state'],
|
||||
'name': result['name'],
|
||||
'message': result['message'],
|
||||
'logdata': result['logdata']})
|
||||
if result['state'] == 'TEST-PASS':
|
||||
self.numpassed += 1
|
||||
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,
|
||||
'testtype': 'crossweave',
|
||||
'productversion': self.productversion,
|
||||
'addonversion': self.addonversion,
|
||||
'synctype': self.synctype,
|
||||
}
|
||||
|
|
|
@ -8,57 +8,57 @@ from testrunner import TPSTestRunner
|
|||
|
||||
class TPSTestThread(Thread):
|
||||
|
||||
def __init__(self, extensionDir, builddata=None,
|
||||
testfile=None, logfile=None, rlock=None, config=None):
|
||||
assert(builddata)
|
||||
assert(config)
|
||||
self.extensionDir = extensionDir
|
||||
self.builddata = builddata
|
||||
self.testfile = testfile
|
||||
self.logfile = logfile
|
||||
self.rlock = rlock
|
||||
self.config = config
|
||||
Thread.__init__(self)
|
||||
def __init__(self, extensionDir, builddata=None,
|
||||
testfile=None, logfile=None, rlock=None, config=None):
|
||||
assert(builddata)
|
||||
assert(config)
|
||||
self.extensionDir = extensionDir
|
||||
self.builddata = builddata
|
||||
self.testfile = testfile
|
||||
self.logfile = logfile
|
||||
self.rlock = rlock
|
||||
self.config = config
|
||||
Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
# run the tests in normal mode ...
|
||||
TPS = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=self.builddata['buildurl'],
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=False)
|
||||
TPS.run_tests()
|
||||
def run(self):
|
||||
# run the tests in normal mode ...
|
||||
TPS = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=self.builddata['buildurl'],
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=False)
|
||||
TPS.run_tests()
|
||||
|
||||
# Get the binary used by this TPS instance, and use it in subsequent
|
||||
# ones, so it doesn't have to be re-downloaded each time.
|
||||
binary = TPS.firefoxRunner.binary
|
||||
# Get the binary used by this TPS instance, and use it in subsequent
|
||||
# ones, so it doesn't have to be re-downloaded each time.
|
||||
binary = TPS.firefoxRunner.binary
|
||||
|
||||
# ... and then again in mobile mode
|
||||
TPS_mobile = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=True)
|
||||
TPS_mobile.run_tests()
|
||||
# ... and then again in mobile mode
|
||||
TPS_mobile = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=True)
|
||||
TPS_mobile.run_tests()
|
||||
|
||||
# ... and again via the staging server, if credentials are present
|
||||
stageaccount = self.config.get('stageaccount')
|
||||
if stageaccount:
|
||||
username = stageaccount.get('username')
|
||||
password = stageaccount.get('password')
|
||||
passphrase = stageaccount.get('passphrase')
|
||||
if username and password and passphrase:
|
||||
stageconfig = self.config.copy()
|
||||
stageconfig['account'] = stageaccount.copy()
|
||||
TPS_stage = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=stageconfig,
|
||||
rlock=self.rlock,
|
||||
mobile=False)#, autolog=self.autolog)
|
||||
TPS_stage.run_tests()
|
||||
# ... and again via the staging server, if credentials are present
|
||||
stageaccount = self.config.get('stageaccount')
|
||||
if stageaccount:
|
||||
username = stageaccount.get('username')
|
||||
password = stageaccount.get('password')
|
||||
passphrase = stageaccount.get('passphrase')
|
||||
if username and password and passphrase:
|
||||
stageconfig = self.config.copy()
|
||||
stageconfig['account'] = stageaccount.copy()
|
||||
TPS_stage = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=stageconfig,
|
||||
rlock=self.rlock,
|
||||
mobile=False)#, autolog=self.autolog)
|
||||
TPS_stage.run_tests()
|
||||
|
|
Загрузка…
Ссылка в новой задаче