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