blob: 6db62438d424480c17dda8b5b61bfffe26fd4f41 [file] [log] [blame]
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
_CMDLINE_NAME_SEGMENT_RE = re.compile(
r' with(?:out)? \{[^\}]*\}')
class ConflictingPositiveFiltersException(Exception):
"""Raised when both filter file and filter argument have positive filters."""
def ParseFilterFile(input_lines):
"""Converts test filter file contents to positive and negative pattern lists.
See //testing/buildbot/filters/README.md for description of the
syntax that |input_lines| are expected to follow.
See
https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#running-a-subset-of-the-tests
for description of the syntax that --gtest_filter argument should follow.
Args:
input_lines: An iterable (e.g. a list or a file) containing input lines.
Returns:
tuple containing the lists of positive patterns and negative patterns
"""
# Strip comments and whitespace from each line and filter non-empty lines.
stripped_lines = (l.split('#', 1)[0].strip() for l in input_lines)
filter_lines = [l for l in stripped_lines if l]
# Split the tests into positive and negative patterns (gtest treats
# every pattern after the first '-' sign as an exclusion).
positive_patterns = [l for l in filter_lines if l[0] != '-']
negative_patterns = [l[1:] for l in filter_lines if l[0] == '-']
return positive_patterns, negative_patterns
def AddFilterOptions(parser):
"""Adds filter command-line options to the provided parser.
Args:
parser: an argparse.ArgumentParser instance.
"""
parser.add_argument(
# Deprecated argument.
'--gtest-filter-file',
# New argument.
'--test-launcher-filter-file',
dest='test_filter_file',
help='Path to file that contains googletest-style filter strings. '
'See also //testing/buildbot/filters/README.md.')
filter_group = parser.add_mutually_exclusive_group()
filter_group.add_argument(
'-f', '--test-filter', '--gtest_filter', '--gtest-filter',
dest='test_filter',
help='googletest-style filter string.',
default=os.environ.get('GTEST_FILTER'))
filter_group.add_argument(
'--isolated-script-test-filter',
help='isolated script filter string. '
'Like gtest filter strings, but with :: separators instead of :')
def AppendPatternsToFilter(test_filter, positive_patterns=None,
negative_patterns=None):
"""Returns a test-filter string with additional patterns.
Args:
test_filter: test filter string
positive_patterns: list of positive patterns to add to string
negative_patterns: list of negative patterns to add to string
"""
positives = []
negatives = []
positive = ''
negative = ''
split_filter = test_filter.split('-', 1)
if len(split_filter) == 1:
positive = split_filter[0]
else:
positive, negative = split_filter
positives += [f for f in positive.split(':') if f]
negatives += [f for f in negative.split(':') if f]
positives += positive_patterns if positive_patterns else []
negatives += negative_patterns if negative_patterns else []
final_filter = ':'.join([p.replace('#', '.') for p in positives])
if negatives:
final_filter += '-' + ':'.join([n.replace('#', '.') for n in negatives])
return final_filter
def HasPositivePatterns(test_filter):
"""Returns True if test_filter contains a positive pattern, else False
Args:
test_filter: test-filter style string
"""
return bool(len(test_filter) > 0 and test_filter[0] != '-')
def InitializeFilterFromArgs(args):
"""Returns a filter string from the command-line option values.
Args:
args: an argparse.Namespace instance resulting from a using parser
to which the filter options above were added.
Raises:
ConflictingPositiveFiltersException if both filter file and command line
specify positive filters.
"""
test_filter = ''
if args.isolated_script_test_filter:
args.test_filter = args.isolated_script_test_filter.replace('::', ':')
if args.test_filter:
test_filter = _CMDLINE_NAME_SEGMENT_RE.sub(
'', args.test_filter.replace('#', '.'))
if args.test_filter_file:
for test_filter_file in args.test_filter_file.split(';'):
with open(test_filter_file, 'r') as f:
positive_file_patterns, negative_file_patterns = ParseFilterFile(f)
if positive_file_patterns and HasPositivePatterns(test_filter):
raise ConflictingPositiveFiltersException(
'Cannot specify positive pattern in both filter file and ' +
'filter command line argument')
test_filter = AppendPatternsToFilter(
test_filter,
positive_patterns=positive_file_patterns,
negative_patterns=negative_file_patterns)
return test_filter