1from __future__ import print_function
2from __future__ import absolute_import
3
4# System modules
5import argparse
6import sys
7import os
8import textwrap
9
10# Third-party modules
11
12# LLDB modules
13from . import configuration
14
15
16class ArgParseNamespace(object):
17    pass
18
19
20def parse_args(parser, argv):
21    """ Returns an argument object. LLDB_TEST_ARGUMENTS environment variable can
22        be used to pass additional arguments.
23    """
24    args = ArgParseNamespace()
25
26    if ('LLDB_TEST_ARGUMENTS' in os.environ):
27        print(
28            "Arguments passed through environment: '%s'" %
29            os.environ['LLDB_TEST_ARGUMENTS'])
30        args = parser.parse_args([sys.argv[0]].__add__(
31            os.environ['LLDB_TEST_ARGUMENTS'].split()), namespace=args)
32
33    return parser.parse_args(args=argv, namespace=args)
34
35
36def create_parser():
37    parser = argparse.ArgumentParser(
38        description='description',
39        prefix_chars='+-',
40        add_help=False)
41    group = None
42
43    # Helper function for boolean options (group will point to the current
44    # group when executing X)
45    X = lambda optstr, helpstr, **kwargs: group.add_argument(
46        optstr, help=helpstr, action='store_true', **kwargs)
47
48    group = parser.add_argument_group('Help')
49    group.add_argument(
50        '-h',
51        '--help',
52        dest='h',
53        action='store_true',
54        help="Print this help message and exit.  Add '-v' for more detailed help.")
55
56    # C and Python toolchain options
57    group = parser.add_argument_group('Toolchain options')
58    group.add_argument(
59        '-A',
60        '--arch',
61        metavar='arch',
62        dest='arch',
63        help=textwrap.dedent('''Specify the architecture(s) to test. This option can be specified more than once'''))
64    group.add_argument('-C', '--compiler', metavar='compiler', dest='compiler', help=textwrap.dedent(
65        '''Specify the compiler(s) used to build the inferior executables. The compiler path can be an executable basename or a full path to a compiler executable. This option can be specified multiple times.'''))
66    if sys.platform == 'darwin':
67        group.add_argument('--apple-sdk', metavar='apple_sdk', dest='apple_sdk', default="macosx", help=textwrap.dedent(
68            '''Specify the name of the Apple SDK (macosx, macosx.internal, iphoneos, iphoneos.internal, or path to SDK) and use the appropriate tools from that SDK's toolchain.'''))
69    # FIXME? This won't work for different extra flags according to each arch.
70    group.add_argument(
71        '-E',
72        metavar='extra-flags',
73        help=textwrap.dedent('''Specify the extra flags to be passed to the toolchain when building the inferior programs to be debugged
74                                                           suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
75
76    group.add_argument('--dsymutil', metavar='dsymutil', dest='dsymutil', help=textwrap.dedent('Specify which dsymutil to use.'))
77
78    group.add_argument('--filecheck', metavar='filecheck', dest='filecheck', help=textwrap.dedent('Specify which FileCheck binary to use.'))
79
80    # Test filtering options
81    group = parser.add_argument_group('Test filtering options')
82    group.add_argument(
83        '-f',
84        metavar='filterspec',
85        action='append',
86        help='Specify a filter, which consists of the test class name, a dot, followed by the test method, to only admit such test into the test suite')  # FIXME: Example?
87    X('-l', "Don't skip long running tests")
88    group.add_argument(
89        '-p',
90        metavar='pattern',
91        help='Specify a regexp filename pattern for inclusion in the test suite')
92    group.add_argument('--excluded', metavar='exclusion-file', action='append', help=textwrap.dedent(
93        '''Specify a file for tests to exclude. File should contain lists of regular expressions for test files or methods,
94                                with each list under a matching header (xfail files, xfail methods, skip files, skip methods)'''))
95    group.add_argument(
96        '-G',
97        '--category',
98        metavar='category',
99        action='append',
100        dest='categoriesList',
101        help=textwrap.dedent('''Specify categories of test cases of interest. Can be specified more than once.'''))
102    group.add_argument(
103        '--skip-category',
104        metavar='category',
105        action='append',
106        dest='skipCategories',
107        help=textwrap.dedent('''Specify categories of test cases to skip. Takes precedence over -G. Can be specified more than once.'''))
108
109    # Configuration options
110    group = parser.add_argument_group('Configuration options')
111    group.add_argument(
112        '--framework',
113        metavar='framework-path',
114        help='The path to LLDB.framework')
115    group.add_argument(
116        '--executable',
117        metavar='executable-path',
118        help='The path to the lldb executable')
119    group.add_argument(
120        '--server',
121        metavar='server-path',
122        help='The path to the debug server executable to use')
123    group.add_argument(
124        '--out-of-tree-debugserver',
125        dest='out_of_tree_debugserver',
126        action='store_true',
127        help='A flag to indicate an out-of-tree debug server is being used')
128    group.add_argument(
129        '-s',
130        metavar='name',
131        help='Specify the name of the dir created to store the session files of tests with errored or failed status. If not specified, the test driver uses the timestamp as the session dir name')
132    group.add_argument(
133        '-S',
134        '--session-file-format',
135        default=configuration.session_file_format,
136        metavar='format',
137        help='Specify session file name format.  See configuration.py for a description.')
138    group.add_argument(
139        '-y',
140        type=int,
141        metavar='count',
142        help="Specify the iteration count used to collect our benchmarks. An example is the number of times to do 'thread step-over' to measure stepping speed.")
143    group.add_argument(
144        '-#',
145        type=int,
146        metavar='sharp',
147        dest='sharp',
148        help='Repeat the test suite for a specified number of times')
149    group.add_argument('--channel', metavar='channel', dest='channels', action='append', help=textwrap.dedent(
150        "Specify the log channels (and optional categories) e.g. 'lldb all' or 'gdb-remote packets' if no categories are specified, 'default' is used"))
151    group.add_argument(
152        '--log-success',
153        dest='log_success',
154        action='store_true',
155        help="Leave logs/traces even for successful test runs (useful for creating reference log files during debugging.)")
156    group.add_argument(
157        '--codesign-identity',
158        metavar='Codesigning identity',
159        default='lldb_codesign',
160        help='The codesigning identity to use')
161    group.add_argument(
162        '--build-dir',
163        dest='test_build_dir',
164        metavar='Test build directory',
165        default='lldb-test-build.noindex',
166        help='The root build directory for the tests. It will be removed before running.')
167
168    # Configuration options
169    group = parser.add_argument_group('Remote platform options')
170    group.add_argument(
171        '--platform-name',
172        dest='lldb_platform_name',
173        metavar='platform-name',
174        help='The name of a remote platform to use')
175    group.add_argument(
176        '--platform-url',
177        dest='lldb_platform_url',
178        metavar='platform-url',
179        help='A LLDB platform URL to use when connecting to a remote platform to run the test suite')
180    group.add_argument(
181        '--platform-working-dir',
182        dest='lldb_platform_working_dir',
183        metavar='platform-working-dir',
184        help='The directory to use on the remote platform.')
185
186    # Test-suite behaviour
187    group = parser.add_argument_group('Runtime behaviour options')
188    X('-d', 'Suspend the process after launch to wait indefinitely for a debugger to attach')
189    X('-q', "Don't print extra output from this script.")
190    X('-t', 'Turn on tracing of lldb command and other detailed test executions')
191    group.add_argument(
192        '-u',
193        dest='unset_env_varnames',
194        metavar='variable',
195        action='append',
196        help='Specify an environment variable to unset before running the test cases. e.g., -u DYLD_INSERT_LIBRARIES -u MallocScribble')
197    group.add_argument(
198        '--env',
199        dest='set_env_vars',
200        metavar='variable',
201        action='append',
202        help='Specify an environment variable to set to the given value before running the test cases e.g.: --env CXXFLAGS=-O3 --env DYLD_INSERT_LIBRARIES')
203    group.add_argument(
204        '--inferior-env',
205        dest='set_inferior_env_vars',
206        metavar='variable',
207        action='append',
208        help='Specify an environment variable to set to the given value for the inferior.')
209    X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
210    group.add_argument(
211        '--enable-crash-dialog',
212        dest='disable_crash_dialog',
213        action='store_false',
214        help='(Windows only) When LLDB crashes, display the Windows crash dialog.')
215    group.set_defaults(disable_crash_dialog=True)
216
217    # Test results support.
218    group = parser.add_argument_group('Test results options')
219    group.add_argument(
220        '--curses',
221        action='store_true',
222        help='Shortcut for specifying test results using the curses formatter')
223    group.add_argument(
224        '--results-file',
225        action='store',
226        help=('Specifies the file where test results will be written '
227              'according to the results-formatter class used'))
228    group.add_argument(
229        '--results-port',
230        action='store',
231        type=int,
232        help=('Specifies the localhost port to which the results '
233              'formatted output should be sent'))
234    group.add_argument(
235        '--results-formatter',
236        action='store',
237        help=('Specifies the full package/module/class name used to translate '
238              'test events into some kind of meaningful report, written to '
239              'the designated output results file-like object'))
240    group.add_argument(
241        '--results-formatter-option',
242        '-O',
243        action='append',
244        dest='results_formatter_options',
245        help=('Specify an option to pass to the formatter. '
246              'Use --results-formatter-option="--option1=val1" '
247              'syntax.  Note the "=" is critical, don\'t include whitespace.'))
248    group.add_argument(
249        '--event-add-entries',
250        action='store',
251        help=('Specify comma-separated KEY=VAL entries to add key and value '
252              'pairs to all test events generated by this test run.  VAL may '
253              'be specified as VAL:TYPE, where TYPE may be int to convert '
254              'the value to an int'))
255
256    # Re-run related arguments
257    group = parser.add_argument_group('Test Re-run Options')
258    group.add_argument(
259        '--rerun-all-issues',
260        action='store_true',
261        help=('Re-run all issues that occurred during the test run '
262              'irrespective of the test method\'s marking as flakey. '
263              'Default behavior is to apply re-runs only to flakey '
264              'tests that generate issues.'))
265    group.add_argument(
266        '--rerun-max-file-threshold',
267        action='store',
268        type=int,
269        default=50,
270        help=('Maximum number of files requiring a rerun beyond '
271              'which the rerun will not occur.  This is meant to '
272              'stop a catastrophically failing test suite from forcing '
273              'all tests to be rerun in the single-worker phase.'))
274
275    # Remove the reference to our helper function
276    del X
277
278    group = parser.add_argument_group('Test directories')
279    group.add_argument(
280        'args',
281        metavar='test-dir',
282        nargs='*',
283        help='Specify a list of directory names to search for test modules named after Test*.py (test discovery). If empty, search from the current working directory instead.')
284
285    return parser
286