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 math
|
||||||
import mozinfo
|
import mozinfo
|
||||||
|
|
||||||
|
|
||||||
class Bisect(object):
|
class Bisect(object):
|
||||||
|
|
||||||
"Class for creating, bisecting and summarizing for --bisect-chunk option."
|
"Class for creating, bisecting and summarizing for --bisect-chunk option."
|
||||||
|
|
||||||
def __init__(self, harness):
|
def __init__(self, harness):
|
||||||
@@ -34,23 +36,28 @@ class Bisect(object):
|
|||||||
if not options.totalChunks or not options.thisChunk:
|
if not options.totalChunks or not options.thisChunk:
|
||||||
return tests
|
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:
|
if options.chunkByDir:
|
||||||
tests_by_dir = {}
|
tests_by_dir = {}
|
||||||
test_dirs = []
|
test_dirs = []
|
||||||
for test in tests:
|
for test in tests:
|
||||||
directory = test.split("/")
|
directory = test.split("/")
|
||||||
directory = directory[0:min(options.chunkByDir, len(directory)-1)]
|
directory = directory[
|
||||||
|
0:min(
|
||||||
|
options.chunkByDir,
|
||||||
|
len(directory) -
|
||||||
|
1)]
|
||||||
directory = "/".join(directory)
|
directory = "/".join(directory)
|
||||||
|
|
||||||
if not directory in tests_by_dir:
|
if directory not in tests_by_dir:
|
||||||
tests_by_dir[directory] = [test]
|
tests_by_dir[directory] = [test]
|
||||||
test_dirs.append(directory)
|
test_dirs.append(directory)
|
||||||
else:
|
else:
|
||||||
tests_by_dir[directory].append(test)
|
tests_by_dir[directory].append(test)
|
||||||
|
|
||||||
tests_per_chunk = float(len(test_dirs)) / options.totalChunks
|
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))
|
end = int(round((options.thisChunk) * tests_per_chunk))
|
||||||
test_dirs = test_dirs[start:end]
|
test_dirs = test_dirs[start:end]
|
||||||
return_tests = []
|
return_tests = []
|
||||||
@@ -59,7 +66,7 @@ class Bisect(object):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
tests_per_chunk = float(len(tests)) / options.totalChunks
|
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))
|
end = int(round(options.thisChunk * tests_per_chunk))
|
||||||
return_tests = tests[start:end]
|
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."
|
"This method is used to call other methods for setting up variables and getting the list of tests for bisection."
|
||||||
if options.bisectChunk == "default":
|
if options.bisectChunk == "default":
|
||||||
return tests
|
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):
|
elif 'loop' not in self.contents or not self.contents['tests'][-1].endswith(options.bisectChunk):
|
||||||
tests = self.get_tests_for_bisection(options, tests)
|
tests = self.get_tests_for_bisection(options, tests)
|
||||||
status = self.setup(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
|
# 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".
|
# in self.expectedError as we do not want to run if it is "default".
|
||||||
if status == -1 and options.bisectChunk in self.expectedError:
|
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']:
|
if mozinfo.info['debug']:
|
||||||
return status
|
return status
|
||||||
|
|
||||||
testBleedThrough = self.contents['testsToRun'][0]
|
testBleedThrough = self.contents['testsToRun'][0]
|
||||||
tests = self.contents['totalTests']
|
tests = self.contents['totalTests']
|
||||||
tests.remove(testBleedThrough)
|
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:
|
if options.bisectChunk in testBleedThrough:
|
||||||
return status
|
return status
|
||||||
|
|
||||||
@@ -133,7 +143,7 @@ class Bisect(object):
|
|||||||
# self.contents['result'] will be expected error only if it fails.
|
# self.contents['result'] will be expected error only if it fails.
|
||||||
elif self.contents['result'] == "FAIL":
|
elif self.contents['result'] == "FAIL":
|
||||||
self.contents['tests'] = self.contents['testsToRun']
|
self.contents['tests'] = self.contents['testsToRun']
|
||||||
status = 1 # for initializing
|
status = 1 # for initializing
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
if status:
|
if status:
|
||||||
@@ -189,22 +199,35 @@ class Bisect(object):
|
|||||||
def summarize_chunk(self, options):
|
def summarize_chunk(self, options):
|
||||||
"This method is used summarize the results after the list of tests is run."
|
"This method is used summarize the results after the list of tests is run."
|
||||||
if options.bisectChunk == "default":
|
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:
|
if len(self.expectedError) == 0:
|
||||||
return -1
|
return -1
|
||||||
options.bisectChunk = self.expectedError.keys()[0]
|
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
|
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:
|
if options.bisectChunk not in self.result:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
self.summary.append("\tPass %d:" % self.contents['loop'])
|
self.summary.append("\tPass %d:" % self.contents['loop'])
|
||||||
if len(self.contents['testsToRun']) > 1:
|
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:
|
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)
|
return self.check_for_intermittent(options)
|
||||||
|
|
||||||
if self.result[options.bisectChunk] == "PASS":
|
if self.result[options.bisectChunk] == "PASS":
|
||||||
@@ -217,23 +240,32 @@ class Bisect(object):
|
|||||||
|
|
||||||
elif self.result[options.bisectChunk] == "FAIL":
|
elif self.result[options.bisectChunk] == "FAIL":
|
||||||
if 'expectedError' not in self.contents:
|
if 'expectedError' not in self.contents:
|
||||||
self.summary.append("\t\t%s failed." % self.contents['testsToRun'][-1])
|
self.summary.append("\t\t%s failed." %
|
||||||
self.contents['expectedError'] = self.expectedError[options.bisectChunk]
|
self.contents['testsToRun'][-1])
|
||||||
|
self.contents['expectedError'] = self.expectedError[
|
||||||
|
options.bisectChunk]
|
||||||
status = 0
|
status = 0
|
||||||
|
|
||||||
elif self.expectedError[options.bisectChunk] == self.contents['expectedError']:
|
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"
|
self.contents['result'] = "FAIL"
|
||||||
status = 0
|
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'])
|
numberOfTests = len(self.contents['testsToRun'])
|
||||||
if numberOfTests < 3:
|
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
|
# This means that only 2 tests are run. Since the last 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])
|
# 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
|
status = -1
|
||||||
else:
|
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
|
status = -1
|
||||||
|
|
||||||
return status
|
return status
|
||||||
@@ -241,7 +273,9 @@ class Bisect(object):
|
|||||||
def check_for_intermittent(self, options):
|
def check_for_intermittent(self, options):
|
||||||
"This method is used to check whether a test is an intermittent."
|
"This method is used to check whether a test is an intermittent."
|
||||||
if self.result[options.bisectChunk] == "PASS":
|
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:
|
if self.repeat > 0:
|
||||||
# loop is set to 1 to again run the single test.
|
# loop is set to 1 to again run the single test.
|
||||||
self.contents['loop'] = 1
|
self.contents['loop'] = 1
|
||||||
@@ -256,7 +290,9 @@ class Bisect(object):
|
|||||||
self.contents['loop'] = 2
|
self.contents['loop'] = 2
|
||||||
return 1
|
return 1
|
||||||
elif self.result[options.bisectChunk] == "FAIL":
|
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.failcount += 1
|
||||||
self.contents['loop'] = 1
|
self.contents['loop'] = 1
|
||||||
self.repeat -= 1
|
self.repeat -= 1
|
||||||
@@ -269,7 +305,9 @@ class Bisect(object):
|
|||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
else:
|
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
|
return -1
|
||||||
|
|
||||||
def print_summary(self):
|
def print_summary(self):
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ FLAVORS = {
|
|||||||
|
|
||||||
|
|
||||||
class MochitestRunner(MozbuildObject):
|
class MochitestRunner(MozbuildObject):
|
||||||
|
|
||||||
"""Easily run mochitests.
|
"""Easily run mochitests.
|
||||||
|
|
||||||
This currently contains just the basics for running mochitests. We may want
|
This currently contains just the basics for running mochitests. We may want
|
||||||
@@ -91,8 +92,12 @@ class MochitestRunner(MozbuildObject):
|
|||||||
import mozinfo
|
import mozinfo
|
||||||
appname = 'webapprt-stub' + mozinfo.info.get('bin_suffix', '')
|
appname = 'webapprt-stub' + mozinfo.info.get('bin_suffix', '')
|
||||||
if sys.platform.startswith('darwin'):
|
if sys.platform.startswith('darwin'):
|
||||||
appname = os.path.join(self.distdir, self.substs['MOZ_MACBUNDLE_NAME'],
|
appname = os.path.join(
|
||||||
'Contents', 'Resources', appname)
|
self.distdir,
|
||||||
|
self.substs['MOZ_MACBUNDLE_NAME'],
|
||||||
|
'Contents',
|
||||||
|
'Resources',
|
||||||
|
appname)
|
||||||
else:
|
else:
|
||||||
appname = os.path.join(self.distdir, 'bin', appname)
|
appname = os.path.join(self.distdir, 'bin', appname)
|
||||||
return appname
|
return appname
|
||||||
@@ -106,12 +111,24 @@ class MochitestRunner(MozbuildObject):
|
|||||||
sys.path.append(build_path)
|
sys.path.append(build_path)
|
||||||
|
|
||||||
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
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')
|
self.bin_dir = os.path.join(self.topobjdir, 'dist', 'bin')
|
||||||
|
|
||||||
def run_b2g_test(self, test_paths=None, b2g_home=None, xre_path=None,
|
def run_b2g_test(
|
||||||
total_chunks=None, this_chunk=None, no_window=None,
|
self,
|
||||||
repeat=0, run_until_failure=False, chrome=False, **kwargs):
|
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.
|
"""Runs a b2g mochitest.
|
||||||
|
|
||||||
test_paths is an enumerable of paths to tests. It can be a relative path
|
test_paths is an enumerable of paths to tests. It can be a relative path
|
||||||
@@ -137,7 +154,7 @@ class MochitestRunner(MozbuildObject):
|
|||||||
path = os.path.join(self.mochitest_dir, 'runtestsb2g.py')
|
path = os.path.join(self.mochitest_dir, 'runtestsb2g.py')
|
||||||
with open(path, 'r') as fh:
|
with open(path, 'r') as fh:
|
||||||
imp.load_module('mochitest', fh, path,
|
imp.load_module('mochitest', fh, path,
|
||||||
('.py', 'r', imp.PY_SOURCE))
|
('.py', 'r', imp.PY_SOURCE))
|
||||||
|
|
||||||
import mochitest
|
import mochitest
|
||||||
from mochitest_options import B2GOptions
|
from mochitest_options import B2GOptions
|
||||||
@@ -147,11 +164,19 @@ class MochitestRunner(MozbuildObject):
|
|||||||
|
|
||||||
if test_path:
|
if test_path:
|
||||||
if chrome:
|
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:
|
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):
|
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
|
return 1
|
||||||
options.testPath = test_path
|
options.testPath = test_path
|
||||||
|
|
||||||
@@ -163,7 +188,9 @@ class MochitestRunner(MozbuildObject):
|
|||||||
options.repeat = repeat
|
options.repeat = repeat
|
||||||
options.runUntilFailure = run_until_failure
|
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'
|
options.consoleLevel = 'INFO'
|
||||||
if conditions.is_b2g_desktop(self):
|
if conditions.is_b2g_desktop(self):
|
||||||
@@ -190,15 +217,46 @@ class MochitestRunner(MozbuildObject):
|
|||||||
options.chrome = chrome
|
options.chrome = chrome
|
||||||
return mochitest.run_remote_mochitests(parser, options)
|
return mochitest.run_remote_mochitests(parser, options)
|
||||||
|
|
||||||
def run_desktop_test(self, context, suite=None, test_paths=None, debugger=None,
|
def run_desktop_test(
|
||||||
debugger_args=None, slowscript=False, screenshot_on_fail = False, shuffle=False, closure_behaviour='auto',
|
self,
|
||||||
rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False,
|
context,
|
||||||
slow=False, chunk_by_dir=0, total_chunks=None, this_chunk=None, extraPrefs=[],
|
suite=None,
|
||||||
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
|
test_paths=None,
|
||||||
e10s=False, strict_content_sandbox=False, nested_oop=False, dmd=False, dump_output_directory=None,
|
debugger=None,
|
||||||
dump_about_memory_after_test=False, dump_dmd_after_test=False,
|
debugger_args=None,
|
||||||
install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False,
|
slowscript=False,
|
||||||
useTestMediaDevices=False, timeout=None, **kwargs):
|
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.
|
"""Runs a mochitest.
|
||||||
|
|
||||||
test_paths are path to tests. They can be a relative path from the
|
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.
|
# Make absolute paths relative before calling os.chdir() below.
|
||||||
if test_paths:
|
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):
|
if rerun_failures and not os.path.exists(failure_file_path):
|
||||||
print('No failure file present. Did you run mochitests before?')
|
print('No failure file present. Did you run mochitests before?')
|
||||||
@@ -241,7 +302,7 @@ class MochitestRunner(MozbuildObject):
|
|||||||
path = os.path.join(self.mochitest_dir, 'runtests.py')
|
path = os.path.join(self.mochitest_dir, 'runtests.py')
|
||||||
with open(path, 'r') as fh:
|
with open(path, 'r') as fh:
|
||||||
imp.load_module('mochitest', fh, path,
|
imp.load_module('mochitest', fh, path,
|
||||||
('.py', 'r', imp.PY_SOURCE))
|
('.py', 'r', imp.PY_SOURCE))
|
||||||
|
|
||||||
import mochitest
|
import mochitest
|
||||||
from manifestparser import TestManifest
|
from manifestparser import TestManifest
|
||||||
@@ -253,7 +314,7 @@ class MochitestRunner(MozbuildObject):
|
|||||||
# Automation installs its own stream handler to stdout. Since we want
|
# Automation installs its own stream handler to stdout. Since we want
|
||||||
# all logging to go through us, we just remove their handler.
|
# all logging to go through us, we just remove their handler.
|
||||||
remove_handlers = [l for l in logging.getLogger().handlers
|
remove_handlers = [l for l in logging.getLogger().handlers
|
||||||
if isinstance(l, logging.StreamHandler)]
|
if isinstance(l, logging.StreamHandler)]
|
||||||
for handler in remove_handlers:
|
for handler in remove_handlers:
|
||||||
logging.getLogger().removeHandler(handler)
|
logging.getLogger().removeHandler(handler)
|
||||||
|
|
||||||
@@ -308,7 +369,9 @@ class MochitestRunner(MozbuildObject):
|
|||||||
options.runSlower = slow
|
options.runSlower = slow
|
||||||
options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
|
options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
|
||||||
options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins'))
|
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.chunkByDir = chunk_by_dir
|
||||||
options.totalChunks = total_chunks
|
options.totalChunks = total_chunks
|
||||||
options.thisChunk = this_chunk
|
options.thisChunk = this_chunk
|
||||||
@@ -329,11 +392,14 @@ class MochitestRunner(MozbuildObject):
|
|||||||
options.runByDir = runByDir
|
options.runByDir = runByDir
|
||||||
options.useTestMediaDevices = useTestMediaDevices
|
options.useTestMediaDevices = useTestMediaDevices
|
||||||
if timeout:
|
if timeout:
|
||||||
options.timeout = int(timeout)
|
options.timeout = int(timeout)
|
||||||
|
|
||||||
options.failureFile = failure_file_path
|
options.failureFile = failure_file_path
|
||||||
if install_extension != None:
|
if install_extension is not None:
|
||||||
options.extensionsToInstall = [os.path.join(self.topsrcdir,install_extension)]
|
options.extensionsToInstall = [
|
||||||
|
os.path.join(
|
||||||
|
self.topsrcdir,
|
||||||
|
install_extension)]
|
||||||
|
|
||||||
for k, v in kwargs.iteritems():
|
for k, v in kwargs.iteritems():
|
||||||
setattr(options, k, v)
|
setattr(options, k, v)
|
||||||
@@ -341,18 +407,22 @@ class MochitestRunner(MozbuildObject):
|
|||||||
if test_paths:
|
if test_paths:
|
||||||
resolver = self._spawn(TestResolver)
|
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:
|
if not tests:
|
||||||
print('No tests could be found in the path specified. Please '
|
print('No tests could be found in the path specified. Please '
|
||||||
'specify a path that is a test file or is a directory '
|
'specify a path that is a test file or is a directory '
|
||||||
'containing tests.')
|
'containing tests.')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
manifest = TestManifest()
|
manifest = TestManifest()
|
||||||
manifest.tests.extend(tests)
|
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.closeWhenDone = False
|
||||||
|
|
||||||
options.manifestFile = manifest
|
options.manifestFile = manifest
|
||||||
@@ -364,7 +434,7 @@ class MochitestRunner(MozbuildObject):
|
|||||||
options.debugger = debugger
|
options.debugger = debugger
|
||||||
|
|
||||||
if debugger_args:
|
if debugger_args:
|
||||||
if options.debugger == None:
|
if options.debugger is None:
|
||||||
print("--debugger-args passed, but no debugger specified.")
|
print("--debugger-args passed, but no debugger specified.")
|
||||||
return 1
|
return 1
|
||||||
options.debuggerArgs = debugger_args
|
options.debuggerArgs = debugger_args
|
||||||
@@ -375,14 +445,22 @@ class MochitestRunner(MozbuildObject):
|
|||||||
elif app_override:
|
elif app_override:
|
||||||
options.app = app_override
|
options.app = app_override
|
||||||
if options.gmp_path is None:
|
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()
|
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.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 = {
|
||||||
logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')}
|
key: value for key,
|
||||||
|
value in vars(options).iteritems() if key.startswith('log')}
|
||||||
runner = mochitest.Mochitest(logger_options)
|
runner = mochitest.Mochitest(logger_options)
|
||||||
options = opts.verifyOptions(options, runner)
|
options = opts.verifyOptions(options, runner)
|
||||||
|
|
||||||
@@ -414,12 +492,17 @@ def MochitestCommand(func):
|
|||||||
# (modified) function. Here, we chain decorators onto the passed in
|
# (modified) function. Here, we chain decorators onto the passed in
|
||||||
# function.
|
# function.
|
||||||
|
|
||||||
debugger = CommandArgument('--debugger', '-d', metavar='DEBUGGER',
|
debugger = CommandArgument(
|
||||||
|
'--debugger',
|
||||||
|
'-d',
|
||||||
|
metavar='DEBUGGER',
|
||||||
help='Debugger binary to run test in. Program name or path.')
|
help='Debugger binary to run test in. Program name or path.')
|
||||||
func = debugger(func)
|
func = debugger(func)
|
||||||
|
|
||||||
debugger_args = CommandArgument('--debugger-args',
|
debugger_args = CommandArgument(
|
||||||
metavar='DEBUGGER_ARGS', help='Arguments to pass to the debugger.')
|
'--debugger-args',
|
||||||
|
metavar='DEBUGGER_ARGS',
|
||||||
|
help='Arguments to pass to the debugger.')
|
||||||
func = debugger_args(func)
|
func = debugger_args(func)
|
||||||
|
|
||||||
# Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
|
# Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
|
||||||
@@ -427,219 +510,300 @@ def MochitestCommand(func):
|
|||||||
# code. If we don't pass this, the user will need to periodically type
|
# code. If we don't pass this, the user will need to periodically type
|
||||||
# "continue" to (safely) resume execution. There are ways to implement
|
# "continue" to (safely) resume execution. There are ways to implement
|
||||||
# automatic resuming; see the bug.
|
# 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')
|
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)
|
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.')
|
help='Take screenshots on all test failures. Set $MOZ_UPLOAD_DIR to a directory for storing the screenshots.')
|
||||||
func = screenshot_on_fail(func)
|
func = screenshot_on_fail(func)
|
||||||
|
|
||||||
shuffle = CommandArgument('--shuffle', action='store_true',
|
shuffle = CommandArgument('--shuffle', action='store_true',
|
||||||
help='Shuffle execution order.')
|
help='Shuffle execution order.')
|
||||||
func = shuffle(func)
|
func = shuffle(func)
|
||||||
|
|
||||||
keep_open = CommandArgument('--keep-open', action='store_const',
|
keep_open = CommandArgument(
|
||||||
dest='closure_behaviour', const='open', default='auto',
|
'--keep-open',
|
||||||
|
action='store_const',
|
||||||
|
dest='closure_behaviour',
|
||||||
|
const='open',
|
||||||
|
default='auto',
|
||||||
help='Always keep the browser open after tests complete.')
|
help='Always keep the browser open after tests complete.')
|
||||||
func = keep_open(func)
|
func = keep_open(func)
|
||||||
|
|
||||||
autoclose = CommandArgument('--auto-close', action='store_const',
|
autoclose = CommandArgument(
|
||||||
dest='closure_behaviour', const='close', default='auto',
|
'--auto-close',
|
||||||
|
action='store_const',
|
||||||
|
dest='closure_behaviour',
|
||||||
|
const='close',
|
||||||
|
default='auto',
|
||||||
help='Always close the browser after tests complete.')
|
help='Always close the browser after tests complete.')
|
||||||
func = autoclose(func)
|
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.')
|
help='Run only the tests that failed during the last test run.')
|
||||||
func = rerun(func)
|
func = rerun(func)
|
||||||
|
|
||||||
autorun = CommandArgument('--no-autorun', action='store_true',
|
autorun = CommandArgument(
|
||||||
|
'--no-autorun',
|
||||||
|
action='store_true',
|
||||||
help='Do not starting running tests automatically.')
|
help='Do not starting running tests automatically.')
|
||||||
func = autorun(func)
|
func = autorun(func)
|
||||||
|
|
||||||
repeat = CommandArgument('--repeat', type=int, default=0,
|
repeat = CommandArgument('--repeat', type=int, default=0,
|
||||||
help='Repeat the test the given number of times.')
|
help='Repeat the test the given number of times.')
|
||||||
func = repeat(func)
|
func = repeat(func)
|
||||||
|
|
||||||
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
|
runUntilFailure = CommandArgument(
|
||||||
help='Run tests repeatedly and stops on the first time a test fails. ' \
|
"--run-until-failure",
|
||||||
'Default cap is 30 runs, which can be overwritten ' \
|
action='store_true',
|
||||||
'with the --repeat parameter.')
|
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)
|
func = runUntilFailure(func)
|
||||||
|
|
||||||
slow = CommandArgument('--slow', action='store_true',
|
slow = CommandArgument('--slow', action='store_true',
|
||||||
help='Delay execution between tests.')
|
help='Delay execution between tests.')
|
||||||
func = slow(func)
|
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.')
|
help='Stop running the test sequence at this test.')
|
||||||
func = end_at(func)
|
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.')
|
help='Start running the test sequence at this test.')
|
||||||
func = start_at(func)
|
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.')
|
help='Group tests together in chunks by this many top directories.')
|
||||||
func = chunk_dir(func)
|
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.')
|
help='Total number of chunks to split tests into.')
|
||||||
func = chunk_total(func)
|
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.')
|
help='If running tests by chunks, the number of the chunk to run.')
|
||||||
func = this_chunk(func)
|
func = this_chunk(func)
|
||||||
|
|
||||||
debug_on_failure = CommandArgument('--debug-on-failure', action='store_true',
|
debug_on_failure = CommandArgument(
|
||||||
help='Breaks execution and enters the JS debugger on a test failure. ' \
|
'--debug-on-failure',
|
||||||
'Should be used together with --jsdebugger.')
|
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)
|
func = debug_on_failure(func)
|
||||||
|
|
||||||
setpref = CommandArgument('--setpref', default=[], action='append',
|
setpref = CommandArgument('--setpref', default=[], action='append',
|
||||||
metavar='PREF=VALUE', dest='extraPrefs',
|
metavar='PREF=VALUE', dest='extraPrefs',
|
||||||
help='defines an extra user preference')
|
help='defines an extra user preference')
|
||||||
func = setpref(func)
|
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.')
|
help='Start the browser JS debugger before running the test. Implies --no-autorun.')
|
||||||
func = jsdebugger(func)
|
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.')
|
help='Run tests with electrolysis preferences and test filtering enabled.')
|
||||||
func = e10s(func)
|
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).')
|
help='Run tests with a more strict content sandbox (Windows only).')
|
||||||
func = strict_content_sandbox(func)
|
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.')
|
help='Run tests with nested oop preferences and test filtering enabled.')
|
||||||
func = this_chunk(func)
|
func = this_chunk(func)
|
||||||
|
|
||||||
dmd = CommandArgument('--dmd', action='store_true',
|
dmd = CommandArgument('--dmd', action='store_true',
|
||||||
help='Run tests with DMD active.')
|
help='Run tests with DMD active.')
|
||||||
func = dmd(func)
|
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.')
|
help='Dump an about:memory log after every test.')
|
||||||
func = dumpAboutMemory(func)
|
func = dumpAboutMemory(func)
|
||||||
|
|
||||||
dumpDMD = CommandArgument('--dump-dmd-after-test', action='store_true',
|
dumpDMD = CommandArgument('--dump-dmd-after-test', action='store_true',
|
||||||
help='Dump a DMD log after every test.')
|
help='Dump a DMD log after every test.')
|
||||||
func = dumpDMD(func)
|
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.')
|
help='Specifies the directory in which to place dumped memory reports.')
|
||||||
func = dumpOutputDirectory(func)
|
func = dumpOutputDirectory(func)
|
||||||
|
|
||||||
path = CommandArgument('test_paths', default=None, nargs='*',
|
path = CommandArgument(
|
||||||
|
'test_paths',
|
||||||
|
default=None,
|
||||||
|
nargs='*',
|
||||||
metavar='TEST',
|
metavar='TEST',
|
||||||
help='Test to run. Can be specified as a single file, a ' \
|
help='Test to run. Can be specified as a single file, a '
|
||||||
'directory, or omitted. If omitted, the entire test suite is ' \
|
'directory, or omitted. If omitted, the entire test suite is '
|
||||||
'executed.')
|
'executed.')
|
||||||
func = path(func)
|
func = path(func)
|
||||||
|
|
||||||
install_extension = CommandArgument('--install-extension',
|
install_extension = CommandArgument(
|
||||||
help='Install given extension before running selected tests. ' \
|
'--install-extension',
|
||||||
'Parameter is a path to xpi file.')
|
help='Install given extension before running selected tests. '
|
||||||
|
'Parameter is a path to xpi file.')
|
||||||
func = install_extension(func)
|
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.')
|
help='Do not print test log lines unless a failure occurs.')
|
||||||
func = quiet(func)
|
func = quiet(func)
|
||||||
|
|
||||||
setenv = CommandArgument('--setenv', default=[], action='append',
|
setenv = CommandArgument(
|
||||||
metavar='NAME=VALUE', dest='environment',
|
'--setenv',
|
||||||
help="Sets the given variable in the application's environment")
|
default=[],
|
||||||
|
action='append',
|
||||||
|
metavar='NAME=VALUE',
|
||||||
|
dest='environment',
|
||||||
|
help="Sets the given variable in the application's environment")
|
||||||
func = setenv(func)
|
func = setenv(func)
|
||||||
|
|
||||||
runbydir = CommandArgument('--run-by-dir', default=False,
|
runbydir = CommandArgument(
|
||||||
action='store_true',
|
'--run-by-dir',
|
||||||
dest='runByDir',
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
dest='runByDir',
|
||||||
help='Run each directory in a single browser instance with a fresh profile.')
|
help='Run each directory in a single browser instance with a fresh profile.')
|
||||||
func = runbydir(func)
|
func = runbydir(func)
|
||||||
|
|
||||||
bisect_chunk = CommandArgument('--bisect-chunk', type=str,
|
bisect_chunk = CommandArgument(
|
||||||
dest='bisectChunk',
|
'--bisect-chunk',
|
||||||
|
type=str,
|
||||||
|
dest='bisectChunk',
|
||||||
help='Specify the failing test name to find the previous tests that may be causing the failure.')
|
help='Specify the failing test name to find the previous tests that may be causing the failure.')
|
||||||
func = bisect_chunk(func)
|
func = bisect_chunk(func)
|
||||||
|
|
||||||
test_media = CommandArgument('--use-test-media-devices', default=False,
|
test_media = CommandArgument(
|
||||||
action='store_true',
|
'--use-test-media-devices',
|
||||||
dest='useTestMediaDevices',
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
dest='useTestMediaDevices',
|
||||||
help='Use test media device drivers for media testing.')
|
help='Use test media device drivers for media testing.')
|
||||||
func = test_media(func)
|
func = test_media(func)
|
||||||
|
|
||||||
app_override = CommandArgument('--app-override', default=None, action='store',
|
app_override = CommandArgument(
|
||||||
help="Override the default binary used to run tests with the path you provide, e.g. " \
|
'--app-override',
|
||||||
" --app-override /usr/bin/firefox . " \
|
default=None,
|
||||||
"If you have run ./mach package beforehand, you can specify 'dist' to " \
|
action='store',
|
||||||
"run tests against the distribution bundle's binary.");
|
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)
|
func = app_override(func)
|
||||||
|
|
||||||
timeout = CommandArgument('--timeout', default=None,
|
timeout = CommandArgument(
|
||||||
help='The per-test timeout time in seconds (default: 60 seconds)');
|
'--timeout',
|
||||||
|
default=None,
|
||||||
|
help='The per-test timeout time in seconds (default: 60 seconds)')
|
||||||
func = timeout(func)
|
func = timeout(func)
|
||||||
|
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
def B2GCommand(func):
|
def B2GCommand(func):
|
||||||
"""Decorator that adds shared command arguments to b2g mochitest commands."""
|
"""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')
|
help='Path to busybox binary to install on device')
|
||||||
func = busybox(func)
|
func = busybox(func)
|
||||||
|
|
||||||
logdir = CommandArgument('--logdir', default=None,
|
logdir = CommandArgument('--logdir', default=None,
|
||||||
help='directory to store log files')
|
help='directory to store log files')
|
||||||
func = logdir(func)
|
func = logdir(func)
|
||||||
|
|
||||||
profile = CommandArgument('--profile', default=None,
|
profile = CommandArgument('--profile', default=None,
|
||||||
help='for desktop testing, the path to the \
|
help='for desktop testing, the path to the \
|
||||||
gaia profile to use')
|
gaia profile to use')
|
||||||
func = profile(func)
|
func = profile(func)
|
||||||
|
|
||||||
geckopath = CommandArgument('--gecko-path', default=None,
|
geckopath = CommandArgument('--gecko-path', default=None,
|
||||||
help='the path to a gecko distribution that should \
|
help='the path to a gecko distribution that should \
|
||||||
be installed on the emulator prior to test')
|
be installed on the emulator prior to test')
|
||||||
func = geckopath(func)
|
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')
|
help='Pass --no-window to the emulator')
|
||||||
func = nowindow(func)
|
func = nowindow(func)
|
||||||
|
|
||||||
sdcard = CommandArgument('--sdcard', default="10MB",
|
sdcard = CommandArgument('--sdcard', default="10MB",
|
||||||
help='Define size of sdcard: 1MB, 50MB...etc')
|
help='Define size of sdcard: 1MB, 50MB...etc')
|
||||||
func = sdcard(func)
|
func = sdcard(func)
|
||||||
|
|
||||||
marionette = CommandArgument('--marionette', default=None,
|
marionette = CommandArgument(
|
||||||
|
'--marionette',
|
||||||
|
default=None,
|
||||||
help='host:port to use when connecting to Marionette')
|
help='host:port to use when connecting to Marionette')
|
||||||
func = marionette(func)
|
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.')
|
help='Total number of chunks to split tests into.')
|
||||||
func = chunk_total(func)
|
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.')
|
help='If running tests by chunks, the number of the chunk to run.')
|
||||||
func = this_chunk(func)
|
func = this_chunk(func)
|
||||||
|
|
||||||
path = CommandArgument('test_paths', default=None, nargs='*',
|
path = CommandArgument(
|
||||||
|
'test_paths',
|
||||||
|
default=None,
|
||||||
|
nargs='*',
|
||||||
metavar='TEST',
|
metavar='TEST',
|
||||||
help='Test to run. Can be specified as a single file, a ' \
|
help='Test to run. Can be specified as a single file, a '
|
||||||
'directory, or omitted. If omitted, the entire test suite is ' \
|
'directory, or omitted. If omitted, the entire test suite is '
|
||||||
'executed.')
|
'executed.')
|
||||||
func = path(func)
|
func = path(func)
|
||||||
|
|
||||||
repeat = CommandArgument('--repeat', type=int, default=0,
|
repeat = CommandArgument('--repeat', type=int, default=0,
|
||||||
help='Repeat the test the given number of times.')
|
help='Repeat the test the given number of times.')
|
||||||
func = repeat(func)
|
func = repeat(func)
|
||||||
|
|
||||||
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
|
runUntilFailure = CommandArgument(
|
||||||
help='Run tests repeatedly and stops on the first time a test fails. ' \
|
"--run-until-failure",
|
||||||
'Default cap is 30 runs, which can be overwritten ' \
|
action='store_true',
|
||||||
'with the --repeat parameter.')
|
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)
|
func = runUntilFailure(func)
|
||||||
|
|
||||||
return func
|
return func
|
||||||
@@ -648,34 +812,48 @@ def B2GCommand(func):
|
|||||||
_st_parser = argparse.ArgumentParser()
|
_st_parser = argparse.ArgumentParser()
|
||||||
structured.commandline.add_logging_group(_st_parser)
|
structured.commandline.add_logging_group(_st_parser)
|
||||||
|
|
||||||
|
|
||||||
@CommandProvider
|
@CommandProvider
|
||||||
class MachCommands(MachCommandBase):
|
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).',
|
description='Run a plain mochitest (integration test, plain web page).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_plain(self, test_paths, **kwargs):
|
def run_mochitest_plain(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'plain', **kwargs)
|
return self.run_mochitest(test_paths, 'plain', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-chrome', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'mochitest-chrome',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_firefox],
|
||||||
description='Run a chrome mochitest (integration test with some XUL).',
|
description='Run a chrome mochitest (integration test with some XUL).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_chrome(self, test_paths, **kwargs):
|
def run_mochitest_chrome(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'chrome', **kwargs)
|
return self.run_mochitest(test_paths, 'chrome', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-browser', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'mochitest-browser',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_firefox],
|
||||||
description='Run a mochitest with browser chrome (integration test with a standard browser).',
|
description='Run a mochitest with browser chrome (integration test with a standard browser).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_browser(self, test_paths, **kwargs):
|
def run_mochitest_browser(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'browser', **kwargs)
|
return self.run_mochitest(test_paths, 'browser', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-devtools', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'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).',
|
description='Run a devtools mochitest with browser chrome (integration test with a standard browser with the devtools frame).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
@@ -683,21 +861,24 @@ class MachCommands(MachCommandBase):
|
|||||||
return self.run_mochitest(test_paths, 'devtools', **kwargs)
|
return self.run_mochitest(test_paths, 'devtools', **kwargs)
|
||||||
|
|
||||||
@Command('jetpack-package', category='testing',
|
@Command('jetpack-package', category='testing',
|
||||||
conditions=[conditions.is_firefox],
|
conditions=[conditions.is_firefox],
|
||||||
description='Run a jetpack package test.')
|
description='Run a jetpack package test.')
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_jetpack_package(self, test_paths, **kwargs):
|
def run_mochitest_jetpack_package(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'jetpack-package', **kwargs)
|
return self.run_mochitest(test_paths, 'jetpack-package', **kwargs)
|
||||||
|
|
||||||
@Command('jetpack-addon', category='testing',
|
@Command('jetpack-addon', category='testing',
|
||||||
conditions=[conditions.is_firefox],
|
conditions=[conditions.is_firefox],
|
||||||
description='Run a jetpack addon test.')
|
description='Run a jetpack addon test.')
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_jetpack_addon(self, test_paths, **kwargs):
|
def run_mochitest_jetpack_addon(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs)
|
return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-metro', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'mochitest-metro',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_firefox],
|
||||||
description='Run a mochitest with metro browser chrome (tests for Windows touch interface).',
|
description='Run a mochitest with metro browser chrome (tests for Windows touch interface).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
@@ -705,23 +886,29 @@ class MachCommands(MachCommandBase):
|
|||||||
return self.run_mochitest(test_paths, 'metro', **kwargs)
|
return self.run_mochitest(test_paths, 'metro', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-a11y', category='testing',
|
@Command('mochitest-a11y', category='testing',
|
||||||
conditions=[conditions.is_firefox],
|
conditions=[conditions.is_firefox],
|
||||||
description='Run an a11y mochitest (accessibility tests).',
|
description='Run an a11y mochitest (accessibility tests).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_a11y(self, test_paths, **kwargs):
|
def run_mochitest_a11y(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'a11y', **kwargs)
|
return self.run_mochitest(test_paths, 'a11y', **kwargs)
|
||||||
|
|
||||||
@Command('webapprt-test-chrome', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'webapprt-test-chrome',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_firefox],
|
||||||
description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).',
|
description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
def run_mochitest_webapprt_chrome(self, test_paths, **kwargs):
|
def run_mochitest_webapprt_chrome(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs)
|
return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs)
|
||||||
|
|
||||||
@Command('webapprt-test-content', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_firefox],
|
'webapprt-test-content',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_firefox],
|
||||||
description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).',
|
description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
@@ -729,14 +916,14 @@ class MachCommands(MachCommandBase):
|
|||||||
return self.run_mochitest(test_paths, 'webapprt-content', **kwargs)
|
return self.run_mochitest(test_paths, 'webapprt-content', **kwargs)
|
||||||
|
|
||||||
@Command('mochitest', category='testing',
|
@Command('mochitest', category='testing',
|
||||||
conditions=[conditions.is_firefox],
|
conditions=[conditions.is_firefox],
|
||||||
description='Run any flavor of mochitest (integration test).',
|
description='Run any flavor of mochitest (integration test).',
|
||||||
parser=_st_parser)
|
parser=_st_parser)
|
||||||
@MochitestCommand
|
@MochitestCommand
|
||||||
@CommandArgument('-f', '--flavor', choices=FLAVORS.keys(),
|
@CommandArgument('-f', '--flavor', choices=FLAVORS.keys(),
|
||||||
help='Only run tests of this flavor.')
|
help='Only run tests of this flavor.')
|
||||||
def run_mochitest_general(self, test_paths, flavor=None, test_objects=None,
|
def run_mochitest_general(self, test_paths, flavor=None, test_objects=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self._preruntest()
|
self._preruntest()
|
||||||
|
|
||||||
from mozbuild.testing import TestResolver
|
from mozbuild.testing import TestResolver
|
||||||
@@ -746,7 +933,7 @@ class MachCommands(MachCommandBase):
|
|||||||
else:
|
else:
|
||||||
resolver = self._spawn(TestResolver)
|
resolver = self._spawn(TestResolver)
|
||||||
tests = list(resolver.resolve_tests(paths=test_paths,
|
tests = list(resolver.resolve_tests(paths=test_paths,
|
||||||
cwd=self._mach_context.cwd))
|
cwd=self._mach_context.cwd))
|
||||||
|
|
||||||
# Our current approach is to group the tests by suite and then perform
|
# Our current approach is to group the tests by suite and then perform
|
||||||
# an invocation for each suite. Ideally, this would be done
|
# an invocation for each suite. Ideally, this would be done
|
||||||
@@ -773,8 +960,11 @@ class MachCommands(MachCommandBase):
|
|||||||
mochitest = self._spawn(MochitestRunner)
|
mochitest = self._spawn(MochitestRunner)
|
||||||
overall = None
|
overall = None
|
||||||
for suite, tests in sorted(suites.items()):
|
for suite, tests in sorted(suites.items()):
|
||||||
result = mochitest.run_desktop_test(self._mach_context,
|
result = mochitest.run_desktop_test(
|
||||||
test_paths=[test['file_relpath'] for test in tests], suite=suite,
|
self._mach_context,
|
||||||
|
test_paths=[
|
||||||
|
test['file_relpath'] for test in tests],
|
||||||
|
suite=suite,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
if result:
|
if result:
|
||||||
overall = result
|
overall = result
|
||||||
@@ -794,8 +984,11 @@ class MachCommands(MachCommandBase):
|
|||||||
|
|
||||||
mochitest = self._spawn(MochitestRunner)
|
mochitest = self._spawn(MochitestRunner)
|
||||||
|
|
||||||
return mochitest.run_desktop_test(self._mach_context,
|
return mochitest.run_desktop_test(
|
||||||
test_paths=test_paths, suite=flavor, **kwargs)
|
self._mach_context,
|
||||||
|
test_paths=test_paths,
|
||||||
|
suite=flavor,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
# TODO For now b2g commands will only work with the emulator,
|
# TODO For now b2g commands will only work with the emulator,
|
||||||
@@ -810,27 +1003,39 @@ def is_emulator(cls):
|
|||||||
|
|
||||||
@CommandProvider
|
@CommandProvider
|
||||||
class B2GCommands(MachCommandBase):
|
class B2GCommands(MachCommandBase):
|
||||||
|
|
||||||
"""So far these are only mochitest plain. They are
|
"""So far these are only mochitest plain. They are
|
||||||
implemented separately because their command lines
|
implemented separately because their command lines
|
||||||
are completely different.
|
are completely different.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
MachCommandBase.__init__(self, context)
|
MachCommandBase.__init__(self, context)
|
||||||
|
|
||||||
for attr in ('b2g_home', 'xre_path', 'device_name', 'get_build_var'):
|
for attr in ('b2g_home', 'xre_path', 'device_name', 'get_build_var'):
|
||||||
setattr(self, attr, getattr(context, attr, None))
|
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).',
|
description='Run a remote mochitest (integration test for fennec/android).',
|
||||||
conditions=[conditions.is_b2g, is_emulator])
|
conditions=[
|
||||||
|
conditions.is_b2g,
|
||||||
|
is_emulator])
|
||||||
@B2GCommand
|
@B2GCommand
|
||||||
def run_mochitest_remote(self, test_paths, **kwargs):
|
def run_mochitest_remote(self, test_paths, **kwargs):
|
||||||
if self.get_build_var:
|
if self.get_build_var:
|
||||||
host_webapps_dir = os.path.join(self.get_build_var('TARGET_OUT_DATA'),
|
host_webapps_dir = os.path.join(
|
||||||
'local', 'webapps')
|
self.get_build_var('TARGET_OUT_DATA'),
|
||||||
if not os.path.isdir(os.path.join(host_webapps_dir,
|
'local',
|
||||||
'test-container.gaiamobile.org')):
|
'webapps')
|
||||||
print(ENG_BUILD_REQUIRED % ('mochitest-remote', host_webapps_dir))
|
if not os.path.isdir(
|
||||||
|
os.path.join(
|
||||||
|
host_webapps_dir,
|
||||||
|
'test-container.gaiamobile.org')):
|
||||||
|
print(
|
||||||
|
ENG_BUILD_REQUIRED %
|
||||||
|
('mochitest-remote', host_webapps_dir))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
from mozbuild.controller.building import BuildDriver
|
from mozbuild.controller.building import BuildDriver
|
||||||
@@ -847,22 +1052,29 @@ class B2GCommands(MachCommandBase):
|
|||||||
driver.install_tests(remove=False)
|
driver.install_tests(remove=False)
|
||||||
|
|
||||||
mochitest = self._spawn(MochitestRunner)
|
mochitest = self._spawn(MochitestRunner)
|
||||||
return mochitest.run_b2g_test(b2g_home=self.b2g_home,
|
return mochitest.run_b2g_test(
|
||||||
xre_path=self.xre_path, test_paths=test_paths, **kwargs)
|
b2g_home=self.b2g_home,
|
||||||
|
xre_path=self.xre_path,
|
||||||
|
test_paths=test_paths,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
@Command('mochitest-chrome-remote', category='testing',
|
@Command('mochitest-chrome-remote', category='testing',
|
||||||
description='Run a remote mochitest-chrome.',
|
description='Run a remote mochitest-chrome.',
|
||||||
conditions=[conditions.is_b2g, is_emulator])
|
conditions=[conditions.is_b2g, is_emulator])
|
||||||
@B2GCommand
|
@B2GCommand
|
||||||
def run_mochitest_chrome_remote(self, test_paths, **kwargs):
|
def run_mochitest_chrome_remote(self, test_paths, **kwargs):
|
||||||
return self.run_mochitest_remote(test_paths, chrome=True, **kwargs)
|
return self.run_mochitest_remote(test_paths, chrome=True, **kwargs)
|
||||||
|
|
||||||
@Command('mochitest-b2g-desktop', category='testing',
|
@Command(
|
||||||
conditions=[conditions.is_b2g_desktop],
|
'mochitest-b2g-desktop',
|
||||||
|
category='testing',
|
||||||
|
conditions=[
|
||||||
|
conditions.is_b2g_desktop],
|
||||||
description='Run a b2g desktop mochitest (same as mochitest-plain but for b2g desktop).')
|
description='Run a b2g desktop mochitest (same as mochitest-plain but for b2g desktop).')
|
||||||
@B2GCommand
|
@B2GCommand
|
||||||
def run_mochitest_b2g_desktop(self, test_paths, **kwargs):
|
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']):
|
if not kwargs['profile'] or not os.path.isdir(kwargs['profile']):
|
||||||
print(GAIA_PROFILE_NOT_FOUND % 'mochitest-b2g-desktop')
|
print(GAIA_PROFILE_NOT_FOUND % 'mochitest-b2g-desktop')
|
||||||
return 1
|
return 1
|
||||||
@@ -886,31 +1098,52 @@ class B2GCommands(MachCommandBase):
|
|||||||
|
|
||||||
@CommandProvider
|
@CommandProvider
|
||||||
class AndroidCommands(MachCommandBase):
|
class AndroidCommands(MachCommandBase):
|
||||||
|
|
||||||
@Command('robocop', category='testing',
|
@Command('robocop', category='testing',
|
||||||
conditions=[conditions.is_android],
|
conditions=[conditions.is_android],
|
||||||
description='Run a Robocop test.')
|
description='Run a Robocop test.')
|
||||||
@CommandArgument('test_path', default=None, nargs='?',
|
@CommandArgument(
|
||||||
|
'test_path',
|
||||||
|
default=None,
|
||||||
|
nargs='?',
|
||||||
metavar='TEST',
|
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.')
|
'or omitted. If omitted, the entire test suite is executed.')
|
||||||
def run_robocop(self, test_path):
|
def run_robocop(self, test_path):
|
||||||
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
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
|
import imp
|
||||||
path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
|
path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
|
||||||
with open(path, 'r') as fh:
|
with open(path, 'r') as fh:
|
||||||
imp.load_module('runtestsremote', fh, path,
|
imp.load_module('runtestsremote', fh, path,
|
||||||
('.py', 'r', imp.PY_SOURCE))
|
('.py', 'r', imp.PY_SOURCE))
|
||||||
import runtestsremote
|
import runtestsremote
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
'--xre-path=' + os.environ.get('MOZ_HOST_BIN'),
|
'--xre-path=' +
|
||||||
|
os.environ.get('MOZ_HOST_BIN'),
|
||||||
'--dm_trans=adb',
|
'--dm_trans=adb',
|
||||||
'--deviceIP=',
|
'--deviceIP=',
|
||||||
'--console-level=INFO',
|
'--console-level=INFO',
|
||||||
'--app=' + self.substs['ANDROID_PACKAGE_NAME'],
|
'--app=' +
|
||||||
'--robocop-apk=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop-debug.apk'),
|
self.substs['ANDROID_PACKAGE_NAME'],
|
||||||
'--robocop-ini=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop.ini'),
|
'--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=-',
|
'--log-mach=-',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -23,14 +23,15 @@ from mozprofile import Profile, Preferences
|
|||||||
from mozlog import structured
|
from mozlog import structured
|
||||||
import mozinfo
|
import mozinfo
|
||||||
|
|
||||||
|
|
||||||
class B2GMochitest(MochitestUtilsMixin):
|
class B2GMochitest(MochitestUtilsMixin):
|
||||||
marionette = None
|
marionette = None
|
||||||
|
|
||||||
def __init__(self, marionette_args,
|
def __init__(self, marionette_args,
|
||||||
logger_options,
|
logger_options,
|
||||||
out_of_process=True,
|
out_of_process=True,
|
||||||
profile_data_dir=None,
|
profile_data_dir=None,
|
||||||
locations=os.path.join(here, 'server-locations.txt')):
|
locations=os.path.join(here, 'server-locations.txt')):
|
||||||
super(B2GMochitest, self).__init__(logger_options)
|
super(B2GMochitest, self).__init__(logger_options)
|
||||||
self.marionette_args = marionette_args
|
self.marionette_args = marionette_args
|
||||||
self.out_of_process = out_of_process
|
self.out_of_process = out_of_process
|
||||||
@@ -43,10 +44,14 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
self.remote_chrome_test_dir = None
|
self.remote_chrome_test_dir = None
|
||||||
|
|
||||||
if profile_data_dir:
|
if profile_data_dir:
|
||||||
self.preferences = [os.path.join(profile_data_dir, f)
|
self.preferences = [
|
||||||
for f in os.listdir(profile_data_dir) if f.startswith('pref')]
|
os.path.join(
|
||||||
self.webapps = [os.path.join(profile_data_dir, f)
|
profile_data_dir,
|
||||||
for f in os.listdir(profile_data_dir) if f.startswith('webapp')]
|
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
|
# mozinfo is populated by the parent class
|
||||||
if mozinfo.info['debug']:
|
if mozinfo.info['debug']:
|
||||||
@@ -68,7 +73,12 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
|
|
||||||
def buildTestPath(self, options, testsToFilter=None):
|
def buildTestPath(self, options, testsToFilter=None):
|
||||||
if options.manifestFile != 'tests.json':
|
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)
|
return self.buildTestURL(options)
|
||||||
|
|
||||||
def build_profile(self, options):
|
def build_profile(self, options):
|
||||||
@@ -85,8 +95,11 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
prefs[thispref[0]] = thispref[1]
|
prefs[thispref[0]] = thispref[1]
|
||||||
|
|
||||||
# interpolate the preferences
|
# interpolate the preferences
|
||||||
interpolation = { "server": "%s:%s" % (options.webServer, options.httpPort),
|
interpolation = {
|
||||||
"OOP": "true" if self.out_of_process else "false" }
|
"server": "%s:%s" %
|
||||||
|
(options.webServer,
|
||||||
|
options.httpPort),
|
||||||
|
"OOP": "true" if self.out_of_process else "false"}
|
||||||
prefs = json.loads(json.dumps(prefs) % interpolation)
|
prefs = json.loads(json.dumps(prefs) % interpolation)
|
||||||
for pref in prefs:
|
for pref in prefs:
|
||||||
prefs[pref] = Preferences.cast(prefs[pref])
|
prefs[pref] = Preferences.cast(prefs[pref])
|
||||||
@@ -138,7 +151,8 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
if message['action'] == 'test_start':
|
if message['action'] == 'test_start':
|
||||||
self.runner.last_test = message['test']
|
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,
|
process_args = {'processOutputLine': on_output,
|
||||||
'stream': None}
|
'stream': None}
|
||||||
self.marionette_args['process_args'] = process_args
|
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,
|
self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
|
||||||
'log', 'mochitest.log')
|
'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)
|
self.app_ctx.dm.mkDirs(self.remote_log)
|
||||||
|
|
||||||
if options.chrome:
|
if options.chrome:
|
||||||
# Update chrome manifest file in profile with correct path.
|
# Update chrome manifest file in profile with correct path.
|
||||||
self.writeChromeManifest(options)
|
self.writeChromeManifest(options)
|
||||||
|
|
||||||
self.leak_report_file = posixpath.join(self.app_ctx.remote_test_root,
|
self.leak_report_file = posixpath.join(
|
||||||
'log', 'runtests_leaks.log')
|
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
|
# We don't want to copy the host env onto the device, so pass in an
|
||||||
# empty env.
|
# empty env.
|
||||||
self.browserEnv = self.buildBrowserEnv(options, env={})
|
self.browserEnv = self.buildBrowserEnv(options, env={})
|
||||||
|
|
||||||
# B2G emulator debug tests still make external connections, so don't
|
# B2G emulator debug tests still make external connections, so don't
|
||||||
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug 1039019).
|
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug
|
||||||
if mozinfo.info['debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
|
# 1039019).
|
||||||
|
if mozinfo.info[
|
||||||
|
'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
|
||||||
del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
|
del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
|
||||||
self.runner.env.update(self.browserEnv)
|
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.wifi)
|
||||||
self.test_script_args.append(options.chrome)
|
self.test_script_args.append(options.chrome)
|
||||||
|
|
||||||
|
|
||||||
self.runner.start(outputTimeout=timeout)
|
self.runner.start(outputTimeout=timeout)
|
||||||
|
|
||||||
self.marionette.wait_for_port()
|
self.marionette.wait_for_port()
|
||||||
@@ -185,7 +204,8 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
|
|
||||||
# Disable offline status management (bug 777145), otherwise the network
|
# Disable offline status management (bug 777145), otherwise the network
|
||||||
# will be 'offline' when the mochitests start. Presumably, 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("""
|
self.marionette.execute_script("""
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
Services.io.manageOfflineStatus = false;
|
Services.io.manageOfflineStatus = false;
|
||||||
@@ -198,16 +218,20 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
local = super(B2GMochitest, self).getChromeTestDir(options)
|
local = super(B2GMochitest, self).getChromeTestDir(options)
|
||||||
local = os.path.join(local, "chrome")
|
local = os.path.join(local, "chrome")
|
||||||
remote = self.remote_chrome_test_dir
|
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)
|
self.app_ctx.dm.pushDir(local, remote)
|
||||||
|
|
||||||
if os.path.isfile(self.test_script):
|
if os.path.isfile(self.test_script):
|
||||||
with open(self.test_script, 'r') as script:
|
with open(self.test_script, 'r') as script:
|
||||||
self.marionette.execute_script(script.read(),
|
self.marionette.execute_script(
|
||||||
script_args=self.test_script_args)
|
script.read(),
|
||||||
|
script_args=self.test_script_args)
|
||||||
else:
|
else:
|
||||||
self.marionette.execute_script(self.test_script,
|
self.marionette.execute_script(
|
||||||
script_args=self.test_script_args)
|
self.test_script,
|
||||||
|
script_args=self.test_script_args)
|
||||||
status = self.runner.wait()
|
status = self.runner.wait()
|
||||||
|
|
||||||
if status is None:
|
if status is None:
|
||||||
@@ -215,16 +239,19 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
status = 124
|
status = 124
|
||||||
|
|
||||||
local_leak_file = tempfile.NamedTemporaryFile()
|
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)
|
self.app_ctx.dm.removeFile(self.leak_report_file)
|
||||||
|
|
||||||
processLeakLog(local_leak_file.name, options)
|
processLeakLog(local_leak_file.name, options)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.log.info("runtests.py | Received keyboard interrupt.\n");
|
self.log.info("runtests.py | Received keyboard interrupt.\n")
|
||||||
status = -1
|
status = -1
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
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'):
|
if hasattr(self, 'runner'):
|
||||||
self.runner.check_for_crashes()
|
self.runner.check_for_crashes()
|
||||||
status = 1
|
status = 1
|
||||||
@@ -249,7 +276,9 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
# is defined; the correct directory will be returned later, over-
|
# is defined; the correct directory will be returned later, over-
|
||||||
# writing the dummy.
|
# writing the dummy.
|
||||||
if hasattr(self, 'app_ctx'):
|
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 self.remote_chrome_test_dir
|
||||||
return 'dummy-chrome-test-dir'
|
return 'dummy-chrome-test-dir'
|
||||||
|
|
||||||
@@ -257,9 +286,20 @@ class B2GMochitest(MochitestUtilsMixin):
|
|||||||
class B2GDeviceMochitest(B2GMochitest, Mochitest):
|
class B2GDeviceMochitest(B2GMochitest, Mochitest):
|
||||||
remote_log = None
|
remote_log = None
|
||||||
|
|
||||||
def __init__(self, marionette_args, logger_options, profile_data_dir,
|
def __init__(
|
||||||
local_binary_dir, remote_test_root=None, remote_log_file=None):
|
self,
|
||||||
B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=True, profile_data_dir=profile_data_dir)
|
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_log = None
|
||||||
self.local_binary_dir = local_binary_dir
|
self.local_binary_dir = local_binary_dir
|
||||||
|
|
||||||
@@ -314,7 +354,12 @@ class B2GDeviceMochitest(B2GMochitest, Mochitest):
|
|||||||
class B2GDesktopMochitest(B2GMochitest, Mochitest):
|
class B2GDesktopMochitest(B2GMochitest, Mochitest):
|
||||||
|
|
||||||
def __init__(self, marionette_args, logger_options, profile_data_dir):
|
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)
|
Mochitest.__init__(self, logger_options)
|
||||||
self.certdbNew = True
|
self.certdbNew = True
|
||||||
|
|
||||||
@@ -347,7 +392,10 @@ class B2GDesktopMochitest(B2GMochitest, Mochitest):
|
|||||||
self.setup_common_options(options)
|
self.setup_common_options(options)
|
||||||
|
|
||||||
# Copy the extensions to the B2G bundles dir.
|
# 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),
|
bundlesDir = os.path.join(os.path.dirname(options.app),
|
||||||
'distribution', 'bundles')
|
'distribution', 'bundles')
|
||||||
|
|
||||||
@@ -378,15 +426,19 @@ def run_remote_mochitests(parser, options):
|
|||||||
marionette_args['port'] = int(port)
|
marionette_args['port'] = int(port)
|
||||||
|
|
||||||
options = parser.verifyRemoteOptions(options)
|
options = parser.verifyRemoteOptions(options)
|
||||||
if (options == None):
|
if (options is None):
|
||||||
print "ERROR: Invalid options specified, use --help for a list of valid options"
|
print "ERROR: Invalid options specified, use --help for a list of valid options"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
mochitest = B2GDeviceMochitest(marionette_args, options, options.profile_data_dir,
|
mochitest = B2GDeviceMochitest(
|
||||||
options.xrePath, remote_log_file=options.remoteLogFile)
|
marionette_args,
|
||||||
|
options,
|
||||||
|
options.profile_data_dir,
|
||||||
|
options.xrePath,
|
||||||
|
remote_log_file=options.remoteLogFile)
|
||||||
|
|
||||||
options = parser.verifyOptions(options, mochitest)
|
options = parser.verifyOptions(options, mochitest)
|
||||||
if (options == None):
|
if (options is None):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
retVal = 1
|
retVal = 1
|
||||||
@@ -407,6 +459,7 @@ def run_remote_mochitests(parser, options):
|
|||||||
|
|
||||||
sys.exit(retVal)
|
sys.exit(retVal)
|
||||||
|
|
||||||
|
|
||||||
def run_desktop_mochitests(parser, options):
|
def run_desktop_mochitests(parser, options):
|
||||||
# create our Marionette instance
|
# create our Marionette instance
|
||||||
marionette_args = {}
|
marionette_args = {}
|
||||||
@@ -420,9 +473,12 @@ def run_desktop_mochitests(parser, options):
|
|||||||
if os.path.isfile("%s-bin" % options.app):
|
if os.path.isfile("%s-bin" % options.app):
|
||||||
options.app = "%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)
|
options = MochitestOptions.verifyOptions(parser, options, mochitest)
|
||||||
if options == None:
|
if options is None:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if options.desktop and not options.profile:
|
if options.desktop and not options.profile:
|
||||||
@@ -435,6 +491,7 @@ def run_desktop_mochitests(parser, options):
|
|||||||
|
|
||||||
sys.exit(retVal)
|
sys.exit(retVal)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = B2GOptions()
|
parser = B2GOptions()
|
||||||
structured.commandline.add_logging_group(parser)
|
structured.commandline.add_logging_group(parser)
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import traceback
|
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 automation import Automation
|
||||||
from remoteautomation import RemoteAutomation, fennecLogcatFilters
|
from remoteautomation import RemoteAutomation, fennecLogcatFilters
|
||||||
@@ -29,6 +32,7 @@ import moznetwork
|
|||||||
|
|
||||||
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
|
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
|
||||||
|
|
||||||
|
|
||||||
class RemoteOptions(MochitestOptions):
|
class RemoteOptions(MochitestOptions):
|
||||||
|
|
||||||
def __init__(self, automation, **kwargs):
|
def __init__(self, automation, **kwargs):
|
||||||
@@ -36,84 +40,117 @@ class RemoteOptions(MochitestOptions):
|
|||||||
self._automation = automation or Automation()
|
self._automation = automation or Automation()
|
||||||
MochitestOptions.__init__(self)
|
MochitestOptions.__init__(self)
|
||||||
|
|
||||||
self.add_option("--remote-app-path", action="store",
|
self.add_option(
|
||||||
type = "string", dest = "remoteAppPath",
|
"--remote-app-path",
|
||||||
help = "Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both")
|
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
|
defaults["remoteAppPath"] = None
|
||||||
|
|
||||||
self.add_option("--deviceIP", action="store",
|
self.add_option("--deviceIP", action="store",
|
||||||
type = "string", dest = "deviceIP",
|
type="string", dest="deviceIP",
|
||||||
help = "ip address of remote device to test")
|
help="ip address of remote device to test")
|
||||||
defaults["deviceIP"] = None
|
defaults["deviceIP"] = None
|
||||||
|
|
||||||
self.add_option("--deviceSerial", action="store",
|
self.add_option("--deviceSerial", action="store",
|
||||||
type = "string", dest = "deviceSerial",
|
type="string", dest="deviceSerial",
|
||||||
help = "ip address of remote device to test")
|
help="ip address of remote device to test")
|
||||||
defaults["deviceSerial"] = None
|
defaults["deviceSerial"] = None
|
||||||
|
|
||||||
self.add_option("--dm_trans", action="store",
|
self.add_option(
|
||||||
type = "string", dest = "dm_trans",
|
"--dm_trans",
|
||||||
help = "the transport to use to communicate with device: [adb|sut]; default=sut")
|
action="store",
|
||||||
|
type="string",
|
||||||
|
dest="dm_trans",
|
||||||
|
help="the transport to use to communicate with device: [adb|sut]; default=sut")
|
||||||
defaults["dm_trans"] = "sut"
|
defaults["dm_trans"] = "sut"
|
||||||
|
|
||||||
self.add_option("--devicePort", action="store",
|
self.add_option("--devicePort", action="store",
|
||||||
type = "string", dest = "devicePort",
|
type="string", dest="devicePort",
|
||||||
help = "port of remote device to test")
|
help="port of remote device to test")
|
||||||
defaults["devicePort"] = 20701
|
defaults["devicePort"] = 20701
|
||||||
|
|
||||||
self.add_option("--remote-product-name", action="store",
|
self.add_option(
|
||||||
type = "string", dest = "remoteProductName",
|
"--remote-product-name",
|
||||||
help = "The executable's name of remote product to test - either fennec or firefox, defaults to fennec")
|
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"
|
defaults["remoteProductName"] = "fennec"
|
||||||
|
|
||||||
self.add_option("--remote-logfile", action="store",
|
self.add_option(
|
||||||
type = "string", dest = "remoteLogFile",
|
"--remote-logfile",
|
||||||
help = "Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.")
|
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
|
defaults["remoteLogFile"] = None
|
||||||
|
|
||||||
self.add_option("--remote-webserver", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "remoteWebServer",
|
"--remote-webserver",
|
||||||
help = "ip address where the remote web server is hosted at")
|
action="store",
|
||||||
|
type="string",
|
||||||
|
dest="remoteWebServer",
|
||||||
|
help="ip address where the remote web server is hosted at")
|
||||||
defaults["remoteWebServer"] = None
|
defaults["remoteWebServer"] = None
|
||||||
|
|
||||||
self.add_option("--http-port", action = "store",
|
self.add_option("--http-port", action="store",
|
||||||
type = "string", dest = "httpPort",
|
type="string", dest="httpPort",
|
||||||
help = "http port of the remote web server")
|
help="http port of the remote web server")
|
||||||
defaults["httpPort"] = automation.DEFAULT_HTTP_PORT
|
defaults["httpPort"] = automation.DEFAULT_HTTP_PORT
|
||||||
|
|
||||||
self.add_option("--ssl-port", action = "store",
|
self.add_option("--ssl-port", action="store",
|
||||||
type = "string", dest = "sslPort",
|
type="string", dest="sslPort",
|
||||||
help = "ssl port of the remote web server")
|
help="ssl port of the remote web server")
|
||||||
defaults["sslPort"] = automation.DEFAULT_SSL_PORT
|
defaults["sslPort"] = automation.DEFAULT_SSL_PORT
|
||||||
|
|
||||||
self.add_option("--robocop-ini", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "robocopIni",
|
"--robocop-ini",
|
||||||
help = "name of the .ini file containing the list of tests to run")
|
action="store",
|
||||||
|
type="string",
|
||||||
|
dest="robocopIni",
|
||||||
|
help="name of the .ini file containing the list of tests to run")
|
||||||
defaults["robocopIni"] = ""
|
defaults["robocopIni"] = ""
|
||||||
|
|
||||||
self.add_option("--robocop", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "robocop",
|
"--robocop",
|
||||||
help = "name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
|
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"] = ""
|
defaults["robocop"] = ""
|
||||||
|
|
||||||
self.add_option("--robocop-apk", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "robocopApk",
|
"--robocop-apk",
|
||||||
help = "name of the Robocop APK to use for ADB test running")
|
action="store",
|
||||||
|
type="string",
|
||||||
|
dest="robocopApk",
|
||||||
|
help="name of the Robocop APK to use for ADB test running")
|
||||||
defaults["robocopApk"] = ""
|
defaults["robocopApk"] = ""
|
||||||
|
|
||||||
self.add_option("--robocop-path", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "robocopPath",
|
"--robocop-path",
|
||||||
help = "Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
|
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"] = ""
|
defaults["robocopPath"] = ""
|
||||||
|
|
||||||
self.add_option("--robocop-ids", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "robocopIds",
|
"--robocop-ids",
|
||||||
help = "name of the file containing the view ID map (fennec_ids.txt)")
|
action="store",
|
||||||
|
type="string",
|
||||||
|
dest="robocopIds",
|
||||||
|
help="name of the file containing the view ID map (fennec_ids.txt)")
|
||||||
defaults["robocopIds"] = ""
|
defaults["robocopIds"] = ""
|
||||||
|
|
||||||
self.add_option("--remoteTestRoot", action = "store",
|
self.add_option(
|
||||||
type = "string", dest = "remoteTestRoot",
|
"--remoteTestRoot",
|
||||||
help = "remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
|
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["remoteTestRoot"] = None
|
||||||
|
|
||||||
defaults["logFile"] = "mochitest.log"
|
defaults["logFile"] = "mochitest.log"
|
||||||
@@ -131,38 +168,43 @@ class RemoteOptions(MochitestOptions):
|
|||||||
if not options.remoteTestRoot:
|
if not options.remoteTestRoot:
|
||||||
options.remoteTestRoot = automation._devicemanager.deviceRoot
|
options.remoteTestRoot = automation._devicemanager.deviceRoot
|
||||||
|
|
||||||
if options.remoteWebServer == None:
|
if options.remoteWebServer is None:
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
options.remoteWebServer = moznetwork.get_ip()
|
options.remoteWebServer = moznetwork.get_ip()
|
||||||
else:
|
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
|
return None
|
||||||
|
|
||||||
options.webServer = options.remoteWebServer
|
options.webServer = options.remoteWebServer
|
||||||
|
|
||||||
if (options.dm_trans == 'sut' and options.deviceIP == None):
|
if (options.dm_trans == 'sut' and options.deviceIP is None):
|
||||||
options_logger.error("If --dm_trans = sut, you must provide a device IP")
|
options_logger.error(
|
||||||
|
"If --dm_trans = sut, you must provide a device IP")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if (options.remoteLogFile == None):
|
if (options.remoteLogFile is None):
|
||||||
options.remoteLogFile = options.remoteTestRoot + '/logs/mochitest.log'
|
options.remoteLogFile = options.remoteTestRoot + \
|
||||||
|
'/logs/mochitest.log'
|
||||||
|
|
||||||
if (options.remoteLogFile.count('/') < 1):
|
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
|
# remoteAppPath or app must be specified to find the product to launch
|
||||||
if (options.remoteAppPath and options.app):
|
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
|
return None
|
||||||
elif (options.remoteAppPath):
|
elif (options.remoteAppPath):
|
||||||
options.app = options.remoteTestRoot + "/" + options.remoteAppPath
|
options.app = options.remoteTestRoot + "/" + options.remoteAppPath
|
||||||
elif (options.app == None):
|
elif (options.app is None):
|
||||||
# Neither remoteAppPath nor app are set -- error
|
# Neither remoteAppPath nor app are set -- error
|
||||||
options_logger.error("You must specify either appPath or app")
|
options_logger.error("You must specify either appPath or app")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Only reset the xrePath if it wasn't provided
|
# Only reset the xrePath if it wasn't provided
|
||||||
if (options.xrePath == None):
|
if (options.xrePath is None):
|
||||||
options.xrePath = options.utilityPath
|
options.xrePath = options.utilityPath
|
||||||
|
|
||||||
if (options.pidFile != ""):
|
if (options.pidFile != ""):
|
||||||
@@ -173,38 +215,49 @@ class RemoteOptions(MochitestOptions):
|
|||||||
# Robocop specific deprecated options.
|
# Robocop specific deprecated options.
|
||||||
if options.robocop:
|
if options.robocop:
|
||||||
if options.robocopIni:
|
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
|
return None
|
||||||
options.robocopIni = options.robocop
|
options.robocopIni = options.robocop
|
||||||
del options.robocop
|
del options.robocop
|
||||||
|
|
||||||
if options.robocopPath:
|
if options.robocopPath:
|
||||||
if options.robocopApk:
|
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
|
return None
|
||||||
options.robocopApk = os.path.join(options.robocopPath, 'robocop.apk')
|
options.robocopApk = os.path.join(
|
||||||
|
options.robocopPath,
|
||||||
|
'robocop.apk')
|
||||||
del options.robocopPath
|
del options.robocopPath
|
||||||
|
|
||||||
# Robocop specific options
|
# Robocop specific options
|
||||||
if options.robocopIni != "":
|
if options.robocopIni != "":
|
||||||
if not os.path.exists(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
|
return None
|
||||||
options.robocopIni = os.path.abspath(options.robocopIni)
|
options.robocopIni = os.path.abspath(options.robocopIni)
|
||||||
|
|
||||||
if options.robocopApk != "":
|
if options.robocopApk != "":
|
||||||
if not os.path.exists(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
|
return None
|
||||||
options.robocopApk = os.path.abspath(options.robocopApk)
|
options.robocopApk = os.path.abspath(options.robocopApk)
|
||||||
|
|
||||||
if options.robocopIds != "":
|
if options.robocopIds != "":
|
||||||
if not os.path.exists(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
|
return None
|
||||||
options.robocopIds = os.path.abspath(options.robocopIds)
|
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
|
options.remoteappname = options.app
|
||||||
return options
|
return options
|
||||||
|
|
||||||
@@ -226,6 +279,7 @@ class RemoteOptions(MochitestOptions):
|
|||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
class MochiRemote(Mochitest):
|
class MochiRemote(Mochitest):
|
||||||
|
|
||||||
_automation = None
|
_automation = None
|
||||||
@@ -247,20 +301,24 @@ class MochiRemote(Mochitest):
|
|||||||
self._automation.deleteTombstones()
|
self._automation.deleteTombstones()
|
||||||
self.certdbNew = True
|
self.certdbNew = True
|
||||||
self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
|
self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
|
||||||
self._dm.removeDir(self.remoteNSPR);
|
self._dm.removeDir(self.remoteNSPR)
|
||||||
self._dm.mkDir(self.remoteNSPR);
|
self._dm.mkDir(self.remoteNSPR)
|
||||||
self.remoteChromeTestDir = os.path.join(options.remoteTestRoot, "chrome")
|
self.remoteChromeTestDir = os.path.join(
|
||||||
self._dm.removeDir(self.remoteChromeTestDir);
|
options.remoteTestRoot,
|
||||||
self._dm.mkDir(self.remoteChromeTestDir);
|
"chrome")
|
||||||
|
self._dm.removeDir(self.remoteChromeTestDir)
|
||||||
|
self._dm.mkDir(self.remoteChromeTestDir)
|
||||||
|
|
||||||
def cleanup(self, options):
|
def cleanup(self, options):
|
||||||
if self._dm.fileExists(self.remoteLog):
|
if self._dm.fileExists(self.remoteLog):
|
||||||
self._dm.getFile(self.remoteLog, self.localLog)
|
self._dm.getFile(self.remoteLog, self.localLog)
|
||||||
self._dm.removeFile(self.remoteLog)
|
self._dm.removeFile(self.remoteLog)
|
||||||
else:
|
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.remoteProfile)
|
||||||
self._dm.removeDir(self.remoteChromeTestDir);
|
self._dm.removeDir(self.remoteChromeTestDir)
|
||||||
# Don't leave an old robotium.config hanging around; the
|
# Don't leave an old robotium.config hanging around; the
|
||||||
# profile it references was just deleted!
|
# profile it references was just deleted!
|
||||||
deviceRoot = self._dm.getDeviceRoot()
|
deviceRoot = self._dm.getDeviceRoot()
|
||||||
@@ -270,7 +328,7 @@ class MochiRemote(Mochitest):
|
|||||||
self._dm.getDirectory(self.remoteNSPR, blobberUploadDir)
|
self._dm.getDirectory(self.remoteNSPR, blobberUploadDir)
|
||||||
Mochitest.cleanup(self, options)
|
Mochitest.cleanup(self, options)
|
||||||
|
|
||||||
def findPath(self, paths, filename = None):
|
def findPath(self, paths, filename=None):
|
||||||
for path in paths:
|
for path in paths:
|
||||||
p = path
|
p = path
|
||||||
if filename:
|
if filename:
|
||||||
@@ -286,7 +344,7 @@ class MochiRemote(Mochitest):
|
|||||||
localAutomation.IS_MAC = False
|
localAutomation.IS_MAC = False
|
||||||
localAutomation.UNIXISH = False
|
localAutomation.UNIXISH = False
|
||||||
hostos = sys.platform
|
hostos = sys.platform
|
||||||
if (hostos == 'mac' or hostos == 'darwin'):
|
if (hostos == 'mac' or hostos == 'darwin'):
|
||||||
localAutomation.IS_MAC = True
|
localAutomation.IS_MAC = True
|
||||||
elif (hostos == 'linux' or hostos == 'linux2'):
|
elif (hostos == 'linux' or hostos == 'linux2'):
|
||||||
localAutomation.IS_LINUX = True
|
localAutomation.IS_LINUX = True
|
||||||
@@ -315,8 +373,10 @@ class MochiRemote(Mochitest):
|
|||||||
os.path.join('..', self._automation._product)
|
os.path.join('..', self._automation._product)
|
||||||
]
|
]
|
||||||
options.xrePath = self.findPath(paths)
|
options.xrePath = self.findPath(paths)
|
||||||
if options.xrePath == None:
|
if options.xrePath is None:
|
||||||
self.log.error("unable to find xulrunner path for %s, please specify with --xre-path" % os.name)
|
self.log.error(
|
||||||
|
"unable to find xulrunner path for %s, please specify with --xre-path" %
|
||||||
|
os.name)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
xpcshell = "xpcshell"
|
xpcshell = "xpcshell"
|
||||||
@@ -329,15 +389,17 @@ class MochiRemote(Mochitest):
|
|||||||
paths = [options.xrePath]
|
paths = [options.xrePath]
|
||||||
options.utilityPath = self.findPath(paths, xpcshell)
|
options.utilityPath = self.findPath(paths, xpcshell)
|
||||||
|
|
||||||
if options.utilityPath == None:
|
if options.utilityPath is None:
|
||||||
self.log.error("unable to find utility path for %s, please specify with --utility-path" % os.name)
|
self.log.error(
|
||||||
|
"unable to find utility path for %s, please specify with --utility-path" %
|
||||||
|
os.name)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
xpcshell_path = os.path.join(options.utilityPath, xpcshell)
|
xpcshell_path = os.path.join(options.utilityPath, xpcshell)
|
||||||
if localAutomation.elf_arm(xpcshell_path):
|
if localAutomation.elf_arm(xpcshell_path):
|
||||||
self.log.error('xpcshell at %s is an ARM binary; please use '
|
self.log.error('xpcshell at %s is an ARM binary; please use '
|
||||||
'the --utility-path argument to specify the path '
|
'the --utility-path argument to specify the path '
|
||||||
'to a desktop version.' % xpcshell_path)
|
'to a desktop version.' % xpcshell_path)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if self.localProfile:
|
if self.localProfile:
|
||||||
@@ -356,7 +418,11 @@ class MochiRemote(Mochitest):
|
|||||||
""" Create the servers on the host and start them up """
|
""" Create the servers on the host and start them up """
|
||||||
restoreRemotePaths = self.switchToLocalPaths(options)
|
restoreRemotePaths = self.switchToLocalPaths(options)
|
||||||
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
||||||
Mochitest.startServers(self, options, debuggerInfo, ignoreSSLTunnelExts = True)
|
Mochitest.startServers(
|
||||||
|
self,
|
||||||
|
options,
|
||||||
|
debuggerInfo,
|
||||||
|
ignoreSSLTunnelExts=True)
|
||||||
restoreRemotePaths()
|
restoreRemotePaths()
|
||||||
|
|
||||||
def buildProfile(self, options):
|
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
|
# we do not need this for robotium based tests, lets save a LOT of time
|
||||||
if options.robocopIni:
|
if options.robocopIni:
|
||||||
shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
|
shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
|
||||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'mochikit@mozilla.org'))
|
shutil.rmtree(
|
||||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'worker-test@mozilla.org'))
|
os.path.join(
|
||||||
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'workerbootstrap-test@mozilla.org'))
|
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'))
|
os.remove(os.path.join(options.profilePath, 'userChrome.css'))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
||||||
except devicemanager.DMError:
|
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
|
raise
|
||||||
|
|
||||||
restoreRemotePaths()
|
restoreRemotePaths()
|
||||||
@@ -392,11 +474,12 @@ class MochiRemote(Mochitest):
|
|||||||
retVal = Mochitest.buildURLOptions(self, options, env)
|
retVal = Mochitest.buildURLOptions(self, options, env)
|
||||||
|
|
||||||
if not options.robocopIni:
|
if not options.robocopIni:
|
||||||
#we really need testConfig.js (for browser chrome)
|
# we really need testConfig.js (for browser chrome)
|
||||||
try:
|
try:
|
||||||
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
||||||
except devicemanager.DMError:
|
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
|
raise
|
||||||
|
|
||||||
options.profilePath = self.remoteProfile
|
options.profilePath = self.remoteProfile
|
||||||
@@ -416,7 +499,11 @@ class MochiRemote(Mochitest):
|
|||||||
# robocop tests.
|
# robocop tests.
|
||||||
return self.buildTestURL(options)
|
return self.buildTestURL(options)
|
||||||
else:
|
else:
|
||||||
return super(MochiRemote, self).buildTestPath(options, testsToFilter)
|
return super(
|
||||||
|
MochiRemote,
|
||||||
|
self).buildTestPath(
|
||||||
|
options,
|
||||||
|
testsToFilter)
|
||||||
|
|
||||||
def getChromeTestDir(self, options):
|
def getChromeTestDir(self, options):
|
||||||
local = super(MochiRemote, self).getChromeTestDir(options)
|
local = super(MochiRemote, self).getChromeTestDir(options)
|
||||||
@@ -430,7 +517,8 @@ class MochiRemote(Mochitest):
|
|||||||
def getLogFilePath(self, logFile):
|
def getLogFilePath(self, logFile):
|
||||||
return 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):
|
def addLogData(self):
|
||||||
with open(self.localLog) as currentLog:
|
with open(self.localLog) as currentLog:
|
||||||
data = currentLog.readlines()
|
data = currentLog.readlines()
|
||||||
@@ -461,7 +549,8 @@ class MochiRemote(Mochitest):
|
|||||||
if fail_found:
|
if fail_found:
|
||||||
result = 1
|
result = 1
|
||||||
if not end_found:
|
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
|
result = 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -494,7 +583,8 @@ class MochiRemote(Mochitest):
|
|||||||
incr += 1
|
incr += 1
|
||||||
logFile.append("%s INFO SimpleTest FINISHED" % incr)
|
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)
|
print '\n'.join(logFile)
|
||||||
with open(self.localLog, 'w') as localLog:
|
with open(self.localLog, 'w') as localLog:
|
||||||
localLog.write('\n'.join(logFile))
|
localLog.write('\n'.join(logFile))
|
||||||
@@ -506,7 +596,9 @@ class MochiRemote(Mochitest):
|
|||||||
def printScreenshots(self, screenShotDir):
|
def printScreenshots(self, screenShotDir):
|
||||||
# TODO: This can be re-written after completion of bug 749421
|
# TODO: This can be re-written after completion of bug 749421
|
||||||
if not self._dm.dirExists(screenShotDir):
|
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
|
return
|
||||||
|
|
||||||
printed = 0
|
printed = 0
|
||||||
@@ -527,8 +619,13 @@ class MochiRemote(Mochitest):
|
|||||||
def printDeviceInfo(self, printLogcat=False):
|
def printDeviceInfo(self, printLogcat=False):
|
||||||
try:
|
try:
|
||||||
if printLogcat:
|
if printLogcat:
|
||||||
logcat = self._dm.getLogcat(filterOutRegexps=fennecLogcatFilters)
|
logcat = self._dm.getLogcat(
|
||||||
self.log.info('\n' + ''.join(logcat).decode('utf-8', 'replace'))
|
filterOutRegexps=fennecLogcatFilters)
|
||||||
|
self.log.info(
|
||||||
|
'\n' +
|
||||||
|
''.join(logcat).decode(
|
||||||
|
'utf-8',
|
||||||
|
'replace'))
|
||||||
self.log.info("Device info: %s" % self._dm.getInfo())
|
self.log.info("Device info: %s" % self._dm.getInfo())
|
||||||
self.log.info("Test root: %s" % self._dm.deviceRoot)
|
self.log.info("Test root: %s" % self._dm.deviceRoot)
|
||||||
except devicemanager.DMError:
|
except devicemanager.DMError:
|
||||||
@@ -543,7 +640,9 @@ class MochiRemote(Mochitest):
|
|||||||
fHandle.write("profile=%s\n" % (self.remoteProfile))
|
fHandle.write("profile=%s\n" % (self.remoteProfile))
|
||||||
fHandle.write("logfile=%s\n" % (options.remoteLogFile))
|
fHandle.write("logfile=%s\n" % (options.remoteLogFile))
|
||||||
fHandle.write("host=http://mochi.test:8888/tests\n")
|
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:
|
if browserEnv:
|
||||||
envstr = ""
|
envstr = ""
|
||||||
@@ -551,7 +650,9 @@ class MochiRemote(Mochitest):
|
|||||||
for key, value in browserEnv.items():
|
for key, value in browserEnv.items():
|
||||||
try:
|
try:
|
||||||
value.index(',')
|
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)
|
self.log.error("browserEnv=%s" % browserEnv)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
envstr += "%s%s=%s" % (delim, key, value)
|
envstr += "%s%s=%s" % (delim, key, value)
|
||||||
@@ -561,7 +662,11 @@ class MochiRemote(Mochitest):
|
|||||||
fHandle.close()
|
fHandle.close()
|
||||||
|
|
||||||
self._dm.removeFile(os.path.join(deviceRoot, "robotium.config"))
|
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)
|
os.unlink(fHandle.name)
|
||||||
|
|
||||||
def getGMPPluginPath(self, options):
|
def getGMPPluginPath(self, options):
|
||||||
@@ -569,10 +674,15 @@ class MochiRemote(Mochitest):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def buildBrowserEnv(self, options, debugger=False):
|
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
|
# override nsprLogs to avoid processing in Mochitest base class
|
||||||
self.nsprLogs = None
|
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)
|
self.buildRobotiumConfig(options, browserEnv)
|
||||||
return browserEnv
|
return browserEnv
|
||||||
|
|
||||||
@@ -593,6 +703,7 @@ class MochiRemote(Mochitest):
|
|||||||
|
|
||||||
return self._automation.runApp(*args, **kwargs)
|
return self._automation.runApp(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
message_logger = MessageLogger(logger=None)
|
message_logger = MessageLogger(logger=None)
|
||||||
process_args = {'messageLogger': message_logger}
|
process_args = {'messageLogger': message_logger}
|
||||||
@@ -604,13 +715,23 @@ def main(args):
|
|||||||
|
|
||||||
if (options.dm_trans == "adb"):
|
if (options.dm_trans == "adb"):
|
||||||
if (options.deviceIP):
|
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):
|
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:
|
else:
|
||||||
dm = droid.DroidADB(deviceRoot=options.remoteTestRoot)
|
dm = droid.DroidADB(deviceRoot=options.remoteTestRoot)
|
||||||
else:
|
else:
|
||||||
dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
|
dm = droid.DroidSUT(
|
||||||
|
options.deviceIP,
|
||||||
|
options.devicePort,
|
||||||
|
deviceRoot=options.remoteTestRoot)
|
||||||
auto.setDeviceManager(dm)
|
auto.setDeviceManager(dm)
|
||||||
options = parser.verifyRemoteOptions(options, auto)
|
options = parser.verifyRemoteOptions(options, auto)
|
||||||
|
|
||||||
@@ -620,23 +741,24 @@ def main(args):
|
|||||||
message_logger.logger = log
|
message_logger.logger = log
|
||||||
mochitest.message_logger = message_logger
|
mochitest.message_logger = message_logger
|
||||||
|
|
||||||
if (options == None):
|
if (options is None):
|
||||||
log.error("Invalid options specified, use --help for a list of valid options")
|
log.error(
|
||||||
|
"Invalid options specified, use --help for a list of valid options")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
productPieces = options.remoteProductName.split('.')
|
productPieces = options.remoteProductName.split('.')
|
||||||
if (productPieces != None):
|
if (productPieces is not None):
|
||||||
auto.setProduct(productPieces[0])
|
auto.setProduct(productPieces[0])
|
||||||
else:
|
else:
|
||||||
auto.setProduct(options.remoteProductName)
|
auto.setProduct(options.remoteProductName)
|
||||||
auto.setAppName(options.remoteappname)
|
auto.setAppName(options.remoteappname)
|
||||||
|
|
||||||
options = parser.verifyOptions(options, mochitest)
|
options = parser.verifyOptions(options, mochitest)
|
||||||
if (options == None):
|
if (options is None):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
logParent = os.path.dirname(options.remoteLogFile)
|
logParent = os.path.dirname(options.remoteLogFile)
|
||||||
dm.mkDir(logParent);
|
dm.mkDir(logParent)
|
||||||
auto.setRemoteLog(options.remoteLogFile)
|
auto.setRemoteLog(options.remoteLogFile)
|
||||||
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
|
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
|
# Add Android version (SDK level) to mozinfo so that manifest entries
|
||||||
# can be conditional on android_version.
|
# can be conditional on android_version.
|
||||||
androidVersion = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk'])
|
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
|
mozinfo.info['android_version'] = androidVersion
|
||||||
|
|
||||||
deviceRoot = dm.deviceRoot
|
deviceRoot = dm.deviceRoot
|
||||||
@@ -677,13 +801,14 @@ def main(args):
|
|||||||
tests.append(test['name'])
|
tests.append(test['name'])
|
||||||
|
|
||||||
if options.totalChunks:
|
if options.totalChunks:
|
||||||
tests_per_chunk = math.ceil(len(tests) / (options.totalChunks * 1.0))
|
tests_per_chunk = math.ceil(
|
||||||
start = int(round((options.thisChunk-1) * tests_per_chunk))
|
len(tests) / (options.totalChunks * 1.0))
|
||||||
|
start = int(round((options.thisChunk - 1) * tests_per_chunk))
|
||||||
end = int(round(options.thisChunk * tests_per_chunk))
|
end = int(round(options.thisChunk * tests_per_chunk))
|
||||||
if end > len(tests):
|
if end > len(tests):
|
||||||
end = len(tests)
|
end = len(tests)
|
||||||
my_tests = tests[start:end]
|
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.enabled=true')
|
||||||
options.extraPrefs.append('browser.search.suggest.prompted=true')
|
options.extraPrefs.append('browser.search.suggest.prompted=true')
|
||||||
@@ -706,7 +831,9 @@ def main(args):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if 'disabled' in test:
|
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
|
continue
|
||||||
|
|
||||||
active_tests.append(test)
|
active_tests.append(test)
|
||||||
@@ -714,7 +841,8 @@ def main(args):
|
|||||||
log.suite_start([t['name'] for t in active_tests])
|
log.suite_start([t['name'] for t in active_tests])
|
||||||
|
|
||||||
for test 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:
|
if mochitest.localProfile:
|
||||||
options.profilePath = mochitest.localProfile
|
options.profilePath = mochitest.localProfile
|
||||||
os.system("rm -Rf %s" % options.profilePath)
|
os.system("rm -Rf %s" % options.profilePath)
|
||||||
@@ -722,34 +850,75 @@ def main(args):
|
|||||||
mochitest.localProfile = options.profilePath
|
mochitest.localProfile = options.profilePath
|
||||||
|
|
||||||
options.app = "am"
|
options.app = "am"
|
||||||
options.browserArgs = ["instrument", "-w", "-e", "deviceroot", deviceRoot, "-e", "class"]
|
options.browserArgs = [
|
||||||
options.browserArgs.append("org.mozilla.gecko.tests.%s" % test['name'])
|
"instrument",
|
||||||
options.browserArgs.append("org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
|
"-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']
|
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":
|
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")
|
osInfo = dm.getInfo("os")
|
||||||
devOS = " ".join(osInfo['os'])
|
devOS = " ".join(osInfo['os'])
|
||||||
|
|
||||||
if ("pandaboard" in devOS):
|
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:
|
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"):
|
if (options.dm_trans == "sut"):
|
||||||
dm._runCmds([{"cmd": " ".join(delete)}])
|
dm._runCmds([{"cmd": " ".join(delete)}])
|
||||||
|
|
||||||
# Insert the bookmarks
|
# 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):
|
for i in range(20):
|
||||||
if ("pandaboard" in devOS):
|
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 = [
|
||||||
else:
|
'execsu',
|
||||||
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);'"]
|
'sqlite3',
|
||||||
if (options.dm_trans == "sut"):
|
"/data/data/com.android.browser/databases/browser2.db 'insert or replace into bookmarks(_id,title,url,folder,parent,position) values (" +
|
||||||
dm._runCmds([{"cmd": " ".join(cmd)}])
|
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);'"]
|
||||||
|
if (options.dm_trans == "sut"):
|
||||||
|
dm._runCmds([{"cmd": " ".join(cmd)}])
|
||||||
try:
|
try:
|
||||||
screenShotDir = "/mnt/sdcard/Robotium-Screenshots"
|
screenShotDir = "/mnt/sdcard/Robotium-Screenshots"
|
||||||
dm.removeDir(screenShotDir)
|
dm.removeDir(screenShotDir)
|
||||||
@@ -761,11 +930,13 @@ def main(args):
|
|||||||
if result != 0 or log_result != 0:
|
if result != 0 or log_result != 0:
|
||||||
mochitest.printDeviceInfo(printLogcat=True)
|
mochitest.printDeviceInfo(printLogcat=True)
|
||||||
mochitest.printScreenshots(screenShotDir)
|
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:
|
if retVal is None or retVal == 0:
|
||||||
retVal = result
|
retVal = result
|
||||||
except:
|
except:
|
||||||
log.error("Automation Error: Exception caught while running tests")
|
log.error(
|
||||||
|
"Automation Error: Exception caught while running tests")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
mochitest.stopServers()
|
mochitest.stopServers()
|
||||||
try:
|
try:
|
||||||
@@ -779,9 +950,15 @@ def main(args):
|
|||||||
# Clean-up added bookmarks
|
# Clean-up added bookmarks
|
||||||
if test['name'] == "testImportFromAndroid":
|
if test['name'] == "testImportFromAndroid":
|
||||||
if ("pandaboard" in devOS):
|
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:
|
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"):
|
if (options.dm_trans == "sut"):
|
||||||
dm._runCmds([{"cmd": " ".join(cmd_del)}])
|
dm._runCmds([{"cmd": " ".join(cmd_del)}])
|
||||||
if retVal is None:
|
if retVal is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user