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 absolute_import 35from __future__ import print_function 36 37# System modules 38import abc 39import collections 40from functools import wraps 41import gc 42import glob 43import inspect 44import io 45import os.path 46import re 47import signal 48from subprocess import * 49import sys 50import time 51import traceback 52import types 53 54# Third-party modules 55import unittest2 56from six import add_metaclass 57from six import StringIO as SixStringIO 58import six 59 60# LLDB modules 61import use_lldb_suite 62import lldb 63from . import configuration 64from . import decorators 65from . import lldbplatformutil 66from . import lldbtest_config 67from . import lldbutil 68from . import test_categories 69from lldbsuite.support import encoded_file 70from lldbsuite.support import funcutils 71 72# dosep.py starts lots and lots of dotest instances 73# This option helps you find if two (or more) dotest instances are using the same 74# directory at the same time 75# Enable it to cause test failures and stderr messages if dotest instances try to run in 76# the same directory simultaneously 77# it is disabled by default because it litters the test directories with ".dirlock" files 78debug_confirm_directory_exclusivity = False 79 80# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 81# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options. 82 83# By default, traceAlways is False. 84if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES": 85 traceAlways = True 86else: 87 traceAlways = False 88 89# By default, doCleanup is True. 90if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO": 91 doCleanup = False 92else: 93 doCleanup = True 94 95 96# 97# Some commonly used assert messages. 98# 99 100COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 101 102CURRENT_EXECUTABLE_SET = "Current executable set successfully" 103 104PROCESS_IS_VALID = "Process is valid" 105 106PROCESS_KILLED = "Process is killed successfully" 107 108PROCESS_EXITED = "Process exited successfully" 109 110PROCESS_STOPPED = "Process status should be stopped" 111 112RUN_SUCCEEDED = "Process is launched successfully" 113 114RUN_COMPLETED = "Process exited successfully" 115 116BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 117 118BREAKPOINT_CREATED = "Breakpoint created successfully" 119 120BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 121 122BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 123 124BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" 125 126BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" 127 128BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" 129 130MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 131 132OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 133 134SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 135 136STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 137 138STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 139 140STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 141 142STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 143 144STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 145 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 146 147STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 148 149STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 150 151STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 152 153STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 154 155STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 156 157DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 158 159VALID_BREAKPOINT = "Got a valid breakpoint" 160 161VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 162 163VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 164 165VALID_FILESPEC = "Got a valid filespec" 166 167VALID_MODULE = "Got a valid module" 168 169VALID_PROCESS = "Got a valid process" 170 171VALID_SYMBOL = "Got a valid symbol" 172 173VALID_TARGET = "Got a valid target" 174 175VALID_PLATFORM = "Got a valid platform" 176 177VALID_TYPE = "Got a valid type" 178 179VALID_VARIABLE = "Got a valid variable" 180 181VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 182 183WATCHPOINT_CREATED = "Watchpoint created successfully" 184 185def CMD_MSG(str): 186 '''A generic "Command '%s' returns successfully" message generator.''' 187 return "Command '%s' returns successfully" % str 188 189def COMPLETION_MSG(str_before, str_after): 190 '''A generic message generator for the completion mechanism.''' 191 return "'%s' successfully completes to '%s'" % (str_before, str_after) 192 193def EXP_MSG(str, actual, exe): 194 '''A generic "'%s' returns expected result" message generator if exe. 195 Otherwise, it generates "'%s' matches expected result" message.''' 196 197 return "'%s' %s expected result, got '%s'" % (str, 'returns' if exe else 'matches', actual.strip()) 198 199def SETTING_MSG(setting): 200 '''A generic "Value of setting '%s' is correct" message generator.''' 201 return "Value of setting '%s' is correct" % setting 202 203def EnvArray(): 204 """Returns an env variable array from the os.environ map object.""" 205 return list(map(lambda k,v: k+"="+v, list(os.environ.keys()), list(os.environ.values()))) 206 207def line_number(filename, string_to_match): 208 """Helper function to return the line number of the first matched string.""" 209 with io.open(filename, mode='r', encoding="utf-8") as f: 210 for i, line in enumerate(f): 211 if line.find(string_to_match) != -1: 212 # Found our match. 213 return i+1 214 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename)) 215 216def pointer_size(): 217 """Return the pointer size of the host system.""" 218 import ctypes 219 a_pointer = ctypes.c_void_p(0xffff) 220 return 8 * ctypes.sizeof(a_pointer) 221 222def is_exe(fpath): 223 """Returns true if fpath is an executable.""" 224 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 225 226def which(program): 227 """Returns the full path to a program; None otherwise.""" 228 fpath, fname = os.path.split(program) 229 if fpath: 230 if is_exe(program): 231 return program 232 else: 233 for path in os.environ["PATH"].split(os.pathsep): 234 exe_file = os.path.join(path, program) 235 if is_exe(exe_file): 236 return exe_file 237 return None 238 239class recording(SixStringIO): 240 """ 241 A nice little context manager for recording the debugger interactions into 242 our session object. If trace flag is ON, it also emits the interactions 243 into the stderr. 244 """ 245 def __init__(self, test, trace): 246 """Create a SixStringIO instance; record the session obj and trace flag.""" 247 SixStringIO.__init__(self) 248 # The test might not have undergone the 'setUp(self)' phase yet, so that 249 # the attribute 'session' might not even exist yet. 250 self.session = getattr(test, "session", None) if test else None 251 self.trace = trace 252 253 def __enter__(self): 254 """ 255 Context management protocol on entry to the body of the with statement. 256 Just return the SixStringIO object. 257 """ 258 return self 259 260 def __exit__(self, type, value, tb): 261 """ 262 Context management protocol on exit from the body of the with statement. 263 If trace is ON, it emits the recordings into stderr. Always add the 264 recordings to our session object. And close the SixStringIO object, too. 265 """ 266 if self.trace: 267 print(self.getvalue(), file=sys.stderr) 268 if self.session: 269 print(self.getvalue(), file=self.session) 270 self.close() 271 272@add_metaclass(abc.ABCMeta) 273class _BaseProcess(object): 274 275 @abc.abstractproperty 276 def pid(self): 277 """Returns process PID if has been launched already.""" 278 279 @abc.abstractmethod 280 def launch(self, executable, args): 281 """Launches new process with given executable and args.""" 282 283 @abc.abstractmethod 284 def terminate(self): 285 """Terminates previously launched process..""" 286 287class _LocalProcess(_BaseProcess): 288 289 def __init__(self, trace_on): 290 self._proc = None 291 self._trace_on = trace_on 292 self._delayafterterminate = 0.1 293 294 @property 295 def pid(self): 296 return self._proc.pid 297 298 def launch(self, executable, args): 299 self._proc = Popen([executable] + args, 300 stdout = open(os.devnull) if not self._trace_on else None, 301 stdin = PIPE) 302 303 def terminate(self): 304 if self._proc.poll() == None: 305 # Terminate _proc like it does the pexpect 306 signals_to_try = [sig for sig in ['SIGHUP', 'SIGCONT', 'SIGINT'] if sig in dir(signal)] 307 for sig in signals_to_try: 308 try: 309 self._proc.send_signal(getattr(signal, sig)) 310 time.sleep(self._delayafterterminate) 311 if self._proc.poll() != None: 312 return 313 except ValueError: 314 pass # Windows says SIGINT is not a valid signal to send 315 self._proc.terminate() 316 time.sleep(self._delayafterterminate) 317 if self._proc.poll() != None: 318 return 319 self._proc.kill() 320 time.sleep(self._delayafterterminate) 321 322 def poll(self): 323 return self._proc.poll() 324 325class _RemoteProcess(_BaseProcess): 326 327 def __init__(self, install_remote): 328 self._pid = None 329 self._install_remote = install_remote 330 331 @property 332 def pid(self): 333 return self._pid 334 335 def launch(self, executable, args): 336 if self._install_remote: 337 src_path = executable 338 dst_path = lldbutil.append_to_process_working_directory(os.path.basename(executable)) 339 340 dst_file_spec = lldb.SBFileSpec(dst_path, False) 341 err = lldb.remote_platform.Install(lldb.SBFileSpec(src_path, True), dst_file_spec) 342 if err.Fail(): 343 raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (src_path, dst_path, err)) 344 else: 345 dst_path = executable 346 dst_file_spec = lldb.SBFileSpec(executable, False) 347 348 launch_info = lldb.SBLaunchInfo(args) 349 launch_info.SetExecutableFile(dst_file_spec, True) 350 launch_info.SetWorkingDirectory(lldb.remote_platform.GetWorkingDirectory()) 351 352 # Redirect stdout and stderr to /dev/null 353 launch_info.AddSuppressFileAction(1, False, True) 354 launch_info.AddSuppressFileAction(2, False, True) 355 356 err = lldb.remote_platform.Launch(launch_info) 357 if err.Fail(): 358 raise Exception("remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err)) 359 self._pid = launch_info.GetProcessID() 360 361 def terminate(self): 362 lldb.remote_platform.Kill(self._pid) 363 364# From 2.7's subprocess.check_output() convenience function. 365# Return a tuple (stdoutdata, stderrdata). 366def system(commands, **kwargs): 367 r"""Run an os command with arguments and return its output as a byte string. 368 369 If the exit code was non-zero it raises a CalledProcessError. The 370 CalledProcessError object will have the return code in the returncode 371 attribute and output in the output attribute. 372 373 The arguments are the same as for the Popen constructor. Example: 374 375 >>> check_output(["ls", "-l", "/dev/null"]) 376 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 377 378 The stdout argument is not allowed as it is used internally. 379 To capture standard error in the result, use stderr=STDOUT. 380 381 >>> check_output(["/bin/sh", "-c", 382 ... "ls -l non_existent_file ; exit 0"], 383 ... stderr=STDOUT) 384 'ls: non_existent_file: No such file or directory\n' 385 """ 386 387 # Assign the sender object to variable 'test' and remove it from kwargs. 388 test = kwargs.pop('sender', None) 389 390 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo'] 391 commandList = [' '.join(x) for x in commands] 392 output = "" 393 error = "" 394 for shellCommand in commandList: 395 if 'stdout' in kwargs: 396 raise ValueError('stdout argument not allowed, it will be overridden.') 397 if 'shell' in kwargs and kwargs['shell']==False: 398 raise ValueError('shell=False not allowed') 399 process = Popen(shellCommand, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True, **kwargs) 400 pid = process.pid 401 this_output, this_error = process.communicate() 402 retcode = process.poll() 403 404 # Enable trace on failure return while tracking down FreeBSD buildbot issues 405 trace = traceAlways 406 if not trace and retcode and sys.platform.startswith("freebsd"): 407 trace = True 408 409 with recording(test, trace) as sbuf: 410 print(file=sbuf) 411 print("os command:", shellCommand, file=sbuf) 412 print("with pid:", pid, file=sbuf) 413 print("stdout:", this_output, file=sbuf) 414 print("stderr:", this_error, file=sbuf) 415 print("retcode:", retcode, file=sbuf) 416 print(file=sbuf) 417 418 if retcode: 419 cmd = kwargs.get("args") 420 if cmd is None: 421 cmd = shellCommand 422 raise CalledProcessError(retcode, cmd) 423 output = output + this_output 424 error = error + this_error 425 return (output, error) 426 427def getsource_if_available(obj): 428 """ 429 Return the text of the source code for an object if available. Otherwise, 430 a print representation is returned. 431 """ 432 import inspect 433 try: 434 return inspect.getsource(obj) 435 except: 436 return repr(obj) 437 438def builder_module(): 439 if sys.platform.startswith("freebsd"): 440 return __import__("builder_freebsd") 441 if sys.platform.startswith("netbsd"): 442 return __import__("builder_netbsd") 443 if sys.platform.startswith("linux"): 444 # sys.platform with Python-3.x returns 'linux', but with 445 # Python-2.x it returns 'linux2'. 446 return __import__("builder_linux") 447 return __import__("builder_" + sys.platform) 448 449 450class Base(unittest2.TestCase): 451 """ 452 Abstract base for performing lldb (see TestBase) or other generic tests (see 453 BenchBase for one example). lldbtest.Base works with the test driver to 454 accomplish things. 455 456 """ 457 458 # The concrete subclass should override this attribute. 459 mydir = None 460 461 # Keep track of the old current working directory. 462 oldcwd = None 463 464 @staticmethod 465 def compute_mydir(test_file): 466 '''Subclasses should call this function to correctly calculate the required "mydir" attribute as follows: 467 468 mydir = TestBase.compute_mydir(__file__)''' 469 test_dir = os.path.dirname(test_file) 470 return test_dir[len(os.environ["LLDB_TEST"])+1:] 471 472 def TraceOn(self): 473 """Returns True if we are in trace mode (tracing detailed test execution).""" 474 return traceAlways 475 476 @classmethod 477 def setUpClass(cls): 478 """ 479 Python unittest framework class setup fixture. 480 Do current directory manipulation. 481 """ 482 # Fail fast if 'mydir' attribute is not overridden. 483 if not cls.mydir or len(cls.mydir) == 0: 484 raise Exception("Subclasses must override the 'mydir' attribute.") 485 486 # Save old working directory. 487 cls.oldcwd = os.getcwd() 488 489 # Change current working directory if ${LLDB_TEST} is defined. 490 # See also dotest.py which sets up ${LLDB_TEST}. 491 if ("LLDB_TEST" in os.environ): 492 full_dir = os.path.join(os.environ["LLDB_TEST"], cls.mydir) 493 if traceAlways: 494 print("Change dir to:", full_dir, file=sys.stderr) 495 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir)) 496 497 if debug_confirm_directory_exclusivity: 498 import lock 499 cls.dir_lock = lock.Lock(os.path.join(full_dir, ".dirlock")) 500 try: 501 cls.dir_lock.try_acquire() 502 # write the class that owns the lock into the lock file 503 cls.dir_lock.handle.write(cls.__name__) 504 except IOError as ioerror: 505 # nothing else should have this directory lock 506 # wait here until we get a lock 507 cls.dir_lock.acquire() 508 # read the previous owner from the lock file 509 lock_id = cls.dir_lock.handle.read() 510 print("LOCK ERROR: {} wants to lock '{}' but it is already locked by '{}'".format(cls.__name__, full_dir, lock_id), file=sys.stderr) 511 raise ioerror 512 513 # Set platform context. 514 cls.platformContext = lldbplatformutil.createPlatformContext() 515 516 @classmethod 517 def tearDownClass(cls): 518 """ 519 Python unittest framework class teardown fixture. 520 Do class-wide cleanup. 521 """ 522 523 if doCleanup: 524 # First, let's do the platform-specific cleanup. 525 module = builder_module() 526 module.cleanup() 527 528 # Subclass might have specific cleanup function defined. 529 if getattr(cls, "classCleanup", None): 530 if traceAlways: 531 print("Call class-specific cleanup function for class:", cls, file=sys.stderr) 532 try: 533 cls.classCleanup() 534 except: 535 exc_type, exc_value, exc_tb = sys.exc_info() 536 traceback.print_exception(exc_type, exc_value, exc_tb) 537 538 if debug_confirm_directory_exclusivity: 539 cls.dir_lock.release() 540 del cls.dir_lock 541 542 # Restore old working directory. 543 if traceAlways: 544 print("Restore dir to:", cls.oldcwd, file=sys.stderr) 545 os.chdir(cls.oldcwd) 546 547 @classmethod 548 def skipLongRunningTest(cls): 549 """ 550 By default, we skip long running test case. 551 This can be overridden by passing '-l' to the test driver (dotest.py). 552 """ 553 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]: 554 return False 555 else: 556 return True 557 558 def enableLogChannelsForCurrentTest(self): 559 if len(lldbtest_config.channels) == 0: 560 return 561 562 # if debug channels are specified in lldbtest_config.channels, 563 # create a new set of log files for every test 564 log_basename = self.getLogBasenameForCurrentTest() 565 566 # confirm that the file is writeable 567 host_log_path = "{}-host.log".format(log_basename) 568 open(host_log_path, 'w').close() 569 570 log_enable = "log enable -Tpn -f {} ".format(host_log_path) 571 for channel_with_categories in lldbtest_config.channels: 572 channel_then_categories = channel_with_categories.split(' ', 1) 573 channel = channel_then_categories[0] 574 if len(channel_then_categories) > 1: 575 categories = channel_then_categories[1] 576 else: 577 categories = "default" 578 579 if channel == "gdb-remote": 580 # communicate gdb-remote categories to debugserver 581 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories 582 583 self.ci.HandleCommand(log_enable + channel_with_categories, self.res) 584 if not self.res.Succeeded(): 585 raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)') 586 587 # Communicate log path name to debugserver & lldb-server 588 server_log_path = "{}-server.log".format(log_basename) 589 open(server_log_path, 'w').close() 590 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path 591 592 # Communicate channels to lldb-server 593 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels) 594 595 if len(lldbtest_config.channels) == 0: 596 return 597 598 def disableLogChannelsForCurrentTest(self): 599 # close all log files that we opened 600 for channel_and_categories in lldbtest_config.channels: 601 # channel format - <channel-name> [<category0> [<category1> ...]] 602 channel = channel_and_categories.split(' ', 1)[0] 603 self.ci.HandleCommand("log disable " + channel, self.res) 604 if not self.res.Succeeded(): 605 raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)') 606 607 def setUp(self): 608 """Fixture for unittest test case setup. 609 610 It works with the test driver to conditionally skip tests and does other 611 initializations.""" 612 #import traceback 613 #traceback.print_stack() 614 615 if "LIBCXX_PATH" in os.environ: 616 self.libcxxPath = os.environ["LIBCXX_PATH"] 617 else: 618 self.libcxxPath = None 619 620 if "LLDBMI_EXEC" in os.environ: 621 self.lldbMiExec = os.environ["LLDBMI_EXEC"] 622 else: 623 self.lldbMiExec = None 624 625 # If we spawn an lldb process for test (via pexpect), do not load the 626 # init file unless told otherwise. 627 if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: 628 self.lldbOption = "" 629 else: 630 self.lldbOption = "--no-lldbinit" 631 632 # Assign the test method name to self.testMethodName. 633 # 634 # For an example of the use of this attribute, look at test/types dir. 635 # There are a bunch of test cases under test/types and we don't want the 636 # module cacheing subsystem to be confused with executable name "a.out" 637 # used for all the test cases. 638 self.testMethodName = self._testMethodName 639 640 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 641 # with it using pexpect. 642 self.child = None 643 self.child_prompt = "(lldb) " 644 # If the child is interacting with the embedded script interpreter, 645 # there are two exits required during tear down, first to quit the 646 # embedded script interpreter and second to quit the lldb command 647 # interpreter. 648 self.child_in_script_interpreter = False 649 650 # These are for customized teardown cleanup. 651 self.dict = None 652 self.doTearDownCleanup = False 653 # And in rare cases where there are multiple teardown cleanups. 654 self.dicts = [] 655 self.doTearDownCleanups = False 656 657 # List of spawned subproces.Popen objects 658 self.subprocesses = [] 659 660 # List of forked process PIDs 661 self.forkedProcessPids = [] 662 663 # Create a string buffer to record the session info, to be dumped into a 664 # test case specific file if test failure is encountered. 665 self.log_basename = self.getLogBasenameForCurrentTest() 666 667 session_file = "{}.log".format(self.log_basename) 668 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. 669 self.session = encoded_file.open(session_file, "utf-8", mode="w") 670 671 # Optimistically set __errored__, __failed__, __expected__ to False 672 # initially. If the test errored/failed, the session info 673 # (self.session) is then dumped into a session specific file for 674 # diagnosis. 675 self.__cleanup_errored__ = False 676 self.__errored__ = False 677 self.__failed__ = False 678 self.__expected__ = False 679 # We are also interested in unexpected success. 680 self.__unexpected__ = False 681 # And skipped tests. 682 self.__skipped__ = False 683 684 # See addTearDownHook(self, hook) which allows the client to add a hook 685 # function to be run during tearDown() time. 686 self.hooks = [] 687 688 # See HideStdout(self). 689 self.sys_stdout_hidden = False 690 691 if self.platformContext: 692 # set environment variable names for finding shared libraries 693 self.dylibPath = self.platformContext.shlib_environment_var 694 695 # Create the debugger instance if necessary. 696 try: 697 self.dbg = lldb.DBG 698 except AttributeError: 699 self.dbg = lldb.SBDebugger.Create() 700 701 if not self.dbg: 702 raise Exception('Invalid debugger instance') 703 704 # Retrieve the associated command interpreter instance. 705 self.ci = self.dbg.GetCommandInterpreter() 706 if not self.ci: 707 raise Exception('Could not get the command interpreter') 708 709 # And the result object. 710 self.res = lldb.SBCommandReturnObject() 711 712 self.enableLogChannelsForCurrentTest() 713 714 #Initialize debug_info 715 self.debug_info = None 716 717 def setAsync(self, value): 718 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 719 old_async = self.dbg.GetAsync() 720 self.dbg.SetAsync(value) 721 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 722 723 def cleanupSubprocesses(self): 724 # Ensure any subprocesses are cleaned up 725 for p in self.subprocesses: 726 p.terminate() 727 del p 728 del self.subprocesses[:] 729 # Ensure any forked processes are cleaned up 730 for pid in self.forkedProcessPids: 731 if os.path.exists("/proc/" + str(pid)): 732 os.kill(pid, signal.SIGTERM) 733 734 def spawnSubprocess(self, executable, args=[], install_remote=True): 735 """ Creates a subprocess.Popen object with the specified executable and arguments, 736 saves it in self.subprocesses, and returns the object. 737 NOTE: if using this function, ensure you also call: 738 739 self.addTearDownHook(self.cleanupSubprocesses) 740 741 otherwise the test suite will leak processes. 742 """ 743 proc = _RemoteProcess(install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) 744 proc.launch(executable, args) 745 self.subprocesses.append(proc) 746 return proc 747 748 def forkSubprocess(self, executable, args=[]): 749 """ Fork a subprocess with its own group ID. 750 NOTE: if using this function, ensure you also call: 751 752 self.addTearDownHook(self.cleanupSubprocesses) 753 754 otherwise the test suite will leak processes. 755 """ 756 child_pid = os.fork() 757 if child_pid == 0: 758 # If more I/O support is required, this can be beefed up. 759 fd = os.open(os.devnull, os.O_RDWR) 760 os.dup2(fd, 1) 761 os.dup2(fd, 2) 762 # This call causes the child to have its of group ID 763 os.setpgid(0,0) 764 os.execvp(executable, [executable] + args) 765 # Give the child time to get through the execvp() call 766 time.sleep(0.1) 767 self.forkedProcessPids.append(child_pid) 768 return child_pid 769 770 def HideStdout(self): 771 """Hide output to stdout from the user. 772 773 During test execution, there might be cases where we don't want to show the 774 standard output to the user. For example, 775 776 self.runCmd(r'''sc print("\n\n\tHello!\n")''') 777 778 tests whether command abbreviation for 'script' works or not. There is no 779 need to show the 'Hello' output to the user as long as the 'script' command 780 succeeds and we are not in TraceOn() mode (see the '-t' option). 781 782 In this case, the test method calls self.HideStdout(self) to redirect the 783 sys.stdout to a null device, and restores the sys.stdout upon teardown. 784 785 Note that you should only call this method at most once during a test case 786 execution. Any subsequent call has no effect at all.""" 787 if self.sys_stdout_hidden: 788 return 789 790 self.sys_stdout_hidden = True 791 old_stdout = sys.stdout 792 sys.stdout = open(os.devnull, 'w') 793 def restore_stdout(): 794 sys.stdout = old_stdout 795 self.addTearDownHook(restore_stdout) 796 797 # ======================================================================= 798 # Methods for customized teardown cleanups as well as execution of hooks. 799 # ======================================================================= 800 801 def setTearDownCleanup(self, dictionary=None): 802 """Register a cleanup action at tearDown() time with a dictinary""" 803 self.dict = dictionary 804 self.doTearDownCleanup = True 805 806 def addTearDownCleanup(self, dictionary): 807 """Add a cleanup action at tearDown() time with a dictinary""" 808 self.dicts.append(dictionary) 809 self.doTearDownCleanups = True 810 811 def addTearDownHook(self, hook): 812 """ 813 Add a function to be run during tearDown() time. 814 815 Hooks are executed in a first come first serve manner. 816 """ 817 if six.callable(hook): 818 with recording(self, traceAlways) as sbuf: 819 print("Adding tearDown hook:", getsource_if_available(hook), file=sbuf) 820 self.hooks.append(hook) 821 822 return self 823 824 def deletePexpectChild(self): 825 # This is for the case of directly spawning 'lldb' and interacting with it 826 # using pexpect. 827 if self.child and self.child.isalive(): 828 import pexpect 829 with recording(self, traceAlways) as sbuf: 830 print("tearing down the child process....", file=sbuf) 831 try: 832 if self.child_in_script_interpreter: 833 self.child.sendline('quit()') 834 self.child.expect_exact(self.child_prompt) 835 self.child.sendline('settings set interpreter.prompt-on-quit false') 836 self.child.sendline('quit') 837 self.child.expect(pexpect.EOF) 838 except (ValueError, pexpect.ExceptionPexpect): 839 # child is already terminated 840 pass 841 except OSError as exception: 842 import errno 843 if exception.errno != errno.EIO: 844 # unexpected error 845 raise 846 # child is already terminated 847 pass 848 finally: 849 # Give it one final blow to make sure the child is terminated. 850 self.child.close() 851 852 def tearDown(self): 853 """Fixture for unittest test case teardown.""" 854 #import traceback 855 #traceback.print_stack() 856 857 self.deletePexpectChild() 858 859 # Check and run any hook functions. 860 for hook in reversed(self.hooks): 861 with recording(self, traceAlways) as sbuf: 862 print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf) 863 if funcutils.requires_self(hook): 864 hook(self) 865 else: 866 hook() # try the plain call and hope it works 867 868 del self.hooks 869 870 # Perform registered teardown cleanup. 871 if doCleanup and self.doTearDownCleanup: 872 self.cleanup(dictionary=self.dict) 873 874 # In rare cases where there are multiple teardown cleanups added. 875 if doCleanup and self.doTearDownCleanups: 876 if self.dicts: 877 for dict in reversed(self.dicts): 878 self.cleanup(dictionary=dict) 879 880 self.disableLogChannelsForCurrentTest() 881 882 # ========================================================= 883 # Various callbacks to allow introspection of test progress 884 # ========================================================= 885 886 def markError(self): 887 """Callback invoked when an error (unexpected exception) errored.""" 888 self.__errored__ = True 889 with recording(self, False) as sbuf: 890 # False because there's no need to write "ERROR" to the stderr twice. 891 # Once by the Python unittest framework, and a second time by us. 892 print("ERROR", file=sbuf) 893 894 def markCleanupError(self): 895 """Callback invoked when an error occurs while a test is cleaning up.""" 896 self.__cleanup_errored__ = True 897 with recording(self, False) as sbuf: 898 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. 899 # Once by the Python unittest framework, and a second time by us. 900 print("CLEANUP_ERROR", file=sbuf) 901 902 def markFailure(self): 903 """Callback invoked when a failure (test assertion failure) occurred.""" 904 self.__failed__ = True 905 with recording(self, False) as sbuf: 906 # False because there's no need to write "FAIL" to the stderr twice. 907 # Once by the Python unittest framework, and a second time by us. 908 print("FAIL", file=sbuf) 909 910 def markExpectedFailure(self,err,bugnumber): 911 """Callback invoked when an expected failure/error occurred.""" 912 self.__expected__ = True 913 with recording(self, False) as sbuf: 914 # False because there's no need to write "expected failure" to the 915 # stderr twice. 916 # Once by the Python unittest framework, and a second time by us. 917 if bugnumber == None: 918 print("expected failure", file=sbuf) 919 else: 920 print("expected failure (problem id:" + str(bugnumber) + ")", file=sbuf) 921 922 def markSkippedTest(self): 923 """Callback invoked when a test is skipped.""" 924 self.__skipped__ = True 925 with recording(self, False) as sbuf: 926 # False because there's no need to write "skipped test" to the 927 # stderr twice. 928 # Once by the Python unittest framework, and a second time by us. 929 print("skipped test", file=sbuf) 930 931 def markUnexpectedSuccess(self, bugnumber): 932 """Callback invoked when an unexpected success occurred.""" 933 self.__unexpected__ = True 934 with recording(self, False) as sbuf: 935 # False because there's no need to write "unexpected success" to the 936 # stderr twice. 937 # Once by the Python unittest framework, and a second time by us. 938 if bugnumber == None: 939 print("unexpected success", file=sbuf) 940 else: 941 print("unexpected success (problem id:" + str(bugnumber) + ")", file=sbuf) 942 943 def getRerunArgs(self): 944 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) 945 946 def getLogBasenameForCurrentTest(self, prefix=None): 947 """ 948 returns a partial path that can be used as the beginning of the name of multiple 949 log files pertaining to this test 950 951 <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method> 952 """ 953 dname = os.path.join(os.environ["LLDB_TEST"], 954 os.environ["LLDB_SESSION_DIRNAME"]) 955 if not os.path.isdir(dname): 956 os.mkdir(dname) 957 958 compiler = self.getCompiler() 959 960 if compiler[1] == ':': 961 compiler = compiler[2:] 962 if os.path.altsep is not None: 963 compiler = compiler.replace(os.path.altsep, os.path.sep) 964 965 fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), "_".join(compiler.split(os.path.sep))) 966 if len(fname) > 200: 967 fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), compiler.split(os.path.sep)[-1]) 968 969 if prefix is not None: 970 fname = "{}-{}".format(prefix, fname) 971 972 return os.path.join(dname, fname) 973 974 def dumpSessionInfo(self): 975 """ 976 Dump the debugger interactions leading to a test error/failure. This 977 allows for more convenient postmortem analysis. 978 979 See also LLDBTestResult (dotest.py) which is a singlton class derived 980 from TextTestResult and overwrites addError, addFailure, and 981 addExpectedFailure methods to allow us to to mark the test instance as 982 such. 983 """ 984 985 # We are here because self.tearDown() detected that this test instance 986 # either errored or failed. The lldb.test_result singleton contains 987 # two lists (erros and failures) which get populated by the unittest 988 # framework. Look over there for stack trace information. 989 # 990 # The lists contain 2-tuples of TestCase instances and strings holding 991 # formatted tracebacks. 992 # 993 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 994 995 # output tracebacks into session 996 pairs = [] 997 if self.__errored__: 998 pairs = configuration.test_result.errors 999 prefix = 'Error' 1000 elif self.__cleanup_errored__: 1001 pairs = configuration.test_result.cleanup_errors 1002 prefix = 'CleanupError' 1003 elif self.__failed__: 1004 pairs = configuration.test_result.failures 1005 prefix = 'Failure' 1006 elif self.__expected__: 1007 pairs = configuration.test_result.expectedFailures 1008 prefix = 'ExpectedFailure' 1009 elif self.__skipped__: 1010 prefix = 'SkippedTest' 1011 elif self.__unexpected__: 1012 prefix = 'UnexpectedSuccess' 1013 else: 1014 prefix = 'Success' 1015 1016 if not self.__unexpected__ and not self.__skipped__: 1017 for test, traceback in pairs: 1018 if test is self: 1019 print(traceback, file=self.session) 1020 1021 # put footer (timestamp/rerun instructions) into session 1022 testMethod = getattr(self, self._testMethodName) 1023 if getattr(testMethod, "__benchmarks_test__", False): 1024 benchmarks = True 1025 else: 1026 benchmarks = False 1027 1028 import datetime 1029 print("Session info generated @", datetime.datetime.now().ctime(), file=self.session) 1030 print("To rerun this test, issue the following command from the 'test' directory:\n", file=self.session) 1031 print("./dotest.py %s -v %s %s" % (self.getRunOptions(), 1032 ('+b' if benchmarks else '-t'), 1033 self.getRerunArgs()), file=self.session) 1034 self.session.close() 1035 del self.session 1036 1037 # process the log files 1038 log_files_for_this_test = glob.glob(self.log_basename + "*") 1039 1040 if prefix != 'Success' or lldbtest_config.log_success: 1041 # keep all log files, rename them to include prefix 1042 dst_log_basename = self.getLogBasenameForCurrentTest(prefix) 1043 for src in log_files_for_this_test: 1044 if os.path.isfile(src): 1045 dst = src.replace(self.log_basename, dst_log_basename) 1046 if os.name == "nt" and os.path.isfile(dst): 1047 # On Windows, renaming a -> b will throw an exception if b exists. On non-Windows platforms 1048 # it silently replaces the destination. Ultimately this means that atomic renames are not 1049 # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the 1050 # destination first if it already exists. 1051 remove_file(dst) 1052 1053 os.rename(src, dst) 1054 else: 1055 # success! (and we don't want log files) delete log files 1056 for log_file in log_files_for_this_test: 1057 remove_file(log_file) 1058 1059 # ==================================================== 1060 # Config. methods supported through a plugin interface 1061 # (enables reading of the current test configuration) 1062 # ==================================================== 1063 1064 def getArchitecture(self): 1065 """Returns the architecture in effect the test suite is running with.""" 1066 module = builder_module() 1067 arch = module.getArchitecture() 1068 if arch == 'amd64': 1069 arch = 'x86_64' 1070 return arch 1071 1072 def getLldbArchitecture(self): 1073 """Returns the architecture of the lldb binary.""" 1074 if not hasattr(self, 'lldbArchitecture'): 1075 1076 # spawn local process 1077 command = [ 1078 lldbtest_config.lldbExec, 1079 "-o", 1080 "file " + lldbtest_config.lldbExec, 1081 "-o", 1082 "quit" 1083 ] 1084 1085 output = check_output(command) 1086 str = output.decode("utf-8"); 1087 1088 for line in str.splitlines(): 1089 m = re.search("Current executable set to '.*' \\((.*)\\)\\.", line) 1090 if m: 1091 self.lldbArchitecture = m.group(1) 1092 break 1093 1094 return self.lldbArchitecture 1095 1096 def getCompiler(self): 1097 """Returns the compiler in effect the test suite is running with.""" 1098 module = builder_module() 1099 return module.getCompiler() 1100 1101 def getCompilerBinary(self): 1102 """Returns the compiler binary the test suite is running with.""" 1103 return self.getCompiler().split()[0] 1104 1105 def getCompilerVersion(self): 1106 """ Returns a string that represents the compiler version. 1107 Supports: llvm, clang. 1108 """ 1109 version = 'unknown' 1110 1111 compiler = self.getCompilerBinary() 1112 version_output = system([[compiler, "-v"]])[1] 1113 for line in version_output.split(os.linesep): 1114 m = re.search('version ([0-9\.]+)', line) 1115 if m: 1116 version = m.group(1) 1117 return version 1118 1119 def getGoCompilerVersion(self): 1120 """ Returns a string that represents the go compiler version, or None if go is not found. 1121 """ 1122 compiler = which("go") 1123 if compiler: 1124 version_output = system([[compiler, "version"]])[0] 1125 for line in version_output.split(os.linesep): 1126 m = re.search('go version (devel|go\\S+)', line) 1127 if m: 1128 return m.group(1) 1129 return None 1130 1131 def platformIsDarwin(self): 1132 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1133 return lldbplatformutil.platformIsDarwin() 1134 1135 def getPlatform(self): 1136 """Returns the target platform the test suite is running on.""" 1137 return lldbplatformutil.getPlatform() 1138 1139 def isIntelCompiler(self): 1140 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1141 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1142 1143 def expectedCompilerVersion(self, compiler_version): 1144 """Returns True iff compiler_version[1] matches the current compiler version. 1145 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1146 Any operator other than the following defaults to an equality test: 1147 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1148 """ 1149 if (compiler_version == None): 1150 return True 1151 operator = str(compiler_version[0]) 1152 version = compiler_version[1] 1153 1154 if (version == None): 1155 return True 1156 if (operator == '>'): 1157 return self.getCompilerVersion() > version 1158 if (operator == '>=' or operator == '=>'): 1159 return self.getCompilerVersion() >= version 1160 if (operator == '<'): 1161 return self.getCompilerVersion() < version 1162 if (operator == '<=' or operator == '=<'): 1163 return self.getCompilerVersion() <= version 1164 if (operator == '!=' or operator == '!' or operator == 'not'): 1165 return str(version) not in str(self.getCompilerVersion()) 1166 return str(version) in str(self.getCompilerVersion()) 1167 1168 def expectedCompiler(self, compilers): 1169 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1170 if (compilers == None): 1171 return True 1172 1173 for compiler in compilers: 1174 if compiler in self.getCompiler(): 1175 return True 1176 1177 return False 1178 1179 def expectedArch(self, archs): 1180 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1181 if (archs == None): 1182 return True 1183 1184 for arch in archs: 1185 if arch in self.getArchitecture(): 1186 return True 1187 1188 return False 1189 1190 def getRunOptions(self): 1191 """Command line option for -A and -C to run this test again, called from 1192 self.dumpSessionInfo().""" 1193 arch = self.getArchitecture() 1194 comp = self.getCompiler() 1195 if arch: 1196 option_str = "-A " + arch 1197 else: 1198 option_str = "" 1199 if comp: 1200 option_str += " -C " + comp 1201 return option_str 1202 1203 # ================================================== 1204 # Build methods supported through a plugin interface 1205 # ================================================== 1206 1207 def getstdlibFlag(self): 1208 """ Returns the proper -stdlib flag, or empty if not required.""" 1209 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1210 stdlibflag = "-stdlib=libc++" 1211 else: # this includes NetBSD 1212 stdlibflag = "" 1213 return stdlibflag 1214 1215 def getstdFlag(self): 1216 """ Returns the proper stdflag. """ 1217 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1218 stdflag = "-std=c++0x" 1219 else: 1220 stdflag = "-std=c++11" 1221 return stdflag 1222 1223 def buildDriver(self, sources, exe_name): 1224 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1225 or LLDB.framework). 1226 """ 1227 1228 stdflag = self.getstdFlag() 1229 stdlibflag = self.getstdlibFlag() 1230 1231 lib_dir = os.environ["LLDB_LIB_DIR"] 1232 if sys.platform.startswith("darwin"): 1233 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 1234 d = {'CXX_SOURCES' : sources, 1235 'EXE' : exe_name, 1236 'CFLAGS_EXTRAS' : "%s %s" % (stdflag, stdlibflag), 1237 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 1238 'LD_EXTRAS' : "%s -Wl,-rpath,%s" % (dsym, lib_dir), 1239 } 1240 elif sys.platform.rstrip('0123456789') in ('freebsd', 'linux', 'netbsd') or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 1241 d = {'CXX_SOURCES' : sources, 1242 'EXE' : exe_name, 1243 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1244 'LD_EXTRAS' : "-L%s -llldb" % lib_dir} 1245 elif sys.platform.startswith('win'): 1246 d = {'CXX_SOURCES' : sources, 1247 'EXE' : exe_name, 1248 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1249 'LD_EXTRAS' : "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]} 1250 if self.TraceOn(): 1251 print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources)) 1252 1253 self.buildDefault(dictionary=d) 1254 1255 def buildLibrary(self, sources, lib_name): 1256 """Platform specific way to build a default library. """ 1257 1258 stdflag = self.getstdFlag() 1259 1260 lib_dir = os.environ["LLDB_LIB_DIR"] 1261 if self.platformIsDarwin(): 1262 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 1263 d = {'DYLIB_CXX_SOURCES' : sources, 1264 'DYLIB_NAME' : lib_name, 1265 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag, 1266 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 1267 'LD_EXTRAS' : "%s -Wl,-rpath,%s -dynamiclib" % (dsym, lib_dir), 1268 } 1269 elif self.getPlatform() in ('freebsd', 'linux', 'netbsd') or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 1270 d = {'DYLIB_CXX_SOURCES' : sources, 1271 'DYLIB_NAME' : lib_name, 1272 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1273 'LD_EXTRAS' : "-shared -L%s -llldb" % lib_dir} 1274 elif self.getPlatform() == 'windows': 1275 d = {'DYLIB_CXX_SOURCES' : sources, 1276 'DYLIB_NAME' : lib_name, 1277 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1278 'LD_EXTRAS' : "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]} 1279 if self.TraceOn(): 1280 print("Building LLDB Library (%s) from sources %s" % (lib_name, sources)) 1281 1282 self.buildDefault(dictionary=d) 1283 1284 def buildProgram(self, sources, exe_name): 1285 """ Platform specific way to build an executable from C/C++ sources. """ 1286 d = {'CXX_SOURCES' : sources, 1287 'EXE' : exe_name} 1288 self.buildDefault(dictionary=d) 1289 1290 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): 1291 """Platform specific way to build the default binaries.""" 1292 module = builder_module() 1293 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1294 if not module.buildDefault(self, architecture, compiler, dictionary, clean): 1295 raise Exception("Don't know how to build default binary") 1296 1297 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True): 1298 """Platform specific way to build binaries with dsym info.""" 1299 module = builder_module() 1300 if not module.buildDsym(self, architecture, compiler, dictionary, clean): 1301 raise Exception("Don't know how to build binary with dsym") 1302 1303 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): 1304 """Platform specific way to build binaries with dwarf maps.""" 1305 module = builder_module() 1306 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1307 if not module.buildDwarf(self, architecture, compiler, dictionary, clean): 1308 raise Exception("Don't know how to build binary with dwarf") 1309 1310 def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True): 1311 """Platform specific way to build binaries with dwarf maps.""" 1312 module = builder_module() 1313 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1314 if not module.buildDwo(self, architecture, compiler, dictionary, clean): 1315 raise Exception("Don't know how to build binary with dwo") 1316 1317 def buildGo(self): 1318 """Build the default go binary. 1319 """ 1320 system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']]) 1321 1322 def signBinary(self, binary_path): 1323 if sys.platform.startswith("darwin"): 1324 codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path) 1325 call(codesign_cmd, shell=True) 1326 1327 def findBuiltClang(self): 1328 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 1329 paths_to_try = [ 1330 "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang", 1331 "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang", 1332 "llvm-build/Release/x86_64/Release/bin/clang", 1333 "llvm-build/Debug/x86_64/Debug/bin/clang", 1334 ] 1335 lldb_root_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..") 1336 for p in paths_to_try: 1337 path = os.path.join(lldb_root_path, p) 1338 if os.path.exists(path): 1339 return path 1340 1341 # Tries to find clang at the same folder as the lldb 1342 path = os.path.join(os.path.dirname(lldbtest_config.lldbExec), "clang") 1343 if os.path.exists(path): 1344 return path 1345 1346 return os.environ["CC"] 1347 1348 def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False): 1349 """ Returns a dictionary (which can be provided to build* functions above) which 1350 contains OS-specific build flags. 1351 """ 1352 cflags = "" 1353 ldflags = "" 1354 1355 # On Mac OS X, unless specifically requested to use libstdc++, use libc++ 1356 if not use_libstdcxx and self.platformIsDarwin(): 1357 use_libcxx = True 1358 1359 if use_libcxx and self.libcxxPath: 1360 cflags += "-stdlib=libc++ " 1361 if self.libcxxPath: 1362 libcxxInclude = os.path.join(self.libcxxPath, "include") 1363 libcxxLib = os.path.join(self.libcxxPath, "lib") 1364 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): 1365 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (libcxxInclude, libcxxLib, libcxxLib) 1366 1367 if use_cpp11: 1368 cflags += "-std=" 1369 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1370 cflags += "c++0x" 1371 else: 1372 cflags += "c++11" 1373 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1374 cflags += " -stdlib=libc++" 1375 elif self.getPlatform() == "netbsd": 1376 cflags += " -stdlib=libstdc++" 1377 elif "clang" in self.getCompiler(): 1378 cflags += " -stdlib=libstdc++" 1379 1380 return {'CFLAGS_EXTRAS' : cflags, 1381 'LD_EXTRAS' : ldflags, 1382 } 1383 1384 def cleanup(self, dictionary=None): 1385 """Platform specific way to do cleanup after build.""" 1386 module = builder_module() 1387 if not module.cleanup(self, dictionary): 1388 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary) 1389 1390 def getLLDBLibraryEnvVal(self): 1391 """ Returns the path that the OS-specific library search environment variable 1392 (self.dylibPath) should be set to in order for a program to find the LLDB 1393 library. If an environment variable named self.dylibPath is already set, 1394 the new path is appended to it and returned. 1395 """ 1396 existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None 1397 lib_dir = os.environ["LLDB_LIB_DIR"] 1398 if existing_library_path: 1399 return "%s:%s" % (existing_library_path, lib_dir) 1400 elif sys.platform.startswith("darwin"): 1401 return os.path.join(lib_dir, 'LLDB.framework') 1402 else: 1403 return lib_dir 1404 1405 def getLibcPlusPlusLibs(self): 1406 if self.getPlatform() in ('freebsd', 'linux', 'netbsd'): 1407 return ['libc++.so.1'] 1408 else: 1409 return ['libc++.1.dylib','libc++abi.dylib'] 1410 1411# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. 1412# We change the test methods to create a new test method for each test for each debug info we are 1413# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding 1414# the new test method we remove the old method at the same time. This functionality can be 1415# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test 1416# level by using the decorator @no_debug_info_test. 1417class LLDBTestCaseFactory(type): 1418 def __new__(cls, name, bases, attrs): 1419 original_testcase = super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, attrs) 1420 if original_testcase.NO_DEBUG_INFO_TESTCASE: 1421 return original_testcase 1422 1423 newattrs = {} 1424 for attrname, attrvalue in attrs.items(): 1425 if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False): 1426 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 1427 1428 # If any debug info categories were explicitly tagged, assume that list to be 1429 # authoritative. If none were specified, try with all debug info formats. 1430 all_dbginfo_categories = set(test_categories.debug_info_categories) 1431 categories = set(getattr(attrvalue, "categories", [])) & all_dbginfo_categories 1432 if not categories: 1433 categories = all_dbginfo_categories 1434 1435 supported_categories = [x for x in categories 1436 if test_categories.is_supported_on_platform(x, target_platform)] 1437 if "dsym" in supported_categories: 1438 @decorators.add_test_categories(["dsym"]) 1439 @wraps(attrvalue) 1440 def dsym_test_method(self, attrvalue=attrvalue): 1441 self.debug_info = "dsym" 1442 return attrvalue(self) 1443 dsym_method_name = attrname + "_dsym" 1444 dsym_test_method.__name__ = dsym_method_name 1445 newattrs[dsym_method_name] = dsym_test_method 1446 1447 if "dwarf" in supported_categories: 1448 @decorators.add_test_categories(["dwarf"]) 1449 @wraps(attrvalue) 1450 def dwarf_test_method(self, attrvalue=attrvalue): 1451 self.debug_info = "dwarf" 1452 return attrvalue(self) 1453 dwarf_method_name = attrname + "_dwarf" 1454 dwarf_test_method.__name__ = dwarf_method_name 1455 newattrs[dwarf_method_name] = dwarf_test_method 1456 1457 if "dwo" in supported_categories: 1458 @decorators.add_test_categories(["dwo"]) 1459 @wraps(attrvalue) 1460 def dwo_test_method(self, attrvalue=attrvalue): 1461 self.debug_info = "dwo" 1462 return attrvalue(self) 1463 dwo_method_name = attrname + "_dwo" 1464 dwo_test_method.__name__ = dwo_method_name 1465 newattrs[dwo_method_name] = dwo_test_method 1466 else: 1467 newattrs[attrname] = attrvalue 1468 return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs) 1469 1470# Setup the metaclass for this class to change the list of the test methods when a new class is loaded 1471@add_metaclass(LLDBTestCaseFactory) 1472class TestBase(Base): 1473 """ 1474 This abstract base class is meant to be subclassed. It provides default 1475 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 1476 among other things. 1477 1478 Important things for test class writers: 1479 1480 - Overwrite the mydir class attribute, otherwise your test class won't 1481 run. It specifies the relative directory to the top level 'test' so 1482 the test harness can change to the correct working directory before 1483 running your test. 1484 1485 - The setUp method sets up things to facilitate subsequent interactions 1486 with the debugger as part of the test. These include: 1487 - populate the test method name 1488 - create/get a debugger set with synchronous mode (self.dbg) 1489 - get the command interpreter from with the debugger (self.ci) 1490 - create a result object for use with the command interpreter 1491 (self.res) 1492 - plus other stuffs 1493 1494 - The tearDown method tries to perform some necessary cleanup on behalf 1495 of the test to return the debugger to a good state for the next test. 1496 These include: 1497 - execute any tearDown hooks registered by the test method with 1498 TestBase.addTearDownHook(); examples can be found in 1499 settings/TestSettings.py 1500 - kill the inferior process associated with each target, if any, 1501 and, then delete the target from the debugger's target list 1502 - perform build cleanup before running the next test method in the 1503 same test class; examples of registering for this service can be 1504 found in types/TestIntegerTypes.py with the call: 1505 - self.setTearDownCleanup(dictionary=d) 1506 1507 - Similarly setUpClass and tearDownClass perform classwise setup and 1508 teardown fixtures. The tearDownClass method invokes a default build 1509 cleanup for the entire test class; also, subclasses can implement the 1510 classmethod classCleanup(cls) to perform special class cleanup action. 1511 1512 - The instance methods runCmd and expect are used heavily by existing 1513 test cases to send a command to the command interpreter and to perform 1514 string/pattern matching on the output of such command execution. The 1515 expect method also provides a mode to peform string/pattern matching 1516 without running a command. 1517 1518 - The build methods buildDefault, buildDsym, and buildDwarf are used to 1519 build the binaries used during a particular test scenario. A plugin 1520 should be provided for the sys.platform running the test suite. The 1521 Mac OS X implementation is located in plugins/darwin.py. 1522 """ 1523 1524 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the 1525 # test multiple times with various debug info types. 1526 NO_DEBUG_INFO_TESTCASE = False 1527 1528 # Maximum allowed attempts when launching the inferior process. 1529 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 1530 maxLaunchCount = 3; 1531 1532 # Time to wait before the next launching attempt in second(s). 1533 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 1534 timeWaitNextLaunch = 1.0; 1535 1536 # Returns the list of categories to which this test case belongs 1537 # by default, look for a ".categories" file, and read its contents 1538 # if no such file exists, traverse the hierarchy - we guarantee 1539 # a .categories to exist at the top level directory so we do not end up 1540 # looping endlessly - subclasses are free to define their own categories 1541 # in whatever way makes sense to them 1542 def getCategories(self): 1543 import inspect 1544 import os.path 1545 folder = inspect.getfile(self.__class__) 1546 folder = os.path.dirname(folder) 1547 while folder != '/': 1548 categories_file_name = os.path.join(folder,".categories") 1549 if os.path.exists(categories_file_name): 1550 categories_file = open(categories_file_name,'r') 1551 categories = categories_file.readline() 1552 categories_file.close() 1553 categories = str.replace(categories,'\n','') 1554 categories = str.replace(categories,'\r','') 1555 return categories.split(',') 1556 else: 1557 folder = os.path.dirname(folder) 1558 continue 1559 1560 def setUp(self): 1561 #import traceback 1562 #traceback.print_stack() 1563 1564 # Works with the test driver to conditionally skip tests via decorators. 1565 Base.setUp(self) 1566 1567 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 1568 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 1569 1570 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 1571 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 1572 1573 # We want our debugger to be synchronous. 1574 self.dbg.SetAsync(False) 1575 1576 # Retrieve the associated command interpreter instance. 1577 self.ci = self.dbg.GetCommandInterpreter() 1578 if not self.ci: 1579 raise Exception('Could not get the command interpreter') 1580 1581 # And the result object. 1582 self.res = lldb.SBCommandReturnObject() 1583 1584 if lldb.remote_platform and configuration.lldb_platform_working_dir: 1585 remote_test_dir = lldbutil.join_remote_paths( 1586 configuration.lldb_platform_working_dir, 1587 self.getArchitecture(), 1588 str(self.test_number), 1589 self.mydir) 1590 error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700 1591 if error.Success(): 1592 lldb.remote_platform.SetWorkingDirectory(remote_test_dir) 1593 1594 # This function removes all files from the current working directory while leaving 1595 # the directories in place. The cleaup is required to reduce the disk space required 1596 # by the test suit while leaving the directories untached is neccessary because 1597 # sub-directories might belong to an other test 1598 def clean_working_directory(): 1599 # TODO: Make it working on Windows when we need it for remote debugging support 1600 # TODO: Replace the heuristic to remove the files with a logic what collects the 1601 # list of files we have to remove during test runs. 1602 shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir) 1603 lldb.remote_platform.Run(shell_cmd) 1604 self.addTearDownHook(clean_working_directory) 1605 else: 1606 print("error: making remote directory '%s': %s" % (remote_test_dir, error)) 1607 1608 def registerSharedLibrariesWithTarget(self, target, shlibs): 1609 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing 1610 1611 Any modules in the target that have their remote install file specification set will 1612 get uploaded to the remote host. This function registers the local copies of the 1613 shared libraries with the target and sets their remote install locations so they will 1614 be uploaded when the target is run. 1615 ''' 1616 if not shlibs or not self.platformContext: 1617 return None 1618 1619 shlib_environment_var = self.platformContext.shlib_environment_var 1620 shlib_prefix = self.platformContext.shlib_prefix 1621 shlib_extension = '.' + self.platformContext.shlib_extension 1622 1623 working_dir = self.get_process_working_directory() 1624 environment = ['%s=%s' % (shlib_environment_var, working_dir)] 1625 # Add any shared libraries to our target if remote so they get 1626 # uploaded into the working directory on the remote side 1627 for name in shlibs: 1628 # The path can be a full path to a shared library, or a make file name like "Foo" for 1629 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a 1630 # basename like "libFoo.so". So figure out which one it is and resolve the local copy 1631 # of the shared library accordingly 1632 if os.path.exists(name): 1633 local_shlib_path = name # name is the full path to the local shared library 1634 else: 1635 # Check relative names 1636 local_shlib_path = os.path.join(os.getcwd(), shlib_prefix + name + shlib_extension) 1637 if not os.path.exists(local_shlib_path): 1638 local_shlib_path = os.path.join(os.getcwd(), name + shlib_extension) 1639 if not os.path.exists(local_shlib_path): 1640 local_shlib_path = os.path.join(os.getcwd(), name) 1641 1642 # Make sure we found the local shared library in the above code 1643 self.assertTrue(os.path.exists(local_shlib_path)) 1644 1645 # Add the shared library to our target 1646 shlib_module = target.AddModule(local_shlib_path, None, None, None) 1647 if lldb.remote_platform: 1648 # We must set the remote install location if we want the shared library 1649 # to get uploaded to the remote target 1650 remote_shlib_path = lldbutil.append_to_process_working_directory(os.path.basename(local_shlib_path)) 1651 shlib_module.SetRemoteInstallFileSpec(lldb.SBFileSpec(remote_shlib_path, False)) 1652 1653 return environment 1654 1655 # utility methods that tests can use to access the current objects 1656 def target(self): 1657 if not self.dbg: 1658 raise Exception('Invalid debugger instance') 1659 return self.dbg.GetSelectedTarget() 1660 1661 def process(self): 1662 if not self.dbg: 1663 raise Exception('Invalid debugger instance') 1664 return self.dbg.GetSelectedTarget().GetProcess() 1665 1666 def thread(self): 1667 if not self.dbg: 1668 raise Exception('Invalid debugger instance') 1669 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() 1670 1671 def frame(self): 1672 if not self.dbg: 1673 raise Exception('Invalid debugger instance') 1674 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() 1675 1676 def get_process_working_directory(self): 1677 '''Get the working directory that should be used when launching processes for local or remote processes.''' 1678 if lldb.remote_platform: 1679 # Remote tests set the platform working directory up in TestBase.setUp() 1680 return lldb.remote_platform.GetWorkingDirectory() 1681 else: 1682 # local tests change directory into each test subdirectory 1683 return os.getcwd() 1684 1685 def tearDown(self): 1686 #import traceback 1687 #traceback.print_stack() 1688 1689 # Ensure all the references to SB objects have gone away so that we can 1690 # be sure that all test-specific resources have been freed before we 1691 # attempt to delete the targets. 1692 gc.collect() 1693 1694 # Delete the target(s) from the debugger as a general cleanup step. 1695 # This includes terminating the process for each target, if any. 1696 # We'd like to reuse the debugger for our next test without incurring 1697 # the initialization overhead. 1698 targets = [] 1699 for target in self.dbg: 1700 if target: 1701 targets.append(target) 1702 process = target.GetProcess() 1703 if process: 1704 rc = self.invoke(process, "Kill") 1705 self.assertTrue(rc.Success(), PROCESS_KILLED) 1706 for target in targets: 1707 self.dbg.DeleteTarget(target) 1708 1709 # Do this last, to make sure it's in reverse order from how we setup. 1710 Base.tearDown(self) 1711 1712 # This must be the last statement, otherwise teardown hooks or other 1713 # lines might depend on this still being active. 1714 del self.dbg 1715 1716 def switch_to_thread_with_stop_reason(self, stop_reason): 1717 """ 1718 Run the 'thread list' command, and select the thread with stop reason as 1719 'stop_reason'. If no such thread exists, no select action is done. 1720 """ 1721 from .lldbutil import stop_reason_to_str 1722 self.runCmd('thread list') 1723 output = self.res.GetOutput() 1724 thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" % 1725 stop_reason_to_str(stop_reason)) 1726 for line in output.splitlines(): 1727 matched = thread_line_pattern.match(line) 1728 if matched: 1729 self.runCmd('thread select %s' % matched.group(1)) 1730 1731 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): 1732 """ 1733 Ask the command interpreter to handle the command and then check its 1734 return status. 1735 """ 1736 # Fail fast if 'cmd' is not meaningful. 1737 if not cmd or len(cmd) == 0: 1738 raise Exception("Bad 'cmd' parameter encountered") 1739 1740 trace = (True if traceAlways else trace) 1741 1742 if cmd.startswith("target create "): 1743 cmd = cmd.replace("target create ", "file ") 1744 1745 running = (cmd.startswith("run") or cmd.startswith("process launch")) 1746 1747 for i in range(self.maxLaunchCount if running else 1): 1748 self.ci.HandleCommand(cmd, self.res, inHistory) 1749 1750 with recording(self, trace) as sbuf: 1751 print("runCmd:", cmd, file=sbuf) 1752 if not check: 1753 print("check of return status not required", file=sbuf) 1754 if self.res.Succeeded(): 1755 print("output:", self.res.GetOutput(), file=sbuf) 1756 else: 1757 print("runCmd failed!", file=sbuf) 1758 print(self.res.GetError(), file=sbuf) 1759 1760 if self.res.Succeeded(): 1761 break 1762 elif running: 1763 # For process launch, wait some time before possible next try. 1764 time.sleep(self.timeWaitNextLaunch) 1765 with recording(self, trace) as sbuf: 1766 print("Command '" + cmd + "' failed!", file=sbuf) 1767 1768 if check: 1769 self.assertTrue(self.res.Succeeded(), 1770 msg if msg else CMD_MSG(cmd)) 1771 1772 def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True): 1773 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 1774 1775 Otherwise, all the arguments have the same meanings as for the expect function""" 1776 1777 trace = (True if traceAlways else trace) 1778 1779 if exe: 1780 # First run the command. If we are expecting error, set check=False. 1781 # Pass the assert message along since it provides more semantic info. 1782 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error) 1783 1784 # Then compare the output against expected strings. 1785 output = self.res.GetError() if error else self.res.GetOutput() 1786 1787 # If error is True, the API client expects the command to fail! 1788 if error: 1789 self.assertFalse(self.res.Succeeded(), 1790 "Command '" + str + "' is expected to fail!") 1791 else: 1792 # No execution required, just compare str against the golden input. 1793 output = str 1794 with recording(self, trace) as sbuf: 1795 print("looking at:", output, file=sbuf) 1796 1797 # The heading says either "Expecting" or "Not expecting". 1798 heading = "Expecting" if matching else "Not expecting" 1799 1800 for pattern in patterns: 1801 # Match Objects always have a boolean value of True. 1802 match_object = re.search(pattern, output) 1803 matched = bool(match_object) 1804 with recording(self, trace) as sbuf: 1805 print("%s pattern: %s" % (heading, pattern), file=sbuf) 1806 print("Matched" if matched else "Not matched", file=sbuf) 1807 if matched: 1808 break 1809 1810 self.assertTrue(matched if matching else not matched, 1811 msg if msg else EXP_MSG(str, output, exe)) 1812 1813 return match_object 1814 1815 def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True, inHistory=False): 1816 """ 1817 Similar to runCmd; with additional expect style output matching ability. 1818 1819 Ask the command interpreter to handle the command and then check its 1820 return status. The 'msg' parameter specifies an informational assert 1821 message. We expect the output from running the command to start with 1822 'startstr', matches the substrings contained in 'substrs', and regexp 1823 matches the patterns contained in 'patterns'. 1824 1825 If the keyword argument error is set to True, it signifies that the API 1826 client is expecting the command to fail. In this case, the error stream 1827 from running the command is retrieved and compared against the golden 1828 input, instead. 1829 1830 If the keyword argument matching is set to False, it signifies that the API 1831 client is expecting the output of the command not to match the golden 1832 input. 1833 1834 Finally, the required argument 'str' represents the lldb command to be 1835 sent to the command interpreter. In case the keyword argument 'exe' is 1836 set to False, the 'str' is treated as a string to be matched/not-matched 1837 against the golden input. 1838 """ 1839 trace = (True if traceAlways else trace) 1840 1841 if exe: 1842 # First run the command. If we are expecting error, set check=False. 1843 # Pass the assert message along since it provides more semantic info. 1844 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error, inHistory=inHistory) 1845 1846 # Then compare the output against expected strings. 1847 output = self.res.GetError() if error else self.res.GetOutput() 1848 1849 # If error is True, the API client expects the command to fail! 1850 if error: 1851 self.assertFalse(self.res.Succeeded(), 1852 "Command '" + str + "' is expected to fail!") 1853 else: 1854 # No execution required, just compare str against the golden input. 1855 if isinstance(str,lldb.SBCommandReturnObject): 1856 output = str.GetOutput() 1857 else: 1858 output = str 1859 with recording(self, trace) as sbuf: 1860 print("looking at:", output, file=sbuf) 1861 1862 # The heading says either "Expecting" or "Not expecting". 1863 heading = "Expecting" if matching else "Not expecting" 1864 1865 # Start from the startstr, if specified. 1866 # If there's no startstr, set the initial state appropriately. 1867 matched = output.startswith(startstr) if startstr else (True if matching else False) 1868 1869 if startstr: 1870 with recording(self, trace) as sbuf: 1871 print("%s start string: %s" % (heading, startstr), file=sbuf) 1872 print("Matched" if matched else "Not matched", file=sbuf) 1873 1874 # Look for endstr, if specified. 1875 keepgoing = matched if matching else not matched 1876 if endstr: 1877 matched = output.endswith(endstr) 1878 with recording(self, trace) as sbuf: 1879 print("%s end string: %s" % (heading, endstr), file=sbuf) 1880 print("Matched" if matched else "Not matched", file=sbuf) 1881 1882 # Look for sub strings, if specified. 1883 keepgoing = matched if matching else not matched 1884 if substrs and keepgoing: 1885 for substr in substrs: 1886 matched = output.find(substr) != -1 1887 with recording(self, trace) as sbuf: 1888 print("%s sub string: %s" % (heading, substr), file=sbuf) 1889 print("Matched" if matched else "Not matched", file=sbuf) 1890 keepgoing = matched if matching else not matched 1891 if not keepgoing: 1892 break 1893 1894 # Search for regular expression patterns, if specified. 1895 keepgoing = matched if matching else not matched 1896 if patterns and keepgoing: 1897 for pattern in patterns: 1898 # Match Objects always have a boolean value of True. 1899 matched = bool(re.search(pattern, output)) 1900 with recording(self, trace) as sbuf: 1901 print("%s pattern: %s" % (heading, pattern), file=sbuf) 1902 print("Matched" if matched else "Not matched", file=sbuf) 1903 keepgoing = matched if matching else not matched 1904 if not keepgoing: 1905 break 1906 1907 self.assertTrue(matched if matching else not matched, 1908 msg if msg else EXP_MSG(str, output, exe)) 1909 1910 def invoke(self, obj, name, trace=False): 1911 """Use reflection to call a method dynamically with no argument.""" 1912 trace = (True if traceAlways else trace) 1913 1914 method = getattr(obj, name) 1915 import inspect 1916 self.assertTrue(inspect.ismethod(method), 1917 name + "is a method name of object: " + str(obj)) 1918 result = method() 1919 with recording(self, trace) as sbuf: 1920 print(str(method) + ":", result, file=sbuf) 1921 return result 1922 1923 def build(self, architecture=None, compiler=None, dictionary=None, clean=True): 1924 """Platform specific way to build the default binaries.""" 1925 module = builder_module() 1926 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1927 if self.debug_info is None: 1928 return self.buildDefault(architecture, compiler, dictionary, clean) 1929 elif self.debug_info == "dsym": 1930 return self.buildDsym(architecture, compiler, dictionary, clean) 1931 elif self.debug_info == "dwarf": 1932 return self.buildDwarf(architecture, compiler, dictionary, clean) 1933 elif self.debug_info == "dwo": 1934 return self.buildDwo(architecture, compiler, dictionary, clean) 1935 else: 1936 self.fail("Can't build for debug info: %s" % self.debug_info) 1937 1938 def run_platform_command(self, cmd): 1939 platform = self.dbg.GetSelectedPlatform() 1940 shell_command = lldb.SBPlatformShellCommand(cmd) 1941 err = platform.Run(shell_command) 1942 return (err, shell_command.GetStatus(), shell_command.GetOutput()) 1943 1944 # ================================================= 1945 # Misc. helper methods for debugging test execution 1946 # ================================================= 1947 1948 def DebugSBValue(self, val): 1949 """Debug print a SBValue object, if traceAlways is True.""" 1950 from .lldbutil import value_type_to_str 1951 1952 if not traceAlways: 1953 return 1954 1955 err = sys.stderr 1956 err.write(val.GetName() + ":\n") 1957 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 1958 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') 1959 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') 1960 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 1961 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n') 1962 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n') 1963 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 1964 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n') 1965 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 1966 1967 def DebugSBType(self, type): 1968 """Debug print a SBType object, if traceAlways is True.""" 1969 if not traceAlways: 1970 return 1971 1972 err = sys.stderr 1973 err.write(type.GetName() + ":\n") 1974 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n') 1975 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n') 1976 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n') 1977 1978 def DebugPExpect(self, child): 1979 """Debug the spwaned pexpect object.""" 1980 if not traceAlways: 1981 return 1982 1983 print(child) 1984 1985 @classmethod 1986 def RemoveTempFile(cls, file): 1987 if os.path.exists(file): 1988 remove_file(file) 1989 1990# On Windows, the first attempt to delete a recently-touched file can fail 1991# because of a race with antimalware scanners. This function will detect a 1992# failure and retry. 1993def remove_file(file, num_retries = 1, sleep_duration = 0.5): 1994 for i in range(num_retries+1): 1995 try: 1996 os.remove(file) 1997 return True 1998 except: 1999 time.sleep(sleep_duration) 2000 continue 2001 return False 2002