1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TesBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7The subclass should override the attribute mydir in order for the python runtime 8to locate the individual test cases when running as part of a large test suite 9or when running each test case as a separate python invocation. 10 11./dotest.py provides a test driver which sets up the environment to run the 12entire of part of the test suite . Example: 13 14# Exercises the test suite in the types directory.... 15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types 16... 17 18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' 19Command invoked: python ./dotest.py -A x86_64 types 20compilers=['clang'] 21 22Configuration: arch=x86_64 compiler=clang 23---------------------------------------------------------------------- 24Collected 72 tests 25 26........................................................................ 27---------------------------------------------------------------------- 28Ran 72 tests in 135.468s 29 30OK 31$ 32""" 33 34from __future__ import print_function 35from __future__ import absolute_import 36 37# System modules 38import abc 39import collections 40from functools import wraps 41import gc 42import glob 43import inspect 44import io 45import os, sys, traceback 46import os.path 47import re 48import signal 49from subprocess import * 50import time 51import types 52 53# Third-party modules 54import unittest2 55from six import add_metaclass 56from six import StringIO as SixStringIO 57import six 58 59# LLDB modules 60import use_lldb_suite 61import lldb 62from . import configuration 63from . import decorators 64from . import lldbplatformutil 65from . import lldbtest_config 66from . import lldbutil 67from . import test_categories 68from lldbsuite.support import encoded_file 69from lldbsuite.support import funcutils 70 71from .result_formatter import EventBuilder 72 73# dosep.py starts lots and lots of dotest instances 74# This option helps you find if two (or more) dotest instances are using the same 75# directory at the same time 76# Enable it to cause test failures and stderr messages if dotest instances try to run in 77# the same directory simultaneously 78# it is disabled by default because it litters the test directories with ".dirlock" files 79debug_confirm_directory_exclusivity = False 80 81# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 82# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options. 83 84# By default, traceAlways is False. 85if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES": 86 traceAlways = True 87else: 88 traceAlways = False 89 90# By default, doCleanup is True. 91if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO": 92 doCleanup = False 93else: 94 doCleanup = True 95 96 97# 98# Some commonly used assert messages. 99# 100 101COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 102 103CURRENT_EXECUTABLE_SET = "Current executable set successfully" 104 105PROCESS_IS_VALID = "Process is valid" 106 107PROCESS_KILLED = "Process is killed successfully" 108 109PROCESS_EXITED = "Process exited successfully" 110 111PROCESS_STOPPED = "Process status should be stopped" 112 113RUN_SUCCEEDED = "Process is launched successfully" 114 115RUN_COMPLETED = "Process exited successfully" 116 117BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 118 119BREAKPOINT_CREATED = "Breakpoint created successfully" 120 121BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 122 123BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 124 125BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" 126 127BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" 128 129BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" 130 131MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 132 133OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 134 135SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 136 137STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 138 139STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 140 141STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 142 143STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 144 145STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 146 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 147 148STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 149 150STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 151 152STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 153 154STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 155 156STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 157 158DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 159 160VALID_BREAKPOINT = "Got a valid breakpoint" 161 162VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 163 164VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 165 166VALID_FILESPEC = "Got a valid filespec" 167 168VALID_MODULE = "Got a valid module" 169 170VALID_PROCESS = "Got a valid process" 171 172VALID_SYMBOL = "Got a valid symbol" 173 174VALID_TARGET = "Got a valid target" 175 176VALID_PLATFORM = "Got a valid platform" 177 178VALID_TYPE = "Got a valid type" 179 180VALID_VARIABLE = "Got a valid variable" 181 182VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 183 184WATCHPOINT_CREATED = "Watchpoint created successfully" 185 186def CMD_MSG(str): 187 '''A generic "Command '%s' returns successfully" message generator.''' 188 return "Command '%s' returns successfully" % str 189 190def COMPLETION_MSG(str_before, str_after): 191 '''A generic message generator for the completion mechanism.''' 192 return "'%s' successfully completes to '%s'" % (str_before, str_after) 193 194def EXP_MSG(str, exe): 195 '''A generic "'%s' returns expected result" message generator if exe. 196 Otherwise, it generates "'%s' matches expected result" message.''' 197 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches') 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 os.remove(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 try: 1058 os.unlink(log_file) 1059 except: 1060 # We've seen consistent unlink failures on Windows, perhaps because the 1061 # just-created log file is being scanned by anti-virus. Empirically, this 1062 # sleep-and-retry approach allows tests to succeed much more reliably. 1063 # Attempts to figure out exactly what process was still holding a file handle 1064 # have failed because running instrumentation like Process Monitor seems to 1065 # slow things down enough that the problem becomes much less consistent. 1066 time.sleep(0.5) 1067 os.unlink(log_file) 1068 1069 # ==================================================== 1070 # Config. methods supported through a plugin interface 1071 # (enables reading of the current test configuration) 1072 # ==================================================== 1073 1074 def getArchitecture(self): 1075 """Returns the architecture in effect the test suite is running with.""" 1076 module = builder_module() 1077 arch = module.getArchitecture() 1078 if arch == 'amd64': 1079 arch = 'x86_64' 1080 return arch 1081 1082 def getLldbArchitecture(self): 1083 """Returns the architecture of the lldb binary.""" 1084 if not hasattr(self, 'lldbArchitecture'): 1085 1086 # spawn local process 1087 command = [ 1088 lldbtest_config.lldbExec, 1089 "-o", 1090 "file " + lldbtest_config.lldbExec, 1091 "-o", 1092 "quit" 1093 ] 1094 1095 output = check_output(command) 1096 str = output.decode("utf-8"); 1097 1098 for line in str.splitlines(): 1099 m = re.search("Current executable set to '.*' \\((.*)\\)\\.", line) 1100 if m: 1101 self.lldbArchitecture = m.group(1) 1102 break 1103 1104 return self.lldbArchitecture 1105 1106 def getCompiler(self): 1107 """Returns the compiler in effect the test suite is running with.""" 1108 module = builder_module() 1109 return module.getCompiler() 1110 1111 def getCompilerBinary(self): 1112 """Returns the compiler binary the test suite is running with.""" 1113 return self.getCompiler().split()[0] 1114 1115 def getCompilerVersion(self): 1116 """ Returns a string that represents the compiler version. 1117 Supports: llvm, clang. 1118 """ 1119 version = 'unknown' 1120 1121 compiler = self.getCompilerBinary() 1122 version_output = system([[compiler, "-v"]])[1] 1123 for line in version_output.split(os.linesep): 1124 m = re.search('version ([0-9\.]+)', line) 1125 if m: 1126 version = m.group(1) 1127 return version 1128 1129 def getGoCompilerVersion(self): 1130 """ Returns a string that represents the go compiler version, or None if go is not found. 1131 """ 1132 compiler = which("go") 1133 if compiler: 1134 version_output = system([[compiler, "version"]])[0] 1135 for line in version_output.split(os.linesep): 1136 m = re.search('go version (devel|go\\S+)', line) 1137 if m: 1138 return m.group(1) 1139 return None 1140 1141 def platformIsDarwin(self): 1142 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1143 return lldbplatformutil.platformIsDarwin() 1144 1145 def getPlatform(self): 1146 """Returns the target platform the test suite is running on.""" 1147 return lldbplatformutil.getPlatform() 1148 1149 def isIntelCompiler(self): 1150 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1151 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1152 1153 def expectedCompilerVersion(self, compiler_version): 1154 """Returns True iff compiler_version[1] matches the current compiler version. 1155 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1156 Any operator other than the following defaults to an equality test: 1157 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1158 """ 1159 if (compiler_version == None): 1160 return True 1161 operator = str(compiler_version[0]) 1162 version = compiler_version[1] 1163 1164 if (version == None): 1165 return True 1166 if (operator == '>'): 1167 return self.getCompilerVersion() > version 1168 if (operator == '>=' or operator == '=>'): 1169 return self.getCompilerVersion() >= version 1170 if (operator == '<'): 1171 return self.getCompilerVersion() < version 1172 if (operator == '<=' or operator == '=<'): 1173 return self.getCompilerVersion() <= version 1174 if (operator == '!=' or operator == '!' or operator == 'not'): 1175 return str(version) not in str(self.getCompilerVersion()) 1176 return str(version) in str(self.getCompilerVersion()) 1177 1178 def expectedCompiler(self, compilers): 1179 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1180 if (compilers == None): 1181 return True 1182 1183 for compiler in compilers: 1184 if compiler in self.getCompiler(): 1185 return True 1186 1187 return False 1188 1189 def expectedArch(self, archs): 1190 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1191 if (archs == None): 1192 return True 1193 1194 for arch in archs: 1195 if arch in self.getArchitecture(): 1196 return True 1197 1198 return False 1199 1200 def getRunOptions(self): 1201 """Command line option for -A and -C to run this test again, called from 1202 self.dumpSessionInfo().""" 1203 arch = self.getArchitecture() 1204 comp = self.getCompiler() 1205 if arch: 1206 option_str = "-A " + arch 1207 else: 1208 option_str = "" 1209 if comp: 1210 option_str += " -C " + comp 1211 return option_str 1212 1213 # ================================================== 1214 # Build methods supported through a plugin interface 1215 # ================================================== 1216 1217 def getstdlibFlag(self): 1218 """ Returns the proper -stdlib flag, or empty if not required.""" 1219 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1220 stdlibflag = "-stdlib=libc++" 1221 else: # this includes NetBSD 1222 stdlibflag = "" 1223 return stdlibflag 1224 1225 def getstdFlag(self): 1226 """ Returns the proper stdflag. """ 1227 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1228 stdflag = "-std=c++0x" 1229 else: 1230 stdflag = "-std=c++11" 1231 return stdflag 1232 1233 def buildDriver(self, sources, exe_name): 1234 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1235 or LLDB.framework). 1236 """ 1237 1238 stdflag = self.getstdFlag() 1239 stdlibflag = self.getstdlibFlag() 1240 1241 lib_dir = os.environ["LLDB_LIB_DIR"] 1242 if sys.platform.startswith("darwin"): 1243 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 1244 d = {'CXX_SOURCES' : sources, 1245 'EXE' : exe_name, 1246 'CFLAGS_EXTRAS' : "%s %s" % (stdflag, stdlibflag), 1247 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 1248 'LD_EXTRAS' : "%s -Wl,-rpath,%s" % (dsym, lib_dir), 1249 } 1250 elif sys.platform.rstrip('0123456789') in ('freebsd', 'linux', 'netbsd') or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 1251 d = {'CXX_SOURCES' : sources, 1252 'EXE' : exe_name, 1253 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1254 'LD_EXTRAS' : "-L%s -llldb" % lib_dir} 1255 elif sys.platform.startswith('win'): 1256 d = {'CXX_SOURCES' : sources, 1257 'EXE' : exe_name, 1258 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1259 'LD_EXTRAS' : "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]} 1260 if self.TraceOn(): 1261 print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources)) 1262 1263 self.buildDefault(dictionary=d) 1264 1265 def buildLibrary(self, sources, lib_name): 1266 """Platform specific way to build a default library. """ 1267 1268 stdflag = self.getstdFlag() 1269 1270 lib_dir = os.environ["LLDB_LIB_DIR"] 1271 if self.platformIsDarwin(): 1272 dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB') 1273 d = {'DYLIB_CXX_SOURCES' : sources, 1274 'DYLIB_NAME' : lib_name, 1275 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag, 1276 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir, 1277 'LD_EXTRAS' : "%s -Wl,-rpath,%s -dynamiclib" % (dsym, lib_dir), 1278 } 1279 elif self.getPlatform() in ('freebsd', 'linux', 'netbsd') or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 1280 d = {'DYLIB_CXX_SOURCES' : sources, 1281 'DYLIB_NAME' : lib_name, 1282 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1283 'LD_EXTRAS' : "-shared -L%s -llldb" % lib_dir} 1284 elif self.getPlatform() == 'windows': 1285 d = {'DYLIB_CXX_SOURCES' : sources, 1286 'DYLIB_NAME' : lib_name, 1287 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1288 'LD_EXTRAS' : "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]} 1289 if self.TraceOn(): 1290 print("Building LLDB Library (%s) from sources %s" % (lib_name, sources)) 1291 1292 self.buildDefault(dictionary=d) 1293 1294 def buildProgram(self, sources, exe_name): 1295 """ Platform specific way to build an executable from C/C++ sources. """ 1296 d = {'CXX_SOURCES' : sources, 1297 'EXE' : exe_name} 1298 self.buildDefault(dictionary=d) 1299 1300 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): 1301 """Platform specific way to build the default binaries.""" 1302 module = builder_module() 1303 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1304 if not module.buildDefault(self, architecture, compiler, dictionary, clean): 1305 raise Exception("Don't know how to build default binary") 1306 1307 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True): 1308 """Platform specific way to build binaries with dsym info.""" 1309 module = builder_module() 1310 if not module.buildDsym(self, architecture, compiler, dictionary, clean): 1311 raise Exception("Don't know how to build binary with dsym") 1312 1313 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): 1314 """Platform specific way to build binaries with dwarf maps.""" 1315 module = builder_module() 1316 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1317 if not module.buildDwarf(self, architecture, compiler, dictionary, clean): 1318 raise Exception("Don't know how to build binary with dwarf") 1319 1320 def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True): 1321 """Platform specific way to build binaries with dwarf maps.""" 1322 module = builder_module() 1323 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1324 if not module.buildDwo(self, architecture, compiler, dictionary, clean): 1325 raise Exception("Don't know how to build binary with dwo") 1326 1327 def buildGo(self): 1328 """Build the default go binary. 1329 """ 1330 system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']]) 1331 1332 def signBinary(self, binary_path): 1333 if sys.platform.startswith("darwin"): 1334 codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path) 1335 call(codesign_cmd, shell=True) 1336 1337 def findBuiltClang(self): 1338 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 1339 paths_to_try = [ 1340 "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang", 1341 "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang", 1342 "llvm-build/Release/x86_64/Release/bin/clang", 1343 "llvm-build/Debug/x86_64/Debug/bin/clang", 1344 ] 1345 lldb_root_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..") 1346 for p in paths_to_try: 1347 path = os.path.join(lldb_root_path, p) 1348 if os.path.exists(path): 1349 return path 1350 1351 # Tries to find clang at the same folder as the lldb 1352 path = os.path.join(os.path.dirname(lldbtest_config.lldbExec), "clang") 1353 if os.path.exists(path): 1354 return path 1355 1356 return os.environ["CC"] 1357 1358 def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False): 1359 """ Returns a dictionary (which can be provided to build* functions above) which 1360 contains OS-specific build flags. 1361 """ 1362 cflags = "" 1363 ldflags = "" 1364 1365 # On Mac OS X, unless specifically requested to use libstdc++, use libc++ 1366 if not use_libstdcxx and self.platformIsDarwin(): 1367 use_libcxx = True 1368 1369 if use_libcxx and self.libcxxPath: 1370 cflags += "-stdlib=libc++ " 1371 if self.libcxxPath: 1372 libcxxInclude = os.path.join(self.libcxxPath, "include") 1373 libcxxLib = os.path.join(self.libcxxPath, "lib") 1374 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): 1375 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (libcxxInclude, libcxxLib, libcxxLib) 1376 1377 if use_cpp11: 1378 cflags += "-std=" 1379 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1380 cflags += "c++0x" 1381 else: 1382 cflags += "c++11" 1383 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1384 cflags += " -stdlib=libc++" 1385 elif self.getPlatform() == "netbsd": 1386 cflags += " -stdlib=libstdc++" 1387 elif "clang" in self.getCompiler(): 1388 cflags += " -stdlib=libstdc++" 1389 1390 return {'CFLAGS_EXTRAS' : cflags, 1391 'LD_EXTRAS' : ldflags, 1392 } 1393 1394 def cleanup(self, dictionary=None): 1395 """Platform specific way to do cleanup after build.""" 1396 module = builder_module() 1397 if not module.cleanup(self, dictionary): 1398 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary) 1399 1400 def getLLDBLibraryEnvVal(self): 1401 """ Returns the path that the OS-specific library search environment variable 1402 (self.dylibPath) should be set to in order for a program to find the LLDB 1403 library. If an environment variable named self.dylibPath is already set, 1404 the new path is appended to it and returned. 1405 """ 1406 existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None 1407 lib_dir = os.environ["LLDB_LIB_DIR"] 1408 if existing_library_path: 1409 return "%s:%s" % (existing_library_path, lib_dir) 1410 elif sys.platform.startswith("darwin"): 1411 return os.path.join(lib_dir, 'LLDB.framework') 1412 else: 1413 return lib_dir 1414 1415 def getLibcPlusPlusLibs(self): 1416 if self.getPlatform() in ('freebsd', 'linux', 'netbsd'): 1417 return ['libc++.so.1'] 1418 else: 1419 return ['libc++.1.dylib','libc++abi.dylib'] 1420 1421# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. 1422# We change the test methods to create a new test method for each test for each debug info we are 1423# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding 1424# the new test method we remove the old method at the same time. 1425class LLDBTestCaseFactory(type): 1426 def __new__(cls, name, bases, attrs): 1427 newattrs = {} 1428 for attrname, attrvalue in attrs.items(): 1429 if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False): 1430 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 1431 1432 # If any debug info categories were explicitly tagged, assume that list to be 1433 # authoritative. If none were specified, try with all debug info formats. 1434 all_dbginfo_categories = set(test_categories.debug_info_categories) 1435 categories = set(getattr(attrvalue, "categories", [])) & all_dbginfo_categories 1436 if not categories: 1437 categories = all_dbginfo_categories 1438 1439 supported_categories = [x for x in categories 1440 if test_categories.is_supported_on_platform(x, target_platform)] 1441 if "dsym" in supported_categories: 1442 @decorators.add_test_categories(["dsym"]) 1443 @wraps(attrvalue) 1444 def dsym_test_method(self, attrvalue=attrvalue): 1445 self.debug_info = "dsym" 1446 return attrvalue(self) 1447 dsym_method_name = attrname + "_dsym" 1448 dsym_test_method.__name__ = dsym_method_name 1449 newattrs[dsym_method_name] = dsym_test_method 1450 1451 if "dwarf" in supported_categories: 1452 @decorators.add_test_categories(["dwarf"]) 1453 @wraps(attrvalue) 1454 def dwarf_test_method(self, attrvalue=attrvalue): 1455 self.debug_info = "dwarf" 1456 return attrvalue(self) 1457 dwarf_method_name = attrname + "_dwarf" 1458 dwarf_test_method.__name__ = dwarf_method_name 1459 newattrs[dwarf_method_name] = dwarf_test_method 1460 1461 if "dwo" in supported_categories: 1462 @decorators.add_test_categories(["dwo"]) 1463 @wraps(attrvalue) 1464 def dwo_test_method(self, attrvalue=attrvalue): 1465 self.debug_info = "dwo" 1466 return attrvalue(self) 1467 dwo_method_name = attrname + "_dwo" 1468 dwo_test_method.__name__ = dwo_method_name 1469 newattrs[dwo_method_name] = dwo_test_method 1470 else: 1471 newattrs[attrname] = attrvalue 1472 return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs) 1473 1474# Setup the metaclass for this class to change the list of the test methods when a new class is loaded 1475@add_metaclass(LLDBTestCaseFactory) 1476class TestBase(Base): 1477 """ 1478 This abstract base class is meant to be subclassed. It provides default 1479 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 1480 among other things. 1481 1482 Important things for test class writers: 1483 1484 - Overwrite the mydir class attribute, otherwise your test class won't 1485 run. It specifies the relative directory to the top level 'test' so 1486 the test harness can change to the correct working directory before 1487 running your test. 1488 1489 - The setUp method sets up things to facilitate subsequent interactions 1490 with the debugger as part of the test. These include: 1491 - populate the test method name 1492 - create/get a debugger set with synchronous mode (self.dbg) 1493 - get the command interpreter from with the debugger (self.ci) 1494 - create a result object for use with the command interpreter 1495 (self.res) 1496 - plus other stuffs 1497 1498 - The tearDown method tries to perform some necessary cleanup on behalf 1499 of the test to return the debugger to a good state for the next test. 1500 These include: 1501 - execute any tearDown hooks registered by the test method with 1502 TestBase.addTearDownHook(); examples can be found in 1503 settings/TestSettings.py 1504 - kill the inferior process associated with each target, if any, 1505 and, then delete the target from the debugger's target list 1506 - perform build cleanup before running the next test method in the 1507 same test class; examples of registering for this service can be 1508 found in types/TestIntegerTypes.py with the call: 1509 - self.setTearDownCleanup(dictionary=d) 1510 1511 - Similarly setUpClass and tearDownClass perform classwise setup and 1512 teardown fixtures. The tearDownClass method invokes a default build 1513 cleanup for the entire test class; also, subclasses can implement the 1514 classmethod classCleanup(cls) to perform special class cleanup action. 1515 1516 - The instance methods runCmd and expect are used heavily by existing 1517 test cases to send a command to the command interpreter and to perform 1518 string/pattern matching on the output of such command execution. The 1519 expect method also provides a mode to peform string/pattern matching 1520 without running a command. 1521 1522 - The build methods buildDefault, buildDsym, and buildDwarf are used to 1523 build the binaries used during a particular test scenario. A plugin 1524 should be provided for the sys.platform running the test suite. The 1525 Mac OS X implementation is located in plugins/darwin.py. 1526 """ 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, 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 str in substrs: 1886 matched = output.find(str) != -1 1887 with recording(self, trace) as sbuf: 1888 print("%s sub string: %s" % (heading, str), 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, 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 # ================================================= 1939 # Misc. helper methods for debugging test execution 1940 # ================================================= 1941 1942 def DebugSBValue(self, val): 1943 """Debug print a SBValue object, if traceAlways is True.""" 1944 from .lldbutil import value_type_to_str 1945 1946 if not traceAlways: 1947 return 1948 1949 err = sys.stderr 1950 err.write(val.GetName() + ":\n") 1951 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 1952 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') 1953 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') 1954 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 1955 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n') 1956 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n') 1957 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 1958 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n') 1959 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 1960 1961 def DebugSBType(self, type): 1962 """Debug print a SBType object, if traceAlways is True.""" 1963 if not traceAlways: 1964 return 1965 1966 err = sys.stderr 1967 err.write(type.GetName() + ":\n") 1968 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n') 1969 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n') 1970 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n') 1971 1972 def DebugPExpect(self, child): 1973 """Debug the spwaned pexpect object.""" 1974 if not traceAlways: 1975 return 1976 1977 print(child) 1978 1979 @classmethod 1980 def RemoveTempFile(cls, file): 1981 if os.path.exists(file): 1982 os.remove(file) 1983