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