Bug 1147129 - upgrade mochitest from optparse to argparse and move android cli to mochitest_options.py, r=chmanchester

--HG--
extra : rebase_source : ce81dffa5feb0be28e30c250eda4ad66cc0cb199
This commit is contained in:
Andrew Halberstadt 2015-03-24 17:42:24 -04:00
Родитель 99a1fa9768
Коммит 5ffa684d03
5 изменённых файлов: 306 добавлений и 413 удалений

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

@ -161,7 +161,7 @@ class MochitestRunner(MozbuildObject):
from mochitest_options import B2GOptions from mochitest_options import B2GOptions
parser = B2GOptions() parser = B2GOptions()
options = parser.parse_args([])[0] options = parser.parse_args([])
if test_path: if test_path:
if chrome: if chrome:
@ -322,7 +322,7 @@ class MochitestRunner(MozbuildObject):
logging.getLogger().removeHandler(handler) logging.getLogger().removeHandler(handler)
opts = mochitest.MochitestOptions() opts = mochitest.MochitestOptions()
options, args = opts.parse_args([]) options = opts.parse_args([])
options.subsuite = '' options.subsuite = ''
flavor = suite flavor = suite

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

@ -2,14 +2,17 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
from argparse import ArgumentParser
from urlparse import urlparse from urlparse import urlparse
import mozinfo import logging
import moznetwork
import optparse
import os import os
import tempfile import tempfile
from mozprofile import DEFAULT_PORTS from mozprofile import DEFAULT_PORTS
import mozinfo
import moznetwork
from automation import Automation
here = os.path.abspath(os.path.dirname(__file__)) here = os.path.abspath(os.path.dirname(__file__))
@ -24,8 +27,7 @@ __all__ = ["MochitestOptions", "B2GOptions"]
VMWARE_RECORDING_HELPER_BASENAME = "vmwarerecordinghelper" VMWARE_RECORDING_HELPER_BASENAME = "vmwarerecordinghelper"
class MochitestOptions(optparse.OptionParser): class MochitestOptions(ArgumentParser):
"""Usage instructions for runtests.py. """Usage instructions for runtests.py.
All arguments are optional. All arguments are optional.
If --chrome is specified, chrome tests will be run instead of web content tests. If --chrome is specified, chrome tests will be run instead of web content tests.
@ -43,23 +45,17 @@ class MochitestOptions(optparse.OptionParser):
"help": "close the application when tests are done running", "help": "close the application when tests are done running",
}], }],
[["--appname"], [["--appname"],
{"action": "store", {"dest": "app",
"type": "string",
"dest": "app",
"default": None, "default": None,
"help": "absolute path to application, overriding default", "help": "absolute path to application, overriding default",
}], }],
[["--utility-path"], [["--utility-path"],
{"action": "store", {"dest": "utilityPath",
"type": "string",
"dest": "utilityPath",
"default": build_obj.bindir if build_obj is not None else None, "default": build_obj.bindir if build_obj is not None else None,
"help": "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)", "help": "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)",
}], }],
[["--certificate-path"], [["--certificate-path"],
{"action": "store", {"dest": "certPath",
"type": "string",
"dest": "certPath",
"help": "absolute path to directory containing certificate store to use testing profile", "help": "absolute path to directory containing certificate store to use testing profile",
"default": os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs') if build_obj is not None else None, "default": os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs') if build_obj is not None else None,
}], }],
@ -70,19 +66,19 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--timeout"], [["--timeout"],
{"type": "int", {"type": int,
"dest": "timeout", "dest": "timeout",
"help": "per-test timeout in seconds", "help": "per-test timeout in seconds",
"default": None, "default": None,
}], }],
[["--total-chunks"], [["--total-chunks"],
{"type": "int", {"type": int,
"dest": "totalChunks", "dest": "totalChunks",
"help": "how many chunks to split the tests up into", "help": "how many chunks to split the tests up into",
"default": None, "default": None,
}], }],
[["--this-chunk"], [["--this-chunk"],
{"type": "int", {"type": int,
"dest": "thisChunk", "dest": "thisChunk",
"help": "which chunk to run", "help": "which chunk to run",
"default": None, "default": None,
@ -94,7 +90,7 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--chunk-by-dir"], [["--chunk-by-dir"],
{"type": "int", {"type": int,
"dest": "chunkByDir", "dest": "chunkByDir",
"help": "group tests together in the same chunk that are in the same top chunkByDir directories", "help": "group tests together in the same chunk that are in the same top chunkByDir directories",
"default": 0, "default": 0,
@ -112,9 +108,7 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--console-level"], [["--console-level"],
{"action": "store", {"dest": "consoleLevel",
"type": "choice",
"dest": "consoleLevel",
"choices": LOG_LEVELS, "choices": LOG_LEVELS,
"metavar": "LEVEL", "metavar": "LEVEL",
"help": "one of %s to determine the level of console " "help": "one of %s to determine the level of console "
@ -134,30 +128,22 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--test-path"], [["--test-path"],
{"action": "store", {"dest": "testPath",
"type": "string",
"dest": "testPath",
"help": "start in the given directory's tests", "help": "start in the given directory's tests",
"default": "", "default": "",
}], }],
[["--bisect-chunk"], [["--bisect-chunk"],
{"action": "store", {"dest": "bisectChunk",
"type": "string",
"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.",
"default": None, "default": None,
}], }],
[["--start-at"], [["--start-at"],
{"action": "store", {"dest": "startAt",
"type": "string",
"dest": "startAt",
"help": "skip over tests until reaching the given test", "help": "skip over tests until reaching the given test",
"default": "", "default": "",
}], }],
[["--end-at"], [["--end-at"],
{"action": "store", {"dest": "endAt",
"type": "string",
"dest": "endAt",
"help": "don't run any tests after the given one", "help": "don't run any tests after the given one",
"default": "", "default": "",
}], }],
@ -168,8 +154,7 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--subsuite"], [["--subsuite"],
{"action": "store", {"dest": "subsuite",
"dest": "subsuite",
"help": "subsuite of tests to run", "help": "subsuite of tests to run",
"default": None, "default": None,
}], }],
@ -205,7 +190,6 @@ class MochitestOptions(optparse.OptionParser):
}], }],
[["--setenv"], [["--setenv"],
{"action": "append", {"action": "append",
"type": "string",
"dest": "environment", "dest": "environment",
"metavar": "NAME=VALUE", "metavar": "NAME=VALUE",
"help": "sets the given variable in the application's " "help": "sets the given variable in the application's "
@ -214,7 +198,6 @@ class MochitestOptions(optparse.OptionParser):
}], }],
[["--exclude-extension"], [["--exclude-extension"],
{"action": "append", {"action": "append",
"type": "string",
"dest": "extensionsToExclude", "dest": "extensionsToExclude",
"help": "excludes the given extension from being installed " "help": "excludes the given extension from being installed "
"in the test profile", "in the test profile",
@ -222,15 +205,13 @@ class MochitestOptions(optparse.OptionParser):
}], }],
[["--browser-arg"], [["--browser-arg"],
{"action": "append", {"action": "append",
"type": "string",
"dest": "browserArgs", "dest": "browserArgs",
"metavar": "ARG", "metavar": "ARG",
"help": "provides an argument to the test application", "help": "provides an argument to the test application",
"default": [], "default": [],
}], }],
[["--leak-threshold"], [["--leak-threshold"],
{"action": "store", {"type": int,
"type": "int",
"dest": "defaultLeakThreshold", "dest": "defaultLeakThreshold",
"metavar": "THRESHOLD", "metavar": "THRESHOLD",
"help": "fail if the number of bytes leaked in default " "help": "fail if the number of bytes leaked in default "
@ -262,17 +243,13 @@ class MochitestOptions(optparse.OptionParser):
"default": [], "default": [],
}], }],
[["--profile-path"], [["--profile-path"],
{"action": "store", {"dest": "profilePath",
"type": "string",
"dest": "profilePath",
"help": "Directory where the profile will be stored." "help": "Directory where the profile will be stored."
"This directory will be deleted after the tests are finished", "This directory will be deleted after the tests are finished",
"default": None, "default": None,
}], }],
[["--testing-modules-dir"], [["--testing-modules-dir"],
{"action": "store", {"dest": "testingModulesDir",
"type": "string",
"dest": "testingModulesDir",
"help": "Directory where testing-only JS modules are located.", "help": "Directory where testing-only JS modules are located.",
"default": None, "default": None,
}], }],
@ -284,8 +261,7 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--repeat"], [["--repeat"],
{"action": "store", {"type": int,
"type": "int",
"dest": "repeat", "dest": "repeat",
"metavar": "REPEAT", "metavar": "REPEAT",
"help": "repeats the test or set of tests the given number of times, ie: repeat: 1 will run the test twice.", "help": "repeats the test or set of tests the given number of times, ie: repeat: 1 will run the test twice.",
@ -299,23 +275,17 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--manifest"], [["--manifest"],
{"action": "store", {"dest": "manifestFile",
"type": "string",
"dest": "manifestFile",
"help": ".ini format of tests to run.", "help": ".ini format of tests to run.",
"default": None, "default": None,
}], }],
[["--testrun-manifest-file"], [["--testrun-manifest-file"],
{"action": "store", {"dest": "testRunManifestFile",
"type": "string",
"dest": "testRunManifestFile",
"help": "Overrides the default filename of the tests.json manifest file that is created from the manifest and used by the test runners to run the tests. Only useful when running multiple test runs simulatenously on the same machine.", "help": "Overrides the default filename of the tests.json manifest file that is created from the manifest and used by the test runners to run the tests. Only useful when running multiple test runs simulatenously on the same machine.",
"default": 'tests.json', "default": 'tests.json',
}], }],
[["--failure-file"], [["--failure-file"],
{"action": "store", {"dest": "failureFile",
"type": "string",
"dest": "failureFile",
"help": "Filename of the output file where we can store a .json list of failures to be run in the future with --run-only-tests.", "help": "Filename of the output file where we can store a .json list of failures to be run in the future with --run-only-tests.",
"default": None, "default": None,
}], }],
@ -332,15 +302,12 @@ class MochitestOptions(optparse.OptionParser):
"default": False, "default": False,
}], }],
[["--httpd-path"], [["--httpd-path"],
{"action": "store", {"dest": "httpdPath",
"type": "string",
"dest": "httpdPath",
"default": None, "default": None,
"help": "path to the httpd.js file", "help": "path to the httpd.js file",
}], }],
[["--setpref"], [["--setpref"],
{"action": "append", {"action": "append",
"type": "string",
"default": [], "default": [],
"dest": "extraPrefs", "dest": "extraPrefs",
"metavar": "PREF=VALUE", "metavar": "PREF=VALUE",
@ -377,14 +344,12 @@ class MochitestOptions(optparse.OptionParser):
"help": "Run tests with nested_oop preferences and test filtering enabled.", "help": "Run tests with nested_oop preferences and test filtering enabled.",
}], }],
[["--dmd-path"], [["--dmd-path"],
{"action": "store", {"default": None,
"default": None,
"dest": "dmdPath", "dest": "dmdPath",
"help": "Specifies the path to the directory containing the shared library for DMD.", "help": "Specifies the path to the directory containing the shared library for DMD.",
}], }],
[["--dump-output-directory"], [["--dump-output-directory"],
{"action": "store", {"default": None,
"default": None,
"dest": "dumpOutputDirectory", "dest": "dumpOutputDirectory",
"help": "Specifies the directory in which to place dumped memory reports.", "help": "Specifies the directory in which to place dumped memory reports.",
}], }],
@ -423,9 +388,7 @@ class MochitestOptions(optparse.OptionParser):
"help": "Do not print test log lines unless a failure occurs." "help": "Do not print test log lines unless a failure occurs."
}], }],
[["--pidfile"], [["--pidfile"],
{"action": "store", {"dest": "pidFile",
"type": "string",
"dest": "pidFile",
"help": "name of the pidfile to generate", "help": "name of the pidfile to generate",
"default": "", "default": "",
}], }],
@ -436,33 +399,26 @@ class MochitestOptions(optparse.OptionParser):
"help": "Use test media device drivers for media testing.", "help": "Use test media device drivers for media testing.",
}], }],
[["--gmp-path"], [["--gmp-path"],
{"action": "store", {"default": None,
"default": None,
"dest": "gmp_path", "dest": "gmp_path",
"help": "Path to fake GMP plugin. Will be deduced from the binary if not passed.", "help": "Path to fake GMP plugin. Will be deduced from the binary if not passed.",
}], }],
[["--xre-path"], [["--xre-path"],
{"action": "store", {"dest": "xrePath",
"type": "string",
"dest": "xrePath",
"default": None, # individual scripts will set a sane default "default": None, # individual scripts will set a sane default
"help": "absolute path to directory containing XRE (probably xulrunner)", "help": "absolute path to directory containing XRE (probably xulrunner)",
}], }],
[["--symbols-path"], [["--symbols-path"],
{"action": "store", {"dest": "symbolsPath",
"type": "string",
"dest": "symbolsPath",
"default": None, "default": None,
"help": "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols", "help": "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols",
}], }],
[["--debugger"], [["--debugger"],
{"action": "store", {"dest": "debugger",
"dest": "debugger",
"help": "use the given debugger to launch the application", "help": "use the given debugger to launch the application",
}], }],
[["--debugger-args"], [["--debugger-args"],
{"action": "store", {"dest": "debuggerArgs",
"dest": "debuggerArgs",
"help": "pass the given args to the debugger _before_ the application on the command line", "help": "pass the given args to the debugger _before_ the application on the command line",
}], }],
[["--debugger-interactive"], [["--debugger-interactive"],
@ -471,13 +427,13 @@ class MochitestOptions(optparse.OptionParser):
"help": "prevents the test harness from redirecting stdout and stderr for interactive debuggers", "help": "prevents the test harness from redirecting stdout and stderr for interactive debuggers",
}], }],
[["--max-timeouts"], [["--max-timeouts"],
{ "type": "int", {"type": int,
"dest": "maxTimeouts", "dest": "maxTimeouts",
"help": "maximum number of timeouts permitted before halting testing", "help": "maximum number of timeouts permitted before halting testing",
"default": None, "default": None,
}], }],
[["--tag"], [["--tag"],
{ "action": "append", {"action": "append",
"dest": "test_tags", "dest": "test_tags",
"default": None, "default": None,
"help": "filter out tests that don't have the given tag. Can be " "help": "filter out tests that don't have the given tag. Can be "
@ -487,15 +443,13 @@ class MochitestOptions(optparse.OptionParser):
] ]
def __init__(self, **kwargs): def __init__(self, **kwargs):
ArgumentParser.__init__(self, usage=self.__doc__, **kwargs)
optparse.OptionParser.__init__(self, **kwargs)
for option, value in self.mochitest_options: for option, value in self.mochitest_options:
# Allocate new lists so references to original don't get mutated. # Allocate new lists so references to original don't get mutated.
# allowing multiple uses within a single process. # allowing multiple uses within a single process.
if "default" in value and isinstance(value["default"], list): if "default" in value and isinstance(value["default"], list):
value["default"] = [] value["default"] = []
self.add_option(*option, **value) self.add_argument(*option, **value)
self.set_usage(self.__doc__)
def verifyOptions(self, options, mochitest): def verifyOptions(self, options, mochitest):
""" verify correct options and cleanup paths """ """ verify correct options and cleanup paths """
@ -528,7 +482,7 @@ class MochitestOptions(optparse.OptionParser):
if options.xrePath is None: if options.xrePath is None:
# default xrePath to the app path if not provided # default xrePath to the app path if not provided
# but only if an app path was explicitly provided # but only if an app path was explicitly provided
if options.app != self.defaults['app']: if options.app != self.get_default('app'):
options.xrePath = os.path.dirname(options.app) options.xrePath = os.path.dirname(options.app)
if mozinfo.isMac: if mozinfo.isMac:
options.xrePath = os.path.join( options.xrePath = os.path.join(
@ -698,9 +652,7 @@ class MochitestOptions(optparse.OptionParser):
class B2GOptions(MochitestOptions): class B2GOptions(MochitestOptions):
b2g_options = [ b2g_options = [
[["--b2gpath"], [["--b2gpath"],
{"action": "store", {"dest": "b2gPath",
"type": "string",
"dest": "b2gPath",
"help": "path to B2G repo or qemu dir", "help": "path to B2G repo or qemu dir",
"default": None, "default": None,
}], }],
@ -711,30 +663,22 @@ class B2GOptions(MochitestOptions):
"default": False, "default": False,
}], }],
[["--marionette"], [["--marionette"],
{"action": "store", {"dest": "marionette",
"type": "string",
"dest": "marionette",
"help": "host:port to use when connecting to Marionette", "help": "host:port to use when connecting to Marionette",
"default": None, "default": None,
}], }],
[["--emulator"], [["--emulator"],
{"action": "store", {"dest": "emulator",
"type": "string",
"dest": "emulator",
"help": "Architecture of emulator to use: x86 or arm", "help": "Architecture of emulator to use: x86 or arm",
"default": None, "default": None,
}], }],
[["--wifi"], [["--wifi"],
{"action": "store", {"dest": "wifi",
"type": "string",
"dest": "wifi",
"help": "Devine wifi configuration for on device mochitest", "help": "Devine wifi configuration for on device mochitest",
"default": False, "default": False,
}], }],
[["--sdcard"], [["--sdcard"],
{"action": "store", {"dest": "sdcard",
"type": "string",
"dest": "sdcard",
"help": "Define size of sdcard: 1MB, 50MB...etc", "help": "Define size of sdcard: 1MB, 50MB...etc",
"default": "10MB", "default": "10MB",
}], }],
@ -745,89 +689,65 @@ class B2GOptions(MochitestOptions):
"default": False, "default": False,
}], }],
[["--adbpath"], [["--adbpath"],
{"action": "store", {"dest": "adbPath",
"type": "string",
"dest": "adbPath",
"help": "path to adb", "help": "path to adb",
"default": "adb", "default": "adb",
}], }],
[["--deviceIP"], [["--deviceIP"],
{"action": "store", {"dest": "deviceIP",
"type": "string",
"dest": "deviceIP",
"help": "ip address of remote device to test", "help": "ip address of remote device to test",
"default": None, "default": None,
}], }],
[["--devicePort"], [["--devicePort"],
{"action": "store", {"dest": "devicePort",
"type": "string",
"dest": "devicePort",
"help": "port of remote device to test", "help": "port of remote device to test",
"default": 20701, "default": 20701,
}], }],
[["--remote-logfile"], [["--remote-logfile"],
{"action": "store", {"dest": "remoteLogFile",
"type": "string",
"dest": "remoteLogFile",
"help": "Name of log file on the device relative to the device root. \ "help": "Name of log file on the device relative to the device root. \
PLEASE ONLY USE A FILENAME.", PLEASE ONLY USE A FILENAME.",
"default": None, "default": None,
}], }],
[["--remote-webserver"], [["--remote-webserver"],
{"action": "store", {"dest": "remoteWebServer",
"type": "string",
"dest": "remoteWebServer",
"help": "ip address where the remote web server is hosted at", "help": "ip address where the remote web server is hosted at",
"default": None, "default": None,
}], }],
[["--http-port"], [["--http-port"],
{"action": "store", {"dest": "httpPort",
"type": "string",
"dest": "httpPort",
"help": "ip address where the remote web server is hosted at", "help": "ip address where the remote web server is hosted at",
"default": None, "default": DEFAULT_PORTS['http'],
}], }],
[["--ssl-port"], [["--ssl-port"],
{"action": "store", {"dest": "sslPort",
"type": "string",
"dest": "sslPort",
"help": "ip address where the remote web server is hosted at", "help": "ip address where the remote web server is hosted at",
"default": None, "default": DEFAULT_PORTS['https'],
}], }],
[["--gecko-path"], [["--gecko-path"],
{"action": "store", {"dest": "geckoPath",
"type": "string",
"dest": "geckoPath",
"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",
"default": None, "default": None,
}], }],
[["--profile"], [["--profile"],
{"action": "store", {"dest": "profile",
"type": "string",
"dest": "profile",
"help": "for desktop testing, the path to the \ "help": "for desktop testing, the path to the \
gaia profile to use", gaia profile to use",
"default": None, "default": None,
}], }],
[["--logdir"], [["--logdir"],
{"action": "store", {"dest": "logdir",
"type": "string",
"dest": "logdir",
"help": "directory to store log files", "help": "directory to store log files",
"default": None, "default": None,
}], }],
[['--busybox'], [['--busybox'],
{"action": 'store', {"dest": 'busybox',
"type": 'string',
"dest": 'busybox',
"help": "Path to busybox binary to install on device", "help": "Path to busybox binary to install on device",
"default": None, "default": None,
}], }],
[['--profile-data-dir'], [['--profile-data-dir'],
{"action": 'store', {"dest": 'profile_data_dir',
"type": 'string',
"dest": 'profile_data_dir',
"help": "Path to a directory containing preference and other \ "help": "Path to a directory containing preference and other \
data to be installed into the profile", data to be installed into the profile",
"default": os.path.join(here, 'profile_data'), "default": os.path.join(here, 'profile_data'),
@ -838,15 +758,12 @@ class B2GOptions(MochitestOptions):
MochitestOptions.__init__(self) MochitestOptions.__init__(self)
for option in self.b2g_options: for option in self.b2g_options:
self.add_option(*option[0], **option[1]) self.add_argument(*option[0], **option[1])
defaults = {} defaults = {}
defaults["httpPort"] = DEFAULT_PORTS['http']
defaults["sslPort"] = DEFAULT_PORTS['https']
defaults["logFile"] = "mochitest.log" defaults["logFile"] = "mochitest.log"
defaults["autorun"] = True defaults["autorun"] = True
defaults["closeWhenDone"] = True defaults["closeWhenDone"] = True
defaults["testPath"] = ""
defaults["extensionsToExclude"] = ["specialpowers"] defaults["extensionsToExclude"] = ["specialpowers"]
# See dependencies of bug 1038943. # See dependencies of bug 1038943.
defaults["defaultLeakThreshold"] = 5536 defaults["defaultLeakThreshold"] = 5536
@ -909,3 +826,229 @@ class B2GOptions(MochitestOptions):
def elf_arm(self, filename): def elf_arm(self, filename):
data = open(filename, 'rb').read(20) data = open(filename, 'rb').read(20)
return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM
class RemoteOptions(MochitestOptions):
remote_options = [
[["--remote-app-path"],
{"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.",
"default": None,
}],
[["--deviceIP"],
{"dest": "deviceIP",
"help": "ip address of remote device to test",
"default": None,
}],
[["--deviceSerial"],
{"dest": "deviceSerial",
"help": "ip address of remote device to test",
"default": None,
}],
[["--dm_trans"],
{"dest": "dm_trans",
"default": "sut",
"help": "the transport to use to communicate with device: \
[adb|sut]; default=sut",
}],
[["--devicePort"],
{"dest": "devicePort",
"type": int,
"default": 20701,
"help": "port of remote device to test",
}],
[["--remote-product-name"],
{"dest": "remoteProductName",
"default": "fennec",
"help": "The executable's name of remote product to test - either \
fennec or firefox, defaults to fennec",
}],
[["--remote-logfile"],
{"dest": "remoteLogFile",
"default": None,
"help": "Name of log file on the device relative to the device \
root. PLEASE ONLY USE A FILENAME.",
}],
[["--remote-webserver"],
{"dest": "remoteWebServer",
"default": None,
"help": "ip address where the remote web server is hosted at",
}],
[["--http-port"],
{"dest": "httpPort",
"default": DEFAULT_PORTS['http'],
"help": "http port of the remote web server",
}],
[["--ssl-port"],
{"dest": "sslPort",
"default": DEFAULT_PORTS['https'],
"help": "ssl port of the remote web server",
}],
[["--robocop-ini"],
{"dest": "robocopIni",
"default": "",
"help": "name of the .ini file containing the list of tests to run",
}],
[["--robocop"],
{"dest": "robocop",
"default": "",
"help": "name of the .ini file containing the list of tests to run. \
[DEPRECATED- please use --robocop-ini",
}],
[["--robocop-apk"],
{"dest": "robocopApk",
"default": "",
"help": "name of the Robocop APK to use for ADB test running",
}],
[["--robocop-path"],
{"dest": "robocopPath",
"default": "",
"help": "Path to the folder where robocop.apk is located at. \
Primarily used for ADB test running. \
[DEPRECATED- please use --robocop-apk]",
}],
[["--robocop-ids"],
{"dest": "robocopIds",
"default": "",
"help": "name of the file containing the view ID map \
(fennec_ids.txt)",
}],
[["--remoteTestRoot"],
{"dest": "remoteTestRoot",
"default": None,
"help": "remote directory to use as test root \
(eg. /mnt/sdcard/tests or /data/local/tests)",
}],
]
def __init__(self, automation, **kwargs):
self._automation = automation or Automation()
MochitestOptions.__init__(self)
for option in self.remote_options:
self.add_argument(*option[0], **option[1])
defaults = {}
defaults["logFile"] = "mochitest.log"
defaults["autorun"] = True
defaults["closeWhenDone"] = True
defaults["utilityPath"] = None
self.set_defaults(**defaults)
def verifyRemoteOptions(self, options, automation):
options_logger = logging.getLogger('MochitestRemote')
if not options.remoteTestRoot:
options.remoteTestRoot = automation._devicemanager.deviceRoot
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>")
return None
options.webServer = options.remoteWebServer
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 is None):
options.remoteLogFile = options.remoteTestRoot + \
'/logs/mochitest.log'
if (options.remoteLogFile.count('/') < 1):
options.remoteLogFile = options.remoteTestRoot + \
'/' + options.remoteLogFile
if (options.remoteAppPath and options.app):
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 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 is None):
options.xrePath = options.utilityPath
if (options.pidFile != ""):
f = open(options.pidFile, 'w')
f.write("%s" % os.getpid())
f.close()
# Robocop specific deprecated options.
if options.robocop:
if options.robocopIni:
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")
return None
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)
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)
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)
return None
options.robocopIds = os.path.abspath(options.robocopIds)
# allow us to keep original application around for cleanup while
# running robocop via 'am'
options.remoteappname = options.app
return options
def verifyOptions(self, options, mochitest):
# since we are reusing verifyOptions, it will exit if App is not found
temp = options.app
options.app = __file__
tempPort = options.httpPort
tempSSL = options.sslPort
tempIP = options.webServer
# We are going to override this option later anyway, just pretend
# like it's not set for verification purposes.
options.dumpOutputDirectory = None
options = MochitestOptions.verifyOptions(self, options, mochitest)
options.webServer = tempIP
options.app = temp
options.sslPort = tempSSL
options.httpPort = tempPort
return options

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

@ -12,6 +12,7 @@ import sys
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__))) SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
sys.path.insert(0, SCRIPT_DIR) sys.path.insert(0, SCRIPT_DIR)
from argparse import Namespace
from urlparse import urlparse from urlparse import urlparse
import ctypes import ctypes
import glob import glob
@ -21,7 +22,6 @@ import mozdebug
import mozinfo import mozinfo
import mozprocess import mozprocess
import mozrunner import mozrunner
import optparse
import re import re
import shutil import shutil
import signal import signal
@ -332,7 +332,7 @@ class MochitestServer(object):
"Web server used to serve Mochitests, for closer fidelity to the real web." "Web server used to serve Mochitests, for closer fidelity to the real web."
def __init__(self, options, logger): def __init__(self, options, logger):
if isinstance(options, optparse.Values): if isinstance(options, Namespace):
options = vars(options) options = vars(options)
self._log = logger self._log = logger
self._closeWhenDone = options['closeWhenDone'] self._closeWhenDone = options['closeWhenDone']
@ -2576,7 +2576,7 @@ def main():
# parse command line options # parse command line options
parser = MochitestOptions() parser = MochitestOptions()
commandline.add_logging_group(parser) commandline.add_logging_group(parser)
options, args = parser.parse_args() options = parser.parse_args()
if options is None: if options is None:
# parsing error # parsing error
sys.exit(1) sys.exit(1)

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

@ -496,7 +496,7 @@ def run_desktop_mochitests(parser, options):
def main(): def main():
parser = B2GOptions() parser = B2GOptions()
structured.commandline.add_logging_group(parser) structured.commandline.add_logging_group(parser)
options, args = parser.parse_args() options = parser.parse_args()
if options.desktop: if options.desktop:
run_desktop_mochitests(parser, options) run_desktop_mochitests(parser, options)

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

@ -4,7 +4,6 @@
import base64 import base64
import json import json
import logging
import os import os
import shutil import shutil
import sys import sys
@ -19,7 +18,7 @@ sys.path.insert(
from automation import Automation from automation import Automation
from remoteautomation import RemoteAutomation, fennecLogcatFilters from remoteautomation import RemoteAutomation, fennecLogcatFilters
from runtests import Mochitest, MessageLogger from runtests import Mochitest, MessageLogger
from mochitest_options import MochitestOptions from mochitest_options import RemoteOptions
from mozlog import structured from mozlog import structured
from manifestparser import TestManifest from manifestparser import TestManifest
@ -27,260 +26,11 @@ from manifestparser.filters import chunk_by_slice
import devicemanager import devicemanager
import droid import droid
import mozinfo import mozinfo
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):
def __init__(self, automation, **kwargs):
defaults = {}
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")
defaults["remoteAppPath"] = None
self.add_option("--deviceIP", action="store",
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")
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")
defaults["dm_trans"] = "sut"
self.add_option("--devicePort", action="store",
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")
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.")
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")
defaults["remoteWebServer"] = None
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")
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")
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")
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")
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]")
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)")
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)")
defaults["remoteTestRoot"] = None
defaults["logFile"] = "mochitest.log"
defaults["autorun"] = True
defaults["closeWhenDone"] = True
defaults["testPath"] = ""
defaults["app"] = None
defaults["utilityPath"] = None
self.set_defaults(**defaults)
def verifyRemoteOptions(self, options, automation):
options_logger = logging.getLogger('MochitestRemote')
if not options.remoteTestRoot:
options.remoteTestRoot = automation._devicemanager.deviceRoot
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>")
return None
options.webServer = options.remoteWebServer
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 is None):
options.remoteLogFile = options.remoteTestRoot + \
'/logs/mochitest.log'
if (options.remoteLogFile.count('/') < 1):
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")
return None
elif (options.remoteAppPath):
options.app = options.remoteTestRoot + "/" + options.remoteAppPath
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 is None):
options.xrePath = options.utilityPath
if (options.pidFile != ""):
f = open(options.pidFile, 'w')
f.write("%s" % os.getpid())
f.close()
# Robocop specific deprecated options.
if options.robocop:
if options.robocopIni:
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")
return None
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)
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)
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)
return None
options.robocopIds = os.path.abspath(options.robocopIds)
# allow us to keep original application around for cleanup while
# running robocop via 'am'
options.remoteappname = options.app
return options
def verifyOptions(self, options, mochitest):
# since we are reusing verifyOptions, it will exit if App is not found
temp = options.app
options.app = __file__
tempPort = options.httpPort
tempSSL = options.sslPort
tempIP = options.webServer
# We are going to override this option later anyway, just pretend
# like it's not set for verification purposes.
options.dumpOutputDirectory = None
options = MochitestOptions.verifyOptions(self, options, mochitest)
options.webServer = tempIP
options.app = temp
options.sslPort = tempSSL
options.httpPort = tempPort
return options
class MochiRemote(Mochitest): class MochiRemote(Mochitest):
_automation = None _automation = None
_dm = None _dm = None
localProfile = None localProfile = None
@ -527,7 +277,7 @@ class MochiRemote(Mochitest):
for line in data: for line in data:
try: try:
message = json.loads(line) message = json.loads(line)
if not isinstance(message, dict) or not 'action' in message: if not isinstance(message, dict) or 'action' not in message:
continue continue
except ValueError: except ValueError:
continue continue
@ -718,7 +468,7 @@ def main(args):
parser = RemoteOptions(auto) parser = RemoteOptions(auto)
structured.commandline.add_logging_group(parser) structured.commandline.add_logging_group(parser)
options, args = parser.parse_args(args) options = parser.parse_args(args)
if (options.dm_trans == "adb"): if (options.dm_trans == "adb"):
if (options.deviceIP): if (options.deviceIP):