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:
Andrew Halberstadt 2015-02-13 14:42:02 -05:00
parent 24445b6701
commit aa84634c8c
6 changed files with 3299 additions and 2464 deletions

View File

@ -1,7 +1,9 @@
import math
import mozinfo
class Bisect(object):
"Class for creating, bisecting and summarizing for --bisect-chunk option."
def __init__(self, harness):
@ -34,23 +36,28 @@ class Bisect(object):
if not options.totalChunks or not options.thisChunk:
return tests
# The logic here is same as chunkifyTests.js, we need this for bisecting tests.
# The logic here is same as chunkifyTests.js, we need this for
# bisecting tests.
if options.chunkByDir:
tests_by_dir = {}
test_dirs = []
for test in tests:
directory = test.split("/")
directory = directory[0:min(options.chunkByDir, len(directory)-1)]
directory = directory[
0:min(
options.chunkByDir,
len(directory) -
1)]
directory = "/".join(directory)
if not directory in tests_by_dir:
if directory not in tests_by_dir:
tests_by_dir[directory] = [test]
test_dirs.append(directory)
else:
tests_by_dir[directory].append(test)
tests_per_chunk = float(len(test_dirs)) / options.totalChunks
start = int(round((options.thisChunk-1) * tests_per_chunk))
start = int(round((options.thisChunk - 1) * tests_per_chunk))
end = int(round((options.thisChunk) * tests_per_chunk))
test_dirs = test_dirs[start:end]
return_tests = []
@ -59,7 +66,7 @@ class Bisect(object):
else:
tests_per_chunk = float(len(tests)) / options.totalChunks
start = int(round((options.thisChunk-1) * tests_per_chunk))
start = int(round((options.thisChunk - 1) * tests_per_chunk))
end = int(round(options.thisChunk * tests_per_chunk))
return_tests = tests[start:end]
@ -83,7 +90,8 @@ class Bisect(object):
"This method is used to call other methods for setting up variables and getting the list of tests for bisection."
if options.bisectChunk == "default":
return tests
# The second condition in 'if' is required to verify that the failing test is the last one.
# The second condition in 'if' is required to verify that the failing
# test is the last one.
elif 'loop' not in self.contents or not self.contents['tests'][-1].endswith(options.bisectChunk):
tests = self.get_tests_for_bisection(options, tests)
status = self.setup(tests)
@ -97,14 +105,16 @@ class Bisect(object):
# Check whether sanity check has to be done. Also it is necessary to check whether options.bisectChunk is present
# in self.expectedError as we do not want to run if it is "default".
if status == -1 and options.bisectChunk in self.expectedError:
# In case we have a debug build, we don't want to run a sanity check, will take too much time.
# In case we have a debug build, we don't want to run a sanity
# check, will take too much time.
if mozinfo.info['debug']:
return status
testBleedThrough = self.contents['testsToRun'][0]
tests = self.contents['totalTests']
tests.remove(testBleedThrough)
# To make sure that the failing test is dependent on some other test.
# To make sure that the failing test is dependent on some other
# test.
if options.bisectChunk in testBleedThrough:
return status
@ -133,7 +143,7 @@ class Bisect(object):
# self.contents['result'] will be expected error only if it fails.
elif self.contents['result'] == "FAIL":
self.contents['tests'] = self.contents['testsToRun']
status = 1 # for initializing
status = 1 # for initializing
# initialize
if status:
@ -189,22 +199,35 @@ class Bisect(object):
def summarize_chunk(self, options):
"This method is used summarize the results after the list of tests is run."
if options.bisectChunk == "default":
# if no expectedError that means all the tests have successfully passed.
# if no expectedError that means all the tests have successfully
# passed.
if len(self.expectedError) == 0:
return -1
options.bisectChunk = self.expectedError.keys()[0]
self.summary.append("\tFound Error in test: %s" % options.bisectChunk)
self.summary.append(
"\tFound Error in test: %s" %
options.bisectChunk)
return 0
# If options.bisectChunk is not in self.result then we need to move to the next run.
# If options.bisectChunk is not in self.result then we need to move to
# the next run.
if options.bisectChunk not in self.result:
return -1
self.summary.append("\tPass %d:" % self.contents['loop'])
if len(self.contents['testsToRun']) > 1:
self.summary.append("\t\t%d test files(start,end,failing). [%s, %s, %s]" % (len(self.contents['testsToRun']), self.contents['testsToRun'][0], self.contents['testsToRun'][-2], self.contents['testsToRun'][-1]))
self.summary.append(
"\t\t%d test files(start,end,failing). [%s, %s, %s]" % (len(
self.contents['testsToRun']),
self.contents['testsToRun'][0],
self.contents['testsToRun'][
-2],
self.contents['testsToRun'][
-1]))
else:
self.summary.append("\t\t1 test file [%s]" % self.contents['testsToRun'][0])
self.summary.append(
"\t\t1 test file [%s]" %
self.contents['testsToRun'][0])
return self.check_for_intermittent(options)
if self.result[options.bisectChunk] == "PASS":
@ -217,23 +240,32 @@ class Bisect(object):
elif self.result[options.bisectChunk] == "FAIL":
if 'expectedError' not in self.contents:
self.summary.append("\t\t%s failed." % self.contents['testsToRun'][-1])
self.contents['expectedError'] = self.expectedError[options.bisectChunk]
self.summary.append("\t\t%s failed." %
self.contents['testsToRun'][-1])
self.contents['expectedError'] = self.expectedError[
options.bisectChunk]
status = 0
elif self.expectedError[options.bisectChunk] == self.contents['expectedError']:
self.summary.append("\t\t%s failed with expected error." % self.contents['testsToRun'][-1])
self.summary.append(
"\t\t%s failed with expected error." % self.contents['testsToRun'][-1])
self.contents['result'] = "FAIL"
status = 0
# This code checks for test-bleedthrough. Should work for any algorithm.
# This code checks for test-bleedthrough. Should work for any
# algorithm.
numberOfTests = len(self.contents['testsToRun'])
if numberOfTests < 3:
# This means that only 2 tests are run. Since the last test is the failing test itself therefore the bleedthrough test is the first test
self.summary.append("TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" % self.contents['testsToRun'][0])
# This means that only 2 tests are run. Since the last test
# is the failing test itself therefore the bleedthrough
# test is the first test
self.summary.append(
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
self.contents['testsToRun'][0])
status = -1
else:
self.summary.append("\t\t%s failed with different error." % self.contents['testsToRun'][-1])
self.summary.append(
"\t\t%s failed with different error." % self.contents['testsToRun'][-1])
status = -1
return status
@ -241,7 +273,9 @@ class Bisect(object):
def check_for_intermittent(self, options):
"This method is used to check whether a test is an intermittent."
if self.result[options.bisectChunk] == "PASS":
self.summary.append("\t\tThe test %s passed." % self.contents['testsToRun'][0])
self.summary.append(
"\t\tThe test %s passed." %
self.contents['testsToRun'][0])
if self.repeat > 0:
# loop is set to 1 to again run the single test.
self.contents['loop'] = 1
@ -256,7 +290,9 @@ class Bisect(object):
self.contents['loop'] = 2
return 1
elif self.result[options.bisectChunk] == "FAIL":
self.summary.append("\t\tThe test %s failed." % self.contents['testsToRun'][0])
self.summary.append(
"\t\tThe test %s failed." %
self.contents['testsToRun'][0])
self.failcount += 1
self.contents['loop'] = 1
self.repeat -= 1
@ -269,7 +305,9 @@ class Bisect(object):
return -1
return 0
else:
self.summary.append("TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" % self.contents['testsToRun'][0])
self.summary.append(
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
self.contents['testsToRun'][0])
return -1
def print_summary(self):

View File

@ -81,6 +81,7 @@ FLAVORS = {
class MochitestRunner(MozbuildObject):
"""Easily run mochitests.
This currently contains just the basics for running mochitests. We may want
@ -91,8 +92,12 @@ class MochitestRunner(MozbuildObject):
import mozinfo
appname = 'webapprt-stub' + mozinfo.info.get('bin_suffix', '')
if sys.platform.startswith('darwin'):
appname = os.path.join(self.distdir, self.substs['MOZ_MACBUNDLE_NAME'],
'Contents', 'Resources', appname)
appname = os.path.join(
self.distdir,
self.substs['MOZ_MACBUNDLE_NAME'],
'Contents',
'Resources',
appname)
else:
appname = os.path.join(self.distdir, 'bin', appname)
return appname
@ -106,12 +111,24 @@ class MochitestRunner(MozbuildObject):
sys.path.append(build_path)
self.tests_dir = os.path.join(self.topobjdir, '_tests')
self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
self.mochitest_dir = os.path.join(
self.tests_dir,
'testing',
'mochitest')
self.bin_dir = os.path.join(self.topobjdir, 'dist', 'bin')
def run_b2g_test(self, test_paths=None, b2g_home=None, xre_path=None,
total_chunks=None, this_chunk=None, no_window=None,
repeat=0, run_until_failure=False, chrome=False, **kwargs):
def run_b2g_test(
self,
test_paths=None,
b2g_home=None,
xre_path=None,
total_chunks=None,
this_chunk=None,
no_window=None,
repeat=0,
run_until_failure=False,
chrome=False,
**kwargs):
"""Runs a b2g mochitest.
test_paths is an enumerable of paths to tests. It can be a relative path
@ -137,7 +154,7 @@ class MochitestRunner(MozbuildObject):
path = os.path.join(self.mochitest_dir, 'runtestsb2g.py')
with open(path, 'r') as fh:
imp.load_module('mochitest', fh, path,
('.py', 'r', imp.PY_SOURCE))
('.py', 'r', imp.PY_SOURCE))
import mochitest
from mochitest_options import B2GOptions
@ -147,11 +164,19 @@ class MochitestRunner(MozbuildObject):
if test_path:
if chrome:
test_root_file = mozpack.path.join(self.mochitest_dir, 'chrome', test_path)
test_root_file = mozpack.path.join(
self.mochitest_dir,
'chrome',
test_path)
else:
test_root_file = mozpack.path.join(self.mochitest_dir, 'tests', test_path)
test_root_file = mozpack.path.join(
self.mochitest_dir,
'tests',
test_path)
if not os.path.exists(test_root_file):
print('Specified test path does not exist: %s' % test_root_file)
print(
'Specified test path does not exist: %s' %
test_root_file)
return 1
options.testPath = test_path
@ -163,7 +188,9 @@ class MochitestRunner(MozbuildObject):
options.repeat = repeat
options.runUntilFailure = run_until_failure
options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
options.symbolsPath = os.path.join(
self.distdir,
'crashreporter-symbols')
options.consoleLevel = 'INFO'
if conditions.is_b2g_desktop(self):
@ -190,15 +217,46 @@ class MochitestRunner(MozbuildObject):
options.chrome = chrome
return mochitest.run_remote_mochitests(parser, options)
def run_desktop_test(self, context, suite=None, test_paths=None, debugger=None,
debugger_args=None, slowscript=False, screenshot_on_fail = False, shuffle=False, closure_behaviour='auto',
rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False,
slow=False, chunk_by_dir=0, total_chunks=None, this_chunk=None, extraPrefs=[],
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
e10s=False, strict_content_sandbox=False, nested_oop=False, dmd=False, dump_output_directory=None,
dump_about_memory_after_test=False, dump_dmd_after_test=False,
install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False,
useTestMediaDevices=False, timeout=None, **kwargs):
def run_desktop_test(
self,
context,
suite=None,
test_paths=None,
debugger=None,
debugger_args=None,
slowscript=False,
screenshot_on_fail=False,
shuffle=False,
closure_behaviour='auto',
rerun_failures=False,
no_autorun=False,
repeat=0,
run_until_failure=False,
slow=False,
chunk_by_dir=0,
total_chunks=None,
this_chunk=None,
extraPrefs=[],
jsdebugger=False,
debug_on_failure=False,
start_at=None,
end_at=None,
e10s=False,
strict_content_sandbox=False,
nested_oop=False,
dmd=False,
dump_output_directory=None,
dump_about_memory_after_test=False,
dump_dmd_after_test=False,
install_extension=None,
quiet=False,
environment=[],
app_override=None,
bisectChunk=None,
runByDir=False,
useTestMediaDevices=False,
timeout=None,
**kwargs):
"""Runs a mochitest.
test_paths are path to tests. They can be a relative path from the
@ -227,9 +285,12 @@ class MochitestRunner(MozbuildObject):
# Make absolute paths relative before calling os.chdir() below.
if test_paths:
test_paths = [self._wrap_path_argument(p).relpath() if os.path.isabs(p) else p for p in test_paths]
test_paths = [self._wrap_path_argument(
p).relpath() if os.path.isabs(p) else p for p in test_paths]
failure_file_path = os.path.join(self.statedir, 'mochitest_failures.json')
failure_file_path = os.path.join(
self.statedir,
'mochitest_failures.json')
if rerun_failures and not os.path.exists(failure_file_path):
print('No failure file present. Did you run mochitests before?')
@ -241,7 +302,7 @@ class MochitestRunner(MozbuildObject):
path = os.path.join(self.mochitest_dir, 'runtests.py')
with open(path, 'r') as fh:
imp.load_module('mochitest', fh, path,
('.py', 'r', imp.PY_SOURCE))
('.py', 'r', imp.PY_SOURCE))
import mochitest
from manifestparser import TestManifest
@ -253,7 +314,7 @@ class MochitestRunner(MozbuildObject):
# Automation installs its own stream handler to stdout. Since we want
# all logging to go through us, we just remove their handler.
remove_handlers = [l for l in logging.getLogger().handlers
if isinstance(l, logging.StreamHandler)]
if isinstance(l, logging.StreamHandler)]
for handler in remove_handlers:
logging.getLogger().removeHandler(handler)
@ -308,7 +369,9 @@ class MochitestRunner(MozbuildObject):
options.runSlower = slow
options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins'))
options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
options.symbolsPath = os.path.join(
self.distdir,
'crashreporter-symbols')
options.chunkByDir = chunk_by_dir
options.totalChunks = total_chunks
options.thisChunk = this_chunk
@ -329,11 +392,14 @@ class MochitestRunner(MozbuildObject):
options.runByDir = runByDir
options.useTestMediaDevices = useTestMediaDevices
if timeout:
options.timeout = int(timeout)
options.timeout = int(timeout)
options.failureFile = failure_file_path
if install_extension != None:
options.extensionsToInstall = [os.path.join(self.topsrcdir,install_extension)]
if install_extension is not None:
options.extensionsToInstall = [
os.path.join(
self.topsrcdir,
install_extension)]
for k, v in kwargs.iteritems():
setattr(options, k, v)
@ -341,18 +407,22 @@ class MochitestRunner(MozbuildObject):
if test_paths:
resolver = self._spawn(TestResolver)
tests = list(resolver.resolve_tests(paths=test_paths, flavor=flavor))
tests = list(
resolver.resolve_tests(
paths=test_paths,
flavor=flavor))
if not tests:
print('No tests could be found in the path specified. Please '
'specify a path that is a test file or is a directory '
'containing tests.')
'specify a path that is a test file or is a directory '
'containing tests.')
return 1
manifest = TestManifest()
manifest.tests.extend(tests)
if len(tests) == 1 and closure_behaviour == 'auto' and suite == 'plain':
if len(
tests) == 1 and closure_behaviour == 'auto' and suite == 'plain':
options.closeWhenDone = False
options.manifestFile = manifest
@ -364,7 +434,7 @@ class MochitestRunner(MozbuildObject):
options.debugger = debugger
if debugger_args:
if options.debugger == None:
if options.debugger is None:
print("--debugger-args passed, but no debugger specified.")
return 1
options.debuggerArgs = debugger_args
@ -375,14 +445,22 @@ class MochitestRunner(MozbuildObject):
elif app_override:
options.app = app_override
if options.gmp_path is None:
# Need to fix the location of gmp_fake which might not be shipped in the binary
# Need to fix the location of gmp_fake which might not be
# shipped in the binary
bin_path = self.get_binary_path()
options.gmp_path = os.path.join(os.path.dirname(bin_path), 'gmp-fake', '1.0')
options.gmp_path = os.path.join(
os.path.dirname(bin_path),
'gmp-fake',
'1.0')
options.gmp_path += os.pathsep
options.gmp_path += os.path.join(os.path.dirname(bin_path), 'gmp-clearkey', '0.1')
options.gmp_path += os.path.join(
os.path.dirname(bin_path),
'gmp-clearkey',
'0.1')
logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')}
logger_options = {
key: value for key,
value in vars(options).iteritems() if key.startswith('log')}
runner = mochitest.Mochitest(logger_options)
options = opts.verifyOptions(options, runner)
@ -414,12 +492,17 @@ def MochitestCommand(func):
# (modified) function. Here, we chain decorators onto the passed in
# function.
debugger = CommandArgument('--debugger', '-d', metavar='DEBUGGER',
debugger = CommandArgument(
'--debugger',
'-d',
metavar='DEBUGGER',
help='Debugger binary to run test in. Program name or path.')
func = debugger(func)
debugger_args = CommandArgument('--debugger-args',
metavar='DEBUGGER_ARGS', help='Arguments to pass to the debugger.')
debugger_args = CommandArgument(
'--debugger-args',
metavar='DEBUGGER_ARGS',
help='Arguments to pass to the debugger.')
func = debugger_args(func)
# Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
@ -427,219 +510,300 @@ def MochitestCommand(func):
# code. If we don't pass this, the user will need to periodically type
# "continue" to (safely) resume execution. There are ways to implement
# automatic resuming; see the bug.
slowscript = CommandArgument('--slowscript', action='store_true',
slowscript = CommandArgument(
'--slowscript',
action='store_true',
help='Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; when not set, recoverable but misleading SIGSEGV instances may occur in Ion/Odin JIT code')
func = slowscript(func)
screenshot_on_fail = CommandArgument('--screenshot-on-fail', action='store_true',
screenshot_on_fail = CommandArgument(
'--screenshot-on-fail',
action='store_true',
help='Take screenshots on all test failures. Set $MOZ_UPLOAD_DIR to a directory for storing the screenshots.')
func = screenshot_on_fail(func)
shuffle = CommandArgument('--shuffle', action='store_true',
help='Shuffle execution order.')
help='Shuffle execution order.')
func = shuffle(func)
keep_open = CommandArgument('--keep-open', action='store_const',
dest='closure_behaviour', const='open', default='auto',
keep_open = CommandArgument(
'--keep-open',
action='store_const',
dest='closure_behaviour',
const='open',
default='auto',
help='Always keep the browser open after tests complete.')
func = keep_open(func)
autoclose = CommandArgument('--auto-close', action='store_const',
dest='closure_behaviour', const='close', default='auto',
autoclose = CommandArgument(
'--auto-close',
action='store_const',
dest='closure_behaviour',
const='close',
default='auto',
help='Always close the browser after tests complete.')
func = autoclose(func)
rerun = CommandArgument('--rerun-failures', action='store_true',
rerun = CommandArgument(
'--rerun-failures',
action='store_true',
help='Run only the tests that failed during the last test run.')
func = rerun(func)
autorun = CommandArgument('--no-autorun', action='store_true',
autorun = CommandArgument(
'--no-autorun',
action='store_true',
help='Do not starting running tests automatically.')
func = autorun(func)
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)
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
help='Run tests repeatedly and stops on the first time a test fails. ' \
'Default cap is 30 runs, which can be overwritten ' \
'with the --repeat parameter.')
runUntilFailure = CommandArgument(
"--run-until-failure",
action='store_true',
help='Run tests repeatedly and stops on the first time a test fails. '
'Default cap is 30 runs, which can be overwritten '
'with the --repeat parameter.')
func = runUntilFailure(func)
slow = CommandArgument('--slow', action='store_true',
help='Delay execution between tests.')
help='Delay execution between tests.')
func = slow(func)
end_at = CommandArgument('--end-at', type=str,
end_at = CommandArgument(
'--end-at',
type=str,
help='Stop running the test sequence at this test.')
func = end_at(func)
start_at = CommandArgument('--start-at', type=str,
start_at = CommandArgument(
'--start-at',
type=str,
help='Start running the test sequence at this test.')
func = start_at(func)
chunk_dir = CommandArgument('--chunk-by-dir', type=int,
chunk_dir = CommandArgument(
'--chunk-by-dir',
type=int,
help='Group tests together in chunks by this many top directories.')
func = chunk_dir(func)
chunk_total = CommandArgument('--total-chunks', type=int,
chunk_total = CommandArgument(
'--total-chunks',
type=int,
help='Total number of chunks to split tests into.')
func = chunk_total(func)
this_chunk = CommandArgument('--this-chunk', type=int,
this_chunk = CommandArgument(
'--this-chunk',
type=int,
help='If running tests by chunks, the number of the chunk to run.')
func = this_chunk(func)
debug_on_failure = CommandArgument('--debug-on-failure', action='store_true',
help='Breaks execution and enters the JS debugger on a test failure. ' \
'Should be used together with --jsdebugger.')
debug_on_failure = CommandArgument(
'--debug-on-failure',
action='store_true',
help='Breaks execution and enters the JS debugger on a test failure. '
'Should be used together with --jsdebugger.')
func = debug_on_failure(func)
setpref = CommandArgument('--setpref', default=[], action='append',
metavar='PREF=VALUE', dest='extraPrefs',
help='defines an extra user preference')
metavar='PREF=VALUE', dest='extraPrefs',
help='defines an extra user preference')
func = setpref(func)
jsdebugger = CommandArgument('--jsdebugger', action='store_true',
jsdebugger = CommandArgument(
'--jsdebugger',
action='store_true',
help='Start the browser JS debugger before running the test. Implies --no-autorun.')
func = jsdebugger(func)
e10s = CommandArgument('--e10s', action='store_true',
e10s = CommandArgument(
'--e10s',
action='store_true',
help='Run tests with electrolysis preferences and test filtering enabled.')
func = e10s(func)
strict_content_sandbox = CommandArgument('--strict-content-sandbox', action='store_true',
strict_content_sandbox = CommandArgument(
'--strict-content-sandbox',
action='store_true',
help='Run tests with a more strict content sandbox (Windows only).')
func = strict_content_sandbox(func)
this_chunk = CommandArgument('--nested_oop', action='store_true',
this_chunk = CommandArgument(
'--nested_oop',
action='store_true',
help='Run tests with nested oop preferences and test filtering enabled.')
func = this_chunk(func)
dmd = CommandArgument('--dmd', action='store_true',
help='Run tests with DMD active.')
help='Run tests with DMD active.')
func = dmd(func)
dumpAboutMemory = CommandArgument('--dump-about-memory-after-test', action='store_true',
dumpAboutMemory = CommandArgument(
'--dump-about-memory-after-test',
action='store_true',
help='Dump an about:memory log after every test.')
func = dumpAboutMemory(func)
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)
dumpOutputDirectory = CommandArgument('--dump-output-directory', action='store',
dumpOutputDirectory = CommandArgument(
'--dump-output-directory',
action='store',
help='Specifies the directory in which to place dumped memory reports.')
func = dumpOutputDirectory(func)
path = CommandArgument('test_paths', default=None, nargs='*',
path = CommandArgument(
'test_paths',
default=None,
nargs='*',
metavar='TEST',
help='Test to run. Can be specified as a single file, a ' \
'directory, or omitted. If omitted, the entire test suite is ' \
'executed.')
help='Test to run. Can be specified as a single file, a '
'directory, or omitted. If omitted, the entire test suite is '
'executed.')
func = path(func)
install_extension = CommandArgument('--install-extension',
help='Install given extension before running selected tests. ' \
'Parameter is a path to xpi file.')
install_extension = CommandArgument(
'--install-extension',
help='Install given extension before running selected tests. '
'Parameter is a path to xpi file.')
func = install_extension(func)
quiet = CommandArgument('--quiet', default=False, action='store_true',
quiet = CommandArgument(
'--quiet',
default=False,
action='store_true',
help='Do not print test log lines unless a failure occurs.')
func = quiet(func)
setenv = CommandArgument('--setenv', default=[], action='append',
metavar='NAME=VALUE', dest='environment',
help="Sets the given variable in the application's environment")
setenv = CommandArgument(
'--setenv',
default=[],
action='append',
metavar='NAME=VALUE',
dest='environment',
help="Sets the given variable in the application's environment")
func = setenv(func)
runbydir = CommandArgument('--run-by-dir', default=False,
action='store_true',
dest='runByDir',
runbydir = CommandArgument(
'--run-by-dir',
default=False,
action='store_true',
dest='runByDir',
help='Run each directory in a single browser instance with a fresh profile.')
func = runbydir(func)
bisect_chunk = CommandArgument('--bisect-chunk', type=str,
dest='bisectChunk',
bisect_chunk = CommandArgument(
'--bisect-chunk',
type=str,
dest='bisectChunk',
help='Specify the failing test name to find the previous tests that may be causing the failure.')
func = bisect_chunk(func)
test_media = CommandArgument('--use-test-media-devices', default=False,
action='store_true',
dest='useTestMediaDevices',
test_media = CommandArgument(
'--use-test-media-devices',
default=False,
action='store_true',
dest='useTestMediaDevices',
help='Use test media device drivers for media testing.')
func = test_media(func)
app_override = CommandArgument('--app-override', default=None, action='store',
help="Override the default binary used to run tests with the path you provide, e.g. " \
" --app-override /usr/bin/firefox . " \
"If you have run ./mach package beforehand, you can specify 'dist' to " \
"run tests against the distribution bundle's binary.");
app_override = CommandArgument(
'--app-override',
default=None,
action='store',
help="Override the default binary used to run tests with the path you provide, e.g. "
" --app-override /usr/bin/firefox . "
"If you have run ./mach package beforehand, you can specify 'dist' to "
"run tests against the distribution bundle's binary.")
func = app_override(func)
timeout = CommandArgument('--timeout', default=None,
help='The per-test timeout time in seconds (default: 60 seconds)');
timeout = CommandArgument(
'--timeout',
default=None,
help='The per-test timeout time in seconds (default: 60 seconds)')
func = timeout(func)
return func
def B2GCommand(func):
"""Decorator that adds shared command arguments to b2g mochitest commands."""
busybox = CommandArgument('--busybox', default=None,
busybox = CommandArgument(
'--busybox',
default=None,
help='Path to busybox binary to install on device')
func = busybox(func)
logdir = CommandArgument('--logdir', default=None,
help='directory to store log files')
help='directory to store log files')
func = logdir(func)
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')
func = profile(func)
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')
func = geckopath(func)
nowindow = CommandArgument('--no-window', action='store_true', default=False,
nowindow = CommandArgument(
'--no-window',
action='store_true',
default=False,
help='Pass --no-window to the emulator')
func = nowindow(func)
sdcard = CommandArgument('--sdcard', default="10MB",
help='Define size of sdcard: 1MB, 50MB...etc')
help='Define size of sdcard: 1MB, 50MB...etc')
func = sdcard(func)
marionette = CommandArgument('--marionette', default=None,
marionette = CommandArgument(
'--marionette',
default=None,
help='host:port to use when connecting to Marionette')
func = marionette(func)
chunk_total = CommandArgument('--total-chunks', type=int,
chunk_total = CommandArgument(
'--total-chunks',
type=int,
help='Total number of chunks to split tests into.')
func = chunk_total(func)
this_chunk = CommandArgument('--this-chunk', type=int,
this_chunk = CommandArgument(
'--this-chunk',
type=int,
help='If running tests by chunks, the number of the chunk to run.')
func = this_chunk(func)
path = CommandArgument('test_paths', default=None, nargs='*',
path = CommandArgument(
'test_paths',
default=None,
nargs='*',
metavar='TEST',
help='Test to run. Can be specified as a single file, a ' \
'directory, or omitted. If omitted, the entire test suite is ' \
'executed.')
help='Test to run. Can be specified as a single file, a '
'directory, or omitted. If omitted, the entire test suite is '
'executed.')
func = path(func)
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)
runUntilFailure = CommandArgument("--run-until-failure", action='store_true',
help='Run tests repeatedly and stops on the first time a test fails. ' \
'Default cap is 30 runs, which can be overwritten ' \
'with the --repeat parameter.')
runUntilFailure = CommandArgument(
"--run-until-failure",
action='store_true',
help='Run tests repeatedly and stops on the first time a test fails. '
'Default cap is 30 runs, which can be overwritten '
'with the --repeat parameter.')
func = runUntilFailure(func)
return func
@ -648,34 +812,48 @@ def B2GCommand(func):
_st_parser = argparse.ArgumentParser()
structured.commandline.add_logging_group(_st_parser)
@CommandProvider
class MachCommands(MachCommandBase):
@Command('mochitest-plain', category='testing',
conditions=[conditions.is_firefox_or_mulet],
@Command(
'mochitest-plain',
category='testing',
conditions=[
conditions.is_firefox_or_mulet],
description='Run a plain mochitest (integration test, plain web page).',
parser=_st_parser)
@MochitestCommand
def run_mochitest_plain(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'plain', **kwargs)
@Command('mochitest-chrome', category='testing',
conditions=[conditions.is_firefox],
@Command(
'mochitest-chrome',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a chrome mochitest (integration test with some XUL).',
parser=_st_parser)
@MochitestCommand
def run_mochitest_chrome(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'chrome', **kwargs)
@Command('mochitest-browser', category='testing',
conditions=[conditions.is_firefox],
@Command(
'mochitest-browser',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a mochitest with browser chrome (integration test with a standard browser).',
parser=_st_parser)
@MochitestCommand
def run_mochitest_browser(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'browser', **kwargs)
@Command('mochitest-devtools', category='testing',
conditions=[conditions.is_firefox],
@Command(
'mochitest-devtools',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a devtools mochitest with browser chrome (integration test with a standard browser with the devtools frame).',
parser=_st_parser)
@MochitestCommand
@ -683,21 +861,24 @@ class MachCommands(MachCommandBase):
return self.run_mochitest(test_paths, 'devtools', **kwargs)
@Command('jetpack-package', category='testing',
conditions=[conditions.is_firefox],
description='Run a jetpack package test.')
conditions=[conditions.is_firefox],
description='Run a jetpack package test.')
@MochitestCommand
def run_mochitest_jetpack_package(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'jetpack-package', **kwargs)
@Command('jetpack-addon', category='testing',
conditions=[conditions.is_firefox],
description='Run a jetpack addon test.')
conditions=[conditions.is_firefox],
description='Run a jetpack addon test.')
@MochitestCommand
def run_mochitest_jetpack_addon(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs)
@Command('mochitest-metro', category='testing',
conditions=[conditions.is_firefox],
@Command(
'mochitest-metro',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a mochitest with metro browser chrome (tests for Windows touch interface).',
parser=_st_parser)
@MochitestCommand
@ -705,23 +886,29 @@ class MachCommands(MachCommandBase):
return self.run_mochitest(test_paths, 'metro', **kwargs)
@Command('mochitest-a11y', category='testing',
conditions=[conditions.is_firefox],
description='Run an a11y mochitest (accessibility tests).',
parser=_st_parser)
conditions=[conditions.is_firefox],
description='Run an a11y mochitest (accessibility tests).',
parser=_st_parser)
@MochitestCommand
def run_mochitest_a11y(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'a11y', **kwargs)
@Command('webapprt-test-chrome', category='testing',
conditions=[conditions.is_firefox],
@Command(
'webapprt-test-chrome',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).',
parser=_st_parser)
@MochitestCommand
def run_mochitest_webapprt_chrome(self, test_paths, **kwargs):
return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs)
@Command('webapprt-test-content', category='testing',
conditions=[conditions.is_firefox],
@Command(
'webapprt-test-content',
category='testing',
conditions=[
conditions.is_firefox],
description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).',
parser=_st_parser)
@MochitestCommand
@ -729,14 +916,14 @@ class MachCommands(MachCommandBase):
return self.run_mochitest(test_paths, 'webapprt-content', **kwargs)
@Command('mochitest', category='testing',
conditions=[conditions.is_firefox],
description='Run any flavor of mochitest (integration test).',
parser=_st_parser)
conditions=[conditions.is_firefox],
description='Run any flavor of mochitest (integration test).',
parser=_st_parser)
@MochitestCommand
@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,
**kwargs):
**kwargs):
self._preruntest()
from mozbuild.testing import TestResolver
@ -746,7 +933,7 @@ class MachCommands(MachCommandBase):
else:
resolver = self._spawn(TestResolver)
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
# an invocation for each suite. Ideally, this would be done
@ -773,8 +960,11 @@ class MachCommands(MachCommandBase):
mochitest = self._spawn(MochitestRunner)
overall = None
for suite, tests in sorted(suites.items()):
result = mochitest.run_desktop_test(self._mach_context,
test_paths=[test['file_relpath'] for test in tests], suite=suite,
result = mochitest.run_desktop_test(
self._mach_context,
test_paths=[
test['file_relpath'] for test in tests],
suite=suite,
**kwargs)
if result:
overall = result
@ -794,8 +984,11 @@ class MachCommands(MachCommandBase):
mochitest = self._spawn(MochitestRunner)
return mochitest.run_desktop_test(self._mach_context,
test_paths=test_paths, suite=flavor, **kwargs)
return mochitest.run_desktop_test(
self._mach_context,
test_paths=test_paths,
suite=flavor,
**kwargs)
# TODO For now b2g commands will only work with the emulator,
@ -810,27 +1003,39 @@ def is_emulator(cls):
@CommandProvider
class B2GCommands(MachCommandBase):
"""So far these are only mochitest plain. They are
implemented separately because their command lines
are completely different.
"""
def __init__(self, context):
MachCommandBase.__init__(self, context)
for attr in ('b2g_home', 'xre_path', 'device_name', 'get_build_var'):
setattr(self, attr, getattr(context, attr, None))
@Command('mochitest-remote', category='testing',
@Command(
'mochitest-remote',
category='testing',
description='Run a remote mochitest (integration test for fennec/android).',
conditions=[conditions.is_b2g, is_emulator])
conditions=[
conditions.is_b2g,
is_emulator])
@B2GCommand
def run_mochitest_remote(self, test_paths, **kwargs):
if self.get_build_var:
host_webapps_dir = os.path.join(self.get_build_var('TARGET_OUT_DATA'),
'local', 'webapps')
if not os.path.isdir(os.path.join(host_webapps_dir,
'test-container.gaiamobile.org')):
print(ENG_BUILD_REQUIRED % ('mochitest-remote', host_webapps_dir))
host_webapps_dir = os.path.join(
self.get_build_var('TARGET_OUT_DATA'),
'local',
'webapps')
if not os.path.isdir(
os.path.join(
host_webapps_dir,
'test-container.gaiamobile.org')):
print(
ENG_BUILD_REQUIRED %
('mochitest-remote', host_webapps_dir))
return 1
from mozbuild.controller.building import BuildDriver
@ -847,22 +1052,29 @@ class B2GCommands(MachCommandBase):
driver.install_tests(remove=False)
mochitest = self._spawn(MochitestRunner)
return mochitest.run_b2g_test(b2g_home=self.b2g_home,
xre_path=self.xre_path, test_paths=test_paths, **kwargs)
return mochitest.run_b2g_test(
b2g_home=self.b2g_home,
xre_path=self.xre_path,
test_paths=test_paths,
**kwargs)
@Command('mochitest-chrome-remote', category='testing',
description='Run a remote mochitest-chrome.',
conditions=[conditions.is_b2g, is_emulator])
description='Run a remote mochitest-chrome.',
conditions=[conditions.is_b2g, is_emulator])
@B2GCommand
def run_mochitest_chrome_remote(self, test_paths, **kwargs):
return self.run_mochitest_remote(test_paths, chrome=True, **kwargs)
@Command('mochitest-b2g-desktop', category='testing',
conditions=[conditions.is_b2g_desktop],
@Command(
'mochitest-b2g-desktop',
category='testing',
conditions=[
conditions.is_b2g_desktop],
description='Run a b2g desktop mochitest (same as mochitest-plain but for b2g desktop).')
@B2GCommand
def run_mochitest_b2g_desktop(self, test_paths, **kwargs):
kwargs['profile'] = kwargs.get('profile') or os.environ.get('GAIA_PROFILE')
kwargs['profile'] = kwargs.get(
'profile') or os.environ.get('GAIA_PROFILE')
if not kwargs['profile'] or not os.path.isdir(kwargs['profile']):
print(GAIA_PROFILE_NOT_FOUND % 'mochitest-b2g-desktop')
return 1
@ -886,31 +1098,52 @@ class B2GCommands(MachCommandBase):
@CommandProvider
class AndroidCommands(MachCommandBase):
@Command('robocop', category='testing',
conditions=[conditions.is_android],
description='Run a Robocop test.')
@CommandArgument('test_path', default=None, nargs='?',
conditions=[conditions.is_android],
description='Run a Robocop test.')
@CommandArgument(
'test_path',
default=None,
nargs='?',
metavar='TEST',
help='Test to run. Can be specified as a Robocop test name (like "testLoad"), ' \
'or omitted. If omitted, the entire test suite is executed.')
help='Test to run. Can be specified as a Robocop test name (like "testLoad"), '
'or omitted. If omitted, the entire test suite is executed.')
def run_robocop(self, test_path):
self.tests_dir = os.path.join(self.topobjdir, '_tests')
self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
self.mochitest_dir = os.path.join(
self.tests_dir,
'testing',
'mochitest')
import imp
path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
with open(path, 'r') as fh:
imp.load_module('runtestsremote', fh, path,
('.py', 'r', imp.PY_SOURCE))
('.py', 'r', imp.PY_SOURCE))
import runtestsremote
args = [
'--xre-path=' + os.environ.get('MOZ_HOST_BIN'),
'--xre-path=' +
os.environ.get('MOZ_HOST_BIN'),
'--dm_trans=adb',
'--deviceIP=',
'--console-level=INFO',
'--app=' + self.substs['ANDROID_PACKAGE_NAME'],
'--robocop-apk=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop-debug.apk'),
'--robocop-ini=' + os.path.join(self.topobjdir, 'build', 'mobile', 'robocop', 'robocop.ini'),
'--app=' +
self.substs['ANDROID_PACKAGE_NAME'],
'--robocop-apk=' +
os.path.join(
self.topobjdir,
'build',
'mobile',
'robocop',
'robocop-debug.apk'),
'--robocop-ini=' +
os.path.join(
self.topobjdir,
'build',
'mobile',
'robocop',
'robocop.ini'),
'--log-mach=-',
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -23,14 +23,15 @@ from mozprofile import Profile, Preferences
from mozlog import structured
import mozinfo
class B2GMochitest(MochitestUtilsMixin):
marionette = None
def __init__(self, marionette_args,
logger_options,
out_of_process=True,
profile_data_dir=None,
locations=os.path.join(here, 'server-locations.txt')):
logger_options,
out_of_process=True,
profile_data_dir=None,
locations=os.path.join(here, 'server-locations.txt')):
super(B2GMochitest, self).__init__(logger_options)
self.marionette_args = marionette_args
self.out_of_process = out_of_process
@ -43,10 +44,14 @@ class B2GMochitest(MochitestUtilsMixin):
self.remote_chrome_test_dir = None
if profile_data_dir:
self.preferences = [os.path.join(profile_data_dir, f)
for f in os.listdir(profile_data_dir) if f.startswith('pref')]
self.webapps = [os.path.join(profile_data_dir, f)
for f in os.listdir(profile_data_dir) if f.startswith('webapp')]
self.preferences = [
os.path.join(
profile_data_dir,
f) for f in os.listdir(profile_data_dir) if f.startswith('pref')]
self.webapps = [
os.path.join(
profile_data_dir,
f) for f in os.listdir(profile_data_dir) if f.startswith('webapp')]
# mozinfo is populated by the parent class
if mozinfo.info['debug']:
@ -68,7 +73,12 @@ class B2GMochitest(MochitestUtilsMixin):
def buildTestPath(self, options, testsToFilter=None):
if options.manifestFile != 'tests.json':
super(B2GMochitest, self).buildTestPath(options, testsToFilter, disabled=False)
super(
B2GMochitest,
self).buildTestPath(
options,
testsToFilter,
disabled=False)
return self.buildTestURL(options)
def build_profile(self, options):
@ -85,8 +95,11 @@ class B2GMochitest(MochitestUtilsMixin):
prefs[thispref[0]] = thispref[1]
# interpolate the preferences
interpolation = { "server": "%s:%s" % (options.webServer, options.httpPort),
"OOP": "true" if self.out_of_process else "false" }
interpolation = {
"server": "%s:%s" %
(options.webServer,
options.httpPort),
"OOP": "true" if self.out_of_process else "false"}
prefs = json.loads(json.dumps(prefs) % interpolation)
for pref in prefs:
prefs[pref] = Preferences.cast(prefs[pref])
@ -138,7 +151,8 @@ class B2GMochitest(MochitestUtilsMixin):
if message['action'] == 'test_start':
self.runner.last_test = message['test']
# The logging will be handled by on_output, so we set the stream to None
# The logging will be handled by on_output, so we set the stream to
# None
process_args = {'processOutputLine': on_output,
'stream': None}
self.marionette_args['process_args'] = process_args
@ -150,23 +164,29 @@ class B2GMochitest(MochitestUtilsMixin):
self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
'log', 'mochitest.log')
if not self.app_ctx.dm.dirExists(posixpath.dirname(self.remote_log)):
if not self.app_ctx.dm.dirExists(
posixpath.dirname(
self.remote_log)):
self.app_ctx.dm.mkDirs(self.remote_log)
if options.chrome:
# Update chrome manifest file in profile with correct path.
self.writeChromeManifest(options)
self.leak_report_file = posixpath.join(self.app_ctx.remote_test_root,
'log', 'runtests_leaks.log')
self.leak_report_file = posixpath.join(
self.app_ctx.remote_test_root,
'log',
'runtests_leaks.log')
# We don't want to copy the host env onto the device, so pass in an
# empty env.
self.browserEnv = self.buildBrowserEnv(options, env={})
# B2G emulator debug tests still make external connections, so don't
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug 1039019).
if mozinfo.info['debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
# pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug
# 1039019).
if mozinfo.info[
'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
self.runner.env.update(self.browserEnv)
@ -176,7 +196,6 @@ class B2GMochitest(MochitestUtilsMixin):
self.test_script_args.append(options.wifi)
self.test_script_args.append(options.chrome)
self.runner.start(outputTimeout=timeout)
self.marionette.wait_for_port()
@ -185,7 +204,8 @@ class B2GMochitest(MochitestUtilsMixin):
# Disable offline status management (bug 777145), otherwise the network
# will be 'offline' when the mochitests start. Presumably, the network
# won't be offline on a real device, so we only do this for emulators.
# won't be offline on a real device, so we only do this for
# emulators.
self.marionette.execute_script("""
Components.utils.import("resource://gre/modules/Services.jsm");
Services.io.manageOfflineStatus = false;
@ -198,16 +218,20 @@ class B2GMochitest(MochitestUtilsMixin):
local = super(B2GMochitest, self).getChromeTestDir(options)
local = os.path.join(local, "chrome")
remote = self.remote_chrome_test_dir
self.log.info("pushing %s to %s on device..." % (local, remote))
self.log.info(
"pushing %s to %s on device..." %
(local, remote))
self.app_ctx.dm.pushDir(local, remote)
if os.path.isfile(self.test_script):
with open(self.test_script, 'r') as script:
self.marionette.execute_script(script.read(),
script_args=self.test_script_args)
self.marionette.execute_script(
script.read(),
script_args=self.test_script_args)
else:
self.marionette.execute_script(self.test_script,
script_args=self.test_script_args)
self.marionette.execute_script(
self.test_script,
script_args=self.test_script_args)
status = self.runner.wait()
if status is None:
@ -215,16 +239,19 @@ class B2GMochitest(MochitestUtilsMixin):
status = 124
local_leak_file = tempfile.NamedTemporaryFile()
self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name)
self.app_ctx.dm.getFile(
self.leak_report_file,
local_leak_file.name)
self.app_ctx.dm.removeFile(self.leak_report_file)
processLeakLog(local_leak_file.name, options)
except KeyboardInterrupt:
self.log.info("runtests.py | Received keyboard interrupt.\n");
self.log.info("runtests.py | Received keyboard interrupt.\n")
status = -1
except:
traceback.print_exc()
self.log.error("Automation Error: Received unexpected exception while running application\n")
self.log.error(
"Automation Error: Received unexpected exception while running application\n")
if hasattr(self, 'runner'):
self.runner.check_for_crashes()
status = 1
@ -249,7 +276,9 @@ class B2GMochitest(MochitestUtilsMixin):
# is defined; the correct directory will be returned later, over-
# writing the dummy.
if hasattr(self, 'app_ctx'):
self.remote_chrome_test_dir = posixpath.join(self.app_ctx.remote_test_root, 'chrome');
self.remote_chrome_test_dir = posixpath.join(
self.app_ctx.remote_test_root,
'chrome')
return self.remote_chrome_test_dir
return 'dummy-chrome-test-dir'
@ -257,9 +286,20 @@ class B2GMochitest(MochitestUtilsMixin):
class B2GDeviceMochitest(B2GMochitest, Mochitest):
remote_log = None
def __init__(self, marionette_args, logger_options, profile_data_dir,
local_binary_dir, remote_test_root=None, remote_log_file=None):
B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=True, profile_data_dir=profile_data_dir)
def __init__(
self,
marionette_args,
logger_options,
profile_data_dir,
local_binary_dir,
remote_test_root=None,
remote_log_file=None):
B2GMochitest.__init__(
self,
marionette_args,
logger_options,
out_of_process=True,
profile_data_dir=profile_data_dir)
self.local_log = None
self.local_binary_dir = local_binary_dir
@ -314,7 +354,12 @@ class B2GDeviceMochitest(B2GMochitest, Mochitest):
class B2GDesktopMochitest(B2GMochitest, Mochitest):
def __init__(self, marionette_args, logger_options, profile_data_dir):
B2GMochitest.__init__(self, marionette_args, logger_options, out_of_process=False, profile_data_dir=profile_data_dir)
B2GMochitest.__init__(
self,
marionette_args,
logger_options,
out_of_process=False,
profile_data_dir=profile_data_dir)
Mochitest.__init__(self, logger_options)
self.certdbNew = True
@ -347,7 +392,10 @@ class B2GDesktopMochitest(B2GMochitest, Mochitest):
self.setup_common_options(options)
# Copy the extensions to the B2G bundles dir.
extensionDir = os.path.join(options.profilePath, 'extensions', 'staged')
extensionDir = os.path.join(
options.profilePath,
'extensions',
'staged')
bundlesDir = os.path.join(os.path.dirname(options.app),
'distribution', 'bundles')
@ -378,15 +426,19 @@ def run_remote_mochitests(parser, options):
marionette_args['port'] = int(port)
options = parser.verifyRemoteOptions(options)
if (options == None):
if (options is None):
print "ERROR: Invalid options specified, use --help for a list of valid options"
sys.exit(1)
mochitest = B2GDeviceMochitest(marionette_args, options, options.profile_data_dir,
options.xrePath, remote_log_file=options.remoteLogFile)
mochitest = B2GDeviceMochitest(
marionette_args,
options,
options.profile_data_dir,
options.xrePath,
remote_log_file=options.remoteLogFile)
options = parser.verifyOptions(options, mochitest)
if (options == None):
if (options is None):
sys.exit(1)
retVal = 1
@ -407,6 +459,7 @@ def run_remote_mochitests(parser, options):
sys.exit(retVal)
def run_desktop_mochitests(parser, options):
# create our Marionette instance
marionette_args = {}
@ -420,9 +473,12 @@ def run_desktop_mochitests(parser, options):
if os.path.isfile("%s-bin" % options.app):
options.app = "%s-bin" % options.app
mochitest = B2GDesktopMochitest(marionette_args, options, options.profile_data_dir)
mochitest = B2GDesktopMochitest(
marionette_args,
options,
options.profile_data_dir)
options = MochitestOptions.verifyOptions(parser, options, mochitest)
if options == None:
if options is None:
sys.exit(1)
if options.desktop and not options.profile:
@ -435,6 +491,7 @@ def run_desktop_mochitests(parser, options):
sys.exit(retVal)
def main():
parser = B2GOptions()
structured.commandline.add_logging_group(parser)

View File

@ -13,7 +13,10 @@ import sys
import tempfile
import traceback
sys.path.insert(0, os.path.abspath(os.path.realpath(os.path.dirname(__file__))))
sys.path.insert(
0, os.path.abspath(
os.path.realpath(
os.path.dirname(__file__))))
from automation import Automation
from remoteautomation import RemoteAutomation, fennecLogcatFilters
@ -29,6 +32,7 @@ import moznetwork
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
class RemoteOptions(MochitestOptions):
def __init__(self, automation, **kwargs):
@ -36,84 +40,117 @@ class RemoteOptions(MochitestOptions):
self._automation = automation or Automation()
MochitestOptions.__init__(self)
self.add_option("--remote-app-path", action="store",
type = "string", dest = "remoteAppPath",
help = "Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both")
self.add_option(
"--remote-app-path",
action="store",
type="string",
dest="remoteAppPath",
help="Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both")
defaults["remoteAppPath"] = None
self.add_option("--deviceIP", action="store",
type = "string", dest = "deviceIP",
help = "ip address of remote device to test")
type="string", dest="deviceIP",
help="ip address of remote device to test")
defaults["deviceIP"] = None
self.add_option("--deviceSerial", action="store",
type = "string", dest = "deviceSerial",
help = "ip address of remote device to test")
type="string", dest="deviceSerial",
help="ip address of remote device to test")
defaults["deviceSerial"] = None
self.add_option("--dm_trans", action="store",
type = "string", dest = "dm_trans",
help = "the transport to use to communicate with device: [adb|sut]; default=sut")
self.add_option(
"--dm_trans",
action="store",
type="string",
dest="dm_trans",
help="the transport to use to communicate with device: [adb|sut]; default=sut")
defaults["dm_trans"] = "sut"
self.add_option("--devicePort", action="store",
type = "string", dest = "devicePort",
help = "port of remote device to test")
type="string", dest="devicePort",
help="port of remote device to test")
defaults["devicePort"] = 20701
self.add_option("--remote-product-name", action="store",
type = "string", dest = "remoteProductName",
help = "The executable's name of remote product to test - either fennec or firefox, defaults to fennec")
self.add_option(
"--remote-product-name",
action="store",
type="string",
dest="remoteProductName",
help="The executable's name of remote product to test - either fennec or firefox, defaults to fennec")
defaults["remoteProductName"] = "fennec"
self.add_option("--remote-logfile", action="store",
type = "string", dest = "remoteLogFile",
help = "Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.")
self.add_option(
"--remote-logfile",
action="store",
type="string",
dest="remoteLogFile",
help="Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.")
defaults["remoteLogFile"] = None
self.add_option("--remote-webserver", action = "store",
type = "string", dest = "remoteWebServer",
help = "ip address where the remote web server is hosted at")
self.add_option(
"--remote-webserver",
action="store",
type="string",
dest="remoteWebServer",
help="ip address where the remote web server is hosted at")
defaults["remoteWebServer"] = None
self.add_option("--http-port", action = "store",
type = "string", dest = "httpPort",
help = "http port of the remote web server")
self.add_option("--http-port", action="store",
type="string", dest="httpPort",
help="http port of the remote web server")
defaults["httpPort"] = automation.DEFAULT_HTTP_PORT
self.add_option("--ssl-port", action = "store",
type = "string", dest = "sslPort",
help = "ssl port of the remote web server")
self.add_option("--ssl-port", action="store",
type="string", dest="sslPort",
help="ssl port of the remote web server")
defaults["sslPort"] = automation.DEFAULT_SSL_PORT
self.add_option("--robocop-ini", action = "store",
type = "string", dest = "robocopIni",
help = "name of the .ini file containing the list of tests to run")
self.add_option(
"--robocop-ini",
action="store",
type="string",
dest="robocopIni",
help="name of the .ini file containing the list of tests to run")
defaults["robocopIni"] = ""
self.add_option("--robocop", action = "store",
type = "string", dest = "robocop",
help = "name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
self.add_option(
"--robocop",
action="store",
type="string",
dest="robocop",
help="name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
defaults["robocop"] = ""
self.add_option("--robocop-apk", action = "store",
type = "string", dest = "robocopApk",
help = "name of the Robocop APK to use for ADB test running")
self.add_option(
"--robocop-apk",
action="store",
type="string",
dest="robocopApk",
help="name of the Robocop APK to use for ADB test running")
defaults["robocopApk"] = ""
self.add_option("--robocop-path", action = "store",
type = "string", dest = "robocopPath",
help = "Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
self.add_option(
"--robocop-path",
action="store",
type="string",
dest="robocopPath",
help="Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
defaults["robocopPath"] = ""
self.add_option("--robocop-ids", action = "store",
type = "string", dest = "robocopIds",
help = "name of the file containing the view ID map (fennec_ids.txt)")
self.add_option(
"--robocop-ids",
action="store",
type="string",
dest="robocopIds",
help="name of the file containing the view ID map (fennec_ids.txt)")
defaults["robocopIds"] = ""
self.add_option("--remoteTestRoot", action = "store",
type = "string", dest = "remoteTestRoot",
help = "remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
self.add_option(
"--remoteTestRoot",
action="store",
type="string",
dest="remoteTestRoot",
help="remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
defaults["remoteTestRoot"] = None
defaults["logFile"] = "mochitest.log"
@ -131,38 +168,43 @@ class RemoteOptions(MochitestOptions):
if not options.remoteTestRoot:
options.remoteTestRoot = automation._devicemanager.deviceRoot
if options.remoteWebServer == None:
if options.remoteWebServer is None:
if os.name != "nt":
options.remoteWebServer = moznetwork.get_ip()
else:
options_logger.error("you must specify a --remote-webserver=<ip address>")
options_logger.error(
"you must specify a --remote-webserver=<ip address>")
return None
options.webServer = options.remoteWebServer
if (options.dm_trans == 'sut' and options.deviceIP == None):
options_logger.error("If --dm_trans = sut, you must provide a device IP")
if (options.dm_trans == 'sut' and options.deviceIP is None):
options_logger.error(
"If --dm_trans = sut, you must provide a device IP")
return None
if (options.remoteLogFile == None):
options.remoteLogFile = options.remoteTestRoot + '/logs/mochitest.log'
if (options.remoteLogFile is None):
options.remoteLogFile = options.remoteTestRoot + \
'/logs/mochitest.log'
if (options.remoteLogFile.count('/') < 1):
options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile
options.remoteLogFile = options.remoteTestRoot + \
'/' + options.remoteLogFile
# remoteAppPath or app must be specified to find the product to launch
if (options.remoteAppPath and options.app):
options_logger.error("You cannot specify both the remoteAppPath and the app setting")
options_logger.error(
"You cannot specify both the remoteAppPath and the app setting")
return None
elif (options.remoteAppPath):
options.app = options.remoteTestRoot + "/" + options.remoteAppPath
elif (options.app == None):
elif (options.app is None):
# Neither remoteAppPath nor app are set -- error
options_logger.error("You must specify either appPath or app")
return None
# Only reset the xrePath if it wasn't provided
if (options.xrePath == None):
if (options.xrePath is None):
options.xrePath = options.utilityPath
if (options.pidFile != ""):
@ -173,38 +215,49 @@ class RemoteOptions(MochitestOptions):
# Robocop specific deprecated options.
if options.robocop:
if options.robocopIni:
options_logger.error("can not use deprecated --robocop and replacement --robocop-ini together")
options_logger.error(
"can not use deprecated --robocop and replacement --robocop-ini together")
return None
options.robocopIni = options.robocop
del options.robocop
if options.robocopPath:
if options.robocopApk:
options_logger.error("can not use deprecated --robocop-path and replacement --robocop-apk together")
options_logger.error(
"can not use deprecated --robocop-path and replacement --robocop-apk together")
return None
options.robocopApk = os.path.join(options.robocopPath, 'robocop.apk')
options.robocopApk = os.path.join(
options.robocopPath,
'robocop.apk')
del options.robocopPath
# Robocop specific options
if options.robocopIni != "":
if not os.path.exists(options.robocopIni):
options_logger.error("Unable to find specified robocop .ini manifest '%s'" % options.robocopIni)
options_logger.error(
"Unable to find specified robocop .ini manifest '%s'" %
options.robocopIni)
return None
options.robocopIni = os.path.abspath(options.robocopIni)
if options.robocopApk != "":
if not os.path.exists(options.robocopApk):
options_logger.error("Unable to find robocop APK '%s'" % options.robocopApk)
options_logger.error(
"Unable to find robocop APK '%s'" %
options.robocopApk)
return None
options.robocopApk = os.path.abspath(options.robocopApk)
if options.robocopIds != "":
if not os.path.exists(options.robocopIds):
options_logger.error("Unable to find specified robocop IDs file '%s'" % options.robocopIds)
options_logger.error(
"Unable to find specified robocop IDs file '%s'" %
options.robocopIds)
return None
options.robocopIds = os.path.abspath(options.robocopIds)
# allow us to keep original application around for cleanup while running robocop via 'am'
# allow us to keep original application around for cleanup while
# running robocop via 'am'
options.remoteappname = options.app
return options
@ -226,6 +279,7 @@ class RemoteOptions(MochitestOptions):
return options
class MochiRemote(Mochitest):
_automation = None
@ -247,20 +301,24 @@ class MochiRemote(Mochitest):
self._automation.deleteTombstones()
self.certdbNew = True
self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
self._dm.removeDir(self.remoteNSPR);
self._dm.mkDir(self.remoteNSPR);
self.remoteChromeTestDir = os.path.join(options.remoteTestRoot, "chrome")
self._dm.removeDir(self.remoteChromeTestDir);
self._dm.mkDir(self.remoteChromeTestDir);
self._dm.removeDir(self.remoteNSPR)
self._dm.mkDir(self.remoteNSPR)
self.remoteChromeTestDir = os.path.join(
options.remoteTestRoot,
"chrome")
self._dm.removeDir(self.remoteChromeTestDir)
self._dm.mkDir(self.remoteChromeTestDir)
def cleanup(self, options):
if self._dm.fileExists(self.remoteLog):
self._dm.getFile(self.remoteLog, self.localLog)
self._dm.removeFile(self.remoteLog)
else:
self.log.warning("Unable to retrieve log file (%s) from remote device" % self.remoteLog)
self.log.warning(
"Unable to retrieve log file (%s) from remote device" %
self.remoteLog)
self._dm.removeDir(self.remoteProfile)
self._dm.removeDir(self.remoteChromeTestDir);
self._dm.removeDir(self.remoteChromeTestDir)
# Don't leave an old robotium.config hanging around; the
# profile it references was just deleted!
deviceRoot = self._dm.getDeviceRoot()
@ -270,7 +328,7 @@ class MochiRemote(Mochitest):
self._dm.getDirectory(self.remoteNSPR, blobberUploadDir)
Mochitest.cleanup(self, options)
def findPath(self, paths, filename = None):
def findPath(self, paths, filename=None):
for path in paths:
p = path
if filename:
@ -286,7 +344,7 @@ class MochiRemote(Mochitest):
localAutomation.IS_MAC = False
localAutomation.UNIXISH = False
hostos = sys.platform
if (hostos == 'mac' or hostos == 'darwin'):
if (hostos == 'mac' or hostos == 'darwin'):
localAutomation.IS_MAC = True
elif (hostos == 'linux' or hostos == 'linux2'):
localAutomation.IS_LINUX = True
@ -315,8 +373,10 @@ class MochiRemote(Mochitest):
os.path.join('..', self._automation._product)
]
options.xrePath = self.findPath(paths)
if options.xrePath == None:
self.log.error("unable to find xulrunner path for %s, please specify with --xre-path" % os.name)
if options.xrePath is None:
self.log.error(
"unable to find xulrunner path for %s, please specify with --xre-path" %
os.name)
sys.exit(1)
xpcshell = "xpcshell"
@ -329,15 +389,17 @@ class MochiRemote(Mochitest):
paths = [options.xrePath]
options.utilityPath = self.findPath(paths, xpcshell)
if options.utilityPath == None:
self.log.error("unable to find utility path for %s, please specify with --utility-path" % os.name)
if options.utilityPath is None:
self.log.error(
"unable to find utility path for %s, please specify with --utility-path" %
os.name)
sys.exit(1)
xpcshell_path = os.path.join(options.utilityPath, xpcshell)
if localAutomation.elf_arm(xpcshell_path):
self.log.error('xpcshell at %s is an ARM binary; please use '
'the --utility-path argument to specify the path '
'to a desktop version.' % xpcshell_path)
'the --utility-path argument to specify the path '
'to a desktop version.' % xpcshell_path)
sys.exit(1)
if self.localProfile:
@ -356,7 +418,11 @@ class MochiRemote(Mochitest):
""" Create the servers on the host and start them up """
restoreRemotePaths = self.switchToLocalPaths(options)
# ignoreSSLTunnelExts is a workaround for bug 1109310
Mochitest.startServers(self, options, debuggerInfo, ignoreSSLTunnelExts = True)
Mochitest.startServers(
self,
options,
debuggerInfo,
ignoreSSLTunnelExts=True)
restoreRemotePaths()
def buildProfile(self, options):
@ -368,15 +434,31 @@ class MochiRemote(Mochitest):
# we do not need this for robotium based tests, lets save a LOT of time
if options.robocopIni:
shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'mochikit@mozilla.org'))
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'worker-test@mozilla.org'))
shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'workerbootstrap-test@mozilla.org'))
shutil.rmtree(
os.path.join(
options.profilePath,
'extensions',
'staged',
'mochikit@mozilla.org'))
shutil.rmtree(
os.path.join(
options.profilePath,
'extensions',
'staged',
'worker-test@mozilla.org'))
shutil.rmtree(
os.path.join(
options.profilePath,
'extensions',
'staged',
'workerbootstrap-test@mozilla.org'))
os.remove(os.path.join(options.profilePath, 'userChrome.css'))
try:
self._dm.pushDir(options.profilePath, self.remoteProfile)
except devicemanager.DMError:
self.log.error("Automation Error: Unable to copy profile to device.")
self.log.error(
"Automation Error: Unable to copy profile to device.")
raise
restoreRemotePaths()
@ -392,11 +474,12 @@ class MochiRemote(Mochitest):
retVal = Mochitest.buildURLOptions(self, options, env)
if not options.robocopIni:
#we really need testConfig.js (for browser chrome)
# we really need testConfig.js (for browser chrome)
try:
self._dm.pushDir(options.profilePath, self.remoteProfile)
except devicemanager.DMError:
self.log.error("Automation Error: Unable to copy profile to device.")
self.log.error(
"Automation Error: Unable to copy profile to device.")
raise
options.profilePath = self.remoteProfile
@ -416,7 +499,11 @@ class MochiRemote(Mochitest):
# robocop tests.
return self.buildTestURL(options)
else:
return super(MochiRemote, self).buildTestPath(options, testsToFilter)
return super(
MochiRemote,
self).buildTestPath(
options,
testsToFilter)
def getChromeTestDir(self, options):
local = super(MochiRemote, self).getChromeTestDir(options)
@ -430,7 +517,8 @@ class MochiRemote(Mochitest):
def getLogFilePath(self, logFile):
return logFile
# In the future we could use LogParser: http://hg.mozilla.org/automation/logparser/
# In the future we could use LogParser:
# http://hg.mozilla.org/automation/logparser/
def addLogData(self):
with open(self.localLog) as currentLog:
data = currentLog.readlines()
@ -461,7 +549,8 @@ class MochiRemote(Mochitest):
if fail_found:
result = 1
if not end_found:
self.log.info("PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
self.log.info(
"PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
result = 1
return result
@ -494,7 +583,8 @@ class MochiRemote(Mochitest):
incr += 1
logFile.append("%s INFO SimpleTest FINISHED" % incr)
# TODO: Consider not printing to stdout because we might be duplicating output
# TODO: Consider not printing to stdout because we might be duplicating
# output
print '\n'.join(logFile)
with open(self.localLog, 'w') as localLog:
localLog.write('\n'.join(logFile))
@ -506,7 +596,9 @@ class MochiRemote(Mochitest):
def printScreenshots(self, screenShotDir):
# TODO: This can be re-written after completion of bug 749421
if not self._dm.dirExists(screenShotDir):
self.log.info("SCREENSHOT: No ScreenShots directory available: " + screenShotDir)
self.log.info(
"SCREENSHOT: No ScreenShots directory available: " +
screenShotDir)
return
printed = 0
@ -527,8 +619,13 @@ class MochiRemote(Mochitest):
def printDeviceInfo(self, printLogcat=False):
try:
if printLogcat:
logcat = self._dm.getLogcat(filterOutRegexps=fennecLogcatFilters)
self.log.info('\n' + ''.join(logcat).decode('utf-8', 'replace'))
logcat = self._dm.getLogcat(
filterOutRegexps=fennecLogcatFilters)
self.log.info(
'\n' +
''.join(logcat).decode(
'utf-8',
'replace'))
self.log.info("Device info: %s" % self._dm.getInfo())
self.log.info("Test root: %s" % self._dm.deviceRoot)
except devicemanager.DMError:
@ -543,7 +640,9 @@ class MochiRemote(Mochitest):
fHandle.write("profile=%s\n" % (self.remoteProfile))
fHandle.write("logfile=%s\n" % (options.remoteLogFile))
fHandle.write("host=http://mochi.test:8888/tests\n")
fHandle.write("rawhost=http://%s:%s/tests\n" % (options.remoteWebServer, options.httpPort))
fHandle.write(
"rawhost=http://%s:%s/tests\n" %
(options.remoteWebServer, options.httpPort))
if browserEnv:
envstr = ""
@ -551,7 +650,9 @@ class MochiRemote(Mochitest):
for key, value in browserEnv.items():
try:
value.index(',')
self.log.error("buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" % (key, value))
self.log.error(
"buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" %
(key, value))
self.log.error("browserEnv=%s" % browserEnv)
except ValueError:
envstr += "%s%s=%s" % (delim, key, value)
@ -561,7 +662,11 @@ class MochiRemote(Mochitest):
fHandle.close()
self._dm.removeFile(os.path.join(deviceRoot, "robotium.config"))
self._dm.pushFile(fHandle.name, os.path.join(deviceRoot, "robotium.config"))
self._dm.pushFile(
fHandle.name,
os.path.join(
deviceRoot,
"robotium.config"))
os.unlink(fHandle.name)
def getGMPPluginPath(self, options):
@ -569,10 +674,15 @@ class MochiRemote(Mochitest):
return None
def buildBrowserEnv(self, options, debugger=False):
browserEnv = Mochitest.buildBrowserEnv(self, options, debugger=debugger)
browserEnv = Mochitest.buildBrowserEnv(
self,
options,
debugger=debugger)
# override nsprLogs to avoid processing in Mochitest base class
self.nsprLogs = None
browserEnv["NSPR_LOG_FILE"] = os.path.join(self.remoteNSPR, self.nsprLogName)
browserEnv["NSPR_LOG_FILE"] = os.path.join(
self.remoteNSPR,
self.nsprLogName)
self.buildRobotiumConfig(options, browserEnv)
return browserEnv
@ -593,6 +703,7 @@ class MochiRemote(Mochitest):
return self._automation.runApp(*args, **kwargs)
def main(args):
message_logger = MessageLogger(logger=None)
process_args = {'messageLogger': message_logger}
@ -604,13 +715,23 @@ def main(args):
if (options.dm_trans == "adb"):
if (options.deviceIP):
dm = droid.DroidADB(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
dm = droid.DroidADB(
options.deviceIP,
options.devicePort,
deviceRoot=options.remoteTestRoot)
elif (options.deviceSerial):
dm = droid.DroidADB(None, None, deviceSerial=options.deviceSerial, deviceRoot=options.remoteTestRoot)
dm = droid.DroidADB(
None,
None,
deviceSerial=options.deviceSerial,
deviceRoot=options.remoteTestRoot)
else:
dm = droid.DroidADB(deviceRoot=options.remoteTestRoot)
else:
dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
dm = droid.DroidSUT(
options.deviceIP,
options.devicePort,
deviceRoot=options.remoteTestRoot)
auto.setDeviceManager(dm)
options = parser.verifyRemoteOptions(options, auto)
@ -620,23 +741,24 @@ def main(args):
message_logger.logger = log
mochitest.message_logger = message_logger
if (options == None):
log.error("Invalid options specified, use --help for a list of valid options")
if (options is None):
log.error(
"Invalid options specified, use --help for a list of valid options")
return 1
productPieces = options.remoteProductName.split('.')
if (productPieces != None):
if (productPieces is not None):
auto.setProduct(productPieces[0])
else:
auto.setProduct(options.remoteProductName)
auto.setAppName(options.remoteappname)
options = parser.verifyOptions(options, mochitest)
if (options == None):
if (options is None):
return 1
logParent = os.path.dirname(options.remoteLogFile)
dm.mkDir(logParent);
dm.mkDir(logParent)
auto.setRemoteLog(options.remoteLogFile)
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
@ -645,7 +767,9 @@ def main(args):
# Add Android version (SDK level) to mozinfo so that manifest entries
# can be conditional on android_version.
androidVersion = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk'])
log.info("Android sdk version '%s'; will use this to filter manifests" % str(androidVersion))
log.info(
"Android sdk version '%s'; will use this to filter manifests" %
str(androidVersion))
mozinfo.info['android_version'] = androidVersion
deviceRoot = dm.deviceRoot
@ -677,13 +801,14 @@ def main(args):
tests.append(test['name'])
if options.totalChunks:
tests_per_chunk = math.ceil(len(tests) / (options.totalChunks * 1.0))
start = int(round((options.thisChunk-1) * tests_per_chunk))
tests_per_chunk = math.ceil(
len(tests) / (options.totalChunks * 1.0))
start = int(round((options.thisChunk - 1) * tests_per_chunk))
end = int(round(options.thisChunk * tests_per_chunk))
if end > len(tests):
end = len(tests)
my_tests = tests[start:end]
log.info("Running tests %d-%d/%d" % (start+1, end, len(tests)))
log.info("Running tests %d-%d/%d" % (start + 1, end, len(tests)))
options.extraPrefs.append('browser.search.suggest.enabled=true')
options.extraPrefs.append('browser.search.suggest.prompted=true')
@ -706,7 +831,9 @@ def main(args):
continue
if 'disabled' in test:
log.info('TEST-INFO | skipping %s | %s' % (test['name'], test['disabled']))
log.info(
'TEST-INFO | skipping %s | %s' %
(test['name'], test['disabled']))
continue
active_tests.append(test)
@ -714,7 +841,8 @@ def main(args):
log.suite_start([t['name'] for t in active_tests])
for test in active_tests:
# When running in a loop, we need to create a fresh profile for each cycle
# When running in a loop, we need to create a fresh profile for
# each cycle
if mochitest.localProfile:
options.profilePath = mochitest.localProfile
os.system("rm -Rf %s" % options.profilePath)
@ -722,34 +850,75 @@ def main(args):
mochitest.localProfile = options.profilePath
options.app = "am"
options.browserArgs = ["instrument", "-w", "-e", "deviceroot", deviceRoot, "-e", "class"]
options.browserArgs.append("org.mozilla.gecko.tests.%s" % test['name'])
options.browserArgs.append("org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
options.browserArgs = [
"instrument",
"-w",
"-e",
"deviceroot",
deviceRoot,
"-e",
"class"]
options.browserArgs.append(
"org.mozilla.gecko.tests.%s" %
test['name'])
options.browserArgs.append(
"org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
mochitest.nsprLogName = "nspr-%s.log" % test['name']
# If the test is for checking the import from bookmarks then make sure there is data to import
# If the test is for checking the import from bookmarks then make
# sure there is data to import
if test['name'] == "testImportFromAndroid":
# Get the OS so we can run the insert in the apropriate database and following the correct table schema
# Get the OS so we can run the insert in the apropriate
# database and following the correct table schema
osInfo = dm.getInfo("os")
devOS = " ".join(osInfo['os'])
if ("pandaboard" in devOS):
delete = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
delete = [
'execsu',
'sqlite3',
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
else:
delete = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
delete = [
'execsu',
'sqlite3',
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
if (options.dm_trans == "sut"):
dm._runCmds([{"cmd": " ".join(delete)}])
# Insert the bookmarks
log.info("Insert bookmarks in the default android browser database")
log.info(
"Insert bookmarks in the default android browser database")
for i in range(20):
if ("pandaboard" in devOS):
cmd = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db 'insert or replace into bookmarks(_id,title,url,folder,parent,position) values (" + str(30 + i) + ",\"Bookmark"+ str(i) + "\",\"http://www.bookmark" + str(i) + ".com\",0,1," + str(100 + i) + ");'"]
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)}])
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) +
");'"]
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:
screenShotDir = "/mnt/sdcard/Robotium-Screenshots"
dm.removeDir(screenShotDir)
@ -761,11 +930,13 @@ def main(args):
if result != 0 or log_result != 0:
mochitest.printDeviceInfo(printLogcat=True)
mochitest.printScreenshots(screenShotDir)
# Ensure earlier failures aren't overwritten by success on this run
# Ensure earlier failures aren't overwritten by success on this
# run
if retVal is None or retVal == 0:
retVal = result
except:
log.error("Automation Error: Exception caught while running tests")
log.error(
"Automation Error: Exception caught while running tests")
traceback.print_exc()
mochitest.stopServers()
try:
@ -779,9 +950,15 @@ def main(args):
# Clean-up added bookmarks
if test['name'] == "testImportFromAndroid":
if ("pandaboard" in devOS):
cmd_del = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
cmd_del = [
'execsu',
'sqlite3',
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
else:
cmd_del = ['execsu', 'sqlite3', "/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
cmd_del = [
'execsu',
'sqlite3',
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
if (options.dm_trans == "sut"):
dm._runCmds([{"cmd": " ".join(cmd_del)}])
if retVal is None: