blob: 8648144f486d11daf46144b5441227939fff8b85 [file] [log] [blame]
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
class _Bailout(Exception):
pass
DEFAULT_COVERAGE_OMIT = ['*/typ/*', '*/site-packages/*']
DEFAULT_STATUS_FORMAT = '[%f/%t] '
DEFAULT_SUFFIXES = ['*_test.py', '*_unittest.py']
class ArgumentParser(argparse.ArgumentParser):
def __init__(self, host):
super(ArgumentParser, self).__init__()
self._host = host
self.exit_status = None
self.usage = '%(prog)s [options] [tests...]'
self.add_argument('--builder-name',
help=('Builder name to include in the '
'uploaded data.'))
self.add_argument('-c', '--coverage', action='store_true',
help='Report coverage information.')
self.add_argument('--coverage-omit', action='append',
default=[],
help=('Globs to omit in coverage report '
'(defaults to %s).' % DEFAULT_COVERAGE_OMIT))
self.add_argument('-d', '--debugger', action='store_true',
help='Run tests under the debugger.')
self.add_argument('-n', '--dry-run', action='store_true',
help=('Do not actually run the tests, act like they '
'succeeded.'))
self.add_argument('-f', '--file-list', metavar='FILENAME',
action='store',
help=('Take the list of tests from the file '
'(use "-" for stdin).'))
self.add_argument('--isolate', metavar='glob', default=[],
action='append',
help='test globs to run in isolation (serially).')
self.add_argument('-j', '--jobs', metavar='N', type=int,
default=host.cpu_count(),
help=('Run N jobs in parallel '
'(defaults to %(default)s).'))
self.add_argument('-l', '--list-only', action='store_true',
help=('List all the test names found in the given '
'tests.'))
self.add_argument('--master-name',
help=('Buildbot master name to include in the '
'uploaded data.'))
self.add_argument('--metadata', action='append', default=[],
help=('Optional key=value metadata that will be '
'included in the results.'))
self.add_argument('-P', '--path', action='append', default=[],
help=('Add dir to sys.path (can specify multiple '
'times).'))
self.add_argument('-q', '--quiet', action='store_true', default=False,
help='Be as quiet as possible (only print errors).')
self.add_argument('--retry-limit', type=int, default=0,
help='Retry each failure up to N times.')
self.add_argument('-s', '--status-format',
default=self._host.getenv('NINJA_STATUS',
DEFAULT_STATUS_FORMAT),
help=('Format for status updates '
'(uses NINJA_STATUS env var if set, '
'"%(default)s" otherwise). '))
self.add_argument('--skip', metavar='glob', default=[],
action='append',
help=('Globs of test names to skip (can specify '
'multiple times).'))
self.add_argument('--suffixes', metavar='glob', default=[],
action='append',
help=('Globs of test filenames to look for ('
'can specify multiple times; defaults to %s).'
% DEFAULT_SUFFIXES))
self.add_argument('--terminal-width', type=int,
default=host.terminal_width(),
help=('width to use for output (defaults to '
'%(default)s; 0 is unbounded).'))
self.add_argument('--test-results-server',
help=('If specified, upload the full results to '
'this server.'))
self.add_argument('--test-type',
help=('Name of test type to include in the uploaded '
'data (e.g., "telemetry_unittests").'))
self.add_argument('-t', '--timing', action='store_true',
help='Print timing info.')
self.add_argument('--top-level-dir', default=None,
help=('Top directory of project '
'(used when running subdirs).'))
self.add_argument('--write-full-results-to', metavar='FILENAME',
action='store',
help=('If specified, write the full results to '
'that path.'))
self.add_argument('-v', '--verbose', action='count', default=0,
help=('Log verbosely (can specify multiple times '
'for more output).'))
self.add_argument('-V', '--version', action='store_true',
help='Print the typ version and exit.')
self.add_argument('--overwrite', action='store_true',
default=None,
help=argparse.SUPPRESS)
self.add_argument('--no-overwrite', action='store_false',
dest='overwrite', default=None,
help=argparse.SUPPRESS)
self.add_argument('--passthrough', action='store_true',
default=False,
help=argparse.SUPPRESS)
self.add_argument('--setup', help=argparse.SUPPRESS)
self.add_argument('--teardown', help=argparse.SUPPRESS)
self.add_argument('--context', help=argparse.SUPPRESS)
self.add_argument('tests', nargs='*', default=[],
help=argparse.SUPPRESS)
def parse_args(self, args=None, namespace=None):
try:
rargs = super(ArgumentParser, self).parse_args(args=args,
namespace=namespace)
except _Bailout:
return None
for val in rargs.metadata:
if '=' not in val:
self._print_message('Error: malformed --metadata "%s"' % val)
self.exit_status = 2
if rargs.test_results_server:
if not rargs.builder_name:
self._print_message('Error: --builder-name must be specified '
'along with --test-result-server')
self.exit_status = 2
if not rargs.master_name:
self._print_message('Error: --master-name must be specified '
'along with --test-result-server')
self.exit_status = 2
if not rargs.test_type:
self._print_message('Error: --test_type must be specified '
'along with --test-result-server')
self.exit_status = 2
if not rargs.suffixes:
rargs.suffixes = DEFAULT_SUFFIXES
if not rargs.coverage_omit:
rargs.coverage_omit = DEFAULT_COVERAGE_OMIT
if rargs.debugger: # pragma: no cover
rargs.jobs = 1
rargs.passthrough = True
if rargs.coverage: # pragma: no cover
rargs.jobs = 1
if rargs.overwrite is None:
rargs.overwrite = self._host.stdout.isatty() and not rargs.verbose
return rargs
# Redefining built-in 'file' pylint: disable=W0622
def _print_message(self, msg, file=None):
self._host.print_(msg=msg, stream=file, end='')
def print_help(self, file=None):
self._print_message(msg=self.format_help(), file=file)
def error(self, message):
self.exit(2, '%s: error: %s\n' % (self.prog, message))
def exit(self, status=0, message=None):
self.exit_status = status
if message:
self._print_message(message, file=self._host.stderr)
raise _Bailout()