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