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