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