1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TestBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7The subclass should override the attribute mydir in order for the python runtime 8to locate the individual test cases when running as part of a large test suite 9or when running each test case as a separate python invocation. 10 11./dotest.py provides a test driver which sets up the environment to run the 12entire of part of the test suite . Example: 13 14# Exercises the test suite in the types directory.... 15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types 16... 17 18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' 19Command invoked: python ./dotest.py -A x86_64 types 20compilers=['clang'] 21 22Configuration: arch=x86_64 compiler=clang 23---------------------------------------------------------------------- 24Collected 72 tests 25 26........................................................................ 27---------------------------------------------------------------------- 28Ran 72 tests in 135.468s 29 30OK 31$ 32""" 33 34from __future__ import absolute_import 35from __future__ import print_function 36 37# System modules 38import abc 39from distutils.version import LooseVersion 40from functools import wraps 41import gc 42import glob 43import io 44import os.path 45import re 46import shutil 47import signal 48from subprocess import * 49import sys 50import time 51import traceback 52import distutils.spawn 53 54# Third-party modules 55import unittest2 56from six import add_metaclass 57from six import StringIO as SixStringIO 58import six 59 60# LLDB modules 61import 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 71# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 72# LLDB_COMMAND_TRACE is set from '-t' option. 73 74# By default, traceAlways is False. 75if "LLDB_COMMAND_TRACE" in os.environ and os.environ[ 76 "LLDB_COMMAND_TRACE"] == "YES": 77 traceAlways = True 78else: 79 traceAlways = False 80 81# By default, doCleanup is True. 82if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"] == "NO": 83 doCleanup = False 84else: 85 doCleanup = True 86 87 88# 89# Some commonly used assert messages. 90# 91 92COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 93 94CURRENT_EXECUTABLE_SET = "Current executable set successfully" 95 96PROCESS_IS_VALID = "Process is valid" 97 98PROCESS_KILLED = "Process is killed successfully" 99 100PROCESS_EXITED = "Process exited successfully" 101 102PROCESS_STOPPED = "Process status should be stopped" 103 104RUN_SUCCEEDED = "Process is launched successfully" 105 106RUN_COMPLETED = "Process exited successfully" 107 108BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 109 110BREAKPOINT_CREATED = "Breakpoint created successfully" 111 112BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 113 114BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 115 116BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit count = 1" 117 118BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit count = 2" 119 120BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit count = 3" 121 122MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 123 124OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 125 126SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 127 128STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 129 130STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 131 132STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 133 134STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 135 136STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 137 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 138 139STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 140 141STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 142 143STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION = "Stopped due to breakpoint jitted condition" 144 145STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 146 147STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 148 149STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 150 151DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 152 153VALID_BREAKPOINT = "Got a valid breakpoint" 154 155VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 156 157VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 158 159VALID_FILESPEC = "Got a valid filespec" 160 161VALID_MODULE = "Got a valid module" 162 163VALID_PROCESS = "Got a valid process" 164 165VALID_SYMBOL = "Got a valid symbol" 166 167VALID_TARGET = "Got a valid target" 168 169VALID_PLATFORM = "Got a valid platform" 170 171VALID_TYPE = "Got a valid type" 172 173VALID_VARIABLE = "Got a valid variable" 174 175VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 176 177WATCHPOINT_CREATED = "Watchpoint created successfully" 178 179 180def CMD_MSG(str): 181 '''A generic "Command '%s' returns successfully" message generator.''' 182 return "Command '%s' returns successfully" % str 183 184 185def COMPLETION_MSG(str_before, str_after, completions): 186 '''A generic message generator for the completion mechanism.''' 187 return ("'%s' successfully completes to '%s', but completions were:\n%s" 188 % (str_before, str_after, "\n".join(completions))) 189 190 191def EXP_MSG(str, actual, exe): 192 '''A generic "'%s' returns expected result" message generator if exe. 193 Otherwise, it generates "'%s' matches expected result" message.''' 194 195 return "'%s' %s expected result, got '%s'" % ( 196 str, 'returns' if exe else 'matches', actual.strip()) 197 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 203 204def line_number(filename, string_to_match): 205 """Helper function to return the line number of the first matched string.""" 206 with io.open(filename, mode='r', encoding="utf-8") as f: 207 for i, line in enumerate(f): 208 if line.find(string_to_match) != -1: 209 # Found our match. 210 return i + 1 211 raise Exception( 212 "Unable to find '%s' within file %s" % 213 (string_to_match, filename)) 214 215def get_line(filename, line_number): 216 """Return the text of the line at the 1-based line number.""" 217 with io.open(filename, mode='r', encoding="utf-8") as f: 218 return f.readlines()[line_number - 1] 219 220def pointer_size(): 221 """Return the pointer size of the host system.""" 222 import ctypes 223 a_pointer = ctypes.c_void_p(0xffff) 224 return 8 * ctypes.sizeof(a_pointer) 225 226 227def is_exe(fpath): 228 """Returns true if fpath is an executable.""" 229 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 230 231 232def which(program): 233 """Returns the full path to a program; None otherwise.""" 234 fpath, fname = os.path.split(program) 235 if fpath: 236 if is_exe(program): 237 return program 238 else: 239 for path in os.environ["PATH"].split(os.pathsep): 240 exe_file = os.path.join(path, program) 241 if is_exe(exe_file): 242 return exe_file 243 return None 244 245 246class recording(SixStringIO): 247 """ 248 A nice little context manager for recording the debugger interactions into 249 our session object. If trace flag is ON, it also emits the interactions 250 into the stderr. 251 """ 252 253 def __init__(self, test, trace): 254 """Create a SixStringIO instance; record the session obj and trace flag.""" 255 SixStringIO.__init__(self) 256 # The test might not have undergone the 'setUp(self)' phase yet, so that 257 # the attribute 'session' might not even exist yet. 258 self.session = getattr(test, "session", None) if test else None 259 self.trace = trace 260 261 def __enter__(self): 262 """ 263 Context management protocol on entry to the body of the with statement. 264 Just return the SixStringIO object. 265 """ 266 return self 267 268 def __exit__(self, type, value, tb): 269 """ 270 Context management protocol on exit from the body of the with statement. 271 If trace is ON, it emits the recordings into stderr. Always add the 272 recordings to our session object. And close the SixStringIO object, too. 273 """ 274 if self.trace: 275 print(self.getvalue(), file=sys.stderr) 276 if self.session: 277 print(self.getvalue(), file=self.session) 278 self.close() 279 280 281@add_metaclass(abc.ABCMeta) 282class _BaseProcess(object): 283 284 @abc.abstractproperty 285 def pid(self): 286 """Returns process PID if has been launched already.""" 287 288 @abc.abstractmethod 289 def launch(self, executable, args): 290 """Launches new process with given executable and args.""" 291 292 @abc.abstractmethod 293 def terminate(self): 294 """Terminates previously launched process..""" 295 296 297class _LocalProcess(_BaseProcess): 298 299 def __init__(self, trace_on): 300 self._proc = None 301 self._trace_on = trace_on 302 self._delayafterterminate = 0.1 303 304 @property 305 def pid(self): 306 return self._proc.pid 307 308 def launch(self, executable, args): 309 self._proc = Popen( 310 [executable] + args, 311 stdout=open( 312 os.devnull) if not self._trace_on else None, 313 stdin=PIPE) 314 315 def terminate(self): 316 if self._proc.poll() is None: 317 # Terminate _proc like it does the pexpect 318 signals_to_try = [ 319 sig for sig in [ 320 'SIGHUP', 321 'SIGCONT', 322 'SIGINT'] if sig in dir(signal)] 323 for sig in signals_to_try: 324 try: 325 self._proc.send_signal(getattr(signal, sig)) 326 time.sleep(self._delayafterterminate) 327 if self._proc.poll() is not None: 328 return 329 except ValueError: 330 pass # Windows says SIGINT is not a valid signal to send 331 self._proc.terminate() 332 time.sleep(self._delayafterterminate) 333 if self._proc.poll() is not None: 334 return 335 self._proc.kill() 336 time.sleep(self._delayafterterminate) 337 338 def poll(self): 339 return self._proc.poll() 340 341 342class _RemoteProcess(_BaseProcess): 343 344 def __init__(self, install_remote): 345 self._pid = None 346 self._install_remote = install_remote 347 348 @property 349 def pid(self): 350 return self._pid 351 352 def launch(self, executable, args): 353 if self._install_remote: 354 src_path = executable 355 dst_path = lldbutil.join_remote_paths( 356 lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable)) 357 358 dst_file_spec = lldb.SBFileSpec(dst_path, False) 359 err = lldb.remote_platform.Install( 360 lldb.SBFileSpec(src_path, True), dst_file_spec) 361 if err.Fail(): 362 raise Exception( 363 "remote_platform.Install('%s', '%s') failed: %s" % 364 (src_path, dst_path, err)) 365 else: 366 dst_path = executable 367 dst_file_spec = lldb.SBFileSpec(executable, False) 368 369 launch_info = lldb.SBLaunchInfo(args) 370 launch_info.SetExecutableFile(dst_file_spec, True) 371 launch_info.SetWorkingDirectory( 372 lldb.remote_platform.GetWorkingDirectory()) 373 374 # Redirect stdout and stderr to /dev/null 375 launch_info.AddSuppressFileAction(1, False, True) 376 launch_info.AddSuppressFileAction(2, False, True) 377 378 err = lldb.remote_platform.Launch(launch_info) 379 if err.Fail(): 380 raise Exception( 381 "remote_platform.Launch('%s', '%s') failed: %s" % 382 (dst_path, args, err)) 383 self._pid = launch_info.GetProcessID() 384 385 def terminate(self): 386 lldb.remote_platform.Kill(self._pid) 387 388# From 2.7's subprocess.check_output() convenience function. 389# Return a tuple (stdoutdata, stderrdata). 390 391 392def system(commands, **kwargs): 393 r"""Run an os command with arguments and return its output as a byte string. 394 395 If the exit code was non-zero it raises a CalledProcessError. The 396 CalledProcessError object will have the return code in the returncode 397 attribute and output in the output attribute. 398 399 The arguments are the same as for the Popen constructor. Example: 400 401 >>> check_output(["ls", "-l", "/dev/null"]) 402 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 403 404 The stdout argument is not allowed as it is used internally. 405 To capture standard error in the result, use stderr=STDOUT. 406 407 >>> check_output(["/bin/sh", "-c", 408 ... "ls -l non_existent_file ; exit 0"], 409 ... stderr=STDOUT) 410 'ls: non_existent_file: No such file or directory\n' 411 """ 412 413 # Assign the sender object to variable 'test' and remove it from kwargs. 414 test = kwargs.pop('sender', None) 415 416 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo'] 417 commandList = [' '.join(x) for x in commands] 418 output = "" 419 error = "" 420 for shellCommand in commandList: 421 if 'stdout' in kwargs: 422 raise ValueError( 423 'stdout argument not allowed, it will be overridden.') 424 if 'shell' in kwargs and kwargs['shell'] == False: 425 raise ValueError('shell=False not allowed') 426 process = Popen( 427 shellCommand, 428 stdout=PIPE, 429 stderr=PIPE, 430 shell=True, 431 **kwargs) 432 pid = process.pid 433 this_output, this_error = process.communicate() 434 retcode = process.poll() 435 436 if retcode: 437 cmd = kwargs.get("args") 438 if cmd is None: 439 cmd = shellCommand 440 cpe = CalledProcessError(retcode, cmd) 441 # Ensure caller can access the stdout/stderr. 442 cpe.lldb_extensions = { 443 "stdout_content": this_output, 444 "stderr_content": this_error, 445 "command": shellCommand 446 } 447 raise cpe 448 output = output + this_output.decode("utf-8") 449 error = error + this_error.decode("utf-8") 450 return (output, error) 451 452 453def getsource_if_available(obj): 454 """ 455 Return the text of the source code for an object if available. Otherwise, 456 a print representation is returned. 457 """ 458 import inspect 459 try: 460 return inspect.getsource(obj) 461 except: 462 return repr(obj) 463 464 465def builder_module(): 466 if sys.platform.startswith("freebsd"): 467 return __import__("builder_freebsd") 468 if sys.platform.startswith("openbsd"): 469 return __import__("builder_openbsd") 470 if sys.platform.startswith("netbsd"): 471 return __import__("builder_netbsd") 472 if sys.platform.startswith("linux"): 473 # sys.platform with Python-3.x returns 'linux', but with 474 # Python-2.x it returns 'linux2'. 475 return __import__("builder_linux") 476 return __import__("builder_" + sys.platform) 477 478 479class Base(unittest2.TestCase): 480 """ 481 Abstract base for performing lldb (see TestBase) or other generic tests (see 482 BenchBase for one example). lldbtest.Base works with the test driver to 483 accomplish things. 484 485 """ 486 487 # The concrete subclass should override this attribute. 488 mydir = None 489 490 # Keep track of the old current working directory. 491 oldcwd = None 492 493 @staticmethod 494 def compute_mydir(test_file): 495 '''Subclasses should call this function to correctly calculate the 496 required "mydir" attribute as follows: 497 498 mydir = TestBase.compute_mydir(__file__) 499 ''' 500 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir 501 rel_prefix = test_file[len(os.environ["LLDB_TEST_SRC"]) + 1:] 502 return os.path.dirname(rel_prefix) 503 504 def TraceOn(self): 505 """Returns True if we are in trace mode (tracing detailed test execution).""" 506 return traceAlways 507 508 def trace(self, *args,**kwargs): 509 with recording(self, self.TraceOn()) as sbuf: 510 print(*args, file=sbuf, **kwargs) 511 512 @classmethod 513 def setUpClass(cls): 514 """ 515 Python unittest framework class setup fixture. 516 Do current directory manipulation. 517 """ 518 # Fail fast if 'mydir' attribute is not overridden. 519 if not cls.mydir or len(cls.mydir) == 0: 520 raise Exception("Subclasses must override the 'mydir' attribute.") 521 522 # Save old working directory. 523 cls.oldcwd = os.getcwd() 524 525 # Change current working directory if ${LLDB_TEST_SRC} is defined. 526 # See also dotest.py which sets up ${LLDB_TEST_SRC}. 527 if ("LLDB_TEST_SRC" in os.environ): 528 full_dir = os.path.join(os.environ["LLDB_TEST_SRC"], 529 cls.mydir) 530 if traceAlways: 531 print("Change dir to:", full_dir, file=sys.stderr) 532 os.chdir(full_dir) 533 lldb.SBReproducer.SetWorkingDirectory(full_dir) 534 535 # Set platform context. 536 cls.platformContext = lldbplatformutil.createPlatformContext() 537 538 @classmethod 539 def tearDownClass(cls): 540 """ 541 Python unittest framework class teardown fixture. 542 Do class-wide cleanup. 543 """ 544 545 if doCleanup: 546 # First, let's do the platform-specific cleanup. 547 module = builder_module() 548 module.cleanup() 549 550 # Subclass might have specific cleanup function defined. 551 if getattr(cls, "classCleanup", None): 552 if traceAlways: 553 print( 554 "Call class-specific cleanup function for class:", 555 cls, 556 file=sys.stderr) 557 try: 558 cls.classCleanup() 559 except: 560 exc_type, exc_value, exc_tb = sys.exc_info() 561 traceback.print_exception(exc_type, exc_value, exc_tb) 562 563 # Restore old working directory. 564 if traceAlways: 565 print("Restore dir to:", cls.oldcwd, file=sys.stderr) 566 os.chdir(cls.oldcwd) 567 568 def enableLogChannelsForCurrentTest(self): 569 if len(lldbtest_config.channels) == 0: 570 return 571 572 # if debug channels are specified in lldbtest_config.channels, 573 # create a new set of log files for every test 574 log_basename = self.getLogBasenameForCurrentTest() 575 576 # confirm that the file is writeable 577 host_log_path = "{}-host.log".format(log_basename) 578 open(host_log_path, 'w').close() 579 580 log_enable = "log enable -Tpn -f {} ".format(host_log_path) 581 for channel_with_categories in lldbtest_config.channels: 582 channel_then_categories = channel_with_categories.split(' ', 1) 583 channel = channel_then_categories[0] 584 if len(channel_then_categories) > 1: 585 categories = channel_then_categories[1] 586 else: 587 categories = "default" 588 589 if channel == "gdb-remote" and lldb.remote_platform is None: 590 # communicate gdb-remote categories to debugserver 591 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories 592 593 self.ci.HandleCommand( 594 log_enable + channel_with_categories, self.res) 595 if not self.res.Succeeded(): 596 raise Exception( 597 'log enable failed (check LLDB_LOG_OPTION env variable)') 598 599 # Communicate log path name to debugserver & lldb-server 600 # For remote debugging, these variables need to be set when starting the platform 601 # instance. 602 if lldb.remote_platform is None: 603 server_log_path = "{}-server.log".format(log_basename) 604 open(server_log_path, 'w').close() 605 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path 606 607 # Communicate channels to lldb-server 608 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join( 609 lldbtest_config.channels) 610 611 self.addTearDownHook(self.disableLogChannelsForCurrentTest) 612 613 def disableLogChannelsForCurrentTest(self): 614 # close all log files that we opened 615 for channel_and_categories in lldbtest_config.channels: 616 # channel format - <channel-name> [<category0> [<category1> ...]] 617 channel = channel_and_categories.split(' ', 1)[0] 618 self.ci.HandleCommand("log disable " + channel, self.res) 619 if not self.res.Succeeded(): 620 raise Exception( 621 'log disable failed (check LLDB_LOG_OPTION env variable)') 622 623 # Retrieve the server log (if any) from the remote system. It is assumed the server log 624 # is writing to the "server.log" file in the current test directory. This can be 625 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote 626 # platform. If the remote logging is not enabled, then just let the Get() command silently 627 # fail. 628 if lldb.remote_platform: 629 lldb.remote_platform.Get( 630 lldb.SBFileSpec("server.log"), lldb.SBFileSpec( 631 self.getLogBasenameForCurrentTest() + "-server.log")) 632 633 def setPlatformWorkingDir(self): 634 if not lldb.remote_platform or not configuration.lldb_platform_working_dir: 635 return 636 637 components = self.mydir.split(os.path.sep) + [str(self.test_number), self.getBuildDirBasename()] 638 remote_test_dir = configuration.lldb_platform_working_dir 639 for c in components: 640 remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c) 641 error = lldb.remote_platform.MakeDirectory( 642 remote_test_dir, 448) # 448 = 0o700 643 if error.Fail(): 644 raise Exception("making remote directory '%s': %s" % ( 645 remote_test_dir, error)) 646 647 lldb.remote_platform.SetWorkingDirectory(remote_test_dir) 648 649 # This function removes all files from the current working directory while leaving 650 # the directories in place. The cleanup is required to reduce the disk space required 651 # by the test suite while leaving the directories untouched is neccessary because 652 # sub-directories might belong to an other test 653 def clean_working_directory(): 654 # TODO: Make it working on Windows when we need it for remote debugging support 655 # TODO: Replace the heuristic to remove the files with a logic what collects the 656 # list of files we have to remove during test runs. 657 shell_cmd = lldb.SBPlatformShellCommand( 658 "rm %s/*" % remote_test_dir) 659 lldb.remote_platform.Run(shell_cmd) 660 self.addTearDownHook(clean_working_directory) 661 662 def getSourceDir(self): 663 """Return the full path to the current test.""" 664 return os.path.join(os.environ["LLDB_TEST_SRC"], self.mydir) 665 666 def getBuildDirBasename(self): 667 return self.__class__.__module__ + "." + self.testMethodName 668 669 def getBuildDir(self): 670 """Return the full path to the current test.""" 671 return os.path.join(configuration.test_build_dir, self.mydir, 672 self.getBuildDirBasename()) 673 674 def getReproducerDir(self): 675 """Return the full path to the reproducer if enabled.""" 676 if configuration.capture_path: 677 return configuration.capture_path 678 if configuration.replay_path: 679 return configuration.replay_path 680 return None 681 682 def makeBuildDir(self): 683 """Create the test-specific working directory, deleting any previous 684 contents.""" 685 bdir = self.getBuildDir() 686 if os.path.isdir(bdir): 687 shutil.rmtree(bdir) 688 lldbutil.mkdir_p(bdir) 689 690 def getBuildArtifact(self, name="a.out"): 691 """Return absolute path to an artifact in the test's build directory.""" 692 return os.path.join(self.getBuildDir(), name) 693 694 def getSourcePath(self, name): 695 """Return absolute path to a file in the test's source directory.""" 696 return os.path.join(self.getSourceDir(), name) 697 698 def getReproducerArtifact(self, name): 699 return os.path.join(self.getReproducerDir(), name) 700 701 @classmethod 702 def setUpCommands(cls): 703 commands = [ 704 # First of all, clear all settings to have clean state of global properties. 705 "settings clear -all", 706 707 # Disable Spotlight lookup. The testsuite creates 708 # different binaries with the same UUID, because they only 709 # differ in the debug info, which is not being hashed. 710 "settings set symbols.enable-external-lookup false", 711 712 # Disable fix-its by default so that incorrect expressions in tests don't 713 # pass just because Clang thinks it has a fix-it. 714 "settings set target.auto-apply-fixits false", 715 716 # Testsuite runs in parallel and the host can have also other load. 717 "settings set plugin.process.gdb-remote.packet-timeout 60", 718 719 'settings set symbols.clang-modules-cache-path "{}"'.format( 720 configuration.lldb_module_cache_dir), 721 "settings set use-color false", 722 ] 723 724 # Set any user-overridden settings. 725 for setting, value in configuration.settings: 726 commands.append('setting set %s %s'%(setting, value)) 727 728 # Make sure that a sanitizer LLDB's environment doesn't get passed on. 729 if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ: 730 commands.append('settings set target.env-vars {}='.format( 731 cls.platformContext.shlib_environment_var)) 732 733 # Set environment variables for the inferior. 734 if lldbtest_config.inferior_env: 735 commands.append('settings set target.env-vars {}'.format( 736 lldbtest_config.inferior_env)) 737 return commands 738 739 def setUp(self): 740 """Fixture for unittest test case setup. 741 742 It works with the test driver to conditionally skip tests and does other 743 initializations.""" 744 #import traceback 745 # traceback.print_stack() 746 747 if "LIBCXX_PATH" in os.environ: 748 self.libcxxPath = os.environ["LIBCXX_PATH"] 749 else: 750 self.libcxxPath = None 751 752 if "LLDBVSCODE_EXEC" in os.environ: 753 self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] 754 else: 755 self.lldbVSCodeExec = None 756 757 self.lldbOption = " ".join( 758 "-o '" + s + "'" for s in self.setUpCommands()) 759 760 # If we spawn an lldb process for test (via pexpect), do not load the 761 # init file unless told otherwise. 762 if os.environ.get("NO_LLDBINIT") != "NO": 763 self.lldbOption += " --no-lldbinit" 764 765 # Assign the test method name to self.testMethodName. 766 # 767 # For an example of the use of this attribute, look at test/types dir. 768 # There are a bunch of test cases under test/types and we don't want the 769 # module cacheing subsystem to be confused with executable name "a.out" 770 # used for all the test cases. 771 self.testMethodName = self._testMethodName 772 773 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 774 # with it using pexpect. 775 self.child = None 776 self.child_prompt = "(lldb) " 777 # If the child is interacting with the embedded script interpreter, 778 # there are two exits required during tear down, first to quit the 779 # embedded script interpreter and second to quit the lldb command 780 # interpreter. 781 self.child_in_script_interpreter = False 782 783 # These are for customized teardown cleanup. 784 self.dict = None 785 self.doTearDownCleanup = False 786 # And in rare cases where there are multiple teardown cleanups. 787 self.dicts = [] 788 self.doTearDownCleanups = False 789 790 # List of spawned subproces.Popen objects 791 self.subprocesses = [] 792 793 # List of forked process PIDs 794 self.forkedProcessPids = [] 795 796 # Create a string buffer to record the session info, to be dumped into a 797 # test case specific file if test failure is encountered. 798 self.log_basename = self.getLogBasenameForCurrentTest() 799 800 session_file = "{}.log".format(self.log_basename) 801 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. 802 self.session = encoded_file.open(session_file, "utf-8", mode="w") 803 804 # Optimistically set __errored__, __failed__, __expected__ to False 805 # initially. If the test errored/failed, the session info 806 # (self.session) is then dumped into a session specific file for 807 # diagnosis. 808 self.__cleanup_errored__ = False 809 self.__errored__ = False 810 self.__failed__ = False 811 self.__expected__ = False 812 # We are also interested in unexpected success. 813 self.__unexpected__ = False 814 # And skipped tests. 815 self.__skipped__ = False 816 817 # See addTearDownHook(self, hook) which allows the client to add a hook 818 # function to be run during tearDown() time. 819 self.hooks = [] 820 821 # See HideStdout(self). 822 self.sys_stdout_hidden = False 823 824 if self.platformContext: 825 # set environment variable names for finding shared libraries 826 self.dylibPath = self.platformContext.shlib_environment_var 827 828 # Create the debugger instance. 829 self.dbg = lldb.SBDebugger.Create() 830 # Copy selected platform from a global instance if it exists. 831 if lldb.selected_platform is not None: 832 self.dbg.SetSelectedPlatform(lldb.selected_platform) 833 834 if not self.dbg: 835 raise Exception('Invalid debugger instance') 836 837 # Retrieve the associated command interpreter instance. 838 self.ci = self.dbg.GetCommandInterpreter() 839 if not self.ci: 840 raise Exception('Could not get the command interpreter') 841 842 # And the result object. 843 self.res = lldb.SBCommandReturnObject() 844 845 self.setPlatformWorkingDir() 846 self.enableLogChannelsForCurrentTest() 847 848 lib_dir = os.environ["LLDB_LIB_DIR"] 849 self.dsym = None 850 self.framework_dir = None 851 self.darwinWithFramework = self.platformIsDarwin() 852 if sys.platform.startswith("darwin"): 853 # Handle the framework environment variable if it is set 854 if hasattr(lldbtest_config, 'lldb_framework_path'): 855 framework_path = lldbtest_config.lldb_framework_path 856 # Framework dir should be the directory containing the framework 857 self.framework_dir = framework_path[:framework_path.rfind('LLDB.framework')] 858 # If a framework dir was not specified assume the Xcode build 859 # directory layout where the framework is in LLDB_LIB_DIR. 860 else: 861 self.framework_dir = lib_dir 862 self.dsym = os.path.join(self.framework_dir, 'LLDB.framework', 'LLDB') 863 # If the framework binary doesn't exist, assume we didn't actually 864 # build a framework, and fallback to standard *nix behavior by 865 # setting framework_dir and dsym to None. 866 if not os.path.exists(self.dsym): 867 self.framework_dir = None 868 self.dsym = None 869 self.darwinWithFramework = False 870 self.makeBuildDir() 871 872 def setAsync(self, value): 873 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 874 old_async = self.dbg.GetAsync() 875 self.dbg.SetAsync(value) 876 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 877 878 def cleanupSubprocesses(self): 879 # Ensure any subprocesses are cleaned up 880 for p in self.subprocesses: 881 p.terminate() 882 del p 883 del self.subprocesses[:] 884 # Ensure any forked processes are cleaned up 885 for pid in self.forkedProcessPids: 886 try: 887 os.kill(pid, signal.SIGTERM) 888 except OSError: 889 pass 890 891 def spawnSubprocess(self, executable, args=[], install_remote=True): 892 """ Creates a subprocess.Popen object with the specified executable and arguments, 893 saves it in self.subprocesses, and returns the object. 894 NOTE: if using this function, ensure you also call: 895 896 self.addTearDownHook(self.cleanupSubprocesses) 897 898 otherwise the test suite will leak processes. 899 """ 900 proc = _RemoteProcess( 901 install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) 902 proc.launch(executable, args) 903 self.subprocesses.append(proc) 904 return proc 905 906 def forkSubprocess(self, executable, args=[]): 907 """ Fork a subprocess with its own group ID. 908 NOTE: if using this function, ensure you also call: 909 910 self.addTearDownHook(self.cleanupSubprocesses) 911 912 otherwise the test suite will leak processes. 913 """ 914 child_pid = os.fork() 915 if child_pid == 0: 916 # If more I/O support is required, this can be beefed up. 917 fd = os.open(os.devnull, os.O_RDWR) 918 os.dup2(fd, 1) 919 os.dup2(fd, 2) 920 # This call causes the child to have its of group ID 921 os.setpgid(0, 0) 922 os.execvp(executable, [executable] + args) 923 # Give the child time to get through the execvp() call 924 time.sleep(0.1) 925 self.forkedProcessPids.append(child_pid) 926 return child_pid 927 928 def HideStdout(self): 929 """Hide output to stdout from the user. 930 931 During test execution, there might be cases where we don't want to show the 932 standard output to the user. For example, 933 934 self.runCmd(r'''sc print("\n\n\tHello!\n")''') 935 936 tests whether command abbreviation for 'script' works or not. There is no 937 need to show the 'Hello' output to the user as long as the 'script' command 938 succeeds and we are not in TraceOn() mode (see the '-t' option). 939 940 In this case, the test method calls self.HideStdout(self) to redirect the 941 sys.stdout to a null device, and restores the sys.stdout upon teardown. 942 943 Note that you should only call this method at most once during a test case 944 execution. Any subsequent call has no effect at all.""" 945 if self.sys_stdout_hidden: 946 return 947 948 self.sys_stdout_hidden = True 949 old_stdout = sys.stdout 950 sys.stdout = open(os.devnull, 'w') 951 952 def restore_stdout(): 953 sys.stdout = old_stdout 954 self.addTearDownHook(restore_stdout) 955 956 # ======================================================================= 957 # Methods for customized teardown cleanups as well as execution of hooks. 958 # ======================================================================= 959 960 def setTearDownCleanup(self, dictionary=None): 961 """Register a cleanup action at tearDown() time with a dictionary""" 962 self.dict = dictionary 963 self.doTearDownCleanup = True 964 965 def addTearDownCleanup(self, dictionary): 966 """Add a cleanup action at tearDown() time with a dictionary""" 967 self.dicts.append(dictionary) 968 self.doTearDownCleanups = True 969 970 def addTearDownHook(self, hook): 971 """ 972 Add a function to be run during tearDown() time. 973 974 Hooks are executed in a first come first serve manner. 975 """ 976 if six.callable(hook): 977 with recording(self, traceAlways) as sbuf: 978 print( 979 "Adding tearDown hook:", 980 getsource_if_available(hook), 981 file=sbuf) 982 self.hooks.append(hook) 983 984 return self 985 986 def deletePexpectChild(self): 987 # This is for the case of directly spawning 'lldb' and interacting with it 988 # using pexpect. 989 if self.child and self.child.isalive(): 990 import pexpect 991 with recording(self, traceAlways) as sbuf: 992 print("tearing down the child process....", file=sbuf) 993 try: 994 if self.child_in_script_interpreter: 995 self.child.sendline('quit()') 996 self.child.expect_exact(self.child_prompt) 997 self.child.sendline( 998 'settings set interpreter.prompt-on-quit false') 999 self.child.sendline('quit') 1000 self.child.expect(pexpect.EOF) 1001 except (ValueError, pexpect.ExceptionPexpect): 1002 # child is already terminated 1003 pass 1004 except OSError as exception: 1005 import errno 1006 if exception.errno != errno.EIO: 1007 # unexpected error 1008 raise 1009 # child is already terminated 1010 finally: 1011 # Give it one final blow to make sure the child is terminated. 1012 self.child.close() 1013 1014 def tearDown(self): 1015 """Fixture for unittest test case teardown.""" 1016 #import traceback 1017 # traceback.print_stack() 1018 1019 self.deletePexpectChild() 1020 1021 # Check and run any hook functions. 1022 for hook in reversed(self.hooks): 1023 with recording(self, traceAlways) as sbuf: 1024 print( 1025 "Executing tearDown hook:", 1026 getsource_if_available(hook), 1027 file=sbuf) 1028 if funcutils.requires_self(hook): 1029 hook(self) 1030 else: 1031 hook() # try the plain call and hope it works 1032 1033 del self.hooks 1034 1035 # Perform registered teardown cleanup. 1036 if doCleanup and self.doTearDownCleanup: 1037 self.cleanup(dictionary=self.dict) 1038 1039 # In rare cases where there are multiple teardown cleanups added. 1040 if doCleanup and self.doTearDownCleanups: 1041 if self.dicts: 1042 for dict in reversed(self.dicts): 1043 self.cleanup(dictionary=dict) 1044 1045 # This must be the last statement, otherwise teardown hooks or other 1046 # lines might depend on this still being active. 1047 lldb.SBDebugger.Destroy(self.dbg) 1048 del self.dbg 1049 1050 # ========================================================= 1051 # Various callbacks to allow introspection of test progress 1052 # ========================================================= 1053 1054 def markError(self): 1055 """Callback invoked when an error (unexpected exception) errored.""" 1056 self.__errored__ = True 1057 with recording(self, False) as sbuf: 1058 # False because there's no need to write "ERROR" to the stderr twice. 1059 # Once by the Python unittest framework, and a second time by us. 1060 print("ERROR", file=sbuf) 1061 1062 def markCleanupError(self): 1063 """Callback invoked when an error occurs while a test is cleaning up.""" 1064 self.__cleanup_errored__ = True 1065 with recording(self, False) as sbuf: 1066 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. 1067 # Once by the Python unittest framework, and a second time by us. 1068 print("CLEANUP_ERROR", file=sbuf) 1069 1070 def markFailure(self): 1071 """Callback invoked when a failure (test assertion failure) occurred.""" 1072 self.__failed__ = True 1073 with recording(self, False) as sbuf: 1074 # False because there's no need to write "FAIL" to the stderr twice. 1075 # Once by the Python unittest framework, and a second time by us. 1076 print("FAIL", file=sbuf) 1077 1078 def markExpectedFailure(self, err, bugnumber): 1079 """Callback invoked when an expected failure/error occurred.""" 1080 self.__expected__ = True 1081 with recording(self, False) as sbuf: 1082 # False because there's no need to write "expected failure" to the 1083 # stderr twice. 1084 # Once by the Python unittest framework, and a second time by us. 1085 if bugnumber is None: 1086 print("expected failure", file=sbuf) 1087 else: 1088 print( 1089 "expected failure (problem id:" + str(bugnumber) + ")", 1090 file=sbuf) 1091 1092 def markSkippedTest(self): 1093 """Callback invoked when a test is skipped.""" 1094 self.__skipped__ = True 1095 with recording(self, False) as sbuf: 1096 # False because there's no need to write "skipped test" to the 1097 # stderr twice. 1098 # Once by the Python unittest framework, and a second time by us. 1099 print("skipped test", file=sbuf) 1100 1101 def markUnexpectedSuccess(self, bugnumber): 1102 """Callback invoked when an unexpected success occurred.""" 1103 self.__unexpected__ = True 1104 with recording(self, False) as sbuf: 1105 # False because there's no need to write "unexpected success" to the 1106 # stderr twice. 1107 # Once by the Python unittest framework, and a second time by us. 1108 if bugnumber is None: 1109 print("unexpected success", file=sbuf) 1110 else: 1111 print( 1112 "unexpected success (problem id:" + str(bugnumber) + ")", 1113 file=sbuf) 1114 1115 def getRerunArgs(self): 1116 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) 1117 1118 def getLogBasenameForCurrentTest(self, prefix=None): 1119 """ 1120 returns a partial path that can be used as the beginning of the name of multiple 1121 log files pertaining to this test 1122 1123 <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method> 1124 """ 1125 dname = os.path.join(os.environ["LLDB_TEST_SRC"], 1126 os.environ["LLDB_SESSION_DIRNAME"]) 1127 if not os.path.isdir(dname): 1128 os.mkdir(dname) 1129 1130 components = [] 1131 if prefix is not None: 1132 components.append(prefix) 1133 for c in configuration.session_file_format: 1134 if c == 'f': 1135 components.append(self.__class__.__module__) 1136 elif c == 'n': 1137 components.append(self.__class__.__name__) 1138 elif c == 'c': 1139 compiler = self.getCompiler() 1140 1141 if compiler[1] == ':': 1142 compiler = compiler[2:] 1143 if os.path.altsep is not None: 1144 compiler = compiler.replace(os.path.altsep, os.path.sep) 1145 path_components = [x for x in compiler.split(os.path.sep) if x != ""] 1146 1147 # Add at most 4 path components to avoid generating very long 1148 # filenames 1149 components.extend(path_components[-4:]) 1150 elif c == 'a': 1151 components.append(self.getArchitecture()) 1152 elif c == 'm': 1153 components.append(self.testMethodName) 1154 fname = "-".join(components) 1155 1156 return os.path.join(dname, fname) 1157 1158 def dumpSessionInfo(self): 1159 """ 1160 Dump the debugger interactions leading to a test error/failure. This 1161 allows for more convenient postmortem analysis. 1162 1163 See also LLDBTestResult (dotest.py) which is a singlton class derived 1164 from TextTestResult and overwrites addError, addFailure, and 1165 addExpectedFailure methods to allow us to to mark the test instance as 1166 such. 1167 """ 1168 1169 # We are here because self.tearDown() detected that this test instance 1170 # either errored or failed. The lldb.test_result singleton contains 1171 # two lists (errors and failures) which get populated by the unittest 1172 # framework. Look over there for stack trace information. 1173 # 1174 # The lists contain 2-tuples of TestCase instances and strings holding 1175 # formatted tracebacks. 1176 # 1177 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 1178 1179 # output tracebacks into session 1180 pairs = [] 1181 if self.__errored__: 1182 pairs = configuration.test_result.errors 1183 prefix = 'Error' 1184 elif self.__cleanup_errored__: 1185 pairs = configuration.test_result.cleanup_errors 1186 prefix = 'CleanupError' 1187 elif self.__failed__: 1188 pairs = configuration.test_result.failures 1189 prefix = 'Failure' 1190 elif self.__expected__: 1191 pairs = configuration.test_result.expectedFailures 1192 prefix = 'ExpectedFailure' 1193 elif self.__skipped__: 1194 prefix = 'SkippedTest' 1195 elif self.__unexpected__: 1196 prefix = 'UnexpectedSuccess' 1197 else: 1198 prefix = 'Success' 1199 1200 if not self.__unexpected__ and not self.__skipped__: 1201 for test, traceback in pairs: 1202 if test is self: 1203 print(traceback, file=self.session) 1204 1205 import datetime 1206 print( 1207 "Session info generated @", 1208 datetime.datetime.now().ctime(), 1209 file=self.session) 1210 self.session.close() 1211 del self.session 1212 1213 # process the log files 1214 log_files_for_this_test = glob.glob(self.log_basename + "*") 1215 1216 if prefix != 'Success' or lldbtest_config.log_success: 1217 # keep all log files, rename them to include prefix 1218 dst_log_basename = self.getLogBasenameForCurrentTest(prefix) 1219 for src in log_files_for_this_test: 1220 if os.path.isfile(src): 1221 dst = src.replace(self.log_basename, dst_log_basename) 1222 if os.name == "nt" and os.path.isfile(dst): 1223 # On Windows, renaming a -> b will throw an exception if 1224 # b exists. On non-Windows platforms it silently 1225 # replaces the destination. Ultimately this means that 1226 # atomic renames are not guaranteed to be possible on 1227 # Windows, but we need this to work anyway, so just 1228 # remove the destination first if it already exists. 1229 remove_file(dst) 1230 1231 lldbutil.mkdir_p(os.path.dirname(dst)) 1232 os.rename(src, dst) 1233 else: 1234 # success! (and we don't want log files) delete log files 1235 for log_file in log_files_for_this_test: 1236 remove_file(log_file) 1237 1238 # ==================================================== 1239 # Config. methods supported through a plugin interface 1240 # (enables reading of the current test configuration) 1241 # ==================================================== 1242 1243 def isMIPS(self): 1244 """Returns true if the architecture is MIPS.""" 1245 arch = self.getArchitecture() 1246 if re.match("mips", arch): 1247 return True 1248 return False 1249 1250 def isPPC64le(self): 1251 """Returns true if the architecture is PPC64LE.""" 1252 arch = self.getArchitecture() 1253 if re.match("powerpc64le", arch): 1254 return True 1255 return False 1256 1257 def getArchitecture(self): 1258 """Returns the architecture in effect the test suite is running with.""" 1259 module = builder_module() 1260 arch = module.getArchitecture() 1261 if arch == 'amd64': 1262 arch = 'x86_64' 1263 if arch in ['armv7l', 'armv8l'] : 1264 arch = 'arm' 1265 return arch 1266 1267 def getLldbArchitecture(self): 1268 """Returns the architecture of the lldb binary.""" 1269 if not hasattr(self, 'lldbArchitecture'): 1270 1271 # spawn local process 1272 command = [ 1273 lldbtest_config.lldbExec, 1274 "-o", 1275 "file " + lldbtest_config.lldbExec, 1276 "-o", 1277 "quit" 1278 ] 1279 1280 output = check_output(command) 1281 str = output.decode("utf-8") 1282 1283 for line in str.splitlines(): 1284 m = re.search( 1285 "Current executable set to '.*' \\((.*)\\)\\.", line) 1286 if m: 1287 self.lldbArchitecture = m.group(1) 1288 break 1289 1290 return self.lldbArchitecture 1291 1292 def getCompiler(self): 1293 """Returns the compiler in effect the test suite is running with.""" 1294 module = builder_module() 1295 return module.getCompiler() 1296 1297 def getCompilerBinary(self): 1298 """Returns the compiler binary the test suite is running with.""" 1299 return self.getCompiler().split()[0] 1300 1301 def getCompilerVersion(self): 1302 """ Returns a string that represents the compiler version. 1303 Supports: llvm, clang. 1304 """ 1305 version = 'unknown' 1306 1307 compiler = self.getCompilerBinary() 1308 version_output = system([[compiler, "-v"]])[1] 1309 for line in version_output.split(os.linesep): 1310 m = re.search('version ([0-9\.]+)', line) 1311 if m: 1312 version = m.group(1) 1313 return version 1314 1315 def getDwarfVersion(self): 1316 """ Returns the dwarf version generated by clang or '0'. """ 1317 if configuration.dwarf_version: 1318 return str(configuration.dwarf_version) 1319 if 'clang' in self.getCompiler(): 1320 try: 1321 driver_output = check_output( 1322 [self.getCompiler()] + '-g -c -x c - -o - -###'.split(), 1323 stderr=STDOUT) 1324 driver_output = driver_output.decode("utf-8") 1325 for line in driver_output.split(os.linesep): 1326 m = re.search('dwarf-version=([0-9])', line) 1327 if m: 1328 return m.group(1) 1329 except: pass 1330 return '0' 1331 1332 def platformIsDarwin(self): 1333 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1334 return lldbplatformutil.platformIsDarwin() 1335 1336 def hasDarwinFramework(self): 1337 return self.darwinWithFramework 1338 1339 def getPlatform(self): 1340 """Returns the target platform the test suite is running on.""" 1341 return lldbplatformutil.getPlatform() 1342 1343 def isIntelCompiler(self): 1344 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1345 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1346 1347 def expectedCompilerVersion(self, compiler_version): 1348 """Returns True iff compiler_version[1] matches the current compiler version. 1349 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1350 Any operator other than the following defaults to an equality test: 1351 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1352 """ 1353 if (compiler_version is None): 1354 return True 1355 operator = str(compiler_version[0]) 1356 version = compiler_version[1] 1357 1358 if (version is None): 1359 return True 1360 if (operator == '>'): 1361 return LooseVersion(self.getCompilerVersion()) > LooseVersion(version) 1362 if (operator == '>=' or operator == '=>'): 1363 return LooseVersion(self.getCompilerVersion()) >= LooseVersion(version) 1364 if (operator == '<'): 1365 return LooseVersion(self.getCompilerVersion()) < LooseVersion(version) 1366 if (operator == '<=' or operator == '=<'): 1367 return LooseVersion(self.getCompilerVersion()) <= LooseVersion(version) 1368 if (operator == '!=' or operator == '!' or operator == 'not'): 1369 return str(version) not in str(self.getCompilerVersion()) 1370 return str(version) in str(self.getCompilerVersion()) 1371 1372 def expectedCompiler(self, compilers): 1373 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1374 if (compilers is None): 1375 return True 1376 1377 for compiler in compilers: 1378 if compiler in self.getCompiler(): 1379 return True 1380 1381 return False 1382 1383 def expectedArch(self, archs): 1384 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1385 if (archs is None): 1386 return True 1387 1388 for arch in archs: 1389 if arch in self.getArchitecture(): 1390 return True 1391 1392 return False 1393 1394 def getRunOptions(self): 1395 """Command line option for -A and -C to run this test again, called from 1396 self.dumpSessionInfo().""" 1397 arch = self.getArchitecture() 1398 comp = self.getCompiler() 1399 option_str = "" 1400 if arch: 1401 option_str = "-A " + arch 1402 if comp: 1403 option_str += " -C " + comp 1404 return option_str 1405 1406 def getDebugInfo(self): 1407 method = getattr(self, self.testMethodName) 1408 return getattr(method, "debug_info", None) 1409 1410 # ================================================== 1411 # Build methods supported through a plugin interface 1412 # ================================================== 1413 1414 def getstdlibFlag(self): 1415 """ Returns the proper -stdlib flag, or empty if not required.""" 1416 if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd": 1417 stdlibflag = "-stdlib=libc++" 1418 else: # this includes NetBSD 1419 stdlibflag = "" 1420 return stdlibflag 1421 1422 def getstdFlag(self): 1423 """ Returns the proper stdflag. """ 1424 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1425 stdflag = "-std=c++0x" 1426 else: 1427 stdflag = "-std=c++11" 1428 return stdflag 1429 1430 def buildDriver(self, sources, exe_name): 1431 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1432 or LLDB.framework). 1433 """ 1434 stdflag = self.getstdFlag() 1435 stdlibflag = self.getstdlibFlag() 1436 1437 lib_dir = configuration.lldb_libs_dir 1438 if self.hasDarwinFramework(): 1439 d = {'CXX_SOURCES': sources, 1440 'EXE': exe_name, 1441 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag), 1442 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1443 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.dsym, self.framework_dir), 1444 } 1445 elif sys.platform.startswith('win'): 1446 d = { 1447 'CXX_SOURCES': sources, 1448 'EXE': exe_name, 1449 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1450 stdlibflag, 1451 os.path.join( 1452 os.environ["LLDB_SRC"], 1453 "include")), 1454 'LD_EXTRAS': "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]} 1455 else: 1456 d = { 1457 'CXX_SOURCES': sources, 1458 'EXE': exe_name, 1459 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1460 stdlibflag, 1461 os.path.join( 1462 os.environ["LLDB_SRC"], 1463 "include")), 1464 'LD_EXTRAS': "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1465 if self.TraceOn(): 1466 print( 1467 "Building LLDB Driver (%s) from sources %s" % 1468 (exe_name, sources)) 1469 1470 self.buildDefault(dictionary=d) 1471 1472 def buildLibrary(self, sources, lib_name): 1473 """Platform specific way to build a default library. """ 1474 1475 stdflag = self.getstdFlag() 1476 1477 lib_dir = configuration.lldb_libs_dir 1478 if self.hasDarwinFramework(): 1479 d = {'DYLIB_CXX_SOURCES': sources, 1480 'DYLIB_NAME': lib_name, 1481 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag, 1482 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1483 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.dsym, self.framework_dir), 1484 } 1485 elif self.getPlatform() == 'windows': 1486 d = { 1487 'DYLIB_CXX_SOURCES': sources, 1488 'DYLIB_NAME': lib_name, 1489 'CFLAGS_EXTRAS': "%s -I%s " % (stdflag, 1490 os.path.join( 1491 os.environ["LLDB_SRC"], 1492 "include")), 1493 'LD_EXTRAS': "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]} 1494 else: 1495 d = { 1496 'DYLIB_CXX_SOURCES': sources, 1497 'DYLIB_NAME': lib_name, 1498 'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag, 1499 os.path.join( 1500 os.environ["LLDB_SRC"], 1501 "include")), 1502 'LD_EXTRAS': "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1503 if self.TraceOn(): 1504 print( 1505 "Building LLDB Library (%s) from sources %s" % 1506 (lib_name, sources)) 1507 1508 self.buildDefault(dictionary=d) 1509 1510 def buildProgram(self, sources, exe_name): 1511 """ Platform specific way to build an executable from C/C++ sources. """ 1512 d = {'CXX_SOURCES': sources, 1513 'EXE': exe_name} 1514 self.buildDefault(dictionary=d) 1515 1516 def buildDefault( 1517 self, 1518 architecture=None, 1519 compiler=None, 1520 dictionary=None): 1521 """Platform specific way to build the default binaries.""" 1522 testdir = self.mydir 1523 testname = self.getBuildDirBasename() 1524 if self.getDebugInfo(): 1525 raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE") 1526 module = builder_module() 1527 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1528 if not module.buildDefault(self, architecture, compiler, 1529 dictionary, testdir, testname): 1530 raise Exception("Don't know how to build default binary") 1531 1532 def buildDsym( 1533 self, 1534 architecture=None, 1535 compiler=None, 1536 dictionary=None): 1537 """Platform specific way to build binaries with dsym info.""" 1538 testdir = self.mydir 1539 testname = self.getBuildDirBasename() 1540 if self.getDebugInfo() != "dsym": 1541 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1542 1543 module = builder_module() 1544 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1545 if not module.buildDsym(self, architecture, compiler, 1546 dictionary, testdir, testname): 1547 raise Exception("Don't know how to build binary with dsym") 1548 1549 def buildDwarf( 1550 self, 1551 architecture=None, 1552 compiler=None, 1553 dictionary=None): 1554 """Platform specific way to build binaries with dwarf maps.""" 1555 testdir = self.mydir 1556 testname = self.getBuildDirBasename() 1557 if self.getDebugInfo() != "dwarf": 1558 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1559 1560 module = builder_module() 1561 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1562 if not module.buildDwarf(self, architecture, compiler, 1563 dictionary, testdir, testname): 1564 raise Exception("Don't know how to build binary with dwarf") 1565 1566 def buildDwo( 1567 self, 1568 architecture=None, 1569 compiler=None, 1570 dictionary=None): 1571 """Platform specific way to build binaries with dwarf maps.""" 1572 testdir = self.mydir 1573 testname = self.getBuildDirBasename() 1574 if self.getDebugInfo() != "dwo": 1575 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1576 1577 module = builder_module() 1578 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1579 if not module.buildDwo(self, architecture, compiler, 1580 dictionary, testdir, testname): 1581 raise Exception("Don't know how to build binary with dwo") 1582 1583 def buildGModules( 1584 self, 1585 architecture=None, 1586 compiler=None, 1587 dictionary=None): 1588 """Platform specific way to build binaries with gmodules info.""" 1589 testdir = self.mydir 1590 testname = self.getBuildDirBasename() 1591 if self.getDebugInfo() != "gmodules": 1592 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1593 1594 module = builder_module() 1595 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1596 if not module.buildGModules(self, architecture, compiler, 1597 dictionary, testdir, testname): 1598 raise Exception("Don't know how to build binary with gmodules") 1599 1600 def signBinary(self, binary_path): 1601 if sys.platform.startswith("darwin"): 1602 codesign_cmd = "codesign --force --sign \"%s\" %s" % ( 1603 lldbtest_config.codesign_identity, binary_path) 1604 call(codesign_cmd, shell=True) 1605 1606 def findBuiltClang(self): 1607 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 1608 paths_to_try = [ 1609 "llvm-build/Release+Asserts/x86_64/bin/clang", 1610 "llvm-build/Debug+Asserts/x86_64/bin/clang", 1611 "llvm-build/Release/x86_64/bin/clang", 1612 "llvm-build/Debug/x86_64/bin/clang", 1613 ] 1614 lldb_root_path = os.path.join( 1615 os.path.dirname(__file__), "..", "..", "..", "..") 1616 for p in paths_to_try: 1617 path = os.path.join(lldb_root_path, p) 1618 if os.path.exists(path): 1619 return path 1620 1621 # Tries to find clang at the same folder as the lldb 1622 lldb_dir = os.path.dirname(lldbtest_config.lldbExec) 1623 path = distutils.spawn.find_executable("clang", lldb_dir) 1624 if path is not None: 1625 return path 1626 1627 return os.environ["CC"] 1628 1629 def findYaml2obj(self): 1630 """ 1631 Get the path to the yaml2obj executable, which can be used to create 1632 test object files from easy to write yaml instructions. 1633 1634 Throws an Exception if the executable cannot be found. 1635 """ 1636 # Tries to find yaml2obj at the same folder as clang 1637 clang_dir = os.path.dirname(self.findBuiltClang()) 1638 path = distutils.spawn.find_executable("yaml2obj", clang_dir) 1639 if path is not None: 1640 return path 1641 raise Exception("yaml2obj executable not found") 1642 1643 1644 def yaml2obj(self, yaml_path, obj_path): 1645 """ 1646 Create an object file at the given path from a yaml file. 1647 1648 Throws subprocess.CalledProcessError if the object could not be created. 1649 """ 1650 yaml2obj = self.findYaml2obj() 1651 command = [yaml2obj, "-o=%s" % obj_path, yaml_path] 1652 system([command]) 1653 1654 def getBuildFlags( 1655 self, 1656 use_cpp11=True, 1657 use_libcxx=False, 1658 use_libstdcxx=False): 1659 """ Returns a dictionary (which can be provided to build* functions above) which 1660 contains OS-specific build flags. 1661 """ 1662 cflags = "" 1663 ldflags = "" 1664 1665 # On Mac OS X, unless specifically requested to use libstdc++, use 1666 # libc++ 1667 if not use_libstdcxx and self.platformIsDarwin(): 1668 use_libcxx = True 1669 1670 if use_libcxx and self.libcxxPath: 1671 cflags += "-stdlib=libc++ " 1672 if self.libcxxPath: 1673 libcxxInclude = os.path.join(self.libcxxPath, "include") 1674 libcxxLib = os.path.join(self.libcxxPath, "lib") 1675 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): 1676 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % ( 1677 libcxxInclude, libcxxLib, libcxxLib) 1678 1679 if use_cpp11: 1680 cflags += "-std=" 1681 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1682 cflags += "c++0x" 1683 else: 1684 cflags += "c++11" 1685 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1686 cflags += " -stdlib=libc++" 1687 elif self.getPlatform() == "openbsd": 1688 cflags += " -stdlib=libc++" 1689 elif self.getPlatform() == "netbsd": 1690 # NetBSD defaults to libc++ 1691 pass 1692 elif "clang" in self.getCompiler(): 1693 cflags += " -stdlib=libstdc++" 1694 1695 return {'CFLAGS_EXTRAS': cflags, 1696 'LD_EXTRAS': ldflags, 1697 } 1698 1699 def cleanup(self, dictionary=None): 1700 """Platform specific way to do cleanup after build.""" 1701 module = builder_module() 1702 if not module.cleanup(self, dictionary): 1703 raise Exception( 1704 "Don't know how to do cleanup with dictionary: " + 1705 dictionary) 1706 1707 def getLLDBLibraryEnvVal(self): 1708 """ Returns the path that the OS-specific library search environment variable 1709 (self.dylibPath) should be set to in order for a program to find the LLDB 1710 library. If an environment variable named self.dylibPath is already set, 1711 the new path is appended to it and returned. 1712 """ 1713 existing_library_path = os.environ[ 1714 self.dylibPath] if self.dylibPath in os.environ else None 1715 lib_dir = os.environ["LLDB_LIB_DIR"] 1716 if existing_library_path: 1717 return "%s:%s" % (existing_library_path, lib_dir) 1718 elif sys.platform.startswith("darwin"): 1719 return os.path.join(lib_dir, 'LLDB.framework') 1720 else: 1721 return lib_dir 1722 1723 def getLibcPlusPlusLibs(self): 1724 if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'): 1725 return ['libc++.so.1'] 1726 else: 1727 return ['libc++.1.dylib', 'libc++abi.'] 1728 1729# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. 1730# We change the test methods to create a new test method for each test for each debug info we are 1731# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding 1732# the new test method we remove the old method at the same time. This functionality can be 1733# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test 1734# level by using the decorator @no_debug_info_test. 1735 1736 1737class LLDBTestCaseFactory(type): 1738 1739 def __new__(cls, name, bases, attrs): 1740 original_testcase = super( 1741 LLDBTestCaseFactory, cls).__new__( 1742 cls, name, bases, attrs) 1743 if original_testcase.NO_DEBUG_INFO_TESTCASE: 1744 return original_testcase 1745 1746 newattrs = {} 1747 for attrname, attrvalue in attrs.items(): 1748 if attrname.startswith("test") and not getattr( 1749 attrvalue, "__no_debug_info_test__", False): 1750 1751 # If any debug info categories were explicitly tagged, assume that list to be 1752 # authoritative. If none were specified, try with all debug 1753 # info formats. 1754 all_dbginfo_categories = set(test_categories.debug_info_categories) 1755 categories = set( 1756 getattr( 1757 attrvalue, 1758 "categories", 1759 [])) & all_dbginfo_categories 1760 if not categories: 1761 categories = all_dbginfo_categories 1762 1763 for cat in categories: 1764 @decorators.add_test_categories([cat]) 1765 @wraps(attrvalue) 1766 def test_method(self, attrvalue=attrvalue): 1767 return attrvalue(self) 1768 1769 method_name = attrname + "_" + cat 1770 test_method.__name__ = method_name 1771 test_method.debug_info = cat 1772 newattrs[method_name] = test_method 1773 1774 else: 1775 newattrs[attrname] = attrvalue 1776 return super( 1777 LLDBTestCaseFactory, 1778 cls).__new__( 1779 cls, 1780 name, 1781 bases, 1782 newattrs) 1783 1784# Setup the metaclass for this class to change the list of the test 1785# methods when a new class is loaded 1786 1787 1788@add_metaclass(LLDBTestCaseFactory) 1789class TestBase(Base): 1790 """ 1791 This abstract base class is meant to be subclassed. It provides default 1792 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 1793 among other things. 1794 1795 Important things for test class writers: 1796 1797 - Overwrite the mydir class attribute, otherwise your test class won't 1798 run. It specifies the relative directory to the top level 'test' so 1799 the test harness can change to the correct working directory before 1800 running your test. 1801 1802 - The setUp method sets up things to facilitate subsequent interactions 1803 with the debugger as part of the test. These include: 1804 - populate the test method name 1805 - create/get a debugger set with synchronous mode (self.dbg) 1806 - get the command interpreter from with the debugger (self.ci) 1807 - create a result object for use with the command interpreter 1808 (self.res) 1809 - plus other stuffs 1810 1811 - The tearDown method tries to perform some necessary cleanup on behalf 1812 of the test to return the debugger to a good state for the next test. 1813 These include: 1814 - execute any tearDown hooks registered by the test method with 1815 TestBase.addTearDownHook(); examples can be found in 1816 settings/TestSettings.py 1817 - kill the inferior process associated with each target, if any, 1818 and, then delete the target from the debugger's target list 1819 - perform build cleanup before running the next test method in the 1820 same test class; examples of registering for this service can be 1821 found in types/TestIntegerTypes.py with the call: 1822 - self.setTearDownCleanup(dictionary=d) 1823 1824 - Similarly setUpClass and tearDownClass perform classwise setup and 1825 teardown fixtures. The tearDownClass method invokes a default build 1826 cleanup for the entire test class; also, subclasses can implement the 1827 classmethod classCleanup(cls) to perform special class cleanup action. 1828 1829 - The instance methods runCmd and expect are used heavily by existing 1830 test cases to send a command to the command interpreter and to perform 1831 string/pattern matching on the output of such command execution. The 1832 expect method also provides a mode to peform string/pattern matching 1833 without running a command. 1834 1835 - The build methods buildDefault, buildDsym, and buildDwarf are used to 1836 build the binaries used during a particular test scenario. A plugin 1837 should be provided for the sys.platform running the test suite. The 1838 Mac OS X implementation is located in plugins/darwin.py. 1839 """ 1840 1841 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the 1842 # test multiple times with various debug info types. 1843 NO_DEBUG_INFO_TESTCASE = False 1844 1845 # Maximum allowed attempts when launching the inferior process. 1846 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 1847 maxLaunchCount = 1 1848 1849 # Time to wait before the next launching attempt in second(s). 1850 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 1851 timeWaitNextLaunch = 1.0 1852 1853 def generateSource(self, source): 1854 template = source + '.template' 1855 temp = os.path.join(self.getSourceDir(), template) 1856 with open(temp, 'r') as f: 1857 content = f.read() 1858 1859 public_api_dir = os.path.join( 1860 os.environ["LLDB_SRC"], "include", "lldb", "API") 1861 1862 # Look under the include/lldb/API directory and add #include statements 1863 # for all the SB API headers. 1864 public_headers = os.listdir(public_api_dir) 1865 # For different platforms, the include statement can vary. 1866 if self.hasDarwinFramework(): 1867 include_stmt = "'#include <%s>' % os.path.join('LLDB', header)" 1868 else: 1869 include_stmt = "'#include <%s>' % os.path.join('" + public_api_dir + "', header)" 1870 list = [eval(include_stmt) for header in public_headers if ( 1871 header.startswith("SB") and header.endswith(".h"))] 1872 includes = '\n'.join(list) 1873 new_content = content.replace('%include_SB_APIs%', includes) 1874 src = os.path.join(self.getBuildDir(), source) 1875 with open(src, 'w') as f: 1876 f.write(new_content) 1877 1878 self.addTearDownHook(lambda: os.remove(src)) 1879 1880 def setUp(self): 1881 #import traceback 1882 # traceback.print_stack() 1883 1884 # Works with the test driver to conditionally skip tests via 1885 # decorators. 1886 Base.setUp(self) 1887 1888 for s in self.setUpCommands(): 1889 self.runCmd(s) 1890 1891 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 1892 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 1893 1894 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 1895 self.timeWaitNextLaunch = float( 1896 os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 1897 1898 # We want our debugger to be synchronous. 1899 self.dbg.SetAsync(False) 1900 1901 # Retrieve the associated command interpreter instance. 1902 self.ci = self.dbg.GetCommandInterpreter() 1903 if not self.ci: 1904 raise Exception('Could not get the command interpreter') 1905 1906 # And the result object. 1907 self.res = lldb.SBCommandReturnObject() 1908 1909 def registerSharedLibrariesWithTarget(self, target, shlibs): 1910 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing 1911 1912 Any modules in the target that have their remote install file specification set will 1913 get uploaded to the remote host. This function registers the local copies of the 1914 shared libraries with the target and sets their remote install locations so they will 1915 be uploaded when the target is run. 1916 ''' 1917 if not shlibs or not self.platformContext: 1918 return None 1919 1920 shlib_environment_var = self.platformContext.shlib_environment_var 1921 shlib_prefix = self.platformContext.shlib_prefix 1922 shlib_extension = '.' + self.platformContext.shlib_extension 1923 1924 working_dir = self.get_process_working_directory() 1925 environment = ['%s=%s' % (shlib_environment_var, working_dir)] 1926 # Add any shared libraries to our target if remote so they get 1927 # uploaded into the working directory on the remote side 1928 for name in shlibs: 1929 # The path can be a full path to a shared library, or a make file name like "Foo" for 1930 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a 1931 # basename like "libFoo.so". So figure out which one it is and resolve the local copy 1932 # of the shared library accordingly 1933 if os.path.isfile(name): 1934 local_shlib_path = name # name is the full path to the local shared library 1935 else: 1936 # Check relative names 1937 local_shlib_path = os.path.join( 1938 self.getBuildDir(), shlib_prefix + name + shlib_extension) 1939 if not os.path.exists(local_shlib_path): 1940 local_shlib_path = os.path.join( 1941 self.getBuildDir(), name + shlib_extension) 1942 if not os.path.exists(local_shlib_path): 1943 local_shlib_path = os.path.join(self.getBuildDir(), name) 1944 1945 # Make sure we found the local shared library in the above code 1946 self.assertTrue(os.path.exists(local_shlib_path)) 1947 1948 # Add the shared library to our target 1949 shlib_module = target.AddModule(local_shlib_path, None, None, None) 1950 if lldb.remote_platform: 1951 # We must set the remote install location if we want the shared library 1952 # to get uploaded to the remote target 1953 remote_shlib_path = lldbutil.append_to_process_working_directory(self, 1954 os.path.basename(local_shlib_path)) 1955 shlib_module.SetRemoteInstallFileSpec( 1956 lldb.SBFileSpec(remote_shlib_path, False)) 1957 1958 return environment 1959 1960 def registerSanitizerLibrariesWithTarget(self, target): 1961 runtimes = [] 1962 for m in target.module_iter(): 1963 libspec = m.GetFileSpec() 1964 if "clang_rt" in libspec.GetFilename(): 1965 runtimes.append(os.path.join(libspec.GetDirectory(), 1966 libspec.GetFilename())) 1967 return self.registerSharedLibrariesWithTarget(target, runtimes) 1968 1969 # utility methods that tests can use to access the current objects 1970 def target(self): 1971 if not self.dbg: 1972 raise Exception('Invalid debugger instance') 1973 return self.dbg.GetSelectedTarget() 1974 1975 def process(self): 1976 if not self.dbg: 1977 raise Exception('Invalid debugger instance') 1978 return self.dbg.GetSelectedTarget().GetProcess() 1979 1980 def thread(self): 1981 if not self.dbg: 1982 raise Exception('Invalid debugger instance') 1983 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() 1984 1985 def frame(self): 1986 if not self.dbg: 1987 raise Exception('Invalid debugger instance') 1988 return self.dbg.GetSelectedTarget().GetProcess( 1989 ).GetSelectedThread().GetSelectedFrame() 1990 1991 def get_process_working_directory(self): 1992 '''Get the working directory that should be used when launching processes for local or remote processes.''' 1993 if lldb.remote_platform: 1994 # Remote tests set the platform working directory up in 1995 # TestBase.setUp() 1996 return lldb.remote_platform.GetWorkingDirectory() 1997 else: 1998 # local tests change directory into each test subdirectory 1999 return self.getBuildDir() 2000 2001 def tearDown(self): 2002 #import traceback 2003 # traceback.print_stack() 2004 2005 # Ensure all the references to SB objects have gone away so that we can 2006 # be sure that all test-specific resources have been freed before we 2007 # attempt to delete the targets. 2008 gc.collect() 2009 2010 # Delete the target(s) from the debugger as a general cleanup step. 2011 # This includes terminating the process for each target, if any. 2012 # We'd like to reuse the debugger for our next test without incurring 2013 # the initialization overhead. 2014 targets = [] 2015 for target in self.dbg: 2016 if target: 2017 targets.append(target) 2018 process = target.GetProcess() 2019 if process: 2020 rc = self.invoke(process, "Kill") 2021 self.assertTrue(rc.Success(), PROCESS_KILLED) 2022 for target in targets: 2023 self.dbg.DeleteTarget(target) 2024 2025 # Do this last, to make sure it's in reverse order from how we setup. 2026 Base.tearDown(self) 2027 2028 def switch_to_thread_with_stop_reason(self, stop_reason): 2029 """ 2030 Run the 'thread list' command, and select the thread with stop reason as 2031 'stop_reason'. If no such thread exists, no select action is done. 2032 """ 2033 from .lldbutil import stop_reason_to_str 2034 self.runCmd('thread list') 2035 output = self.res.GetOutput() 2036 thread_line_pattern = re.compile( 2037 "^[ *] thread #([0-9]+):.*stop reason = %s" % 2038 stop_reason_to_str(stop_reason)) 2039 for line in output.splitlines(): 2040 matched = thread_line_pattern.match(line) 2041 if matched: 2042 self.runCmd('thread select %s' % matched.group(1)) 2043 2044 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): 2045 """ 2046 Ask the command interpreter to handle the command and then check its 2047 return status. 2048 """ 2049 # Fail fast if 'cmd' is not meaningful. 2050 if not cmd or len(cmd) == 0: 2051 raise Exception("Bad 'cmd' parameter encountered") 2052 2053 trace = (True if traceAlways else trace) 2054 2055 if cmd.startswith("target create "): 2056 cmd = cmd.replace("target create ", "file ") 2057 2058 running = (cmd.startswith("run") or cmd.startswith("process launch")) 2059 2060 for i in range(self.maxLaunchCount if running else 1): 2061 self.ci.HandleCommand(cmd, self.res, inHistory) 2062 2063 with recording(self, trace) as sbuf: 2064 print("runCmd:", cmd, file=sbuf) 2065 if not check: 2066 print("check of return status not required", file=sbuf) 2067 if self.res.Succeeded(): 2068 print("output:", self.res.GetOutput(), file=sbuf) 2069 else: 2070 print("runCmd failed!", file=sbuf) 2071 print(self.res.GetError(), file=sbuf) 2072 2073 if self.res.Succeeded(): 2074 break 2075 elif running: 2076 # For process launch, wait some time before possible next try. 2077 time.sleep(self.timeWaitNextLaunch) 2078 with recording(self, trace) as sbuf: 2079 print("Command '" + cmd + "' failed!", file=sbuf) 2080 2081 if check: 2082 output = "" 2083 if self.res.GetOutput(): 2084 output += "\nCommand output:\n" + self.res.GetOutput() 2085 if self.res.GetError(): 2086 output += "\nError output:\n" + self.res.GetError() 2087 if msg: 2088 msg += output 2089 if cmd: 2090 cmd += output 2091 self.assertTrue(self.res.Succeeded(), 2092 msg if (msg) else CMD_MSG(cmd)) 2093 2094 def match( 2095 self, 2096 str, 2097 patterns, 2098 msg=None, 2099 trace=False, 2100 error=False, 2101 matching=True, 2102 exe=True): 2103 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 2104 2105 Otherwise, all the arguments have the same meanings as for the expect function""" 2106 2107 trace = (True if traceAlways else trace) 2108 2109 if exe: 2110 # First run the command. If we are expecting error, set check=False. 2111 # Pass the assert message along since it provides more semantic 2112 # info. 2113 self.runCmd( 2114 str, 2115 msg=msg, 2116 trace=( 2117 True if trace else False), 2118 check=not error) 2119 2120 # Then compare the output against expected strings. 2121 output = self.res.GetError() if error else self.res.GetOutput() 2122 2123 # If error is True, the API client expects the command to fail! 2124 if error: 2125 self.assertFalse(self.res.Succeeded(), 2126 "Command '" + str + "' is expected to fail!") 2127 else: 2128 # No execution required, just compare str against the golden input. 2129 output = str 2130 with recording(self, trace) as sbuf: 2131 print("looking at:", output, file=sbuf) 2132 2133 # The heading says either "Expecting" or "Not expecting". 2134 heading = "Expecting" if matching else "Not expecting" 2135 2136 for pattern in patterns: 2137 # Match Objects always have a boolean value of True. 2138 match_object = re.search(pattern, output) 2139 matched = bool(match_object) 2140 with recording(self, trace) as sbuf: 2141 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2142 print("Matched" if matched else "Not matched", file=sbuf) 2143 if matched: 2144 break 2145 2146 self.assertTrue(matched if matching else not matched, 2147 msg if msg else EXP_MSG(str, output, exe)) 2148 2149 return match_object 2150 2151 def check_completion_with_desc(self, str_input, match_desc_pairs, enforce_order=False): 2152 """ 2153 Checks that when the given input is completed at the given list of 2154 completions and descriptions is returned. 2155 :param str_input: The input that should be completed. The completion happens at the end of the string. 2156 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of 2157 completions returned by LLDB. The first element of the pair is the completion 2158 string that LLDB should generate and the second element the description. 2159 :param enforce_order: True iff the order in which the completions are returned by LLDB 2160 should match the order of the match_desc_pairs pairs. 2161 """ 2162 interp = self.dbg.GetCommandInterpreter() 2163 match_strings = lldb.SBStringList() 2164 description_strings = lldb.SBStringList() 2165 num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) 2166 self.assertEqual(len(description_strings), len(match_strings)) 2167 2168 # The index of the last matched description in description_strings or 2169 # -1 if no description has been matched yet. 2170 last_found_index = -1 2171 out_of_order_errors = "" 2172 missing_pairs = [] 2173 for pair in match_desc_pairs: 2174 found_pair = False 2175 for i in range(num_matches + 1): 2176 match_candidate = match_strings.GetStringAtIndex(i) 2177 description_candidate = description_strings.GetStringAtIndex(i) 2178 if match_candidate == pair[0] and description_candidate == pair[1]: 2179 found_pair = True 2180 if enforce_order and last_found_index > i: 2181 new_err = ("Found completion " + pair[0] + " at index " + 2182 str(i) + " in returned completion list but " + 2183 "should have been after completion " + 2184 match_strings.GetStringAtIndex(last_found_index) + 2185 " (index:" + str(last_found_index) + ")\n") 2186 out_of_order_errors += new_err 2187 last_found_index = i 2188 break 2189 if not found_pair: 2190 missing_pairs.append(pair) 2191 2192 error_msg = "" 2193 got_failure = False 2194 if len(missing_pairs): 2195 got_failure = True 2196 error_msg += "Missing pairs:\n" 2197 for pair in missing_pairs: 2198 error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" 2199 if len(out_of_order_errors): 2200 got_failure = True 2201 error_msg += out_of_order_errors 2202 if got_failure: 2203 error_msg += "Got the following " + str(num_matches) + " completions back:\n" 2204 for i in range(num_matches + 1): 2205 match_candidate = match_strings.GetStringAtIndex(i) 2206 description_candidate = description_strings.GetStringAtIndex(i) 2207 error_msg += "[" + match_candidate + ":" + description_candidate + "] index " + str(i) + "\n" 2208 self.assertFalse(got_failure, error_msg) 2209 2210 def complete_exactly(self, str_input, patterns): 2211 self.complete_from_to(str_input, patterns, True) 2212 2213 def complete_from_to(self, str_input, patterns, turn_off_re_match=False): 2214 """Test that the completion mechanism completes str_input to patterns, 2215 where patterns could be a pattern-string or a list of pattern-strings""" 2216 # Patterns should not be None in order to proceed. 2217 self.assertFalse(patterns is None) 2218 # And should be either a string or list of strings. Check for list type 2219 # below, if not, make a list out of the singleton string. If patterns 2220 # is not a string or not a list of strings, there'll be runtime errors 2221 # later on. 2222 if not isinstance(patterns, list): 2223 patterns = [patterns] 2224 2225 interp = self.dbg.GetCommandInterpreter() 2226 match_strings = lldb.SBStringList() 2227 num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) 2228 common_match = match_strings.GetStringAtIndex(0) 2229 if num_matches == 0: 2230 compare_string = str_input 2231 else: 2232 if common_match != None and len(common_match) > 0: 2233 compare_string = str_input + common_match 2234 else: 2235 compare_string = "" 2236 for idx in range(1, num_matches+1): 2237 compare_string += match_strings.GetStringAtIndex(idx) + "\n" 2238 2239 for p in patterns: 2240 if turn_off_re_match: 2241 self.expect( 2242 compare_string, msg=COMPLETION_MSG( 2243 str_input, p, match_strings), exe=False, substrs=[p]) 2244 else: 2245 self.expect( 2246 compare_string, msg=COMPLETION_MSG( 2247 str_input, p, match_strings), exe=False, patterns=[p]) 2248 2249 def completions_match(self, command, completions): 2250 """Checks that the completions for the given command are equal to the 2251 given list of completions""" 2252 interp = self.dbg.GetCommandInterpreter() 2253 match_strings = lldb.SBStringList() 2254 interp.HandleCompletion(command, len(command), 0, -1, match_strings) 2255 # match_strings is a 1-indexed list, so we have to slice... 2256 self.assertItemsEqual(completions, list(match_strings)[1:], 2257 "List of returned completion is wrong") 2258 2259 def filecheck( 2260 self, 2261 command, 2262 check_file, 2263 filecheck_options = '', 2264 expect_cmd_failure = False): 2265 # Run the command. 2266 self.runCmd( 2267 command, 2268 check=(not expect_cmd_failure), 2269 msg="FileCheck'ing result of `{0}`".format(command)) 2270 2271 self.assertTrue((not expect_cmd_failure) == self.res.Succeeded()) 2272 2273 # Get the error text if there was an error, and the regular text if not. 2274 output = self.res.GetOutput() if self.res.Succeeded() \ 2275 else self.res.GetError() 2276 2277 # Assemble the absolute path to the check file. As a convenience for 2278 # LLDB inline tests, assume that the check file is a relative path to 2279 # a file within the inline test directory. 2280 if check_file.endswith('.pyc'): 2281 check_file = check_file[:-1] 2282 check_file_abs = os.path.abspath(check_file) 2283 2284 # Run FileCheck. 2285 filecheck_bin = configuration.get_filecheck_path() 2286 if not filecheck_bin: 2287 self.assertTrue(False, "No valid FileCheck executable specified") 2288 filecheck_args = [filecheck_bin, check_file_abs] 2289 if filecheck_options: 2290 filecheck_args.append(filecheck_options) 2291 subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) 2292 cmd_stdout, cmd_stderr = subproc.communicate(input=output) 2293 cmd_status = subproc.returncode 2294 2295 filecheck_cmd = " ".join(filecheck_args) 2296 filecheck_trace = """ 2297--- FileCheck trace (code={0}) --- 2298{1} 2299 2300FileCheck input: 2301{2} 2302 2303FileCheck output: 2304{3} 2305{4} 2306""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) 2307 2308 trace = cmd_status != 0 or traceAlways 2309 with recording(self, trace) as sbuf: 2310 print(filecheck_trace, file=sbuf) 2311 2312 self.assertTrue(cmd_status == 0) 2313 2314 def expect( 2315 self, 2316 str, 2317 msg=None, 2318 patterns=None, 2319 startstr=None, 2320 endstr=None, 2321 substrs=None, 2322 trace=False, 2323 error=False, 2324 ordered=True, 2325 matching=True, 2326 exe=True, 2327 inHistory=False): 2328 """ 2329 Similar to runCmd; with additional expect style output matching ability. 2330 2331 Ask the command interpreter to handle the command and then check its 2332 return status. The 'msg' parameter specifies an informational assert 2333 message. We expect the output from running the command to start with 2334 'startstr', matches the substrings contained in 'substrs', and regexp 2335 matches the patterns contained in 'patterns'. 2336 2337 When matching is true and ordered is true, which are both the default, 2338 the strings in the substrs array have to appear in the command output 2339 in the order in which they appear in the array. 2340 2341 If the keyword argument error is set to True, it signifies that the API 2342 client is expecting the command to fail. In this case, the error stream 2343 from running the command is retrieved and compared against the golden 2344 input, instead. 2345 2346 If the keyword argument matching is set to False, it signifies that the API 2347 client is expecting the output of the command not to match the golden 2348 input. 2349 2350 Finally, the required argument 'str' represents the lldb command to be 2351 sent to the command interpreter. In case the keyword argument 'exe' is 2352 set to False, the 'str' is treated as a string to be matched/not-matched 2353 against the golden input. 2354 """ 2355 trace = (True if traceAlways else trace) 2356 2357 if exe: 2358 # First run the command. If we are expecting error, set check=False. 2359 # Pass the assert message along since it provides more semantic 2360 # info. 2361 self.runCmd( 2362 str, 2363 msg=msg, 2364 trace=( 2365 True if trace else False), 2366 check=not error, 2367 inHistory=inHistory) 2368 2369 # Then compare the output against expected strings. 2370 output = self.res.GetError() if error else self.res.GetOutput() 2371 2372 # If error is True, the API client expects the command to fail! 2373 if error: 2374 self.assertFalse(self.res.Succeeded(), 2375 "Command '" + str + "' is expected to fail!") 2376 else: 2377 # No execution required, just compare str against the golden input. 2378 if isinstance(str, lldb.SBCommandReturnObject): 2379 output = str.GetOutput() 2380 else: 2381 output = str 2382 with recording(self, trace) as sbuf: 2383 print("looking at:", output, file=sbuf) 2384 2385 # The heading says either "Expecting" or "Not expecting". 2386 heading = "Expecting" if matching else "Not expecting" 2387 2388 # Start from the startstr, if specified. 2389 # If there's no startstr, set the initial state appropriately. 2390 matched = output.startswith(startstr) if startstr else ( 2391 True if matching else False) 2392 2393 if startstr: 2394 with recording(self, trace) as sbuf: 2395 print("%s start string: %s" % (heading, startstr), file=sbuf) 2396 print("Matched" if matched else "Not matched", file=sbuf) 2397 2398 # Look for endstr, if specified. 2399 keepgoing = matched if matching else not matched 2400 if endstr: 2401 matched = output.endswith(endstr) 2402 with recording(self, trace) as sbuf: 2403 print("%s end string: %s" % (heading, endstr), file=sbuf) 2404 print("Matched" if matched else "Not matched", file=sbuf) 2405 2406 # Look for sub strings, if specified. 2407 keepgoing = matched if matching else not matched 2408 if substrs and keepgoing: 2409 start = 0 2410 for substr in substrs: 2411 index = output[start:].find(substr) 2412 start = start + index if ordered and matching else 0 2413 matched = index != -1 2414 with recording(self, trace) as sbuf: 2415 print("%s sub string: %s" % (heading, substr), file=sbuf) 2416 print("Matched" if matched else "Not matched", file=sbuf) 2417 keepgoing = matched if matching else not matched 2418 if not keepgoing: 2419 break 2420 2421 # Search for regular expression patterns, if specified. 2422 keepgoing = matched if matching else not matched 2423 if patterns and keepgoing: 2424 for pattern in patterns: 2425 # Match Objects always have a boolean value of True. 2426 matched = bool(re.search(pattern, output)) 2427 with recording(self, trace) as sbuf: 2428 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2429 print("Matched" if matched else "Not matched", file=sbuf) 2430 keepgoing = matched if matching else not matched 2431 if not keepgoing: 2432 break 2433 2434 self.assertTrue(matched if matching else not matched, 2435 msg + "\nCommand output:\n" + EXP_MSG(str, output, exe) 2436 if msg else EXP_MSG(str, output, exe)) 2437 2438 def expect_expr( 2439 self, 2440 expr, 2441 result_summary=None, 2442 result_value=None, 2443 result_type=None, 2444 ): 2445 """ 2446 Evaluates the given expression and verifies the result. 2447 :param expr: The expression as a string. 2448 :param result_summary: The summary that the expression should have. None if the summary should not be checked. 2449 :param result_value: The value that the expression should have. None if the value should not be checked. 2450 :param result_type: The type that the expression result should have. None if the type should not be checked. 2451 """ 2452 self.assertTrue(expr.strip() == expr, "Expression contains trailing/leading whitespace: '" + expr + "'") 2453 2454 frame = self.frame() 2455 options = lldb.SBExpressionOptions() 2456 2457 # Disable fix-its that tests don't pass by accident. 2458 options.SetAutoApplyFixIts(False) 2459 2460 # Set the usual default options for normal expressions. 2461 options.SetIgnoreBreakpoints(True) 2462 2463 if self.frame().IsValid(): 2464 options.SetLanguage(frame.GuessLanguage()) 2465 eval_result = self.frame().EvaluateExpression(expr, options) 2466 else: 2467 eval_result = self.target().EvaluateExpression(expr, options) 2468 2469 if not eval_result.GetError().Success(): 2470 self.assertTrue(eval_result.GetError().Success(), 2471 "Unexpected failure with msg: " + eval_result.GetError().GetCString()) 2472 2473 if result_type: 2474 self.assertEqual(result_type, eval_result.GetDisplayTypeName()) 2475 2476 if result_value: 2477 self.assertEqual(result_value, eval_result.GetValue()) 2478 2479 if result_summary: 2480 self.assertEqual(result_summary, eval_result.GetSummary()) 2481 2482 def invoke(self, obj, name, trace=False): 2483 """Use reflection to call a method dynamically with no argument.""" 2484 trace = (True if traceAlways else trace) 2485 2486 method = getattr(obj, name) 2487 import inspect 2488 self.assertTrue(inspect.ismethod(method), 2489 name + "is a method name of object: " + str(obj)) 2490 result = method() 2491 with recording(self, trace) as sbuf: 2492 print(str(method) + ":", result, file=sbuf) 2493 return result 2494 2495 def build( 2496 self, 2497 architecture=None, 2498 compiler=None, 2499 dictionary=None): 2500 """Platform specific way to build the default binaries.""" 2501 module = builder_module() 2502 2503 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 2504 if self.getDebugInfo() is None: 2505 return self.buildDefault(architecture, compiler, dictionary) 2506 elif self.getDebugInfo() == "dsym": 2507 return self.buildDsym(architecture, compiler, dictionary) 2508 elif self.getDebugInfo() == "dwarf": 2509 return self.buildDwarf(architecture, compiler, dictionary) 2510 elif self.getDebugInfo() == "dwo": 2511 return self.buildDwo(architecture, compiler, dictionary) 2512 elif self.getDebugInfo() == "gmodules": 2513 return self.buildGModules(architecture, compiler, dictionary) 2514 else: 2515 self.fail("Can't build for debug info: %s" % self.getDebugInfo()) 2516 2517 def run_platform_command(self, cmd): 2518 platform = self.dbg.GetSelectedPlatform() 2519 shell_command = lldb.SBPlatformShellCommand(cmd) 2520 err = platform.Run(shell_command) 2521 return (err, shell_command.GetStatus(), shell_command.GetOutput()) 2522 2523 # ================================================= 2524 # Misc. helper methods for debugging test execution 2525 # ================================================= 2526 2527 def DebugSBValue(self, val): 2528 """Debug print a SBValue object, if traceAlways is True.""" 2529 from .lldbutil import value_type_to_str 2530 2531 if not traceAlways: 2532 return 2533 2534 err = sys.stderr 2535 err.write(val.GetName() + ":\n") 2536 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 2537 err.write('\t' + "ByteSize -> " + 2538 str(val.GetByteSize()) + '\n') 2539 err.write('\t' + "NumChildren -> " + 2540 str(val.GetNumChildren()) + '\n') 2541 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 2542 err.write('\t' + "ValueAsUnsigned -> " + 2543 str(val.GetValueAsUnsigned()) + '\n') 2544 err.write( 2545 '\t' + 2546 "ValueType -> " + 2547 value_type_to_str( 2548 val.GetValueType()) + 2549 '\n') 2550 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 2551 err.write('\t' + "IsPointerType -> " + 2552 str(val.TypeIsPointerType()) + '\n') 2553 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 2554 2555 def DebugSBType(self, type): 2556 """Debug print a SBType object, if traceAlways is True.""" 2557 if not traceAlways: 2558 return 2559 2560 err = sys.stderr 2561 err.write(type.GetName() + ":\n") 2562 err.write('\t' + "ByteSize -> " + 2563 str(type.GetByteSize()) + '\n') 2564 err.write('\t' + "IsPointerType -> " + 2565 str(type.IsPointerType()) + '\n') 2566 err.write('\t' + "IsReferenceType -> " + 2567 str(type.IsReferenceType()) + '\n') 2568 2569 def DebugPExpect(self, child): 2570 """Debug the spwaned pexpect object.""" 2571 if not traceAlways: 2572 return 2573 2574 print(child) 2575 2576 @classmethod 2577 def RemoveTempFile(cls, file): 2578 if os.path.exists(file): 2579 remove_file(file) 2580 2581# On Windows, the first attempt to delete a recently-touched file can fail 2582# because of a race with antimalware scanners. This function will detect a 2583# failure and retry. 2584 2585 2586def remove_file(file, num_retries=1, sleep_duration=0.5): 2587 for i in range(num_retries + 1): 2588 try: 2589 os.remove(file) 2590 return True 2591 except: 2592 time.sleep(sleep_duration) 2593 continue 2594 return False 2595