Source code for stestr.selection
# 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 contextlib
import re
import sys
[docs]def filter_tests(filters, test_ids):
"""Filter test_ids by the test_filters.
:param list filters: A list of regex filters to apply to the test_ids. The
output will contain any test_ids which have a re.search() match for any
of the regexes in this list. If this is None all test_ids will be
returned
:param list test_ids: A list of test_ids that will be filtered
:return: A list of test ids.
"""
if filters is None:
return test_ids
_filters = []
for f in filters:
if isinstance(f, str):
try:
_filters.append(re.compile(f))
except re.error:
print("Invalid regex: %s provided in filters" % f, file=sys.stderr)
sys.exit(5)
else:
_filters.append(f)
def include(test_id):
for pred in _filters:
if pred.search(test_id):
return True
return list(filter(include, test_ids))
def exclusion_reader(exclude_list):
with contextlib.closing(open(exclude_list)) as exclude_file:
regex_comment_lst = [] # tuple of (regex_compiled, msg, skipped_lst)
for line in exclude_file:
raw_line = line.strip()
split_line = raw_line.split("#")
# Before the # is the regex
line_regex = split_line[0].strip()
if len(split_line) > 1:
# After the # is a comment
comment = "".join(split_line[1:]).strip()
else:
comment = "Skipped because of regex %s:" % line_regex
if not line_regex:
continue
try:
regex_comment_lst.append((re.compile(line_regex), comment, []))
except re.error:
print(
"Invalid regex: %s in provided exclusion list file" % line_regex,
file=sys.stderr,
)
sys.exit(5)
return regex_comment_lst
def _get_regex_from_include_list(file_path):
lines = []
for line in open(file_path).read().splitlines():
split_line = line.strip().split("#")
# Before the # is the regex
line_regex = split_line[0].strip()
if line_regex:
try:
lines.append(re.compile(line_regex))
except re.error:
print(
"Invalid regex: %s in provided inclusion_list file" % line_regex,
file=sys.stderr,
)
sys.exit(5)
return lines
[docs]def construct_list(
test_ids, regexes=None, exclude_list=None, include_list=None, exclude_regex=None
):
"""Filters the discovered test cases
:param list test_ids: The set of test_ids to be filtered
:param list regexes: A list of regex filters to apply to the test_ids. The
output will contain any test_ids which have a re.search() match for any
of the regexes in this list. If this is None all test_ids will be
returned
:param str exclude_list: The path to an exclusion_list file
:param str include_list: The path to an inclusion_list file
:param str exclude_regex: regex pattern to exclude tests
:return: iterable of strings. The strings are full
test_ids
:rtype: set
"""
if not regexes:
regexes = None # handle the other false things
safe_re = None
if include_list:
safe_re = _get_regex_from_include_list(include_list)
if not regexes and safe_re:
regexes = safe_re
elif regexes and safe_re:
regexes += safe_re
if exclude_list:
exclude_data = exclusion_reader(exclude_list)
else:
exclude_data = None
if exclude_regex:
msg = "Skipped because of regexp provided as a command line argument:"
try:
record = (re.compile(exclude_regex), msg, [])
except re.error:
print(
"Invalid regex: %s used for exclude_regex" % exclude_regex,
file=sys.stderr,
)
sys.exit(5)
if exclude_data:
exclude_data.append(record)
else:
exclude_data = [record]
list_of_test_cases = filter_tests(regexes, test_ids)
set_of_test_cases = set(list_of_test_cases)
if not exclude_data:
return set_of_test_cases
# NOTE(afazekas): We might use a faster logic when the
# print option is not requested
for (rex, msg, s_list) in exclude_data:
for test_case in list_of_test_cases:
if rex.search(test_case):
# NOTE(mtreinish): In the case of overlapping regex the test
# case might have already been removed from the set of tests
if test_case in set_of_test_cases:
set_of_test_cases.remove(test_case)
s_list.append(test_case)
return set_of_test_cases