xref: /openbsd-src/gnu/llvm/lldb/packages/Python/lldbsuite/test/dotest.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick"""
2061da546SpatrickA simple testing framework for lldb using python's unit testing framework.
3061da546Spatrick
4061da546SpatrickTests for lldb are written as python scripts which take advantage of the script
5061da546Spatrickbridging provided by LLDB.framework to interact with lldb core.
6061da546Spatrick
7061da546SpatrickA specific naming pattern is followed by the .py script to be recognized as
8061da546Spatricka module which implements a test scenario, namely, Test*.py.
9061da546Spatrick
10061da546SpatrickTo specify the directories where "Test*.py" python test scripts are located,
11061da546Spatrickyou need to pass in a list of directory names.  By default, the current
12061da546Spatrickworking directory is searched if nothing is specified on the command line.
13061da546Spatrick
14061da546SpatrickType:
15061da546Spatrick
16061da546Spatrick./dotest.py -h
17061da546Spatrick
18061da546Spatrickfor available options.
19061da546Spatrick"""
20061da546Spatrick
21061da546Spatrickfrom __future__ import absolute_import
22061da546Spatrickfrom __future__ import print_function
23061da546Spatrick
24061da546Spatrick# System modules
25061da546Spatrickimport atexit
26061da546Spatrickimport datetime
27061da546Spatrickimport errno
28061da546Spatrickimport logging
29061da546Spatrickimport os
30061da546Spatrickimport platform
31061da546Spatrickimport re
32be691f3bSpatrickimport shutil
33061da546Spatrickimport signal
34061da546Spatrickimport subprocess
35061da546Spatrickimport sys
36061da546Spatrickimport tempfile
37061da546Spatrick
38061da546Spatrick# Third-party modules
39061da546Spatrickimport unittest2
40061da546Spatrick
41061da546Spatrick# LLDB Modules
42061da546Spatrickimport lldbsuite
43061da546Spatrickfrom . import configuration
44061da546Spatrickfrom . import dotest_args
45061da546Spatrickfrom . import lldbtest_config
46061da546Spatrickfrom . import test_categories
47061da546Spatrickfrom . import test_result
48061da546Spatrickfrom ..support import seven
49061da546Spatrick
50061da546Spatrick
51061da546Spatrickdef is_exe(fpath):
52061da546Spatrick    """Returns true if fpath is an executable."""
53061da546Spatrick    if fpath == None:
54061da546Spatrick        return False
55be691f3bSpatrick    if sys.platform == 'win32':
56be691f3bSpatrick        if not fpath.endswith(".exe"):
57be691f3bSpatrick            fpath += ".exe"
58061da546Spatrick    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
59061da546Spatrick
60061da546Spatrick
61061da546Spatrickdef which(program):
62061da546Spatrick    """Returns the full path to a program; None otherwise."""
63061da546Spatrick    fpath, _ = os.path.split(program)
64061da546Spatrick    if fpath:
65061da546Spatrick        if is_exe(program):
66061da546Spatrick            return program
67061da546Spatrick    else:
68061da546Spatrick        for path in os.environ["PATH"].split(os.pathsep):
69061da546Spatrick            exe_file = os.path.join(path, program)
70061da546Spatrick            if is_exe(exe_file):
71061da546Spatrick                return exe_file
72061da546Spatrick    return None
73061da546Spatrick
74061da546Spatrick
75061da546Spatrickdef usage(parser):
76061da546Spatrick    parser.print_help()
77061da546Spatrick    if configuration.verbose > 0:
78061da546Spatrick        print("""
79061da546SpatrickExamples:
80061da546Spatrick
81061da546SpatrickThis is an example of using the -f option to pinpoint to a specific test class
82061da546Spatrickand test method to be run:
83061da546Spatrick
84061da546Spatrick$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
85061da546Spatrick----------------------------------------------------------------------
86061da546SpatrickCollected 1 test
87061da546Spatrick
88061da546Spatricktest_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
89061da546SpatrickTest 'frame variable this' when stopped on a class constructor. ... ok
90061da546Spatrick
91061da546Spatrick----------------------------------------------------------------------
92061da546SpatrickRan 1 test in 1.396s
93061da546Spatrick
94061da546SpatrickOK
95061da546Spatrick
96061da546SpatrickAnd this is an example of using the -p option to run a single file (the filename
97061da546Spatrickmatches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
98061da546Spatrick
99061da546Spatrick$ ./dotest.py -v -p ObjC
100061da546Spatrick----------------------------------------------------------------------
101061da546SpatrickCollected 4 tests
102061da546Spatrick
103061da546Spatricktest_break_with_dsym (TestObjCMethods.FoundationTestCase)
104061da546SpatrickTest setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
105061da546Spatricktest_break_with_dwarf (TestObjCMethods.FoundationTestCase)
106061da546SpatrickTest setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
107061da546Spatricktest_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
108061da546SpatrickLookup objective-c data types and evaluate expressions. ... ok
109061da546Spatricktest_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
110061da546SpatrickLookup objective-c data types and evaluate expressions. ... ok
111061da546Spatrick
112061da546Spatrick----------------------------------------------------------------------
113061da546SpatrickRan 4 tests in 16.661s
114061da546Spatrick
115061da546SpatrickOK
116061da546Spatrick
117061da546SpatrickRunning of this script also sets up the LLDB_TEST environment variable so that
118061da546Spatrickindividual test cases can locate their supporting files correctly.  The script
119061da546Spatricktries to set up Python's search paths for modules by looking at the build tree
120061da546Spatrickrelative to this script.  See also the '-i' option in the following example.
121061da546Spatrick
122061da546SpatrickFinally, this is an example of using the lldb.py module distributed/installed by
123061da546SpatrickXcode4 to run against the tests under the 'forward' directory, and with the '-w'
124061da546Spatrickoption to add some delay between two tests.  It uses ARCH=x86_64 to specify that
125061da546Spatrickas the architecture and CC=clang to specify the compiler used for the test run:
126061da546Spatrick
127061da546Spatrick$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
128061da546Spatrick
129061da546SpatrickSession logs for test failures/errors will go into directory '2010-11-11-13_56_16'
130061da546Spatrick----------------------------------------------------------------------
131061da546SpatrickCollected 2 tests
132061da546Spatrick
133061da546Spatricktest_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
134061da546SpatrickDisplay *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
135061da546Spatricktest_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
136061da546SpatrickDisplay *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
137061da546Spatrick
138061da546Spatrick----------------------------------------------------------------------
139061da546SpatrickRan 2 tests in 5.659s
140061da546Spatrick
141061da546SpatrickOK
142061da546Spatrick
143061da546SpatrickThe 'Session ...' verbiage is recently introduced (see also the '-s' option) to
144061da546Spatricknotify the directory containing the session logs for test failures or errors.
145061da546SpatrickIn case there is any test failure/error, a similar message is appended at the
146061da546Spatrickend of the stderr output for your convenience.
147061da546Spatrick
148061da546SpatrickENABLING LOGS FROM TESTS
149061da546Spatrick
150061da546SpatrickOption 1:
151061da546Spatrick
152061da546SpatrickWriting logs into different files per test case::
153061da546Spatrick
154061da546Spatrick$ ./dotest.py --channel "lldb all"
155061da546Spatrick
156061da546Spatrick$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets"
157061da546Spatrick
158061da546SpatrickThese log files are written to:
159061da546Spatrick
160061da546Spatrick<session-dir>/<test-id>-host.log (logs from lldb host process)
161061da546Spatrick<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server)
162061da546Spatrick<session-dir>/<test-id>-<test-result>.log (console logs)
163061da546Spatrick
164061da546SpatrickBy default, logs from successful runs are deleted.  Use the --log-success flag
165061da546Spatrickto create reference logs for debugging.
166061da546Spatrick
167061da546Spatrick$ ./dotest.py --log-success
168061da546Spatrick
169061da546Spatrick""")
170061da546Spatrick    sys.exit(0)
171061da546Spatrick
172061da546Spatrick
173061da546Spatrickdef parseExclusion(exclusion_file):
174061da546Spatrick    """Parse an exclusion file, of the following format, where
175061da546Spatrick       'skip files', 'skip methods', 'xfail files', and 'xfail methods'
176061da546Spatrick       are the possible list heading values:
177061da546Spatrick
178061da546Spatrick       skip files
179061da546Spatrick       <file name>
180061da546Spatrick       <file name>
181061da546Spatrick
182061da546Spatrick       xfail methods
183061da546Spatrick       <method name>
184061da546Spatrick    """
185061da546Spatrick    excl_type = None
186061da546Spatrick
187061da546Spatrick    with open(exclusion_file) as f:
188061da546Spatrick        for line in f:
189061da546Spatrick            line = line.strip()
190061da546Spatrick            if not excl_type:
191061da546Spatrick                excl_type = line
192061da546Spatrick                continue
193061da546Spatrick
194061da546Spatrick            if not line:
195061da546Spatrick                excl_type = None
196061da546Spatrick            elif excl_type == 'skip':
197061da546Spatrick                if not configuration.skip_tests:
198061da546Spatrick                    configuration.skip_tests = []
199061da546Spatrick                configuration.skip_tests.append(line)
200061da546Spatrick            elif excl_type == 'xfail':
201061da546Spatrick                if not configuration.xfail_tests:
202061da546Spatrick                    configuration.xfail_tests = []
203061da546Spatrick                configuration.xfail_tests.append(line)
204061da546Spatrick
205061da546Spatrick
206061da546Spatrickdef parseOptionsAndInitTestdirs():
207061da546Spatrick    """Initialize the list of directories containing our unittest scripts.
208061da546Spatrick
209061da546Spatrick    '-h/--help as the first option prints out usage info and exit the program.
210061da546Spatrick    """
211061da546Spatrick
212061da546Spatrick    do_help = False
213061da546Spatrick
214061da546Spatrick    platform_system = platform.system()
215061da546Spatrick    platform_machine = platform.machine()
216061da546Spatrick
217061da546Spatrick    try:
218061da546Spatrick        parser = dotest_args.create_parser()
219061da546Spatrick        args = parser.parse_args()
220061da546Spatrick    except:
221061da546Spatrick        raise
222061da546Spatrick
223061da546Spatrick    if args.unset_env_varnames:
224061da546Spatrick        for env_var in args.unset_env_varnames:
225061da546Spatrick            if env_var in os.environ:
226061da546Spatrick                # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
227061da546Spatrick                # is automatically translated into a corresponding call to
228061da546Spatrick                # unsetenv().
229061da546Spatrick                del os.environ[env_var]
230061da546Spatrick                # os.unsetenv(env_var)
231061da546Spatrick
232061da546Spatrick    if args.set_env_vars:
233061da546Spatrick        for env_var in args.set_env_vars:
234061da546Spatrick            parts = env_var.split('=', 1)
235061da546Spatrick            if len(parts) == 1:
236061da546Spatrick                os.environ[parts[0]] = ""
237061da546Spatrick            else:
238061da546Spatrick                os.environ[parts[0]] = parts[1]
239061da546Spatrick
240061da546Spatrick    if args.set_inferior_env_vars:
241061da546Spatrick        lldbtest_config.inferior_env = ' '.join(args.set_inferior_env_vars)
242061da546Spatrick
243061da546Spatrick    if args.h:
244061da546Spatrick        do_help = True
245061da546Spatrick
246061da546Spatrick    if args.compiler:
247be691f3bSpatrick        configuration.compiler = os.path.abspath(args.compiler)
248061da546Spatrick        if not is_exe(configuration.compiler):
249061da546Spatrick            configuration.compiler = which(args.compiler)
250061da546Spatrick        if not is_exe(configuration.compiler):
251061da546Spatrick            logging.error(
252061da546Spatrick                    '%s is not a valid compiler executable; aborting...',
253061da546Spatrick                    args.compiler)
254061da546Spatrick            sys.exit(-1)
255061da546Spatrick    else:
256061da546Spatrick        # Use a compiler appropriate appropriate for the Apple SDK if one was
257061da546Spatrick        # specified
258061da546Spatrick        if platform_system == 'Darwin' and args.apple_sdk:
259061da546Spatrick            configuration.compiler = seven.get_command_output(
260061da546Spatrick                'xcrun -sdk "%s" -find clang 2> /dev/null' %
261061da546Spatrick                (args.apple_sdk))
262061da546Spatrick        else:
263061da546Spatrick            # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first
264061da546Spatrick            candidateCompilers = ['clang-3.5', 'clang', 'gcc']
265061da546Spatrick            for candidate in candidateCompilers:
266061da546Spatrick                if which(candidate):
267061da546Spatrick                    configuration.compiler = candidate
268061da546Spatrick                    break
269061da546Spatrick
270061da546Spatrick    if args.dsymutil:
271dda28197Spatrick        configuration.dsymutil = args.dsymutil
272061da546Spatrick    elif platform_system == 'Darwin':
273dda28197Spatrick        configuration.dsymutil = seven.get_command_output(
274061da546Spatrick            'xcrun -find -toolchain default dsymutil')
275be691f3bSpatrick    if args.llvm_tools_dir:
276be691f3bSpatrick        configuration.filecheck = shutil.which("FileCheck", path=args.llvm_tools_dir)
277be691f3bSpatrick        configuration.yaml2obj = shutil.which("yaml2obj", path=args.llvm_tools_dir)
278dda28197Spatrick
279061da546Spatrick    if not configuration.get_filecheck_path():
280061da546Spatrick        logging.warning('No valid FileCheck executable; some tests may fail...')
281be691f3bSpatrick        logging.warning('(Double-check the --llvm-tools-dir argument to dotest.py)')
282061da546Spatrick
283*f6aab3d8Srobert    if args.libcxx_include_dir or args.libcxx_library_dir:
284*f6aab3d8Srobert        if args.lldb_platform_name:
285*f6aab3d8Srobert            logging.warning('Custom libc++ is not supported for remote runs: ignoring --libcxx arguments')
286*f6aab3d8Srobert        elif not (args.libcxx_include_dir and args.libcxx_library_dir):
287*f6aab3d8Srobert            logging.error('Custom libc++ requires both --libcxx-include-dir and --libcxx-library-dir')
288*f6aab3d8Srobert            sys.exit(-1)
289*f6aab3d8Srobert    configuration.libcxx_include_dir = args.libcxx_include_dir
290*f6aab3d8Srobert    configuration.libcxx_include_target_dir = args.libcxx_include_target_dir
291*f6aab3d8Srobert    configuration.libcxx_library_dir = args.libcxx_library_dir
292*f6aab3d8Srobert
293061da546Spatrick    if args.channels:
294061da546Spatrick        lldbtest_config.channels = args.channels
295061da546Spatrick
296061da546Spatrick    if args.log_success:
297061da546Spatrick        lldbtest_config.log_success = args.log_success
298061da546Spatrick
299061da546Spatrick    if args.out_of_tree_debugserver:
300061da546Spatrick        lldbtest_config.out_of_tree_debugserver = args.out_of_tree_debugserver
301061da546Spatrick
302061da546Spatrick    # Set SDKROOT if we are using an Apple SDK
303061da546Spatrick    if platform_system == 'Darwin' and args.apple_sdk:
304dda28197Spatrick        configuration.sdkroot = seven.get_command_output(
305061da546Spatrick            'xcrun --sdk "%s" --show-sdk-path 2> /dev/null' %
306061da546Spatrick            (args.apple_sdk))
307be691f3bSpatrick        if not configuration.sdkroot:
308be691f3bSpatrick            logging.error(
309be691f3bSpatrick                    'No SDK found with the name %s; aborting...',
310be691f3bSpatrick                    args.apple_sdk)
311be691f3bSpatrick            sys.exit(-1)
312061da546Spatrick
313061da546Spatrick    if args.arch:
314061da546Spatrick        configuration.arch = args.arch
315061da546Spatrick    else:
316061da546Spatrick        configuration.arch = platform_machine
317061da546Spatrick
318061da546Spatrick    if args.categories_list:
319061da546Spatrick        configuration.categories_list = set(
320061da546Spatrick            test_categories.validate(
321061da546Spatrick                args.categories_list, False))
322061da546Spatrick        configuration.use_categories = True
323061da546Spatrick    else:
324061da546Spatrick        configuration.categories_list = []
325061da546Spatrick
326061da546Spatrick    if args.skip_categories:
327061da546Spatrick        configuration.skip_categories += test_categories.validate(
328061da546Spatrick            args.skip_categories, False)
329061da546Spatrick
330061da546Spatrick    if args.xfail_categories:
331061da546Spatrick        configuration.xfail_categories += test_categories.validate(
332061da546Spatrick            args.xfail_categories, False)
333061da546Spatrick
334061da546Spatrick    if args.E:
335061da546Spatrick        os.environ['CFLAGS_EXTRAS'] = args.E
336061da546Spatrick
337061da546Spatrick    if args.dwarf_version:
338061da546Spatrick        configuration.dwarf_version = args.dwarf_version
339061da546Spatrick        # We cannot modify CFLAGS_EXTRAS because they're used in test cases
340061da546Spatrick        # that explicitly require no debug info.
341061da546Spatrick        os.environ['CFLAGS'] = '-gdwarf-{}'.format(configuration.dwarf_version)
342061da546Spatrick
343061da546Spatrick    if args.settings:
344061da546Spatrick        for setting in args.settings:
345061da546Spatrick            if not len(setting) == 1 or not setting[0].count('='):
346061da546Spatrick                logging.error('"%s" is not a setting in the form "key=value"',
347061da546Spatrick                              setting[0])
348061da546Spatrick                sys.exit(-1)
349dda28197Spatrick            setting_list = setting[0].split('=', 1)
350dda28197Spatrick            configuration.settings.append((setting_list[0], setting_list[1]))
351061da546Spatrick
352061da546Spatrick    if args.d:
353061da546Spatrick        sys.stdout.write(
354061da546Spatrick            "Suspending the process %d to wait for debugger to attach...\n" %
355061da546Spatrick            os.getpid())
356061da546Spatrick        sys.stdout.flush()
357061da546Spatrick        os.kill(os.getpid(), signal.SIGSTOP)
358061da546Spatrick
359061da546Spatrick    if args.f:
360061da546Spatrick        if any([x.startswith('-') for x in args.f]):
361061da546Spatrick            usage(parser)
362061da546Spatrick        configuration.filters.extend(args.f)
363061da546Spatrick
364061da546Spatrick    if args.framework:
365061da546Spatrick        configuration.lldb_framework_path = args.framework
366061da546Spatrick
367061da546Spatrick    if args.executable:
368061da546Spatrick        # lldb executable is passed explicitly
369*f6aab3d8Srobert        lldbtest_config.lldbExec = os.path.abspath(args.executable)
370061da546Spatrick        if not is_exe(lldbtest_config.lldbExec):
371061da546Spatrick            lldbtest_config.lldbExec = which(args.executable)
372061da546Spatrick        if not is_exe(lldbtest_config.lldbExec):
373061da546Spatrick            logging.error(
374061da546Spatrick                    '%s is not a valid executable to test; aborting...',
375061da546Spatrick                    args.executable)
376061da546Spatrick            sys.exit(-1)
377061da546Spatrick
378061da546Spatrick    if args.excluded:
379061da546Spatrick        for excl_file in args.excluded:
380061da546Spatrick            parseExclusion(excl_file)
381061da546Spatrick
382061da546Spatrick    if args.p:
383061da546Spatrick        if args.p.startswith('-'):
384061da546Spatrick            usage(parser)
385061da546Spatrick        configuration.regexp = args.p
386061da546Spatrick
387061da546Spatrick    if args.t:
388061da546Spatrick        os.environ['LLDB_COMMAND_TRACE'] = 'YES'
389061da546Spatrick
390061da546Spatrick    if args.v:
391061da546Spatrick        configuration.verbose = 2
392061da546Spatrick
393061da546Spatrick    # argparse makes sure we have a number
394061da546Spatrick    if args.sharp:
395061da546Spatrick        configuration.count = args.sharp
396061da546Spatrick
397061da546Spatrick    if sys.platform.startswith('win32'):
398061da546Spatrick        os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(
399061da546Spatrick            args.disable_crash_dialog)
400061da546Spatrick        os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True)
401061da546Spatrick
402061da546Spatrick    if do_help:
403061da546Spatrick        usage(parser)
404061da546Spatrick
405061da546Spatrick    if args.lldb_platform_name:
406061da546Spatrick        configuration.lldb_platform_name = args.lldb_platform_name
407061da546Spatrick    if args.lldb_platform_url:
408061da546Spatrick        configuration.lldb_platform_url = args.lldb_platform_url
409061da546Spatrick    if args.lldb_platform_working_dir:
410061da546Spatrick        configuration.lldb_platform_working_dir = args.lldb_platform_working_dir
411be691f3bSpatrick    if platform_system == 'Darwin'  and args.apple_sdk:
412be691f3bSpatrick        configuration.apple_sdk = args.apple_sdk
413061da546Spatrick    if args.test_build_dir:
414061da546Spatrick        configuration.test_build_dir = args.test_build_dir
415061da546Spatrick    if args.lldb_module_cache_dir:
416061da546Spatrick        configuration.lldb_module_cache_dir = args.lldb_module_cache_dir
417061da546Spatrick    else:
418061da546Spatrick        configuration.lldb_module_cache_dir = os.path.join(
419061da546Spatrick            configuration.test_build_dir, 'module-cache-lldb')
420061da546Spatrick    if args.clang_module_cache_dir:
421061da546Spatrick        configuration.clang_module_cache_dir = args.clang_module_cache_dir
422061da546Spatrick    else:
423061da546Spatrick        configuration.clang_module_cache_dir = os.path.join(
424061da546Spatrick            configuration.test_build_dir, 'module-cache-clang')
425061da546Spatrick
426dda28197Spatrick    if args.lldb_libs_dir:
427dda28197Spatrick        configuration.lldb_libs_dir = args.lldb_libs_dir
428dda28197Spatrick
429dda28197Spatrick    if args.enabled_plugins:
430dda28197Spatrick        configuration.enabled_plugins = args.enabled_plugins
431061da546Spatrick
432061da546Spatrick    # Gather all the dirs passed on the command line.
433061da546Spatrick    if len(args.args) > 0:
434061da546Spatrick        configuration.testdirs = [os.path.realpath(os.path.abspath(x)) for x in args.args]
435061da546Spatrick
436061da546Spatrick    lldbtest_config.codesign_identity = args.codesign_identity
437061da546Spatrick
438be691f3bSpatrickdef registerFaulthandler():
439be691f3bSpatrick    try:
440be691f3bSpatrick        import faulthandler
441be691f3bSpatrick    except ImportError:
442be691f3bSpatrick        # faulthandler is not available until python3
443be691f3bSpatrick        return
444061da546Spatrick
445be691f3bSpatrick    faulthandler.enable()
446be691f3bSpatrick    # faulthandler.register is not available on Windows.
447be691f3bSpatrick    if getattr(faulthandler, 'register', None):
448be691f3bSpatrick        faulthandler.register(signal.SIGTERM, chain=True)
449061da546Spatrick
450061da546Spatrickdef setupSysPath():
451061da546Spatrick    """
452061da546Spatrick    Add LLDB.framework/Resources/Python to the search paths for modules.
453061da546Spatrick    As a side effect, we also discover the 'lldb' executable and export it here.
454061da546Spatrick    """
455061da546Spatrick
456061da546Spatrick    # Get the directory containing the current script.
457061da546Spatrick    if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
458061da546Spatrick        scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
459061da546Spatrick    else:
460be691f3bSpatrick        scriptPath = os.path.dirname(os.path.abspath(__file__))
461061da546Spatrick    if not scriptPath.endswith('test'):
462061da546Spatrick        print("This script expects to reside in lldb's test directory.")
463061da546Spatrick        sys.exit(-1)
464061da546Spatrick
465061da546Spatrick    os.environ["LLDB_TEST"] = scriptPath
466061da546Spatrick
467061da546Spatrick    # Set up the root build directory.
468061da546Spatrick    if not configuration.test_build_dir:
469061da546Spatrick        raise Exception("test_build_dir is not set")
470dda28197Spatrick    configuration.test_build_dir = os.path.abspath(configuration.test_build_dir)
471061da546Spatrick
472061da546Spatrick    # Set up the LLDB_SRC environment variable, so that the tests can locate
473061da546Spatrick    # the LLDB source code.
474061da546Spatrick    os.environ["LLDB_SRC"] = lldbsuite.lldb_root
475061da546Spatrick
476061da546Spatrick    pluginPath = os.path.join(scriptPath, 'plugins')
477061da546Spatrick    toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode')
478061da546Spatrick    toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
479be691f3bSpatrick    intelpt = os.path.join(scriptPath, 'tools', 'intelpt')
480061da546Spatrick
481061da546Spatrick    # Insert script dir, plugin dir and lldb-server dir to the sys.path.
482061da546Spatrick    sys.path.insert(0, pluginPath)
483061da546Spatrick    # Adding test/tools/lldb-vscode to the path makes it easy to
484061da546Spatrick    # "import lldb_vscode_testcase" from the VSCode tests
485061da546Spatrick    sys.path.insert(0, toolsLLDBVSCode)
486061da546Spatrick    # Adding test/tools/lldb-server to the path makes it easy
487061da546Spatrick    # to "import lldbgdbserverutils" from the lldb-server tests
488be691f3bSpatrick    sys.path.insert(0, toolsLLDBServerPath)
489be691f3bSpatrick    # Adding test/tools/intelpt to the path makes it easy
490be691f3bSpatrick    # to "import intelpt_testcase" from the lldb-server tests
491be691f3bSpatrick    sys.path.insert(0, intelpt)
492061da546Spatrick
493061da546Spatrick    # This is the root of the lldb git/svn checkout
494061da546Spatrick    # When this changes over to a package instead of a standalone script, this
495061da546Spatrick    # will be `lldbsuite.lldb_root`
496061da546Spatrick    lldbRootDirectory = lldbsuite.lldb_root
497061da546Spatrick
498061da546Spatrick    # Some of the tests can invoke the 'lldb' command directly.
499061da546Spatrick    # We'll try to locate the appropriate executable right here.
500061da546Spatrick
501061da546Spatrick    # The lldb executable can be set from the command line
502061da546Spatrick    # if it's not set, we try to find it now
503061da546Spatrick    # first, we try the environment
504061da546Spatrick    if not lldbtest_config.lldbExec:
505061da546Spatrick        # First, you can define an environment variable LLDB_EXEC specifying the
506061da546Spatrick        # full pathname of the lldb executable.
507061da546Spatrick        if "LLDB_EXEC" in os.environ:
508061da546Spatrick            lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]
509061da546Spatrick
510061da546Spatrick    if not lldbtest_config.lldbExec:
511061da546Spatrick        # Last, check the path
512061da546Spatrick        lldbtest_config.lldbExec = which('lldb')
513061da546Spatrick
514061da546Spatrick    if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
515061da546Spatrick        print(
516061da546Spatrick            "'{}' is not a path to a valid executable".format(
517061da546Spatrick                lldbtest_config.lldbExec))
518061da546Spatrick        lldbtest_config.lldbExec = None
519061da546Spatrick
520061da546Spatrick    if not lldbtest_config.lldbExec:
521061da546Spatrick        print("The 'lldb' executable cannot be located.  Some of the tests may not be run as a result.")
522061da546Spatrick        sys.exit(-1)
523061da546Spatrick
524061da546Spatrick    os.system('%s -v' % lldbtest_config.lldbExec)
525061da546Spatrick
526061da546Spatrick    lldbDir = os.path.dirname(lldbtest_config.lldbExec)
527061da546Spatrick
528061da546Spatrick    lldbVSCodeExec = os.path.join(lldbDir, "lldb-vscode")
529061da546Spatrick    if is_exe(lldbVSCodeExec):
530061da546Spatrick        os.environ["LLDBVSCODE_EXEC"] = lldbVSCodeExec
531061da546Spatrick    else:
532061da546Spatrick        if not configuration.shouldSkipBecauseOfCategories(["lldb-vscode"]):
533061da546Spatrick            print(
534061da546Spatrick                "The 'lldb-vscode' executable cannot be located.  The lldb-vscode tests can not be run as a result.")
535061da546Spatrick            configuration.skip_categories.append("lldb-vscode")
536061da546Spatrick
537061da546Spatrick    lldbPythonDir = None  # The directory that contains 'lldb/__init__.py'
538be691f3bSpatrick
539061da546Spatrick    # If our lldb supports the -P option, use it to find the python path:
540be691f3bSpatrick    lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], universal_newlines=True)
541be691f3bSpatrick    if lldb_dash_p_result:
542be691f3bSpatrick        for line in lldb_dash_p_result.splitlines():
543be691f3bSpatrick            if os.path.isdir(line) and os.path.exists(os.path.join(line, 'lldb', '__init__.py')):
544be691f3bSpatrick                lldbPythonDir = line
545be691f3bSpatrick                break
546061da546Spatrick
547061da546Spatrick    if not lldbPythonDir:
548061da546Spatrick        print(
549061da546Spatrick            "Unable to load lldb extension module.  Possible reasons for this include:")
550061da546Spatrick        print("  1) LLDB was built with LLDB_ENABLE_PYTHON=0")
551061da546Spatrick        print(
552061da546Spatrick            "  2) PYTHONPATH and PYTHONHOME are not set correctly.  PYTHONHOME should refer to")
553061da546Spatrick        print(
554061da546Spatrick            "     the version of Python that LLDB built and linked against, and PYTHONPATH")
555061da546Spatrick        print(
556061da546Spatrick            "     should contain the Lib directory for the same python distro, as well as the")
557061da546Spatrick        print("     location of LLDB\'s site-packages folder.")
558061da546Spatrick        print(
559061da546Spatrick            "  3) A different version of Python than that which was built against is exported in")
560061da546Spatrick        print("     the system\'s PATH environment variable, causing conflicts.")
561061da546Spatrick        print(
562061da546Spatrick            "  4) The executable '%s' could not be found.  Please check " %
563061da546Spatrick            lldbtest_config.lldbExec)
564061da546Spatrick        print("     that it exists and is executable.")
565061da546Spatrick
566061da546Spatrick    if lldbPythonDir:
567061da546Spatrick        lldbPythonDir = os.path.normpath(lldbPythonDir)
568061da546Spatrick        # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
569061da546Spatrick        # If the path we've constructed looks like that, then we'll strip out
570061da546Spatrick        # the Versions/A part.
571061da546Spatrick        (before, frameWithVersion, after) = lldbPythonDir.rpartition(
572061da546Spatrick            "LLDB.framework/Versions/A")
573061da546Spatrick        if frameWithVersion != "":
574061da546Spatrick            lldbPythonDir = before + "LLDB.framework" + after
575061da546Spatrick
576061da546Spatrick        lldbPythonDir = os.path.abspath(lldbPythonDir)
577061da546Spatrick
578be691f3bSpatrick        if "freebsd" in sys.platform or "linux" in sys.platform:
579be691f3bSpatrick            os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..')
580be691f3bSpatrick
581061da546Spatrick        # If tests need to find LLDB_FRAMEWORK, now they can do it
582061da546Spatrick        os.environ["LLDB_FRAMEWORK"] = os.path.dirname(
583061da546Spatrick            os.path.dirname(lldbPythonDir))
584061da546Spatrick
585061da546Spatrick        # This is to locate the lldb.py module.  Insert it right after
586061da546Spatrick        # sys.path[0].
587061da546Spatrick        sys.path[1:1] = [lldbPythonDir]
588061da546Spatrick
589061da546Spatrick
590061da546Spatrickdef visit_file(dir, name):
591061da546Spatrick    # Try to match the regexp pattern, if specified.
592061da546Spatrick    if configuration.regexp:
593061da546Spatrick        if not re.search(configuration.regexp, name):
594061da546Spatrick            # We didn't match the regex, we're done.
595061da546Spatrick            return
596061da546Spatrick
597061da546Spatrick    if configuration.skip_tests:
598061da546Spatrick        for file_regexp in configuration.skip_tests:
599061da546Spatrick            if re.search(file_regexp, name):
600061da546Spatrick                return
601061da546Spatrick
602061da546Spatrick    # We found a match for our test.  Add it to the suite.
603061da546Spatrick
604061da546Spatrick    # Update the sys.path first.
605061da546Spatrick    if not sys.path.count(dir):
606061da546Spatrick        sys.path.insert(0, dir)
607061da546Spatrick    base = os.path.splitext(name)[0]
608061da546Spatrick
609061da546Spatrick    # Thoroughly check the filterspec against the base module and admit
610061da546Spatrick    # the (base, filterspec) combination only when it makes sense.
611061da546Spatrick
612061da546Spatrick    def check(obj, parts):
613061da546Spatrick        for part in parts:
614061da546Spatrick            try:
615061da546Spatrick                parent, obj = obj, getattr(obj, part)
616061da546Spatrick            except AttributeError:
617061da546Spatrick                # The filterspec has failed.
618061da546Spatrick                return False
619061da546Spatrick        return True
620061da546Spatrick
621061da546Spatrick    module = __import__(base)
622061da546Spatrick
623061da546Spatrick    def iter_filters():
624061da546Spatrick        for filterspec in configuration.filters:
625061da546Spatrick            parts = filterspec.split('.')
626061da546Spatrick            if check(module, parts):
627061da546Spatrick                yield filterspec
628061da546Spatrick            elif parts[0] == base and len(parts) > 1 and check(module, parts[1:]):
629061da546Spatrick                yield '.'.join(parts[1:])
630061da546Spatrick            else:
631061da546Spatrick                for key,value in module.__dict__.items():
632061da546Spatrick                    if check(value, parts):
633061da546Spatrick                        yield key + '.' + filterspec
634061da546Spatrick
635061da546Spatrick    filtered = False
636061da546Spatrick    for filterspec in iter_filters():
637061da546Spatrick        filtered = True
638061da546Spatrick        print("adding filter spec %s to module %s" % (filterspec, repr(module)))
639061da546Spatrick        tests = unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)
640061da546Spatrick        configuration.suite.addTests(tests)
641061da546Spatrick
642061da546Spatrick    # Forgo this module if the (base, filterspec) combo is invalid
643061da546Spatrick    if configuration.filters and not filtered:
644061da546Spatrick        return
645061da546Spatrick
646061da546Spatrick    if not filtered:
647061da546Spatrick        # Add the entire file's worth of tests since we're not filtered.
648061da546Spatrick        # Also the fail-over case when the filterspec branch
649061da546Spatrick        # (base, filterspec) combo doesn't make sense.
650061da546Spatrick        configuration.suite.addTests(
651061da546Spatrick            unittest2.defaultTestLoader.loadTestsFromName(base))
652061da546Spatrick
653061da546Spatrick
654061da546Spatrickdef visit(prefix, dir, names):
655061da546Spatrick    """Visitor function for os.path.walk(path, visit, arg)."""
656061da546Spatrick
657061da546Spatrick    dir_components = set(dir.split(os.sep))
658061da546Spatrick    excluded_components = set(['.svn', '.git'])
659061da546Spatrick    if dir_components.intersection(excluded_components):
660061da546Spatrick        return
661061da546Spatrick
662061da546Spatrick    # Gather all the Python test file names that follow the Test*.py pattern.
663061da546Spatrick    python_test_files = [
664061da546Spatrick        name
665061da546Spatrick        for name in names
666061da546Spatrick        if name.endswith('.py') and name.startswith(prefix)]
667061da546Spatrick
668061da546Spatrick    # Visit all the python test files.
669061da546Spatrick    for name in python_test_files:
670061da546Spatrick        # Ensure we error out if we have multiple tests with the same
671061da546Spatrick        # base name.
672061da546Spatrick        # Future improvement: find all the places where we work with base
673061da546Spatrick        # names and convert to full paths.  We have directory structure
674061da546Spatrick        # to disambiguate these, so we shouldn't need this constraint.
675061da546Spatrick        if name in configuration.all_tests:
676061da546Spatrick            raise Exception("Found multiple tests with the name %s" % name)
677061da546Spatrick        configuration.all_tests.add(name)
678061da546Spatrick
679061da546Spatrick        # Run the relevant tests in the python file.
680061da546Spatrick        visit_file(dir, name)
681061da546Spatrick
682061da546Spatrick
683061da546Spatrick# ======================================== #
684061da546Spatrick#                                          #
685061da546Spatrick# Execution of the test driver starts here #
686061da546Spatrick#                                          #
687061da546Spatrick# ======================================== #
688061da546Spatrick
689061da546Spatrick
690061da546Spatrickdef checkDsymForUUIDIsNotOn():
691061da546Spatrick    cmd = ["defaults", "read", "com.apple.DebugSymbols"]
692061da546Spatrick    process = subprocess.Popen(
693061da546Spatrick        cmd,
694061da546Spatrick        stdout=subprocess.PIPE,
695061da546Spatrick        stderr=subprocess.STDOUT)
696061da546Spatrick    cmd_output = process.stdout.read()
697061da546Spatrick    output_str = cmd_output.decode("utf-8")
698061da546Spatrick    if "DBGFileMappedPaths = " in output_str:
699061da546Spatrick        print("%s =>" % ' '.join(cmd))
700061da546Spatrick        print(output_str)
701061da546Spatrick        print(
702061da546Spatrick            "Disable automatic lookup and caching of dSYMs before running the test suite!")
703061da546Spatrick        print("Exiting...")
704061da546Spatrick        sys.exit(0)
705061da546Spatrick
706061da546Spatrick
707061da546Spatrickdef exitTestSuite(exitCode=None):
708dda28197Spatrick    # lldb.py does SBDebugger.Initialize().
709dda28197Spatrick    # Call SBDebugger.Terminate() on exit.
710061da546Spatrick    import lldb
711061da546Spatrick    lldb.SBDebugger.Terminate()
712061da546Spatrick    if exitCode:
713061da546Spatrick        sys.exit(exitCode)
714061da546Spatrick
715061da546Spatrick
716061da546Spatrickdef getVersionForSDK(sdk):
717061da546Spatrick    sdk = str.lower(sdk)
718061da546Spatrick    full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
719061da546Spatrick    basename = os.path.basename(full_path)
720061da546Spatrick    basename = os.path.splitext(basename)[0]
721061da546Spatrick    basename = str.lower(basename)
722061da546Spatrick    ver = basename.replace(sdk, '')
723061da546Spatrick    return ver
724061da546Spatrick
725061da546Spatrick
726061da546Spatrickdef checkCompiler():
727061da546Spatrick    # Add some intervention here to sanity check that the compiler requested is sane.
728061da546Spatrick    # If found not to be an executable program, we abort.
729061da546Spatrick    c = configuration.compiler
730061da546Spatrick    if which(c):
731061da546Spatrick        return
732061da546Spatrick
733061da546Spatrick    if not sys.platform.startswith("darwin"):
734061da546Spatrick        raise Exception(c + " is not a valid compiler")
735061da546Spatrick
736061da546Spatrick    pipe = subprocess.Popen(
737061da546Spatrick        ['xcrun', '-find', c], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
738061da546Spatrick    cmd_output = pipe.stdout.read()
739061da546Spatrick    if not cmd_output or "not found" in cmd_output:
740061da546Spatrick        raise Exception(c + " is not a valid compiler")
741061da546Spatrick
742061da546Spatrick    configuration.compiler = cmd_output.split('\n')[0]
743061da546Spatrick    print("'xcrun -find %s' returning %s" % (c, configuration.compiler))
744061da546Spatrick
745061da546Spatrickdef canRunLibcxxTests():
746061da546Spatrick    from lldbsuite.test import lldbplatformutil
747061da546Spatrick
748061da546Spatrick    platform = lldbplatformutil.getPlatform()
749061da546Spatrick
750061da546Spatrick    if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin():
751061da546Spatrick        return True, "libc++ always present"
752061da546Spatrick
753061da546Spatrick    if platform == "linux":
754061da546Spatrick        with tempfile.NamedTemporaryFile() as f:
755061da546Spatrick            cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.name, "-"]
756061da546Spatrick            p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
757be691f3bSpatrick            _, stderr = p.communicate("#include <cassert>\nint main() {}")
758061da546Spatrick            if not p.returncode:
759061da546Spatrick                return True, "Compiling with -stdlib=libc++ works"
760061da546Spatrick            return False, "Compiling with -stdlib=libc++ fails with the error: %s" % stderr
761061da546Spatrick
762061da546Spatrick    return False, "Don't know how to build with libc++ on %s" % platform
763061da546Spatrick
764061da546Spatrickdef checkLibcxxSupport():
765061da546Spatrick    result, reason = canRunLibcxxTests()
766061da546Spatrick    if result:
767061da546Spatrick        return # libc++ supported
768061da546Spatrick    if "libc++" in configuration.categories_list:
769061da546Spatrick        return # libc++ category explicitly requested, let it run.
770be691f3bSpatrick    if configuration.verbose:
771be691f3bSpatrick        print("libc++ tests will not be run because: " + reason)
772061da546Spatrick    configuration.skip_categories.append("libc++")
773061da546Spatrick
774061da546Spatrickdef canRunLibstdcxxTests():
775061da546Spatrick    from lldbsuite.test import lldbplatformutil
776061da546Spatrick
777061da546Spatrick    platform = lldbplatformutil.getPlatform()
778061da546Spatrick    if lldbplatformutil.target_is_android():
779061da546Spatrick        platform = "android"
780061da546Spatrick    if platform == "linux":
781061da546Spatrick        return True, "libstdcxx always present"
782061da546Spatrick    return False, "Don't know how to build with libstdcxx on %s" % platform
783061da546Spatrick
784061da546Spatrickdef checkLibstdcxxSupport():
785061da546Spatrick    result, reason = canRunLibstdcxxTests()
786061da546Spatrick    if result:
787061da546Spatrick        return # libstdcxx supported
788061da546Spatrick    if "libstdcxx" in configuration.categories_list:
789061da546Spatrick        return # libstdcxx category explicitly requested, let it run.
790be691f3bSpatrick    if configuration.verbose:
791061da546Spatrick        print("libstdcxx tests will not be run because: " + reason)
792061da546Spatrick    configuration.skip_categories.append("libstdcxx")
793061da546Spatrick
794061da546Spatrickdef canRunWatchpointTests():
795061da546Spatrick    from lldbsuite.test import lldbplatformutil
796061da546Spatrick
797061da546Spatrick    platform = lldbplatformutil.getPlatform()
798061da546Spatrick    if platform == "netbsd":
799061da546Spatrick        if os.geteuid() == 0:
800061da546Spatrick            return True, "root can always write dbregs"
801061da546Spatrick        try:
802061da546Spatrick            output = subprocess.check_output(["/sbin/sysctl", "-n",
803061da546Spatrick              "security.models.extensions.user_set_dbregs"]).decode().strip()
804061da546Spatrick            if output == "1":
805061da546Spatrick                return True, "security.models.extensions.user_set_dbregs enabled"
806061da546Spatrick        except subprocess.CalledProcessError:
807061da546Spatrick            pass
808061da546Spatrick        return False, "security.models.extensions.user_set_dbregs disabled"
809be691f3bSpatrick    elif platform == "freebsd" and configuration.arch == "aarch64":
810be691f3bSpatrick        import lldb
811be691f3bSpatrick        if lldb.SBPlatform.GetHostPlatform().GetOSMajorVersion() < 13:
812be691f3bSpatrick            return False, "Watchpoint support on arm64 requires FreeBSD 13.0"
813061da546Spatrick    return True, "watchpoint support available"
814061da546Spatrick
815061da546Spatrickdef checkWatchpointSupport():
816061da546Spatrick    result, reason = canRunWatchpointTests()
817061da546Spatrick    if result:
818061da546Spatrick        return # watchpoints supported
819061da546Spatrick    if "watchpoint" in configuration.categories_list:
820061da546Spatrick        return # watchpoint category explicitly requested, let it run.
821be691f3bSpatrick    if configuration.verbose:
822061da546Spatrick        print("watchpoint tests will not be run because: " + reason)
823061da546Spatrick    configuration.skip_categories.append("watchpoint")
824061da546Spatrick
825be691f3bSpatrickdef checkObjcSupport():
826be691f3bSpatrick    from lldbsuite.test import lldbplatformutil
827be691f3bSpatrick
828be691f3bSpatrick    if not lldbplatformutil.platformIsDarwin():
829be691f3bSpatrick        if configuration.verbose:
830be691f3bSpatrick            print("objc tests will be skipped because of unsupported platform")
831be691f3bSpatrick        configuration.skip_categories.append("objc")
832be691f3bSpatrick
833061da546Spatrickdef checkDebugInfoSupport():
834*f6aab3d8Srobert    from lldbsuite.test import lldbplatformutil
835061da546Spatrick
836*f6aab3d8Srobert    platform = lldbplatformutil.getPlatform()
837061da546Spatrick    compiler = configuration.compiler
838061da546Spatrick    for cat in test_categories.debug_info_categories:
839061da546Spatrick        if cat in configuration.categories_list:
840061da546Spatrick            continue # Category explicitly requested, let it run.
841061da546Spatrick        if test_categories.is_supported_on_platform(cat, platform, compiler):
842061da546Spatrick            continue
843061da546Spatrick        configuration.skip_categories.append(cat)
844be691f3bSpatrick
845be691f3bSpatrickdef checkDebugServerSupport():
846be691f3bSpatrick    from lldbsuite.test import lldbplatformutil
847be691f3bSpatrick    import lldb
848be691f3bSpatrick
849be691f3bSpatrick    skip_msg = "Skipping %s tests, as they are not compatible with remote testing on this platform"
850be691f3bSpatrick    if lldbplatformutil.platformIsDarwin():
851be691f3bSpatrick        configuration.skip_categories.append("llgs")
852be691f3bSpatrick        if lldb.remote_platform:
853be691f3bSpatrick            # <rdar://problem/34539270>
854be691f3bSpatrick            configuration.skip_categories.append("debugserver")
855be691f3bSpatrick            if configuration.verbose:
856be691f3bSpatrick                print(skip_msg%"debugserver");
857be691f3bSpatrick    else:
858be691f3bSpatrick        configuration.skip_categories.append("debugserver")
859be691f3bSpatrick        if lldb.remote_platform and lldbplatformutil.getPlatform() == "windows":
860be691f3bSpatrick            configuration.skip_categories.append("llgs")
861be691f3bSpatrick            if configuration.verbose:
862be691f3bSpatrick                print(skip_msg%"lldb-server");
863be691f3bSpatrick
864be691f3bSpatrick
865be691f3bSpatrickdef checkForkVForkSupport():
866be691f3bSpatrick    from lldbsuite.test import lldbplatformutil
867be691f3bSpatrick
868be691f3bSpatrick    platform = lldbplatformutil.getPlatform()
869be691f3bSpatrick    if platform not in ["freebsd", "linux", "netbsd"]:
870be691f3bSpatrick        configuration.skip_categories.append("fork")
871be691f3bSpatrick
872061da546Spatrick
873061da546Spatrickdef run_suite():
874061da546Spatrick    # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
875061da546Spatrick    # does not exist before proceeding to running the test suite.
876061da546Spatrick    if sys.platform.startswith("darwin"):
877061da546Spatrick        checkDsymForUUIDIsNotOn()
878061da546Spatrick
879061da546Spatrick    # Start the actions by first parsing the options while setting up the test
880061da546Spatrick    # directories, followed by setting up the search paths for lldb utilities;
881061da546Spatrick    # then, we walk the directory trees and collect the tests into our test suite.
882061da546Spatrick    #
883061da546Spatrick    parseOptionsAndInitTestdirs()
884061da546Spatrick
885be691f3bSpatrick    # Print a stack trace if the test hangs or is passed SIGTERM.
886be691f3bSpatrick    registerFaulthandler()
887061da546Spatrick
888061da546Spatrick    setupSysPath()
889061da546Spatrick
890061da546Spatrick    import lldb
891dda28197Spatrick    lldb.SBDebugger.Initialize()
892*f6aab3d8Srobert    lldb.SBDebugger.PrintStackTraceOnError()
893dda28197Spatrick
894dda28197Spatrick    # Use host platform by default.
895*f6aab3d8Srobert    lldb.remote_platform = None
896dda28197Spatrick    lldb.selected_platform = lldb.SBPlatform.GetHostPlatform()
897dda28197Spatrick
898061da546Spatrick    # Now we can also import lldbutil
899061da546Spatrick    from lldbsuite.test import lldbutil
900061da546Spatrick
901061da546Spatrick    if configuration.lldb_platform_name:
902061da546Spatrick        print("Setting up remote platform '%s'" %
903061da546Spatrick              (configuration.lldb_platform_name))
904061da546Spatrick        lldb.remote_platform = lldb.SBPlatform(
905061da546Spatrick            configuration.lldb_platform_name)
906*f6aab3d8Srobert        lldb.selected_platform = lldb.remote_platform
907061da546Spatrick        if not lldb.remote_platform.IsValid():
908061da546Spatrick            print(
909061da546Spatrick                "error: unable to create the LLDB platform named '%s'." %
910061da546Spatrick                (configuration.lldb_platform_name))
911061da546Spatrick            exitTestSuite(1)
912061da546Spatrick        if configuration.lldb_platform_url:
913061da546Spatrick            # We must connect to a remote platform if a LLDB platform URL was
914061da546Spatrick            # specified
915061da546Spatrick            print(
916061da546Spatrick                "Connecting to remote platform '%s' at '%s'..." %
917061da546Spatrick                (configuration.lldb_platform_name, configuration.lldb_platform_url))
918061da546Spatrick            platform_connect_options = lldb.SBPlatformConnectOptions(
919061da546Spatrick                configuration.lldb_platform_url)
920061da546Spatrick            err = lldb.remote_platform.ConnectRemote(platform_connect_options)
921061da546Spatrick            if err.Success():
922061da546Spatrick                print("Connected.")
923061da546Spatrick            else:
924061da546Spatrick                print("error: failed to connect to remote platform using URL '%s': %s" % (
925061da546Spatrick                    configuration.lldb_platform_url, err))
926061da546Spatrick                exitTestSuite(1)
927061da546Spatrick        else:
928061da546Spatrick            configuration.lldb_platform_url = None
929061da546Spatrick
930061da546Spatrick    if configuration.lldb_platform_working_dir:
931061da546Spatrick        print("Setting remote platform working directory to '%s'..." %
932061da546Spatrick              (configuration.lldb_platform_working_dir))
933061da546Spatrick        error = lldb.remote_platform.MakeDirectory(
934061da546Spatrick            configuration.lldb_platform_working_dir, 448)  # 448 = 0o700
935061da546Spatrick        if error.Fail():
936061da546Spatrick            raise Exception("making remote directory '%s': %s" % (
937061da546Spatrick                configuration.lldb_platform_working_dir, error))
938061da546Spatrick
939061da546Spatrick        if not lldb.remote_platform.SetWorkingDirectory(
940061da546Spatrick                configuration.lldb_platform_working_dir):
941061da546Spatrick            raise Exception("failed to set working directory '%s'" % configuration.lldb_platform_working_dir)
942dda28197Spatrick        lldb.selected_platform = lldb.remote_platform
943061da546Spatrick    else:
944061da546Spatrick        lldb.remote_platform = None
945061da546Spatrick        configuration.lldb_platform_working_dir = None
946061da546Spatrick        configuration.lldb_platform_url = None
947061da546Spatrick
948061da546Spatrick    # Set up the working directory.
949061da546Spatrick    # Note that it's not dotest's job to clean this directory.
950dda28197Spatrick    lldbutil.mkdir_p(configuration.test_build_dir)
951061da546Spatrick
952061da546Spatrick    checkLibcxxSupport()
953061da546Spatrick    checkLibstdcxxSupport()
954061da546Spatrick    checkWatchpointSupport()
955061da546Spatrick    checkDebugInfoSupport()
956be691f3bSpatrick    checkDebugServerSupport()
957be691f3bSpatrick    checkObjcSupport()
958be691f3bSpatrick    checkForkVForkSupport()
959061da546Spatrick
960*f6aab3d8Srobert    skipped_categories_list = ", ".join(configuration.skip_categories)
961be691f3bSpatrick    print("Skipping the following test categories: {}".format(configuration.skip_categories))
962061da546Spatrick
963dda28197Spatrick    for testdir in configuration.testdirs:
964061da546Spatrick        for (dirpath, dirnames, filenames) in os.walk(testdir):
965061da546Spatrick            visit('Test', dirpath, filenames)
966061da546Spatrick
967061da546Spatrick    #
968061da546Spatrick    # Now that we have loaded all the test cases, run the whole test suite.
969061da546Spatrick    #
970061da546Spatrick
971061da546Spatrick    # Install the control-c handler.
972061da546Spatrick    unittest2.signals.installHandler()
973061da546Spatrick
974061da546Spatrick    #
975061da546Spatrick    # Invoke the default TextTestRunner to run the test suite
976061da546Spatrick    #
977061da546Spatrick    checkCompiler()
978061da546Spatrick
979061da546Spatrick    if configuration.verbose:
980061da546Spatrick        print("compiler=%s" % configuration.compiler)
981061da546Spatrick
982061da546Spatrick    # Iterating over all possible architecture and compiler combinations.
983061da546Spatrick    configString = "arch=%s compiler=%s" % (configuration.arch,
984061da546Spatrick                                            configuration.compiler)
985061da546Spatrick
986061da546Spatrick    # Output the configuration.
987061da546Spatrick    if configuration.verbose:
988061da546Spatrick        sys.stderr.write("\nConfiguration: " + configString + "\n")
989061da546Spatrick
990061da546Spatrick    # First, write out the number of collected test cases.
991061da546Spatrick    if configuration.verbose:
992061da546Spatrick        sys.stderr.write(configuration.separator + "\n")
993061da546Spatrick        sys.stderr.write(
994061da546Spatrick            "Collected %d test%s\n\n" %
995061da546Spatrick            (configuration.suite.countTestCases(),
996061da546Spatrick             configuration.suite.countTestCases() != 1 and "s" or ""))
997061da546Spatrick
998be691f3bSpatrick    if configuration.suite.countTestCases() == 0:
999be691f3bSpatrick        logging.error("did not discover any matching tests")
1000be691f3bSpatrick        exitTestSuite(1)
1001be691f3bSpatrick
1002061da546Spatrick    # Invoke the test runner.
1003061da546Spatrick    if configuration.count == 1:
1004061da546Spatrick        result = unittest2.TextTestRunner(
1005061da546Spatrick            stream=sys.stderr,
1006061da546Spatrick            verbosity=configuration.verbose,
1007061da546Spatrick            resultclass=test_result.LLDBTestResult).run(
1008061da546Spatrick            configuration.suite)
1009061da546Spatrick    else:
1010061da546Spatrick        # We are invoking the same test suite more than once.  In this case,
1011061da546Spatrick        # mark __ignore_singleton__ flag as True so the signleton pattern is
1012061da546Spatrick        # not enforced.
1013061da546Spatrick        test_result.LLDBTestResult.__ignore_singleton__ = True
1014061da546Spatrick        for i in range(configuration.count):
1015061da546Spatrick
1016061da546Spatrick            result = unittest2.TextTestRunner(
1017061da546Spatrick                stream=sys.stderr,
1018061da546Spatrick                verbosity=configuration.verbose,
1019061da546Spatrick                resultclass=test_result.LLDBTestResult).run(
1020061da546Spatrick                configuration.suite)
1021061da546Spatrick
1022061da546Spatrick    configuration.failed = not result.wasSuccessful()
1023061da546Spatrick
1024061da546Spatrick    if configuration.sdir_has_content and configuration.verbose:
1025061da546Spatrick        sys.stderr.write(
1026061da546Spatrick            "Session logs for test failures/errors/unexpected successes"
1027be691f3bSpatrick            " can be found in the test build directory\n")
1028061da546Spatrick
1029061da546Spatrick    if configuration.use_categories and len(
1030061da546Spatrick            configuration.failures_per_category) > 0:
1031061da546Spatrick        sys.stderr.write("Failures per category:\n")
1032061da546Spatrick        for category in configuration.failures_per_category:
1033061da546Spatrick            sys.stderr.write(
1034061da546Spatrick                "%s - %d\n" %
1035061da546Spatrick                (category, configuration.failures_per_category[category]))
1036061da546Spatrick
1037061da546Spatrick    # Exiting.
1038061da546Spatrick    exitTestSuite(configuration.failed)
1039061da546Spatrick
1040061da546Spatrickif __name__ == "__main__":
1041061da546Spatrick    print(
1042061da546Spatrick        __file__ +
1043061da546Spatrick        " is for use as a module only.  It should not be run as a standalone script.")
1044061da546Spatrick    sys.exit(-1)
1045