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