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