1"""
2A simple testing framework for lldb using python's unit testing framework.
3
4Tests for lldb are written as python scripts which take advantage of the script
5bridging provided by LLDB.framework to interact with lldb core.
6
7A specific naming pattern is followed by the .py script to be recognized as
8a module which implements a test scenario, namely, Test*.py.
9
10To specify the directories where "Test*.py" python test scripts are located,
11you need to pass in a list of directory names.  By default, the current
12working directory is searched if nothing is specified on the command line.
13
14Type:
15
16./dotest.py -h
17
18for available options.
19"""
20
21from __future__ import absolute_import
22from __future__ import print_function
23
24# System modules
25import atexit
26import importlib
27import os
28import errno
29import platform
30import progress
31import signal
32import socket
33import subprocess
34import sys
35import inspect
36
37# Third-party modules
38import six
39import unittest2
40
41# LLDB Modules
42import lldbsuite
43from . import dotest_args
44from . import lldbtest_config
45from . import test_categories
46from . import test_results
47from .test_results import EventBuilder
48from ..support import seven
49
50def is_exe(fpath):
51    """Returns true if fpath is an executable."""
52    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
53
54def which(program):
55    """Returns the full path to a program; None otherwise."""
56    fpath, fname = os.path.split(program)
57    if fpath:
58        if is_exe(program):
59            return program
60    else:
61        for path in os.environ["PATH"].split(os.pathsep):
62            exe_file = os.path.join(path, program)
63            if is_exe(exe_file):
64                return exe_file
65    return None
66
67class _WritelnDecorator(object):
68    """Used to decorate file-like objects with a handy 'writeln' method"""
69    def __init__(self,stream):
70        self.stream = stream
71
72    def __getattr__(self, attr):
73        if attr in ('stream', '__getstate__'):
74            raise AttributeError(attr)
75        return getattr(self.stream,attr)
76
77    def writeln(self, arg=None):
78        if arg:
79            self.write(arg)
80        self.write('\n') # text-mode streams translate to \r\n if needed
81
82#
83# Global variables:
84#
85
86# The test suite.
87suite = unittest2.TestSuite()
88
89# By default, benchmarks tests are not run.
90just_do_benchmarks_test = False
91
92dont_do_dsym_test = False
93dont_do_dwarf_test = False
94dont_do_dwo_test = False
95
96# The blacklist is optional (-b blacklistFile) and allows a central place to skip
97# testclass's and/or testclass.testmethod's.
98blacklist = None
99
100# The dictionary as a result of sourcing blacklistFile.
101blacklistConfig = {}
102
103# The list of categories we said we care about
104categoriesList = None
105# set to true if we are going to use categories for cherry-picking test cases
106useCategories = False
107# Categories we want to skip
108skipCategories = []
109# use this to track per-category failures
110failuresPerCategory = {}
111
112# The path to LLDB.framework is optional.
113lldbFrameworkPath = None
114
115# The config file is optional.
116configFile = None
117
118# Test suite repeat count.  Can be overwritten with '-# count'.
119count = 1
120
121# The dictionary as a result of sourcing configFile.
122config = {}
123# The pre_flight and post_flight functions come from reading a config file.
124pre_flight = None
125post_flight = None
126# So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables.
127lldbtest_remote_sandbox = None
128lldbtest_remote_shell_template = None
129
130# The 'archs' and 'compilers' can be specified via either command line or configFile,
131# with the command line overriding the configFile.  The corresponding options can be
132# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
133# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
134archs = None        # Must be initialized after option parsing
135compilers = None    # Must be initialized after option parsing
136
137# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
138# the inferior programs.  The global variable cflags_extras provides a hook to do
139# just that.
140cflags_extras = ''
141
142# Dump the Python sys.path variable.  Use '-D' to dump sys.path.
143dumpSysPath = False
144
145# Full path of the benchmark executable, as specified by the '-e' option.
146bmExecutable = None
147# The breakpoint specification of bmExecutable, as specified by the '-x' option.
148bmBreakpointSpec = None
149# The benchmark iteration count, as specified by the '-y' option.
150bmIterationCount = -1
151
152# By default, don't exclude any directories.  Use '-X' to add one excluded directory.
153excluded = set(['.svn', '.git'])
154
155# By default, failfast is False.  Use '-F' to overwrite it.
156failfast = False
157
158# The filters (testclass.testmethod) used to admit tests into our test suite.
159filters = []
160
161# The runhooks is a list of lldb commands specifically for the debugger.
162# Use '-k' to specify a runhook.
163runHooks = []
164
165# If '-g' is specified, the filterspec is not exclusive.  If a test module does
166# not contain testclass.testmethod which matches the filterspec, the whole test
167# module is still admitted into our test suite.  fs4all flag defaults to True.
168fs4all = True
169
170# Ignore the build search path relative to this script to locate the lldb.py module.
171ignore = False
172
173# By default, we do not skip build and cleanup.  Use '-S' option to override.
174skip_build_and_cleanup = False
175
176# By default, we skip long running test case.  Use '-l' option to override.
177skip_long_running_test = True
178
179# By default, we print the build dir, lldb version, and svn info.  Use '-n' option to
180# turn it off.
181noHeaders = False
182
183# Parsable mode silences headers, and any other output this script might generate, and instead
184# prints machine-readable output similar to what clang tests produce.
185parsable = False
186
187# The regular expression pattern to match against eligible filenames as our test cases.
188regexp = None
189
190# By default, tests are executed in place and cleanups are performed afterwards.
191# Use '-r dir' option to relocate the tests and their intermediate files to a
192# different directory and to forgo any cleanups.  The directory specified must
193# not exist yet.
194rdir = None
195
196# By default, recorded session info for errored/failed test are dumped into its
197# own file under a session directory named after the timestamp of the test suite
198# run.  Use '-s session-dir-name' to specify a specific dir name.
199sdir_name = None
200
201# Set this flag if there is any session info dumped during the test run.
202sdir_has_content = False
203
204# svn_info stores the output from 'svn info lldb.base.dir'.
205svn_info = ''
206
207# svn_silent means do not try to obtain svn status
208svn_silent = True
209
210# Default verbosity is 0.
211verbose = 1
212
213# Set to True only if verbose is 0 and LLDB trace mode is off.
214progress_bar = False
215
216# By default, search from the script directory.
217# We can't use sys.path[0] to determine the script directory
218# because it doesn't work under a debugger
219testdirs = [ os.path.dirname(os.path.realpath(__file__)) ]
220
221# Separator string.
222separator = '-' * 70
223
224failed = False
225
226# LLDB Remote platform setting
227lldb_platform_name = None
228lldb_platform_url = None
229lldb_platform_working_dir = None
230
231# Parallel execution settings
232is_inferior_test_runner = False
233multiprocess_test_subdir = None
234num_threads = None
235output_on_success = False
236no_multiprocess_test_runner = False
237test_runner_name = None
238
239# Test results handling globals
240results_filename = None
241results_port = None
242results_file_object = None
243results_formatter_name = None
244results_formatter_object = None
245results_formatter_options = None
246
247# The names of all tests. Used to assert we don't have two tests with the same base name.
248all_tests = set()
249
250def usage(parser):
251    parser.print_help()
252    if verbose > 0:
253        print("""
254Examples:
255
256This is an example of using the -f option to pinpoint to a specific test class
257and test method to be run:
258
259$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
260----------------------------------------------------------------------
261Collected 1 test
262
263test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
264Test 'frame variable this' when stopped on a class constructor. ... ok
265
266----------------------------------------------------------------------
267Ran 1 test in 1.396s
268
269OK
270
271And this is an example of using the -p option to run a single file (the filename
272matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
273
274$ ./dotest.py -v -p ObjC
275----------------------------------------------------------------------
276Collected 4 tests
277
278test_break_with_dsym (TestObjCMethods.FoundationTestCase)
279Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
280test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
281Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
282test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
283Lookup objective-c data types and evaluate expressions. ... ok
284test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
285Lookup objective-c data types and evaluate expressions. ... ok
286
287----------------------------------------------------------------------
288Ran 4 tests in 16.661s
289
290OK
291
292Running of this script also sets up the LLDB_TEST environment variable so that
293individual test cases can locate their supporting files correctly.  The script
294tries to set up Python's search paths for modules by looking at the build tree
295relative to this script.  See also the '-i' option in the following example.
296
297Finally, this is an example of using the lldb.py module distributed/installed by
298Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
299option to add some delay between two tests.  It uses ARCH=x86_64 to specify that
300as the architecture and CC=clang to specify the compiler used for the test run:
301
302$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
303
304Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
305----------------------------------------------------------------------
306Collected 2 tests
307
308test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
309Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
310test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
311Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
312
313----------------------------------------------------------------------
314Ran 2 tests in 5.659s
315
316OK
317
318The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
319notify the directory containing the session logs for test failures or errors.
320In case there is any test failure/error, a similar message is appended at the
321end of the stderr output for your convenience.
322
323ENABLING LOGS FROM TESTS
324
325Option 1:
326
327Writing logs into different files per test case::
328
329This option is particularly useful when multiple dotest instances are created
330by dosep.py
331
332$ ./dotest.py --channel "lldb all"
333
334$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets"
335
336These log files are written to:
337
338<session-dir>/<test-id>-host.log (logs from lldb host process)
339<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server)
340<session-dir>/<test-id>-<test-result>.log (console logs)
341
342By default, logs from successful runs are deleted.  Use the --log-success flag
343to create reference logs for debugging.
344
345$ ./dotest.py --log-success
346
347Option 2: (DEPRECATED)
348
349The following options can only enable logs from the host lldb process.
350Only categories from the "lldb" or "gdb-remote" channels can be enabled
351They also do not automatically enable logs in locally running debug servers.
352Also, logs from all test case are written into each log file
353
354o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
355  with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
356
357o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
358  'process.gdb-remote' subsystem with a default option of 'packets' if
359  GDB_REMOTE_LOG_OPTION is not defined.
360
361""")
362    sys.exit(0)
363
364
365def setCrashInfoHook_Mac(text):
366    from . import crashinfo
367    crashinfo.setCrashReporterDescription(text)
368
369# implement this in some suitable way for your platform, and then bind it
370# to setCrashInfoHook
371def setCrashInfoHook_NonMac(text):
372    pass
373
374setCrashInfoHook = None
375
376def deleteCrashInfoDylib(dylib_path):
377    try:
378        # Need to modify this to handle multiple tests running at the same time.  If we move this
379        # to the test's real dir, all should be we run sequentially within a test directory.
380        # os.remove(dylib_path)
381        None
382    finally:
383        pass
384
385def setupCrashInfoHook():
386    global setCrashInfoHook
387    setCrashInfoHook = setCrashInfoHook_NonMac # safe default
388    if platform.system() == "Darwin":
389        from . import lock
390        test_dir = os.environ['LLDB_TEST']
391        if not test_dir or not os.path.exists(test_dir):
392            return
393        dylib_lock = os.path.join(test_dir,"crashinfo.lock")
394        dylib_src = os.path.join(test_dir,"crashinfo.c")
395        dylib_dst = os.path.join(test_dir,"crashinfo.so")
396        try:
397            compile_lock = lock.Lock(dylib_lock)
398            compile_lock.acquire()
399            if not os.path.isfile(dylib_dst) or os.path.getmtime(dylib_dst) < os.path.getmtime(dylib_src):
400                # we need to compile
401                cmd = "SDKROOT= xcrun clang %s -o %s -framework Python -Xlinker -dylib -iframework /System/Library/Frameworks/ -Xlinker -F /System/Library/Frameworks/" % (dylib_src,dylib_dst)
402                if subprocess.call(cmd,shell=True) != 0 or not os.path.isfile(dylib_dst):
403                    raise Exception('command failed: "{}"'.format(cmd))
404        finally:
405            compile_lock.release()
406            del compile_lock
407
408        setCrashInfoHook = setCrashInfoHook_Mac
409
410    else:
411        pass
412
413def shouldSkipBecauseOfCategories(test_categories):
414    global useCategories, categoriesList, skipCategories
415
416    if useCategories:
417        if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
418            return True
419
420    for category in skipCategories:
421        if category in test_categories:
422            return True
423
424    return False
425
426def parseOptionsAndInitTestdirs():
427    """Initialize the list of directories containing our unittest scripts.
428
429    '-h/--help as the first option prints out usage info and exit the program.
430    """
431
432    global just_do_benchmarks_test
433    global dont_do_dsym_test
434    global dont_do_dwarf_test
435    global dont_do_dwo_test
436    global blacklist
437    global blacklistConfig
438    global categoriesList
439    global validCategories
440    global useCategories
441    global skipCategories
442    global lldbFrameworkPath
443    global configFile
444    global archs
445    global compilers
446    global count
447    global dumpSysPath
448    global bmExecutable
449    global bmBreakpointSpec
450    global bmIterationCount
451    global failfast
452    global filters
453    global fs4all
454    global ignore
455    global progress_bar
456    global runHooks
457    global skip_build_and_cleanup
458    global skip_long_running_test
459    global noHeaders
460    global parsable
461    global regexp
462    global rdir
463    global sdir_name
464    global svn_silent
465    global verbose
466    global testdirs
467    global lldb_platform_name
468    global lldb_platform_url
469    global lldb_platform_working_dir
470    global setCrashInfoHook
471    global is_inferior_test_runner
472    global multiprocess_test_subdir
473    global num_threads
474    global output_on_success
475    global no_multiprocess_test_runner
476    global test_runner_name
477    global results_filename
478    global results_formatter_name
479    global results_formatter_options
480    global results_port
481
482    do_help = False
483
484    platform_system = platform.system()
485    platform_machine = platform.machine()
486
487    parser = dotest_args.create_parser()
488    args = dotest_args.parse_args(parser, sys.argv[1:])
489
490    if args.unset_env_varnames:
491        for env_var in args.unset_env_varnames:
492            if env_var in os.environ:
493                # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
494                # is automatically translated into a corresponding call to unsetenv().
495                del os.environ[env_var]
496                #os.unsetenv(env_var)
497
498    if args.set_env_vars:
499        for env_var in args.set_env_vars:
500            parts = env_var.split('=', 1)
501            if len(parts) == 1:
502                os.environ[parts[0]] = ""
503            else:
504                os.environ[parts[0]] = parts[1]
505
506    # only print the args if being verbose (and parsable is off)
507    if args.v and not args.q:
508        print(sys.argv)
509
510    if args.h:
511        do_help = True
512
513    if args.compilers:
514        compilers = args.compilers
515    else:
516        # Use a compiler appropriate appropriate for the Apple SDK if one was specified
517        if platform_system == 'Darwin' and args.apple_sdk:
518            compilers = [seven.get_command_output('xcrun -sdk "%s" -find clang 2> /dev/null' % (args.apple_sdk))]
519        else:
520            # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first
521            candidateCompilers = ['clang-3.5', 'clang', 'gcc']
522            for candidate in candidateCompilers:
523                if which(candidate):
524                    compilers = [candidate]
525                    break
526
527    if args.channels:
528        lldbtest_config.channels = args.channels
529
530    if args.log_success:
531        lldbtest_config.log_success = args.log_success
532
533    # Set SDKROOT if we are using an Apple SDK
534    if platform_system == 'Darwin' and args.apple_sdk:
535        os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk "%s" --show-sdk-path 2> /dev/null' % (args.apple_sdk))
536
537    if args.archs:
538        archs = args.archs
539        for arch in archs:
540            if arch.startswith('arm') and platform_system == 'Darwin' and not args.apple_sdk:
541                os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos.internal --show-sdk-path 2> /dev/null')
542                if not os.path.exists(os.environ['SDKROOT']):
543                    os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos --show-sdk-path 2> /dev/null')
544    else:
545        archs = [platform_machine]
546
547    if args.categoriesList:
548        categoriesList = set(test_categories.validate(args.categoriesList, False))
549        useCategories = True
550    else:
551        categoriesList = []
552
553    if args.skipCategories:
554        skipCategories = test_categories.validate(args.skipCategories, False)
555
556    if args.D:
557        dumpSysPath = True
558
559    if args.E:
560        cflags_extras = args.E
561        os.environ['CFLAGS_EXTRAS'] = cflags_extras
562
563    # argparse makes sure we have correct options
564    if args.N == 'dwarf':
565        dont_do_dwarf_test = True
566    elif args.N == 'dwo':
567        dont_do_dwo_test = True
568    elif args.N == 'dsym':
569        dont_do_dsym_test = True
570
571    if args.a or args.plus_a:
572        print("Options '-a' and '+a' have been deprecated. Please use the test category\n"
573              "functionality (-G pyapi, --skip-category pyapi) instead.")
574        sys.exit(1)
575
576    if args.m or args.plus_m:
577        print("Options '-m' and '+m' have been deprecated. Please use the test category\n"
578              "functionality (-G lldb-mi, --skip-category lldb-mi) instead.")
579        sys.exit(1)
580
581    if args.plus_b:
582        just_do_benchmarks_test = True
583
584    if args.b:
585        if args.b.startswith('-'):
586            usage(parser)
587        blacklistFile = args.b
588        if not os.path.isfile(blacklistFile):
589            print('Blacklist file:', blacklistFile, 'does not exist!')
590            usage(parser)
591        # Now read the blacklist contents and assign it to blacklist.
592        execfile(blacklistFile, globals(), blacklistConfig)
593        blacklist = blacklistConfig.get('blacklist')
594
595    if args.c:
596        if args.c.startswith('-'):
597            usage(parser)
598        configFile = args.c
599        if not os.path.isfile(configFile):
600            print('Config file:', configFile, 'does not exist!')
601            usage(parser)
602
603    if args.d:
604        sys.stdout.write("Suspending the process %d to wait for debugger to attach...\n" % os.getpid())
605        sys.stdout.flush()
606        os.kill(os.getpid(), signal.SIGSTOP)
607
608    if args.e:
609        if args.e.startswith('-'):
610            usage(parser)
611        bmExecutable = args.e
612        if not is_exe(bmExecutable):
613            usage(parser)
614
615    if args.F:
616        failfast = True
617
618    if args.f:
619        if any([x.startswith('-') for x in args.f]):
620            usage(parser)
621        filters.extend(args.f)
622        # Shut off multiprocessing mode when additional filters are specified.
623        # The rational is that the user is probably going after a very specific
624        # test and doesn't need a bunch of parallel test runners all looking for
625        # it in a frenzy.  Also, '-v' now spits out all test run output even
626        # on success, so the standard recipe for redoing a failing test (with -v
627        # and a -f to filter to the specific test) now causes all test scanning
628        # (in parallel) to print results for do-nothing runs in a very distracting
629        # manner.  If we really need filtered parallel runs in the future, consider
630        # adding a --no-output-on-success that prevents -v from setting
631        # output-on-success.
632        no_multiprocess_test_runner = True
633
634    if args.g:
635        fs4all = False
636
637    if args.i:
638        ignore = True
639
640    if args.k:
641        runHooks.extend(args.k)
642
643    if args.l:
644        skip_long_running_test = False
645
646    if args.framework:
647        lldbFrameworkPath = args.framework
648
649    if args.executable:
650        lldbtest_config.lldbExec = args.executable
651
652    if args.libcxx:
653        os.environ["LIBCXX_PATH"] = args.libcxx
654
655    if args.n:
656        noHeaders = True
657
658    if args.p:
659        if args.p.startswith('-'):
660            usage(parser)
661        regexp = args.p
662
663    if args.q:
664        noHeaders = True
665        parsable = True
666
667    if args.P and not args.v:
668        progress_bar = True
669        verbose = 0
670
671    if args.R:
672        if args.R.startswith('-'):
673            usage(parser)
674        rdir = os.path.abspath(args.R)
675        if os.path.exists(rdir):
676            import shutil
677            print('Removing tree:', rdir)
678            shutil.rmtree(rdir)
679
680    if args.r:
681        if args.r.startswith('-'):
682            usage(parser)
683        rdir = os.path.abspath(args.r)
684        if os.path.exists(rdir):
685            print('Relocated directory:', rdir, 'must not exist!')
686            usage(parser)
687
688    if args.S:
689        skip_build_and_cleanup = True
690
691    if args.s:
692        if args.s.startswith('-'):
693            usage(parser)
694        sdir_name = args.s
695
696    if args.t:
697        os.environ['LLDB_COMMAND_TRACE'] = 'YES'
698
699    if args.T:
700        svn_silent = False
701
702    if args.v:
703        verbose = 2
704
705    if args.w:
706        os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
707
708    if args.X:
709        if args.X.startswith('-'):
710            usage(parser)
711        excluded.add(args.X)
712
713    if args.x:
714        if args.x.startswith('-'):
715            usage(parser)
716        bmBreakpointSpec = args.x
717
718    # argparse makes sure we have a number
719    if args.y:
720        bmIterationCount = args.y
721
722    # argparse makes sure we have a number
723    if args.sharp:
724        count = args.sharp
725
726    if sys.platform.startswith('win32'):
727        os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(args.disable_crash_dialog)
728        os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(args.hide_inferior_console)
729
730    if do_help == True:
731        usage(parser)
732
733    if args.no_multiprocess:
734        no_multiprocess_test_runner = True
735
736    if args.inferior:
737        is_inferior_test_runner = True
738
739    # Turn on output_on_sucess if either explicitly added or -v specified.
740    if args.output_on_success or args.v:
741        output_on_success = True
742
743    if args.num_threads:
744        num_threads = args.num_threads
745
746    if args.test_subdir:
747        multiprocess_test_subdir = args.test_subdir
748
749    if args.test_runner_name:
750        test_runner_name = args.test_runner_name
751
752    # Capture test results-related args.
753    if args.curses and not args.inferior:
754        # Act as if the following args were set.
755        args.results_formatter = "lldbsuite.test.curses_results.Curses"
756        args.results_file = "stdout"
757
758    if args.results_file:
759        results_filename = args.results_file
760
761    if args.results_port:
762        results_port = args.results_port
763
764    if args.results_file and args.results_port:
765        sys.stderr.write(
766            "only one of --results-file and --results-port should "
767            "be specified\n")
768        usage(args)
769
770    if args.results_formatter:
771        results_formatter_name = args.results_formatter
772    if args.results_formatter_options:
773        results_formatter_options = args.results_formatter_options
774
775    if args.lldb_platform_name:
776        lldb_platform_name = args.lldb_platform_name
777    if args.lldb_platform_url:
778        lldb_platform_url = args.lldb_platform_url
779    if args.lldb_platform_working_dir:
780        lldb_platform_working_dir = args.lldb_platform_working_dir
781
782    if args.event_add_entries and len(args.event_add_entries) > 0:
783        entries = {}
784        # Parse out key=val pairs, separated by comma
785        for keyval in args.event_add_entries.split(","):
786            key_val_entry = keyval.split("=")
787            if len(key_val_entry) == 2:
788                (key, val) = key_val_entry
789                val_parts = val.split(':')
790                if len(val_parts) > 1:
791                    (val, val_type) = val_parts
792                    if val_type == 'int':
793                        val = int(val)
794                entries[key] = val
795        # Tell the event builder to create all events with these
796        # key/val pairs in them.
797        if len(entries) > 0:
798            test_results.EventBuilder.add_entries_to_all_events(entries)
799
800    # Gather all the dirs passed on the command line.
801    if len(args.args) > 0:
802        testdirs = list(map(os.path.abspath, args.args))
803        # Shut off multiprocessing mode when test directories are specified.
804        no_multiprocess_test_runner = True
805
806    # If '-r dir' is specified, the tests should be run under the relocated
807    # directory.  Let's copy the testdirs over.
808    if rdir:
809        from shutil import copytree, ignore_patterns
810
811        tmpdirs = []
812        orig_testdirs = testdirs[:]
813        for srcdir in testdirs:
814            # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
815            # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
816            # Utilize the relative path to the 'test' directory to make our destination dir path.
817            if ("test" + os.sep) in srcdir:
818                to_split_on = "test" + os.sep
819            else:
820                to_split_on = "test"
821            dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
822            dstdir = dstdir.rstrip(os.sep)
823            # Don't copy the *.pyc and .svn stuffs.
824            copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
825            tmpdirs.append(dstdir)
826
827        # This will be our modified testdirs.
828        testdirs = tmpdirs
829
830        # With '-r dir' specified, there's no cleanup of intermediate test files.
831        os.environ["LLDB_DO_CLEANUP"] = 'NO'
832
833        # If the original testdirs is ['test'], the make directory has already been copied
834        # recursively and is contained within the rdir/test dir.  For anything
835        # else, we would need to copy over the make directory and its contents,
836        # so that, os.listdir(rdir) looks like, for example:
837        #
838        #     array_types conditional_break make
839        #
840        # where the make directory contains the Makefile.rules file.
841        if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
842            scriptdir = os.path.dirname(__file__)
843            # Don't copy the .svn stuffs.
844            copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
845                     ignore=ignore_patterns('.svn'))
846
847    #print("testdirs:", testdirs)
848
849    # Source the configFile if specified.
850    # The side effect, if any, will be felt from this point on.  An example
851    # config file may be these simple two lines:
852    #
853    # sys.stderr = open("/tmp/lldbtest-stderr", "w")
854    # sys.stdout = open("/tmp/lldbtest-stdout", "w")
855    #
856    # which will reassign the two file objects to sys.stderr and sys.stdout,
857    # respectively.
858    #
859    # See also lldb-trunk/examples/test/usage-config.
860    global config, pre_flight, post_flight, lldbtest_remote_sandbox, lldbtest_remote_shell_template
861    if configFile:
862        # Pass config (a dictionary) as the locals namespace for side-effect.
863        execfile(configFile, globals(), config)
864        #print("config:", config)
865        if "pre_flight" in config:
866            pre_flight = config["pre_flight"]
867            if not six.callable(pre_flight):
868                print("fatal error: pre_flight is not callable, exiting.")
869                sys.exit(1)
870        if "post_flight" in config:
871            post_flight = config["post_flight"]
872            if not six.callable(post_flight):
873                print("fatal error: post_flight is not callable, exiting.")
874                sys.exit(1)
875        if "lldbtest_remote_sandbox" in config:
876            lldbtest_remote_sandbox = config["lldbtest_remote_sandbox"]
877        if "lldbtest_remote_shell_template" in config:
878            lldbtest_remote_shell_template = config["lldbtest_remote_shell_template"]
879        #print("sys.stderr:", sys.stderr)
880        #print("sys.stdout:", sys.stdout)
881
882def getXcodeOutputPaths(lldbRootDirectory):
883    result = []
884
885    # These are for xcode build directories.
886    xcode3_build_dir = ['build']
887    xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
888
889    configurations = [['Debug'], ['DebugClang'], ['Release'], ['BuildAndIntegration']]
890    xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir]
891    for configuration in configurations:
892        for xcode_build_dir in xcode_build_dirs:
893            outputPath = os.path.join(lldbRootDirectory, *(xcode_build_dir+configuration) )
894            result.append(outputPath)
895
896    return result
897
898
899def createSocketToLocalPort(port):
900    def socket_closer(s):
901        """Close down an opened socket properly."""
902        s.shutdown(socket.SHUT_RDWR)
903        s.close()
904
905    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
906    sock.connect(("localhost", port))
907    return (sock, lambda: socket_closer(sock))
908
909
910def setupTestResults():
911    """Sets up test results-related objects based on arg settings."""
912    global results_filename
913    global results_file_object
914    global results_formatter_name
915    global results_formatter_object
916    global results_formatter_options
917    global results_port
918
919    default_formatter_name = None
920    cleanup_func = None
921
922    if results_filename:
923        # Open the results file for writing.
924        if results_filename == 'stdout':
925            results_file_object = sys.stdout
926            cleanup_func = None
927        elif results_filename == 'stderr':
928            results_file_object = sys.stderr
929            cleanup_func = None
930        else:
931            results_file_object = open(results_filename, "w")
932            cleanup_func = results_file_object.close
933        default_formatter_name = "lldbsuite.test.test_results.XunitFormatter"
934    elif results_port:
935        # Connect to the specified localhost port.
936        results_file_object, cleanup_func = createSocketToLocalPort(
937            results_port)
938        default_formatter_name = (
939            "lldbsuite.test.test_results.RawPickledFormatter")
940
941    # If we have a results formatter name specified and we didn't specify
942    # a results file, we should use stdout.
943    if results_formatter_name is not None and results_file_object is None:
944        # Use stdout.
945        results_file_object = sys.stdout
946        cleanup_func = None
947
948    if results_file_object:
949        # We care about the formatter.  Choose user-specified or, if
950        # none specified, use the default for the output type.
951        if results_formatter_name:
952            formatter_name = results_formatter_name
953        else:
954            formatter_name = default_formatter_name
955
956        # Create an instance of the class.
957        # First figure out the package/module.
958        components = formatter_name.split(".")
959        module = importlib.import_module(".".join(components[:-1]))
960
961        # Create the class name we need to load.
962        clazz = getattr(module, components[-1])
963
964        # Handle formatter options for the results formatter class.
965        formatter_arg_parser = clazz.arg_parser()
966        if results_formatter_options and len(results_formatter_options) > 0:
967            command_line_options = results_formatter_options
968        else:
969            command_line_options = []
970
971        formatter_options = formatter_arg_parser.parse_args(
972            command_line_options)
973
974        # Create the TestResultsFormatter given the processed options.
975        results_formatter_object = clazz(
976            results_file_object, formatter_options)
977
978        # Start the results formatter session - we'll only have one
979        # during a given dotest process invocation.
980        initialize_event = EventBuilder.bare_event("initialize")
981        if isMultiprocessTestRunner():
982            if test_runner_name is not None and test_runner_name == "serial":
983                # Only one worker queue here.
984                worker_count = 1
985            else:
986                # Workers will be the number of threads specified.
987                worker_count = num_threads
988        else:
989            worker_count = 1
990        initialize_event["worker_count"] = worker_count
991
992        results_formatter_object.handle_event(initialize_event)
993
994        def shutdown_formatter():
995            # Tell the formatter to write out anything it may have
996            # been saving until the very end (e.g. xUnit results
997            # can't complete its output until this point).
998            results_formatter_object.send_terminate_as_needed()
999
1000            # And now close out the output file-like object.
1001            if cleanup_func is not None:
1002                cleanup_func()
1003
1004        atexit.register(shutdown_formatter)
1005
1006
1007def getOutputPaths(lldbRootDirectory):
1008    """
1009    Returns typical build output paths for the lldb executable
1010
1011    lldbDirectory - path to the root of the lldb svn/git repo
1012    """
1013    result = []
1014
1015    if sys.platform == 'darwin':
1016        result.extend(getXcodeOutputPaths(lldbRootDirectory))
1017
1018    # cmake builds?  look for build or build/host folder next to llvm directory
1019    # lldb is located in llvm/tools/lldb so we need to go up three levels
1020    llvmParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir, os.pardir, os.pardir))
1021    result.append(os.path.join(llvmParentDir, 'build', 'bin'))
1022    result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin'))
1023
1024    # some cmake developers keep their build directory beside their lldb directory
1025    lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir))
1026    result.append(os.path.join(lldbParentDir, 'build', 'bin'))
1027    result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin'))
1028
1029    return result
1030
1031def setupSysPath():
1032    """
1033    Add LLDB.framework/Resources/Python to the search paths for modules.
1034    As a side effect, we also discover the 'lldb' executable and export it here.
1035    """
1036
1037    global rdir
1038    global testdirs
1039    global dumpSysPath
1040    global noHeaders
1041    global svn_info
1042    global svn_silent
1043    global lldbFrameworkPath
1044
1045    # Get the directory containing the current script.
1046    if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
1047        scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
1048    else:
1049        scriptPath = os.path.dirname(os.path.realpath(__file__))
1050    if not scriptPath.endswith('test'):
1051        print("This script expects to reside in lldb's test directory.")
1052        sys.exit(-1)
1053
1054    if rdir:
1055        # Set up the LLDB_TEST environment variable appropriately, so that the
1056        # individual tests can be located relatively.
1057        #
1058        # See also lldbtest.TestBase.setUpClass(cls).
1059        if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1060            os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
1061        else:
1062            os.environ["LLDB_TEST"] = rdir
1063    else:
1064        os.environ["LLDB_TEST"] = scriptPath
1065
1066    # Set up the LLDB_SRC environment variable, so that the tests can locate
1067    # the LLDB source code.
1068    os.environ["LLDB_SRC"] = lldbsuite.lldb_root
1069
1070    pluginPath = os.path.join(scriptPath, 'plugins')
1071    toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi')
1072    toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
1073
1074    # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the sys.path.
1075    sys.path.insert(0, pluginPath)
1076    sys.path.insert(0, toolsLLDBMIPath)      # Adding test/tools/lldb-mi to the path makes it easy
1077                                             # to "import lldbmi_testcase" from the MI tests
1078    sys.path.insert(0, toolsLLDBServerPath)  # Adding test/tools/lldb-server to the path makes it easy
1079                                             # to "import lldbgdbserverutils" from the lldb-server tests
1080
1081    # This is the root of the lldb git/svn checkout
1082    # When this changes over to a package instead of a standalone script, this
1083    # will be `lldbsuite.lldb_root`
1084    lldbRootDirectory = lldbsuite.lldb_root
1085
1086    # Some of the tests can invoke the 'lldb' command directly.
1087    # We'll try to locate the appropriate executable right here.
1088
1089    # The lldb executable can be set from the command line
1090    # if it's not set, we try to find it now
1091    # first, we try the environment
1092    if not lldbtest_config.lldbExec:
1093        # First, you can define an environment variable LLDB_EXEC specifying the
1094        # full pathname of the lldb executable.
1095        if "LLDB_EXEC" in os.environ:
1096            lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]
1097
1098    if not lldbtest_config.lldbExec:
1099        outputPaths = getOutputPaths(lldbRootDirectory)
1100        for outputPath in outputPaths:
1101            candidatePath = os.path.join(outputPath, 'lldb')
1102            if is_exe(candidatePath):
1103                lldbtest_config.lldbExec = candidatePath
1104                break
1105
1106    if not lldbtest_config.lldbExec:
1107        # Last, check the path
1108        lldbtest_config.lldbExec = which('lldb')
1109
1110    if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
1111        print("'{}' is not a path to a valid executable".format(lldbtest_config.lldbExec))
1112        lldbtest_config.lldbExec = None
1113
1114    if not lldbtest_config.lldbExec:
1115        print("The 'lldb' executable cannot be located.  Some of the tests may not be run as a result.")
1116        sys.exit(-1)
1117
1118    lldbLibDir = os.path.dirname(lldbtest_config.lldbExec)  # confusingly, this is the "bin" directory
1119    os.environ["LLDB_LIB_DIR"] = lldbLibDir
1120    lldbImpLibDir = os.path.join(lldbLibDir, '..', 'lib') if sys.platform.startswith('win32') else lldbLibDir
1121    os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir
1122    if not noHeaders:
1123        print("LLDB library dir:", os.environ["LLDB_LIB_DIR"])
1124        print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"])
1125        os.system('%s -v' % lldbtest_config.lldbExec)
1126
1127    # Assume lldb-mi is in same place as lldb
1128    # If not found, disable the lldb-mi tests
1129    lldbMiExec = None
1130    if lldbtest_config.lldbExec and is_exe(lldbtest_config.lldbExec + "-mi"):
1131        lldbMiExec = lldbtest_config.lldbExec + "-mi"
1132    if not lldbMiExec:
1133        if not shouldSkipBecauseOfCategories(["lldb-mi"]):
1134            print("The 'lldb-mi' executable cannot be located.  The lldb-mi tests can not be run as a result.")
1135            skipCategories.append("lldb-mi")
1136    else:
1137        os.environ["LLDBMI_EXEC"] = lldbMiExec
1138
1139    # Skip printing svn/git information when running in parsable (lit-test compatibility) mode
1140    if not svn_silent and not parsable:
1141        if os.path.isdir(os.path.join(lldbRootDirectory, '.svn')) and which("svn") is not None:
1142            pipe = subprocess.Popen([which("svn"), "info", lldbRootDirectory], stdout = subprocess.PIPE)
1143            svn_info = pipe.stdout.read()
1144        elif os.path.isdir(os.path.join(lldbRootDirectory, '.git')) and which("git") is not None:
1145            pipe = subprocess.Popen([which("git"), "svn", "info", lldbRootDirectory], stdout = subprocess.PIPE)
1146            svn_info = pipe.stdout.read()
1147        if not noHeaders:
1148            print(svn_info)
1149
1150    global ignore
1151
1152    lldbPythonDir = None # The directory that contains 'lldb/__init__.py'
1153    if lldbFrameworkPath:
1154        candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
1155        if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
1156            lldbPythonDir = candidatePath
1157        if not lldbPythonDir:
1158            print('Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath)
1159            sys.exit(-1)
1160    else:
1161        # The '-i' option is used to skip looking for lldb.py in the build tree.
1162        if ignore:
1163            return
1164
1165        # If our lldb supports the -P option, use it to find the python path:
1166        init_in_python_dir = os.path.join('lldb', '__init__.py')
1167
1168        lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True)
1169
1170        if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")) \
1171							  and not lldb_dash_p_result.startswith("Traceback"):
1172            lines = lldb_dash_p_result.splitlines()
1173
1174            # Workaround for readline vs libedit issue on FreeBSD.  If stdout
1175            # is not a terminal Python executes
1176            #     rl_variable_bind ("enable-meta-key", "off");
1177            # This produces a warning with FreeBSD's libedit because the
1178            # enable-meta-key variable is unknown.  Not an issue on Apple
1179            # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__
1180            # around the call.  See http://bugs.python.org/issue19884 for more
1181            # information.  For now we just discard the warning output.
1182            if len(lines) >= 1 and lines[0].startswith("bind: Invalid command"):
1183                lines.pop(0)
1184
1185            # Taking the last line because lldb outputs
1186            # 'Cannot read termcap database;\nusing dumb terminal settings.\n'
1187            # before the path
1188            if len(lines) >= 1 and os.path.isfile(os.path.join(lines[-1], init_in_python_dir)):
1189                lldbPythonDir = lines[-1]
1190                if "freebsd" in sys.platform or "linux" in sys.platform:
1191                    os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..')
1192
1193        if not lldbPythonDir:
1194            if platform.system() == "Darwin":
1195                python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
1196                outputPaths = getXcodeOutputPaths()
1197                for outputPath in outputPaths:
1198                    candidatePath = os.path.join(outputPath, python_resource_dir)
1199                    if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)):
1200                        lldbPythonDir = candidatePath
1201                        break
1202
1203                if not lldbPythonDir:
1204                    print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ')
1205                    print(relPath + ', or ' + baiPath + '. Some tests might fail.')
1206            else:
1207                print("Unable to load lldb extension module.  Possible reasons for this include:")
1208                print("  1) LLDB was built with LLDB_DISABLE_PYTHON=1")
1209                print("  2) PYTHONPATH and PYTHONHOME are not set correctly.  PYTHONHOME should refer to")
1210                print("     the version of Python that LLDB built and linked against, and PYTHONPATH")
1211                print("     should contain the Lib directory for the same python distro, as well as the")
1212                print("     location of LLDB\'s site-packages folder.")
1213                print("  3) A different version of Python than that which was built against is exported in")
1214                print("     the system\'s PATH environment variable, causing conflicts.")
1215                print("  4) The executable '%s' could not be found.  Please check " % lldbExecutable)
1216                print("     that it exists and is executable.")
1217
1218    if lldbPythonDir:
1219        lldbPythonDir = os.path.normpath(lldbPythonDir)
1220        # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
1221        # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
1222        (before, frameWithVersion, after) = lldbPythonDir.rpartition("LLDB.framework/Versions/A")
1223        if frameWithVersion != "" :
1224            lldbPythonDir = before + "LLDB.framework" + after
1225
1226        lldbPythonDir = os.path.abspath(lldbPythonDir)
1227
1228        # If tests need to find LLDB_FRAMEWORK, now they can do it
1229        os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPythonDir))
1230
1231        # This is to locate the lldb.py module.  Insert it right after sys.path[0].
1232        sys.path[1:1] = [lldbPythonDir]
1233        if dumpSysPath:
1234            print("sys.path:", sys.path)
1235
1236def visit(prefix, dir, names):
1237    """Visitor function for os.path.walk(path, visit, arg)."""
1238
1239    global suite
1240    global regexp
1241    global filters
1242    global fs4all
1243    global excluded
1244    global all_tests
1245
1246    if set(dir.split(os.sep)).intersection(excluded):
1247        #print("Detected an excluded dir component: %s" % dir)
1248        return
1249
1250    for name in names:
1251        if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
1252
1253            if name in all_tests:
1254                raise Exception("Found multiple tests with the name %s" % name)
1255            all_tests.add(name)
1256
1257            # Try to match the regexp pattern, if specified.
1258            if regexp:
1259                import re
1260                if re.search(regexp, name):
1261                    #print("Filename: '%s' matches pattern: '%s'" % (name, regexp))
1262                    pass
1263                else:
1264                    #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp))
1265                    continue
1266
1267            # We found a match for our test.  Add it to the suite.
1268
1269            # Update the sys.path first.
1270            if not sys.path.count(dir):
1271                sys.path.insert(0, dir)
1272            base = os.path.splitext(name)[0]
1273
1274            # Thoroughly check the filterspec against the base module and admit
1275            # the (base, filterspec) combination only when it makes sense.
1276            filterspec = None
1277            for filterspec in filters:
1278                # Optimistically set the flag to True.
1279                filtered = True
1280                module = __import__(base)
1281                parts = filterspec.split('.')
1282                obj = module
1283                for part in parts:
1284                    try:
1285                        parent, obj = obj, getattr(obj, part)
1286                    except AttributeError:
1287                        # The filterspec has failed.
1288                        filtered = False
1289                        break
1290
1291                # If filtered, we have a good filterspec.  Add it.
1292                if filtered:
1293                    #print("adding filter spec %s to module %s" % (filterspec, module))
1294                    suite.addTests(
1295                        unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
1296                    continue
1297
1298            # Forgo this module if the (base, filterspec) combo is invalid
1299            # and no '-g' option is specified
1300            if filters and fs4all and not filtered:
1301                continue
1302
1303            # Add either the filtered test case(s) (which is done before) or the entire test class.
1304            if not filterspec or not filtered:
1305                # A simple case of just the module name.  Also the failover case
1306                # from the filterspec branch when the (base, filterspec) combo
1307                # doesn't make sense.
1308                suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
1309
1310
1311def disabledynamics():
1312    import lldb
1313    ci = lldb.DBG.GetCommandInterpreter()
1314    res = lldb.SBCommandReturnObject()
1315    ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False)
1316    if not res.Succeeded():
1317        raise Exception('disabling dynamic type support failed')
1318
1319def lldbLoggings():
1320    import lldb
1321    """Check and do lldb loggings if necessary."""
1322
1323    # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1324    # defined.  Use ${LLDB_LOG} to specify the log file.
1325    ci = lldb.DBG.GetCommandInterpreter()
1326    res = lldb.SBCommandReturnObject()
1327    if ("LLDB_LOG" in os.environ):
1328        open(os.environ["LLDB_LOG"], 'w').close()
1329        if ("LLDB_LOG_OPTION" in os.environ):
1330            lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1331        else:
1332            lldb_log_option = "event process expr state api"
1333        ci.HandleCommand(
1334            "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
1335            res)
1336        if not res.Succeeded():
1337            raise Exception('log enable failed (check LLDB_LOG env variable)')
1338
1339    if ("LLDB_LINUX_LOG" in os.environ):
1340        open(os.environ["LLDB_LINUX_LOG"], 'w').close()
1341        if ("LLDB_LINUX_LOG_OPTION" in os.environ):
1342            lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"]
1343        else:
1344            lldb_log_option = "event process expr state api"
1345        ci.HandleCommand(
1346            "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option,
1347            res)
1348        if not res.Succeeded():
1349            raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)')
1350
1351    # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1352    # Use ${GDB_REMOTE_LOG} to specify the log file.
1353    if ("GDB_REMOTE_LOG" in os.environ):
1354        if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1355            gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1356        else:
1357            gdb_remote_log_option = "packets process"
1358        ci.HandleCommand(
1359            "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
1360            + gdb_remote_log_option,
1361            res)
1362        if not res.Succeeded():
1363            raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)')
1364
1365def getMyCommandLine():
1366    return ' '.join(sys.argv)
1367
1368# ======================================== #
1369#                                          #
1370# Execution of the test driver starts here #
1371#                                          #
1372# ======================================== #
1373
1374def checkDsymForUUIDIsNotOn():
1375    cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1376    pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1377    cmd_output = pipe.stdout.read()
1378    if cmd_output and "DBGFileMappedPaths = " in cmd_output:
1379        print("%s =>" % ' '.join(cmd))
1380        print(cmd_output)
1381        print("Disable automatic lookup and caching of dSYMs before running the test suite!")
1382        print("Exiting...")
1383        sys.exit(0)
1384
1385def exitTestSuite(exitCode = None):
1386    import lldb
1387    lldb.SBDebugger.Terminate()
1388    if exitCode:
1389        sys.exit(exitCode)
1390
1391
1392def isMultiprocessTestRunner():
1393    # We're not multiprocess when we're either explicitly
1394    # the inferior (as specified by the multiprocess test
1395    # runner) OR we've been told to skip using the multiprocess
1396    # test runner
1397    return not (is_inferior_test_runner or no_multiprocess_test_runner)
1398
1399def getVersionForSDK(sdk):
1400    sdk = str.lower(sdk)
1401    full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1402    basename = os.path.basename(full_path)
1403    basename = os.path.splitext(basename)[0]
1404    basename = str.lower(basename)
1405    ver = basename.replace(sdk, '')
1406    return ver
1407
1408def getPathForSDK(sdk):
1409    sdk = str.lower(sdk)
1410    full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1411    if os.path.exists(full_path): return full_path
1412    return None
1413
1414def setDefaultTripleForPlatform():
1415    if lldb_platform_name == 'ios-simulator':
1416        triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator'))
1417        os.environ['TRIPLE'] = triple_str
1418        return {'TRIPLE':triple_str}
1419    return {}
1420
1421def run_suite():
1422    global just_do_benchmarks_test
1423    global dont_do_dsym_test
1424    global dont_do_dwarf_test
1425    global dont_do_dwo_test
1426    global blacklist
1427    global blacklistConfig
1428    global categoriesList
1429    global validCategories
1430    global useCategories
1431    global skipCategories
1432    global lldbFrameworkPath
1433    global configFile
1434    global archs
1435    global compilers
1436    global count
1437    global dumpSysPath
1438    global bmExecutable
1439    global bmBreakpointSpec
1440    global bmIterationCount
1441    global failed
1442    global failfast
1443    global filters
1444    global fs4all
1445    global ignore
1446    global progress_bar
1447    global runHooks
1448    global skip_build_and_cleanup
1449    global skip_long_running_test
1450    global noHeaders
1451    global parsable
1452    global regexp
1453    global rdir
1454    global sdir_name
1455    global svn_silent
1456    global verbose
1457    global testdirs
1458    global lldb_platform_name
1459    global lldb_platform_url
1460    global lldb_platform_working_dir
1461    global setCrashInfoHook
1462    global is_inferior_test_runner
1463    global multiprocess_test_subdir
1464    global num_threads
1465    global output_on_success
1466    global no_multiprocess_test_runner
1467    global test_runner_name
1468    global results_filename
1469    global results_formatter_name
1470    global results_formatter_options
1471    global results_port
1472
1473    # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1474    # does not exist before proceeding to running the test suite.
1475    if sys.platform.startswith("darwin"):
1476        checkDsymForUUIDIsNotOn()
1477
1478    #
1479    # Start the actions by first parsing the options while setting up the test
1480    # directories, followed by setting up the search paths for lldb utilities;
1481    # then, we walk the directory trees and collect the tests into our test suite.
1482    #
1483    parseOptionsAndInitTestdirs()
1484
1485    # Setup test results (test results formatter and output handling).
1486    setupTestResults()
1487
1488    # If we are running as the multiprocess test runner, kick off the
1489    # multiprocess test runner here.
1490    if isMultiprocessTestRunner():
1491        from . import dosep
1492        dosep.main(output_on_success, num_threads, multiprocess_test_subdir,
1493                   test_runner_name, results_formatter_object)
1494        raise Exception("should never get here")
1495    elif is_inferior_test_runner:
1496        # Shut off Ctrl-C processing in inferiors.  The parallel
1497        # test runner handles this more holistically.
1498        signal.signal(signal.SIGINT, signal.SIG_IGN)
1499
1500    setupSysPath()
1501    setupCrashInfoHook()
1502
1503    #
1504    # If '-l' is specified, do not skip the long running tests.
1505    if not skip_long_running_test:
1506        os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1507
1508    # For the time being, let's bracket the test runner within the
1509    # lldb.SBDebugger.Initialize()/Terminate() pair.
1510    import lldb
1511
1512    # Create a singleton SBDebugger in the lldb namespace.
1513    lldb.DBG = lldb.SBDebugger.Create()
1514
1515    if lldb_platform_name:
1516        print("Setting up remote platform '%s'" % (lldb_platform_name))
1517        lldb.remote_platform = lldb.SBPlatform(lldb_platform_name)
1518        lldb.remote_platform_name = lldb_platform_name
1519        if not lldb.remote_platform.IsValid():
1520            print("error: unable to create the LLDB platform named '%s'." % (lldb_platform_name))
1521            exitTestSuite(1)
1522        if lldb_platform_url:
1523            # We must connect to a remote platform if a LLDB platform URL was specified
1524            print("Connecting to remote platform '%s' at '%s'..." % (lldb_platform_name, lldb_platform_url))
1525            lldb.platform_url = lldb_platform_url
1526            platform_connect_options = lldb.SBPlatformConnectOptions(lldb_platform_url)
1527            err = lldb.remote_platform.ConnectRemote(platform_connect_options)
1528            if err.Success():
1529                print("Connected.")
1530            else:
1531                print("error: failed to connect to remote platform using URL '%s': %s" % (lldb_platform_url, err))
1532                exitTestSuite(1)
1533        else:
1534            lldb.platform_url = None
1535
1536    platform_changes = setDefaultTripleForPlatform()
1537    first = True
1538    for key in platform_changes:
1539        if first:
1540            print("Environment variables setup for platform support:")
1541            first = False
1542        print("%s = %s" % (key,platform_changes[key]))
1543
1544    if lldb_platform_working_dir:
1545        print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir))
1546        lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir)
1547        lldb.remote_platform_working_dir = lldb_platform_working_dir
1548        lldb.DBG.SetSelectedPlatform(lldb.remote_platform)
1549    else:
1550        lldb.remote_platform = None
1551        lldb.remote_platform_working_dir = None
1552        lldb.platform_url = None
1553
1554    target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
1555
1556    # By default, both dsym, dwarf and dwo tests are performed.
1557    # Use @dsym_test, @dwarf_test or @dwo_test decorators, defined in lldbtest.py, to mark a test as
1558    # a dsym, dwarf or dwo test.  Use '-N dsym', '-N dwarf' or '-N dwo' to exclude dsym, dwarf or
1559    # dwo tests from running.
1560    dont_do_dsym_test = dont_do_dsym_test or any(platform in target_platform for platform in ["linux", "freebsd", "windows"])
1561    dont_do_dwo_test = dont_do_dwo_test or any(platform in target_platform for platform in ["darwin", "macosx", "ios"])
1562
1563    # Don't do debugserver tests on everything except OS X.
1564    dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform
1565
1566    # Don't do lldb-server (llgs) tests on anything except Linux.
1567    dont_do_llgs_test = not ("linux" in target_platform)
1568
1569    #
1570    # Walk through the testdirs while collecting tests.
1571    #
1572    for testdir in testdirs:
1573        for (dirpath, dirnames, filenames) in os.walk(testdir):
1574            visit('Test', dirpath, filenames)
1575
1576    #
1577    # Now that we have loaded all the test cases, run the whole test suite.
1578    #
1579
1580    # Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
1581    lldb.blacklist = blacklist
1582
1583    # The pre_flight and post_flight come from reading a config file.
1584    lldb.pre_flight = pre_flight
1585    lldb.post_flight = post_flight
1586    def getsource_if_available(obj):
1587        """
1588        Return the text of the source code for an object if available.  Otherwise,
1589        a print representation is returned.
1590        """
1591        import inspect
1592        try:
1593            return inspect.getsource(obj)
1594        except:
1595            return repr(obj)
1596
1597    if not noHeaders:
1598        print("lldb.pre_flight:", getsource_if_available(lldb.pre_flight))
1599        print("lldb.post_flight:", getsource_if_available(lldb.post_flight))
1600
1601    # If either pre_flight or post_flight is defined, set lldb.test_remote to True.
1602    if lldb.pre_flight or lldb.post_flight:
1603        lldb.test_remote = True
1604    else:
1605        lldb.test_remote = False
1606
1607    # So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables.
1608    lldb.lldbtest_remote_sandbox = lldbtest_remote_sandbox
1609    lldb.lldbtest_remote_sandboxed_executable = None
1610    lldb.lldbtest_remote_shell_template = lldbtest_remote_shell_template
1611
1612    # Put all these test decorators in the lldb namespace.
1613    lldb.just_do_benchmarks_test = just_do_benchmarks_test
1614    lldb.dont_do_dsym_test = dont_do_dsym_test
1615    lldb.dont_do_dwarf_test = dont_do_dwarf_test
1616    lldb.dont_do_dwo_test = dont_do_dwo_test
1617    lldb.dont_do_debugserver_test = dont_do_debugserver_test
1618    lldb.dont_do_llgs_test = dont_do_llgs_test
1619
1620    # Do we need to skip build and cleanup?
1621    lldb.skip_build_and_cleanup = skip_build_and_cleanup
1622
1623    # Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
1624    lldb.bmExecutable = bmExecutable
1625    lldb.bmBreakpointSpec = bmBreakpointSpec
1626    lldb.bmIterationCount = bmIterationCount
1627
1628    # And don't forget the runHooks!
1629    lldb.runHooks = runHooks
1630
1631    # Turn on lldb loggings if necessary.
1632    lldbLoggings()
1633
1634    # Disable default dynamic types for testing purposes
1635    disabledynamics()
1636
1637    # Install the control-c handler.
1638    unittest2.signals.installHandler()
1639
1640    # If sdir_name is not specified through the '-s sdir_name' option, get a
1641    # timestamp string and export it as LLDB_SESSION_DIR environment var.  This will
1642    # be used when/if we want to dump the session info of individual test cases
1643    # later on.
1644    #
1645    # See also TestBase.dumpSessionInfo() in lldbtest.py.
1646    import datetime
1647    # The windows platforms don't like ':' in the pathname.
1648    timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1649    if not sdir_name:
1650        sdir_name = timestamp_started
1651    os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
1652
1653    if not noHeaders:
1654        sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1655                         " will go into directory '%s'\n" % sdir_name)
1656        sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
1657
1658    if not os.path.isdir(sdir_name):
1659        try:
1660            os.mkdir(sdir_name)
1661        except OSError as exception:
1662            if exception.errno != errno.EEXIST:
1663                raise
1664    where_to_save_session = os.getcwd()
1665    fname = os.path.join(sdir_name, "TestStarted-%d" % os.getpid())
1666    with open(fname, "w") as f:
1667        print("Test started at: %s\n" % timestamp_started, file=f)
1668        print(svn_info, file=f)
1669        print("Command invoked: %s\n" % getMyCommandLine(), file=f)
1670
1671    #
1672    # Invoke the default TextTestRunner to run the test suite, possibly iterating
1673    # over different configurations.
1674    #
1675
1676    iterArchs = False
1677    iterCompilers = False
1678
1679    if not archs and "archs" in config:
1680        archs = config["archs"]
1681
1682    if isinstance(archs, list) and len(archs) >= 1:
1683        iterArchs = True
1684
1685    if not compilers and "compilers" in config:
1686        compilers = config["compilers"]
1687
1688    #
1689    # Add some intervention here to sanity check that the compilers requested are sane.
1690    # If found not to be an executable program, the invalid one is dropped from the list.
1691    for i in range(len(compilers)):
1692        c = compilers[i]
1693        if which(c):
1694            continue
1695        else:
1696            if sys.platform.startswith("darwin"):
1697                pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1698                cmd_output = pipe.stdout.read()
1699                if cmd_output:
1700                    if "not found" in cmd_output:
1701                        print("dropping %s from the compilers used" % c)
1702                        compilers.remove(i)
1703                    else:
1704                        compilers[i] = cmd_output.split('\n')[0]
1705                        print("'xcrun -find %s' returning %s" % (c, compilers[i]))
1706
1707    if not parsable:
1708        print("compilers=%s" % str(compilers))
1709
1710    if not compilers or len(compilers) == 0:
1711        print("No eligible compiler found, exiting.")
1712        exitTestSuite(1)
1713
1714    if isinstance(compilers, list) and len(compilers) >= 1:
1715        iterCompilers = True
1716
1717    # Make a shallow copy of sys.path, we need to manipulate the search paths later.
1718    # This is only necessary if we are relocated and with different configurations.
1719    if rdir:
1720        old_sys_path = sys.path[:]
1721    # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1722    if iterArchs or iterCompilers:
1723        old_stderr = sys.stderr
1724        old_stdout = sys.stdout
1725        new_stderr = None
1726        new_stdout = None
1727
1728    # Iterating over all possible architecture and compiler combinations.
1729    for ia in range(len(archs) if iterArchs else 1):
1730        archConfig = ""
1731        if iterArchs:
1732            os.environ["ARCH"] = archs[ia]
1733            archConfig = "arch=%s" % archs[ia]
1734        for ic in range(len(compilers) if iterCompilers else 1):
1735            if iterCompilers:
1736                os.environ["CC"] = compilers[ic]
1737                configString = "%s compiler=%s" % (archConfig, compilers[ic])
1738            else:
1739                configString = archConfig
1740
1741            if iterArchs or iterCompilers:
1742                # Translate ' ' to '-' for pathname component.
1743                if six.PY2:
1744                    import string
1745                    tbl = string.maketrans(' ', '-')
1746                else:
1747                    tbl = str.maketrans(' ', '-')
1748                configPostfix = configString.translate(tbl)
1749
1750                # Check whether we need to split stderr/stdout into configuration
1751                # specific files.
1752                if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1753                    if new_stderr:
1754                        new_stderr.close()
1755                    new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1756                    sys.stderr = new_stderr
1757                if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1758                    if new_stdout:
1759                        new_stdout.close()
1760                    new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1761                    sys.stdout = new_stdout
1762
1763                # If we specified a relocated directory to run the test suite, do
1764                # the extra housekeeping to copy the testdirs to a configStringified
1765                # directory and to update sys.path before invoking the test runner.
1766                # The purpose is to separate the configuration-specific directories
1767                # from each other.
1768                if rdir:
1769                    from shutil import copytree, rmtree, ignore_patterns
1770
1771                    newrdir = "%s.%s" % (rdir, configPostfix)
1772
1773                    # Copy the tree to a new directory with postfix name configPostfix.
1774                    if os.path.exists(newrdir):
1775                        rmtree(newrdir)
1776                    copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1777
1778                    # Update the LLDB_TEST environment variable to reflect new top
1779                    # level test directory.
1780                    #
1781                    # See also lldbtest.TestBase.setUpClass(cls).
1782                    if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1783                        os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1784                    else:
1785                        os.environ["LLDB_TEST"] = newrdir
1786
1787                    # And update the Python search paths for modules.
1788                    sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1789
1790                # Output the configuration.
1791                if not parsable:
1792                    sys.stderr.write("\nConfiguration: " + configString + "\n")
1793
1794            #print("sys.stderr name is", sys.stderr.name)
1795            #print("sys.stdout name is", sys.stdout.name)
1796
1797            # First, write out the number of collected test cases.
1798            if not parsable:
1799                sys.stderr.write(separator + "\n")
1800                sys.stderr.write("Collected %d test%s\n\n"
1801                                 % (suite.countTestCases(),
1802                                    suite.countTestCases() != 1 and "s" or ""))
1803
1804            class LLDBTestResult(unittest2.TextTestResult):
1805                """
1806                Enforce a singleton pattern to allow introspection of test progress.
1807
1808                Overwrite addError(), addFailure(), and addExpectedFailure() methods
1809                to enable each test instance to track its failure/error status.  It
1810                is used in the LLDB test framework to emit detailed trace messages
1811                to a log file for easier human inspection of test failures/errors.
1812                """
1813                __singleton__ = None
1814                __ignore_singleton__ = False
1815
1816                @staticmethod
1817                def getTerminalSize():
1818                    import os
1819                    env = os.environ
1820                    def ioctl_GWINSZ(fd):
1821                        try:
1822                            import fcntl, termios, struct, os
1823                            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1824                        '1234'))
1825                        except:
1826                            return
1827                        return cr
1828                    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1829                    if not cr:
1830                        try:
1831                            fd = os.open(os.ctermid(), os.O_RDONLY)
1832                            cr = ioctl_GWINSZ(fd)
1833                            os.close(fd)
1834                        except:
1835                            pass
1836                    if not cr:
1837                        cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1838                    return int(cr[1]), int(cr[0])
1839
1840                def __init__(self, *args):
1841                    if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
1842                        raise Exception("LLDBTestResult instantiated more than once")
1843                    super(LLDBTestResult, self).__init__(*args)
1844                    LLDBTestResult.__singleton__ = self
1845                    # Now put this singleton into the lldb module namespace.
1846                    lldb.test_result = self
1847                    # Computes the format string for displaying the counter.
1848                    global suite
1849                    counterWidth = len(str(suite.countTestCases()))
1850                    self.fmt = "%" + str(counterWidth) + "d: "
1851                    self.indentation = ' ' * (counterWidth + 2)
1852                    # This counts from 1 .. suite.countTestCases().
1853                    self.counter = 0
1854                    (width, height) = LLDBTestResult.getTerminalSize()
1855                    self.progressbar = None
1856                    global progress_bar
1857                    if width > 10 and not parsable and progress_bar:
1858                        try:
1859                            self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
1860                        except:
1861                            self.progressbar = None
1862                    self.results_formatter = results_formatter_object
1863
1864                def _config_string(self, test):
1865                  compiler = getattr(test, "getCompiler", None)
1866                  arch = getattr(test, "getArchitecture", None)
1867                  return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
1868
1869                def _exc_info_to_string(self, err, test):
1870                    """Overrides superclass TestResult's method in order to append
1871                    our test config info string to the exception info string."""
1872                    if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"):
1873                        return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1874                                                                  test.getArchitecture(),
1875                                                                  test.getCompiler())
1876                    else:
1877                        return super(LLDBTestResult, self)._exc_info_to_string(err, test)
1878
1879                def getDescription(self, test):
1880                    doc_first_line = test.shortDescription()
1881                    if self.descriptions and doc_first_line:
1882                        return '\n'.join((str(test), self.indentation + doc_first_line))
1883                    else:
1884                        return str(test)
1885
1886                def getCategoriesForTest(self,test):
1887                    if hasattr(test,"_testMethodName"):
1888                        test_method = getattr(test,"_testMethodName")
1889                        test_method = getattr(test,test_method)
1890                    else:
1891                        test_method = None
1892                    if test_method != None and hasattr(test_method,"getCategories"):
1893                        test_categories = test_method.getCategories(test)
1894                    elif hasattr(test,"getCategories"):
1895                        test_categories = test.getCategories()
1896                    elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1897                        test_categories = test.__self__.getCategories()
1898                    else:
1899                        test_categories = []
1900                    if test_categories == None:
1901                        test_categories = []
1902                    return test_categories
1903
1904                def hardMarkAsSkipped(self,test):
1905                    getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1906                    getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1907                    test.__class__.__unittest_skip__ = True
1908                    test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1909
1910                def startTest(self, test):
1911                    if shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)):
1912                        self.hardMarkAsSkipped(test)
1913                    global setCrashInfoHook
1914                    setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__)))
1915                    self.counter += 1
1916                    #if self.counter == 4:
1917                    #    import crashinfo
1918                    #    crashinfo.testCrashReporterDescription(None)
1919                    test.test_number = self.counter
1920                    if self.showAll:
1921                        self.stream.write(self.fmt % self.counter)
1922                    super(LLDBTestResult, self).startTest(test)
1923                    if self.results_formatter:
1924                        self.results_formatter.handle_event(
1925                            EventBuilder.event_for_start(test))
1926
1927                def addSuccess(self, test):
1928                    global parsable
1929                    super(LLDBTestResult, self).addSuccess(test)
1930                    if parsable:
1931                        self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1932                    if self.results_formatter:
1933                        self.results_formatter.handle_event(
1934                            EventBuilder.event_for_success(test))
1935
1936                def addError(self, test, err):
1937                    global sdir_has_content
1938                    global parsable
1939                    sdir_has_content = True
1940                    super(LLDBTestResult, self).addError(test, err)
1941                    method = getattr(test, "markError", None)
1942                    if method:
1943                        method()
1944                    if parsable:
1945                        self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1946                    if self.results_formatter:
1947                        self.results_formatter.handle_event(
1948                            EventBuilder.event_for_error(test, err))
1949
1950                def addCleanupError(self, test, err):
1951                    global sdir_has_content
1952                    global parsable
1953                    sdir_has_content = True
1954                    super(LLDBTestResult, self).addCleanupError(test, err)
1955                    method = getattr(test, "markCleanupError", None)
1956                    if method:
1957                        method()
1958                    if parsable:
1959                        self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1960                    if self.results_formatter:
1961                        self.results_formatter.handle_event(
1962                            EventBuilder.event_for_cleanup_error(
1963                                test, err))
1964
1965                def addFailure(self, test, err):
1966                    global sdir_has_content
1967                    global failuresPerCategory
1968                    global parsable
1969                    sdir_has_content = True
1970                    super(LLDBTestResult, self).addFailure(test, err)
1971                    method = getattr(test, "markFailure", None)
1972                    if method:
1973                        method()
1974                    if parsable:
1975                        self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1976                    if useCategories:
1977                        test_categories = self.getCategoriesForTest(test)
1978                        for category in test_categories:
1979                            if category in failuresPerCategory:
1980                                failuresPerCategory[category] = failuresPerCategory[category] + 1
1981                            else:
1982                                failuresPerCategory[category] = 1
1983                    if self.results_formatter:
1984                        self.results_formatter.handle_event(
1985                            EventBuilder.event_for_failure(test, err))
1986
1987
1988                def addExpectedFailure(self, test, err, bugnumber):
1989                    global sdir_has_content
1990                    global parsable
1991                    sdir_has_content = True
1992                    super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
1993                    method = getattr(test, "markExpectedFailure", None)
1994                    if method:
1995                        method(err, bugnumber)
1996                    if parsable:
1997                        self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1998                    if self.results_formatter:
1999                        self.results_formatter.handle_event(
2000                            EventBuilder.event_for_expected_failure(
2001                            test, err, bugnumber))
2002
2003                def addSkip(self, test, reason):
2004                    global sdir_has_content
2005                    global parsable
2006                    sdir_has_content = True
2007                    super(LLDBTestResult, self).addSkip(test, reason)
2008                    method = getattr(test, "markSkippedTest", None)
2009                    if method:
2010                        method()
2011                    if parsable:
2012                        self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
2013                    if self.results_formatter:
2014                        self.results_formatter.handle_event(
2015                            EventBuilder.event_for_skip(test, reason))
2016
2017                def addUnexpectedSuccess(self, test, bugnumber):
2018                    global sdir_has_content
2019                    global parsable
2020                    sdir_has_content = True
2021                    super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
2022                    method = getattr(test, "markUnexpectedSuccess", None)
2023                    if method:
2024                        method(bugnumber)
2025                    if parsable:
2026                        self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
2027                    if self.results_formatter:
2028                        self.results_formatter.handle_event(
2029                            EventBuilder.event_for_unexpected_success(
2030                                test, bugnumber))
2031
2032
2033            if parsable:
2034                v = 0
2035            elif progress_bar:
2036                v = 1
2037            else:
2038                v = verbose
2039
2040            # Invoke the test runner.
2041            if count == 1:
2042                result = unittest2.TextTestRunner(stream=sys.stderr,
2043                                                  verbosity=v,
2044                                                  failfast=failfast,
2045                                                  resultclass=LLDBTestResult).run(suite)
2046            else:
2047                # We are invoking the same test suite more than once.  In this case,
2048                # mark __ignore_singleton__ flag as True so the signleton pattern is
2049                # not enforced.
2050                LLDBTestResult.__ignore_singleton__ = True
2051                for i in range(count):
2052
2053                    result = unittest2.TextTestRunner(stream=sys.stderr,
2054                                                      verbosity=v,
2055                                                      failfast=failfast,
2056                                                      resultclass=LLDBTestResult).run(suite)
2057
2058            failed = failed or not result.wasSuccessful()
2059
2060    if sdir_has_content and not parsable:
2061        sys.stderr.write("Session logs for test failures/errors/unexpected successes"
2062                         " can be found in directory '%s'\n" % sdir_name)
2063
2064    if useCategories and len(failuresPerCategory) > 0:
2065        sys.stderr.write("Failures per category:\n")
2066        for category in failuresPerCategory:
2067            sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
2068
2069    os.chdir(where_to_save_session)
2070    fname = os.path.join(sdir_name, "TestFinished-%d" % os.getpid())
2071    with open(fname, "w") as f:
2072        print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f)
2073
2074    # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
2075    # This should not be necessary now.
2076    if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
2077        print("Terminating Test suite...")
2078        subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
2079
2080    # Exiting.
2081    exitTestSuite(failed)
2082
2083if __name__ == "__main__":
2084    print(__file__ + " is for use as a module only.  It should not be run as a standalone script.")
2085    sys.exit(-1)
2086