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