]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/dotest.py
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / dotest.py
1 """
2 A simple testing framework for lldb using python's unit testing framework.
3
4 Tests for lldb are written as python scripts which take advantage of the script
5 bridging provided by LLDB.framework to interact with lldb core.
6
7 A specific naming pattern is followed by the .py script to be recognized as
8 a module which implements a test scenario, namely, Test*.py.
9
10 To specify the directories where "Test*.py" python test scripts are located,
11 you need to pass in a list of directory names.  By default, the current
12 working directory is searched if nothing is specified on the command line.
13
14 Type:
15
16 ./dotest.py -h
17
18 for available options.
19 """
20
21 from __future__ import absolute_import
22 from __future__ import print_function
23
24 # System modules
25 import atexit
26 import os
27 import errno
28 import platform
29 import re
30 import signal
31 import socket
32 import subprocess
33 import sys
34
35 # Third-party modules
36 import six
37 import unittest2
38
39 # LLDB Modules
40 import lldbsuite
41 from . import configuration
42 from . import dotest_args
43 from . import lldbtest_config
44 from . import test_categories
45 from lldbsuite.test_event import formatter
46 from . import test_result
47 from lldbsuite.test_event.event_builder import EventBuilder
48 from ..support import seven
49
50
51 def is_exe(fpath):
52     """Returns true if fpath is an executable."""
53     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
54
55
56 def which(program):
57     """Returns the full path to a program; None otherwise."""
58     fpath, fname = os.path.split(program)
59     if fpath:
60         if is_exe(program):
61             return program
62     else:
63         for path in os.environ["PATH"].split(os.pathsep):
64             exe_file = os.path.join(path, program)
65             if is_exe(exe_file):
66                 return exe_file
67     return None
68
69
70 class _WritelnDecorator(object):
71     """Used to decorate file-like objects with a handy 'writeln' method"""
72
73     def __init__(self, stream):
74         self.stream = stream
75
76     def __getattr__(self, attr):
77         if attr in ('stream', '__getstate__'):
78             raise AttributeError(attr)
79         return getattr(self.stream, attr)
80
81     def writeln(self, arg=None):
82         if arg:
83             self.write(arg)
84         self.write('\n')  # text-mode streams translate to \r\n if needed
85
86 #
87 # Global variables:
88 #
89
90
91 def usage(parser):
92     parser.print_help()
93     if configuration.verbose > 0:
94         print("""
95 Examples:
96
97 This is an example of using the -f option to pinpoint to a specific test class
98 and test method to be run:
99
100 $ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
101 ----------------------------------------------------------------------
102 Collected 1 test
103
104 test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
105 Test 'frame variable this' when stopped on a class constructor. ... ok
106
107 ----------------------------------------------------------------------
108 Ran 1 test in 1.396s
109
110 OK
111
112 And this is an example of using the -p option to run a single file (the filename
113 matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
114
115 $ ./dotest.py -v -p ObjC
116 ----------------------------------------------------------------------
117 Collected 4 tests
118
119 test_break_with_dsym (TestObjCMethods.FoundationTestCase)
120 Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
121 test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
122 Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
123 test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
124 Lookup objective-c data types and evaluate expressions. ... ok
125 test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
126 Lookup objective-c data types and evaluate expressions. ... ok
127
128 ----------------------------------------------------------------------
129 Ran 4 tests in 16.661s
130
131 OK
132
133 Running of this script also sets up the LLDB_TEST environment variable so that
134 individual test cases can locate their supporting files correctly.  The script
135 tries to set up Python's search paths for modules by looking at the build tree
136 relative to this script.  See also the '-i' option in the following example.
137
138 Finally, this is an example of using the lldb.py module distributed/installed by
139 Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
140 option to add some delay between two tests.  It uses ARCH=x86_64 to specify that
141 as the architecture and CC=clang to specify the compiler used for the test run:
142
143 $ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
144
145 Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
146 ----------------------------------------------------------------------
147 Collected 2 tests
148
149 test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
150 Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
151 test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
152 Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
153
154 ----------------------------------------------------------------------
155 Ran 2 tests in 5.659s
156
157 OK
158
159 The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
160 notify the directory containing the session logs for test failures or errors.
161 In case there is any test failure/error, a similar message is appended at the
162 end of the stderr output for your convenience.
163
164 ENABLING LOGS FROM TESTS
165
166 Option 1:
167
168 Writing logs into different files per test case::
169
170 This option is particularly useful when multiple dotest instances are created
171 by dosep.py
172
173 $ ./dotest.py --channel "lldb all"
174
175 $ ./dotest.py --channel "lldb all" --channel "gdb-remote packets"
176
177 These log files are written to:
178
179 <session-dir>/<test-id>-host.log (logs from lldb host process)
180 <session-dir>/<test-id>-server.log (logs from debugserver/lldb-server)
181 <session-dir>/<test-id>-<test-result>.log (console logs)
182
183 By default, logs from successful runs are deleted.  Use the --log-success flag
184 to create reference logs for debugging.
185
186 $ ./dotest.py --log-success
187
188 Option 2: (DEPRECATED)
189
190 The following options can only enable logs from the host lldb process.
191 Only categories from the "lldb" or "gdb-remote" channels can be enabled
192 They also do not automatically enable logs in locally running debug servers.
193 Also, logs from all test case are written into each log file
194
195 o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
196   with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
197
198 o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
199   'process.gdb-remote' subsystem with a default option of 'packets' if
200   GDB_REMOTE_LOG_OPTION is not defined.
201
202 """)
203     sys.exit(0)
204
205
206 def parseExclusion(exclusion_file):
207     """Parse an exclusion file, of the following format, where
208        'skip files', 'skip methods', 'xfail files', and 'xfail methods'
209        are the possible list heading values:
210
211        skip files
212        <file name>
213        <file name>
214
215        xfail methods
216        <method name>
217     """
218     excl_type = None
219
220     with open(exclusion_file) as f:
221         for line in f:
222             line = line.strip()
223             if not excl_type:
224                 excl_type = line
225                 continue
226
227             if not line:
228                 excl_type = None
229             elif excl_type == 'skip':
230                 if not configuration.skip_tests:
231                     configuration.skip_tests = []
232                 configuration.skip_tests.append(line)
233             elif excl_type == 'xfail':
234                 if not configuration.xfail_tests:
235                     configuration.xfail_tests = []
236                 configuration.xfail_tests.append(line)
237
238
239 def parseOptionsAndInitTestdirs():
240     """Initialize the list of directories containing our unittest scripts.
241
242     '-h/--help as the first option prints out usage info and exit the program.
243     """
244
245     do_help = False
246
247     platform_system = platform.system()
248     platform_machine = platform.machine()
249
250     parser = dotest_args.create_parser()
251     args = dotest_args.parse_args(parser, sys.argv[1:])
252
253     if args.unset_env_varnames:
254         for env_var in args.unset_env_varnames:
255             if env_var in os.environ:
256                 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
257                 # is automatically translated into a corresponding call to
258                 # unsetenv().
259                 del os.environ[env_var]
260                 # os.unsetenv(env_var)
261
262     if args.set_env_vars:
263         for env_var in args.set_env_vars:
264             parts = env_var.split('=', 1)
265             if len(parts) == 1:
266                 os.environ[parts[0]] = ""
267             else:
268                 os.environ[parts[0]] = parts[1]
269
270     # only print the args if being verbose (and parsable is off)
271     if args.v and not args.q:
272         print(sys.argv)
273
274     if args.h:
275         do_help = True
276
277     if args.compilers:
278         configuration.compilers = args.compilers
279     else:
280         # Use a compiler appropriate appropriate for the Apple SDK if one was
281         # specified
282         if platform_system == 'Darwin' and args.apple_sdk:
283             configuration.compilers = [
284                 seven.get_command_output(
285                     'xcrun -sdk "%s" -find clang 2> /dev/null' %
286                     (args.apple_sdk))]
287         else:
288             # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first
289             candidateCompilers = ['clang-3.5', 'clang', 'gcc']
290             for candidate in candidateCompilers:
291                 if which(candidate):
292                     configuration.compilers = [candidate]
293                     break
294
295     if args.channels:
296         lldbtest_config.channels = args.channels
297
298     if args.log_success:
299         lldbtest_config.log_success = args.log_success
300
301     # Set SDKROOT if we are using an Apple SDK
302     if platform_system == 'Darwin' and args.apple_sdk:
303         os.environ['SDKROOT'] = seven.get_command_output(
304             'xcrun --sdk "%s" --show-sdk-path 2> /dev/null' %
305             (args.apple_sdk))
306
307     if args.archs:
308         configuration.archs = args.archs
309         for arch in configuration.archs:
310             if arch.startswith(
311                     'arm') and platform_system == 'Darwin' and not args.apple_sdk:
312                 os.environ['SDKROOT'] = seven.get_command_output(
313                     'xcrun --sdk iphoneos.internal --show-sdk-path 2> /dev/null')
314                 if not os.path.exists(os.environ['SDKROOT']):
315                     os.environ['SDKROOT'] = seven.get_command_output(
316                         'xcrun --sdk iphoneos --show-sdk-path 2> /dev/null')
317     else:
318         configuration.archs = [platform_machine]
319
320     if args.categoriesList:
321         configuration.categoriesList = set(
322             test_categories.validate(
323                 args.categoriesList, False))
324         configuration.useCategories = True
325     else:
326         configuration.categoriesList = []
327
328     if args.skipCategories:
329         configuration.skipCategories = test_categories.validate(
330             args.skipCategories, False)
331
332     if args.E:
333         cflags_extras = args.E
334         os.environ['CFLAGS_EXTRAS'] = cflags_extras
335
336     if args.d:
337         sys.stdout.write(
338             "Suspending the process %d to wait for debugger to attach...\n" %
339             os.getpid())
340         sys.stdout.flush()
341         os.kill(os.getpid(), signal.SIGSTOP)
342
343     if args.f:
344         if any([x.startswith('-') for x in args.f]):
345             usage(parser)
346         configuration.filters.extend(args.f)
347         # Shut off multiprocessing mode when additional filters are specified.
348         # The rational is that the user is probably going after a very specific
349         # test and doesn't need a bunch of parallel test runners all looking for
350         # it in a frenzy.  Also, '-v' now spits out all test run output even
351         # on success, so the standard recipe for redoing a failing test (with -v
352         # and a -f to filter to the specific test) now causes all test scanning
353         # (in parallel) to print results for do-nothing runs in a very distracting
354         # manner.  If we really need filtered parallel runs in the future, consider
355         # adding a --no-output-on-success that prevents -v from setting
356         # output-on-success.
357         configuration.no_multiprocess_test_runner = True
358
359     if args.l:
360         configuration.skip_long_running_test = False
361
362     if args.framework:
363         configuration.lldbFrameworkPath = args.framework
364
365     if args.executable:
366         lldbtest_config.lldbExec = os.path.realpath(args.executable)
367
368     if args.excluded:
369         for excl_file in args.excluded:
370             parseExclusion(excl_file)
371
372     if args.p:
373         if args.p.startswith('-'):
374             usage(parser)
375         configuration.regexp = args.p
376
377     if args.q:
378         configuration.parsable = True
379
380     if args.s:
381         if args.s.startswith('-'):
382             usage(parser)
383         configuration.sdir_name = args.s
384     configuration.session_file_format = args.session_file_format
385
386     if args.t:
387         os.environ['LLDB_COMMAND_TRACE'] = 'YES'
388
389     if args.v:
390         configuration.verbose = 2
391
392     # argparse makes sure we have a number
393     if args.sharp:
394         configuration.count = args.sharp
395
396     if sys.platform.startswith('win32'):
397         os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(
398             args.disable_crash_dialog)
399         os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True)
400
401     if do_help:
402         usage(parser)
403
404     if args.no_multiprocess:
405         configuration.no_multiprocess_test_runner = True
406
407     if args.inferior:
408         configuration.is_inferior_test_runner = True
409
410     if args.num_threads:
411         configuration.num_threads = args.num_threads
412
413     if args.test_subdir:
414         configuration.multiprocess_test_subdir = args.test_subdir
415
416     if args.test_runner_name:
417         configuration.test_runner_name = args.test_runner_name
418
419     # Capture test results-related args.
420     if args.curses and not args.inferior:
421         # Act as if the following args were set.
422         args.results_formatter = "lldbsuite.test_event.formatter.curses.Curses"
423         args.results_file = "stdout"
424
425     if args.results_file:
426         configuration.results_filename = args.results_file
427
428     if args.results_port:
429         configuration.results_port = args.results_port
430
431     if args.results_file and args.results_port:
432         sys.stderr.write(
433             "only one of --results-file and --results-port should "
434             "be specified\n")
435         usage(args)
436
437     if args.results_formatter:
438         configuration.results_formatter_name = args.results_formatter
439     if args.results_formatter_options:
440         configuration.results_formatter_options = args.results_formatter_options
441
442     # Default to using the BasicResultsFormatter if no formatter is specified
443     # and we're not a test inferior.
444     if not args.inferior and configuration.results_formatter_name is None:
445         configuration.results_formatter_name = (
446             "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter")
447
448     # rerun-related arguments
449     configuration.rerun_all_issues = args.rerun_all_issues
450     configuration.rerun_max_file_threshold = args.rerun_max_file_threshold
451
452     if args.lldb_platform_name:
453         configuration.lldb_platform_name = args.lldb_platform_name
454     if args.lldb_platform_url:
455         configuration.lldb_platform_url = args.lldb_platform_url
456     if args.lldb_platform_working_dir:
457         configuration.lldb_platform_working_dir = args.lldb_platform_working_dir
458
459     if args.event_add_entries and len(args.event_add_entries) > 0:
460         entries = {}
461         # Parse out key=val pairs, separated by comma
462         for keyval in args.event_add_entries.split(","):
463             key_val_entry = keyval.split("=")
464             if len(key_val_entry) == 2:
465                 (key, val) = key_val_entry
466                 val_parts = val.split(':')
467                 if len(val_parts) > 1:
468                     (val, val_type) = val_parts
469                     if val_type == 'int':
470                         val = int(val)
471                 entries[key] = val
472         # Tell the event builder to create all events with these
473         # key/val pairs in them.
474         if len(entries) > 0:
475             EventBuilder.add_entries_to_all_events(entries)
476
477     # Gather all the dirs passed on the command line.
478     if len(args.args) > 0:
479         configuration.testdirs = list(
480             map(lambda x: os.path.realpath(os.path.abspath(x)), args.args))
481         # Shut off multiprocessing mode when test directories are specified.
482         configuration.no_multiprocess_test_runner = True
483
484     lldbtest_config.codesign_identity = args.codesign_identity
485
486     #print("testdirs:", testdirs)
487
488
489 def getXcodeOutputPaths(lldbRootDirectory):
490     result = []
491
492     # These are for xcode build directories.
493     xcode3_build_dir = ['build']
494     xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
495
496     configurations = [
497         ['Debug'],
498         ['DebugClang'],
499         ['Release'],
500         ['BuildAndIntegration']]
501     xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir]
502     for configuration in configurations:
503         for xcode_build_dir in xcode_build_dirs:
504             outputPath = os.path.join(
505                 lldbRootDirectory, *(xcode_build_dir + configuration))
506             result.append(outputPath)
507
508     return result
509
510
511 def createSocketToLocalPort(port):
512     def socket_closer(s):
513         """Close down an opened socket properly."""
514         s.shutdown(socket.SHUT_RDWR)
515         s.close()
516
517     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
518     sock.connect(("localhost", port))
519     return (sock, lambda: socket_closer(sock))
520
521
522 def setupTestResults():
523     """Sets up test results-related objects based on arg settings."""
524     # Setup the results formatter configuration.
525     formatter_config = formatter.FormatterConfig()
526     formatter_config.filename = configuration.results_filename
527     formatter_config.formatter_name = configuration.results_formatter_name
528     formatter_config.formatter_options = (
529         configuration.results_formatter_options)
530     formatter_config.port = configuration.results_port
531
532     # Create the results formatter.
533     formatter_spec = formatter.create_results_formatter(
534         formatter_config)
535     if formatter_spec is not None and formatter_spec.formatter is not None:
536         configuration.results_formatter_object = formatter_spec.formatter
537
538         # Send an initialize message to the formatter.
539         initialize_event = EventBuilder.bare_event("initialize")
540         if isMultiprocessTestRunner():
541             if (configuration.test_runner_name is not None and
542                     configuration.test_runner_name == "serial"):
543                 # Only one worker queue here.
544                 worker_count = 1
545             else:
546                 # Workers will be the number of threads specified.
547                 worker_count = configuration.num_threads
548         else:
549             worker_count = 1
550         initialize_event["worker_count"] = worker_count
551
552         formatter_spec.formatter.handle_event(initialize_event)
553
554         # Make sure we clean up the formatter on shutdown.
555         if formatter_spec.cleanup_func is not None:
556             atexit.register(formatter_spec.cleanup_func)
557
558
559 def getOutputPaths(lldbRootDirectory):
560     """
561     Returns typical build output paths for the lldb executable
562
563     lldbDirectory - path to the root of the lldb svn/git repo
564     """
565     result = []
566
567     if sys.platform == 'darwin':
568         result.extend(getXcodeOutputPaths(lldbRootDirectory))
569
570     # cmake builds?  look for build or build/host folder next to llvm directory
571     # lldb is located in llvm/tools/lldb so we need to go up three levels
572     llvmParentDir = os.path.abspath(
573         os.path.join(
574             lldbRootDirectory,
575             os.pardir,
576             os.pardir,
577             os.pardir))
578     result.append(os.path.join(llvmParentDir, 'build', 'bin'))
579     result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin'))
580
581     # some cmake developers keep their build directory beside their lldb
582     # directory
583     lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir))
584     result.append(os.path.join(lldbParentDir, 'build', 'bin'))
585     result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin'))
586
587     return result
588
589
590 def setupSysPath():
591     """
592     Add LLDB.framework/Resources/Python to the search paths for modules.
593     As a side effect, we also discover the 'lldb' executable and export it here.
594     """
595
596     # Get the directory containing the current script.
597     if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
598         scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
599     else:
600         scriptPath = os.path.dirname(os.path.realpath(__file__))
601     if not scriptPath.endswith('test'):
602         print("This script expects to reside in lldb's test directory.")
603         sys.exit(-1)
604
605     os.environ["LLDB_TEST"] = scriptPath
606
607     # Set up the LLDB_SRC environment variable, so that the tests can locate
608     # the LLDB source code.
609     os.environ["LLDB_SRC"] = lldbsuite.lldb_root
610
611     pluginPath = os.path.join(scriptPath, 'plugins')
612     toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi')
613     toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
614
615     # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the
616     # sys.path.
617     sys.path.insert(0, pluginPath)
618     # Adding test/tools/lldb-mi to the path makes it easy
619     sys.path.insert(0, toolsLLDBMIPath)
620     # to "import lldbmi_testcase" from the MI tests
621     # Adding test/tools/lldb-server to the path makes it easy
622     sys.path.insert(0, toolsLLDBServerPath)
623     # to "import lldbgdbserverutils" from the lldb-server tests
624
625     # This is the root of the lldb git/svn checkout
626     # When this changes over to a package instead of a standalone script, this
627     # will be `lldbsuite.lldb_root`
628     lldbRootDirectory = lldbsuite.lldb_root
629
630     # Some of the tests can invoke the 'lldb' command directly.
631     # We'll try to locate the appropriate executable right here.
632
633     # The lldb executable can be set from the command line
634     # if it's not set, we try to find it now
635     # first, we try the environment
636     if not lldbtest_config.lldbExec:
637         # First, you can define an environment variable LLDB_EXEC specifying the
638         # full pathname of the lldb executable.
639         if "LLDB_EXEC" in os.environ:
640             lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]
641
642     if not lldbtest_config.lldbExec:
643         outputPaths = getOutputPaths(lldbRootDirectory)
644         for outputPath in outputPaths:
645             candidatePath = os.path.join(outputPath, 'lldb')
646             if is_exe(candidatePath):
647                 lldbtest_config.lldbExec = candidatePath
648                 break
649
650     if not lldbtest_config.lldbExec:
651         # Last, check the path
652         lldbtest_config.lldbExec = which('lldb')
653
654     if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
655         print(
656             "'{}' is not a path to a valid executable".format(
657                 lldbtest_config.lldbExec))
658         lldbtest_config.lldbExec = None
659
660     if not lldbtest_config.lldbExec:
661         print("The 'lldb' executable cannot be located.  Some of the tests may not be run as a result.")
662         sys.exit(-1)
663
664     # confusingly, this is the "bin" directory
665     lldbLibDir = os.path.dirname(lldbtest_config.lldbExec)
666     os.environ["LLDB_LIB_DIR"] = lldbLibDir
667     lldbImpLibDir = os.path.join(
668         lldbLibDir,
669         '..',
670         'lib') if sys.platform.startswith('win32') else lldbLibDir
671     os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir
672     print("LLDB library dir:", os.environ["LLDB_LIB_DIR"])
673     print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"])
674     os.system('%s -v' % lldbtest_config.lldbExec)
675
676     # Assume lldb-mi is in same place as lldb
677     # If not found, disable the lldb-mi tests
678     # TODO: Append .exe on Windows
679     #   - this will be in a separate commit in case the mi tests fail horribly
680     lldbDir = os.path.dirname(lldbtest_config.lldbExec)
681     lldbMiExec = os.path.join(lldbDir, "lldb-mi")
682     if is_exe(lldbMiExec):
683         os.environ["LLDBMI_EXEC"] = lldbMiExec
684     else:
685         if not configuration.shouldSkipBecauseOfCategories(["lldb-mi"]):
686             print(
687                 "The 'lldb-mi' executable cannot be located.  The lldb-mi tests can not be run as a result.")
688             configuration.skipCategories.append("lldb-mi")
689
690     lldbPythonDir = None  # The directory that contains 'lldb/__init__.py'
691     if not configuration.lldbFrameworkPath and os.path.exists(os.path.join(lldbLibDir, "LLDB.framework")):
692         configuration.lldbFrameworkPath = os.path.join(lldbLibDir, "LLDB.framework")
693     if configuration.lldbFrameworkPath:
694         lldbtest_config.lldbFrameworkPath = configuration.lldbFrameworkPath
695         candidatePath = os.path.join(
696             configuration.lldbFrameworkPath, 'Resources', 'Python')
697         if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
698             lldbPythonDir = candidatePath
699         if not lldbPythonDir:
700             print(
701                 'Resources/Python/lldb/__init__.py was not found in ' +
702                 configuration.lldbFrameworkPath)
703             sys.exit(-1)
704     else:
705         # If our lldb supports the -P option, use it to find the python path:
706         init_in_python_dir = os.path.join('lldb', '__init__.py')
707
708         lldb_dash_p_result = subprocess.check_output(
709             [lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True)
710
711         if lldb_dash_p_result and not lldb_dash_p_result.startswith(
712                 ("<", "lldb: invalid option:")) and not lldb_dash_p_result.startswith("Traceback"):
713             lines = lldb_dash_p_result.splitlines()
714
715             # Workaround for readline vs libedit issue on FreeBSD.  If stdout
716             # is not a terminal Python executes
717             #     rl_variable_bind ("enable-meta-key", "off");
718             # This produces a warning with FreeBSD's libedit because the
719             # enable-meta-key variable is unknown.  Not an issue on Apple
720             # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__
721             # around the call.  See http://bugs.python.org/issue19884 for more
722             # information.  For now we just discard the warning output.
723             if len(lines) >= 1 and lines[0].startswith(
724                     "bind: Invalid command"):
725                 lines.pop(0)
726
727             # Taking the last line because lldb outputs
728             # 'Cannot read termcap database;\nusing dumb terminal settings.\n'
729             # before the path
730             if len(lines) >= 1 and os.path.isfile(
731                     os.path.join(lines[-1], init_in_python_dir)):
732                 lldbPythonDir = lines[-1]
733                 if "freebsd" in sys.platform or "linux" in sys.platform:
734                     os.environ['LLDB_LIB_DIR'] = os.path.join(
735                         lldbPythonDir, '..', '..')
736
737         if not lldbPythonDir:
738             if platform.system() == "Darwin":
739                 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
740                 outputPaths = getXcodeOutputPaths(lldbRootDirectory)
741                 for outputPath in outputPaths:
742                     candidatePath = os.path.join(
743                         outputPath, *python_resource_dir)
744                     if os.path.isfile(
745                         os.path.join(
746                             candidatePath,
747                             init_in_python_dir)):
748                         lldbPythonDir = candidatePath
749                         break
750
751                 if not lldbPythonDir:
752                     print("lldb.py is not found, some tests may fail.")
753             else:
754                 print(
755                     "Unable to load lldb extension module.  Possible reasons for this include:")
756                 print("  1) LLDB was built with LLDB_DISABLE_PYTHON=1")
757                 print(
758                     "  2) PYTHONPATH and PYTHONHOME are not set correctly.  PYTHONHOME should refer to")
759                 print(
760                     "     the version of Python that LLDB built and linked against, and PYTHONPATH")
761                 print(
762                     "     should contain the Lib directory for the same python distro, as well as the")
763                 print("     location of LLDB\'s site-packages folder.")
764                 print(
765                     "  3) A different version of Python than that which was built against is exported in")
766                 print("     the system\'s PATH environment variable, causing conflicts.")
767                 print(
768                     "  4) The executable '%s' could not be found.  Please check " %
769                     lldbtest_config.lldbExec)
770                 print("     that it exists and is executable.")
771
772     if lldbPythonDir:
773         lldbPythonDir = os.path.normpath(lldbPythonDir)
774         # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
775         # If the path we've constructed looks like that, then we'll strip out
776         # the Versions/A part.
777         (before, frameWithVersion, after) = lldbPythonDir.rpartition(
778             "LLDB.framework/Versions/A")
779         if frameWithVersion != "":
780             lldbPythonDir = before + "LLDB.framework" + after
781
782         lldbPythonDir = os.path.abspath(lldbPythonDir)
783
784         # If tests need to find LLDB_FRAMEWORK, now they can do it
785         os.environ["LLDB_FRAMEWORK"] = os.path.dirname(
786             os.path.dirname(lldbPythonDir))
787
788         # This is to locate the lldb.py module.  Insert it right after
789         # sys.path[0].
790         sys.path[1:1] = [lldbPythonDir]
791
792
793 def visit_file(dir, name):
794     # Try to match the regexp pattern, if specified.
795     if configuration.regexp:
796         if not re.search(configuration.regexp, name):
797             # We didn't match the regex, we're done.
798             return
799
800     if configuration.skip_tests:
801         for file_regexp in configuration.skip_tests:
802             if re.search(file_regexp, name):
803                 return
804
805     # We found a match for our test.  Add it to the suite.
806
807     # Update the sys.path first.
808     if not sys.path.count(dir):
809         sys.path.insert(0, dir)
810     base = os.path.splitext(name)[0]
811
812     # Thoroughly check the filterspec against the base module and admit
813     # the (base, filterspec) combination only when it makes sense.
814     filterspec = None
815     for filterspec in configuration.filters:
816         # Optimistically set the flag to True.
817         filtered = True
818         module = __import__(base)
819         parts = filterspec.split('.')
820         obj = module
821         for part in parts:
822             try:
823                 parent, obj = obj, getattr(obj, part)
824             except AttributeError:
825                 # The filterspec has failed.
826                 filtered = False
827                 break
828
829         # If filtered, we have a good filterspec.  Add it.
830         if filtered:
831             # print("adding filter spec %s to module %s" % (filterspec, module))
832             configuration.suite.addTests(
833                 unittest2.defaultTestLoader.loadTestsFromName(
834                     filterspec, module))
835             continue
836
837     # Forgo this module if the (base, filterspec) combo is invalid
838     if configuration.filters and not filtered:
839         return
840
841     if not filterspec or not filtered:
842         # Add the entire file's worth of tests since we're not filtered.
843         # Also the fail-over case when the filterspec branch
844         # (base, filterspec) combo doesn't make sense.
845         configuration.suite.addTests(
846             unittest2.defaultTestLoader.loadTestsFromName(base))
847
848
849 def visit(prefix, dir, names):
850     """Visitor function for os.path.walk(path, visit, arg)."""
851
852     dir_components = set(dir.split(os.sep))
853     excluded_components = set(['.svn', '.git'])
854     if dir_components.intersection(excluded_components):
855         return
856
857     # Gather all the Python test file names that follow the Test*.py pattern.
858     python_test_files = [
859         name
860         for name in names
861         if name.endswith('.py') and name.startswith(prefix)]
862
863     # Visit all the python test files.
864     for name in python_test_files:
865         try:
866             # Ensure we error out if we have multiple tests with the same
867             # base name.
868             # Future improvement: find all the places where we work with base
869             # names and convert to full paths.  We have directory structure
870             # to disambiguate these, so we shouldn't need this constraint.
871             if name in configuration.all_tests:
872                 raise Exception("Found multiple tests with the name %s" % name)
873             configuration.all_tests.add(name)
874
875             # Run the relevant tests in the python file.
876             visit_file(dir, name)
877         except Exception as ex:
878             # Convert this exception to a test event error for the file.
879             test_filename = os.path.abspath(os.path.join(dir, name))
880             if configuration.results_formatter_object is not None:
881                 # Grab the backtrace for the exception.
882                 import traceback
883                 backtrace = traceback.format_exc()
884
885                 # Generate the test event.
886                 configuration.results_formatter_object.handle_event(
887                     EventBuilder.event_for_job_test_add_error(
888                         test_filename, ex, backtrace))
889             raise
890
891
892 def disabledynamics():
893     import lldb
894     ci = lldb.DBG.GetCommandInterpreter()
895     res = lldb.SBCommandReturnObject()
896     ci.HandleCommand(
897         "setting set target.prefer-dynamic-value no-dynamic-values",
898         res,
899         False)
900     if not res.Succeeded():
901         raise Exception('disabling dynamic type support failed')
902
903
904 def lldbLoggings():
905     import lldb
906     """Check and do lldb loggings if necessary."""
907
908     # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
909     # defined.  Use ${LLDB_LOG} to specify the log file.
910     ci = lldb.DBG.GetCommandInterpreter()
911     res = lldb.SBCommandReturnObject()
912     if ("LLDB_LOG" in os.environ):
913         open(os.environ["LLDB_LOG"], 'w').close()
914         if ("LLDB_LOG_OPTION" in os.environ):
915             lldb_log_option = os.environ["LLDB_LOG_OPTION"]
916         else:
917             lldb_log_option = "event process expr state api"
918         ci.HandleCommand(
919             "log enable -n -f " +
920             os.environ["LLDB_LOG"] +
921             " lldb " +
922             lldb_log_option,
923             res)
924         if not res.Succeeded():
925             raise Exception('log enable failed (check LLDB_LOG env variable)')
926
927     if ("LLDB_LINUX_LOG" in os.environ):
928         open(os.environ["LLDB_LINUX_LOG"], 'w').close()
929         if ("LLDB_LINUX_LOG_OPTION" in os.environ):
930             lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"]
931         else:
932             lldb_log_option = "event process expr state api"
933         ci.HandleCommand(
934             "log enable -n -f " +
935             os.environ["LLDB_LINUX_LOG"] +
936             " linux " +
937             lldb_log_option,
938             res)
939         if not res.Succeeded():
940             raise Exception(
941                 'log enable failed (check LLDB_LINUX_LOG env variable)')
942
943     # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
944     # Use ${GDB_REMOTE_LOG} to specify the log file.
945     if ("GDB_REMOTE_LOG" in os.environ):
946         if ("GDB_REMOTE_LOG_OPTION" in os.environ):
947             gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
948         else:
949             gdb_remote_log_option = "packets process"
950         ci.HandleCommand(
951             "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
952             + gdb_remote_log_option,
953             res)
954         if not res.Succeeded():
955             raise Exception(
956                 'log enable failed (check GDB_REMOTE_LOG env variable)')
957
958
959 def getMyCommandLine():
960     return ' '.join(sys.argv)
961
962 # ======================================== #
963 #                                          #
964 # Execution of the test driver starts here #
965 #                                          #
966 # ======================================== #
967
968
969 def checkDsymForUUIDIsNotOn():
970     cmd = ["defaults", "read", "com.apple.DebugSymbols"]
971     pipe = subprocess.Popen(
972         cmd,
973         stdout=subprocess.PIPE,
974         stderr=subprocess.STDOUT)
975     cmd_output = pipe.stdout.read()
976     if cmd_output and "DBGFileMappedPaths = " in cmd_output:
977         print("%s =>" % ' '.join(cmd))
978         print(cmd_output)
979         print(
980             "Disable automatic lookup and caching of dSYMs before running the test suite!")
981         print("Exiting...")
982         sys.exit(0)
983
984
985 def exitTestSuite(exitCode=None):
986     import lldb
987     lldb.SBDebugger.Terminate()
988     if exitCode:
989         sys.exit(exitCode)
990
991
992 def isMultiprocessTestRunner():
993     # We're not multiprocess when we're either explicitly
994     # the inferior (as specified by the multiprocess test
995     # runner) OR we've been told to skip using the multiprocess
996     # test runner
997     return not (
998         configuration.is_inferior_test_runner or configuration.no_multiprocess_test_runner)
999
1000
1001 def getVersionForSDK(sdk):
1002     sdk = str.lower(sdk)
1003     full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1004     basename = os.path.basename(full_path)
1005     basename = os.path.splitext(basename)[0]
1006     basename = str.lower(basename)
1007     ver = basename.replace(sdk, '')
1008     return ver
1009
1010
1011 def getPathForSDK(sdk):
1012     sdk = str.lower(sdk)
1013     full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1014     if os.path.exists(full_path):
1015         return full_path
1016     return None
1017
1018
1019 def setDefaultTripleForPlatform():
1020     if configuration.lldb_platform_name == 'ios-simulator':
1021         triple_str = 'x86_64-apple-ios%s' % (
1022             getVersionForSDK('iphonesimulator'))
1023         os.environ['TRIPLE'] = triple_str
1024         return {'TRIPLE': triple_str}
1025     return {}
1026
1027
1028 def run_suite():
1029     # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1030     # does not exist before proceeding to running the test suite.
1031     if sys.platform.startswith("darwin"):
1032         checkDsymForUUIDIsNotOn()
1033
1034     #
1035     # Start the actions by first parsing the options while setting up the test
1036     # directories, followed by setting up the search paths for lldb utilities;
1037     # then, we walk the directory trees and collect the tests into our test suite.
1038     #
1039     parseOptionsAndInitTestdirs()
1040
1041     # Setup test results (test results formatter and output handling).
1042     setupTestResults()
1043
1044     # If we are running as the multiprocess test runner, kick off the
1045     # multiprocess test runner here.
1046     if isMultiprocessTestRunner():
1047         from . import dosep
1048         dosep.main(
1049             configuration.num_threads,
1050             configuration.multiprocess_test_subdir,
1051             configuration.test_runner_name,
1052             configuration.results_formatter_object)
1053         raise Exception("should never get here")
1054     elif configuration.is_inferior_test_runner:
1055         # Shut off Ctrl-C processing in inferiors.  The parallel
1056         # test runner handles this more holistically.
1057         signal.signal(signal.SIGINT, signal.SIG_IGN)
1058
1059     setupSysPath()
1060     configuration.setupCrashInfoHook()
1061
1062     #
1063     # If '-l' is specified, do not skip the long running tests.
1064     if not configuration.skip_long_running_test:
1065         os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1066
1067     # For the time being, let's bracket the test runner within the
1068     # lldb.SBDebugger.Initialize()/Terminate() pair.
1069     import lldb
1070
1071     # Create a singleton SBDebugger in the lldb namespace.
1072     lldb.DBG = lldb.SBDebugger.Create()
1073
1074     if configuration.lldb_platform_name:
1075         print("Setting up remote platform '%s'" %
1076               (configuration.lldb_platform_name))
1077         lldb.remote_platform = lldb.SBPlatform(
1078             configuration.lldb_platform_name)
1079         if not lldb.remote_platform.IsValid():
1080             print(
1081                 "error: unable to create the LLDB platform named '%s'." %
1082                 (configuration.lldb_platform_name))
1083             exitTestSuite(1)
1084         if configuration.lldb_platform_url:
1085             # We must connect to a remote platform if a LLDB platform URL was
1086             # specified
1087             print(
1088                 "Connecting to remote platform '%s' at '%s'..." %
1089                 (configuration.lldb_platform_name, configuration.lldb_platform_url))
1090             platform_connect_options = lldb.SBPlatformConnectOptions(
1091                 configuration.lldb_platform_url)
1092             err = lldb.remote_platform.ConnectRemote(platform_connect_options)
1093             if err.Success():
1094                 print("Connected.")
1095             else:
1096                 print("error: failed to connect to remote platform using URL '%s': %s" % (
1097                     configuration.lldb_platform_url, err))
1098                 exitTestSuite(1)
1099         else:
1100             configuration.lldb_platform_url = None
1101
1102     platform_changes = setDefaultTripleForPlatform()
1103     first = True
1104     for key in platform_changes:
1105         if first:
1106             print("Environment variables setup for platform support:")
1107             first = False
1108         print("%s = %s" % (key, platform_changes[key]))
1109
1110     if configuration.lldb_platform_working_dir:
1111         print("Setting remote platform working directory to '%s'..." %
1112               (configuration.lldb_platform_working_dir))
1113         lldb.remote_platform.SetWorkingDirectory(
1114             configuration.lldb_platform_working_dir)
1115         lldb.DBG.SetSelectedPlatform(lldb.remote_platform)
1116     else:
1117         lldb.remote_platform = None
1118         configuration.lldb_platform_working_dir = None
1119         configuration.lldb_platform_url = None
1120
1121     target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
1122
1123     # Don't do debugserver tests on everything except OS X.
1124     configuration.dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform
1125
1126     # Don't do lldb-server (llgs) tests on anything except Linux.
1127     configuration.dont_do_llgs_test = not ("linux" in target_platform)
1128
1129     #
1130     # Walk through the testdirs while collecting tests.
1131     #
1132     for testdir in configuration.testdirs:
1133         for (dirpath, dirnames, filenames) in os.walk(testdir):
1134             visit('Test', dirpath, filenames)
1135
1136     #
1137     # Now that we have loaded all the test cases, run the whole test suite.
1138     #
1139
1140     # Turn on lldb loggings if necessary.
1141     lldbLoggings()
1142
1143     # Disable default dynamic types for testing purposes
1144     disabledynamics()
1145
1146     # Install the control-c handler.
1147     unittest2.signals.installHandler()
1148
1149     # If sdir_name is not specified through the '-s sdir_name' option, get a
1150     # timestamp string and export it as LLDB_SESSION_DIR environment var.  This will
1151     # be used when/if we want to dump the session info of individual test cases
1152     # later on.
1153     #
1154     # See also TestBase.dumpSessionInfo() in lldbtest.py.
1155     import datetime
1156     # The windows platforms don't like ':' in the pathname.
1157     timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1158     if not configuration.sdir_name:
1159         configuration.sdir_name = timestamp_started
1160     os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(
1161         os.getcwd(), configuration.sdir_name)
1162
1163     sys.stderr.write(
1164         "\nSession logs for test failures/errors/unexpected successes"
1165         " will go into directory '%s'\n" %
1166         configuration.sdir_name)
1167     sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
1168
1169     if not os.path.isdir(configuration.sdir_name):
1170         try:
1171             os.mkdir(configuration.sdir_name)
1172         except OSError as exception:
1173             if exception.errno != errno.EEXIST:
1174                 raise
1175
1176     #
1177     # Invoke the default TextTestRunner to run the test suite, possibly iterating
1178     # over different configurations.
1179     #
1180
1181     iterArchs = False
1182     iterCompilers = False
1183
1184     if isinstance(configuration.archs, list) and len(configuration.archs) >= 1:
1185         iterArchs = True
1186
1187     #
1188     # Add some intervention here to sanity check that the compilers requested are sane.
1189     # If found not to be an executable program, the invalid one is dropped
1190     # from the list.
1191     for i in range(len(configuration.compilers)):
1192         c = configuration.compilers[i]
1193         if which(c):
1194             continue
1195         else:
1196             if sys.platform.startswith("darwin"):
1197                 pipe = subprocess.Popen(
1198                     ['xcrun', '-find', c], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1199                 cmd_output = pipe.stdout.read()
1200                 if cmd_output:
1201                     if "not found" in cmd_output:
1202                         print("dropping %s from the compilers used" % c)
1203                         configuration.compilers.remove(i)
1204                     else:
1205                         configuration.compilers[i] = cmd_output.split('\n')[0]
1206                         print(
1207                             "'xcrun -find %s' returning %s" %
1208                             (c, configuration.compilers[i]))
1209
1210     if not configuration.parsable:
1211         print("compilers=%s" % str(configuration.compilers))
1212
1213     if not configuration.compilers or len(configuration.compilers) == 0:
1214         print("No eligible compiler found, exiting.")
1215         exitTestSuite(1)
1216
1217     if isinstance(
1218         configuration.compilers,
1219         list) and len(
1220             configuration.compilers) >= 1:
1221         iterCompilers = True
1222
1223     # If we iterate on archs or compilers, there is a chance we want to split
1224     # stderr/stdout.
1225     if iterArchs or iterCompilers:
1226         old_stderr = sys.stderr
1227         old_stdout = sys.stdout
1228         new_stderr = None
1229         new_stdout = None
1230
1231     # Iterating over all possible architecture and compiler combinations.
1232     for ia in range(len(configuration.archs) if iterArchs else 1):
1233         archConfig = ""
1234         if iterArchs:
1235             os.environ["ARCH"] = configuration.archs[ia]
1236             archConfig = "arch=%s" % configuration.archs[ia]
1237         for ic in range(len(configuration.compilers) if iterCompilers else 1):
1238             if iterCompilers:
1239                 os.environ["CC"] = configuration.compilers[ic]
1240                 configString = "%s compiler=%s" % (
1241                     archConfig, configuration.compilers[ic])
1242             else:
1243                 configString = archConfig
1244
1245             if iterArchs or iterCompilers:
1246                 # Translate ' ' to '-' for pathname component.
1247                 if six.PY2:
1248                     import string
1249                     tbl = string.maketrans(' ', '-')
1250                 else:
1251                     tbl = str.maketrans(' ', '-')
1252                 configPostfix = configString.translate(tbl)
1253
1254                 # Output the configuration.
1255                 if not configuration.parsable:
1256                     sys.stderr.write("\nConfiguration: " + configString + "\n")
1257
1258             #print("sys.stderr name is", sys.stderr.name)
1259             #print("sys.stdout name is", sys.stdout.name)
1260
1261             # First, write out the number of collected test cases.
1262             if not configuration.parsable:
1263                 sys.stderr.write(configuration.separator + "\n")
1264                 sys.stderr.write(
1265                     "Collected %d test%s\n\n" %
1266                     (configuration.suite.countTestCases(),
1267                      configuration.suite.countTestCases() != 1 and "s" or ""))
1268
1269             if configuration.parsable:
1270                 v = 0
1271             else:
1272                 v = configuration.verbose
1273
1274             # Invoke the test runner.
1275             if configuration.count == 1:
1276                 result = unittest2.TextTestRunner(
1277                     stream=sys.stderr,
1278                     verbosity=v,
1279                     resultclass=test_result.LLDBTestResult).run(
1280                     configuration.suite)
1281             else:
1282                 # We are invoking the same test suite more than once.  In this case,
1283                 # mark __ignore_singleton__ flag as True so the signleton pattern is
1284                 # not enforced.
1285                 test_result.LLDBTestResult.__ignore_singleton__ = True
1286                 for i in range(configuration.count):
1287
1288                     result = unittest2.TextTestRunner(
1289                         stream=sys.stderr,
1290                         verbosity=v,
1291                         resultclass=test_result.LLDBTestResult).run(
1292                         configuration.suite)
1293
1294             configuration.failed = configuration.failed or not result.wasSuccessful()
1295
1296     if configuration.sdir_has_content and not configuration.parsable:
1297         sys.stderr.write(
1298             "Session logs for test failures/errors/unexpected successes"
1299             " can be found in directory '%s'\n" %
1300             configuration.sdir_name)
1301
1302     if configuration.useCategories and len(
1303             configuration.failuresPerCategory) > 0:
1304         sys.stderr.write("Failures per category:\n")
1305         for category in configuration.failuresPerCategory:
1306             sys.stderr.write(
1307                 "%s - %d\n" %
1308                 (category, configuration.failuresPerCategory[category]))
1309
1310     # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1311     # This should not be necessary now.
1312     if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
1313         print("Terminating Test suite...")
1314         subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1315
1316     # Exiting.
1317     exitTestSuite(configuration.failed)
1318
1319 if __name__ == "__main__":
1320     print(
1321         __file__ +
1322         " is for use as a module only.  It should not be run as a standalone script.")
1323     sys.exit(-1)