Dan Harrington | 238d339 | 2018-10-19 20:14:53 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright (c) 2018 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | """Reads lines from files or stdin and identifies C++ tests. |
| 6 | |
| 7 | Outputs a filter that can be used with --gtest_filter to run only the tests |
| 8 | identified. |
| 9 | |
| 10 | Usage: |
| 11 | |
| 12 | Outputs filter for all test fixtures in a directory. --class-only avoids an |
| 13 | overly long filter string. |
| 14 | > cat components/mycomp/**test.cc | make-gtest-filter.py --class-only |
| 15 | |
| 16 | Outputs filter for all tests in a file. |
| 17 | > make-gtest-filter.py ./myfile_unittest.cc |
| 18 | |
| 19 | Outputs filter for only test at line 123 |
| 20 | > make-gtest-filter.py --line=123 ./myfile_unittest.cc |
| 21 | """ |
| 22 | |
Raul Tambre | 26d7db4 | 2019-09-25 11:06:35 | [diff] [blame] | 23 | from __future__ import print_function |
| 24 | |
Dan Harrington | 238d339 | 2018-10-19 20:14:53 | [diff] [blame] | 25 | import argparse |
| 26 | import fileinput |
| 27 | import re |
| 28 | import sys |
| 29 | |
| 30 | parser = argparse.ArgumentParser() |
| 31 | parser.add_argument('--line', type=int) |
| 32 | parser.add_argument('--class-only', action='store_true') |
| 33 | args, left = parser.parse_known_args() |
| 34 | file_input = fileinput.input(left) |
| 35 | |
| 36 | if args.line: |
| 37 | # If --line is used, restrict text to a few lines around the requested |
| 38 | # line. |
| 39 | requested_line = args.line |
| 40 | selected_lines = [] |
| 41 | for line in file_input: |
| 42 | if (fileinput.lineno() >= requested_line and |
| 43 | fileinput.lineno() <= requested_line + 1): |
| 44 | selected_lines.append(line) |
| 45 | txt = ''.join(selected_lines) |
| 46 | else: |
| 47 | txt = ''.join(list(file_input)) |
| 48 | |
| 49 | # This regex is not exhaustive, and should be updated as needed. |
| 50 | rx = re.compile( |
| 51 | r'^(?:TYPED_)?(?:IN_PROC_BROWSER_)?TEST(_F|_P)?\(\s*(\w+)\s*,\s*(\w+)\s*\)', |
| 52 | flags=re.DOTALL | re.M) |
| 53 | tests = [] |
| 54 | for m in rx.finditer(txt): |
| 55 | tests.append(m.group(2) + '.' + m.group(3)) |
| 56 | |
| 57 | # Note: Test names have the following structures: |
| 58 | # * FixtureName.TestName |
| 59 | # * InstantiationName/FixtureName.TestName/## |
| 60 | # Since this script doesn't parse instantiations, we generate filters to match |
| 61 | # either regular tests or instantiated tests. |
| 62 | if args.class_only: |
| 63 | fixtures = set([t.split('.')[0] for t in tests]) |
| 64 | test_filters = [c + '.*' for c in fixtures] |
| 65 | instantiation_filters = ['*/' + c + '.*/*' for c in fixtures] |
Raul Tambre | 26d7db4 | 2019-09-25 11:06:35 | [diff] [blame] | 66 | print(':'.join(test_filters + instantiation_filters)) |
Dan Harrington | 238d339 | 2018-10-19 20:14:53 | [diff] [blame] | 67 | else: |
| 68 | instantiations = ['*/' + c + '/*' for c in tests] |
Raul Tambre | 26d7db4 | 2019-09-25 11:06:35 | [diff] [blame] | 69 | print(':'.join(tests + instantiations)) |