Bug 822875 - Make TPS .py files use 4-space indent, r=jgriffin

This commit is contained in:
Vignesh Sarma 2013-01-11 13:32:50 -08:00
Родитель e23d811ae6
Коммит 7939b690c0
6 изменённых файлов: 640 добавлений и 642 удалений

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

@ -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()