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