1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TesBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7The subclass should override the attribute mydir in order for the python runtime 8to locate the individual test cases when running as part of a large test suite 9or when running each test case as a separate python invocation. 10 11./dotest.py provides a test driver which sets up the environment to run the 12entire of part of the test suite . Example: 13 14# Exercises the test suite in the types directory.... 15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types 16... 17 18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' 19Command invoked: python ./dotest.py -A x86_64 types 20compilers=['clang'] 21 22Configuration: arch=x86_64 compiler=clang 23---------------------------------------------------------------------- 24Collected 72 tests 25 26........................................................................ 27---------------------------------------------------------------------- 28Ran 72 tests in 135.468s 29 30OK 31$ 32""" 33 34from __future__ import print_function 35from __future__ import absolute_import 36 37# System modules 38import abc 39import collections 40import gc 41import glob 42import os, sys, traceback 43import os.path 44import re 45import signal 46from subprocess import * 47import time 48import types 49 50# Third-party modules 51import unittest2 52from six import add_metaclass 53from six import StringIO as SixStringIO 54from six.moves.urllib import parse as urlparse 55import six 56 57# LLDB modules 58import lldb 59from . import lldbtest_config 60from . import lldbutil 61from . import test_categories 62 63# dosep.py starts lots and lots of dotest instances 64# This option helps you find if two (or more) dotest instances are using the same 65# directory at the same time 66# Enable it to cause test failures and stderr messages if dotest instances try to run in 67# the same directory simultaneously 68# it is disabled by default because it litters the test directories with ".dirlock" files 69debug_confirm_directory_exclusivity = False 70 71# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 72# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options. 73 74# By default, traceAlways is False. 75if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES": 76 traceAlways = True 77else: 78 traceAlways = False 79 80# By default, doCleanup is True. 81if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO": 82 doCleanup = False 83else: 84 doCleanup = True 85 86 87# 88# Some commonly used assert messages. 89# 90 91COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 92 93CURRENT_EXECUTABLE_SET = "Current executable set successfully" 94 95PROCESS_IS_VALID = "Process is valid" 96 97PROCESS_KILLED = "Process is killed successfully" 98 99PROCESS_EXITED = "Process exited successfully" 100 101PROCESS_STOPPED = "Process status should be stopped" 102 103RUN_SUCCEEDED = "Process is launched successfully" 104 105RUN_COMPLETED = "Process exited successfully" 106 107BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 108 109BREAKPOINT_CREATED = "Breakpoint created successfully" 110 111BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 112 113BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 114 115BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" 116 117BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" 118 119BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" 120 121MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 122 123OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 124 125SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 126 127STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 128 129STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 130 131STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 132 133STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 134 135STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 136 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 137 138STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 139 140STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 141 142STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 143 144STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 145 146STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 147 148DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 149 150VALID_BREAKPOINT = "Got a valid breakpoint" 151 152VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 153 154VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 155 156VALID_FILESPEC = "Got a valid filespec" 157 158VALID_MODULE = "Got a valid module" 159 160VALID_PROCESS = "Got a valid process" 161 162VALID_SYMBOL = "Got a valid symbol" 163 164VALID_TARGET = "Got a valid target" 165 166VALID_PLATFORM = "Got a valid platform" 167 168VALID_TYPE = "Got a valid type" 169 170VALID_VARIABLE = "Got a valid variable" 171 172VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 173 174WATCHPOINT_CREATED = "Watchpoint created successfully" 175 176def CMD_MSG(str): 177 '''A generic "Command '%s' returns successfully" message generator.''' 178 return "Command '%s' returns successfully" % str 179 180def COMPLETION_MSG(str_before, str_after): 181 '''A generic message generator for the completion mechanism.''' 182 return "'%s' successfully completes to '%s'" % (str_before, str_after) 183 184def EXP_MSG(str, exe): 185 '''A generic "'%s' returns expected result" message generator if exe. 186 Otherwise, it generates "'%s' matches expected result" message.''' 187 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches') 188 189def SETTING_MSG(setting): 190 '''A generic "Value of setting '%s' is correct" message generator.''' 191 return "Value of setting '%s' is correct" % setting 192 193def EnvArray(): 194 """Returns an env variable array from the os.environ map object.""" 195 return list(map(lambda k,v: k+"="+v, list(os.environ.keys()), list(os.environ.values()))) 196 197def line_number(filename, string_to_match): 198 """Helper function to return the line number of the first matched string.""" 199 with open(filename, 'r') as f: 200 for i, line in enumerate(f): 201 if line.find(string_to_match) != -1: 202 # Found our match. 203 return i+1 204 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename)) 205 206def pointer_size(): 207 """Return the pointer size of the host system.""" 208 import ctypes 209 a_pointer = ctypes.c_void_p(0xffff) 210 return 8 * ctypes.sizeof(a_pointer) 211 212def is_exe(fpath): 213 """Returns true if fpath is an executable.""" 214 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 215 216def which(program): 217 """Returns the full path to a program; None otherwise.""" 218 fpath, fname = os.path.split(program) 219 if fpath: 220 if is_exe(program): 221 return program 222 else: 223 for path in os.environ["PATH"].split(os.pathsep): 224 exe_file = os.path.join(path, program) 225 if is_exe(exe_file): 226 return exe_file 227 return None 228 229class recording(SixStringIO): 230 """ 231 A nice little context manager for recording the debugger interactions into 232 our session object. If trace flag is ON, it also emits the interactions 233 into the stderr. 234 """ 235 def __init__(self, test, trace): 236 """Create a SixStringIO instance; record the session obj and trace flag.""" 237 SixStringIO.__init__(self) 238 # The test might not have undergone the 'setUp(self)' phase yet, so that 239 # the attribute 'session' might not even exist yet. 240 self.session = getattr(test, "session", None) if test else None 241 self.trace = trace 242 243 def __enter__(self): 244 """ 245 Context management protocol on entry to the body of the with statement. 246 Just return the SixStringIO object. 247 """ 248 return self 249 250 def __exit__(self, type, value, tb): 251 """ 252 Context management protocol on exit from the body of the with statement. 253 If trace is ON, it emits the recordings into stderr. Always add the 254 recordings to our session object. And close the SixStringIO object, too. 255 """ 256 if self.trace: 257 print(self.getvalue(), file=sys.stderr) 258 if self.session: 259 print(self.getvalue(), file=self.session) 260 self.close() 261 262@add_metaclass(abc.ABCMeta) 263class _BaseProcess(object): 264 265 @abc.abstractproperty 266 def pid(self): 267 """Returns process PID if has been launched already.""" 268 269 @abc.abstractmethod 270 def launch(self, executable, args): 271 """Launches new process with given executable and args.""" 272 273 @abc.abstractmethod 274 def terminate(self): 275 """Terminates previously launched process..""" 276 277class _LocalProcess(_BaseProcess): 278 279 def __init__(self, trace_on): 280 self._proc = None 281 self._trace_on = trace_on 282 self._delayafterterminate = 0.1 283 284 @property 285 def pid(self): 286 return self._proc.pid 287 288 def launch(self, executable, args): 289 self._proc = Popen([executable] + args, 290 stdout = open(os.devnull) if not self._trace_on else None, 291 stdin = PIPE) 292 293 def terminate(self): 294 if self._proc.poll() == None: 295 # Terminate _proc like it does the pexpect 296 signals_to_try = [sig for sig in ['SIGHUP', 'SIGCONT', 'SIGINT'] if sig in dir(signal)] 297 for sig in signals_to_try: 298 try: 299 self._proc.send_signal(getattr(signal, sig)) 300 time.sleep(self._delayafterterminate) 301 if self._proc.poll() != None: 302 return 303 except ValueError: 304 pass # Windows says SIGINT is not a valid signal to send 305 self._proc.terminate() 306 time.sleep(self._delayafterterminate) 307 if self._proc.poll() != None: 308 return 309 self._proc.kill() 310 time.sleep(self._delayafterterminate) 311 312 def poll(self): 313 return self._proc.poll() 314 315class _RemoteProcess(_BaseProcess): 316 317 def __init__(self, install_remote): 318 self._pid = None 319 self._install_remote = install_remote 320 321 @property 322 def pid(self): 323 return self._pid 324 325 def launch(self, executable, args): 326 if self._install_remote: 327 src_path = executable 328 dst_path = lldbutil.append_to_process_working_directory(os.path.basename(executable)) 329 330 dst_file_spec = lldb.SBFileSpec(dst_path, False) 331 err = lldb.remote_platform.Install(lldb.SBFileSpec(src_path, True), dst_file_spec) 332 if err.Fail(): 333 raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (src_path, dst_path, err)) 334 else: 335 dst_path = executable 336 dst_file_spec = lldb.SBFileSpec(executable, False) 337 338 launch_info = lldb.SBLaunchInfo(args) 339 launch_info.SetExecutableFile(dst_file_spec, True) 340 launch_info.SetWorkingDirectory(lldb.remote_platform.GetWorkingDirectory()) 341 342 # Redirect stdout and stderr to /dev/null 343 launch_info.AddSuppressFileAction(1, False, True) 344 launch_info.AddSuppressFileAction(2, False, True) 345 346 err = lldb.remote_platform.Launch(launch_info) 347 if err.Fail(): 348 raise Exception("remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err)) 349 self._pid = launch_info.GetProcessID() 350 351 def terminate(self): 352 lldb.remote_platform.Kill(self._pid) 353 354# From 2.7's subprocess.check_output() convenience function. 355# Return a tuple (stdoutdata, stderrdata). 356def system(commands, **kwargs): 357 r"""Run an os command with arguments and return its output as a byte string. 358 359 If the exit code was non-zero it raises a CalledProcessError. The 360 CalledProcessError object will have the return code in the returncode 361 attribute and output in the output attribute. 362 363 The arguments are the same as for the Popen constructor. Example: 364 365 >>> check_output(["ls", "-l", "/dev/null"]) 366 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 367 368 The stdout argument is not allowed as it is used internally. 369 To capture standard error in the result, use stderr=STDOUT. 370 371 >>> check_output(["/bin/sh", "-c", 372 ... "ls -l non_existent_file ; exit 0"], 373 ... stderr=STDOUT) 374 'ls: non_existent_file: No such file or directory\n' 375 """ 376 377 # Assign the sender object to variable 'test' and remove it from kwargs. 378 test = kwargs.pop('sender', None) 379 380 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo'] 381 commandList = [' '.join(x) for x in commands] 382 output = "" 383 error = "" 384 for shellCommand in commandList: 385 if 'stdout' in kwargs: 386 raise ValueError('stdout argument not allowed, it will be overridden.') 387 if 'shell' in kwargs and kwargs['shell']==False: 388 raise ValueError('shell=False not allowed') 389 process = Popen(shellCommand, stdout=PIPE, stderr=PIPE, shell=True, **kwargs) 390 pid = process.pid 391 this_output, this_error = process.communicate() 392 retcode = process.poll() 393 394 # Enable trace on failure return while tracking down FreeBSD buildbot issues 395 trace = traceAlways 396 if not trace and retcode and sys.platform.startswith("freebsd"): 397 trace = True 398 399 with recording(test, trace) as sbuf: 400 print(file=sbuf) 401 print("os command:", shellCommand, file=sbuf) 402 print("with pid:", pid, file=sbuf) 403 print("stdout:", this_output, file=sbuf) 404 print("stderr:", this_error, file=sbuf) 405 print("retcode:", retcode, file=sbuf) 406 print(file=sbuf) 407 408 if retcode: 409 cmd = kwargs.get("args") 410 if cmd is None: 411 cmd = shellCommand 412 raise CalledProcessError(retcode, cmd) 413 output = output + this_output 414 error = error + this_error 415 return (output, error) 416 417def getsource_if_available(obj): 418 """ 419 Return the text of the source code for an object if available. Otherwise, 420 a print representation is returned. 421 """ 422 import inspect 423 try: 424 return inspect.getsource(obj) 425 except: 426 return repr(obj) 427 428def builder_module(): 429 if sys.platform.startswith("freebsd"): 430 return __import__("builder_freebsd") 431 return __import__("builder_" + sys.platform) 432 433def run_adb_command(cmd, device_id): 434 device_id_args = [] 435 if device_id: 436 device_id_args = ["-s", device_id] 437 full_cmd = ["adb"] + device_id_args + cmd 438 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE) 439 stdout, stderr = p.communicate() 440 return p.returncode, stdout, stderr 441 442def append_android_envs(dictionary): 443 if dictionary is None: 444 dictionary = {} 445 dictionary["OS"] = "Android" 446 if android_device_api() >= 16: 447 dictionary["PIE"] = 1 448 return dictionary 449 450def target_is_android(): 451 if not hasattr(target_is_android, 'result'): 452 triple = lldb.DBG.GetSelectedPlatform().GetTriple() 453 match = re.match(".*-.*-.*-android", triple) 454 target_is_android.result = match is not None 455 return target_is_android.result 456 457def android_device_api(): 458 if not hasattr(android_device_api, 'result'): 459 assert lldb.platform_url is not None 460 device_id = None 461 parsed_url = urlparse.urlparse(lldb.platform_url) 462 if parsed_url.scheme == "adb": 463 device_id = parsed_url.netloc.split(":")[0] 464 retcode, stdout, stderr = run_adb_command( 465 ["shell", "getprop", "ro.build.version.sdk"], device_id) 466 if retcode == 0: 467 android_device_api.result = int(stdout) 468 else: 469 raise LookupError( 470 ">>> Unable to determine the API level of the Android device.\n" 471 ">>> stdout:\n%s\n" 472 ">>> stderr:\n%s\n" % (stdout, stderr)) 473 return android_device_api.result 474 475# 476# Decorators for categorizing test cases. 477# 478from functools import wraps 479def add_test_categories(cat): 480 """Decorate an item with test categories""" 481 cat = test_categories.validate(cat, True) 482 def impl(func): 483 func.getCategories = lambda test: cat 484 return func 485 return impl 486 487def benchmarks_test(func): 488 """Decorate the item as a benchmarks test.""" 489 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 490 raise Exception("@benchmarks_test can only be used to decorate a test method") 491 @wraps(func) 492 def wrapper(self, *args, **kwargs): 493 if not lldb.just_do_benchmarks_test: 494 self.skipTest("benchmarks tests") 495 return func(self, *args, **kwargs) 496 497 # Mark this function as such to separate them from the regular tests. 498 wrapper.__benchmarks_test__ = True 499 return wrapper 500 501def no_debug_info_test(func): 502 """Decorate the item as a test what don't use any debug info. If this annotation is specified 503 then the test runner won't generate a separate test for each debug info format. """ 504 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 505 raise Exception("@no_debug_info_test can only be used to decorate a test method") 506 @wraps(func) 507 def wrapper(self, *args, **kwargs): 508 return func(self, *args, **kwargs) 509 510 # Mark this function as such to separate them from the regular tests. 511 wrapper.__no_debug_info_test__ = True 512 return wrapper 513 514def dsym_test(func): 515 """Decorate the item as a dsym test.""" 516 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 517 raise Exception("@dsym_test can only be used to decorate a test method") 518 @wraps(func) 519 def wrapper(self, *args, **kwargs): 520 if lldb.dont_do_dsym_test: 521 self.skipTest("dsym tests") 522 return func(self, *args, **kwargs) 523 524 # Mark this function as such to separate them from the regular tests. 525 wrapper.__dsym_test__ = True 526 return wrapper 527 528def dwarf_test(func): 529 """Decorate the item as a dwarf test.""" 530 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 531 raise Exception("@dwarf_test can only be used to decorate a test method") 532 @wraps(func) 533 def wrapper(self, *args, **kwargs): 534 if lldb.dont_do_dwarf_test: 535 self.skipTest("dwarf tests") 536 return func(self, *args, **kwargs) 537 538 # Mark this function as such to separate them from the regular tests. 539 wrapper.__dwarf_test__ = True 540 return wrapper 541 542def dwo_test(func): 543 """Decorate the item as a dwo test.""" 544 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 545 raise Exception("@dwo_test can only be used to decorate a test method") 546 @wraps(func) 547 def wrapper(self, *args, **kwargs): 548 if lldb.dont_do_dwo_test: 549 self.skipTest("dwo tests") 550 return func(self, *args, **kwargs) 551 552 # Mark this function as such to separate them from the regular tests. 553 wrapper.__dwo_test__ = True 554 return wrapper 555 556def debugserver_test(func): 557 """Decorate the item as a debugserver test.""" 558 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 559 raise Exception("@debugserver_test can only be used to decorate a test method") 560 @wraps(func) 561 def wrapper(self, *args, **kwargs): 562 if lldb.dont_do_debugserver_test: 563 self.skipTest("debugserver tests") 564 return func(self, *args, **kwargs) 565 566 # Mark this function as such to separate them from the regular tests. 567 wrapper.__debugserver_test__ = True 568 return wrapper 569 570def llgs_test(func): 571 """Decorate the item as a lldb-server test.""" 572 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 573 raise Exception("@llgs_test can only be used to decorate a test method") 574 @wraps(func) 575 def wrapper(self, *args, **kwargs): 576 if lldb.dont_do_llgs_test: 577 self.skipTest("llgs tests") 578 return func(self, *args, **kwargs) 579 580 # Mark this function as such to separate them from the regular tests. 581 wrapper.__llgs_test__ = True 582 return wrapper 583 584def not_remote_testsuite_ready(func): 585 """Decorate the item as a test which is not ready yet for remote testsuite.""" 586 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 587 raise Exception("@not_remote_testsuite_ready can only be used to decorate a test method") 588 @wraps(func) 589 def wrapper(self, *args, **kwargs): 590 if lldb.lldbtest_remote_sandbox or lldb.remote_platform: 591 self.skipTest("not ready for remote testsuite") 592 return func(self, *args, **kwargs) 593 594 # Mark this function as such to separate them from the regular tests. 595 wrapper.__not_ready_for_remote_testsuite_test__ = True 596 return wrapper 597 598def expectedFailure(expected_fn, bugnumber=None): 599 def expectedFailure_impl(func): 600 @wraps(func) 601 def wrapper(*args, **kwargs): 602 from unittest2 import case 603 self = args[0] 604 if expected_fn(self): 605 xfail_func = unittest2.expectedFailure(func) 606 xfail_func(*args, **kwargs) 607 else: 608 func(*args, **kwargs) 609 return wrapper 610 # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments 611 # return decorator in this case, so it will be used to decorating original method 612 if six.callable(bugnumber): 613 return expectedFailure_impl(bugnumber) 614 else: 615 return expectedFailure_impl 616 617# provide a function to xfail on defined oslist, compiler version, and archs 618# if none is specified for any argument, that argument won't be checked and thus means for all 619# for example, 620# @expectedFailureAll, xfail for all platform/compiler/arch, 621# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture 622# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 623def expectedFailureAll(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, triple=None, debug_info=None): 624 def fn(self): 625 return ((oslist is None or self.getPlatform() in oslist) and 626 (compiler is None or (compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version))) and 627 self.expectedArch(archs) and 628 (triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple())) and 629 (debug_info is None or self.debug_info in debug_info)) 630 return expectedFailure(fn, bugnumber) 631 632def expectedFailureDwarf(bugnumber=None): 633 return expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf") 634 635def expectedFailureDwo(bugnumber=None): 636 return expectedFailureAll(bugnumber=bugnumber, debug_info="dwo") 637 638def expectedFailureDsym(bugnumber=None): 639 return expectedFailureAll(bugnumber=bugnumber, debug_info="dsym") 640 641def expectedFailureCompiler(compiler, compiler_version=None, bugnumber=None): 642 if compiler_version is None: 643 compiler_version=['=', None] 644 return expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version) 645 646# to XFAIL a specific clang versions, try this 647# @expectedFailureClang('bugnumber', ['<=', '3.4']) 648def expectedFailureClang(bugnumber=None, compiler_version=None): 649 return expectedFailureCompiler('clang', compiler_version, bugnumber) 650 651def expectedFailureGcc(bugnumber=None, compiler_version=None): 652 return expectedFailureCompiler('gcc', compiler_version, bugnumber) 653 654def expectedFailureIcc(bugnumber=None): 655 return expectedFailureCompiler('icc', None, bugnumber) 656 657def expectedFailureArch(arch, bugnumber=None): 658 def fn(self): 659 return arch in self.getArchitecture() 660 return expectedFailure(fn, bugnumber) 661 662def expectedFailurei386(bugnumber=None): 663 return expectedFailureArch('i386', bugnumber) 664 665def expectedFailurex86_64(bugnumber=None): 666 return expectedFailureArch('x86_64', bugnumber) 667 668def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None): 669 def fn(self): 670 return (self.getPlatform() in oslist and 671 self.expectedCompiler(compilers) and 672 (debug_info is None or self.debug_info in debug_info)) 673 return expectedFailure(fn, bugnumber) 674 675def expectedFailureHostOS(oslist, bugnumber=None, compilers=None): 676 def fn(self): 677 return (getHostPlatform() in oslist and 678 self.expectedCompiler(compilers)) 679 return expectedFailure(fn, bugnumber) 680 681def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): 682 # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. 683 return expectedFailureOS(getDarwinOSTriples(), bugnumber, compilers, debug_info=debug_info) 684 685def expectedFailureFreeBSD(bugnumber=None, compilers=None, debug_info=None): 686 return expectedFailureOS(['freebsd'], bugnumber, compilers, debug_info=debug_info) 687 688def expectedFailureLinux(bugnumber=None, compilers=None, debug_info=None): 689 return expectedFailureOS(['linux'], bugnumber, compilers, debug_info=debug_info) 690 691def expectedFailureWindows(bugnumber=None, compilers=None, debug_info=None): 692 return expectedFailureOS(['windows'], bugnumber, compilers, debug_info=debug_info) 693 694def expectedFailureHostWindows(bugnumber=None, compilers=None): 695 return expectedFailureHostOS(['windows'], bugnumber, compilers) 696 697def matchAndroid(api_levels=None, archs=None): 698 def match(self): 699 if not target_is_android(): 700 return False 701 if archs is not None and self.getArchitecture() not in archs: 702 return False 703 if api_levels is not None and android_device_api() not in api_levels: 704 return False 705 return True 706 return match 707 708 709def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): 710 """ Mark a test as xfail for Android. 711 712 Arguments: 713 bugnumber - The LLVM pr associated with the problem. 714 api_levels - A sequence of numbers specifying the Android API levels 715 for which a test is expected to fail. None means all API level. 716 arch - A sequence of architecture names specifying the architectures 717 for which a test is expected to fail. None means all architectures. 718 """ 719 return expectedFailure(matchAndroid(api_levels, archs), bugnumber) 720 721# if the test passes on the first try, we're done (success) 722# if the test fails once, then passes on the second try, raise an ExpectedFailure 723# if the test fails twice in a row, re-throw the exception from the second test run 724def expectedFlakey(expected_fn, bugnumber=None): 725 def expectedFailure_impl(func): 726 @wraps(func) 727 def wrapper(*args, **kwargs): 728 from unittest2 import case 729 self = args[0] 730 try: 731 func(*args, **kwargs) 732 # don't retry if the test case is already decorated with xfail or skip 733 except (case._ExpectedFailure, case.SkipTest, case._UnexpectedSuccess): 734 raise 735 except Exception: 736 if expected_fn(self): 737 # before retry, run tearDown for previous run and setup for next 738 try: 739 self.tearDown() 740 self.setUp() 741 func(*args, **kwargs) 742 except Exception: 743 # oh snap! two failures in a row, record a failure/error 744 raise 745 # record the expected failure 746 raise case._ExpectedFailure(sys.exc_info(), bugnumber) 747 else: 748 raise 749 return wrapper 750 # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments 751 # return decorator in this case, so it will be used to decorating original method 752 if six.callable(bugnumber): 753 return expectedFailure_impl(bugnumber) 754 else: 755 return expectedFailure_impl 756 757def expectedFlakeyDwarf(bugnumber=None): 758 def fn(self): 759 return self.debug_info == "dwarf" 760 return expectedFlakey(fn, bugnumber) 761 762def expectedFlakeyDsym(bugnumber=None): 763 def fn(self): 764 return self.debug_info == "dwarf" 765 return expectedFlakey(fn, bugnumber) 766 767def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): 768 def fn(self): 769 return (self.getPlatform() in oslist and 770 self.expectedCompiler(compilers)) 771 return expectedFlakey(fn, bugnumber) 772 773def expectedFlakeyDarwin(bugnumber=None, compilers=None): 774 # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. 775 return expectedFlakeyOS(getDarwinOSTriples(), bugnumber, compilers) 776 777def expectedFlakeyLinux(bugnumber=None, compilers=None): 778 return expectedFlakeyOS(['linux'], bugnumber, compilers) 779 780def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): 781 return expectedFlakeyOS(['freebsd'], bugnumber, compilers) 782 783def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None): 784 if compiler_version is None: 785 compiler_version=['=', None] 786 def fn(self): 787 return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version) 788 return expectedFlakey(fn, bugnumber) 789 790# @expectedFlakeyClang('bugnumber', ['<=', '3.4']) 791def expectedFlakeyClang(bugnumber=None, compiler_version=None): 792 return expectedFlakeyCompiler('clang', compiler_version, bugnumber) 793 794# @expectedFlakeyGcc('bugnumber', ['<=', '3.4']) 795def expectedFlakeyGcc(bugnumber=None, compiler_version=None): 796 return expectedFlakeyCompiler('gcc', compiler_version, bugnumber) 797 798def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None): 799 return expectedFlakey(matchAndroid(api_levels, archs), bugnumber) 800 801def skipIfRemote(func): 802 """Decorate the item to skip tests if testing remotely.""" 803 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 804 raise Exception("@skipIfRemote can only be used to decorate a test method") 805 @wraps(func) 806 def wrapper(*args, **kwargs): 807 from unittest2 import case 808 if lldb.remote_platform: 809 self = args[0] 810 self.skipTest("skip on remote platform") 811 else: 812 func(*args, **kwargs) 813 return wrapper 814 815def skipUnlessListedRemote(remote_list=None): 816 def myImpl(func): 817 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 818 raise Exception("@skipIfRemote can only be used to decorate a " 819 "test method") 820 821 @wraps(func) 822 def wrapper(*args, **kwargs): 823 if remote_list and lldb.remote_platform: 824 self = args[0] 825 triple = self.dbg.GetSelectedPlatform().GetTriple() 826 for r in remote_list: 827 if r in triple: 828 func(*args, **kwargs) 829 return 830 self.skipTest("skip on remote platform %s" % str(triple)) 831 else: 832 func(*args, **kwargs) 833 return wrapper 834 835 return myImpl 836 837def skipIfRemoteDueToDeadlock(func): 838 """Decorate the item to skip tests if testing remotely due to the test deadlocking.""" 839 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 840 raise Exception("@skipIfRemote can only be used to decorate a test method") 841 @wraps(func) 842 def wrapper(*args, **kwargs): 843 from unittest2 import case 844 if lldb.remote_platform: 845 self = args[0] 846 self.skipTest("skip on remote platform (deadlocks)") 847 else: 848 func(*args, **kwargs) 849 return wrapper 850 851def skipIfNoSBHeaders(func): 852 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" 853 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 854 raise Exception("@skipIfNoSBHeaders can only be used to decorate a test method") 855 @wraps(func) 856 def wrapper(*args, **kwargs): 857 from unittest2 import case 858 self = args[0] 859 if sys.platform.startswith("darwin"): 860 header = os.path.join(os.environ["LLDB_LIB_DIR"], 'LLDB.framework', 'Versions','Current','Headers','LLDB.h') 861 else: 862 header = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h") 863 platform = sys.platform 864 if not os.path.exists(header): 865 self.skipTest("skip because LLDB.h header not found") 866 else: 867 func(*args, **kwargs) 868 return wrapper 869 870def skipIfiOSSimulator(func): 871 """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" 872 return unittest2.skipIf(hasattr(lldb, 'remote_platform_name') and lldb.remote_platform_name == 'ios-simulator', 'skip on the iOS Simulator')(func) 873 874def skipIfFreeBSD(func): 875 """Decorate the item to skip tests that should be skipped on FreeBSD.""" 876 return skipIfPlatform(["freebsd"])(func) 877 878def getDarwinOSTriples(): 879 return ['darwin', 'macosx', 'ios'] 880 881def skipIfDarwin(func): 882 """Decorate the item to skip tests that should be skipped on Darwin.""" 883 return skipIfPlatform(getDarwinOSTriples())(func) 884 885def skipIfLinux(func): 886 """Decorate the item to skip tests that should be skipped on Linux.""" 887 return skipIfPlatform(["linux"])(func) 888 889def skipUnlessHostLinux(func): 890 """Decorate the item to skip tests that should be skipped on any non Linux host.""" 891 return skipUnlessHostPlatform(["linux"])(func) 892 893def skipIfWindows(func): 894 """Decorate the item to skip tests that should be skipped on Windows.""" 895 return skipIfPlatform(["windows"])(func) 896 897def skipIfHostWindows(func): 898 """Decorate the item to skip tests that should be skipped on Windows.""" 899 return skipIfHostPlatform(["windows"])(func) 900 901def skipUnlessWindows(func): 902 """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" 903 return skipUnlessPlatform(["windows"])(func) 904 905def skipUnlessDarwin(func): 906 """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" 907 return skipUnlessPlatform(getDarwinOSTriples())(func) 908 909def skipUnlessGoInstalled(func): 910 """Decorate the item to skip tests when no Go compiler is available.""" 911 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 912 raise Exception("@skipIfGcc can only be used to decorate a test method") 913 @wraps(func) 914 def wrapper(*args, **kwargs): 915 from unittest2 import case 916 self = args[0] 917 compiler = self.getGoCompilerVersion() 918 if not compiler: 919 self.skipTest("skipping because go compiler not found") 920 else: 921 # Ensure the version is the minimum version supported by 922 # the LLDB go support. 923 match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) 924 if not match_version: 925 # Couldn't determine version. 926 self.skipTest( 927 "skipping because go version could not be parsed " 928 "out of {}".format(compiler)) 929 else: 930 from distutils.version import StrictVersion 931 min_strict_version = StrictVersion("1.4.0") 932 compiler_strict_version = StrictVersion(match_version.group(1)) 933 if compiler_strict_version < min_strict_version: 934 self.skipTest( 935 "skipping because available go version ({}) does " 936 "not meet minimum required go version ({})".format( 937 compiler_strict_version, 938 min_strict_version)) 939 func(*args, **kwargs) 940 return wrapper 941 942def getPlatform(): 943 """Returns the target platform which the tests are running on.""" 944 platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 945 if platform.startswith('freebsd'): 946 platform = 'freebsd' 947 return platform 948 949def getHostPlatform(): 950 """Returns the host platform running the test suite.""" 951 # Attempts to return a platform name matching a target Triple platform. 952 if sys.platform.startswith('linux'): 953 return 'linux' 954 elif sys.platform.startswith('win32'): 955 return 'windows' 956 elif sys.platform.startswith('darwin'): 957 return 'darwin' 958 elif sys.platform.startswith('freebsd'): 959 return 'freebsd' 960 else: 961 return sys.platform 962 963def platformIsDarwin(): 964 """Returns true if the OS triple for the selected platform is any valid apple OS""" 965 return getPlatform() in getDarwinOSTriples() 966 967def skipIfHostIncompatibleWithRemote(func): 968 """Decorate the item to skip tests if binaries built on this host are incompatible.""" 969 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 970 raise Exception("@skipIfHostIncompatibleWithRemote can only be used to decorate a test method") 971 @wraps(func) 972 def wrapper(*args, **kwargs): 973 from unittest2 import case 974 self = args[0] 975 host_arch = self.getLldbArchitecture() 976 host_platform = getHostPlatform() 977 target_arch = self.getArchitecture() 978 target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() 979 if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch: 980 self.skipTest("skipping because target %s is not compatible with host architecture %s" % (target_arch, host_arch)) 981 elif target_platform != host_platform: 982 self.skipTest("skipping because target is %s but host is %s" % (target_platform, host_platform)) 983 else: 984 func(*args, **kwargs) 985 return wrapper 986 987def skipIfHostPlatform(oslist): 988 """Decorate the item to skip tests if running on one of the listed host platforms.""" 989 return unittest2.skipIf(getHostPlatform() in oslist, 990 "skip on %s" % (", ".join(oslist))) 991 992def skipUnlessHostPlatform(oslist): 993 """Decorate the item to skip tests unless running on one of the listed host platforms.""" 994 return unittest2.skipUnless(getHostPlatform() in oslist, 995 "requires on of %s" % (", ".join(oslist))) 996 997def skipUnlessArch(archlist): 998 """Decorate the item to skip tests unless running on one of the listed architectures.""" 999 def myImpl(func): 1000 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1001 raise Exception("@skipUnlessArch can only be used to decorate a test method") 1002 1003 @wraps(func) 1004 def wrapper(*args, **kwargs): 1005 self = args[0] 1006 if self.getArchitecture() not in archlist: 1007 self.skipTest("skipping for architecture %s (requires one of %s)" % 1008 (self.getArchitecture(), ", ".join(archlist))) 1009 else: 1010 func(*args, **kwargs) 1011 return wrapper 1012 1013 return myImpl 1014 1015def skipIfPlatform(oslist): 1016 """Decorate the item to skip tests if running on one of the listed platforms.""" 1017 return unittest2.skipIf(getPlatform() in oslist, 1018 "skip on %s" % (", ".join(oslist))) 1019 1020def skipUnlessPlatform(oslist): 1021 """Decorate the item to skip tests unless running on one of the listed platforms.""" 1022 return unittest2.skipUnless(getPlatform() in oslist, 1023 "requires on of %s" % (", ".join(oslist))) 1024 1025def skipIfLinuxClang(func): 1026 """Decorate the item to skip tests that should be skipped if building on 1027 Linux with clang. 1028 """ 1029 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1030 raise Exception("@skipIfLinuxClang can only be used to decorate a test method") 1031 @wraps(func) 1032 def wrapper(*args, **kwargs): 1033 from unittest2 import case 1034 self = args[0] 1035 compiler = self.getCompiler() 1036 platform = self.getPlatform() 1037 if "clang" in compiler and platform == "linux": 1038 self.skipTest("skipping because Clang is used on Linux") 1039 else: 1040 func(*args, **kwargs) 1041 return wrapper 1042 1043# provide a function to skip on defined oslist, compiler version, and archs 1044# if none is specified for any argument, that argument won't be checked and thus means for all 1045# for example, 1046# @skipIf, skip for all platform/compiler/arch, 1047# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture 1048# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 1049 1050# TODO: refactor current code, to make skipIfxxx functions to call this function 1051def skipIf(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, debug_info=None): 1052 def fn(self): 1053 return ((oslist is None or self.getPlatform() in oslist) and 1054 (compiler is None or (compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version))) and 1055 self.expectedArch(archs) and 1056 (debug_info is None or self.debug_info in debug_info)) 1057 return skipTestIfFn(fn, bugnumber, skipReason="skipping because os:%s compiler: %s %s arch: %s debug info: %s"%(oslist, compiler, compiler_version, archs, debug_info)) 1058 1059def skipIfDebugInfo(bugnumber=None, debug_info=None): 1060 return skipIf(bugnumber=bugnumber, debug_info=debug_info) 1061 1062def skipIfDWO(bugnumber=None): 1063 return skipIfDebugInfo(bugnumber, ["dwo"]) 1064 1065def skipIfDwarf(bugnumber=None): 1066 return skipIfDebugInfo(bugnumber, ["dwarf"]) 1067 1068def skipIfDsym(bugnumber=None): 1069 return skipIfDebugInfo(bugnumber, ["dsym"]) 1070 1071def skipTestIfFn(expected_fn, bugnumber=None, skipReason=None): 1072 def skipTestIfFn_impl(func): 1073 @wraps(func) 1074 def wrapper(*args, **kwargs): 1075 from unittest2 import case 1076 self = args[0] 1077 if expected_fn(self): 1078 self.skipTest(skipReason) 1079 else: 1080 func(*args, **kwargs) 1081 return wrapper 1082 if six.callable(bugnumber): 1083 return skipTestIfFn_impl(bugnumber) 1084 else: 1085 return skipTestIfFn_impl 1086 1087def skipIfGcc(func): 1088 """Decorate the item to skip tests that should be skipped if building with gcc .""" 1089 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1090 raise Exception("@skipIfGcc can only be used to decorate a test method") 1091 @wraps(func) 1092 def wrapper(*args, **kwargs): 1093 from unittest2 import case 1094 self = args[0] 1095 compiler = self.getCompiler() 1096 if "gcc" in compiler: 1097 self.skipTest("skipping because gcc is the test compiler") 1098 else: 1099 func(*args, **kwargs) 1100 return wrapper 1101 1102def skipIfIcc(func): 1103 """Decorate the item to skip tests that should be skipped if building with icc .""" 1104 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1105 raise Exception("@skipIfIcc can only be used to decorate a test method") 1106 @wraps(func) 1107 def wrapper(*args, **kwargs): 1108 from unittest2 import case 1109 self = args[0] 1110 compiler = self.getCompiler() 1111 if "icc" in compiler: 1112 self.skipTest("skipping because icc is the test compiler") 1113 else: 1114 func(*args, **kwargs) 1115 return wrapper 1116 1117def skipIfi386(func): 1118 """Decorate the item to skip tests that should be skipped if building 32-bit.""" 1119 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1120 raise Exception("@skipIfi386 can only be used to decorate a test method") 1121 @wraps(func) 1122 def wrapper(*args, **kwargs): 1123 from unittest2 import case 1124 self = args[0] 1125 if "i386" == self.getArchitecture(): 1126 self.skipTest("skipping because i386 is not a supported architecture") 1127 else: 1128 func(*args, **kwargs) 1129 return wrapper 1130 1131def skipIfTargetAndroid(api_levels=None, archs=None): 1132 """Decorator to skip tests when the target is Android. 1133 1134 Arguments: 1135 api_levels - The API levels for which the test should be skipped. If 1136 it is None, then the test will be skipped for all API levels. 1137 arch - A sequence of architecture names specifying the architectures 1138 for which a test is skipped. None means all architectures. 1139 """ 1140 def myImpl(func): 1141 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1142 raise Exception("@skipIfTargetAndroid can only be used to " 1143 "decorate a test method") 1144 @wraps(func) 1145 def wrapper(*args, **kwargs): 1146 from unittest2 import case 1147 self = args[0] 1148 if matchAndroid(api_levels, archs)(self): 1149 self.skipTest("skiped on Android target with API %d and architecture %s" % 1150 (android_device_api(), self.getArchitecture())) 1151 func(*args, **kwargs) 1152 return wrapper 1153 return myImpl 1154 1155def skipUnlessCompilerRt(func): 1156 """Decorate the item to skip tests if testing remotely.""" 1157 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 1158 raise Exception("@skipUnless can only be used to decorate a test method") 1159 @wraps(func) 1160 def wrapper(*args, **kwargs): 1161 from unittest2 import case 1162 import os.path 1163 compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "projects", "compiler-rt") 1164 if not os.path.exists(compilerRtPath): 1165 self = args[0] 1166 self.skipTest("skip if compiler-rt not found") 1167 else: 1168 func(*args, **kwargs) 1169 return wrapper 1170 1171class _PlatformContext(object): 1172 """Value object class which contains platform-specific options.""" 1173 1174 def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension): 1175 self.shlib_environment_var = shlib_environment_var 1176 self.shlib_prefix = shlib_prefix 1177 self.shlib_extension = shlib_extension 1178 1179 1180class Base(unittest2.TestCase): 1181 """ 1182 Abstract base for performing lldb (see TestBase) or other generic tests (see 1183 BenchBase for one example). lldbtest.Base works with the test driver to 1184 accomplish things. 1185 1186 """ 1187 1188 # The concrete subclass should override this attribute. 1189 mydir = None 1190 1191 # Keep track of the old current working directory. 1192 oldcwd = None 1193 1194 @staticmethod 1195 def compute_mydir(test_file): 1196 '''Subclasses should call this function to correctly calculate the required "mydir" attribute as follows: 1197 1198 mydir = TestBase.compute_mydir(__file__)''' 1199 test_dir = os.path.dirname(test_file) 1200 return test_dir[len(os.environ["LLDB_TEST"])+1:] 1201 1202 def TraceOn(self): 1203 """Returns True if we are in trace mode (tracing detailed test execution).""" 1204 return traceAlways 1205 1206 @classmethod 1207 def setUpClass(cls): 1208 """ 1209 Python unittest framework class setup fixture. 1210 Do current directory manipulation. 1211 """ 1212 # Fail fast if 'mydir' attribute is not overridden. 1213 if not cls.mydir or len(cls.mydir) == 0: 1214 raise Exception("Subclasses must override the 'mydir' attribute.") 1215 1216 # Save old working directory. 1217 cls.oldcwd = os.getcwd() 1218 1219 # Change current working directory if ${LLDB_TEST} is defined. 1220 # See also dotest.py which sets up ${LLDB_TEST}. 1221 if ("LLDB_TEST" in os.environ): 1222 full_dir = os.path.join(os.environ["LLDB_TEST"], cls.mydir) 1223 if traceAlways: 1224 print("Change dir to:", full_dir, file=sys.stderr) 1225 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir)) 1226 1227 if debug_confirm_directory_exclusivity: 1228 import lock 1229 cls.dir_lock = lock.Lock(os.path.join(full_dir, ".dirlock")) 1230 try: 1231 cls.dir_lock.try_acquire() 1232 # write the class that owns the lock into the lock file 1233 cls.dir_lock.handle.write(cls.__name__) 1234 except IOError as ioerror: 1235 # nothing else should have this directory lock 1236 # wait here until we get a lock 1237 cls.dir_lock.acquire() 1238 # read the previous owner from the lock file 1239 lock_id = cls.dir_lock.handle.read() 1240 print("LOCK ERROR: {} wants to lock '{}' but it is already locked by '{}'".format(cls.__name__, full_dir, lock_id), file=sys.stderr) 1241 raise ioerror 1242 1243 # Set platform context. 1244 if platformIsDarwin(): 1245 cls.platformContext = _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib') 1246 elif getPlatform() == "linux" or getPlatform() == "freebsd": 1247 cls.platformContext = _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so') 1248 else: 1249 cls.platformContext = None 1250 1251 @classmethod 1252 def tearDownClass(cls): 1253 """ 1254 Python unittest framework class teardown fixture. 1255 Do class-wide cleanup. 1256 """ 1257 1258 if doCleanup and not lldb.skip_build_and_cleanup: 1259 # First, let's do the platform-specific cleanup. 1260 module = builder_module() 1261 module.cleanup() 1262 1263 # Subclass might have specific cleanup function defined. 1264 if getattr(cls, "classCleanup", None): 1265 if traceAlways: 1266 print("Call class-specific cleanup function for class:", cls, file=sys.stderr) 1267 try: 1268 cls.classCleanup() 1269 except: 1270 exc_type, exc_value, exc_tb = sys.exc_info() 1271 traceback.print_exception(exc_type, exc_value, exc_tb) 1272 1273 if debug_confirm_directory_exclusivity: 1274 cls.dir_lock.release() 1275 del cls.dir_lock 1276 1277 # Restore old working directory. 1278 if traceAlways: 1279 print("Restore dir to:", cls.oldcwd, file=sys.stderr) 1280 os.chdir(cls.oldcwd) 1281 1282 @classmethod 1283 def skipLongRunningTest(cls): 1284 """ 1285 By default, we skip long running test case. 1286 This can be overridden by passing '-l' to the test driver (dotest.py). 1287 """ 1288 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]: 1289 return False 1290 else: 1291 return True 1292 1293 def enableLogChannelsForCurrentTest(self): 1294 if len(lldbtest_config.channels) == 0: 1295 return 1296 1297 # if debug channels are specified in lldbtest_config.channels, 1298 # create a new set of log files for every test 1299 log_basename = self.getLogBasenameForCurrentTest() 1300 1301 # confirm that the file is writeable 1302 host_log_path = "{}-host.log".format(log_basename) 1303 open(host_log_path, 'w').close() 1304 1305 log_enable = "log enable -Tpn -f {} ".format(host_log_path) 1306 for channel_with_categories in lldbtest_config.channels: 1307 channel_then_categories = channel_with_categories.split(' ', 1) 1308 channel = channel_then_categories[0] 1309 if len(channel_then_categories) > 1: 1310 categories = channel_then_categories[1] 1311 else: 1312 categories = "default" 1313 1314 if channel == "gdb-remote": 1315 # communicate gdb-remote categories to debugserver 1316 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories 1317 1318 self.ci.HandleCommand(log_enable + channel_with_categories, self.res) 1319 if not self.res.Succeeded(): 1320 raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)') 1321 1322 # Communicate log path name to debugserver & lldb-server 1323 server_log_path = "{}-server.log".format(log_basename) 1324 open(server_log_path, 'w').close() 1325 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path 1326 1327 # Communicate channels to lldb-server 1328 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels) 1329 1330 if len(lldbtest_config.channels) == 0: 1331 return 1332 1333 def disableLogChannelsForCurrentTest(self): 1334 # close all log files that we opened 1335 for channel_and_categories in lldbtest_config.channels: 1336 # channel format - <channel-name> [<category0> [<category1> ...]] 1337 channel = channel_and_categories.split(' ', 1)[0] 1338 self.ci.HandleCommand("log disable " + channel, self.res) 1339 if not self.res.Succeeded(): 1340 raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)') 1341 1342 def setUp(self): 1343 """Fixture for unittest test case setup. 1344 1345 It works with the test driver to conditionally skip tests and does other 1346 initializations.""" 1347 #import traceback 1348 #traceback.print_stack() 1349 1350 if "LIBCXX_PATH" in os.environ: 1351 self.libcxxPath = os.environ["LIBCXX_PATH"] 1352 else: 1353 self.libcxxPath = None 1354 1355 if "LLDBMI_EXEC" in os.environ: 1356 self.lldbMiExec = os.environ["LLDBMI_EXEC"] 1357 else: 1358 self.lldbMiExec = None 1359 1360 # If we spawn an lldb process for test (via pexpect), do not load the 1361 # init file unless told otherwise. 1362 if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: 1363 self.lldbOption = "" 1364 else: 1365 self.lldbOption = "--no-lldbinit" 1366 1367 # Assign the test method name to self.testMethodName. 1368 # 1369 # For an example of the use of this attribute, look at test/types dir. 1370 # There are a bunch of test cases under test/types and we don't want the 1371 # module cacheing subsystem to be confused with executable name "a.out" 1372 # used for all the test cases. 1373 self.testMethodName = self._testMethodName 1374 1375 # Benchmarks test is decorated with @benchmarks_test, 1376 # which also sets the "__benchmarks_test__" attribute of the 1377 # function object to True. 1378 try: 1379 if lldb.just_do_benchmarks_test: 1380 testMethod = getattr(self, self._testMethodName) 1381 if getattr(testMethod, "__benchmarks_test__", False): 1382 pass 1383 else: 1384 self.skipTest("non benchmarks test") 1385 except AttributeError: 1386 pass 1387 1388 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 1389 # with it using pexpect. 1390 self.child = None 1391 self.child_prompt = "(lldb) " 1392 # If the child is interacting with the embedded script interpreter, 1393 # there are two exits required during tear down, first to quit the 1394 # embedded script interpreter and second to quit the lldb command 1395 # interpreter. 1396 self.child_in_script_interpreter = False 1397 1398 # These are for customized teardown cleanup. 1399 self.dict = None 1400 self.doTearDownCleanup = False 1401 # And in rare cases where there are multiple teardown cleanups. 1402 self.dicts = [] 1403 self.doTearDownCleanups = False 1404 1405 # List of spawned subproces.Popen objects 1406 self.subprocesses = [] 1407 1408 # List of forked process PIDs 1409 self.forkedProcessPids = [] 1410 1411 # Create a string buffer to record the session info, to be dumped into a 1412 # test case specific file if test failure is encountered. 1413 self.log_basename = self.getLogBasenameForCurrentTest() 1414 1415 session_file = "{}.log".format(self.log_basename) 1416 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. 1417 self.session = open(session_file, "w") 1418 1419 # Optimistically set __errored__, __failed__, __expected__ to False 1420 # initially. If the test errored/failed, the session info 1421 # (self.session) is then dumped into a session specific file for 1422 # diagnosis. 1423 self.__cleanup_errored__ = False 1424 self.__errored__ = False 1425 self.__failed__ = False 1426 self.__expected__ = False 1427 # We are also interested in unexpected success. 1428 self.__unexpected__ = False 1429 # And skipped tests. 1430 self.__skipped__ = False 1431 1432 # See addTearDownHook(self, hook) which allows the client to add a hook 1433 # function to be run during tearDown() time. 1434 self.hooks = [] 1435 1436 # See HideStdout(self). 1437 self.sys_stdout_hidden = False 1438 1439 if self.platformContext: 1440 # set environment variable names for finding shared libraries 1441 self.dylibPath = self.platformContext.shlib_environment_var 1442 1443 # Create the debugger instance if necessary. 1444 try: 1445 self.dbg = lldb.DBG 1446 except AttributeError: 1447 self.dbg = lldb.SBDebugger.Create() 1448 1449 if not self.dbg: 1450 raise Exception('Invalid debugger instance') 1451 1452 # Retrieve the associated command interpreter instance. 1453 self.ci = self.dbg.GetCommandInterpreter() 1454 if not self.ci: 1455 raise Exception('Could not get the command interpreter') 1456 1457 # And the result object. 1458 self.res = lldb.SBCommandReturnObject() 1459 1460 self.enableLogChannelsForCurrentTest() 1461 1462 def runHooks(self, child=None, child_prompt=None, use_cmd_api=False): 1463 """Perform the run hooks to bring lldb debugger to the desired state. 1464 1465 By default, expect a pexpect spawned child and child prompt to be 1466 supplied (use_cmd_api=False). If use_cmd_api is true, ignore the child 1467 and child prompt and use self.runCmd() to run the hooks one by one. 1468 1469 Note that child is a process spawned by pexpect.spawn(). If not, your 1470 test case is mostly likely going to fail. 1471 1472 See also dotest.py where lldb.runHooks are processed/populated. 1473 """ 1474 if not lldb.runHooks: 1475 self.skipTest("No runhooks specified for lldb, skip the test") 1476 if use_cmd_api: 1477 for hook in lldb.runhooks: 1478 self.runCmd(hook) 1479 else: 1480 if not child or not child_prompt: 1481 self.fail("Both child and child_prompt need to be defined.") 1482 for hook in lldb.runHooks: 1483 child.sendline(hook) 1484 child.expect_exact(child_prompt) 1485 1486 def setAsync(self, value): 1487 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 1488 old_async = self.dbg.GetAsync() 1489 self.dbg.SetAsync(value) 1490 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 1491 1492 def cleanupSubprocesses(self): 1493 # Ensure any subprocesses are cleaned up 1494 for p in self.subprocesses: 1495 p.terminate() 1496 del p 1497 del self.subprocesses[:] 1498 # Ensure any forked processes are cleaned up 1499 for pid in self.forkedProcessPids: 1500 if os.path.exists("/proc/" + str(pid)): 1501 os.kill(pid, signal.SIGTERM) 1502 1503 def spawnSubprocess(self, executable, args=[], install_remote=True): 1504 """ Creates a subprocess.Popen object with the specified executable and arguments, 1505 saves it in self.subprocesses, and returns the object. 1506 NOTE: if using this function, ensure you also call: 1507 1508 self.addTearDownHook(self.cleanupSubprocesses) 1509 1510 otherwise the test suite will leak processes. 1511 """ 1512 proc = _RemoteProcess(install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) 1513 proc.launch(executable, args) 1514 self.subprocesses.append(proc) 1515 return proc 1516 1517 def forkSubprocess(self, executable, args=[]): 1518 """ Fork a subprocess with its own group ID. 1519 NOTE: if using this function, ensure you also call: 1520 1521 self.addTearDownHook(self.cleanupSubprocesses) 1522 1523 otherwise the test suite will leak processes. 1524 """ 1525 child_pid = os.fork() 1526 if child_pid == 0: 1527 # If more I/O support is required, this can be beefed up. 1528 fd = os.open(os.devnull, os.O_RDWR) 1529 os.dup2(fd, 1) 1530 os.dup2(fd, 2) 1531 # This call causes the child to have its of group ID 1532 os.setpgid(0,0) 1533 os.execvp(executable, [executable] + args) 1534 # Give the child time to get through the execvp() call 1535 time.sleep(0.1) 1536 self.forkedProcessPids.append(child_pid) 1537 return child_pid 1538 1539 def HideStdout(self): 1540 """Hide output to stdout from the user. 1541 1542 During test execution, there might be cases where we don't want to show the 1543 standard output to the user. For example, 1544 1545 self.runCmd(r'''sc print("\n\n\tHello!\n")''') 1546 1547 tests whether command abbreviation for 'script' works or not. There is no 1548 need to show the 'Hello' output to the user as long as the 'script' command 1549 succeeds and we are not in TraceOn() mode (see the '-t' option). 1550 1551 In this case, the test method calls self.HideStdout(self) to redirect the 1552 sys.stdout to a null device, and restores the sys.stdout upon teardown. 1553 1554 Note that you should only call this method at most once during a test case 1555 execution. Any subsequent call has no effect at all.""" 1556 if self.sys_stdout_hidden: 1557 return 1558 1559 self.sys_stdout_hidden = True 1560 old_stdout = sys.stdout 1561 sys.stdout = open(os.devnull, 'w') 1562 def restore_stdout(): 1563 sys.stdout = old_stdout 1564 self.addTearDownHook(restore_stdout) 1565 1566 # ======================================================================= 1567 # Methods for customized teardown cleanups as well as execution of hooks. 1568 # ======================================================================= 1569 1570 def setTearDownCleanup(self, dictionary=None): 1571 """Register a cleanup action at tearDown() time with a dictinary""" 1572 self.dict = dictionary 1573 self.doTearDownCleanup = True 1574 1575 def addTearDownCleanup(self, dictionary): 1576 """Add a cleanup action at tearDown() time with a dictinary""" 1577 self.dicts.append(dictionary) 1578 self.doTearDownCleanups = True 1579 1580 def addTearDownHook(self, hook): 1581 """ 1582 Add a function to be run during tearDown() time. 1583 1584 Hooks are executed in a first come first serve manner. 1585 """ 1586 if six.callable(hook): 1587 with recording(self, traceAlways) as sbuf: 1588 print("Adding tearDown hook:", getsource_if_available(hook), file=sbuf) 1589 self.hooks.append(hook) 1590 1591 return self 1592 1593 def deletePexpectChild(self): 1594 # This is for the case of directly spawning 'lldb' and interacting with it 1595 # using pexpect. 1596 if self.child and self.child.isalive(): 1597 import pexpect 1598 with recording(self, traceAlways) as sbuf: 1599 print("tearing down the child process....", file=sbuf) 1600 try: 1601 if self.child_in_script_interpreter: 1602 self.child.sendline('quit()') 1603 self.child.expect_exact(self.child_prompt) 1604 self.child.sendline('settings set interpreter.prompt-on-quit false') 1605 self.child.sendline('quit') 1606 self.child.expect(pexpect.EOF) 1607 except (ValueError, pexpect.ExceptionPexpect): 1608 # child is already terminated 1609 pass 1610 except OSError as exception: 1611 import errno 1612 if exception.errno != errno.EIO: 1613 # unexpected error 1614 raise 1615 # child is already terminated 1616 pass 1617 finally: 1618 # Give it one final blow to make sure the child is terminated. 1619 self.child.close() 1620 1621 def tearDown(self): 1622 """Fixture for unittest test case teardown.""" 1623 #import traceback 1624 #traceback.print_stack() 1625 1626 self.deletePexpectChild() 1627 1628 # Check and run any hook functions. 1629 for hook in reversed(self.hooks): 1630 with recording(self, traceAlways) as sbuf: 1631 print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf) 1632 import inspect 1633 hook_argc = len(inspect.getargspec(hook).args) 1634 if hook_argc == 0 or getattr(hook,'im_self',None): 1635 hook() 1636 elif hook_argc == 1: 1637 hook(self) 1638 else: 1639 hook() # try the plain call and hope it works 1640 1641 del self.hooks 1642 1643 # Perform registered teardown cleanup. 1644 if doCleanup and self.doTearDownCleanup: 1645 self.cleanup(dictionary=self.dict) 1646 1647 # In rare cases where there are multiple teardown cleanups added. 1648 if doCleanup and self.doTearDownCleanups: 1649 if self.dicts: 1650 for dict in reversed(self.dicts): 1651 self.cleanup(dictionary=dict) 1652 1653 self.disableLogChannelsForCurrentTest() 1654 1655 # ========================================================= 1656 # Various callbacks to allow introspection of test progress 1657 # ========================================================= 1658 1659 def markError(self): 1660 """Callback invoked when an error (unexpected exception) errored.""" 1661 self.__errored__ = True 1662 with recording(self, False) as sbuf: 1663 # False because there's no need to write "ERROR" to the stderr twice. 1664 # Once by the Python unittest framework, and a second time by us. 1665 print("ERROR", file=sbuf) 1666 1667 def markCleanupError(self): 1668 """Callback invoked when an error occurs while a test is cleaning up.""" 1669 self.__cleanup_errored__ = True 1670 with recording(self, False) as sbuf: 1671 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. 1672 # Once by the Python unittest framework, and a second time by us. 1673 print("CLEANUP_ERROR", file=sbuf) 1674 1675 def markFailure(self): 1676 """Callback invoked when a failure (test assertion failure) occurred.""" 1677 self.__failed__ = True 1678 with recording(self, False) as sbuf: 1679 # False because there's no need to write "FAIL" to the stderr twice. 1680 # Once by the Python unittest framework, and a second time by us. 1681 print("FAIL", file=sbuf) 1682 1683 def markExpectedFailure(self,err,bugnumber): 1684 """Callback invoked when an expected failure/error occurred.""" 1685 self.__expected__ = True 1686 with recording(self, False) as sbuf: 1687 # False because there's no need to write "expected failure" to the 1688 # stderr twice. 1689 # Once by the Python unittest framework, and a second time by us. 1690 if bugnumber == None: 1691 print("expected failure", file=sbuf) 1692 else: 1693 print("expected failure (problem id:" + str(bugnumber) + ")", file=sbuf) 1694 1695 def markSkippedTest(self): 1696 """Callback invoked when a test is skipped.""" 1697 self.__skipped__ = True 1698 with recording(self, False) as sbuf: 1699 # False because there's no need to write "skipped test" to the 1700 # stderr twice. 1701 # Once by the Python unittest framework, and a second time by us. 1702 print("skipped test", file=sbuf) 1703 1704 def markUnexpectedSuccess(self, bugnumber): 1705 """Callback invoked when an unexpected success occurred.""" 1706 self.__unexpected__ = True 1707 with recording(self, False) as sbuf: 1708 # False because there's no need to write "unexpected success" to the 1709 # stderr twice. 1710 # Once by the Python unittest framework, and a second time by us. 1711 if bugnumber == None: 1712 print("unexpected success", file=sbuf) 1713 else: 1714 print("unexpected success (problem id:" + str(bugnumber) + ")", file=sbuf) 1715 1716 def getRerunArgs(self): 1717 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) 1718 1719 def getLogBasenameForCurrentTest(self, prefix=None): 1720 """ 1721 returns a partial path that can be used as the beginning of the name of multiple 1722 log files pertaining to this test 1723 1724 <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method> 1725 """ 1726 dname = os.path.join(os.environ["LLDB_TEST"], 1727 os.environ["LLDB_SESSION_DIRNAME"]) 1728 if not os.path.isdir(dname): 1729 os.mkdir(dname) 1730 1731 compiler = self.getCompiler() 1732 1733 if compiler[1] == ':': 1734 compiler = compiler[2:] 1735 if os.path.altsep is not None: 1736 compiler = compiler.replace(os.path.altsep, os.path.sep) 1737 1738 fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), "_".join(compiler.split(os.path.sep))) 1739 if len(fname) > 200: 1740 fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), compiler.split(os.path.sep)[-1]) 1741 1742 if prefix is not None: 1743 fname = "{}-{}".format(prefix, fname) 1744 1745 return os.path.join(dname, fname) 1746 1747 def dumpSessionInfo(self): 1748 """ 1749 Dump the debugger interactions leading to a test error/failure. This 1750 allows for more convenient postmortem analysis. 1751 1752 See also LLDBTestResult (dotest.py) which is a singlton class derived 1753 from TextTestResult and overwrites addError, addFailure, and 1754 addExpectedFailure methods to allow us to to mark the test instance as 1755 such. 1756 """ 1757 1758 # We are here because self.tearDown() detected that this test instance 1759 # either errored or failed. The lldb.test_result singleton contains 1760 # two lists (erros and failures) which get populated by the unittest 1761 # framework. Look over there for stack trace information. 1762 # 1763 # The lists contain 2-tuples of TestCase instances and strings holding 1764 # formatted tracebacks. 1765 # 1766 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 1767 1768 # output tracebacks into session 1769 pairs = [] 1770 if self.__errored__: 1771 pairs = lldb.test_result.errors 1772 prefix = 'Error' 1773 elif self.__cleanup_errored__: 1774 pairs = lldb.test_result.cleanup_errors 1775 prefix = 'CleanupError' 1776 elif self.__failed__: 1777 pairs = lldb.test_result.failures 1778 prefix = 'Failure' 1779 elif self.__expected__: 1780 pairs = lldb.test_result.expectedFailures 1781 prefix = 'ExpectedFailure' 1782 elif self.__skipped__: 1783 prefix = 'SkippedTest' 1784 elif self.__unexpected__: 1785 prefix = 'UnexpectedSuccess' 1786 else: 1787 prefix = 'Success' 1788 1789 if not self.__unexpected__ and not self.__skipped__: 1790 for test, traceback in pairs: 1791 if test is self: 1792 print(traceback, file=self.session) 1793 1794 # put footer (timestamp/rerun instructions) into session 1795 testMethod = getattr(self, self._testMethodName) 1796 if getattr(testMethod, "__benchmarks_test__", False): 1797 benchmarks = True 1798 else: 1799 benchmarks = False 1800 1801 import datetime 1802 print("Session info generated @", datetime.datetime.now().ctime(), file=self.session) 1803 print("To rerun this test, issue the following command from the 'test' directory:\n", file=self.session) 1804 print("./dotest.py %s -v %s %s" % (self.getRunOptions(), 1805 ('+b' if benchmarks else '-t'), 1806 self.getRerunArgs()), file=self.session) 1807 self.session.close() 1808 del self.session 1809 1810 # process the log files 1811 log_files_for_this_test = glob.glob(self.log_basename + "*") 1812 1813 if prefix != 'Success' or lldbtest_config.log_success: 1814 # keep all log files, rename them to include prefix 1815 dst_log_basename = self.getLogBasenameForCurrentTest(prefix) 1816 for src in log_files_for_this_test: 1817 if os.path.isfile(src): 1818 dst = src.replace(self.log_basename, dst_log_basename) 1819 if os.name == "nt" and os.path.isfile(dst): 1820 # On Windows, renaming a -> b will throw an exception if b exists. On non-Windows platforms 1821 # it silently replaces the destination. Ultimately this means that atomic renames are not 1822 # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the 1823 # destination first if it already exists. 1824 os.remove(dst) 1825 1826 os.rename(src, dst) 1827 else: 1828 # success! (and we don't want log files) delete log files 1829 for log_file in log_files_for_this_test: 1830 try: 1831 os.unlink(log_file) 1832 except: 1833 # We've seen consistent unlink failures on Windows, perhaps because the 1834 # just-created log file is being scanned by anti-virus. Empirically, this 1835 # sleep-and-retry approach allows tests to succeed much more reliably. 1836 # Attempts to figure out exactly what process was still holding a file handle 1837 # have failed because running instrumentation like Process Monitor seems to 1838 # slow things down enough that the problem becomes much less consistent. 1839 time.sleep(0.5) 1840 os.unlink(log_file) 1841 1842 # ==================================================== 1843 # Config. methods supported through a plugin interface 1844 # (enables reading of the current test configuration) 1845 # ==================================================== 1846 1847 def getArchitecture(self): 1848 """Returns the architecture in effect the test suite is running with.""" 1849 module = builder_module() 1850 arch = module.getArchitecture() 1851 if arch == 'amd64': 1852 arch = 'x86_64' 1853 return arch 1854 1855 def getLldbArchitecture(self): 1856 """Returns the architecture of the lldb binary.""" 1857 if not hasattr(self, 'lldbArchitecture'): 1858 1859 # spawn local process 1860 command = [ 1861 lldbtest_config.lldbExec, 1862 "-o", 1863 "file " + lldbtest_config.lldbExec, 1864 "-o", 1865 "quit" 1866 ] 1867 1868 output = check_output(command) 1869 str = output.decode("utf-8"); 1870 1871 for line in str.splitlines(): 1872 m = re.search("Current executable set to '.*' \\((.*)\\)\\.", line) 1873 if m: 1874 self.lldbArchitecture = m.group(1) 1875 break 1876 1877 return self.lldbArchitecture 1878 1879 def getCompiler(self): 1880 """Returns the compiler in effect the test suite is running with.""" 1881 module = builder_module() 1882 return module.getCompiler() 1883 1884 def getCompilerBinary(self): 1885 """Returns the compiler binary the test suite is running with.""" 1886 return self.getCompiler().split()[0] 1887 1888 def getCompilerVersion(self): 1889 """ Returns a string that represents the compiler version. 1890 Supports: llvm, clang. 1891 """ 1892 from .lldbutil import which 1893 version = 'unknown' 1894 1895 compiler = self.getCompilerBinary() 1896 version_output = system([[which(compiler), "-v"]])[1] 1897 for line in version_output.split(os.linesep): 1898 m = re.search('version ([0-9\.]+)', line) 1899 if m: 1900 version = m.group(1) 1901 return version 1902 1903 def getGoCompilerVersion(self): 1904 """ Returns a string that represents the go compiler version, or None if go is not found. 1905 """ 1906 compiler = which("go") 1907 if compiler: 1908 version_output = system([[compiler, "version"]])[0] 1909 for line in version_output.split(os.linesep): 1910 m = re.search('go version (devel|go\\S+)', line) 1911 if m: 1912 return m.group(1) 1913 return None 1914 1915 def platformIsDarwin(self): 1916 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1917 return platformIsDarwin() 1918 1919 def getPlatform(self): 1920 """Returns the target platform the test suite is running on.""" 1921 return getPlatform() 1922 1923 def isIntelCompiler(self): 1924 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1925 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1926 1927 def expectedCompilerVersion(self, compiler_version): 1928 """Returns True iff compiler_version[1] matches the current compiler version. 1929 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1930 Any operator other than the following defaults to an equality test: 1931 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1932 """ 1933 if (compiler_version == None): 1934 return True 1935 operator = str(compiler_version[0]) 1936 version = compiler_version[1] 1937 1938 if (version == None): 1939 return True 1940 if (operator == '>'): 1941 return self.getCompilerVersion() > version 1942 if (operator == '>=' or operator == '=>'): 1943 return self.getCompilerVersion() >= version 1944 if (operator == '<'): 1945 return self.getCompilerVersion() < version 1946 if (operator == '<=' or operator == '=<'): 1947 return self.getCompilerVersion() <= version 1948 if (operator == '!=' or operator == '!' or operator == 'not'): 1949 return str(version) not in str(self.getCompilerVersion()) 1950 return str(version) in str(self.getCompilerVersion()) 1951 1952 def expectedCompiler(self, compilers): 1953 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1954 if (compilers == None): 1955 return True 1956 1957 for compiler in compilers: 1958 if compiler in self.getCompiler(): 1959 return True 1960 1961 return False 1962 1963 def expectedArch(self, archs): 1964 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1965 if (archs == None): 1966 return True 1967 1968 for arch in archs: 1969 if arch in self.getArchitecture(): 1970 return True 1971 1972 return False 1973 1974 def getRunOptions(self): 1975 """Command line option for -A and -C to run this test again, called from 1976 self.dumpSessionInfo().""" 1977 arch = self.getArchitecture() 1978 comp = self.getCompiler() 1979 if arch: 1980 option_str = "-A " + arch 1981 else: 1982 option_str = "" 1983 if comp: 1984 option_str += " -C " + comp 1985 return option_str 1986 1987 # ================================================== 1988 # Build methods supported through a plugin interface 1989 # ================================================== 1990 1991 def getstdlibFlag(self): 1992 """ Returns the proper -stdlib flag, or empty if not required.""" 1993 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1994 stdlibflag = "-stdlib=libc++" 1995 else: 1996 stdlibflag = "" 1997 return stdlibflag 1998 1999 def getstdFlag(self): 2000 """ Returns the proper stdflag. """ 2001 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 2002 stdflag = "-std=c++0x" 2003 else: 2004 stdflag = "-std=c++11" 2005 return stdflag 2006 2007 def buildDriver(self, sources, exe_name): 2008 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 2009 or LLDB.framework). 2010 """ 2011 2012 stdflag = self.getstdFlag() 2013 stdlibflag = self.getstdlibFlag() 2014 2015 lib_dir = os.environ["LLDB_LIB_DIR"] 2016 if sys.platform.startswith("darwin"): 2017 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 2018 d = {'CXX_SOURCES' : sources, 2019 'EXE' : exe_name, 2020 'CFLAGS_EXTRAS' : "%s %s" % (stdflag, stdlibflag), 2021 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 2022 'LD_EXTRAS' : "%s -Wl,-rpath,%s" % (dsym, lib_dir), 2023 } 2024 elif sys.platform.startswith('freebsd') or sys.platform.startswith("linux") or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 2025 d = {'CXX_SOURCES' : sources, 2026 'EXE' : exe_name, 2027 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 2028 'LD_EXTRAS' : "-L%s -llldb" % lib_dir} 2029 elif sys.platform.startswith('win'): 2030 d = {'CXX_SOURCES' : sources, 2031 'EXE' : exe_name, 2032 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 2033 'LD_EXTRAS' : "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]} 2034 if self.TraceOn(): 2035 print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources)) 2036 2037 self.buildDefault(dictionary=d) 2038 2039 def buildLibrary(self, sources, lib_name): 2040 """Platform specific way to build a default library. """ 2041 2042 stdflag = self.getstdFlag() 2043 2044 lib_dir = os.environ["LLDB_LIB_DIR"] 2045 if self.platformIsDarwin(): 2046 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 2047 d = {'DYLIB_CXX_SOURCES' : sources, 2048 'DYLIB_NAME' : lib_name, 2049 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag, 2050 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 2051 'LD_EXTRAS' : "%s -Wl,-rpath,%s -dynamiclib" % (dsym, lib_dir), 2052 } 2053 elif self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux' or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 2054 d = {'DYLIB_CXX_SOURCES' : sources, 2055 'DYLIB_NAME' : lib_name, 2056 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 2057 'LD_EXTRAS' : "-shared -L%s -llldb" % lib_dir} 2058 elif self.getPlatform() == 'windows': 2059 d = {'DYLIB_CXX_SOURCES' : sources, 2060 'DYLIB_NAME' : lib_name, 2061 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 2062 'LD_EXTRAS' : "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]} 2063 if self.TraceOn(): 2064 print("Building LLDB Library (%s) from sources %s" % (lib_name, sources)) 2065 2066 self.buildDefault(dictionary=d) 2067 2068 def buildProgram(self, sources, exe_name): 2069 """ Platform specific way to build an executable from C/C++ sources. """ 2070 d = {'CXX_SOURCES' : sources, 2071 'EXE' : exe_name} 2072 self.buildDefault(dictionary=d) 2073 2074 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): 2075 """Platform specific way to build the default binaries.""" 2076 if lldb.skip_build_and_cleanup: 2077 return 2078 module = builder_module() 2079 if target_is_android(): 2080 dictionary = append_android_envs(dictionary) 2081 if not module.buildDefault(self, architecture, compiler, dictionary, clean): 2082 raise Exception("Don't know how to build default binary") 2083 2084 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True): 2085 """Platform specific way to build binaries with dsym info.""" 2086 if lldb.skip_build_and_cleanup: 2087 return 2088 module = builder_module() 2089 if not module.buildDsym(self, architecture, compiler, dictionary, clean): 2090 raise Exception("Don't know how to build binary with dsym") 2091 2092 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): 2093 """Platform specific way to build binaries with dwarf maps.""" 2094 if lldb.skip_build_and_cleanup: 2095 return 2096 module = builder_module() 2097 if target_is_android(): 2098 dictionary = append_android_envs(dictionary) 2099 if not module.buildDwarf(self, architecture, compiler, dictionary, clean): 2100 raise Exception("Don't know how to build binary with dwarf") 2101 2102 def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True): 2103 """Platform specific way to build binaries with dwarf maps.""" 2104 if lldb.skip_build_and_cleanup: 2105 return 2106 module = builder_module() 2107 if target_is_android(): 2108 dictionary = append_android_envs(dictionary) 2109 if not module.buildDwo(self, architecture, compiler, dictionary, clean): 2110 raise Exception("Don't know how to build binary with dwo") 2111 2112 def buildGo(self): 2113 """Build the default go binary. 2114 """ 2115 system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']]) 2116 2117 def signBinary(self, binary_path): 2118 if sys.platform.startswith("darwin"): 2119 codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path) 2120 call(codesign_cmd, shell=True) 2121 2122 def findBuiltClang(self): 2123 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 2124 paths_to_try = [ 2125 "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang", 2126 "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang", 2127 "llvm-build/Release/x86_64/Release/bin/clang", 2128 "llvm-build/Debug/x86_64/Debug/bin/clang", 2129 ] 2130 lldb_root_path = os.path.join(os.path.dirname(__file__), "..") 2131 for p in paths_to_try: 2132 path = os.path.join(lldb_root_path, p) 2133 if os.path.exists(path): 2134 return path 2135 2136 # Tries to find clang at the same folder as the lldb 2137 path = os.path.join(os.path.dirname(lldbtest_config.lldbExec), "clang") 2138 if os.path.exists(path): 2139 return path 2140 2141 return os.environ["CC"] 2142 2143 def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False): 2144 """ Returns a dictionary (which can be provided to build* functions above) which 2145 contains OS-specific build flags. 2146 """ 2147 cflags = "" 2148 ldflags = "" 2149 2150 # On Mac OS X, unless specifically requested to use libstdc++, use libc++ 2151 if not use_libstdcxx and self.platformIsDarwin(): 2152 use_libcxx = True 2153 2154 if use_libcxx and self.libcxxPath: 2155 cflags += "-stdlib=libc++ " 2156 if self.libcxxPath: 2157 libcxxInclude = os.path.join(self.libcxxPath, "include") 2158 libcxxLib = os.path.join(self.libcxxPath, "lib") 2159 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): 2160 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (libcxxInclude, libcxxLib, libcxxLib) 2161 2162 if use_cpp11: 2163 cflags += "-std=" 2164 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 2165 cflags += "c++0x" 2166 else: 2167 cflags += "c++11" 2168 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 2169 cflags += " -stdlib=libc++" 2170 elif "clang" in self.getCompiler(): 2171 cflags += " -stdlib=libstdc++" 2172 2173 return {'CFLAGS_EXTRAS' : cflags, 2174 'LD_EXTRAS' : ldflags, 2175 } 2176 2177 def cleanup(self, dictionary=None): 2178 """Platform specific way to do cleanup after build.""" 2179 if lldb.skip_build_and_cleanup: 2180 return 2181 module = builder_module() 2182 if not module.cleanup(self, dictionary): 2183 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary) 2184 2185 def getLLDBLibraryEnvVal(self): 2186 """ Returns the path that the OS-specific library search environment variable 2187 (self.dylibPath) should be set to in order for a program to find the LLDB 2188 library. If an environment variable named self.dylibPath is already set, 2189 the new path is appended to it and returned. 2190 """ 2191 existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None 2192 lib_dir = os.environ["LLDB_LIB_DIR"] 2193 if existing_library_path: 2194 return "%s:%s" % (existing_library_path, lib_dir) 2195 elif sys.platform.startswith("darwin"): 2196 return os.path.join(lib_dir, 'LLDB.framework') 2197 else: 2198 return lib_dir 2199 2200 def getLibcPlusPlusLibs(self): 2201 if self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux': 2202 return ['libc++.so.1'] 2203 else: 2204 return ['libc++.1.dylib','libc++abi.dylib'] 2205 2206# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. 2207# We change the test methods to create a new test method for each test for each debug info we are 2208# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding 2209# the new test method we remove the old method at the same time. 2210class LLDBTestCaseFactory(type): 2211 def __new__(cls, name, bases, attrs): 2212 newattrs = {} 2213 for attrname, attrvalue in attrs.items(): 2214 if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False): 2215 @dsym_test 2216 @wraps(attrvalue) 2217 def dsym_test_method(self, attrvalue=attrvalue): 2218 self.debug_info = "dsym" 2219 return attrvalue(self) 2220 dsym_method_name = attrname + "_dsym" 2221 dsym_test_method.__name__ = dsym_method_name 2222 newattrs[dsym_method_name] = dsym_test_method 2223 2224 @dwarf_test 2225 @wraps(attrvalue) 2226 def dwarf_test_method(self, attrvalue=attrvalue): 2227 self.debug_info = "dwarf" 2228 return attrvalue(self) 2229 dwarf_method_name = attrname + "_dwarf" 2230 dwarf_test_method.__name__ = dwarf_method_name 2231 newattrs[dwarf_method_name] = dwarf_test_method 2232 2233 @dwo_test 2234 @wraps(attrvalue) 2235 def dwo_test_method(self, attrvalue=attrvalue): 2236 self.debug_info = "dwo" 2237 return attrvalue(self) 2238 dwo_method_name = attrname + "_dwo" 2239 dwo_test_method.__name__ = dwo_method_name 2240 newattrs[dwo_method_name] = dwo_test_method 2241 else: 2242 newattrs[attrname] = attrvalue 2243 return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs) 2244 2245# Setup the metaclass for this class to change the list of the test methods when a new class is loaded 2246@add_metaclass(LLDBTestCaseFactory) 2247class TestBase(Base): 2248 """ 2249 This abstract base class is meant to be subclassed. It provides default 2250 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 2251 among other things. 2252 2253 Important things for test class writers: 2254 2255 - Overwrite the mydir class attribute, otherwise your test class won't 2256 run. It specifies the relative directory to the top level 'test' so 2257 the test harness can change to the correct working directory before 2258 running your test. 2259 2260 - The setUp method sets up things to facilitate subsequent interactions 2261 with the debugger as part of the test. These include: 2262 - populate the test method name 2263 - create/get a debugger set with synchronous mode (self.dbg) 2264 - get the command interpreter from with the debugger (self.ci) 2265 - create a result object for use with the command interpreter 2266 (self.res) 2267 - plus other stuffs 2268 2269 - The tearDown method tries to perform some necessary cleanup on behalf 2270 of the test to return the debugger to a good state for the next test. 2271 These include: 2272 - execute any tearDown hooks registered by the test method with 2273 TestBase.addTearDownHook(); examples can be found in 2274 settings/TestSettings.py 2275 - kill the inferior process associated with each target, if any, 2276 and, then delete the target from the debugger's target list 2277 - perform build cleanup before running the next test method in the 2278 same test class; examples of registering for this service can be 2279 found in types/TestIntegerTypes.py with the call: 2280 - self.setTearDownCleanup(dictionary=d) 2281 2282 - Similarly setUpClass and tearDownClass perform classwise setup and 2283 teardown fixtures. The tearDownClass method invokes a default build 2284 cleanup for the entire test class; also, subclasses can implement the 2285 classmethod classCleanup(cls) to perform special class cleanup action. 2286 2287 - The instance methods runCmd and expect are used heavily by existing 2288 test cases to send a command to the command interpreter and to perform 2289 string/pattern matching on the output of such command execution. The 2290 expect method also provides a mode to peform string/pattern matching 2291 without running a command. 2292 2293 - The build methods buildDefault, buildDsym, and buildDwarf are used to 2294 build the binaries used during a particular test scenario. A plugin 2295 should be provided for the sys.platform running the test suite. The 2296 Mac OS X implementation is located in plugins/darwin.py. 2297 """ 2298 2299 # Maximum allowed attempts when launching the inferior process. 2300 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 2301 maxLaunchCount = 3; 2302 2303 # Time to wait before the next launching attempt in second(s). 2304 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 2305 timeWaitNextLaunch = 1.0; 2306 2307 def doDelay(self): 2308 """See option -w of dotest.py.""" 2309 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and 2310 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'): 2311 waitTime = 1.0 2312 if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ: 2313 waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"]) 2314 time.sleep(waitTime) 2315 2316 # Returns the list of categories to which this test case belongs 2317 # by default, look for a ".categories" file, and read its contents 2318 # if no such file exists, traverse the hierarchy - we guarantee 2319 # a .categories to exist at the top level directory so we do not end up 2320 # looping endlessly - subclasses are free to define their own categories 2321 # in whatever way makes sense to them 2322 def getCategories(self): 2323 import inspect 2324 import os.path 2325 folder = inspect.getfile(self.__class__) 2326 folder = os.path.dirname(folder) 2327 while folder != '/': 2328 categories_file_name = os.path.join(folder,".categories") 2329 if os.path.exists(categories_file_name): 2330 categories_file = open(categories_file_name,'r') 2331 categories = categories_file.readline() 2332 categories_file.close() 2333 categories = str.replace(categories,'\n','') 2334 categories = str.replace(categories,'\r','') 2335 return categories.split(',') 2336 else: 2337 folder = os.path.dirname(folder) 2338 continue 2339 2340 def setUp(self): 2341 #import traceback 2342 #traceback.print_stack() 2343 2344 # Works with the test driver to conditionally skip tests via decorators. 2345 Base.setUp(self) 2346 2347 try: 2348 if lldb.blacklist: 2349 className = self.__class__.__name__ 2350 classAndMethodName = "%s.%s" % (className, self._testMethodName) 2351 if className in lldb.blacklist: 2352 self.skipTest(lldb.blacklist.get(className)) 2353 elif classAndMethodName in lldb.blacklist: 2354 self.skipTest(lldb.blacklist.get(classAndMethodName)) 2355 except AttributeError: 2356 pass 2357 2358 # Insert some delay between successive test cases if specified. 2359 self.doDelay() 2360 2361 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 2362 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 2363 2364 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 2365 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 2366 2367 # 2368 # Warning: MAJOR HACK AHEAD! 2369 # If we are running testsuite remotely (by checking lldb.lldbtest_remote_sandbox), 2370 # redefine the self.dbg.CreateTarget(filename) method to execute a "file filename" 2371 # command, instead. See also runCmd() where it decorates the "file filename" call 2372 # with additional functionality when running testsuite remotely. 2373 # 2374 if lldb.lldbtest_remote_sandbox: 2375 def DecoratedCreateTarget(arg): 2376 self.runCmd("file %s" % arg) 2377 target = self.dbg.GetSelectedTarget() 2378 # 2379 # SBtarget.LaunchSimple () currently not working for remote platform? 2380 # johnny @ 04/23/2012 2381 # 2382 def DecoratedLaunchSimple(argv, envp, wd): 2383 self.runCmd("run") 2384 return target.GetProcess() 2385 target.LaunchSimple = DecoratedLaunchSimple 2386 2387 return target 2388 self.dbg.CreateTarget = DecoratedCreateTarget 2389 if self.TraceOn(): 2390 print("self.dbg.Create is redefined to:\n%s" % getsource_if_available(DecoratedCreateTarget)) 2391 2392 # We want our debugger to be synchronous. 2393 self.dbg.SetAsync(False) 2394 2395 # Retrieve the associated command interpreter instance. 2396 self.ci = self.dbg.GetCommandInterpreter() 2397 if not self.ci: 2398 raise Exception('Could not get the command interpreter') 2399 2400 # And the result object. 2401 self.res = lldb.SBCommandReturnObject() 2402 2403 # Run global pre-flight code, if defined via the config file. 2404 if lldb.pre_flight: 2405 lldb.pre_flight(self) 2406 2407 if lldb.remote_platform and lldb.remote_platform_working_dir: 2408 remote_test_dir = lldbutil.join_remote_paths( 2409 lldb.remote_platform_working_dir, 2410 self.getArchitecture(), 2411 str(self.test_number), 2412 self.mydir) 2413 error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700 2414 if error.Success(): 2415 lldb.remote_platform.SetWorkingDirectory(remote_test_dir) 2416 2417 # This function removes all files from the current working directory while leaving 2418 # the directories in place. The cleaup is required to reduce the disk space required 2419 # by the test suit while leaving the directories untached is neccessary because 2420 # sub-directories might belong to an other test 2421 def clean_working_directory(): 2422 # TODO: Make it working on Windows when we need it for remote debugging support 2423 # TODO: Replace the heuristic to remove the files with a logic what collects the 2424 # list of files we have to remove during test runs. 2425 shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir) 2426 lldb.remote_platform.Run(shell_cmd) 2427 self.addTearDownHook(clean_working_directory) 2428 else: 2429 print("error: making remote directory '%s': %s" % (remote_test_dir, error)) 2430 2431 def registerSharedLibrariesWithTarget(self, target, shlibs): 2432 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing 2433 2434 Any modules in the target that have their remote install file specification set will 2435 get uploaded to the remote host. This function registers the local copies of the 2436 shared libraries with the target and sets their remote install locations so they will 2437 be uploaded when the target is run. 2438 ''' 2439 if not shlibs or not self.platformContext: 2440 return None 2441 2442 shlib_environment_var = self.platformContext.shlib_environment_var 2443 shlib_prefix = self.platformContext.shlib_prefix 2444 shlib_extension = '.' + self.platformContext.shlib_extension 2445 2446 working_dir = self.get_process_working_directory() 2447 environment = ['%s=%s' % (shlib_environment_var, working_dir)] 2448 # Add any shared libraries to our target if remote so they get 2449 # uploaded into the working directory on the remote side 2450 for name in shlibs: 2451 # The path can be a full path to a shared library, or a make file name like "Foo" for 2452 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a 2453 # basename like "libFoo.so". So figure out which one it is and resolve the local copy 2454 # of the shared library accordingly 2455 if os.path.exists(name): 2456 local_shlib_path = name # name is the full path to the local shared library 2457 else: 2458 # Check relative names 2459 local_shlib_path = os.path.join(os.getcwd(), shlib_prefix + name + shlib_extension) 2460 if not os.path.exists(local_shlib_path): 2461 local_shlib_path = os.path.join(os.getcwd(), name + shlib_extension) 2462 if not os.path.exists(local_shlib_path): 2463 local_shlib_path = os.path.join(os.getcwd(), name) 2464 2465 # Make sure we found the local shared library in the above code 2466 self.assertTrue(os.path.exists(local_shlib_path)) 2467 2468 # Add the shared library to our target 2469 shlib_module = target.AddModule(local_shlib_path, None, None, None) 2470 if lldb.remote_platform: 2471 # We must set the remote install location if we want the shared library 2472 # to get uploaded to the remote target 2473 remote_shlib_path = lldbutil.append_to_process_working_directory(os.path.basename(local_shlib_path)) 2474 shlib_module.SetRemoteInstallFileSpec(lldb.SBFileSpec(remote_shlib_path, False)) 2475 2476 return environment 2477 2478 # utility methods that tests can use to access the current objects 2479 def target(self): 2480 if not self.dbg: 2481 raise Exception('Invalid debugger instance') 2482 return self.dbg.GetSelectedTarget() 2483 2484 def process(self): 2485 if not self.dbg: 2486 raise Exception('Invalid debugger instance') 2487 return self.dbg.GetSelectedTarget().GetProcess() 2488 2489 def thread(self): 2490 if not self.dbg: 2491 raise Exception('Invalid debugger instance') 2492 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() 2493 2494 def frame(self): 2495 if not self.dbg: 2496 raise Exception('Invalid debugger instance') 2497 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() 2498 2499 def get_process_working_directory(self): 2500 '''Get the working directory that should be used when launching processes for local or remote processes.''' 2501 if lldb.remote_platform: 2502 # Remote tests set the platform working directory up in TestBase.setUp() 2503 return lldb.remote_platform.GetWorkingDirectory() 2504 else: 2505 # local tests change directory into each test subdirectory 2506 return os.getcwd() 2507 2508 def tearDown(self): 2509 #import traceback 2510 #traceback.print_stack() 2511 2512 # Ensure all the references to SB objects have gone away so that we can 2513 # be sure that all test-specific resources have been freed before we 2514 # attempt to delete the targets. 2515 gc.collect() 2516 2517 # Delete the target(s) from the debugger as a general cleanup step. 2518 # This includes terminating the process for each target, if any. 2519 # We'd like to reuse the debugger for our next test without incurring 2520 # the initialization overhead. 2521 targets = [] 2522 for target in self.dbg: 2523 if target: 2524 targets.append(target) 2525 process = target.GetProcess() 2526 if process: 2527 rc = self.invoke(process, "Kill") 2528 self.assertTrue(rc.Success(), PROCESS_KILLED) 2529 for target in targets: 2530 self.dbg.DeleteTarget(target) 2531 2532 # Run global post-flight code, if defined via the config file. 2533 if lldb.post_flight: 2534 lldb.post_flight(self) 2535 2536 # Do this last, to make sure it's in reverse order from how we setup. 2537 Base.tearDown(self) 2538 2539 # This must be the last statement, otherwise teardown hooks or other 2540 # lines might depend on this still being active. 2541 del self.dbg 2542 2543 def switch_to_thread_with_stop_reason(self, stop_reason): 2544 """ 2545 Run the 'thread list' command, and select the thread with stop reason as 2546 'stop_reason'. If no such thread exists, no select action is done. 2547 """ 2548 from .lldbutil import stop_reason_to_str 2549 self.runCmd('thread list') 2550 output = self.res.GetOutput() 2551 thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" % 2552 stop_reason_to_str(stop_reason)) 2553 for line in output.splitlines(): 2554 matched = thread_line_pattern.match(line) 2555 if matched: 2556 self.runCmd('thread select %s' % matched.group(1)) 2557 2558 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): 2559 """ 2560 Ask the command interpreter to handle the command and then check its 2561 return status. 2562 """ 2563 # Fail fast if 'cmd' is not meaningful. 2564 if not cmd or len(cmd) == 0: 2565 raise Exception("Bad 'cmd' parameter encountered") 2566 2567 trace = (True if traceAlways else trace) 2568 2569 # This is an opportunity to insert the 'platform target-install' command if we are told so 2570 # via the settig of lldb.lldbtest_remote_sandbox. 2571 if cmd.startswith("target create "): 2572 cmd = cmd.replace("target create ", "file ") 2573 if cmd.startswith("file ") and lldb.lldbtest_remote_sandbox: 2574 with recording(self, trace) as sbuf: 2575 the_rest = cmd.split("file ")[1] 2576 # Split the rest of the command line. 2577 atoms = the_rest.split() 2578 # 2579 # NOTE: This assumes that the options, if any, follow the file command, 2580 # instead of follow the specified target. 2581 # 2582 target = atoms[-1] 2583 # Now let's get the absolute pathname of our target. 2584 abs_target = os.path.abspath(target) 2585 print("Found a file command, target (with absolute pathname)=%s" % abs_target, file=sbuf) 2586 fpath, fname = os.path.split(abs_target) 2587 parent_dir = os.path.split(fpath)[0] 2588 platform_target_install_command = 'platform target-install %s %s' % (fpath, lldb.lldbtest_remote_sandbox) 2589 print("Insert this command to be run first: %s" % platform_target_install_command, file=sbuf) 2590 self.ci.HandleCommand(platform_target_install_command, self.res) 2591 # And this is the file command we want to execute, instead. 2592 # 2593 # Warning: SIDE EFFECT AHEAD!!! 2594 # Populate the remote executable pathname into the lldb namespace, 2595 # so that test cases can grab this thing out of the namespace. 2596 # 2597 lldb.lldbtest_remote_sandboxed_executable = abs_target.replace(parent_dir, lldb.lldbtest_remote_sandbox) 2598 cmd = "file -P %s %s %s" % (lldb.lldbtest_remote_sandboxed_executable, the_rest.replace(target, ''), abs_target) 2599 print("And this is the replaced file command: %s" % cmd, file=sbuf) 2600 2601 running = (cmd.startswith("run") or cmd.startswith("process launch")) 2602 2603 for i in range(self.maxLaunchCount if running else 1): 2604 self.ci.HandleCommand(cmd, self.res, inHistory) 2605 2606 with recording(self, trace) as sbuf: 2607 print("runCmd:", cmd, file=sbuf) 2608 if not check: 2609 print("check of return status not required", file=sbuf) 2610 if self.res.Succeeded(): 2611 print("output:", self.res.GetOutput(), file=sbuf) 2612 else: 2613 print("runCmd failed!", file=sbuf) 2614 print(self.res.GetError(), file=sbuf) 2615 2616 if self.res.Succeeded(): 2617 break 2618 elif running: 2619 # For process launch, wait some time before possible next try. 2620 time.sleep(self.timeWaitNextLaunch) 2621 with recording(self, trace) as sbuf: 2622 print("Command '" + cmd + "' failed!", file=sbuf) 2623 2624 if check: 2625 self.assertTrue(self.res.Succeeded(), 2626 msg if msg else CMD_MSG(cmd)) 2627 2628 def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True): 2629 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 2630 2631 Otherwise, all the arguments have the same meanings as for the expect function""" 2632 2633 trace = (True if traceAlways else trace) 2634 2635 if exe: 2636 # First run the command. If we are expecting error, set check=False. 2637 # Pass the assert message along since it provides more semantic info. 2638 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error) 2639 2640 # Then compare the output against expected strings. 2641 output = self.res.GetError() if error else self.res.GetOutput() 2642 2643 # If error is True, the API client expects the command to fail! 2644 if error: 2645 self.assertFalse(self.res.Succeeded(), 2646 "Command '" + str + "' is expected to fail!") 2647 else: 2648 # No execution required, just compare str against the golden input. 2649 output = str 2650 with recording(self, trace) as sbuf: 2651 print("looking at:", output, file=sbuf) 2652 2653 # The heading says either "Expecting" or "Not expecting". 2654 heading = "Expecting" if matching else "Not expecting" 2655 2656 for pattern in patterns: 2657 # Match Objects always have a boolean value of True. 2658 match_object = re.search(pattern, output) 2659 matched = bool(match_object) 2660 with recording(self, trace) as sbuf: 2661 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2662 print("Matched" if matched else "Not matched", file=sbuf) 2663 if matched: 2664 break 2665 2666 self.assertTrue(matched if matching else not matched, 2667 msg if msg else EXP_MSG(str, exe)) 2668 2669 return match_object 2670 2671 def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True, inHistory=False): 2672 """ 2673 Similar to runCmd; with additional expect style output matching ability. 2674 2675 Ask the command interpreter to handle the command and then check its 2676 return status. The 'msg' parameter specifies an informational assert 2677 message. We expect the output from running the command to start with 2678 'startstr', matches the substrings contained in 'substrs', and regexp 2679 matches the patterns contained in 'patterns'. 2680 2681 If the keyword argument error is set to True, it signifies that the API 2682 client is expecting the command to fail. In this case, the error stream 2683 from running the command is retrieved and compared against the golden 2684 input, instead. 2685 2686 If the keyword argument matching is set to False, it signifies that the API 2687 client is expecting the output of the command not to match the golden 2688 input. 2689 2690 Finally, the required argument 'str' represents the lldb command to be 2691 sent to the command interpreter. In case the keyword argument 'exe' is 2692 set to False, the 'str' is treated as a string to be matched/not-matched 2693 against the golden input. 2694 """ 2695 trace = (True if traceAlways else trace) 2696 2697 if exe: 2698 # First run the command. If we are expecting error, set check=False. 2699 # Pass the assert message along since it provides more semantic info. 2700 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error, inHistory=inHistory) 2701 2702 # Then compare the output against expected strings. 2703 output = self.res.GetError() if error else self.res.GetOutput() 2704 2705 # If error is True, the API client expects the command to fail! 2706 if error: 2707 self.assertFalse(self.res.Succeeded(), 2708 "Command '" + str + "' is expected to fail!") 2709 else: 2710 # No execution required, just compare str against the golden input. 2711 if isinstance(str,lldb.SBCommandReturnObject): 2712 output = str.GetOutput() 2713 else: 2714 output = str 2715 with recording(self, trace) as sbuf: 2716 print("looking at:", output, file=sbuf) 2717 2718 # The heading says either "Expecting" or "Not expecting". 2719 heading = "Expecting" if matching else "Not expecting" 2720 2721 # Start from the startstr, if specified. 2722 # If there's no startstr, set the initial state appropriately. 2723 matched = output.startswith(startstr) if startstr else (True if matching else False) 2724 2725 if startstr: 2726 with recording(self, trace) as sbuf: 2727 print("%s start string: %s" % (heading, startstr), file=sbuf) 2728 print("Matched" if matched else "Not matched", file=sbuf) 2729 2730 # Look for endstr, if specified. 2731 keepgoing = matched if matching else not matched 2732 if endstr: 2733 matched = output.endswith(endstr) 2734 with recording(self, trace) as sbuf: 2735 print("%s end string: %s" % (heading, endstr), file=sbuf) 2736 print("Matched" if matched else "Not matched", file=sbuf) 2737 2738 # Look for sub strings, if specified. 2739 keepgoing = matched if matching else not matched 2740 if substrs and keepgoing: 2741 for str in substrs: 2742 matched = output.find(str) != -1 2743 with recording(self, trace) as sbuf: 2744 print("%s sub string: %s" % (heading, str), file=sbuf) 2745 print("Matched" if matched else "Not matched", file=sbuf) 2746 keepgoing = matched if matching else not matched 2747 if not keepgoing: 2748 break 2749 2750 # Search for regular expression patterns, if specified. 2751 keepgoing = matched if matching else not matched 2752 if patterns and keepgoing: 2753 for pattern in patterns: 2754 # Match Objects always have a boolean value of True. 2755 matched = bool(re.search(pattern, output)) 2756 with recording(self, trace) as sbuf: 2757 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2758 print("Matched" if matched else "Not matched", file=sbuf) 2759 keepgoing = matched if matching else not matched 2760 if not keepgoing: 2761 break 2762 2763 self.assertTrue(matched if matching else not matched, 2764 msg if msg else EXP_MSG(str, exe)) 2765 2766 def invoke(self, obj, name, trace=False): 2767 """Use reflection to call a method dynamically with no argument.""" 2768 trace = (True if traceAlways else trace) 2769 2770 method = getattr(obj, name) 2771 import inspect 2772 self.assertTrue(inspect.ismethod(method), 2773 name + "is a method name of object: " + str(obj)) 2774 result = method() 2775 with recording(self, trace) as sbuf: 2776 print(str(method) + ":", result, file=sbuf) 2777 return result 2778 2779 def build(self, architecture=None, compiler=None, dictionary=None, clean=True): 2780 """Platform specific way to build the default binaries.""" 2781 if lldb.skip_build_and_cleanup: 2782 return 2783 module = builder_module() 2784 if target_is_android(): 2785 dictionary = append_android_envs(dictionary) 2786 if self.debug_info is None: 2787 return self.buildDefault(architecture, compiler, dictionary, clean) 2788 elif self.debug_info == "dsym": 2789 return self.buildDsym(architecture, compiler, dictionary, clean) 2790 elif self.debug_info == "dwarf": 2791 return self.buildDwarf(architecture, compiler, dictionary, clean) 2792 elif self.debug_info == "dwo": 2793 return self.buildDwo(architecture, compiler, dictionary, clean) 2794 else: 2795 self.fail("Can't build for debug info: %s" % self.debug_info) 2796 2797 # ================================================= 2798 # Misc. helper methods for debugging test execution 2799 # ================================================= 2800 2801 def DebugSBValue(self, val): 2802 """Debug print a SBValue object, if traceAlways is True.""" 2803 from .lldbutil import value_type_to_str 2804 2805 if not traceAlways: 2806 return 2807 2808 err = sys.stderr 2809 err.write(val.GetName() + ":\n") 2810 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 2811 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') 2812 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') 2813 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 2814 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n') 2815 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n') 2816 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 2817 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n') 2818 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 2819 2820 def DebugSBType(self, type): 2821 """Debug print a SBType object, if traceAlways is True.""" 2822 if not traceAlways: 2823 return 2824 2825 err = sys.stderr 2826 err.write(type.GetName() + ":\n") 2827 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n') 2828 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n') 2829 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n') 2830 2831 def DebugPExpect(self, child): 2832 """Debug the spwaned pexpect object.""" 2833 if not traceAlways: 2834 return 2835 2836 print(child) 2837 2838 @classmethod 2839 def RemoveTempFile(cls, file): 2840 if os.path.exists(file): 2841 os.remove(file) 2842