Bug 1127376 - PEP8-ify all mochitest .py files (auto-generated), r=ted
This change was generated using the `autopep8` module [1]. To replicate:
$ pip install --upgrade autopep8
$ cd gecko
$ autopep8 -i -a -a -r testing/mochitest --exclude 'testing/mochitest/pywebsocket/*'
[1] https://github.com/hhatto/autopep8
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import math
|
||||
import mozinfo
|
||||
|
||||
|
||||
class Bisect(object):
|
||||
|
||||
"Class for creating, bisecting and summarizing for --bisect-chunk option."
|
||||
|
||||
def __init__(self, harness):
|
||||
@@ -34,23 +36,28 @@ class Bisect(object):
|
||||
if not options.totalChunks or not options.thisChunk:
|
||||
return tests
|
||||
|
||||
# The logic here is same as chunkifyTests.js, we need this for bisecting tests.
|
||||
# The logic here is same as chunkifyTests.js, we need this for
|
||||
# bisecting tests.
|
||||
if options.chunkByDir:
|
||||
tests_by_dir = {}
|
||||
test_dirs = []
|
||||
for test in tests:
|
||||
directory = test.split("/")
|
||||
directory = directory[0:min(options.chunkByDir, len(directory)-1)]
|
||||
directory = directory[
|
||||
0:min(
|
||||
options.chunkByDir,
|
||||
len(directory) -
|
||||
1)]
|
||||
directory = "/".join(directory)
|
||||
|
||||
if not directory in tests_by_dir:
|
||||
if directory not in tests_by_dir:
|
||||
tests_by_dir[directory] = [test]
|
||||
test_dirs.append(directory)
|
||||
else:
|
||||
tests_by_dir[directory].append(test)
|
||||
|
||||
tests_per_chunk = float(len(test_dirs)) / options.totalChunks
|
||||
start = int(round((options.thisChunk-1) * tests_per_chunk))
|
||||
start = int(round((options.thisChunk - 1) * tests_per_chunk))
|
||||
end = int(round((options.thisChunk) * tests_per_chunk))
|
||||
test_dirs = test_dirs[start:end]
|
||||
return_tests = []
|
||||
@@ -59,7 +66,7 @@ class Bisect(object):
|
||||
|
||||
else:
|
||||
tests_per_chunk = float(len(tests)) / options.totalChunks
|
||||
start = int(round((options.thisChunk-1) * tests_per_chunk))
|
||||
start = int(round((options.thisChunk - 1) * tests_per_chunk))
|
||||
end = int(round(options.thisChunk * tests_per_chunk))
|
||||
return_tests = tests[start:end]
|
||||
|
||||
@@ -83,7 +90,8 @@ class Bisect(object):
|
||||
"This method is used to call other methods for setting up variables and getting the list of tests for bisection."
|
||||
if options.bisectChunk == "default":
|
||||
return tests
|
||||
# The second condition in 'if' is required to verify that the failing test is the last one.
|
||||
# The second condition in 'if' is required to verify that the failing
|
||||
# test is the last one.
|
||||
elif 'loop' not in self.contents or not self.contents['tests'][-1].endswith(options.bisectChunk):
|
||||
tests = self.get_tests_for_bisection(options, tests)
|
||||
status = self.setup(tests)
|
||||
@@ -97,14 +105,16 @@ class Bisect(object):
|
||||
# Check whether sanity check has to be done. Also it is necessary to check whether options.bisectChunk is present
|
||||
# in self.expectedError as we do not want to run if it is "default".
|
||||
if status == -1 and options.bisectChunk in self.expectedError:
|
||||
# In case we have a debug build, we don't want to run a sanity check, will take too much time.
|
||||
# In case we have a debug build, we don't want to run a sanity
|
||||
# check, will take too much time.
|
||||
if mozinfo.info['debug']:
|
||||
return status
|
||||
|
||||
testBleedThrough = self.contents['testsToRun'][0]
|
||||
tests = self.contents['totalTests']
|
||||
tests.remove(testBleedThrough)
|
||||
# To make sure that the failing test is dependent on some other test.
|
||||
# To make sure that the failing test is dependent on some other
|
||||
# test.
|
||||
if options.bisectChunk in testBleedThrough:
|
||||
return status
|
||||
|
||||
@@ -189,22 +199,35 @@ class Bisect(object):
|
||||
def summarize_chunk(self, options):
|
||||
"This method is used summarize the results after the list of tests is run."
|
||||
if options.bisectChunk == "default":
|
||||
# if no expectedError that means all the tests have successfully passed.
|
||||
# if no expectedError that means all the tests have successfully
|
||||
# passed.
|
||||
if len(self.expectedError) == 0:
|
||||
return -1
|
||||
options.bisectChunk = self.expectedError.keys()[0]
|
||||
self.summary.append("\tFound Error in test: %s" % options.bisectChunk)
|
||||
self.summary.append(
|
||||
"\tFound Error in test: %s" %
|
||||
options.bisectChunk)
|
||||
return 0
|
||||
|
||||
# If options.bisectChunk is not in self.result then we need to move to the next run.
|
||||
# If options.bisectChunk is not in self.result then we need to move to
|
||||
# the next run.
|
||||
if options.bisectChunk not in self.result:
|
||||
return -1
|
||||
|
||||
self.summary.append("\tPass %d:" % self.contents['loop'])
|
||||
if len(self.contents['testsToRun']) > 1:
|
||||
self.summary.append("\t\t%d test files(start,end,failing). [%s, %s, %s]" % (len(self.contents['testsToRun']), self.contents['testsToRun'][0], self.contents['testsToRun'][-2], self.contents['testsToRun'][-1]))
|
||||
self.summary.append(
|
||||
"\t\t%d test files(start,end,failing). [%s, %s, %s]" % (len(
|
||||
self.contents['testsToRun']),
|
||||
self.contents['testsToRun'][0],
|
||||
self.contents['testsToRun'][
|
||||
-2],
|
||||
self.contents['testsToRun'][
|
||||
-1]))
|
||||
else:
|
||||
self.summary.append("\t\t1 test file [%s]" % self.contents['testsToRun'][0])
|
||||
self.summary.append(
|
||||
"\t\t1 test file [%s]" %
|
||||
self.contents['testsToRun'][0])
|
||||
return self.check_for_intermittent(options)
|
||||
|
||||
if self.result[options.bisectChunk] == "PASS":
|
||||
@@ -217,23 +240,32 @@ class Bisect(object):
|
||||
|
||||
elif self.result[options.bisectChunk] == "FAIL":
|
||||
if 'expectedError' not in self.contents:
|
||||
self.summary.append("\t\t%s failed." % self.contents['testsToRun'][-1])
|
||||
self.contents['expectedError'] = self.expectedError[options.bisectChunk]
|
||||
self.summary.append("\t\t%s failed." %
|
||||
self.contents['testsToRun'][-1])
|
||||
self.contents['expectedError'] = self.expectedError[
|
||||
options.bisectChunk]
|
||||
status = 0
|
||||
|
||||
elif self.expectedError[options.bisectChunk] == self.contents['expectedError']:
|
||||
self.summary.append("\t\t%s failed with expected error." % self.contents['testsToRun'][-1])
|
||||
self.summary.append(
|
||||
"\t\t%s failed with expected error." % self.contents['testsToRun'][-1])
|
||||
self.contents['result'] = "FAIL"
|
||||
status = 0
|
||||
|
||||
# This code checks for test-bleedthrough. Should work for any algorithm.
|
||||
# This code checks for test-bleedthrough. Should work for any
|
||||
# algorithm.
|
||||
numberOfTests = len(self.contents['testsToRun'])
|
||||
if numberOfTests < 3:
|
||||
# This means that only 2 tests are run. Since the last test is the failing test itself therefore the bleedthrough test is the first test
|
||||
self.summary.append("TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" % self.contents['testsToRun'][0])
|
||||
# This means that only 2 tests are run. Since the last test
|
||||
# is the failing test itself therefore the bleedthrough
|
||||
# test is the first test
|
||||
self.summary.append(
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
|
||||
self.contents['testsToRun'][0])
|
||||
status = -1
|
||||
else:
|
||||
self.summary.append("\t\t%s failed with different error." % self.contents['testsToRun'][-1])
|
||||
self.summary.append(
|
||||
"\t\t%s failed with different error." % self.contents['testsToRun'][-1])
|
||||
status = -1
|
||||
|
||||
return status
|
||||
@@ -241,7 +273,9 @@ class Bisect(object):
|
||||
def check_for_intermittent(self, options):
|
||||
"This method is used to check whether a test is an intermittent."
|
||||
if self.result[options.bisectChunk] == "PASS":
|
||||
self.summary.append("\t\tThe test %s passed." % self.contents['testsToRun'][0])
|
||||
self.summary.append(
|
||||
"\t\tThe test %s passed." %
|
||||
self.contents['testsToRun'][0])
|
||||
if self.repeat > 0:
|
||||
# loop is set to 1 to again run the single test.
|
||||
self.contents['loop'] = 1
|
||||
@@ -256,7 +290,9 @@ class Bisect(object):
|
||||
self.contents['loop'] = 2
|
||||
return 1
|
||||
elif self.result[options.bisectChunk] == "FAIL":
|
||||
self.summary.append("\t\tThe test %s failed." % self.contents['testsToRun'][0])
|
||||
self.summary.append(
|
||||
"\t\tThe test %s failed." %
|
||||
self.contents['testsToRun'][0])
|
||||
self.failcount += 1
|
||||
self.contents['loop'] = 1
|
||||
self.repeat -= 1
|
||||
@@ -269,7 +305,9 @@ class Bisect(object):
|
||||
return -1
|
||||
return 0
|
||||
else:
|
||||
self.summary.append("TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" % self.contents['testsToRun'][0])
|
||||
self.summary.append(
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
|
||||
self.contents['testsToRun'][0])
|
||||
return -1
|
||||
|
||||
def print_summary(self):
|
||||
|
||||
@@ -81,6 +81,7 @@ FLAVORS = {
|
||||
|
||||
|
||||
class MochitestRunner(MozbuildObject):
|
||||
|
||||
"""Easily run mochitests.
|
||||
|
||||
This currently contains just the basics for running mochitests. We may want
|
||||
@@ -91,8 +92,12 @@ class MochitestRunner(MozbuildObject):
|
||||
import mozinfo
|
||||
appname = 'webapprt-stub' + mozinfo.info.get('bin_suffix', '')
|
||||
if sys.platform.startswith('darwin'):
|
||||
appname = os.path.join(self.distdir, self.substs['MOZ_MACBUNDLE_NAME'],
|
||||
'Contents', 'Resources', appname)
|
||||
appname = os.path.join(
|
||||
self.distdir,
|
||||
self.substs['MOZ_MACBUNDLE_NAME'],
|
||||
'Contents',
|
||||
'Resources',
|
||||
appname)
|
||||
else:
|
||||
appname = os.path.join(self.distdir, 'bin', appname)
|
||||
return appname
|
||||
@@ -106,12 +111,24 @@ class MochitestRunner(MozbuildObject):
|
||||
sys.path.append(build_path)
|
||||
|
||||
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
||||
self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
|
||||
self.mochitest_dir = os.path.join(
|
||||
self.tests_dir,
|
||||
'testing',
|
||||
'mochitest')
|
||||
self.bin_dir = os.path.join(self.topobjdir, 'dist', 'bin')
|
||||
|
||||
def run_b2g_test(self, test_paths=None, b2g_home=None, xre_path=None,
|
||||
total_chunks=None, this_chunk=None, no_window=None,
|
||||
repeat=0, run_until_failure=False, chrome=False, **kwargs):
|
||||
def run_b2g_test(
|
||||
self,
|
||||
test_paths=None,
|
||||
b2g_home=None,
|
||||
xre_path=None,
|
||||
total_chunks=None,
|
||||
this_chunk=None,
|
||||
no_window=None,
|
||||
repeat=0,
|
||||
run_until_failure=False,
|
||||
chrome=False,
|
||||
**kwargs):
|
||||
"""Runs a b2g mochitest.
|
||||
|
||||
test_paths is an enumerable of paths to tests. It can be a relative path
|
||||
@@ -147,11 +164,19 @@ class MochitestRunner(MozbuildObject):
|
||||
|
||||
if test_path:
|
||||
if chrome:
|
||||
test_root_file = mozpack.path.join(self.mochitest_dir, 'chrome', test_path)
|
||||
test_root_file = mozpack.path.join(
|
||||
self.mochitest_dir,
|
||||
'chrome',
|
||||
test_path)
|
||||
else:
|
||||
test_root_file = mozpack.path.join(self.mochitest_dir, 'tests', test_path)
|
||||
test_root_file = mozpack.path.join(
|
||||
self.mochitest_dir,
|
||||
'tests',
|
||||
test_path)
|
||||
if not os.path.exists(test_root_file):
|
||||
print('Specified test path does not exist: %s' % test_root_file)
|
||||
print(
|
||||
'Specified test path does not exist: %s' %
|
||||
test_root_file)
|
||||
return 1
|
||||
options.testPath = test_path
|
||||
|
||||
@@ -163,7 +188,9 @@ class MochitestRunner(MozbuildObject):
|
||||
options.repeat = repeat
|
||||
options.runUntilFailure = run_until_failure
|
||||
|
||||
options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
|
||||
options.symbolsPath = os.path.join(
|
||||
self.distdir,
|
||||
'crashreporter-symbols')
|
||||
|
||||
options.consoleLevel = 'INFO'
|
||||
if conditions.is_b2g_desktop(self):
|
||||
@@ -190,15 +217,46 @@ class MochitestRunner(MozbuildObject):
|
||||
options.chrome = chrome
|
||||
return mochitest.run_remote_mochitests(parser, options)
|
||||
|
||||
def run_desktop_test(self, context, suite=None, test_paths=None, debugger=None,
|
||||
debugger_args=None, slowscript=False, screenshot_on_fail = False, shuffle=False, closure_behaviour='auto',
|
||||
rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False,
|
||||
slow=False, chunk_by_dir=0, total_chunks=None, this_chunk=None, extraPrefs=[],
|
||||
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
|
||||
e10s=False, strict_content_sandbox=False, nested_oop=False, dmd=False, dump_output_directory=None,
|
||||
dump_about_memory_after_test=False, dump_dmd_after_test=False,
|
||||
install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False,
|
||||
useTestMediaDevices=False, timeout=None, **kwargs):
|
||||
def run_desktop_test(
|
||||
self,
|
||||
context,
|
||||
suite=None,
|
||||
test_paths=None,
|
||||
debugger=None,
|
||||
debugger_args=None,
|
||||
slowscript=False,
|
||||
screenshot_on_fail=False,
|
||||
shuffle=False,
|
||||
closure_behaviour='auto',
|
||||
rerun_failures=False,
|
||||
no_autorun=False,
|
||||
repeat=0,
|
||||
run_until_failure=False,
|
||||
slow=False,
|
||||
chunk_by_dir=0,
|
||||
total_chunks=None,
|
||||
this_chunk=None,
|
||||
extraPrefs=[],
|
||||
jsdebugger=False,
|
||||
debug_on_failure=False,
|
||||
start_at=None,
|
||||
end_at=None,
|
||||
e10s=False,
|
||||
strict_content_sandbox=False,
|
||||
nested_oop=False,
|
||||
dmd=False,
|
||||
dump_output_directory=None,
|
||||
dump_about_memory_after_test=False,
|
||||
dump_dmd_after_test=False,
|
||||
install_extension=None,
|
||||
quiet=False,
|
||||
environment=[],
|
||||
app_override=None,
|
||||
bisectChunk=None,
|
||||
runByDir=False,
|
||||
useTestMediaDevices=False,
|
||||
timeout=None,
|
||||
**kwargs):
|
||||
"""Runs a mochitest.
|
||||
|
||||
test_paths are path to tests. They can be a relative path from the
|
||||
@@ -227,9 +285,12 @@ class MochitestRunner(MozbuildObject):
|
||||
|
||||
# Make absolute paths relative before calling os.chdir() below.
|
||||
if test_paths:
|
||||
test_paths = [self._wrap_path_argument(p).relpath() if os.path.isabs(p) else p for p in test_paths]
|
||||
test_paths = [self._wrap_path_argument(
|
||||
p).relpath() if os.path.isabs(p) else p for p in test_paths]
|
||||
|
||||
failure_file_path = os.path.join(self.statedir, 'mochitest_failures.json')
|
||||
failure_file_path = os.path.join(
|
||||
self.statedir,
|
||||
'mochitest_failures.json')
|
||||
|
||||
if rerun_failures and not os.path.exists(failure_file_path):
|
||||
print('No failure file present. Did you run mochitests before?')
|
||||
@@ -308,7 +369,9 @@ class MochitestRunner(MozbuildObject):
|
||||
options.runSlower = slow
|
||||
options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
|
||||
options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins'))
|
||||
options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
|
||||
options.symbolsPath = os.path.join(
|
||||
self.distdir,
|
||||
'crashreporter-symbols')
|
||||
options.chunkByDir = chunk_by_dir
|
||||
options.totalChunks = total_chunks
|
||||
options.thisChunk = this_chunk
|
||||
@@ -332,8 +395,11 @@ class MochitestRunner(MozbuildObject):
|
||||
options.timeout = int(timeout)
|
||||
|
||||
options.failureFile = failure_file_path
|
||||
if install_extension != None:
|
||||
options.extensionsToInstall = [os.path.join(self.topsrcdir,install_extension)]
|
||||
if install_extension is not None:
|
||||
options.extensionsToInstall = [
|
||||
os.path.join(
|
||||
self.topsrcdir,
|
||||
install_extension)]
|
||||
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(options, k, v)
|
||||
@@ -341,7 +407,10 @@ class MochitestRunner(MozbuildObject):
|
||||
if test_paths:
|
||||
resolver = self._spawn(TestResolver)
|
||||
|
||||
tests = list(resolver.resolve_tests(paths=test_paths, flavor=flavor))
|
||||
tests = list(
|
||||
resolver.resolve_tests(
|
||||
paths=test_paths,
|
||||
flavor=flavor))
|
||||
|
||||
if not tests:
|
||||
print('No tests could be found in the path specified. Please '
|
||||
@@ -352,7 +421,8 @@ class MochitestRunner(MozbuildObject):
|
||||
manifest = TestManifest()
|
||||
manifest.tests.extend(tests)
|
||||
|
||||
if len(tests) == 1 and closure_behaviour == 'auto' and suite == 'plain':
|
||||
if len(
|
||||
tests) == 1 and closure_behaviour == 'auto' and suite == 'plain':
|
||||
options.closeWhenDone = False
|
||||
|
||||
options.manifestFile = manifest
|
||||
@@ -364,7 +434,7 @@ class MochitestRunner(MozbuildObject):
|
||||
options.debugger = debugger
|
||||
|
||||
if debugger_args:
|
||||
if options.debugger == None:
|
||||
if options.debugger is None:
|
||||
print("--debugger-args passed, but no debugger specified.")
|
||||
return 1
|
||||
options.debuggerArgs = debugger_args
|
||||
@@ -375,14 +445,22 @@ class MochitestRunner(MozbuildObject):
|
||||
elif app_override:
|
||||
options.app = app_override
|
||||
if options.gmp_path is None:
|
||||
# Need to fix the location of gmp_fake which might not be shipped in the binary
|
||||
# Need to fix the location of gmp_fake which might not be
|
||||
# shipped in the binary
|
||||
bin_path = self.get_binary_path()
|
||||
options.gmp_path = os.path.join(os.path.dirname(bin_path), 'gmp-fake', '1.0')
|
||||
options.gmp_path = os.path.join(
|
||||
os.path.dirname(bin_path),
|
||||
'gmp-fake',
|
||||
'1.0')
|
||||
options.gmp_path += os.pathsep
|
||||
options.gmp_path += os.path.join(os.path.dirname(bin_path), 'gmp-clearkey', '0.1')
|
||||
options.gmp_path += os.path.join(
|
||||
os.path.dirname(bin_path),
|
||||
'gmp-clearkey',
|
||||
'0.1')
|
||||
|
||||
|
||||
logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')}
|
||||
logger_options = {
|
||||
key: value for key,
|
||||
value in vars(options).iteritems() if key.startswith('log')}
|
||||
runner = mochitest.Mochitest(logger_options)
|
||||
options = opts.verifyOptions(options, runner)
|
||||
|
||||
@@ -414,12 +492,17 @@ def MochitestCommand(func):
|
||||
# (modified) function. Here, we chain decorators onto the passed in
|
||||
# function.
|
||||
|
||||
debugger = CommandArgument('--debugger', '-d', metavar='DEBUGGER',
|
||||
debugger = CommandArgument(
|
||||
'--debugger',
|
||||
'-d',
|
||||
metavar='DEBUGGER',
|
||||
help='Debugger binary to run test in. Program name or path.')
|
||||
func = debugger(func)
|
||||
|
||||
debugger_args = CommandArgument('--debugger-args',
|
||||
metavar='DEBUGGER_ARGS', help='Arguments to pass to the debugger.')
|
||||
debugger_args = CommandArgument(
|
||||
'--debugger-args',
|
||||
metavar='DEBUGGER_ARGS',
|
||||
help='Arguments to pass to the debugger.')
|
||||
func = debugger_args(func)
|
||||
|
||||
# Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
|
||||
@@ -427,11 +510,15 @@ def MochitestCommand(func):
|
||||
# code. If we don't pass this, the user will need to periodically type
|
||||
# "continue" to (safely) resume execution. There are ways to implement
|
||||
# automatic resuming; see the bug.
|
||||
slowscript = CommandArgument('--slowscript', action='store_true',
|
||||
slowscript = CommandArgument(
|
||||
'--slowscript',
|
||||
action='store_true',
|
||||
help='Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; when not set, recoverable but misleading SIGSEGV instances may occur in Ion/Odin JIT code')
|
||||
func = slowscript(func)
|
||||
|
||||
screenshot_on_fail = CommandArgument('--screenshot-on-fail', action='store_true',
|
||||
screenshot_on_fail = CommandArgument(
|
||||
'--screenshot-on-fail',
|
||||
action='store_true',
|
||||
help='Take screenshots on all test failures. Set $MOZ_UPLOAD_DIR to a directory for storing the screenshots.')
|
||||
func = screenshot_on_fail(func)
|
||||
|
||||
@@ -439,21 +526,33 @@ def MochitestCommand(func):
|
||||
help='Shuffle execution order.')
|
||||
func = shuffle(func)
|
||||
|
||||
keep_open = CommandArgument('--keep-open', action='store_const',
|
||||
dest='closure_behaviour', const='open', default='auto',
|
||||
keep_open = CommandArgument(
|
||||
'--keep-open',
|
||||
action='store_const',
|
||||
dest='closure_behaviour',
|
||||
const='open',
|
||||
default='auto',
|
||||
help='Always keep the browser open after tests complete.')
|
||||
func = keep_open(func)
|
||||
|
||||
autoclose = CommandArgument('--auto-close', action='store_const',
|
||||
dest='closure_behaviour', const='close', default='auto',
|
||||
autoclose = CommandArgument(
|
||||
'--auto-close',
|
||||
action='store_const',
|
||||
dest='closure_behaviour',
|
||||
const='close',
|
||||
default='auto',
|
||||
help='Always close the browser after tests complete.')
|
||||
func = autoclose(func)
|
||||
|
||||
rerun = CommandArgument('--rerun-failures', action='store_true',
|
||||
rerun = CommandArgument(
|
||||
'--rerun-failures',
|
||||
action='store_true',
|
||||
help='Run only the tests that failed during the last test run.')
|
||||
func = rerun(func)
|
||||
|
||||
autorun = CommandArgument('--no-autorun', action='store_true',
|
||||
autorun = CommandArgument(
|
||||
'--no-autorun',
|
||||
action='store_true',
|
||||
help='Do not starting running tests automatically.')
|
||||
func = autorun(func)
|
||||
|
||||
@@ -461,9 +560,11 @@ def MochitestCommand(func):
|
||||
help='Repeat the test the given number of times.')
|
||||
func = repeat(func)
|
||||
|
||||
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
|
||||
help='Run tests repeatedly and stops on the first time a test fails. ' \
|
||||
'Default cap is 30 runs, which can be overwritten ' \
|
||||
runUntilFailure = CommandArgument(
|
||||
"--run-until-failure",
|
||||
action='store_true',
|
||||
help='Run tests repeatedly and stops on the first time a test fails. '
|
||||
'Default cap is 30 runs, which can be overwritten '
|
||||
'with the --repeat parameter.')
|
||||
func = runUntilFailure(func)
|
||||
|
||||
@@ -471,28 +572,40 @@ def MochitestCommand(func):
|
||||
help='Delay execution between tests.')
|
||||
func = slow(func)
|
||||
|
||||
end_at = CommandArgument('--end-at', type=str,
|
||||
end_at = CommandArgument(
|
||||
'--end-at',
|
||||
type=str,
|
||||
help='Stop running the test sequence at this test.')
|
||||
func = end_at(func)
|
||||
|
||||
start_at = CommandArgument('--start-at', type=str,
|
||||
start_at = CommandArgument(
|
||||
'--start-at',
|
||||
type=str,
|
||||
help='Start running the test sequence at this test.')
|
||||
func = start_at(func)
|
||||
|
||||
chunk_dir = CommandArgument('--chunk-by-dir', type=int,
|
||||
chunk_dir = CommandArgument(
|
||||
'--chunk-by-dir',
|
||||
type=int,
|
||||
help='Group tests together in chunks by this many top directories.')
|
||||
func = chunk_dir(func)
|
||||
|
||||
chunk_total = CommandArgument('--total-chunks', type=int,
|
||||
chunk_total = CommandArgument(
|
||||
'--total-chunks',
|
||||
type=int,
|
||||
help='Total number of chunks to split tests into.')
|
||||
func = chunk_total(func)
|
||||
|
||||
this_chunk = CommandArgument('--this-chunk', type=int,
|
||||
this_chunk = CommandArgument(
|
||||
'--this-chunk',
|
||||
type=int,
|
||||
help='If running tests by chunks, the number of the chunk to run.')
|
||||
func = this_chunk(func)
|
||||
|
||||
debug_on_failure = CommandArgument('--debug-on-failure', action='store_true',
|
||||
help='Breaks execution and enters the JS debugger on a test failure. ' \
|
||||
debug_on_failure = CommandArgument(
|
||||
'--debug-on-failure',
|
||||
action='store_true',
|
||||
help='Breaks execution and enters the JS debugger on a test failure. '
|
||||
'Should be used together with --jsdebugger.')
|
||||
func = debug_on_failure(func)
|
||||
|
||||
@@ -501,19 +614,27 @@ def MochitestCommand(func):
|
||||
help='defines an extra user preference')
|
||||
func = setpref(func)
|
||||
|
||||
jsdebugger = CommandArgument('--jsdebugger', action='store_true',
|
||||
jsdebugger = CommandArgument(
|
||||
'--jsdebugger',
|
||||
action='store_true',
|
||||
help='Start the browser JS debugger before running the test. Implies --no-autorun.')
|
||||
func = jsdebugger(func)
|
||||
|
||||
e10s = CommandArgument('--e10s', action='store_true',
|
||||
e10s = CommandArgument(
|
||||
'--e10s',
|
||||
action='store_true',
|
||||
help='Run tests with electrolysis preferences and test filtering enabled.')
|
||||
func = e10s(func)
|
||||
|
||||
strict_content_sandbox = CommandArgument('--strict-content-sandbox', action='store_true',
|
||||
strict_content_sandbox = CommandArgument(
|
||||
'--strict-content-sandbox',
|
||||
action='store_true',
|
||||
help='Run tests with a more strict content sandbox (Windows only).')
|
||||
func = strict_content_sandbox(func)
|
||||
|
||||
this_chunk = CommandArgument('--nested_oop', action='store_true',
|
||||
this_chunk = CommandArgument(
|
||||
'--nested_oop',
|
||||
action='store_true',
|
||||
help='Run tests with nested oop preferences and test filtering enabled.')
|
||||
func = this_chunk(func)
|
||||
|
||||
@@ -521,7 +642,9 @@ def MochitestCommand(func):
|
||||
help='Run tests with DMD active.')
|
||||
func = dmd(func)
|
||||
|
||||
dumpAboutMemory = CommandArgument('--dump-about-memory-after-test', action='store_true',
|
||||
dumpAboutMemory = CommandArgument(
|
||||
'--dump-about-memory-after-test',
|
||||
action='store_true',
|
||||
help='Dump an about:memory log after every test.')
|
||||
func = dumpAboutMemory(func)
|
||||
|
||||
@@ -529,65 +652,92 @@ def MochitestCommand(func):
|
||||
help='Dump a DMD log after every test.')
|
||||
func = dumpDMD(func)
|
||||
|
||||
dumpOutputDirectory = CommandArgument('--dump-output-directory', action='store',
|
||||
dumpOutputDirectory = CommandArgument(
|
||||
'--dump-output-directory',
|
||||
action='store',
|
||||
help='Specifies the directory in which to place dumped memory reports.')
|
||||
func = dumpOutputDirectory(func)
|
||||
|
||||
path = CommandArgument('test_paths', default=None, nargs='*',
|
||||
path = CommandArgument(
|
||||
'test_paths',
|
||||
default=None,
|
||||
nargs='*',
|
||||
metavar='TEST',
|
||||
help='Test to run. Can be specified as a single file, a ' \
|
||||
'directory, or omitted. If omitted, the entire test suite is ' \
|
||||
help='Test to run. Can be specified as a single file, a '
|
||||
'directory, or omitted. If omitted, the entire test suite is '
|
||||
'executed.')
|
||||
func = path(func)
|
||||
|
||||
install_extension = CommandArgument('--install-extension',
|
||||
help='Install given extension before running selected tests. ' \
|
||||
install_extension = CommandArgument(
|
||||
'--install-extension',
|
||||
help='Install given extension before running selected tests. '
|
||||
'Parameter is a path to xpi file.')
|
||||
func = install_extension(func)
|
||||
|
||||
quiet = CommandArgument('--quiet', default=False, action='store_true',
|
||||
quiet = CommandArgument(
|
||||
'--quiet',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Do not print test log lines unless a failure occurs.')
|
||||
func = quiet(func)
|
||||
|
||||
setenv = CommandArgument('--setenv', default=[], action='append',
|
||||
metavar='NAME=VALUE', dest='environment',
|
||||
setenv = CommandArgument(
|
||||
'--setenv',
|
||||
default=[],
|
||||
action='append',
|
||||
metavar='NAME=VALUE',
|
||||
dest='environment',
|
||||
help="Sets the given variable in the application's environment")
|
||||
func = setenv(func)
|
||||
|
||||
runbydir = CommandArgument('--run-by-dir', default=False,
|
||||
runbydir = CommandArgument(
|
||||
'--run-by-dir',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='runByDir',
|
||||
help='Run each directory in a single browser instance with a fresh profile.')
|
||||
func = runbydir(func)
|
||||
|
||||
bisect_chunk = CommandArgument('--bisect-chunk', type=str,
|
||||
bisect_chunk = CommandArgument(
|
||||
'--bisect-chunk',
|
||||
type=str,
|
||||
dest='bisectChunk',
|
||||
help='Specify the failing test name to find the previous tests that may be causing the failure.')
|
||||
func = bisect_chunk(func)
|
||||
|
||||
test_media = CommandArgument('--use-test-media-devices', default=False,
|
||||
test_media = CommandArgument(
|
||||
'--use-test-media-devices',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='useTestMediaDevices',
|
||||
help='Use test media device drivers for media testing.')
|
||||
func = test_media(func)
|
||||
|
||||
app_override = CommandArgument('--app-override', default=None, action='store',
|
||||
help="Override the default binary used to run tests with the path you provide, e.g. " \
|
||||
" --app-override /usr/bin/firefox . " \
|
||||
"If you have run ./mach package beforehand, you can specify 'dist' to " \
|
||||
"run tests against the distribution bundle's binary.");
|
||||
app_override = CommandArgument(
|
||||
'--app-override',
|
||||
default=None,
|
||||
action='store',
|
||||
help="Override the default binary used to run tests with the path you provide, e.g. "
|
||||
" --app-override /usr/bin/firefox . "
|
||||
"If you have run ./mach package beforehand, you can specify 'dist' to "
|
||||
"run tests against the distribution bundle's binary.")
|
||||
func = app_override(func)
|
||||
|
||||
timeout = CommandArgument('--timeout', default=None,
|
||||
help='The per-test timeout time in seconds (default: 60 seconds)');
|
||||
timeout = CommandArgument(
|
||||
'--timeout',
|
||||
default=None,
|
||||
help='The per-test timeout time in seconds (default: 60 seconds)')
|
||||
func = timeout(func)
|
||||
|
||||
return func
|
||||
|
||||
|
||||
def B2GCommand(func):
|
||||
"""Decorator that adds shared command arguments to b2g mochitest commands."""
|
||||
|
||||
busybox = CommandArgument('--busybox', default=None,
|
||||
busybox = CommandArgument(
|
||||
'--busybox',
|
||||
default=None,
|
||||
help='Path to busybox binary to install on device')
|
||||
func = busybox(func)
|
||||
|
||||
@@ -605,7 +755,10 @@ def B2GCommand(func):
|
||||
be installed on the emulator prior to test')
|
||||
func = geckopath(func)
|
||||
|
||||
nowindow = CommandArgument('--no-window', action='store_true', default=False,
|
||||
nowindow = CommandArgument(
|
||||
'--no-window',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Pass --no-window to the emulator')
|
||||
func = nowindow(func)
|
||||
|
||||
@@ -613,22 +766,31 @@ def B2GCommand(func):
|
||||
help='Define size of sdcard: 1MB, 50MB...etc')
|
||||
func = sdcard(func)
|
||||
|
||||
marionette = CommandArgument('--marionette', default=None,
|
||||
marionette = CommandArgument(
|
||||
'--marionette',
|
||||
default=None,
|
||||
help='host:port to use when connecting to Marionette')
|
||||
func = marionette(func)
|
||||
|
||||
chunk_total = CommandArgument('--total-chunks', type=int,
|
||||
chunk_total = CommandArgument(
|
||||
'--total-chunks',
|
||||
type=int,
|
||||
help='Total number of chunks to split tests into.')
|
||||
func = chunk_total(func)
|
||||
|
||||
this_chunk = CommandArgument('--this-chunk', type=int,
|
||||
this_chunk = CommandArgument(
|
||||
'--this-chunk',
|
||||
type=int,
|
||||
help='If running tests by chunks, the number of the chunk to run.')
|
||||
func = this_chunk(func)
|
||||
|
||||
path = CommandArgument('test_paths', default=None, nargs='*',
|
||||
path = CommandArgument(
|
||||
'test_paths',
|
||||
default=None,
|
||||
nargs='*',
|
||||
metavar='TEST',
|
||||
help='Test to run. Can be specified as a single file, a ' \
|
||||
'directory, or omitted. If omitted, the entire test suite is ' \
|
||||
help='Test to run. Can be specified as a single file, a '
|
||||
'directory, or omitted. If omitted, the entire test suite is '
|
||||
'executed.')
|
||||
func = path(func)
|
||||
|
||||
@@ -636,9 +798,11 @@ def B2GCommand(func):
|
||||
help='Repeat the test the given number of times.')
|
||||
func = repeat(func)
|
||||
|
||||
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
|
||||
help='Run tests repeatedly and stops on the first time a test fails. ' \
|
||||
'Default cap is 30 runs, which can be overwritten ' \
|
||||
runUntilFailure = CommandArgument(
|
||||
"--run-until-failure",
|
||||
action='store_true',
|
||||
help='Run tests repeatedly and stops on the first time a test fails. '
|
||||
'Default cap is 30 runs, which can be overwritten '
|
||||
'with the --repeat parameter.')
|
||||
func = runUntilFailure(func)
|
||||
|
||||
@@ -648,34 +812,48 @@ def B2GCommand(func):
|
||||
_st_parser = argparse.ArgumentParser()
|
||||
structured.commandline.add_logging_group(_st_parser)
|
||||
|
||||
|
||||
@CommandProvider
|
||||
class MachCommands(MachCommandBase):
|
||||
@Command('mochitest-plain', category='testing',
|
||||
conditions=[conditions.is_firefox_or_mulet],
|
||||
|
||||
@Command(
|
||||
'mochitest-plain',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox_or_mulet],
|
||||
description='Run a plain mochitest (integration test, plain web page).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
def run_mochitest_plain(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'plain', **kwargs)
|
||||
|
||||
@Command('mochitest-chrome', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'mochitest-chrome',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a chrome mochitest (integration test with some XUL).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
def run_mochitest_chrome(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'chrome', **kwargs)
|
||||
|
||||
@Command('mochitest-browser', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'mochitest-browser',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a mochitest with browser chrome (integration test with a standard browser).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
def run_mochitest_browser(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'browser', **kwargs)
|
||||
|
||||
@Command('mochitest-devtools', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'mochitest-devtools',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a devtools mochitest with browser chrome (integration test with a standard browser with the devtools frame).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
@@ -696,8 +874,11 @@ class MachCommands(MachCommandBase):
|
||||
def run_mochitest_jetpack_addon(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs)
|
||||
|
||||
@Command('mochitest-metro', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'mochitest-metro',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a mochitest with metro browser chrome (tests for Windows touch interface).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
@@ -712,16 +893,22 @@ class MachCommands(MachCommandBase):
|
||||
def run_mochitest_a11y(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'a11y', **kwargs)
|
||||
|
||||
@Command('webapprt-test-chrome', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'webapprt-test-chrome',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
def run_mochitest_webapprt_chrome(self, test_paths, **kwargs):
|
||||
return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs)
|
||||
|
||||
@Command('webapprt-test-content', category='testing',
|
||||
conditions=[conditions.is_firefox],
|
||||
@Command(
|
||||
'webapprt-test-content',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_firefox],
|
||||
description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).',
|
||||
parser=_st_parser)
|
||||
@MochitestCommand
|
||||
@@ -773,8 +960,11 @@ class MachCommands(MachCommandBase):
|
||||
mochitest = self._spawn(MochitestRunner)
|
||||
overall = None
|
||||
for suite, tests in sorted(suites.items()):
|
||||
result = mochitest.run_desktop_test(self._mach_context,
|
||||
test_paths=[test['file_relpath'] for test in tests], suite=suite,
|
||||
result = mochitest.run_desktop_test(
|
||||
self._mach_context,
|
||||
test_paths=[
|
||||
test['file_relpath'] for test in tests],
|
||||
suite=suite,
|
||||
**kwargs)
|
||||
if result:
|
||||
overall = result
|
||||
@@ -794,8 +984,11 @@ class MachCommands(MachCommandBase):
|
||||
|
||||
mochitest = self._spawn(MochitestRunner)
|
||||
|
||||
return mochitest.run_desktop_test(self._mach_context,
|
||||
test_paths=test_paths, suite=flavor, **kwargs)
|
||||
return mochitest.run_desktop_test(
|
||||
self._mach_context,
|
||||
test_paths=test_paths,
|
||||
suite=flavor,
|
||||
**kwargs)
|
||||
|
||||
|
||||
# TODO For now b2g commands will only work with the emulator,
|
||||
@@ -810,27 +1003,39 @@ def is_emulator(cls):
|
||||
|
||||
@CommandProvider
|
||||
class B2GCommands(MachCommandBase):
|
||||
|
||||
"""So far these are only mochitest plain. They are
|
||||
implemented separately because their command lines
|
||||
are completely different.
|
||||
"""
|
||||
|
||||
def __init__(self, context):
|
||||
MachCommandBase.__init__(self, context)
|
||||
|
||||
for attr in ('b2g_home', 'xre_path', 'device_name', 'get_build_var'):
|
||||
setattr(self, attr, getattr(context, attr, None))
|
||||
|
||||
@Command('mochitest-remote', category='testing',
|
||||
@Command(
|
||||
'mochitest-remote',
|
||||
category='testing',
|
||||
description='Run a remote mochitest (integration test for fennec/android).',
|
||||
conditions=[conditions.is_b2g, is_emulator])
|
||||
conditions=[
|
||||
conditions.is_b2g,
|
||||
is_emulator])
|
||||
@B2GCommand
|
||||
def run_mochitest_remote(self, test_paths, **kwargs):
|
||||
if self.get_build_var:
|
||||
host_webapps_dir = os.path.join(self.get_build_var('TARGET_OUT_DATA'),
|
||||
'local', 'webapps')
|
||||
if not os.path.isdir(os.path.join(host_webapps_dir,
|
||||
host_webapps_dir = os.path.join(
|
||||
self.get_build_var('TARGET_OUT_DATA'),
|
||||
'local',
|
||||
'webapps')
|
||||
if not os.path.isdir(
|
||||
os.path.join(
|
||||
host_webapps_dir,
|
||||
'test-container.gaiamobile.org')):
|
||||
print(ENG_BUILD_REQUIRED % ('mochitest-remote', host_webapps_dir))
|
||||
print(
|
||||
ENG_BUILD_REQUIRED %
|
||||
('mochitest-remote', host_webapps_dir))
|
||||
return 1
|
||||
|
||||
from mozbuild.controller.building import BuildDriver
|
||||
@@ -847,8 +1052,11 @@ class B2GCommands(MachCommandBase):
|
||||
driver.install_tests(remove=False)
|
||||
|
||||
mochitest = self._spawn(MochitestRunner)
|
||||
return mochitest.run_b2g_test(b2g_home=self.b2g_home,
|
||||
xre_path=self.xre_path, test_paths=test_paths, **kwargs)
|
||||
return mochitest.run_b2g_test(
|
||||
b2g_home=self.b2g_home,
|
||||
xre_path=self.xre_path,
|
||||
test_paths=test_paths,
|
||||
**kwargs)
|
||||
|
||||
@Command('mochitest-chrome-remote', category='testing',
|
||||
description='Run a remote mochitest-chrome.',
|
||||
@@ -857,12 +1065,16 @@ class B2GCommands(MachCommandBase):
|
||||
def run_mochitest_chrome_remote(self, test_paths, **kwargs):
|
||||
return self.run_mochitest_remote(test_paths, chrome=True, **kwargs)
|
||||
|
||||
@Command('mochitest-b2g-desktop', category='testing',
|
||||
conditions=[conditions.is_b2g_desktop],
|
||||
@Command(
|
||||
'mochitest-b2g-desktop',
|
||||
category='testing',
|
||||
conditions=[
|
||||
conditions.is_b2g_desktop],
|
||||
description='Run a b2g desktop mochitest (same as mochitest-plain but for b2g desktop).')
|
||||
@B2GCommand
|
||||
def run_mochitest_b2g_desktop(self, test_paths, **kwargs):
|
||||
kwargs['profile'] = kwargs.get('profile') or os.environ.get('GAIA_PROFILE')
|
||||
kwargs['profile'] = kwargs.get(
|
||||
'profile') or os.environ.get('GAIA_PROFILE')
|
||||
if not kwargs['profile'] or not os.path.isdir(kwargs['profile']):
|
||||
print(GAIA_PROFILE_NOT_FOUND % 'mochitest-b2g-desktop')
|
||||
return 1
|
||||
@@ -886,16 +1098,23 @@ class B2GCommands(MachCommandBase):
|
||||
|
||||
@CommandProvider
|
||||
class AndroidCommands(MachCommandBase):
|
||||
|
||||
@Command('robocop', category='testing',
|
||||
conditions=[conditions.is_android],
|
||||
description='Run a Robocop test.')
|
||||
@CommandArgument('test_path', default=None, nargs='?',
|
||||
@CommandArgument(
|
||||
'test_path',
|
||||
default=None,
|
||||
nargs='?',
|
||||
metavar='TEST',
|
||||
help='Test to run. Can be specified as a Robocop test name (like "testLoad"), ' \
|
||||
help='Test to run. Can be specified as a Robocop test name (like "testLoad"), '
|
||||
'or omitted. If omitted, the entire test suite is executed.')
|
||||
def run_robocop(self, test_path):
|
||||
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
||||
self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
|
||||
self.mochitest_dir = os.path.join(
|
||||
self.tests_dir,
|
||||
'testing',
|
||||
'mochitest')
|
||||
import imp
|
||||
path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
|
||||
with open(path, 'r') as fh:
|
||||
@@ -904,13 +1123,27 @@ class AndroidCommands(MachCommandBase):
|
||||
import runtestsremote
|
||||
|
||||
args = [
|
||||
'--xre-path=' + os.environ.get('MOZ_HOST_BIN'),
|
||||
'--xre-path=' +
|
||||
os.environ.get('MOZ_HOST_BIN'),
|
||||
'--dm_trans=adb',
|
||||
'--deviceIP=',
|
||||
'--console-level=INFO',
|
||||
'--app=' + self.substs['ANDROID_PACKAGE_NAME'],
|
||||
'--robocop-apk=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop-debug.apk'),
|
||||
'--robocop-ini=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop.ini'),
|
||||
'--app=' +
|
||||
self.substs['ANDROID_PACKAGE_NAME'],
|
||||
'--robocop-apk=' +
|
||||
os.path.join(
|
||||
self.topobjdir,
|
||||
'build',
|
||||
'mobile',
|
||||
'robocop',
|
||||
'robocop-debug.apk'),
|
||||
'--robocop-ini=' +
|
||||
os.path.join(
|
||||
self.topobjdir,
|
||||
'build',
|
||||
'mobile',
|
||||
'robocop',
|
||||
'robocop.ini'),
|
||||
'--log-mach=-',
|
||||
]
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ __all__ = ["MochitestOptions", "B2GOptions"]
|
||||
|
||||
VMWARE_RECORDING_HELPER_BASENAME = "vmwarerecordinghelper"
|
||||
|
||||
|
||||
class MochitestOptions(optparse.OptionParser):
|
||||
|
||||
"""Usage instructions for runtests.py.
|
||||
All arguments are optional.
|
||||
If --chrome is specified, chrome tests will be run instead of web content tests.
|
||||
@@ -35,76 +37,76 @@ class MochitestOptions(optparse.OptionParser):
|
||||
LEVEL_STRING = ", ".join(LOG_LEVELS)
|
||||
mochitest_options = [
|
||||
[["--close-when-done"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "closeWhenDone",
|
||||
"default": False,
|
||||
"help": "close the application when tests are done running",
|
||||
}],
|
||||
[["--appname"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "app",
|
||||
"default": None,
|
||||
"help": "absolute path to application, overriding default",
|
||||
}],
|
||||
[["--utility-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "utilityPath",
|
||||
"default": build_obj.bindir if build_obj is not None else None,
|
||||
"help": "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)",
|
||||
}],
|
||||
[["--certificate-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "certPath",
|
||||
"help": "absolute path to directory containing certificate store to use testing profile",
|
||||
"default": os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs') if build_obj is not None else None,
|
||||
}],
|
||||
[["--autorun"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "autorun",
|
||||
"help": "start running tests when the application starts",
|
||||
"default": False,
|
||||
}],
|
||||
[["--timeout"],
|
||||
{ "type": "int",
|
||||
{"type": "int",
|
||||
"dest": "timeout",
|
||||
"help": "per-test timeout in seconds",
|
||||
"default": None,
|
||||
}],
|
||||
[["--total-chunks"],
|
||||
{ "type": "int",
|
||||
{"type": "int",
|
||||
"dest": "totalChunks",
|
||||
"help": "how many chunks to split the tests up into",
|
||||
"default": None,
|
||||
}],
|
||||
[["--this-chunk"],
|
||||
{ "type": "int",
|
||||
{"type": "int",
|
||||
"dest": "thisChunk",
|
||||
"help": "which chunk to run",
|
||||
"default": None,
|
||||
}],
|
||||
[["--chunk-by-dir"],
|
||||
{ "type": "int",
|
||||
{"type": "int",
|
||||
"dest": "chunkByDir",
|
||||
"help": "group tests together in the same chunk that are in the same top chunkByDir directories",
|
||||
"default": 0,
|
||||
}],
|
||||
[["--run-by-dir"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "runByDir",
|
||||
"help": "Run each directory in a single browser instance with a fresh profile",
|
||||
"default": False,
|
||||
}],
|
||||
[["--shuffle"],
|
||||
{ "dest": "shuffle",
|
||||
{"dest": "shuffle",
|
||||
"action": "store_true",
|
||||
"help": "randomize test order",
|
||||
"default": False,
|
||||
}],
|
||||
[["--console-level"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "choice",
|
||||
"dest": "consoleLevel",
|
||||
"choices": LOG_LEVELS,
|
||||
@@ -114,89 +116,89 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": None,
|
||||
}],
|
||||
[["--chrome"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "chrome",
|
||||
"help": "run chrome Mochitests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--ipcplugins"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "ipcplugins",
|
||||
"help": "run ipcplugins Mochitests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--test-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "testPath",
|
||||
"help": "start in the given directory's tests",
|
||||
"default": "",
|
||||
}],
|
||||
[["--bisect-chunk"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "bisectChunk",
|
||||
"help": "Specify the failing test name to find the previous tests that may be causing the failure.",
|
||||
"default": None,
|
||||
}],
|
||||
[["--start-at"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "startAt",
|
||||
"help": "skip over tests until reaching the given test",
|
||||
"default": "",
|
||||
}],
|
||||
[["--end-at"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "endAt",
|
||||
"help": "don't run any tests after the given one",
|
||||
"default": "",
|
||||
}],
|
||||
[["--browser-chrome"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "browserChrome",
|
||||
"help": "run browser chrome Mochitests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--subsuite"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"dest": "subsuite",
|
||||
"help": "subsuite of tests to run",
|
||||
"default": None,
|
||||
}],
|
||||
[["--jetpack-package"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "jetpackPackage",
|
||||
"help": "run jetpack package tests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--jetpack-addon"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "jetpackAddon",
|
||||
"help": "run jetpack addon tests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--webapprt-content"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "webapprtContent",
|
||||
"help": "run WebappRT content tests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--webapprt-chrome"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "webapprtChrome",
|
||||
"help": "run WebappRT chrome tests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--a11y"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "a11y",
|
||||
"help": "run accessibility Mochitests",
|
||||
"default": False,
|
||||
}],
|
||||
[["--setenv"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"type": "string",
|
||||
"dest": "environment",
|
||||
"metavar": "NAME=VALUE",
|
||||
@@ -205,7 +207,7 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": [],
|
||||
}],
|
||||
[["--exclude-extension"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"type": "string",
|
||||
"dest": "extensionsToExclude",
|
||||
"help": "excludes the given extension from being installed "
|
||||
@@ -213,7 +215,7 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": [],
|
||||
}],
|
||||
[["--browser-arg"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"type": "string",
|
||||
"dest": "browserArgs",
|
||||
"metavar": "ARG",
|
||||
@@ -221,7 +223,7 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": [],
|
||||
}],
|
||||
[["--leak-threshold"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "int",
|
||||
"dest": "defaultLeakThreshold",
|
||||
"metavar": "THRESHOLD",
|
||||
@@ -232,20 +234,20 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": 0,
|
||||
}],
|
||||
[["--fatal-assertions"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "fatalAssertions",
|
||||
"help": "abort testing whenever an assertion is hit "
|
||||
"(requires a debug build to be effective)",
|
||||
"default": False,
|
||||
}],
|
||||
[["--extra-profile-file"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"dest": "extraProfileFiles",
|
||||
"help": "copy specified files/dirs to testing profile",
|
||||
"default": [],
|
||||
}],
|
||||
[["--install-extension"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"dest": "extensionsToInstall",
|
||||
"help": "install the specified extension in the testing profile."
|
||||
"The extension file's name should be <id>.xpi where <id> is"
|
||||
@@ -254,7 +256,7 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": [],
|
||||
}],
|
||||
[["--profile-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "profilePath",
|
||||
"help": "Directory where the profile will be stored."
|
||||
@@ -262,21 +264,21 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": None,
|
||||
}],
|
||||
[["--testing-modules-dir"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "testingModulesDir",
|
||||
"help": "Directory where testing-only JS modules are located.",
|
||||
"default": None,
|
||||
}],
|
||||
[["--use-vmware-recording"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "vmwareRecording",
|
||||
"help": "enables recording while the application is running "
|
||||
"inside a VMware Workstation 7.0 or later VM",
|
||||
"default": False,
|
||||
}],
|
||||
[["--repeat"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "int",
|
||||
"dest": "repeat",
|
||||
"metavar": "REPEAT",
|
||||
@@ -284,68 +286,68 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"default": 0,
|
||||
}],
|
||||
[["--run-until-failure"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "runUntilFailure",
|
||||
"help": "Run tests repeatedly and stops on the first time a test fails. "
|
||||
"Default cap is 30 runs, which can be overwritten with the --repeat parameter.",
|
||||
"default": False,
|
||||
}],
|
||||
[["--run-only-tests"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "runOnlyTests",
|
||||
"help": "JSON list of tests that we only want to run. [DEPRECATED- please use --test-manifest]",
|
||||
"default": None,
|
||||
}],
|
||||
[["--test-manifest"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "testManifest",
|
||||
"help": "JSON list of tests to specify 'runtests'. Old format for mobile specific tests",
|
||||
"default": None,
|
||||
}],
|
||||
[["--manifest"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "manifestFile",
|
||||
"help": ".ini format of tests to run.",
|
||||
"default": None,
|
||||
}],
|
||||
[["--testrun-manifest-file"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "testRunManifestFile",
|
||||
"help": "Overrides the default filename of the tests.json manifest file that is created from the manifest and used by the test runners to run the tests. Only useful when running multiple test runs simulatenously on the same machine.",
|
||||
"default": 'tests.json',
|
||||
}],
|
||||
[["--failure-file"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "failureFile",
|
||||
"help": "Filename of the output file where we can store a .json list of failures to be run in the future with --run-only-tests.",
|
||||
"default": None,
|
||||
}],
|
||||
[["--run-slower"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "runSlower",
|
||||
"help": "Delay execution between test files.",
|
||||
"default": False,
|
||||
}],
|
||||
[["--metro-immersive"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "immersiveMode",
|
||||
"help": "launches tests in immersive browser",
|
||||
"default": False,
|
||||
}],
|
||||
[["--httpd-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "httpdPath",
|
||||
"default": None,
|
||||
"help": "path to the httpd.js file",
|
||||
}],
|
||||
[["--setpref"],
|
||||
{ "action": "append",
|
||||
{"action": "append",
|
||||
"type": "string",
|
||||
"default": [],
|
||||
"dest": "extraPrefs",
|
||||
@@ -353,63 +355,63 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"help": "defines an extra user preference",
|
||||
}],
|
||||
[["--jsdebugger"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "jsdebugger",
|
||||
"help": "open the browser debugger",
|
||||
}],
|
||||
[["--debug-on-failure"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "debugOnFailure",
|
||||
"help": "breaks execution and enters the JS debugger on a test failure. Should be used together with --jsdebugger."
|
||||
}],
|
||||
[["--e10s"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "e10s",
|
||||
"help": "Run tests with electrolysis preferences and test filtering enabled.",
|
||||
}],
|
||||
[["--strict-content-sandbox"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "strictContentSandbox",
|
||||
"help": "Run tests with a more strict content sandbox (Windows only).",
|
||||
}],
|
||||
[["--nested_oop"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "nested_oop",
|
||||
"help": "Run tests with nested_oop preferences and test filtering enabled.",
|
||||
}],
|
||||
[["--dmd-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"default": None,
|
||||
"dest": "dmdPath",
|
||||
"help": "Specifies the path to the directory containing the shared library for DMD.",
|
||||
}],
|
||||
[["--dump-output-directory"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"default": None,
|
||||
"dest": "dumpOutputDirectory",
|
||||
"help": "Specifies the directory in which to place dumped memory reports.",
|
||||
}],
|
||||
[["--dump-about-memory-after-test"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "dumpAboutMemoryAfterTest",
|
||||
"help": "Produce an about:memory dump after each test in the directory specified "
|
||||
"by --dump-output-directory."
|
||||
}],
|
||||
[["--dump-dmd-after-test"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "dumpDMDAfterTest",
|
||||
"help": "Produce a DMD dump after each test in the directory specified "
|
||||
"by --dump-output-directory."
|
||||
}],
|
||||
[["--slowscript"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "slowscript",
|
||||
"help": "Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; "
|
||||
@@ -417,62 +419,62 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"may occur in Ion/Odin JIT code."
|
||||
}],
|
||||
[["--screenshot-on-fail"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "screenshotOnFail",
|
||||
"help": "Take screenshots on all test failures. Set $MOZ_UPLOAD_DIR to a directory for storing the screenshots."
|
||||
}],
|
||||
[["--quiet"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "quiet",
|
||||
"help": "Do not print test log lines unless a failure occurs."
|
||||
}],
|
||||
[["--pidfile"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "pidFile",
|
||||
"help": "name of the pidfile to generate",
|
||||
"default": "",
|
||||
}],
|
||||
[["--use-test-media-devices"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"default": False,
|
||||
"dest": "useTestMediaDevices",
|
||||
"help": "Use test media device drivers for media testing.",
|
||||
}],
|
||||
[["--gmp-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"default": None,
|
||||
"dest": "gmp_path",
|
||||
"help": "Path to fake GMP plugin. Will be deduced from the binary if not passed.",
|
||||
}],
|
||||
[["--xre-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "xrePath",
|
||||
"default": None, # individual scripts will set a sane default
|
||||
"help": "absolute path to directory containing XRE (probably xulrunner)",
|
||||
}],
|
||||
[["--symbols-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "symbolsPath",
|
||||
"default": None,
|
||||
"help": "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols",
|
||||
}],
|
||||
[["--debugger"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"dest": "debugger",
|
||||
"help": "use the given debugger to launch the application",
|
||||
}],
|
||||
[["--debugger-args"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"dest": "debuggerArgs",
|
||||
"help": "pass the given args to the debugger _before_ the application on the command line",
|
||||
}],
|
||||
[["--debugger-interactive"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "debuggerInteractive",
|
||||
"help": "prevents the test harness from redirecting stdout and stderr for interactive debuggers",
|
||||
}],
|
||||
@@ -493,17 +495,21 @@ class MochitestOptions(optparse.OptionParser):
|
||||
""" verify correct options and cleanup paths """
|
||||
|
||||
mozinfo.update({"e10s": options.e10s}) # for test manifest parsing.
|
||||
mozinfo.update({"strictContentSandbox": options.strictContentSandbox}) # for test manifest parsing.
|
||||
mozinfo.update({"nested_oop": options.nested_oop}) # for test manifest parsing.
|
||||
# for test manifest parsing.
|
||||
mozinfo.update({"strictContentSandbox": options.strictContentSandbox})
|
||||
# for test manifest parsing.
|
||||
mozinfo.update({"nested_oop": options.nested_oop})
|
||||
|
||||
if options.app is None:
|
||||
if build_obj is not None:
|
||||
options.app = build_obj.get_binary_path()
|
||||
else:
|
||||
self.error("could not find the application path, --appname must be specified")
|
||||
self.error(
|
||||
"could not find the application path, --appname must be specified")
|
||||
|
||||
if options.totalChunks is not None and options.thisChunk is None:
|
||||
self.error("thisChunk must be specified when totalChunks is specified")
|
||||
self.error(
|
||||
"thisChunk must be specified when totalChunks is specified")
|
||||
|
||||
if options.totalChunks:
|
||||
if not 1 <= options.thisChunk <= options.totalChunks:
|
||||
@@ -515,12 +521,16 @@ class MochitestOptions(optparse.OptionParser):
|
||||
if options.app != self.defaults['app']:
|
||||
options.xrePath = os.path.dirname(options.app)
|
||||
if mozinfo.isMac:
|
||||
options.xrePath = os.path.join(os.path.dirname(options.xrePath), "Resources")
|
||||
options.xrePath = os.path.join(
|
||||
os.path.dirname(
|
||||
options.xrePath),
|
||||
"Resources")
|
||||
elif build_obj is not None:
|
||||
# otherwise default to dist/bin
|
||||
options.xrePath = build_obj.bindir
|
||||
else:
|
||||
self.error("could not find xre directory, --xre-path must be specified")
|
||||
self.error(
|
||||
"could not find xre directory, --xre-path must be specified")
|
||||
|
||||
# allow relative paths
|
||||
options.xrePath = mochitest.getFullPath(options.xrePath)
|
||||
@@ -543,7 +553,9 @@ class MochitestOptions(optparse.OptionParser):
|
||||
if options.certPath:
|
||||
options.certPath = mochitest.getFullPath(options.certPath)
|
||||
|
||||
if options.symbolsPath and len(urlparse(options.symbolsPath).scheme) < 2:
|
||||
if options.symbolsPath and len(
|
||||
urlparse(
|
||||
options.symbolsPath).scheme) < 2:
|
||||
options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
|
||||
|
||||
# Set server information on the options object
|
||||
@@ -551,14 +563,16 @@ class MochitestOptions(optparse.OptionParser):
|
||||
options.httpPort = DEFAULT_PORTS['http']
|
||||
options.sslPort = DEFAULT_PORTS['https']
|
||||
# options.webSocketPort = DEFAULT_PORTS['ws']
|
||||
options.webSocketPort = str(9988) # <- http://hg.mozilla.org/mozilla-central/file/b871dfb2186f/build/automation.py.in#l30
|
||||
# <- http://hg.mozilla.org/mozilla-central/file/b871dfb2186f/build/automation.py.in#l30
|
||||
options.webSocketPort = str(9988)
|
||||
# The default websocket port is incorrect in mozprofile; it is
|
||||
# set to the SSL proxy setting. See:
|
||||
# see https://bugzilla.mozilla.org/show_bug.cgi?id=916517
|
||||
|
||||
if options.vmwareRecording:
|
||||
if not mozinfo.isWin:
|
||||
self.error("use-vmware-recording is only supported on Windows.")
|
||||
self.error(
|
||||
"use-vmware-recording is only supported on Windows.")
|
||||
mochitest.vmwareHelperPath = os.path.join(
|
||||
options.utilityPath, VMWARE_RECORDING_HELPER_BASENAME + ".dll")
|
||||
if not os.path.exists(mochitest.vmwareHelperPath):
|
||||
@@ -566,20 +580,29 @@ class MochitestOptions(optparse.OptionParser):
|
||||
mochitest.vmwareHelperPath)
|
||||
|
||||
if options.testManifest and options.runOnlyTests:
|
||||
self.error("Please use --test-manifest only and not --run-only-tests")
|
||||
self.error(
|
||||
"Please use --test-manifest only and not --run-only-tests")
|
||||
|
||||
if options.runOnlyTests:
|
||||
if not os.path.exists(os.path.abspath(os.path.join(here, options.runOnlyTests))):
|
||||
self.error("unable to find --run-only-tests file '%s'" % options.runOnlyTests)
|
||||
if not os.path.exists(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
here,
|
||||
options.runOnlyTests))):
|
||||
self.error(
|
||||
"unable to find --run-only-tests file '%s'" %
|
||||
options.runOnlyTests)
|
||||
options.runOnly = True
|
||||
options.testManifest = options.runOnlyTests
|
||||
options.runOnlyTests = None
|
||||
|
||||
if options.manifestFile and options.testManifest:
|
||||
self.error("Unable to support both --manifest and --test-manifest/--run-only-tests at the same time")
|
||||
self.error(
|
||||
"Unable to support both --manifest and --test-manifest/--run-only-tests at the same time")
|
||||
|
||||
if options.webapprtContent and options.webapprtChrome:
|
||||
self.error("Only one of --webapprt-content and --webapprt-chrome may be given.")
|
||||
self.error(
|
||||
"Only one of --webapprt-content and --webapprt-chrome may be given.")
|
||||
|
||||
if options.jsdebugger:
|
||||
options.extraPrefs += [
|
||||
@@ -591,7 +614,8 @@ class MochitestOptions(optparse.OptionParser):
|
||||
options.autorun = False
|
||||
|
||||
if options.debugOnFailure and not options.jsdebugger:
|
||||
self.error("--debug-on-failure should be used together with --jsdebugger.")
|
||||
self.error(
|
||||
"--debug-on-failure should be used together with --jsdebugger.")
|
||||
|
||||
# Try to guess the testing modules directory.
|
||||
# This somewhat grotesque hack allows the buildbot machines to find the
|
||||
@@ -608,16 +632,20 @@ class MochitestOptions(optparse.OptionParser):
|
||||
# Even if buildbot is updated, we still want this, as the path we pass in
|
||||
# to the app must be absolute and have proper slashes.
|
||||
if options.testingModulesDir is not None:
|
||||
options.testingModulesDir = os.path.normpath(options.testingModulesDir)
|
||||
options.testingModulesDir = os.path.normpath(
|
||||
options.testingModulesDir)
|
||||
|
||||
if not os.path.isabs(options.testingModulesDir):
|
||||
options.testingModulesDir = os.path.abspath(options.testingModulesDir)
|
||||
options.testingModulesDir = os.path.abspath(
|
||||
options.testingModulesDir)
|
||||
|
||||
if not os.path.isdir(options.testingModulesDir):
|
||||
self.error('--testing-modules-dir not a directory: %s' %
|
||||
options.testingModulesDir)
|
||||
|
||||
options.testingModulesDir = options.testingModulesDir.replace('\\', '/')
|
||||
options.testingModulesDir = options.testingModulesDir.replace(
|
||||
'\\',
|
||||
'/')
|
||||
if options.testingModulesDir[-1] != '/':
|
||||
options.testingModulesDir += '/'
|
||||
|
||||
@@ -644,10 +672,12 @@ class MochitestOptions(optparse.OptionParser):
|
||||
|
||||
if options.useTestMediaDevices:
|
||||
if not mozinfo.isLinux:
|
||||
self.error('--use-test-media-devices is only supported on Linux currently')
|
||||
self.error(
|
||||
'--use-test-media-devices is only supported on Linux currently')
|
||||
for f in ['/usr/bin/gst-launch-0.10', '/usr/bin/pactl']:
|
||||
if not os.path.isfile(f):
|
||||
self.error('Missing binary %s required for --use-test-media-devices')
|
||||
self.error(
|
||||
'Missing binary %s required for --use-test-media-devices')
|
||||
|
||||
if options.nested_oop:
|
||||
if not options.e10s:
|
||||
@@ -656,13 +686,16 @@ class MochitestOptions(optparse.OptionParser):
|
||||
options.leakThresholds = {
|
||||
"default": options.defaultLeakThreshold,
|
||||
"tab": 25000, # See dependencies of bug 1051230.
|
||||
"geckomediaplugin": 20000, # GMP rarely gets a log, but when it does, it leaks a little.
|
||||
# GMP rarely gets a log, but when it does, it leaks a little.
|
||||
"geckomediaplugin": 20000,
|
||||
}
|
||||
|
||||
# Bug 1065098 - The geckomediaplugin process fails to produce a leak log for some reason.
|
||||
# Bug 1065098 - The geckomediaplugin process fails to produce a leak
|
||||
# log for some reason.
|
||||
options.ignoreMissingLeaks = ["geckomediaplugin"]
|
||||
|
||||
# Bug 1091917 - We exit early in tab processes on Windows, so we don't get leak logs yet.
|
||||
# Bug 1091917 - We exit early in tab processes on Windows, so we don't
|
||||
# get leak logs yet.
|
||||
if mozinfo.isWin:
|
||||
options.ignoreMissingLeaks.append("tab")
|
||||
|
||||
@@ -676,104 +709,104 @@ class MochitestOptions(optparse.OptionParser):
|
||||
class B2GOptions(MochitestOptions):
|
||||
b2g_options = [
|
||||
[["--b2gpath"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "b2gPath",
|
||||
"help": "path to B2G repo or qemu dir",
|
||||
"default": None,
|
||||
}],
|
||||
[["--desktop"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "desktop",
|
||||
"help": "Run the tests on a B2G desktop build",
|
||||
"default": False,
|
||||
}],
|
||||
[["--marionette"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "marionette",
|
||||
"help": "host:port to use when connecting to Marionette",
|
||||
"default": None,
|
||||
}],
|
||||
[["--emulator"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "emulator",
|
||||
"help": "Architecture of emulator to use: x86 or arm",
|
||||
"default": None,
|
||||
}],
|
||||
[["--wifi"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "wifi",
|
||||
"help": "Devine wifi configuration for on device mochitest",
|
||||
"default": False,
|
||||
}],
|
||||
[["--sdcard"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "sdcard",
|
||||
"help": "Define size of sdcard: 1MB, 50MB...etc",
|
||||
"default": "10MB",
|
||||
}],
|
||||
[["--no-window"],
|
||||
{ "action": "store_true",
|
||||
{"action": "store_true",
|
||||
"dest": "noWindow",
|
||||
"help": "Pass --no-window to the emulator",
|
||||
"default": False,
|
||||
}],
|
||||
[["--adbpath"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "adbPath",
|
||||
"help": "path to adb",
|
||||
"default": "adb",
|
||||
}],
|
||||
[["--deviceIP"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "deviceIP",
|
||||
"help": "ip address of remote device to test",
|
||||
"default": None,
|
||||
}],
|
||||
[["--devicePort"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "devicePort",
|
||||
"help": "port of remote device to test",
|
||||
"default": 20701,
|
||||
}],
|
||||
[["--remote-logfile"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "remoteLogFile",
|
||||
"help": "Name of log file on the device relative to the device root. \
|
||||
PLEASE ONLY USE A FILENAME.",
|
||||
"default" : None,
|
||||
"default": None,
|
||||
}],
|
||||
[["--remote-webserver"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "remoteWebServer",
|
||||
"help": "ip address where the remote web server is hosted at",
|
||||
"default": None,
|
||||
}],
|
||||
[["--http-port"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "httpPort",
|
||||
"help": "ip address where the remote web server is hosted at",
|
||||
"default": None,
|
||||
}],
|
||||
[["--ssl-port"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "sslPort",
|
||||
"help": "ip address where the remote web server is hosted at",
|
||||
"default": None,
|
||||
}],
|
||||
[["--gecko-path"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "geckoPath",
|
||||
"help": "the path to a gecko distribution that should \
|
||||
@@ -781,7 +814,7 @@ class B2GOptions(MochitestOptions):
|
||||
"default": None,
|
||||
}],
|
||||
[["--profile"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "profile",
|
||||
"help": "for desktop testing, the path to the \
|
||||
@@ -789,21 +822,21 @@ class B2GOptions(MochitestOptions):
|
||||
"default": None,
|
||||
}],
|
||||
[["--logdir"],
|
||||
{ "action": "store",
|
||||
{"action": "store",
|
||||
"type": "string",
|
||||
"dest": "logdir",
|
||||
"help": "directory to store log files",
|
||||
"default": None,
|
||||
}],
|
||||
[['--busybox'],
|
||||
{ "action": 'store',
|
||||
{"action": 'store',
|
||||
"type": 'string',
|
||||
"dest": 'busybox',
|
||||
"help": "Path to busybox binary to install on device",
|
||||
"default": None,
|
||||
}],
|
||||
[['--profile-data-dir'],
|
||||
{ "action": 'store',
|
||||
{"action": 'store',
|
||||
"type": 'string',
|
||||
"dest": 'profile_data_dir',
|
||||
"help": "Path to a directory containing preference and other \
|
||||
@@ -831,15 +864,17 @@ class B2GOptions(MochitestOptions):
|
||||
self.set_defaults(**defaults)
|
||||
|
||||
def verifyRemoteOptions(self, options):
|
||||
if options.remoteWebServer == None:
|
||||
if options.remoteWebServer is None:
|
||||
if os.name != "nt":
|
||||
options.remoteWebServer = moznetwork.get_ip()
|
||||
else:
|
||||
self.error("You must specify a --remote-webserver=<ip address>")
|
||||
self.error(
|
||||
"You must specify a --remote-webserver=<ip address>")
|
||||
options.webServer = options.remoteWebServer
|
||||
|
||||
if options.geckoPath and not options.emulator:
|
||||
self.error("You must specify --emulator if you specify --gecko-path")
|
||||
self.error(
|
||||
"You must specify --emulator if you specify --gecko-path")
|
||||
|
||||
if options.logdir and not options.emulator:
|
||||
self.error("You must specify --emulator if you specify --logdir")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ from mozprofile import Profile, Preferences
|
||||
from mozlog import structured
|
||||
import mozinfo
|
||||
|
||||
|
||||
class B2GMochitest(MochitestUtilsMixin):
|
||||
marionette = None
|
||||
|
||||
@@ -43,10 +44,14 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
self.remote_chrome_test_dir = None
|
||||
|
||||
if profile_data_dir:
|
||||
self.preferences = [os.path.join(profile_data_dir, f)
|
||||
for f in os.listdir(profile_data_dir) if f.startswith('pref')]
|
||||
self.webapps = [os.path.join(profile_data_dir, f)
|
||||
for f in os.listdir(profile_data_dir) if f.startswith('webapp')]
|
||||
self.preferences = [
|
||||
os.path.join(
|
||||
profile_data_dir,
|
||||
f) for f in os.listdir(profile_data_dir) if f.startswith('pref')]
|
||||
self.webapps = [
|
||||
os.path.join(
|
||||
profile_data_dir,
|
||||
f) for f in os.listdir(profile_data_dir) if f.startswith('webapp')]
|
||||
|
||||
# mozinfo is populated by the parent class
|
||||
if mozinfo.info['debug']:
|
||||
@@ -68,7 +73,12 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
|
||||
def buildTestPath(self, options, testsToFilter=None):
|
||||
if options.manifestFile != 'tests.json':
|
||||
super(B2GMochitest, self).buildTestPath(options, testsToFilter, disabled=False)
|
||||
super(
|
||||
B2GMochitest,
|
||||
self).buildTestPath(
|
||||
options,
|
||||
testsToFilter,
|
||||
disabled=False)
|
||||
return self.buildTestURL(options)
|
||||
|
||||
def build_profile(self, options):
|
||||
@@ -85,8 +95,11 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
prefs[thispref[0]] = thispref[1]
|
||||
|
||||
# interpolate the preferences
|
||||
interpolation = { "server": "%s:%s" % (options.webServer, options.httpPort),
|
||||
"OOP": "true" if self.out_of_process else "false" }
|
||||
interpolation = {
|
||||
"server": "%s:%s" %
|
||||
(options.webServer,
|
||||
options.httpPort),
|
||||
"OOP": "true" if self.out_of_process else "false"}
|
||||
prefs = json.loads(json.dumps(prefs) % interpolation)
|
||||
for pref in prefs:
|
||||
prefs[pref] = Preferences.cast(prefs[pref])
|
||||
@@ -138,7 +151,8 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
if message['action'] == 'test_start':
|
||||
self.runner.last_test = message['test']
|
||||
|
||||
# The logging will be handled by on_output, so we set the stream to None
|
||||
# The logging will be handled by on_output, so we set the stream to
|
||||
# None
|
||||
process_args = {'processOutputLine': on_output,
|
||||
'stream': None}
|
||||
self.marionette_args['process_args'] = process_args
|
||||
@@ -150,23 +164,29 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
|
||||
self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
|
||||
'log', 'mochitest.log')
|
||||
if not self.app_ctx.dm.dirExists(posixpath.dirname(self.remote_log)):
|
||||
if not self.app_ctx.dm.dirExists(
|
||||
posixpath.dirname(
|
||||
self.remote_log)):
|
||||
self.app_ctx.dm.mkDirs(self.remote_log)
|
||||
|
||||
if options.chrome:
|
||||
# Update chrome manifest file in profile with correct path.
|
||||
self.writeChromeManifest(options)
|
||||
|
||||
self.leak_report_file = posixpath.join(self.app_ctx.remote_test_root,
|
||||
'log', 'runtests_leaks.log')
|
||||
self.leak_report_file = posixpath.join(
|
||||
self.app_ctx.remote_test_root,
|
||||
'log',
|
||||
'runtests_leaks.log')
|
||||
|
||||
# We don't want to copy the host env onto the device, so pass in an
|
||||
# empty env.
|
||||
self.browserEnv = self.buildBrowserEnv(options, env={})
|
||||
|
||||
# B2G emulator debug tests still make external connections, so don't
|
||||
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug 1039019).
|
||||
if mozinfo.info['debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
|
||||
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug
|
||||
# 1039019).
|
||||
if mozinfo.info[
|
||||
'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
|
||||
del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
|
||||
self.runner.env.update(self.browserEnv)
|
||||
|
||||
@@ -176,7 +196,6 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
self.test_script_args.append(options.wifi)
|
||||
self.test_script_args.append(options.chrome)
|
||||
|
||||
|
||||
self.runner.start(outputTimeout=timeout)
|
||||
|
||||
self.marionette.wait_for_port()
|
||||
@@ -185,7 +204,8 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
|
||||
# Disable offline status management (bug 777145), otherwise the network
|
||||
# will be 'offline' when the mochitests start. Presumably, the network
|
||||
# won't be offline on a real device, so we only do this for emulators.
|
||||
# won't be offline on a real device, so we only do this for
|
||||
# emulators.
|
||||
self.marionette.execute_script("""
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.io.manageOfflineStatus = false;
|
||||
@@ -198,15 +218,19 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
local = super(B2GMochitest, self).getChromeTestDir(options)
|
||||
local = os.path.join(local, "chrome")
|
||||
remote = self.remote_chrome_test_dir
|
||||
self.log.info("pushing %s to %s on device..." % (local, remote))
|
||||
self.log.info(
|
||||
"pushing %s to %s on device..." %
|
||||
(local, remote))
|
||||
self.app_ctx.dm.pushDir(local, remote)
|
||||
|
||||
if os.path.isfile(self.test_script):
|
||||
with open(self.test_script, 'r') as script:
|
||||
self.marionette.execute_script(script.read(),
|
||||
self.marionette.execute_script(
|
||||
script.read(),
|
||||
script_args=self.test_script_args)
|
||||
else:
|
||||
self.marionette.execute_script(self.test_script,
|
||||
self.marionette.execute_script(
|
||||
self.test_script,
|
||||
script_args=self.test_script_args)
|
||||
status = self.runner.wait()
|
||||
|
||||
@@ -215,16 +239,19 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
status = 124
|
||||
|
||||
local_leak_file = tempfile.NamedTemporaryFile()
|
||||
self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name)
|
||||
self.app_ctx.dm.getFile(
|
||||
self.leak_report_file,
|
||||
local_leak_file.name)
|
||||
self.app_ctx.dm.removeFile(self.leak_report_file)
|
||||
|
||||
processLeakLog(local_leak_file.name, options)
|
||||
except KeyboardInterrupt:
|
||||
self.log.info("runtests.py | Received keyboard interrupt.\n");
|
||||
self.log.info("runtests.py | Received keyboard interrupt.\n")
|
||||
status = -1
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.log.error("Automation Error: Received unexpected exception while running application\n")
|
||||
self.log.error(
|
||||
"Automation Error: Received unexpected exception while running application\n")
|
||||
if hasattr(self, 'runner'):
|
||||
self.runner.check_for_crashes()
|
||||
status = 1
|
||||
@@ -249,7 +276,9 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
# is defined; the correct directory will be returned later, over-
|
||||
# writing the dummy.
|
||||
if hasattr(self, 'app_ctx'):
|
||||
self.remote_chrome_test_dir = posixpath.join(self.app_ctx.remote_test_root, 'chrome');
|
||||
self.remote_chrome_test_dir = posixpath.join(
|
||||
self.app_ctx.remote_test_root,
|
||||
'chrome')
|
||||
return self.remote_chrome_test_dir
|
||||
return 'dummy-chrome-test-dir'
|
||||
|
||||
@@ -257,9 +286,20 @@ class B2GMochitest(MochitestUtilsMixin):
|
||||
class B2GDeviceMochitest(B2GMochitest, Mochitest):
|
||||
remote_log = None
|
||||
|
||||
def __init__(self, marionette_args, logger_options, profile_data_dir,
|
||||
local_binary_dir, remote_test_root=None, remote_log_file=None):
|
||||
B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=True, profile_data_dir=profile_data_dir)
|
||||
def __init__(
|
||||
self,
|
||||
marionette_args,
|
||||
logger_options,
|
||||
profile_data_dir,
|
||||
local_binary_dir,
|
||||
remote_test_root=None,
|
||||
remote_log_file=None):
|
||||
B2GMochitest.__init__(
|
||||
self,
|
||||
marionette_args,
|
||||
logger_options,
|
||||
out_of_process=True,
|
||||
profile_data_dir=profile_data_dir)
|
||||
self.local_log = None
|
||||
self.local_binary_dir = local_binary_dir
|
||||
|
||||
@@ -314,7 +354,12 @@ class B2GDeviceMochitest(B2GMochitest, Mochitest):
|
||||
class B2GDesktopMochitest(B2GMochitest, Mochitest):
|
||||
|
||||
def __init__(self, marionette_args, logger_options, profile_data_dir):
|
||||
B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=False, profile_data_dir=profile_data_dir)
|
||||
B2GMochitest.__init__(
|
||||
self,
|
||||
marionette_args,
|
||||
logger_options,
|
||||
out_of_process=False,
|
||||
profile_data_dir=profile_data_dir)
|
||||
Mochitest.__init__(self, logger_options)
|
||||
self.certdbNew = True
|
||||
|
||||
@@ -347,7 +392,10 @@ class B2GDesktopMochitest(B2GMochitest, Mochitest):
|
||||
self.setup_common_options(options)
|
||||
|
||||
# Copy the extensions to the B2G bundles dir.
|
||||
extensionDir = os.path.join(options.profilePath, 'extensions', 'staged')
|
||||
extensionDir = os.path.join(
|
||||
options.profilePath,
|
||||
'extensions',
|
||||
'staged')
|
||||
bundlesDir = os.path.join(os.path.dirname(options.app),
|
||||
'distribution', 'bundles')
|
||||
|
||||
@@ -378,15 +426,19 @@ def run_remote_mochitests(parser, options):
|
||||
marionette_args['port'] = int(port)
|
||||
|
||||
options = parser.verifyRemoteOptions(options)
|
||||
if (options == None):
|
||||
if (options is None):
|
||||
print "ERROR: Invalid options specified, use --help for a list of valid options"
|
||||
sys.exit(1)
|
||||
|
||||
mochitest = B2GDeviceMochitest(marionette_args, options, options.profile_data_dir,
|
||||
options.xrePath, remote_log_file=options.remoteLogFile)
|
||||
mochitest = B2GDeviceMochitest(
|
||||
marionette_args,
|
||||
options,
|
||||
options.profile_data_dir,
|
||||
options.xrePath,
|
||||
remote_log_file=options.remoteLogFile)
|
||||
|
||||
options = parser.verifyOptions(options, mochitest)
|
||||
if (options == None):
|
||||
if (options is None):
|
||||
sys.exit(1)
|
||||
|
||||
retVal = 1
|
||||
@@ -407,6 +459,7 @@ def run_remote_mochitests(parser, options):
|
||||
|
||||
sys.exit(retVal)
|
||||
|
||||
|
||||
def run_desktop_mochitests(parser, options):
|
||||
# create our Marionette instance
|
||||
marionette_args = {}
|
||||
@@ -420,9 +473,12 @@ def run_desktop_mochitests(parser, options):
|
||||
if os.path.isfile("%s-bin" % options.app):
|
||||
options.app = "%s-bin" % options.app
|
||||
|
||||
mochitest = B2GDesktopMochitest(marionette_args, options, options.profile_data_dir)
|
||||
mochitest = B2GDesktopMochitest(
|
||||
marionette_args,
|
||||
options,
|
||||
options.profile_data_dir)
|
||||
options = MochitestOptions.verifyOptions(parser, options, mochitest)
|
||||
if options == None:
|
||||
if options is None:
|
||||
sys.exit(1)
|
||||
|
||||
if options.desktop and not options.profile:
|
||||
@@ -435,6 +491,7 @@ def run_desktop_mochitests(parser, options):
|
||||
|
||||
sys.exit(retVal)
|
||||
|
||||
|
||||
def main():
|
||||
parser = B2GOptions()
|
||||
structured.commandline.add_logging_group(parser)
|
||||
|
||||
@@ -13,7 +13,10 @@ import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.realpath(os.path.dirname(__file__))))
|
||||
sys.path.insert(
|
||||
0, os.path.abspath(
|
||||
os.path.realpath(
|
||||
os.path.dirname(__file__))))
|
||||
|
||||
from automation import Automation
|
||||
from remoteautomation import RemoteAutomation, fennecLogcatFilters
|
||||
@@ -29,6 +32,7 @@ import moznetwork
|
||||
|
||||
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
|
||||
|
||||
|
||||
class RemoteOptions(MochitestOptions):
|
||||
|
||||
def __init__(self, automation, **kwargs):
|
||||
@@ -36,84 +40,117 @@ class RemoteOptions(MochitestOptions):
|
||||
self._automation = automation or Automation()
|
||||
MochitestOptions.__init__(self)
|
||||
|
||||
self.add_option("--remote-app-path", action="store",
|
||||
type = "string", dest = "remoteAppPath",
|
||||
help = "Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both")
|
||||
self.add_option(
|
||||
"--remote-app-path",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="remoteAppPath",
|
||||
help="Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both")
|
||||
defaults["remoteAppPath"] = None
|
||||
|
||||
self.add_option("--deviceIP", action="store",
|
||||
type = "string", dest = "deviceIP",
|
||||
help = "ip address of remote device to test")
|
||||
type="string", dest="deviceIP",
|
||||
help="ip address of remote device to test")
|
||||
defaults["deviceIP"] = None
|
||||
|
||||
self.add_option("--deviceSerial", action="store",
|
||||
type = "string", dest = "deviceSerial",
|
||||
help = "ip address of remote device to test")
|
||||
type="string", dest="deviceSerial",
|
||||
help="ip address of remote device to test")
|
||||
defaults["deviceSerial"] = None
|
||||
|
||||
self.add_option("--dm_trans", action="store",
|
||||
type = "string", dest = "dm_trans",
|
||||
help = "the transport to use to communicate with device: [adb|sut]; default=sut")
|
||||
self.add_option(
|
||||
"--dm_trans",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="dm_trans",
|
||||
help="the transport to use to communicate with device: [adb|sut]; default=sut")
|
||||
defaults["dm_trans"] = "sut"
|
||||
|
||||
self.add_option("--devicePort", action="store",
|
||||
type = "string", dest = "devicePort",
|
||||
help = "port of remote device to test")
|
||||
type="string", dest="devicePort",
|
||||
help="port of remote device to test")
|
||||
defaults["devicePort"] = 20701
|
||||
|
||||
self.add_option("--remote-product-name", action="store",
|
||||
type = "string", dest = "remoteProductName",
|
||||
help = "The executable's name of remote product to test - either fennec or firefox, defaults to fennec")
|
||||
self.add_option(
|
||||
"--remote-product-name",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="remoteProductName",
|
||||
help="The executable's name of remote product to test - either fennec or firefox, defaults to fennec")
|
||||
defaults["remoteProductName"] = "fennec"
|
||||
|
||||
self.add_option("--remote-logfile", action="store",
|
||||
type = "string", dest = "remoteLogFile",
|
||||
help = "Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.")
|
||||
self.add_option(
|
||||
"--remote-logfile",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="remoteLogFile",
|
||||
help="Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.")
|
||||
defaults["remoteLogFile"] = None
|
||||
|
||||
self.add_option("--remote-webserver", action = "store",
|
||||
type = "string", dest = "remoteWebServer",
|
||||
help = "ip address where the remote web server is hosted at")
|
||||
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("--http-port", action = "store",
|
||||
type = "string", dest = "httpPort",
|
||||
help = "http port of the remote web server")
|
||||
self.add_option("--http-port", action="store",
|
||||
type="string", dest="httpPort",
|
||||
help="http port of the remote web server")
|
||||
defaults["httpPort"] = automation.DEFAULT_HTTP_PORT
|
||||
|
||||
self.add_option("--ssl-port", action = "store",
|
||||
type = "string", dest = "sslPort",
|
||||
help = "ssl port of the remote web server")
|
||||
self.add_option("--ssl-port", action="store",
|
||||
type="string", dest="sslPort",
|
||||
help="ssl port of the remote web server")
|
||||
defaults["sslPort"] = automation.DEFAULT_SSL_PORT
|
||||
|
||||
self.add_option("--robocop-ini", action = "store",
|
||||
type = "string", dest = "robocopIni",
|
||||
help = "name of the .ini file containing the list of tests to run")
|
||||
self.add_option(
|
||||
"--robocop-ini",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="robocopIni",
|
||||
help="name of the .ini file containing the list of tests to run")
|
||||
defaults["robocopIni"] = ""
|
||||
|
||||
self.add_option("--robocop", action = "store",
|
||||
type = "string", dest = "robocop",
|
||||
help = "name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
|
||||
self.add_option(
|
||||
"--robocop",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="robocop",
|
||||
help="name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
|
||||
defaults["robocop"] = ""
|
||||
|
||||
self.add_option("--robocop-apk", action = "store",
|
||||
type = "string", dest = "robocopApk",
|
||||
help = "name of the Robocop APK to use for ADB test running")
|
||||
self.add_option(
|
||||
"--robocop-apk",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="robocopApk",
|
||||
help="name of the Robocop APK to use for ADB test running")
|
||||
defaults["robocopApk"] = ""
|
||||
|
||||
self.add_option("--robocop-path", action = "store",
|
||||
type = "string", dest = "robocopPath",
|
||||
help = "Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
|
||||
self.add_option(
|
||||
"--robocop-path",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="robocopPath",
|
||||
help="Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
|
||||
defaults["robocopPath"] = ""
|
||||
|
||||
self.add_option("--robocop-ids", action = "store",
|
||||
type = "string", dest = "robocopIds",
|
||||
help = "name of the file containing the view ID map (fennec_ids.txt)")
|
||||
self.add_option(
|
||||
"--robocop-ids",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="robocopIds",
|
||||
help="name of the file containing the view ID map (fennec_ids.txt)")
|
||||
defaults["robocopIds"] = ""
|
||||
|
||||
self.add_option("--remoteTestRoot", action = "store",
|
||||
type = "string", dest = "remoteTestRoot",
|
||||
help = "remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
|
||||
self.add_option(
|
||||
"--remoteTestRoot",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="remoteTestRoot",
|
||||
help="remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
|
||||
defaults["remoteTestRoot"] = None
|
||||
|
||||
defaults["logFile"] = "mochitest.log"
|
||||
@@ -131,38 +168,43 @@ class RemoteOptions(MochitestOptions):
|
||||
if not options.remoteTestRoot:
|
||||
options.remoteTestRoot = automation._devicemanager.deviceRoot
|
||||
|
||||
if options.remoteWebServer == None:
|
||||
if options.remoteWebServer is None:
|
||||
if os.name != "nt":
|
||||
options.remoteWebServer = moznetwork.get_ip()
|
||||
else:
|
||||
options_logger.error("you must specify a --remote-webserver=<ip address>")
|
||||
options_logger.error(
|
||||
"you must specify a --remote-webserver=<ip address>")
|
||||
return None
|
||||
|
||||
options.webServer = options.remoteWebServer
|
||||
|
||||
if (options.dm_trans == 'sut' and options.deviceIP == None):
|
||||
options_logger.error("If --dm_trans = sut, you must provide a device IP")
|
||||
if (options.dm_trans == 'sut' and options.deviceIP is None):
|
||||
options_logger.error(
|
||||
"If --dm_trans = sut, you must provide a device IP")
|
||||
return None
|
||||
|
||||
if (options.remoteLogFile == None):
|
||||
options.remoteLogFile = options.remoteTestRoot + '/logs/mochitest.log'
|
||||
if (options.remoteLogFile is None):
|
||||
options.remoteLogFile = options.remoteTestRoot + \
|
||||
'/logs/mochitest.log'
|
||||
|
||||
if (options.remoteLogFile.count('/') < 1):
|
||||
options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile
|
||||
options.remoteLogFile = options.remoteTestRoot + \
|
||||
'/' + options.remoteLogFile
|
||||
|
||||
# remoteAppPath or app must be specified to find the product to launch
|
||||
if (options.remoteAppPath and options.app):
|
||||
options_logger.error("You cannot specify both the remoteAppPath and the app setting")
|
||||
options_logger.error(
|
||||
"You cannot specify both the remoteAppPath and the app setting")
|
||||
return None
|
||||
elif (options.remoteAppPath):
|
||||
options.app = options.remoteTestRoot + "/" + options.remoteAppPath
|
||||
elif (options.app == None):
|
||||
elif (options.app is None):
|
||||
# Neither remoteAppPath nor app are set -- error
|
||||
options_logger.error("You must specify either appPath or app")
|
||||
return None
|
||||
|
||||
# Only reset the xrePath if it wasn't provided
|
||||
if (options.xrePath == None):
|
||||
if (options.xrePath is None):
|
||||
options.xrePath = options.utilityPath
|
||||
|
||||
if (options.pidFile != ""):
|
||||
@@ -173,38 +215,49 @@ class RemoteOptions(MochitestOptions):
|
||||
# Robocop specific deprecated options.
|
||||
if options.robocop:
|
||||
if options.robocopIni:
|
||||
options_logger.error("can not use deprecated --robocop and replacement --robocop-ini together")
|
||||
options_logger.error(
|
||||
"can not use deprecated --robocop and replacement --robocop-ini together")
|
||||
return None
|
||||
options.robocopIni = options.robocop
|
||||
del options.robocop
|
||||
|
||||
if options.robocopPath:
|
||||
if options.robocopApk:
|
||||
options_logger.error("can not use deprecated --robocop-path and replacement --robocop-apk together")
|
||||
options_logger.error(
|
||||
"can not use deprecated --robocop-path and replacement --robocop-apk together")
|
||||
return None
|
||||
options.robocopApk = os.path.join(options.robocopPath, 'robocop.apk')
|
||||
options.robocopApk = os.path.join(
|
||||
options.robocopPath,
|
||||
'robocop.apk')
|
||||
del options.robocopPath
|
||||
|
||||
# Robocop specific options
|
||||
if options.robocopIni != "":
|
||||
if not os.path.exists(options.robocopIni):
|
||||
options_logger.error("Unable to find specified robocop .ini manifest '%s'" % options.robocopIni)
|
||||
options_logger.error(
|
||||
"Unable to find specified robocop .ini manifest '%s'" %
|
||||
options.robocopIni)
|
||||
return None
|
||||
options.robocopIni = os.path.abspath(options.robocopIni)
|
||||
|
||||
if options.robocopApk != "":
|
||||
if not os.path.exists(options.robocopApk):
|
||||
options_logger.error("Unable to find robocop APK '%s'" % options.robocopApk)
|
||||
options_logger.error(
|
||||
"Unable to find robocop APK '%s'" %
|
||||
options.robocopApk)
|
||||
return None
|
||||
options.robocopApk = os.path.abspath(options.robocopApk)
|
||||
|
||||
if options.robocopIds != "":
|
||||
if not os.path.exists(options.robocopIds):
|
||||
options_logger.error("Unable to find specified robocop IDs file '%s'" % options.robocopIds)
|
||||
options_logger.error(
|
||||
"Unable to find specified robocop IDs file '%s'" %
|
||||
options.robocopIds)
|
||||
return None
|
||||
options.robocopIds = os.path.abspath(options.robocopIds)
|
||||
|
||||
# allow us to keep original application around for cleanup while running robocop via 'am'
|
||||
# allow us to keep original application around for cleanup while
|
||||
# running robocop via 'am'
|
||||
options.remoteappname = options.app
|
||||
return options
|
||||
|
||||
@@ -226,6 +279,7 @@ class RemoteOptions(MochitestOptions):
|
||||
|
||||
return options
|
||||
|
||||
|
||||
class MochiRemote(Mochitest):
|
||||
|
||||
_automation = None
|
||||
@@ -247,20 +301,24 @@ class MochiRemote(Mochitest):
|
||||
self._automation.deleteTombstones()
|
||||
self.certdbNew = True
|
||||
self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
|
||||
self._dm.removeDir(self.remoteNSPR);
|
||||
self._dm.mkDir(self.remoteNSPR);
|
||||
self.remoteChromeTestDir = os.path.join(options.remoteTestRoot, "chrome")
|
||||
self._dm.removeDir(self.remoteChromeTestDir);
|
||||
self._dm.mkDir(self.remoteChromeTestDir);
|
||||
self._dm.removeDir(self.remoteNSPR)
|
||||
self._dm.mkDir(self.remoteNSPR)
|
||||
self.remoteChromeTestDir = os.path.join(
|
||||
options.remoteTestRoot,
|
||||
"chrome")
|
||||
self._dm.removeDir(self.remoteChromeTestDir)
|
||||
self._dm.mkDir(self.remoteChromeTestDir)
|
||||
|
||||
def cleanup(self, options):
|
||||
if self._dm.fileExists(self.remoteLog):
|
||||
self._dm.getFile(self.remoteLog, self.localLog)
|
||||
self._dm.removeFile(self.remoteLog)
|
||||
else:
|
||||
self.log.warning("Unable to retrieve log file (%s) from remote device" % self.remoteLog)
|
||||
self.log.warning(
|
||||
"Unable to retrieve log file (%s) from remote device" %
|
||||
self.remoteLog)
|
||||
self._dm.removeDir(self.remoteProfile)
|
||||
self._dm.removeDir(self.remoteChromeTestDir);
|
||||
self._dm.removeDir(self.remoteChromeTestDir)
|
||||
# Don't leave an old robotium.config hanging around; the
|
||||
# profile it references was just deleted!
|
||||
deviceRoot = self._dm.getDeviceRoot()
|
||||
@@ -270,7 +328,7 @@ class MochiRemote(Mochitest):
|
||||
self._dm.getDirectory(self.remoteNSPR, blobberUploadDir)
|
||||
Mochitest.cleanup(self, options)
|
||||
|
||||
def findPath(self, paths, filename = None):
|
||||
def findPath(self, paths, filename=None):
|
||||
for path in paths:
|
||||
p = path
|
||||
if filename:
|
||||
@@ -315,8 +373,10 @@ class MochiRemote(Mochitest):
|
||||
os.path.join('..', self._automation._product)
|
||||
]
|
||||
options.xrePath = self.findPath(paths)
|
||||
if options.xrePath == None:
|
||||
self.log.error("unable to find xulrunner path for %s, please specify with --xre-path" % os.name)
|
||||
if options.xrePath is None:
|
||||
self.log.error(
|
||||
"unable to find xulrunner path for %s, please specify with --xre-path" %
|
||||
os.name)
|
||||
sys.exit(1)
|
||||
|
||||
xpcshell = "xpcshell"
|
||||
@@ -329,8 +389,10 @@ class MochiRemote(Mochitest):
|
||||
paths = [options.xrePath]
|
||||
options.utilityPath = self.findPath(paths, xpcshell)
|
||||
|
||||
if options.utilityPath == None:
|
||||
self.log.error("unable to find utility path for %s, please specify with --utility-path" % os.name)
|
||||
if options.utilityPath is None:
|
||||
self.log.error(
|
||||
"unable to find utility path for %s, please specify with --utility-path" %
|
||||
os.name)
|
||||
sys.exit(1)
|
||||
|
||||
xpcshell_path = os.path.join(options.utilityPath, xpcshell)
|
||||
@@ -356,7 +418,11 @@ class MochiRemote(Mochitest):
|
||||
""" Create the servers on the host and start them up """
|
||||
restoreRemotePaths = self.switchToLocalPaths(options)
|
||||
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
||||
Mochitest.startServers(self, options, debuggerInfo, ignoreSSLTunnelExts = True)
|
||||
Mochitest.startServers(
|
||||
self,
|
||||
options,
|
||||
debuggerInfo,
|
||||
ignoreSSLTunnelExts=True)
|
||||
restoreRemotePaths()
|
||||
|
||||
def buildProfile(self, options):
|
||||
@@ -368,15 +434,31 @@ class MochiRemote(Mochitest):
|
||||
# we do not need this for robotium based tests, lets save a LOT of time
|
||||
if options.robocopIni:
|
||||
shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
|
||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'mochikit@mozilla.org'))
|
||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'worker-test@mozilla.org'))
|
||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'workerbootstrap-test@mozilla.org'))
|
||||
shutil.rmtree(
|
||||
os.path.join(
|
||||
options.profilePath,
|
||||
'extensions',
|
||||
'staged',
|
||||
'mochikit@mozilla.org'))
|
||||
shutil.rmtree(
|
||||
os.path.join(
|
||||
options.profilePath,
|
||||
'extensions',
|
||||
'staged',
|
||||
'worker-test@mozilla.org'))
|
||||
shutil.rmtree(
|
||||
os.path.join(
|
||||
options.profilePath,
|
||||
'extensions',
|
||||
'staged',
|
||||
'workerbootstrap-test@mozilla.org'))
|
||||
os.remove(os.path.join(options.profilePath, 'userChrome.css'))
|
||||
|
||||
try:
|
||||
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
||||
except devicemanager.DMError:
|
||||
self.log.error("Automation Error: Unable to copy profile to device.")
|
||||
self.log.error(
|
||||
"Automation Error: Unable to copy profile to device.")
|
||||
raise
|
||||
|
||||
restoreRemotePaths()
|
||||
@@ -392,11 +474,12 @@ class MochiRemote(Mochitest):
|
||||
retVal = Mochitest.buildURLOptions(self, options, env)
|
||||
|
||||
if not options.robocopIni:
|
||||
#we really need testConfig.js (for browser chrome)
|
||||
# we really need testConfig.js (for browser chrome)
|
||||
try:
|
||||
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
||||
except devicemanager.DMError:
|
||||
self.log.error("Automation Error: Unable to copy profile to device.")
|
||||
self.log.error(
|
||||
"Automation Error: Unable to copy profile to device.")
|
||||
raise
|
||||
|
||||
options.profilePath = self.remoteProfile
|
||||
@@ -416,7 +499,11 @@ class MochiRemote(Mochitest):
|
||||
# robocop tests.
|
||||
return self.buildTestURL(options)
|
||||
else:
|
||||
return super(MochiRemote, self).buildTestPath(options, testsToFilter)
|
||||
return super(
|
||||
MochiRemote,
|
||||
self).buildTestPath(
|
||||
options,
|
||||
testsToFilter)
|
||||
|
||||
def getChromeTestDir(self, options):
|
||||
local = super(MochiRemote, self).getChromeTestDir(options)
|
||||
@@ -430,7 +517,8 @@ class MochiRemote(Mochitest):
|
||||
def getLogFilePath(self, logFile):
|
||||
return logFile
|
||||
|
||||
# In the future we could use LogParser: http://hg.mozilla.org/automation/logparser/
|
||||
# In the future we could use LogParser:
|
||||
# http://hg.mozilla.org/automation/logparser/
|
||||
def addLogData(self):
|
||||
with open(self.localLog) as currentLog:
|
||||
data = currentLog.readlines()
|
||||
@@ -461,7 +549,8 @@ class MochiRemote(Mochitest):
|
||||
if fail_found:
|
||||
result = 1
|
||||
if not end_found:
|
||||
self.log.info("PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
|
||||
self.log.info(
|
||||
"PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
|
||||
result = 1
|
||||
return result
|
||||
|
||||
@@ -494,7 +583,8 @@ class MochiRemote(Mochitest):
|
||||
incr += 1
|
||||
logFile.append("%s INFO SimpleTest FINISHED" % incr)
|
||||
|
||||
# TODO: Consider not printing to stdout because we might be duplicating output
|
||||
# TODO: Consider not printing to stdout because we might be duplicating
|
||||
# output
|
||||
print '\n'.join(logFile)
|
||||
with open(self.localLog, 'w') as localLog:
|
||||
localLog.write('\n'.join(logFile))
|
||||
@@ -506,7 +596,9 @@ class MochiRemote(Mochitest):
|
||||
def printScreenshots(self, screenShotDir):
|
||||
# TODO: This can be re-written after completion of bug 749421
|
||||
if not self._dm.dirExists(screenShotDir):
|
||||
self.log.info("SCREENSHOT: No ScreenShots directory available: " + screenShotDir)
|
||||
self.log.info(
|
||||
"SCREENSHOT: No ScreenShots directory available: " +
|
||||
screenShotDir)
|
||||
return
|
||||
|
||||
printed = 0
|
||||
@@ -527,8 +619,13 @@ class MochiRemote(Mochitest):
|
||||
def printDeviceInfo(self, printLogcat=False):
|
||||
try:
|
||||
if printLogcat:
|
||||
logcat = self._dm.getLogcat(filterOutRegexps=fennecLogcatFilters)
|
||||
self.log.info('\n' + ''.join(logcat).decode('utf-8', 'replace'))
|
||||
logcat = self._dm.getLogcat(
|
||||
filterOutRegexps=fennecLogcatFilters)
|
||||
self.log.info(
|
||||
'\n' +
|
||||
''.join(logcat).decode(
|
||||
'utf-8',
|
||||
'replace'))
|
||||
self.log.info("Device info: %s" % self._dm.getInfo())
|
||||
self.log.info("Test root: %s" % self._dm.deviceRoot)
|
||||
except devicemanager.DMError:
|
||||
@@ -543,7 +640,9 @@ class MochiRemote(Mochitest):
|
||||
fHandle.write("profile=%s\n" % (self.remoteProfile))
|
||||
fHandle.write("logfile=%s\n" % (options.remoteLogFile))
|
||||
fHandle.write("host=http://mochi.test:8888/tests\n")
|
||||
fHandle.write("rawhost=http://%s:%s/tests\n" % (options.remoteWebServer, options.httpPort))
|
||||
fHandle.write(
|
||||
"rawhost=http://%s:%s/tests\n" %
|
||||
(options.remoteWebServer, options.httpPort))
|
||||
|
||||
if browserEnv:
|
||||
envstr = ""
|
||||
@@ -551,7 +650,9 @@ class MochiRemote(Mochitest):
|
||||
for key, value in browserEnv.items():
|
||||
try:
|
||||
value.index(',')
|
||||
self.log.error("buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" % (key, value))
|
||||
self.log.error(
|
||||
"buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" %
|
||||
(key, value))
|
||||
self.log.error("browserEnv=%s" % browserEnv)
|
||||
except ValueError:
|
||||
envstr += "%s%s=%s" % (delim, key, value)
|
||||
@@ -561,7 +662,11 @@ class MochiRemote(Mochitest):
|
||||
fHandle.close()
|
||||
|
||||
self._dm.removeFile(os.path.join(deviceRoot, "robotium.config"))
|
||||
self._dm.pushFile(fHandle.name, os.path.join(deviceRoot, "robotium.config"))
|
||||
self._dm.pushFile(
|
||||
fHandle.name,
|
||||
os.path.join(
|
||||
deviceRoot,
|
||||
"robotium.config"))
|
||||
os.unlink(fHandle.name)
|
||||
|
||||
def getGMPPluginPath(self, options):
|
||||
@@ -569,10 +674,15 @@ class MochiRemote(Mochitest):
|
||||
return None
|
||||
|
||||
def buildBrowserEnv(self, options, debugger=False):
|
||||
browserEnv = Mochitest.buildBrowserEnv(self, options, debugger=debugger)
|
||||
browserEnv = Mochitest.buildBrowserEnv(
|
||||
self,
|
||||
options,
|
||||
debugger=debugger)
|
||||
# override nsprLogs to avoid processing in Mochitest base class
|
||||
self.nsprLogs = None
|
||||
browserEnv["NSPR_LOG_FILE"] = os.path.join(self.remoteNSPR, self.nsprLogName)
|
||||
browserEnv["NSPR_LOG_FILE"] = os.path.join(
|
||||
self.remoteNSPR,
|
||||
self.nsprLogName)
|
||||
self.buildRobotiumConfig(options, browserEnv)
|
||||
return browserEnv
|
||||
|
||||
@@ -593,6 +703,7 @@ class MochiRemote(Mochitest):
|
||||
|
||||
return self._automation.runApp(*args, **kwargs)
|
||||
|
||||
|
||||
def main(args):
|
||||
message_logger = MessageLogger(logger=None)
|
||||
process_args = {'messageLogger': message_logger}
|
||||
@@ -604,13 +715,23 @@ def main(args):
|
||||
|
||||
if (options.dm_trans == "adb"):
|
||||
if (options.deviceIP):
|
||||
dm = droid.DroidADB(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
|
||||
dm = droid.DroidADB(
|
||||
options.deviceIP,
|
||||
options.devicePort,
|
||||
deviceRoot=options.remoteTestRoot)
|
||||
elif (options.deviceSerial):
|
||||
dm = droid.DroidADB(None, None, deviceSerial=options.deviceSerial, deviceRoot=options.remoteTestRoot)
|
||||
dm = droid.DroidADB(
|
||||
None,
|
||||
None,
|
||||
deviceSerial=options.deviceSerial,
|
||||
deviceRoot=options.remoteTestRoot)
|
||||
else:
|
||||
dm = droid.DroidADB(deviceRoot=options.remoteTestRoot)
|
||||
else:
|
||||
dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
|
||||
dm = droid.DroidSUT(
|
||||
options.deviceIP,
|
||||
options.devicePort,
|
||||
deviceRoot=options.remoteTestRoot)
|
||||
auto.setDeviceManager(dm)
|
||||
options = parser.verifyRemoteOptions(options, auto)
|
||||
|
||||
@@ -620,23 +741,24 @@ def main(args):
|
||||
message_logger.logger = log
|
||||
mochitest.message_logger = message_logger
|
||||
|
||||
if (options == None):
|
||||
log.error("Invalid options specified, use --help for a list of valid options")
|
||||
if (options is None):
|
||||
log.error(
|
||||
"Invalid options specified, use --help for a list of valid options")
|
||||
return 1
|
||||
|
||||
productPieces = options.remoteProductName.split('.')
|
||||
if (productPieces != None):
|
||||
if (productPieces is not None):
|
||||
auto.setProduct(productPieces[0])
|
||||
else:
|
||||
auto.setProduct(options.remoteProductName)
|
||||
auto.setAppName(options.remoteappname)
|
||||
|
||||
options = parser.verifyOptions(options, mochitest)
|
||||
if (options == None):
|
||||
if (options is None):
|
||||
return 1
|
||||
|
||||
logParent = os.path.dirname(options.remoteLogFile)
|
||||
dm.mkDir(logParent);
|
||||
dm.mkDir(logParent)
|
||||
auto.setRemoteLog(options.remoteLogFile)
|
||||
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
|
||||
|
||||
@@ -645,7 +767,9 @@ def main(args):
|
||||
# Add Android version (SDK level) to mozinfo so that manifest entries
|
||||
# can be conditional on android_version.
|
||||
androidVersion = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk'])
|
||||
log.info("Android sdk version '%s'; will use this to filter manifests" % str(androidVersion))
|
||||
log.info(
|
||||
"Android sdk version '%s'; will use this to filter manifests" %
|
||||
str(androidVersion))
|
||||
mozinfo.info['android_version'] = androidVersion
|
||||
|
||||
deviceRoot = dm.deviceRoot
|
||||
@@ -677,13 +801,14 @@ def main(args):
|
||||
tests.append(test['name'])
|
||||
|
||||
if options.totalChunks:
|
||||
tests_per_chunk = math.ceil(len(tests) / (options.totalChunks * 1.0))
|
||||
start = int(round((options.thisChunk-1) * tests_per_chunk))
|
||||
tests_per_chunk = math.ceil(
|
||||
len(tests) / (options.totalChunks * 1.0))
|
||||
start = int(round((options.thisChunk - 1) * tests_per_chunk))
|
||||
end = int(round(options.thisChunk * tests_per_chunk))
|
||||
if end > len(tests):
|
||||
end = len(tests)
|
||||
my_tests = tests[start:end]
|
||||
log.info("Running tests %d-%d/%d" % (start+1, end, len(tests)))
|
||||
log.info("Running tests %d-%d/%d" % (start + 1, end, len(tests)))
|
||||
|
||||
options.extraPrefs.append('browser.search.suggest.enabled=true')
|
||||
options.extraPrefs.append('browser.search.suggest.prompted=true')
|
||||
@@ -706,7 +831,9 @@ def main(args):
|
||||
continue
|
||||
|
||||
if 'disabled' in test:
|
||||
log.info('TEST-INFO | skipping %s | %s' % (test['name'], test['disabled']))
|
||||
log.info(
|
||||
'TEST-INFO | skipping %s | %s' %
|
||||
(test['name'], test['disabled']))
|
||||
continue
|
||||
|
||||
active_tests.append(test)
|
||||
@@ -714,7 +841,8 @@ def main(args):
|
||||
log.suite_start([t['name'] for t in active_tests])
|
||||
|
||||
for test in active_tests:
|
||||
# When running in a loop, we need to create a fresh profile for each cycle
|
||||
# When running in a loop, we need to create a fresh profile for
|
||||
# each cycle
|
||||
if mochitest.localProfile:
|
||||
options.profilePath = mochitest.localProfile
|
||||
os.system("rm -Rf %s" % options.profilePath)
|
||||
@@ -722,32 +850,73 @@ def main(args):
|
||||
mochitest.localProfile = options.profilePath
|
||||
|
||||
options.app = "am"
|
||||
options.browserArgs = ["instrument", "-w", "-e", "deviceroot", deviceRoot, "-e", "class"]
|
||||
options.browserArgs.append("org.mozilla.gecko.tests.%s" % test['name'])
|
||||
options.browserArgs.append("org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
|
||||
options.browserArgs = [
|
||||
"instrument",
|
||||
"-w",
|
||||
"-e",
|
||||
"deviceroot",
|
||||
deviceRoot,
|
||||
"-e",
|
||||
"class"]
|
||||
options.browserArgs.append(
|
||||
"org.mozilla.gecko.tests.%s" %
|
||||
test['name'])
|
||||
options.browserArgs.append(
|
||||
"org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
|
||||
mochitest.nsprLogName = "nspr-%s.log" % test['name']
|
||||
|
||||
# If the test is for checking the import from bookmarks then make sure there is data to import
|
||||
# If the test is for checking the import from bookmarks then make
|
||||
# sure there is data to import
|
||||
if test['name'] == "testImportFromAndroid":
|
||||
|
||||
# Get the OS so we can run the insert in the apropriate database and following the correct table schema
|
||||
# Get the OS so we can run the insert in the apropriate
|
||||
# database and following the correct table schema
|
||||
osInfo = dm.getInfo("os")
|
||||
devOS = " ".join(osInfo['os'])
|
||||
|
||||
if ("pandaboard" in devOS):
|
||||
delete = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
||||
delete = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
||||
else:
|
||||
delete = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
||||
delete = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
||||
if (options.dm_trans == "sut"):
|
||||
dm._runCmds([{"cmd": " ".join(delete)}])
|
||||
|
||||
# Insert the bookmarks
|
||||
log.info("Insert bookmarks in the default android browser database")
|
||||
log.info(
|
||||
"Insert bookmarks in the default android browser database")
|
||||
for i in range(20):
|
||||
if ("pandaboard" in devOS):
|
||||
cmd = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db 'insert or replace into bookmarks(_id,title,url,folder,parent,position) values (" + str(30 + i) + ",\"Bookmark"+ str(i) + "\",\"http://www.bookmark" + str(i) + ".com\",0,1," + str(100 + i) + ");'"]
|
||||
cmd = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser2.db 'insert or replace into bookmarks(_id,title,url,folder,parent,position) values (" +
|
||||
str(
|
||||
30 +
|
||||
i) +
|
||||
",\"Bookmark" +
|
||||
str(i) +
|
||||
"\",\"http://www.bookmark" +
|
||||
str(i) +
|
||||
".com\",0,1," +
|
||||
str(
|
||||
100 +
|
||||
i) +
|
||||
");'"]
|
||||
else:
|
||||
cmd = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser.db 'insert into bookmarks(title,url,bookmark) values (\"Bookmark"+ str(i) + "\",\"http://www.bookmark" + str(i) + ".com\",1);'"]
|
||||
cmd = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser.db 'insert into bookmarks(title,url,bookmark) values (\"Bookmark" +
|
||||
str(i) +
|
||||
"\",\"http://www.bookmark" +
|
||||
str(i) +
|
||||
".com\",1);'"]
|
||||
if (options.dm_trans == "sut"):
|
||||
dm._runCmds([{"cmd": " ".join(cmd)}])
|
||||
try:
|
||||
@@ -761,11 +930,13 @@ def main(args):
|
||||
if result != 0 or log_result != 0:
|
||||
mochitest.printDeviceInfo(printLogcat=True)
|
||||
mochitest.printScreenshots(screenShotDir)
|
||||
# Ensure earlier failures aren't overwritten by success on this run
|
||||
# Ensure earlier failures aren't overwritten by success on this
|
||||
# run
|
||||
if retVal is None or retVal == 0:
|
||||
retVal = result
|
||||
except:
|
||||
log.error("Automation Error: Exception caught while running tests")
|
||||
log.error(
|
||||
"Automation Error: Exception caught while running tests")
|
||||
traceback.print_exc()
|
||||
mochitest.stopServers()
|
||||
try:
|
||||
@@ -779,9 +950,15 @@ def main(args):
|
||||
# Clean-up added bookmarks
|
||||
if test['name'] == "testImportFromAndroid":
|
||||
if ("pandaboard" in devOS):
|
||||
cmd_del = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
||||
cmd_del = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
||||
else:
|
||||
cmd_del = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
||||
cmd_del = [
|
||||
'execsu',
|
||||
'sqlite3',
|
||||
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
||||
if (options.dm_trans == "sut"):
|
||||
dm._runCmds([{"cmd": " ".join(cmd_del)}])
|
||||
if retVal is None:
|
||||
|
||||
Reference in New Issue
Block a user