forked from OSchip/llvm-project
Cleaned up results formatter options hand-off.
* --results-formatter-options renamed to --results-formatter-option, with short version of -O * Multiple --results-formatter-option=OPTION can be specified. The comma-separating mechanism has been removed. * XunitFormatter options modified: -n and -r are now short forms of --ignore-skip-name and --ignore-skip-reason. Those long option names were tweaked lightly. They also can be specified multiple times on the command line. The comma-separating, multiple-pattern- per-option mechanism has been removed. One can now specify: dotest.py --results-file stdout -O-ndsym -O-nlldb-mi for example, to ignore reporting skips for dsym-related or lldb-mi-related tests in the xUnit report. llvm-svn: 248384
This commit is contained in:
parent
0d427986f5
commit
ea73624e5f
|
@ -1068,43 +1068,87 @@ def get_test_runner_strategies(num_threads):
|
|||
}
|
||||
|
||||
|
||||
def _remove_option(args, option_name, removal_count):
|
||||
def _remove_option(
|
||||
args, long_option_name, short_option_name, takes_arg):
|
||||
"""Removes option and related option arguments from args array.
|
||||
|
||||
This method removes all short/long options that match the given
|
||||
arguments.
|
||||
|
||||
@param args the array of command line arguments (in/out)
|
||||
@param option_name the full command line representation of the
|
||||
option that will be removed (including '--' or '-').
|
||||
@param the count of elements to remove. A value of 1 will remove
|
||||
just the found option, while 2 will remove the option and its first
|
||||
argument.
|
||||
|
||||
@param long_option_name the full command line representation of the
|
||||
long-form option that will be removed (including '--').
|
||||
|
||||
@param short_option_name the short version of the command line option
|
||||
that will be removed (including '-').
|
||||
|
||||
@param takes_arg True if the option takes an argument.
|
||||
|
||||
"""
|
||||
try:
|
||||
index = args.index(option_name)
|
||||
# Handle the exact match case.
|
||||
del args[index:index+removal_count]
|
||||
return
|
||||
except ValueError:
|
||||
# Thanks to argparse not handling options with known arguments
|
||||
# like other options parsing libraries (see
|
||||
# https://bugs.python.org/issue9334), we need to support the
|
||||
# --results-formatter-options={second-level-arguments} (note
|
||||
# the equal sign to fool the first-level arguments parser into
|
||||
# not treating the second-level arguments as first-level
|
||||
# options). We're certainly at risk of getting this wrong
|
||||
# since now we're forced into the business of trying to figure
|
||||
# out what is an argument (although I think this
|
||||
# implementation will suffice).
|
||||
regex_string = "^" + option_name + "="
|
||||
regex = re.compile(regex_string)
|
||||
if long_option_name is not None:
|
||||
regex_string = "^" + long_option_name + "="
|
||||
long_regex = re.compile(regex_string)
|
||||
if short_option_name is not None:
|
||||
# Short options we only match the -X and assume
|
||||
# any arg is one command line argument jammed together.
|
||||
# i.e. -O--abc=1 is a single argument in the args list.
|
||||
# We don't handle -O --abc=1, as argparse doesn't handle
|
||||
# it, either.
|
||||
regex_string = "^" + short_option_name
|
||||
short_regex = re.compile(regex_string)
|
||||
|
||||
def remove_long_internal():
|
||||
"""Removes one matching long option from args.
|
||||
@returns True if one was found and removed; False otherwise.
|
||||
"""
|
||||
try:
|
||||
index = args.index(long_option_name)
|
||||
# Handle the exact match case.
|
||||
if takes_arg:
|
||||
removal_count = 2
|
||||
else:
|
||||
removal_count = 1
|
||||
del args[index:index+removal_count]
|
||||
return True
|
||||
except ValueError:
|
||||
# Thanks to argparse not handling options with known arguments
|
||||
# like other options parsing libraries (see
|
||||
# https://bugs.python.org/issue9334), we need to support the
|
||||
# --results-formatter-options={second-level-arguments} (note
|
||||
# the equal sign to fool the first-level arguments parser into
|
||||
# not treating the second-level arguments as first-level
|
||||
# options). We're certainly at risk of getting this wrong
|
||||
# since now we're forced into the business of trying to figure
|
||||
# out what is an argument (although I think this
|
||||
# implementation will suffice).
|
||||
for index in range(len(args)):
|
||||
match = long_regex.search(args[index])
|
||||
if match:
|
||||
del args[index]
|
||||
return True
|
||||
return False
|
||||
|
||||
def remove_short_internal():
|
||||
"""Removes one matching short option from args.
|
||||
@returns True if one was found and removed; False otherwise.
|
||||
"""
|
||||
for index in range(len(args)):
|
||||
match = regex.match(args[index])
|
||||
match = short_regex.search(args[index])
|
||||
if match:
|
||||
del args[index]
|
||||
return
|
||||
print "failed to find regex '{}'".format(regex_string)
|
||||
return True
|
||||
return False
|
||||
|
||||
# We didn't find the option but we should have.
|
||||
raise Exception("failed to find option '{}' in args '{}'".format(
|
||||
option_name, args))
|
||||
removal_count = 0
|
||||
while long_option_name is not None and remove_long_internal():
|
||||
removal_count += 1
|
||||
while short_option_name is not None and remove_short_internal():
|
||||
removal_count += 1
|
||||
if removal_count == 0:
|
||||
raise Exception(
|
||||
"failed to find at least one of '{}', '{}' in options".format(
|
||||
long_option_name, short_option_name))
|
||||
|
||||
|
||||
def adjust_inferior_options(dotest_argv):
|
||||
|
@ -1132,17 +1176,18 @@ def adjust_inferior_options(dotest_argv):
|
|||
# we'll have inferiors spawn with the --results-port option and
|
||||
# strip the original test runner options.
|
||||
if dotest_options.results_file is not None:
|
||||
_remove_option(dotest_argv, "--results-file", 2)
|
||||
_remove_option(dotest_argv, "--results-file", None, True)
|
||||
if dotest_options.results_port is not None:
|
||||
_remove_option(dotest_argv, "--results-port", 2)
|
||||
_remove_option(dotest_argv, "--results-port", None, True)
|
||||
if dotest_options.results_formatter is not None:
|
||||
_remove_option(dotest_argv, "--results-formatter", 2)
|
||||
_remove_option(dotest_argv, "--results-formatter", None, True)
|
||||
if dotest_options.results_formatter_options is not None:
|
||||
_remove_option(dotest_argv, "--results-formatter-options", 2)
|
||||
_remove_option(dotest_argv, "--results-formatter-option", "-O",
|
||||
True)
|
||||
|
||||
# Remove test runner name if present.
|
||||
if dotest_options.test_runner_name is not None:
|
||||
_remove_option(dotest_argv, "--test-runner-name", 2)
|
||||
_remove_option(dotest_argv, "--test-runner-name", None, True)
|
||||
|
||||
|
||||
def is_darwin_version_lower_than(target_version):
|
||||
|
|
|
@ -1000,12 +1000,10 @@ def setupTestResults():
|
|||
# Handle formatter options for the results formatter class.
|
||||
formatter_arg_parser = clazz.arg_parser()
|
||||
if results_formatter_options and len(results_formatter_options) > 0:
|
||||
import shlex
|
||||
split_options = shlex.split(results_formatter_options)
|
||||
formatter_options = formatter_arg_parser.parse_args(
|
||||
results_formatter_options)
|
||||
else:
|
||||
split_options = []
|
||||
|
||||
formatter_options = formatter_arg_parser.parse_args(split_options)
|
||||
formatter_options = []
|
||||
|
||||
# Create the TestResultsFormatter given the processed options.
|
||||
results_formatter_object = clazz(results_file_object, formatter_options)
|
||||
|
|
|
@ -172,11 +172,13 @@ def create_parser():
|
|||
'test events into some kind of meaningful report, written to '
|
||||
'the designated output results file-like object'))
|
||||
group.add_argument(
|
||||
'--results-formatter-options',
|
||||
action='store',
|
||||
help=('Specify comma-separated options to pass to the formatter. '
|
||||
'Use --results-formatter-options="--option1[,--option2[,...]]" '
|
||||
'syntax. Note the "=" is critical, and don\'t use whitespace.'))
|
||||
'--results-formatter-option',
|
||||
'-O',
|
||||
action='append',
|
||||
dest='results_formatter_options',
|
||||
help=('Specify an option to pass to the formatter. '
|
||||
'Use --results-formatter-option="--option1=val1" '
|
||||
'syntax. Note the "=" is critical, don\'t include whitespace.'))
|
||||
group.add_argument(
|
||||
'--event-add-entries',
|
||||
action='store',
|
||||
|
|
|
@ -538,19 +538,25 @@ class XunitFormatter(ResultsFormatter):
|
|||
help=('cause unknown test events to generate '
|
||||
'a python assert. Default is to ignore.'))
|
||||
parser.add_argument(
|
||||
"--ignore-skip-matching-name",
|
||||
action="store",
|
||||
help=('one or more comma-separated python regex patterns, where '
|
||||
"--ignore-skip-name",
|
||||
"-n",
|
||||
metavar='PATTERN',
|
||||
action="append",
|
||||
dest='ignore_skip_name_patterns',
|
||||
help=('a python regex pattern, where '
|
||||
'any skipped test with a test method name where regex '
|
||||
'matches (via search) will be ignored for xUnit test '
|
||||
'result purposes.'))
|
||||
'result purposes. Can be specified multiple times.'))
|
||||
parser.add_argument(
|
||||
"--ignore-skip-matching-reason",
|
||||
action="store",
|
||||
help=('one or more comma-separated python regex patterns, where '
|
||||
"--ignore-skip-reason",
|
||||
"-r",
|
||||
metavar='PATTERN',
|
||||
action="append",
|
||||
dest='ignore_skip_reason_patterns',
|
||||
help=('a python regex pattern, where '
|
||||
'any skipped test with a skip reason where the regex '
|
||||
'matches (via search) will be ignored for xUnit test '
|
||||
'result purposes.'))
|
||||
'result purposes. Can be specified multiple times.'))
|
||||
parser.add_argument(
|
||||
"--xpass", action="store", choices=results_mapping_choices,
|
||||
default=XunitFormatter.RM_FAILURE,
|
||||
|
@ -564,7 +570,7 @@ class XunitFormatter(ResultsFormatter):
|
|||
return parser
|
||||
|
||||
@staticmethod
|
||||
def _build_regex_list_from_option(option):
|
||||
def _build_regex_list_from_patterns(patterns):
|
||||
"""Builds a list of compiled regexes from option value.
|
||||
|
||||
@param option string containing a comma-separated list of regex
|
||||
|
@ -574,8 +580,8 @@ class XunitFormatter(ResultsFormatter):
|
|||
patterns provided.
|
||||
"""
|
||||
regex_list = []
|
||||
if option is not None and len(option) > 0:
|
||||
for pattern in option.split(","):
|
||||
if patterns is not None:
|
||||
for pattern in patterns:
|
||||
regex_list.append(re.compile(pattern))
|
||||
return regex_list
|
||||
|
||||
|
@ -591,11 +597,11 @@ class XunitFormatter(ResultsFormatter):
|
|||
self.invalid_xml_re = XunitFormatter._build_illegal_xml_regex()
|
||||
self.total_test_count = 0
|
||||
self.ignore_skip_name_regexes = (
|
||||
XunitFormatter._build_regex_list_from_option(
|
||||
options.ignore_skip_matching_name))
|
||||
XunitFormatter._build_regex_list_from_patterns(
|
||||
options.ignore_skip_name_patterns))
|
||||
self.ignore_skip_reason_regexes = (
|
||||
XunitFormatter._build_regex_list_from_option(
|
||||
options.ignore_skip_matching_reason))
|
||||
XunitFormatter._build_regex_list_from_patterns(
|
||||
options.ignore_skip_reason_patterns))
|
||||
|
||||
self.elements = {
|
||||
"successes": [],
|
||||
|
|
Loading…
Reference in New Issue