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