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