blob: aec1762a729ec3ea259f84da941dd5944e8e9873 [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 Turner19474e12015-11-03 19:20:39 +000022import sys
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
Todd Fialad8078ff2015-11-04 17:10:40 +0000925 default_formatter_name = "lldbsuite.test.test_results.XunitFormatter"
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000926 elif results_port:
927 # Connect to the specified localhost port.
928 results_file_object, cleanup_func = createSocketToLocalPort(
929 results_port)
Todd Fialad8078ff2015-11-04 17:10:40 +0000930 default_formatter_name = "lldbsuite.test.test_results.RawPickledFormatter"
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000931
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
Zachary Turnerbbc5b462015-11-04 01:03:47 +00001150 lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001151
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:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001233 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
1234
1235 if name in all_tests:
1236 raise Exception("Found multiple tests with the name %s" % name)
1237 all_tests.add(name)
1238
1239 # Try to match the regexp pattern, if specified.
1240 if regexp:
1241 import re
1242 if re.search(regexp, name):
1243 #print("Filename: '%s' matches pattern: '%s'" % (name, regexp))
1244 pass
1245 else:
1246 #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp))
1247 continue
1248
1249 # We found a match for our test. Add it to the suite.
1250
1251 # Update the sys.path first.
1252 if not sys.path.count(dir):
1253 sys.path.insert(0, dir)
1254 base = os.path.splitext(name)[0]
1255
1256 # Thoroughly check the filterspec against the base module and admit
1257 # the (base, filterspec) combination only when it makes sense.
1258 filterspec = None
1259 for filterspec in filters:
1260 # Optimistically set the flag to True.
1261 filtered = True
1262 module = __import__(base)
1263 parts = filterspec.split('.')
1264 obj = module
1265 for part in parts:
1266 try:
1267 parent, obj = obj, getattr(obj, part)
1268 except AttributeError:
1269 # The filterspec has failed.
1270 filtered = False
1271 break
1272
1273 # If filtered, we have a good filterspec. Add it.
1274 if filtered:
1275 #print("adding filter spec %s to module %s" % (filterspec, module))
1276 suite.addTests(
1277 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
1278 continue
1279
1280 # Forgo this module if the (base, filterspec) combo is invalid
1281 # and no '-g' option is specified
1282 if filters and fs4all and not filtered:
1283 continue
1284
1285 # Add either the filtered test case(s) (which is done before) or the entire test class.
1286 if not filterspec or not filtered:
1287 # A simple case of just the module name. Also the failover case
1288 # from the filterspec branch when the (base, filterspec) combo
1289 # doesn't make sense.
1290 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
1291
1292
1293def disabledynamics():
1294 import lldb
1295 ci = lldb.DBG.GetCommandInterpreter()
1296 res = lldb.SBCommandReturnObject()
1297 ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False)
1298 if not res.Succeeded():
1299 raise Exception('disabling dynamic type support failed')
1300
1301def lldbLoggings():
1302 import lldb
1303 """Check and do lldb loggings if necessary."""
1304
1305 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1306 # defined. Use ${LLDB_LOG} to specify the log file.
1307 ci = lldb.DBG.GetCommandInterpreter()
1308 res = lldb.SBCommandReturnObject()
1309 if ("LLDB_LOG" in os.environ):
1310 open(os.environ["LLDB_LOG"], 'w').close()
1311 if ("LLDB_LOG_OPTION" in os.environ):
1312 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1313 else:
1314 lldb_log_option = "event process expr state api"
1315 ci.HandleCommand(
1316 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
1317 res)
1318 if not res.Succeeded():
1319 raise Exception('log enable failed (check LLDB_LOG env variable)')
1320
1321 if ("LLDB_LINUX_LOG" in os.environ):
1322 open(os.environ["LLDB_LINUX_LOG"], 'w').close()
1323 if ("LLDB_LINUX_LOG_OPTION" in os.environ):
1324 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"]
1325 else:
1326 lldb_log_option = "event process expr state api"
1327 ci.HandleCommand(
1328 "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option,
1329 res)
1330 if not res.Succeeded():
1331 raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)')
1332
1333 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1334 # Use ${GDB_REMOTE_LOG} to specify the log file.
1335 if ("GDB_REMOTE_LOG" in os.environ):
1336 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1337 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1338 else:
1339 gdb_remote_log_option = "packets process"
1340 ci.HandleCommand(
1341 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
1342 + gdb_remote_log_option,
1343 res)
1344 if not res.Succeeded():
1345 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)')
1346
1347def getMyCommandLine():
1348 return ' '.join(sys.argv)
1349
1350# ======================================== #
1351# #
1352# Execution of the test driver starts here #
1353# #
1354# ======================================== #
1355
1356def checkDsymForUUIDIsNotOn():
1357 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1358 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1359 cmd_output = pipe.stdout.read()
1360 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
1361 print("%s =>" % ' '.join(cmd))
1362 print(cmd_output)
1363 print("Disable automatic lookup and caching of dSYMs before running the test suite!")
1364 print("Exiting...")
1365 sys.exit(0)
1366
1367def exitTestSuite(exitCode = None):
1368 import lldb
1369 lldb.SBDebugger.Terminate()
1370 if exitCode:
1371 sys.exit(exitCode)
1372
1373
1374def isMultiprocessTestRunner():
1375 # We're not multiprocess when we're either explicitly
1376 # the inferior (as specified by the multiprocess test
1377 # runner) OR we've been told to skip using the multiprocess
1378 # test runner
1379 return not (is_inferior_test_runner or no_multiprocess_test_runner)
1380
Enrico Granata5f92a132015-11-05 00:46:25 +00001381def getVersionForSDK(sdk):
1382 sdk = str.lower(sdk)
1383 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1384 basename = os.path.basename(full_path)
1385 basename = os.path.splitext(basename)[0]
1386 basename = str.lower(basename)
1387 ver = basename.replace(sdk, '')
1388 return ver
1389
1390def getPathForSDK(sdk):
1391 sdk = str.lower(sdk)
1392 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
1393 if os.path.exists(full_path): return full_path
1394 return None
1395
1396def setDefaultTripleForPlatform():
1397 if lldb_platform_name == 'ios-simulator':
1398 triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator'))
1399 os.environ['TRIPLE'] = triple_str
1400 return {'TRIPLE':triple_str}
1401 return {}
1402
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001403def run_suite():
1404 global just_do_benchmarks_test
1405 global dont_do_dsym_test
1406 global dont_do_dwarf_test
1407 global dont_do_dwo_test
1408 global blacklist
1409 global blacklistConfig
1410 global categoriesList
1411 global validCategories
1412 global useCategories
1413 global skipCategories
1414 global lldbFrameworkPath
1415 global configFile
1416 global archs
1417 global compilers
1418 global count
1419 global dumpSysPath
1420 global bmExecutable
1421 global bmBreakpointSpec
1422 global bmIterationCount
1423 global failed
1424 global failfast
1425 global filters
1426 global fs4all
1427 global ignore
1428 global progress_bar
1429 global runHooks
1430 global skip_build_and_cleanup
1431 global skip_long_running_test
1432 global noHeaders
1433 global parsable
1434 global regexp
1435 global rdir
1436 global sdir_name
1437 global svn_silent
1438 global verbose
1439 global testdirs
1440 global lldb_platform_name
1441 global lldb_platform_url
1442 global lldb_platform_working_dir
1443 global setCrashInfoHook
1444 global is_inferior_test_runner
1445 global multiprocess_test_subdir
1446 global num_threads
1447 global output_on_success
1448 global no_multiprocess_test_runner
1449 global test_runner_name
1450 global results_filename
1451 global results_formatter_name
1452 global results_formatter_options
1453 global results_port
1454
1455 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1456 # does not exist before proceeding to running the test suite.
1457 if sys.platform.startswith("darwin"):
1458 checkDsymForUUIDIsNotOn()
1459
1460 #
1461 # Start the actions by first parsing the options while setting up the test
1462 # directories, followed by setting up the search paths for lldb utilities;
1463 # then, we walk the directory trees and collect the tests into our test suite.
1464 #
1465 parseOptionsAndInitTestdirs()
1466
1467 # Setup test results (test results formatter and output handling).
1468 setupTestResults()
1469
1470 # If we are running as the multiprocess test runner, kick off the
1471 # multiprocess test runner here.
1472 if isMultiprocessTestRunner():
1473 import dosep
1474 dosep.main(output_on_success, num_threads, multiprocess_test_subdir,
1475 test_runner_name, results_formatter_object)
1476 raise Exception("should never get here")
1477 elif is_inferior_test_runner:
1478 # Shut off Ctrl-C processing in inferiors. The parallel
1479 # test runner handles this more holistically.
1480 signal.signal(signal.SIGINT, signal.SIG_IGN)
1481
1482 setupSysPath()
1483 setupCrashInfoHook()
1484
1485 #
1486 # If '-l' is specified, do not skip the long running tests.
1487 if not skip_long_running_test:
1488 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1489
1490 # For the time being, let's bracket the test runner within the
1491 # lldb.SBDebugger.Initialize()/Terminate() pair.
1492 import lldb
1493
1494 # Create a singleton SBDebugger in the lldb namespace.
1495 lldb.DBG = lldb.SBDebugger.Create()
1496
1497 if lldb_platform_name:
1498 print("Setting up remote platform '%s'" % (lldb_platform_name))
1499 lldb.remote_platform = lldb.SBPlatform(lldb_platform_name)
Enrico Granata5f92a132015-11-05 00:46:25 +00001500 lldb.remote_platform_name = lldb_platform_name
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001501 if not lldb.remote_platform.IsValid():
1502 print("error: unable to create the LLDB platform named '%s'." % (lldb_platform_name))
1503 exitTestSuite(1)
1504 if lldb_platform_url:
1505 # We must connect to a remote platform if a LLDB platform URL was specified
1506 print("Connecting to remote platform '%s' at '%s'..." % (lldb_platform_name, lldb_platform_url))
1507 lldb.platform_url = lldb_platform_url
1508 platform_connect_options = lldb.SBPlatformConnectOptions(lldb_platform_url)
1509 err = lldb.remote_platform.ConnectRemote(platform_connect_options)
1510 if err.Success():
1511 print("Connected.")
1512 else:
1513 print("error: failed to connect to remote platform using URL '%s': %s" % (lldb_platform_url, err))
1514 exitTestSuite(1)
1515 else:
1516 lldb.platform_url = None
1517
Enrico Granata5f92a132015-11-05 00:46:25 +00001518 platform_changes = setDefaultTripleForPlatform()
1519 first = True
1520 for key in platform_changes:
1521 if first:
1522 print("Environment variables setup for platform support:")
1523 first = False
1524 print("%s = %s" % (key,platform_changes[key]))
1525
1526 if lldb_platform_working_dir:
1527 print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir))
1528 lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001529 lldb.remote_platform_working_dir = lldb_platform_working_dir
1530 lldb.DBG.SetSelectedPlatform(lldb.remote_platform)
1531 else:
1532 lldb.remote_platform = None
1533 lldb.remote_platform_working_dir = None
1534 lldb.platform_url = None
1535
1536 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
1537
1538 # By default, both dsym, dwarf and dwo tests are performed.
1539 # Use @dsym_test, @dwarf_test or @dwo_test decorators, defined in lldbtest.py, to mark a test as
1540 # a dsym, dwarf or dwo test. Use '-N dsym', '-N dwarf' or '-N dwo' to exclude dsym, dwarf or
1541 # dwo tests from running.
1542 dont_do_dsym_test = dont_do_dsym_test or any(platform in target_platform for platform in ["linux", "freebsd", "windows"])
1543 dont_do_dwo_test = dont_do_dwo_test or any(platform in target_platform for platform in ["darwin", "macosx", "ios"])
1544
1545 # Don't do debugserver tests on everything except OS X.
1546 dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform
1547
1548 # Don't do lldb-server (llgs) tests on anything except Linux.
1549 dont_do_llgs_test = not ("linux" in target_platform)
1550
1551 #
1552 # Walk through the testdirs while collecting tests.
1553 #
1554 for testdir in testdirs:
Zachary Turnere6ba0532015-11-05 01:33:54 +00001555 for (dirpath, dirnames, filenames) in os.walk(testdir):
1556 visit('Test', dirpath, filenames)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001557
1558 #
1559 # Now that we have loaded all the test cases, run the whole test suite.
1560 #
1561
1562 # Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
1563 lldb.blacklist = blacklist
1564
1565 # The pre_flight and post_flight come from reading a config file.
1566 lldb.pre_flight = pre_flight
1567 lldb.post_flight = post_flight
1568 def getsource_if_available(obj):
1569 """
1570 Return the text of the source code for an object if available. Otherwise,
1571 a print representation is returned.
1572 """
1573 import inspect
1574 try:
1575 return inspect.getsource(obj)
1576 except:
1577 return repr(obj)
1578
1579 if not noHeaders:
1580 print("lldb.pre_flight:", getsource_if_available(lldb.pre_flight))
1581 print("lldb.post_flight:", getsource_if_available(lldb.post_flight))
1582
1583 # If either pre_flight or post_flight is defined, set lldb.test_remote to True.
1584 if lldb.pre_flight or lldb.post_flight:
1585 lldb.test_remote = True
1586 else:
1587 lldb.test_remote = False
1588
1589 # So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables.
1590 lldb.lldbtest_remote_sandbox = lldbtest_remote_sandbox
1591 lldb.lldbtest_remote_sandboxed_executable = None
1592 lldb.lldbtest_remote_shell_template = lldbtest_remote_shell_template
1593
1594 # Put all these test decorators in the lldb namespace.
1595 lldb.just_do_benchmarks_test = just_do_benchmarks_test
1596 lldb.dont_do_dsym_test = dont_do_dsym_test
1597 lldb.dont_do_dwarf_test = dont_do_dwarf_test
1598 lldb.dont_do_dwo_test = dont_do_dwo_test
1599 lldb.dont_do_debugserver_test = dont_do_debugserver_test
1600 lldb.dont_do_llgs_test = dont_do_llgs_test
1601
1602 # Do we need to skip build and cleanup?
1603 lldb.skip_build_and_cleanup = skip_build_and_cleanup
1604
1605 # Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
1606 lldb.bmExecutable = bmExecutable
1607 lldb.bmBreakpointSpec = bmBreakpointSpec
1608 lldb.bmIterationCount = bmIterationCount
1609
1610 # And don't forget the runHooks!
1611 lldb.runHooks = runHooks
1612
1613 # Turn on lldb loggings if necessary.
1614 lldbLoggings()
1615
1616 # Disable default dynamic types for testing purposes
1617 disabledynamics()
1618
1619 # Install the control-c handler.
1620 unittest2.signals.installHandler()
1621
1622 # If sdir_name is not specified through the '-s sdir_name' option, get a
1623 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1624 # be used when/if we want to dump the session info of individual test cases
1625 # later on.
1626 #
1627 # See also TestBase.dumpSessionInfo() in lldbtest.py.
1628 import datetime
1629 # The windows platforms don't like ':' in the pathname.
1630 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1631 if not sdir_name:
1632 sdir_name = timestamp_started
1633 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
1634
1635 if not noHeaders:
1636 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1637 " will go into directory '%s'\n" % sdir_name)
1638 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
1639
1640 if not os.path.isdir(sdir_name):
1641 try:
1642 os.mkdir(sdir_name)
1643 except OSError as exception:
1644 if exception.errno != errno.EEXIST:
1645 raise
1646 where_to_save_session = os.getcwd()
1647 fname = os.path.join(sdir_name, "TestStarted-%d" % os.getpid())
1648 with open(fname, "w") as f:
1649 print("Test started at: %s\n" % timestamp_started, file=f)
1650 print(svn_info, file=f)
1651 print("Command invoked: %s\n" % getMyCommandLine(), file=f)
1652
1653 #
1654 # Invoke the default TextTestRunner to run the test suite, possibly iterating
1655 # over different configurations.
1656 #
1657
1658 iterArchs = False
1659 iterCompilers = False
1660
1661 if not archs and "archs" in config:
1662 archs = config["archs"]
1663
1664 if isinstance(archs, list) and len(archs) >= 1:
1665 iterArchs = True
1666
1667 if not compilers and "compilers" in config:
1668 compilers = config["compilers"]
1669
1670 #
1671 # Add some intervention here to sanity check that the compilers requested are sane.
1672 # If found not to be an executable program, the invalid one is dropped from the list.
1673 for i in range(len(compilers)):
1674 c = compilers[i]
1675 if which(c):
1676 continue
1677 else:
1678 if sys.platform.startswith("darwin"):
1679 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1680 cmd_output = pipe.stdout.read()
1681 if cmd_output:
1682 if "not found" in cmd_output:
1683 print("dropping %s from the compilers used" % c)
1684 compilers.remove(i)
1685 else:
1686 compilers[i] = cmd_output.split('\n')[0]
1687 print("'xcrun -find %s' returning %s" % (c, compilers[i]))
1688
1689 if not parsable:
1690 print("compilers=%s" % str(compilers))
1691
1692 if not compilers or len(compilers) == 0:
1693 print("No eligible compiler found, exiting.")
1694 exitTestSuite(1)
1695
1696 if isinstance(compilers, list) and len(compilers) >= 1:
1697 iterCompilers = True
1698
1699 # Make a shallow copy of sys.path, we need to manipulate the search paths later.
1700 # This is only necessary if we are relocated and with different configurations.
1701 if rdir:
1702 old_sys_path = sys.path[:]
1703 # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1704 if iterArchs or iterCompilers:
1705 old_stderr = sys.stderr
1706 old_stdout = sys.stdout
1707 new_stderr = None
1708 new_stdout = None
1709
1710 # Iterating over all possible architecture and compiler combinations.
1711 for ia in range(len(archs) if iterArchs else 1):
1712 archConfig = ""
1713 if iterArchs:
1714 os.environ["ARCH"] = archs[ia]
1715 archConfig = "arch=%s" % archs[ia]
1716 for ic in range(len(compilers) if iterCompilers else 1):
1717 if iterCompilers:
1718 os.environ["CC"] = compilers[ic]
1719 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1720 else:
1721 configString = archConfig
1722
1723 if iterArchs or iterCompilers:
1724 # Translate ' ' to '-' for pathname component.
1725 from string import maketrans
1726 tbl = maketrans(' ', '-')
1727 configPostfix = configString.translate(tbl)
1728
1729 # Check whether we need to split stderr/stdout into configuration
1730 # specific files.
1731 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1732 if new_stderr:
1733 new_stderr.close()
1734 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1735 sys.stderr = new_stderr
1736 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1737 if new_stdout:
1738 new_stdout.close()
1739 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1740 sys.stdout = new_stdout
1741
1742 # If we specified a relocated directory to run the test suite, do
1743 # the extra housekeeping to copy the testdirs to a configStringified
1744 # directory and to update sys.path before invoking the test runner.
1745 # The purpose is to separate the configuration-specific directories
1746 # from each other.
1747 if rdir:
1748 from shutil import copytree, rmtree, ignore_patterns
1749
1750 newrdir = "%s.%s" % (rdir, configPostfix)
1751
1752 # Copy the tree to a new directory with postfix name configPostfix.
1753 if os.path.exists(newrdir):
1754 rmtree(newrdir)
1755 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1756
1757 # Update the LLDB_TEST environment variable to reflect new top
1758 # level test directory.
1759 #
1760 # See also lldbtest.TestBase.setUpClass(cls).
1761 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1762 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1763 else:
1764 os.environ["LLDB_TEST"] = newrdir
1765
1766 # And update the Python search paths for modules.
1767 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1768
1769 # Output the configuration.
1770 if not parsable:
1771 sys.stderr.write("\nConfiguration: " + configString + "\n")
1772
1773 #print("sys.stderr name is", sys.stderr.name)
1774 #print("sys.stdout name is", sys.stdout.name)
1775
1776 # First, write out the number of collected test cases.
1777 if not parsable:
1778 sys.stderr.write(separator + "\n")
1779 sys.stderr.write("Collected %d test%s\n\n"
1780 % (suite.countTestCases(),
1781 suite.countTestCases() != 1 and "s" or ""))
1782
1783 class LLDBTestResult(unittest2.TextTestResult):
1784 """
1785 Enforce a singleton pattern to allow introspection of test progress.
1786
1787 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1788 to enable each test instance to track its failure/error status. It
1789 is used in the LLDB test framework to emit detailed trace messages
1790 to a log file for easier human inspection of test failures/errors.
1791 """
1792 __singleton__ = None
1793 __ignore_singleton__ = False
1794
1795 @staticmethod
1796 def getTerminalSize():
1797 import os
1798 env = os.environ
1799 def ioctl_GWINSZ(fd):
1800 try:
1801 import fcntl, termios, struct, os
1802 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1803 '1234'))
1804 except:
1805 return
1806 return cr
1807 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1808 if not cr:
1809 try:
1810 fd = os.open(os.ctermid(), os.O_RDONLY)
1811 cr = ioctl_GWINSZ(fd)
1812 os.close(fd)
1813 except:
1814 pass
1815 if not cr:
1816 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1817 return int(cr[1]), int(cr[0])
1818
1819 def __init__(self, *args):
1820 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
1821 raise Exception("LLDBTestResult instantiated more than once")
1822 super(LLDBTestResult, self).__init__(*args)
1823 LLDBTestResult.__singleton__ = self
1824 # Now put this singleton into the lldb module namespace.
1825 lldb.test_result = self
1826 # Computes the format string for displaying the counter.
1827 global suite
1828 counterWidth = len(str(suite.countTestCases()))
1829 self.fmt = "%" + str(counterWidth) + "d: "
1830 self.indentation = ' ' * (counterWidth + 2)
1831 # This counts from 1 .. suite.countTestCases().
1832 self.counter = 0
1833 (width, height) = LLDBTestResult.getTerminalSize()
1834 self.progressbar = None
1835 global progress_bar
1836 if width > 10 and not parsable and progress_bar:
1837 try:
1838 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
1839 except:
1840 self.progressbar = None
1841 self.results_formatter = results_formatter_object
1842
1843 def _config_string(self, test):
1844 compiler = getattr(test, "getCompiler", None)
1845 arch = getattr(test, "getArchitecture", None)
1846 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
1847
1848 def _exc_info_to_string(self, err, test):
1849 """Overrides superclass TestResult's method in order to append
1850 our test config info string to the exception info string."""
1851 if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"):
1852 return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1853 test.getArchitecture(),
1854 test.getCompiler())
1855 else:
1856 return super(LLDBTestResult, self)._exc_info_to_string(err, test)
1857
1858 def getDescription(self, test):
1859 doc_first_line = test.shortDescription()
1860 if self.descriptions and doc_first_line:
1861 return '\n'.join((str(test), self.indentation + doc_first_line))
1862 else:
1863 return str(test)
1864
1865 def getCategoriesForTest(self,test):
1866 if hasattr(test,"_testMethodName"):
1867 test_method = getattr(test,"_testMethodName")
1868 test_method = getattr(test,test_method)
1869 else:
1870 test_method = None
1871 if test_method != None and hasattr(test_method,"getCategories"):
1872 test_categories = test_method.getCategories(test)
1873 elif hasattr(test,"getCategories"):
1874 test_categories = test.getCategories()
1875 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1876 test_categories = test.__self__.getCategories()
1877 else:
1878 test_categories = []
1879 if test_categories == None:
1880 test_categories = []
1881 return test_categories
1882
1883 def hardMarkAsSkipped(self,test):
1884 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1885 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1886 test.__class__.__unittest_skip__ = True
1887 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1888
1889 def startTest(self, test):
1890 if shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)):
1891 self.hardMarkAsSkipped(test)
1892 global setCrashInfoHook
1893 setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__)))
1894 self.counter += 1
1895 #if self.counter == 4:
1896 # import crashinfo
1897 # crashinfo.testCrashReporterDescription(None)
1898 test.test_number = self.counter
1899 if self.showAll:
1900 self.stream.write(self.fmt % self.counter)
1901 super(LLDBTestResult, self).startTest(test)
1902 if self.results_formatter:
1903 self.results_formatter.handle_event(
1904 EventBuilder.event_for_start(test))
1905
1906 def addSuccess(self, test):
1907 global parsable
1908 super(LLDBTestResult, self).addSuccess(test)
1909 if parsable:
1910 self.stream.write("PASS: 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_success(test))
1914
1915 def addError(self, test, err):
1916 global sdir_has_content
1917 global parsable
1918 sdir_has_content = True
1919 super(LLDBTestResult, self).addError(test, err)
1920 method = getattr(test, "markError", None)
1921 if method:
1922 method()
1923 if parsable:
1924 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1925 if self.results_formatter:
1926 self.results_formatter.handle_event(
1927 EventBuilder.event_for_error(test, err))
1928
1929 def addCleanupError(self, test, err):
1930 global sdir_has_content
1931 global parsable
1932 sdir_has_content = True
1933 super(LLDBTestResult, self).addCleanupError(test, err)
1934 method = getattr(test, "markCleanupError", None)
1935 if method:
1936 method()
1937 if parsable:
1938 self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1939 if self.results_formatter:
1940 self.results_formatter.handle_event(
1941 EventBuilder.event_for_cleanup_error(
1942 test, err))
1943
1944 def addFailure(self, test, err):
1945 global sdir_has_content
1946 global failuresPerCategory
1947 global parsable
1948 sdir_has_content = True
1949 super(LLDBTestResult, self).addFailure(test, err)
1950 method = getattr(test, "markFailure", None)
1951 if method:
1952 method()
1953 if parsable:
1954 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1955 if useCategories:
1956 test_categories = self.getCategoriesForTest(test)
1957 for category in test_categories:
1958 if category in failuresPerCategory:
1959 failuresPerCategory[category] = failuresPerCategory[category] + 1
1960 else:
1961 failuresPerCategory[category] = 1
1962 if self.results_formatter:
1963 self.results_formatter.handle_event(
1964 EventBuilder.event_for_failure(test, err))
1965
1966
1967 def addExpectedFailure(self, test, err, bugnumber):
1968 global sdir_has_content
1969 global parsable
1970 sdir_has_content = True
1971 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
1972 method = getattr(test, "markExpectedFailure", None)
1973 if method:
1974 method(err, bugnumber)
1975 if parsable:
1976 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1977 if self.results_formatter:
1978 self.results_formatter.handle_event(
1979 EventBuilder.event_for_expected_failure(
1980 test, err, bugnumber))
1981
1982 def addSkip(self, test, reason):
1983 global sdir_has_content
1984 global parsable
1985 sdir_has_content = True
1986 super(LLDBTestResult, self).addSkip(test, reason)
1987 method = getattr(test, "markSkippedTest", None)
1988 if method:
1989 method()
1990 if parsable:
1991 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
1992 if self.results_formatter:
1993 self.results_formatter.handle_event(
1994 EventBuilder.event_for_skip(test, reason))
1995
1996 def addUnexpectedSuccess(self, test, bugnumber):
1997 global sdir_has_content
1998 global parsable
1999 sdir_has_content = True
2000 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
2001 method = getattr(test, "markUnexpectedSuccess", None)
2002 if method:
2003 method(bugnumber)
2004 if parsable:
2005 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
2006 if self.results_formatter:
2007 self.results_formatter.handle_event(
2008 EventBuilder.event_for_unexpected_success(
2009 test, bugnumber))
2010
2011
2012 if parsable:
2013 v = 0
2014 elif progress_bar:
2015 v = 1
2016 else:
2017 v = verbose
2018
2019 # Invoke the test runner.
2020 if count == 1:
2021 result = unittest2.TextTestRunner(stream=sys.stderr,
2022 verbosity=v,
2023 failfast=failfast,
2024 resultclass=LLDBTestResult).run(suite)
2025 else:
2026 # We are invoking the same test suite more than once. In this case,
2027 # mark __ignore_singleton__ flag as True so the signleton pattern is
2028 # not enforced.
2029 LLDBTestResult.__ignore_singleton__ = True
2030 for i in range(count):
2031
2032 result = unittest2.TextTestRunner(stream=sys.stderr,
2033 verbosity=v,
2034 failfast=failfast,
2035 resultclass=LLDBTestResult).run(suite)
2036
2037 failed = failed or not result.wasSuccessful()
2038
2039 if sdir_has_content and not parsable:
2040 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
2041 " can be found in directory '%s'\n" % sdir_name)
2042
2043 if useCategories and len(failuresPerCategory) > 0:
2044 sys.stderr.write("Failures per category:\n")
2045 for category in failuresPerCategory:
2046 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
2047
2048 os.chdir(where_to_save_session)
2049 fname = os.path.join(sdir_name, "TestFinished-%d" % os.getpid())
2050 with open(fname, "w") as f:
2051 print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f)
2052
2053 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
2054 # This should not be necessary now.
2055 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
2056 print("Terminating Test suite...")
2057 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
2058
2059 # Exiting.
2060 exitTestSuite(failed)
2061
2062if __name__ == "__main__":
Zachary Turner7d564542015-11-02 19:19:49 +00002063 print(__file__ + " is for use as a module only. It should not be run as a standalone script.")
2064 sys.exit(-1)