lldbtest.py revision 0c521648b02c92a221293d7f9762b6c5a4b02813
1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TesBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7The subclass should override the attribute mydir in order for the python runtime 8to locate the individual test cases when running as part of a large test suite 9or when running each test case as a separate python invocation. 10 11./dotest.py provides a test driver which sets up the environment to run the 12entire of part of the test suite . Example: 13 14# Exercises the test suite in the types directory.... 15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types 16... 17 18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' 19Command invoked: python ./dotest.py -A x86_64 types 20compilers=['clang'] 21 22Configuration: arch=x86_64 compiler=clang 23---------------------------------------------------------------------- 24Collected 72 tests 25 26........................................................................ 27---------------------------------------------------------------------- 28Ran 72 tests in 135.468s 29 30OK 31$ 32""" 33 34import os, sys, traceback 35import os.path 36import re 37import signal 38from subprocess import * 39import StringIO 40import time 41import types 42import unittest2 43import lldb 44 45# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 46# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options. 47 48# By default, traceAlways is False. 49if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES": 50 traceAlways = True 51else: 52 traceAlways = False 53 54# By default, doCleanup is True. 55if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO": 56 doCleanup = False 57else: 58 doCleanup = True 59 60 61# 62# Some commonly used assert messages. 63# 64 65COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 66 67CURRENT_EXECUTABLE_SET = "Current executable set successfully" 68 69PROCESS_IS_VALID = "Process is valid" 70 71PROCESS_KILLED = "Process is killed successfully" 72 73PROCESS_EXITED = "Process exited successfully" 74 75PROCESS_STOPPED = "Process status should be stopped" 76 77RUN_SUCCEEDED = "Process is launched successfully" 78 79RUN_COMPLETED = "Process exited successfully" 80 81BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 82 83BREAKPOINT_CREATED = "Breakpoint created successfully" 84 85BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 86 87BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 88 89BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" 90 91BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" 92 93BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" 94 95MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 96 97OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 98 99SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 100 101STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 102 103STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 104 105STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 106 107STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 108 109STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 110 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 111 112STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 113 114STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 115 116STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 117 118STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 119 120STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 121 122DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 123 124VALID_BREAKPOINT = "Got a valid breakpoint" 125 126VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 127 128VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 129 130VALID_FILESPEC = "Got a valid filespec" 131 132VALID_MODULE = "Got a valid module" 133 134VALID_PROCESS = "Got a valid process" 135 136VALID_SYMBOL = "Got a valid symbol" 137 138VALID_TARGET = "Got a valid target" 139 140VALID_TYPE = "Got a valid type" 141 142VALID_VARIABLE = "Got a valid variable" 143 144VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 145 146WATCHPOINT_CREATED = "Watchpoint created successfully" 147 148def CMD_MSG(str): 149 '''A generic "Command '%s' returns successfully" message generator.''' 150 return "Command '%s' returns successfully" % str 151 152def COMPLETION_MSG(str_before, str_after): 153 '''A generic message generator for the completion mechanism.''' 154 return "'%s' successfully completes to '%s'" % (str_before, str_after) 155 156def EXP_MSG(str, exe): 157 '''A generic "'%s' returns expected result" message generator if exe. 158 Otherwise, it generates "'%s' matches expected result" message.''' 159 return "'%s' %s expected result" % (str, 'returns' if exe else 'matches') 160 161def SETTING_MSG(setting): 162 '''A generic "Value of setting '%s' is correct" message generator.''' 163 return "Value of setting '%s' is correct" % setting 164 165def EnvArray(): 166 """Returns an env variable array from the os.environ map object.""" 167 return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values()) 168 169def line_number(filename, string_to_match): 170 """Helper function to return the line number of the first matched string.""" 171 with open(filename, 'r') as f: 172 for i, line in enumerate(f): 173 if line.find(string_to_match) != -1: 174 # Found our match. 175 return i+1 176 raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename)) 177 178def pointer_size(): 179 """Return the pointer size of the host system.""" 180 import ctypes 181 a_pointer = ctypes.c_void_p(0xffff) 182 return 8 * ctypes.sizeof(a_pointer) 183 184def is_exe(fpath): 185 """Returns true if fpath is an executable.""" 186 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 187 188def which(program): 189 """Returns the full path to a program; None otherwise.""" 190 fpath, fname = os.path.split(program) 191 if fpath: 192 if is_exe(program): 193 return program 194 else: 195 for path in os.environ["PATH"].split(os.pathsep): 196 exe_file = os.path.join(path, program) 197 if is_exe(exe_file): 198 return exe_file 199 return None 200 201class recording(StringIO.StringIO): 202 """ 203 A nice little context manager for recording the debugger interactions into 204 our session object. If trace flag is ON, it also emits the interactions 205 into the stderr. 206 """ 207 def __init__(self, test, trace): 208 """Create a StringIO instance; record the session obj and trace flag.""" 209 StringIO.StringIO.__init__(self) 210 # The test might not have undergone the 'setUp(self)' phase yet, so that 211 # the attribute 'session' might not even exist yet. 212 self.session = getattr(test, "session", None) if test else None 213 self.trace = trace 214 215 def __enter__(self): 216 """ 217 Context management protocol on entry to the body of the with statement. 218 Just return the StringIO object. 219 """ 220 return self 221 222 def __exit__(self, type, value, tb): 223 """ 224 Context management protocol on exit from the body of the with statement. 225 If trace is ON, it emits the recordings into stderr. Always add the 226 recordings to our session object. And close the StringIO object, too. 227 """ 228 if self.trace: 229 print >> sys.stderr, self.getvalue() 230 if self.session: 231 print >> self.session, self.getvalue() 232 self.close() 233 234# From 2.7's subprocess.check_output() convenience function. 235# Return a tuple (stdoutdata, stderrdata). 236def system(*popenargs, **kwargs): 237 r"""Run an os command with arguments and return its output as a byte string. 238 239 If the exit code was non-zero it raises a CalledProcessError. The 240 CalledProcessError object will have the return code in the returncode 241 attribute and output in the output attribute. 242 243 The arguments are the same as for the Popen constructor. Example: 244 245 >>> check_output(["ls", "-l", "/dev/null"]) 246 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 247 248 The stdout argument is not allowed as it is used internally. 249 To capture standard error in the result, use stderr=STDOUT. 250 251 >>> check_output(["/bin/sh", "-c", 252 ... "ls -l non_existent_file ; exit 0"], 253 ... stderr=STDOUT) 254 'ls: non_existent_file: No such file or directory\n' 255 """ 256 257 # Assign the sender object to variable 'test' and remove it from kwargs. 258 test = kwargs.pop('sender', None) 259 260 if 'stdout' in kwargs: 261 raise ValueError('stdout argument not allowed, it will be overridden.') 262 process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs) 263 pid = process.pid 264 output, error = process.communicate() 265 retcode = process.poll() 266 267 with recording(test, traceAlways) as sbuf: 268 if isinstance(popenargs, types.StringTypes): 269 args = [popenargs] 270 else: 271 args = list(popenargs) 272 print >> sbuf 273 print >> sbuf, "os command:", args 274 print >> sbuf, "with pid:", pid 275 print >> sbuf, "stdout:", output 276 print >> sbuf, "stderr:", error 277 print >> sbuf, "retcode:", retcode 278 print >> sbuf 279 280 if retcode: 281 cmd = kwargs.get("args") 282 if cmd is None: 283 cmd = popenargs[0] 284 raise CalledProcessError(retcode, cmd) 285 return (output, error) 286 287def getsource_if_available(obj): 288 """ 289 Return the text of the source code for an object if available. Otherwise, 290 a print representation is returned. 291 """ 292 import inspect 293 try: 294 return inspect.getsource(obj) 295 except: 296 return repr(obj) 297 298def builder_module(): 299 return __import__("builder_" + sys.platform) 300 301# 302# Decorators for categorizing test cases. 303# 304 305from functools import wraps 306def python_api_test(func): 307 """Decorate the item as a Python API only test.""" 308 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 309 raise Exception("@python_api_test can only be used to decorate a test method") 310 @wraps(func) 311 def wrapper(self, *args, **kwargs): 312 try: 313 if lldb.dont_do_python_api_test: 314 self.skipTest("python api tests") 315 except AttributeError: 316 pass 317 return func(self, *args, **kwargs) 318 319 # Mark this function as such to separate them from lldb command line tests. 320 wrapper.__python_api_test__ = True 321 return wrapper 322 323def benchmarks_test(func): 324 """Decorate the item as a benchmarks test.""" 325 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 326 raise Exception("@benchmarks_test can only be used to decorate a test method") 327 @wraps(func) 328 def wrapper(self, *args, **kwargs): 329 try: 330 if not lldb.just_do_benchmarks_test: 331 self.skipTest("benchmarks tests") 332 except AttributeError: 333 pass 334 return func(self, *args, **kwargs) 335 336 # Mark this function as such to separate them from the regular tests. 337 wrapper.__benchmarks_test__ = True 338 return wrapper 339 340def dsym_test(func): 341 """Decorate the item as a dsym test.""" 342 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 343 raise Exception("@dsym_test can only be used to decorate a test method") 344 @wraps(func) 345 def wrapper(self, *args, **kwargs): 346 try: 347 if lldb.dont_do_dsym_test: 348 self.skipTest("dsym tests") 349 except AttributeError: 350 pass 351 return func(self, *args, **kwargs) 352 353 # Mark this function as such to separate them from the regular tests. 354 wrapper.__dsym_test__ = True 355 return wrapper 356 357def dwarf_test(func): 358 """Decorate the item as a dwarf test.""" 359 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 360 raise Exception("@dwarf_test can only be used to decorate a test method") 361 @wraps(func) 362 def wrapper(self, *args, **kwargs): 363 try: 364 if lldb.dont_do_dwarf_test: 365 self.skipTest("dwarf tests") 366 except AttributeError: 367 pass 368 return func(self, *args, **kwargs) 369 370 # Mark this function as such to separate them from the regular tests. 371 wrapper.__dwarf_test__ = True 372 return wrapper 373 374def expectedFailureGcc(bugnumber=None, compiler_version=["=", None]): 375 if callable(bugnumber): 376 @wraps(bugnumber) 377 def expectedFailureGcc_easy_wrapper(*args, **kwargs): 378 from unittest2 import case 379 self = args[0] 380 test_compiler = self.getCompiler() 381 try: 382 bugnumber(*args, **kwargs) 383 except Exception: 384 if "gcc" in test_compiler and self.expectedCompilerVersion(compiler_version): 385 raise case._ExpectedFailure(sys.exc_info(),None) 386 else: 387 raise 388 if "gcc" in test_compiler: 389 raise case._UnexpectedSuccess(sys.exc_info(),None) 390 return expectedFailureGcc_easy_wrapper 391 else: 392 def expectedFailureGcc_impl(func): 393 @wraps(func) 394 def wrapper(*args, **kwargs): 395 from unittest2 import case 396 self = args[0] 397 test_compiler = self.getCompiler() 398 try: 399 func(*args, **kwargs) 400 except Exception: 401 if "gcc" in test_compiler and self.expectedCompilerVersion(compiler_version): 402 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 403 else: 404 raise 405 if "gcc" in test_compiler: 406 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 407 return wrapper 408 return expectedFailureGcc_impl 409 410def expectedFailureClang(bugnumber=None): 411 if callable(bugnumber): 412 @wraps(bugnumber) 413 def expectedFailureClang_easy_wrapper(*args, **kwargs): 414 from unittest2 import case 415 self = args[0] 416 test_compiler = self.getCompiler() 417 try: 418 bugnumber(*args, **kwargs) 419 except Exception: 420 if "clang" in test_compiler: 421 raise case._ExpectedFailure(sys.exc_info(),None) 422 else: 423 raise 424 if "clang" in test_compiler: 425 raise case._UnexpectedSuccess(sys.exc_info(),None) 426 return expectedFailureClang_easy_wrapper 427 else: 428 def expectedFailureClang_impl(func): 429 @wraps(func) 430 def wrapper(*args, **kwargs): 431 from unittest2 import case 432 self = args[0] 433 test_compiler = self.getCompiler() 434 try: 435 func(*args, **kwargs) 436 except Exception: 437 if "clang" in test_compiler: 438 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 439 else: 440 raise 441 if "clang" in test_compiler: 442 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 443 return wrapper 444 return expectedFailureClang_impl 445 446def expectedFailureIcc(bugnumber=None): 447 if callable(bugnumber): 448 @wraps(bugnumber) 449 def expectedFailureIcc_easy_wrapper(*args, **kwargs): 450 from unittest2 import case 451 self = args[0] 452 test_compiler = self.getCompiler() 453 try: 454 bugnumber(*args, **kwargs) 455 except Exception: 456 if "icc" in test_compiler: 457 raise case._ExpectedFailure(sys.exc_info(),None) 458 else: 459 raise 460 if "icc" in test_compiler: 461 raise case._UnexpectedSuccess(sys.exc_info(),None) 462 return expectedFailureIcc_easy_wrapper 463 else: 464 def expectedFailureIcc_impl(func): 465 @wraps(func) 466 def wrapper(*args, **kwargs): 467 from unittest2 import case 468 self = args[0] 469 test_compiler = self.getCompiler() 470 try: 471 func(*args, **kwargs) 472 except Exception: 473 if "icc" in test_compiler: 474 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 475 else: 476 raise 477 if "icc" in test_compiler: 478 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 479 return wrapper 480 return expectedFailureIcc_impl 481 482 483def expectedFailurei386(bugnumber=None): 484 if callable(bugnumber): 485 @wraps(bugnumber) 486 def expectedFailurei386_easy_wrapper(*args, **kwargs): 487 from unittest2 import case 488 self = args[0] 489 arch = self.getArchitecture() 490 try: 491 bugnumber(*args, **kwargs) 492 except Exception: 493 if "i386" in arch: 494 raise case._ExpectedFailure(sys.exc_info(),None) 495 else: 496 raise 497 if "i386" in arch: 498 raise case._UnexpectedSuccess(sys.exc_info(),None) 499 return expectedFailurei386_easy_wrapper 500 else: 501 def expectedFailurei386_impl(func): 502 @wraps(func) 503 def wrapper(*args, **kwargs): 504 from unittest2 import case 505 self = args[0] 506 arch = self.getArchitecture() 507 try: 508 func(*args, **kwargs) 509 except Exception: 510 if "i386" in arch: 511 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 512 else: 513 raise 514 if "i386" in arch: 515 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 516 return wrapper 517 return expectedFailurei386_impl 518 519def expectedFailureLinux(bugnumber=None, compilers=None): 520 if callable(bugnumber): 521 @wraps(bugnumber) 522 def expectedFailureLinux_easy_wrapper(*args, **kwargs): 523 from unittest2 import case 524 self = args[0] 525 platform = sys.platform 526 try: 527 bugnumber(*args, **kwargs) 528 except Exception: 529 if "linux" in platform and self.expectedCompiler(compilers): 530 raise case._ExpectedFailure(sys.exc_info(),None) 531 else: 532 raise 533 if "linux" in platform and self.expectedCompiler(compilers): 534 raise case._UnexpectedSuccess(sys.exc_info(),None) 535 return expectedFailureLinux_easy_wrapper 536 else: 537 def expectedFailureLinux_impl(func): 538 @wraps(func) 539 def wrapper(*args, **kwargs): 540 from unittest2 import case 541 self = args[0] 542 platform = sys.platform 543 try: 544 func(*args, **kwargs) 545 except Exception: 546 if "linux" in platform and self.expectedCompiler(compilers): 547 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 548 else: 549 raise 550 if "linux" in platform and self.expectedCompiler(compilers): 551 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 552 return wrapper 553 return expectedFailureLinux_impl 554 555def expectedFailureDarwin(bugnumber=None): 556 if callable(bugnumber): 557 @wraps(bugnumber) 558 def expectedFailureDarwin_easy_wrapper(*args, **kwargs): 559 from unittest2 import case 560 self = args[0] 561 platform = sys.platform 562 try: 563 bugnumber(*args, **kwargs) 564 except Exception: 565 if "darwin" in platform: 566 raise case._ExpectedFailure(sys.exc_info(),None) 567 else: 568 raise 569 if "darwin" in platform: 570 raise case._UnexpectedSuccess(sys.exc_info(),None) 571 return expectedFailureDarwin_easy_wrapper 572 else: 573 def expectedFailureDarwin_impl(func): 574 @wraps(func) 575 def wrapper(*args, **kwargs): 576 from unittest2 import case 577 self = args[0] 578 platform = sys.platform 579 try: 580 func(*args, **kwargs) 581 except Exception: 582 if "darwin" in platform: 583 raise case._ExpectedFailure(sys.exc_info(),bugnumber) 584 else: 585 raise 586 if "darwin" in platform: 587 raise case._UnexpectedSuccess(sys.exc_info(),bugnumber) 588 return wrapper 589 return expectedFailureDarwin_impl 590 591def skipIfLinux(func): 592 """Decorate the item to skip tests that should be skipped on Linux.""" 593 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 594 raise Exception("@skipIfLinux can only be used to decorate a test method") 595 @wraps(func) 596 def wrapper(*args, **kwargs): 597 from unittest2 import case 598 self = args[0] 599 platform = sys.platform 600 if "linux" in platform: 601 self.skipTest("skip on linux") 602 else: 603 func(*args, **kwargs) 604 return wrapper 605 606def skipIfLinuxClang(func): 607 """Decorate the item to skip tests that should be skipped if building on 608 Linux with clang. 609 """ 610 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 611 raise Exception("@skipIfLinuxClang can only be used to decorate a test method") 612 @wraps(func) 613 def wrapper(*args, **kwargs): 614 from unittest2 import case 615 self = args[0] 616 compiler = self.getCompiler() 617 platform = sys.platform 618 if "clang" in compiler and "linux" in platform: 619 self.skipTest("skipping because Clang is used on Linux") 620 else: 621 func(*args, **kwargs) 622 return wrapper 623 624def skipIfGcc(func): 625 """Decorate the item to skip tests that should be skipped if building with gcc .""" 626 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 627 raise Exception("@skipIfGcc can only be used to decorate a test method") 628 @wraps(func) 629 def wrapper(*args, **kwargs): 630 from unittest2 import case 631 self = args[0] 632 compiler = self.getCompiler() 633 if "gcc" in compiler: 634 self.skipTest("skipping because gcc is the test compiler") 635 else: 636 func(*args, **kwargs) 637 return wrapper 638 639def skipIfIcc(func): 640 """Decorate the item to skip tests that should be skipped if building with icc .""" 641 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 642 raise Exception("@skipIfIcc can only be used to decorate a test method") 643 @wraps(func) 644 def wrapper(*args, **kwargs): 645 from unittest2 import case 646 self = args[0] 647 compiler = self.getCompiler() 648 if "icc" in compiler: 649 self.skipTest("skipping because icc is the test compiler") 650 else: 651 func(*args, **kwargs) 652 return wrapper 653 654def skipIfi386(func): 655 """Decorate the item to skip tests that should be skipped if building 32-bit.""" 656 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 657 raise Exception("@skipIfi386 can only be used to decorate a test method") 658 @wraps(func) 659 def wrapper(*args, **kwargs): 660 from unittest2 import case 661 self = args[0] 662 if "i386" == self.getArchitecture(): 663 self.skipTest("skipping because i386 is not a supported architecture") 664 else: 665 func(*args, **kwargs) 666 return wrapper 667 668 669class Base(unittest2.TestCase): 670 """ 671 Abstract base for performing lldb (see TestBase) or other generic tests (see 672 BenchBase for one example). lldbtest.Base works with the test driver to 673 accomplish things. 674 675 """ 676 677 # The concrete subclass should override this attribute. 678 mydir = None 679 680 # Keep track of the old current working directory. 681 oldcwd = None 682 683 def TraceOn(self): 684 """Returns True if we are in trace mode (tracing detailed test execution).""" 685 return traceAlways 686 687 @classmethod 688 def setUpClass(cls): 689 """ 690 Python unittest framework class setup fixture. 691 Do current directory manipulation. 692 """ 693 694 # Fail fast if 'mydir' attribute is not overridden. 695 if not cls.mydir or len(cls.mydir) == 0: 696 raise Exception("Subclasses must override the 'mydir' attribute.") 697 698 # Save old working directory. 699 cls.oldcwd = os.getcwd() 700 701 # Change current working directory if ${LLDB_TEST} is defined. 702 # See also dotest.py which sets up ${LLDB_TEST}. 703 if ("LLDB_TEST" in os.environ): 704 if traceAlways: 705 print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir) 706 os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir)) 707 708 @classmethod 709 def tearDownClass(cls): 710 """ 711 Python unittest framework class teardown fixture. 712 Do class-wide cleanup. 713 """ 714 715 if doCleanup and not lldb.skip_build_and_cleanup: 716 # First, let's do the platform-specific cleanup. 717 module = builder_module() 718 if not module.cleanup(): 719 raise Exception("Don't know how to do cleanup") 720 721 # Subclass might have specific cleanup function defined. 722 if getattr(cls, "classCleanup", None): 723 if traceAlways: 724 print >> sys.stderr, "Call class-specific cleanup function for class:", cls 725 try: 726 cls.classCleanup() 727 except: 728 exc_type, exc_value, exc_tb = sys.exc_info() 729 traceback.print_exception(exc_type, exc_value, exc_tb) 730 731 # Restore old working directory. 732 if traceAlways: 733 print >> sys.stderr, "Restore dir to:", cls.oldcwd 734 os.chdir(cls.oldcwd) 735 736 @classmethod 737 def skipLongRunningTest(cls): 738 """ 739 By default, we skip long running test case. 740 This can be overridden by passing '-l' to the test driver (dotest.py). 741 """ 742 if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]: 743 return False 744 else: 745 return True 746 747 def setUp(self): 748 """Fixture for unittest test case setup. 749 750 It works with the test driver to conditionally skip tests and does other 751 initializations.""" 752 #import traceback 753 #traceback.print_stack() 754 755 if "LLDB_EXEC" in os.environ: 756 self.lldbExec = os.environ["LLDB_EXEC"] 757 else: 758 self.lldbExec = None 759 if "LLDB_HERE" in os.environ: 760 self.lldbHere = os.environ["LLDB_HERE"] 761 else: 762 self.lldbHere = None 763 # If we spawn an lldb process for test (via pexpect), do not load the 764 # init file unless told otherwise. 765 if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: 766 self.lldbOption = "" 767 else: 768 self.lldbOption = "--no-lldbinit" 769 770 # Assign the test method name to self.testMethodName. 771 # 772 # For an example of the use of this attribute, look at test/types dir. 773 # There are a bunch of test cases under test/types and we don't want the 774 # module cacheing subsystem to be confused with executable name "a.out" 775 # used for all the test cases. 776 self.testMethodName = self._testMethodName 777 778 # Python API only test is decorated with @python_api_test, 779 # which also sets the "__python_api_test__" attribute of the 780 # function object to True. 781 try: 782 if lldb.just_do_python_api_test: 783 testMethod = getattr(self, self._testMethodName) 784 if getattr(testMethod, "__python_api_test__", False): 785 pass 786 else: 787 self.skipTest("non python api test") 788 except AttributeError: 789 pass 790 791 # Benchmarks test is decorated with @benchmarks_test, 792 # which also sets the "__benchmarks_test__" attribute of the 793 # function object to True. 794 try: 795 if lldb.just_do_benchmarks_test: 796 testMethod = getattr(self, self._testMethodName) 797 if getattr(testMethod, "__benchmarks_test__", False): 798 pass 799 else: 800 self.skipTest("non benchmarks test") 801 except AttributeError: 802 pass 803 804 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 805 # with it using pexpect. 806 self.child = None 807 self.child_prompt = "(lldb) " 808 # If the child is interacting with the embedded script interpreter, 809 # there are two exits required during tear down, first to quit the 810 # embedded script interpreter and second to quit the lldb command 811 # interpreter. 812 self.child_in_script_interpreter = False 813 814 # These are for customized teardown cleanup. 815 self.dict = None 816 self.doTearDownCleanup = False 817 # And in rare cases where there are multiple teardown cleanups. 818 self.dicts = [] 819 self.doTearDownCleanups = False 820 821 # List of spawned subproces.Popen objects 822 self.subprocesses = [] 823 824 # List of forked process PIDs 825 self.forkedProcessPids = [] 826 827 # Create a string buffer to record the session info, to be dumped into a 828 # test case specific file if test failure is encountered. 829 self.session = StringIO.StringIO() 830 831 # Optimistically set __errored__, __failed__, __expected__ to False 832 # initially. If the test errored/failed, the session info 833 # (self.session) is then dumped into a session specific file for 834 # diagnosis. 835 self.__errored__ = False 836 self.__failed__ = False 837 self.__expected__ = False 838 # We are also interested in unexpected success. 839 self.__unexpected__ = False 840 # And skipped tests. 841 self.__skipped__ = False 842 843 # See addTearDownHook(self, hook) which allows the client to add a hook 844 # function to be run during tearDown() time. 845 self.hooks = [] 846 847 # See HideStdout(self). 848 self.sys_stdout_hidden = False 849 850 # set environment variable names for finding shared libraries 851 if sys.platform.startswith("darwin"): 852 self.dylibPath = 'DYLD_LIBRARY_PATH' 853 elif sys.platform.startswith("linux") or sys.platform.startswith("freebsd"): 854 self.dylibPath = 'LD_LIBRARY_PATH' 855 856 def runHooks(self, child=None, child_prompt=None, use_cmd_api=False): 857 """Perform the run hooks to bring lldb debugger to the desired state. 858 859 By default, expect a pexpect spawned child and child prompt to be 860 supplied (use_cmd_api=False). If use_cmd_api is true, ignore the child 861 and child prompt and use self.runCmd() to run the hooks one by one. 862 863 Note that child is a process spawned by pexpect.spawn(). If not, your 864 test case is mostly likely going to fail. 865 866 See also dotest.py where lldb.runHooks are processed/populated. 867 """ 868 if not lldb.runHooks: 869 self.skipTest("No runhooks specified for lldb, skip the test") 870 if use_cmd_api: 871 for hook in lldb.runhooks: 872 self.runCmd(hook) 873 else: 874 if not child or not child_prompt: 875 self.fail("Both child and child_prompt need to be defined.") 876 for hook in lldb.runHooks: 877 child.sendline(hook) 878 child.expect_exact(child_prompt) 879 880 def setAsync(self, value): 881 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 882 old_async = self.dbg.GetAsync() 883 self.dbg.SetAsync(value) 884 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 885 886 def cleanupSubprocesses(self): 887 # Ensure any subprocesses are cleaned up 888 for p in self.subprocesses: 889 if p.poll() == None: 890 p.terminate() 891 del p 892 del self.subprocesses[:] 893 # Ensure any forked processes are cleaned up 894 for pid in self.forkedProcessPids: 895 if os.path.exists("/proc/" + str(pid)): 896 os.kill(pid, signal.SIGTERM) 897 898 def spawnSubprocess(self, executable, args=[]): 899 """ Creates a subprocess.Popen object with the specified executable and arguments, 900 saves it in self.subprocesses, and returns the object. 901 NOTE: if using this function, ensure you also call: 902 903 self.addTearDownHook(self.cleanupSubprocesses) 904 905 otherwise the test suite will leak processes. 906 """ 907 908 # Don't display the stdout if not in TraceOn() mode. 909 proc = Popen([executable] + args, 910 stdout = open(os.devnull) if not self.TraceOn() else None, 911 stdin = PIPE) 912 self.subprocesses.append(proc) 913 return proc 914 915 def forkSubprocess(self, executable, args=[]): 916 """ Fork a subprocess with its own group ID. 917 NOTE: if using this function, ensure you also call: 918 919 self.addTearDownHook(self.cleanupSubprocesses) 920 921 otherwise the test suite will leak processes. 922 """ 923 child_pid = os.fork() 924 if child_pid == 0: 925 # If more I/O support is required, this can be beefed up. 926 fd = os.open(os.devnull, os.O_RDWR) 927 os.dup2(fd, 0) 928 os.dup2(fd, 1) 929 os.dup2(fd, 2) 930 # This call causes the child to have its of group ID 931 os.setpgid(0,0) 932 os.execvp(executable, [executable] + args) 933 # Give the child time to get through the execvp() call 934 time.sleep(0.1) 935 self.forkedProcessPids.append(child_pid) 936 return child_pid 937 938 def HideStdout(self): 939 """Hide output to stdout from the user. 940 941 During test execution, there might be cases where we don't want to show the 942 standard output to the user. For example, 943 944 self.runCmd(r'''sc print "\n\n\tHello!\n"''') 945 946 tests whether command abbreviation for 'script' works or not. There is no 947 need to show the 'Hello' output to the user as long as the 'script' command 948 succeeds and we are not in TraceOn() mode (see the '-t' option). 949 950 In this case, the test method calls self.HideStdout(self) to redirect the 951 sys.stdout to a null device, and restores the sys.stdout upon teardown. 952 953 Note that you should only call this method at most once during a test case 954 execution. Any subsequent call has no effect at all.""" 955 if self.sys_stdout_hidden: 956 return 957 958 self.sys_stdout_hidden = True 959 old_stdout = sys.stdout 960 sys.stdout = open(os.devnull, 'w') 961 def restore_stdout(): 962 sys.stdout = old_stdout 963 self.addTearDownHook(restore_stdout) 964 965 # ======================================================================= 966 # Methods for customized teardown cleanups as well as execution of hooks. 967 # ======================================================================= 968 969 def setTearDownCleanup(self, dictionary=None): 970 """Register a cleanup action at tearDown() time with a dictinary""" 971 self.dict = dictionary 972 self.doTearDownCleanup = True 973 974 def addTearDownCleanup(self, dictionary): 975 """Add a cleanup action at tearDown() time with a dictinary""" 976 self.dicts.append(dictionary) 977 self.doTearDownCleanups = True 978 979 def addTearDownHook(self, hook): 980 """ 981 Add a function to be run during tearDown() time. 982 983 Hooks are executed in a first come first serve manner. 984 """ 985 if callable(hook): 986 with recording(self, traceAlways) as sbuf: 987 print >> sbuf, "Adding tearDown hook:", getsource_if_available(hook) 988 self.hooks.append(hook) 989 990 def tearDown(self): 991 """Fixture for unittest test case teardown.""" 992 #import traceback 993 #traceback.print_stack() 994 995 # This is for the case of directly spawning 'lldb' and interacting with it 996 # using pexpect. 997 import pexpect 998 if self.child and self.child.isalive(): 999 with recording(self, traceAlways) as sbuf: 1000 print >> sbuf, "tearing down the child process...." 1001 try: 1002 if self.child_in_script_interpreter: 1003 self.child.sendline('quit()') 1004 self.child.expect_exact(self.child_prompt) 1005 self.child.sendline('settings set interpreter.prompt-on-quit false') 1006 self.child.sendline('quit') 1007 self.child.expect(pexpect.EOF) 1008 except ValueError, ExceptionPexpect: 1009 # child is already terminated 1010 pass 1011 1012 # Give it one final blow to make sure the child is terminated. 1013 self.child.close() 1014 1015 # Check and run any hook functions. 1016 for hook in reversed(self.hooks): 1017 with recording(self, traceAlways) as sbuf: 1018 print >> sbuf, "Executing tearDown hook:", getsource_if_available(hook) 1019 hook() 1020 1021 del self.hooks 1022 1023 # Perform registered teardown cleanup. 1024 if doCleanup and self.doTearDownCleanup: 1025 self.cleanup(dictionary=self.dict) 1026 1027 # In rare cases where there are multiple teardown cleanups added. 1028 if doCleanup and self.doTearDownCleanups: 1029 if self.dicts: 1030 for dict in reversed(self.dicts): 1031 self.cleanup(dictionary=dict) 1032 1033 # Decide whether to dump the session info. 1034 self.dumpSessionInfo() 1035 1036 # ========================================================= 1037 # Various callbacks to allow introspection of test progress 1038 # ========================================================= 1039 1040 def markError(self): 1041 """Callback invoked when an error (unexpected exception) errored.""" 1042 self.__errored__ = True 1043 with recording(self, False) as sbuf: 1044 # False because there's no need to write "ERROR" to the stderr twice. 1045 # Once by the Python unittest framework, and a second time by us. 1046 print >> sbuf, "ERROR" 1047 1048 def markFailure(self): 1049 """Callback invoked when a failure (test assertion failure) occurred.""" 1050 self.__failed__ = True 1051 with recording(self, False) as sbuf: 1052 # False because there's no need to write "FAIL" to the stderr twice. 1053 # Once by the Python unittest framework, and a second time by us. 1054 print >> sbuf, "FAIL" 1055 1056 def markExpectedFailure(self,err,bugnumber): 1057 """Callback invoked when an expected failure/error occurred.""" 1058 self.__expected__ = True 1059 with recording(self, False) as sbuf: 1060 # False because there's no need to write "expected failure" to the 1061 # stderr twice. 1062 # Once by the Python unittest framework, and a second time by us. 1063 if bugnumber == None: 1064 print >> sbuf, "expected failure" 1065 else: 1066 print >> sbuf, "expected failure (problem id:" + str(bugnumber) + ")" 1067 1068 def markSkippedTest(self): 1069 """Callback invoked when a test is skipped.""" 1070 self.__skipped__ = True 1071 with recording(self, False) as sbuf: 1072 # False because there's no need to write "skipped test" to the 1073 # stderr twice. 1074 # Once by the Python unittest framework, and a second time by us. 1075 print >> sbuf, "skipped test" 1076 1077 def markUnexpectedSuccess(self, bugnumber): 1078 """Callback invoked when an unexpected success occurred.""" 1079 self.__unexpected__ = True 1080 with recording(self, False) as sbuf: 1081 # False because there's no need to write "unexpected success" to the 1082 # stderr twice. 1083 # Once by the Python unittest framework, and a second time by us. 1084 if bugnumber == None: 1085 print >> sbuf, "unexpected success" 1086 else: 1087 print >> sbuf, "unexpected success (problem id:" + str(bugnumber) + ")" 1088 1089 def dumpSessionInfo(self): 1090 """ 1091 Dump the debugger interactions leading to a test error/failure. This 1092 allows for more convenient postmortem analysis. 1093 1094 See also LLDBTestResult (dotest.py) which is a singlton class derived 1095 from TextTestResult and overwrites addError, addFailure, and 1096 addExpectedFailure methods to allow us to to mark the test instance as 1097 such. 1098 """ 1099 1100 # We are here because self.tearDown() detected that this test instance 1101 # either errored or failed. The lldb.test_result singleton contains 1102 # two lists (erros and failures) which get populated by the unittest 1103 # framework. Look over there for stack trace information. 1104 # 1105 # The lists contain 2-tuples of TestCase instances and strings holding 1106 # formatted tracebacks. 1107 # 1108 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 1109 if self.__errored__: 1110 pairs = lldb.test_result.errors 1111 prefix = 'Error' 1112 elif self.__failed__: 1113 pairs = lldb.test_result.failures 1114 prefix = 'Failure' 1115 elif self.__expected__: 1116 pairs = lldb.test_result.expectedFailures 1117 prefix = 'ExpectedFailure' 1118 elif self.__skipped__: 1119 prefix = 'SkippedTest' 1120 elif self.__unexpected__: 1121 prefix = "UnexpectedSuccess" 1122 else: 1123 # Simply return, there's no session info to dump! 1124 return 1125 1126 if not self.__unexpected__ and not self.__skipped__: 1127 for test, traceback in pairs: 1128 if test is self: 1129 print >> self.session, traceback 1130 1131 testMethod = getattr(self, self._testMethodName) 1132 if getattr(testMethod, "__benchmarks_test__", False): 1133 benchmarks = True 1134 else: 1135 benchmarks = False 1136 1137 # This records the compiler version used for the test. 1138 system([self.getCompiler(), "-v"], sender=self) 1139 1140 dname = os.path.join(os.environ["LLDB_TEST"], 1141 os.environ["LLDB_SESSION_DIRNAME"]) 1142 if not os.path.isdir(dname): 1143 os.mkdir(dname) 1144 fname = os.path.join(dname, "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), "_".join(self.getCompiler().split('/')), self.id())) 1145 with open(fname, "w") as f: 1146 import datetime 1147 print >> f, "Session info generated @", datetime.datetime.now().ctime() 1148 print >> f, self.session.getvalue() 1149 print >> f, "To rerun this test, issue the following command from the 'test' directory:\n" 1150 print >> f, "./dotest.py %s -v %s -f %s.%s" % (self.getRunOptions(), 1151 ('+b' if benchmarks else '-t'), 1152 self.__class__.__name__, 1153 self._testMethodName) 1154 1155 # ==================================================== 1156 # Config. methods supported through a plugin interface 1157 # (enables reading of the current test configuration) 1158 # ==================================================== 1159 1160 def getArchitecture(self): 1161 """Returns the architecture in effect the test suite is running with.""" 1162 module = builder_module() 1163 return module.getArchitecture() 1164 1165 def getCompiler(self): 1166 """Returns the compiler in effect the test suite is running with.""" 1167 module = builder_module() 1168 return module.getCompiler() 1169 1170 def getCompilerVersion(self): 1171 """ Returns a string that represents the compiler version. 1172 Supports: llvm, clang. 1173 """ 1174 from lldbutil import which 1175 version = 'unknown' 1176 1177 compiler = self.getCompiler() 1178 version_output = system([which(compiler), "-v"])[1] 1179 for line in version_output.split(os.linesep): 1180 m = re.search('version ([0-9\.]+)', line) 1181 if m: 1182 version = m.group(1) 1183 return version 1184 1185 def expectedCompilerVersion(self, compiler_version): 1186 """Returns True iff compiler_version[1] matches the current compiler version. 1187 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1188 Any operator other than the following defaults to an equality test: 1189 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1190 """ 1191 if (compiler_version == None): 1192 return True 1193 operator = str(compiler_version[0]) 1194 version = compiler_version[1] 1195 1196 if (version == None): 1197 return True 1198 if (operator == '>'): 1199 return self.getCompilerVersion() > version 1200 if (operator == '>=' or operator == '=>'): 1201 return self.getCompilerVersion() >= version 1202 if (operator == '<'): 1203 return self.getCompilerVersion() < version 1204 if (operator == '<=' or operator == '=<'): 1205 return self.getCompilerVersion() <= version 1206 if (operator == '!=' or operator == '!' or operator == 'not'): 1207 return str(version) not in str(self.getCompilerVersion()) 1208 return str(version) in str(self.getCompilerVersion()) 1209 1210 def expectedCompiler(self, compilers): 1211 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1212 if (compilers == None): 1213 return True 1214 1215 for compiler in compilers: 1216 if compiler in self.getCompiler(): 1217 return True 1218 1219 return False 1220 1221 def getRunOptions(self): 1222 """Command line option for -A and -C to run this test again, called from 1223 self.dumpSessionInfo().""" 1224 arch = self.getArchitecture() 1225 comp = self.getCompiler() 1226 if arch: 1227 option_str = "-A " + arch 1228 else: 1229 option_str = "" 1230 if comp: 1231 option_str += " -C " + comp 1232 return option_str 1233 1234 # ================================================== 1235 # Build methods supported through a plugin interface 1236 # ================================================== 1237 1238 def buildDriver(self, sources, exe_name): 1239 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1240 or LLDB.framework). 1241 """ 1242 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1243 stdflag = "-std=c++0x" 1244 else: 1245 stdflag = "-std=c++11" 1246 1247 if sys.platform.startswith("darwin"): 1248 dsym = os.path.join(self.lib_dir, 'LLDB.framework', 'LLDB') 1249 d = {'CXX_SOURCES' : sources, 1250 'EXE' : exe_name, 1251 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag, 1252 'FRAMEWORK_INCLUDES' : "-F%s" % self.lib_dir, 1253 'LD_EXTRAS' : "%s -rpath %s" % (dsym, self.lib_dir), 1254 } 1255 elif sys.platform.startswith("linux") or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile': 1256 d = {'CXX_SOURCES' : sources, 1257 'EXE' : exe_name, 1258 'CFLAGS_EXTRAS' : "%s -I%s" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), 1259 'LD_EXTRAS' : "-L%s -llldb" % self.lib_dir} 1260 if self.TraceOn(): 1261 print "Building LLDB Driver (%s) from sources %s" % (exe_name, sources) 1262 1263 self.buildDefault(dictionary=d) 1264 1265 def buildProgram(self, sources, exe_name): 1266 """ Platform specific way to build an executable from C/C++ sources. """ 1267 d = {'CXX_SOURCES' : sources, 1268 'EXE' : exe_name} 1269 self.buildDefault(dictionary=d) 1270 1271 def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): 1272 """Platform specific way to build the default binaries.""" 1273 if lldb.skip_build_and_cleanup: 1274 return 1275 module = builder_module() 1276 if not module.buildDefault(self, architecture, compiler, dictionary, clean): 1277 raise Exception("Don't know how to build default binary") 1278 1279 def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True): 1280 """Platform specific way to build binaries with dsym info.""" 1281 if lldb.skip_build_and_cleanup: 1282 return 1283 module = builder_module() 1284 if not module.buildDsym(self, architecture, compiler, dictionary, clean): 1285 raise Exception("Don't know how to build binary with dsym") 1286 1287 def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): 1288 """Platform specific way to build binaries with dwarf maps.""" 1289 if lldb.skip_build_and_cleanup: 1290 return 1291 module = builder_module() 1292 if not module.buildDwarf(self, architecture, compiler, dictionary, clean): 1293 raise Exception("Don't know how to build binary with dwarf") 1294 1295 def getBuildFlags(self, use_cpp11=True, use_pthreads=True): 1296 """ Returns a dictionary (which can be provided to build* functions above) which 1297 contains OS-specific build flags. 1298 """ 1299 cflags = "" 1300 if use_cpp11: 1301 cflags += "-std=" 1302 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1303 cflags += "c++0x" 1304 else: 1305 cflags += "c++11" 1306 if sys.platform.startswith("darwin"): 1307 cflags += " -stdlib=libc++" 1308 elif "clang" in self.getCompiler(): 1309 cflags += " -stdlib=libstdc++" 1310 1311 if use_pthreads: 1312 ldflags = "-lpthread" 1313 1314 return {'CFLAGS_EXTRAS' : cflags, 1315 'LD_EXTRAS' : ldflags, 1316 } 1317 1318 def cleanup(self, dictionary=None): 1319 """Platform specific way to do cleanup after build.""" 1320 if lldb.skip_build_and_cleanup: 1321 return 1322 module = builder_module() 1323 if not module.cleanup(self, dictionary): 1324 raise Exception("Don't know how to do cleanup with dictionary: "+dictionary) 1325 1326 def getLLDBLibraryEnvVal(self): 1327 """ Returns the path that the OS-specific library search environment variable 1328 (self.dylibPath) should be set to in order for a program to find the LLDB 1329 library. If an environment variable named self.dylibPath is already set, 1330 the new path is appended to it and returned. 1331 """ 1332 existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None 1333 if existing_library_path: 1334 return "%s:%s" % (existing_library_path, self.lib_dir) 1335 elif sys.platform.startswith("darwin"): 1336 return os.path.join(self.lib_dir, 'LLDB.framework') 1337 else: 1338 return self.lib_dir 1339 1340class TestBase(Base): 1341 """ 1342 This abstract base class is meant to be subclassed. It provides default 1343 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 1344 among other things. 1345 1346 Important things for test class writers: 1347 1348 - Overwrite the mydir class attribute, otherwise your test class won't 1349 run. It specifies the relative directory to the top level 'test' so 1350 the test harness can change to the correct working directory before 1351 running your test. 1352 1353 - The setUp method sets up things to facilitate subsequent interactions 1354 with the debugger as part of the test. These include: 1355 - populate the test method name 1356 - create/get a debugger set with synchronous mode (self.dbg) 1357 - get the command interpreter from with the debugger (self.ci) 1358 - create a result object for use with the command interpreter 1359 (self.res) 1360 - plus other stuffs 1361 1362 - The tearDown method tries to perform some necessary cleanup on behalf 1363 of the test to return the debugger to a good state for the next test. 1364 These include: 1365 - execute any tearDown hooks registered by the test method with 1366 TestBase.addTearDownHook(); examples can be found in 1367 settings/TestSettings.py 1368 - kill the inferior process associated with each target, if any, 1369 and, then delete the target from the debugger's target list 1370 - perform build cleanup before running the next test method in the 1371 same test class; examples of registering for this service can be 1372 found in types/TestIntegerTypes.py with the call: 1373 - self.setTearDownCleanup(dictionary=d) 1374 1375 - Similarly setUpClass and tearDownClass perform classwise setup and 1376 teardown fixtures. The tearDownClass method invokes a default build 1377 cleanup for the entire test class; also, subclasses can implement the 1378 classmethod classCleanup(cls) to perform special class cleanup action. 1379 1380 - The instance methods runCmd and expect are used heavily by existing 1381 test cases to send a command to the command interpreter and to perform 1382 string/pattern matching on the output of such command execution. The 1383 expect method also provides a mode to peform string/pattern matching 1384 without running a command. 1385 1386 - The build methods buildDefault, buildDsym, and buildDwarf are used to 1387 build the binaries used during a particular test scenario. A plugin 1388 should be provided for the sys.platform running the test suite. The 1389 Mac OS X implementation is located in plugins/darwin.py. 1390 """ 1391 1392 # Maximum allowed attempts when launching the inferior process. 1393 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 1394 maxLaunchCount = 3; 1395 1396 # Time to wait before the next launching attempt in second(s). 1397 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 1398 timeWaitNextLaunch = 1.0; 1399 1400 def doDelay(self): 1401 """See option -w of dotest.py.""" 1402 if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and 1403 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'): 1404 waitTime = 1.0 1405 if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ: 1406 waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"]) 1407 time.sleep(waitTime) 1408 1409 # Returns the list of categories to which this test case belongs 1410 # by default, look for a ".categories" file, and read its contents 1411 # if no such file exists, traverse the hierarchy - we guarantee 1412 # a .categories to exist at the top level directory so we do not end up 1413 # looping endlessly - subclasses are free to define their own categories 1414 # in whatever way makes sense to them 1415 def getCategories(self): 1416 import inspect 1417 import os.path 1418 folder = inspect.getfile(self.__class__) 1419 folder = os.path.dirname(folder) 1420 while folder != '/': 1421 categories_file_name = os.path.join(folder,".categories") 1422 if os.path.exists(categories_file_name): 1423 categories_file = open(categories_file_name,'r') 1424 categories = categories_file.readline() 1425 categories_file.close() 1426 categories = str.replace(categories,'\n','') 1427 categories = str.replace(categories,'\r','') 1428 return categories.split(',') 1429 else: 1430 folder = os.path.dirname(folder) 1431 continue 1432 1433 def setUp(self): 1434 #import traceback 1435 #traceback.print_stack() 1436 1437 # Works with the test driver to conditionally skip tests via decorators. 1438 Base.setUp(self) 1439 1440 try: 1441 if lldb.blacklist: 1442 className = self.__class__.__name__ 1443 classAndMethodName = "%s.%s" % (className, self._testMethodName) 1444 if className in lldb.blacklist: 1445 self.skipTest(lldb.blacklist.get(className)) 1446 elif classAndMethodName in lldb.blacklist: 1447 self.skipTest(lldb.blacklist.get(classAndMethodName)) 1448 except AttributeError: 1449 pass 1450 1451 # Insert some delay between successive test cases if specified. 1452 self.doDelay() 1453 1454 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 1455 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 1456 1457 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 1458 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 1459 1460 # Create the debugger instance if necessary. 1461 try: 1462 self.dbg = lldb.DBG 1463 except AttributeError: 1464 self.dbg = lldb.SBDebugger.Create() 1465 1466 if not self.dbg: 1467 raise Exception('Invalid debugger instance') 1468 1469 # We want our debugger to be synchronous. 1470 self.dbg.SetAsync(False) 1471 1472 # Retrieve the associated command interpreter instance. 1473 self.ci = self.dbg.GetCommandInterpreter() 1474 if not self.ci: 1475 raise Exception('Could not get the command interpreter') 1476 1477 # And the result object. 1478 self.res = lldb.SBCommandReturnObject() 1479 1480 # Run global pre-flight code, if defined via the config file. 1481 if lldb.pre_flight: 1482 lldb.pre_flight(self) 1483 1484 # utility methods that tests can use to access the current objects 1485 def target(self): 1486 if not self.dbg: 1487 raise Exception('Invalid debugger instance') 1488 return self.dbg.GetSelectedTarget() 1489 1490 def process(self): 1491 if not self.dbg: 1492 raise Exception('Invalid debugger instance') 1493 return self.dbg.GetSelectedTarget().GetProcess() 1494 1495 def thread(self): 1496 if not self.dbg: 1497 raise Exception('Invalid debugger instance') 1498 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() 1499 1500 def frame(self): 1501 if not self.dbg: 1502 raise Exception('Invalid debugger instance') 1503 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() 1504 1505 def tearDown(self): 1506 #import traceback 1507 #traceback.print_stack() 1508 1509 Base.tearDown(self) 1510 1511 # Delete the target(s) from the debugger as a general cleanup step. 1512 # This includes terminating the process for each target, if any. 1513 # We'd like to reuse the debugger for our next test without incurring 1514 # the initialization overhead. 1515 targets = [] 1516 for target in self.dbg: 1517 if target: 1518 targets.append(target) 1519 process = target.GetProcess() 1520 if process: 1521 rc = self.invoke(process, "Kill") 1522 self.assertTrue(rc.Success(), PROCESS_KILLED) 1523 for target in targets: 1524 self.dbg.DeleteTarget(target) 1525 1526 # Run global post-flight code, if defined via the config file. 1527 if lldb.post_flight: 1528 lldb.post_flight(self) 1529 1530 del self.dbg 1531 1532 def switch_to_thread_with_stop_reason(self, stop_reason): 1533 """ 1534 Run the 'thread list' command, and select the thread with stop reason as 1535 'stop_reason'. If no such thread exists, no select action is done. 1536 """ 1537 from lldbutil import stop_reason_to_str 1538 self.runCmd('thread list') 1539 output = self.res.GetOutput() 1540 thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" % 1541 stop_reason_to_str(stop_reason)) 1542 for line in output.splitlines(): 1543 matched = thread_line_pattern.match(line) 1544 if matched: 1545 self.runCmd('thread select %s' % matched.group(1)) 1546 1547 def runCmd(self, cmd, msg=None, check=True, trace=False): 1548 """ 1549 Ask the command interpreter to handle the command and then check its 1550 return status. 1551 """ 1552 # Fail fast if 'cmd' is not meaningful. 1553 if not cmd or len(cmd) == 0: 1554 raise Exception("Bad 'cmd' parameter encountered") 1555 1556 trace = (True if traceAlways else trace) 1557 1558 running = (cmd.startswith("run") or cmd.startswith("process launch")) 1559 1560 for i in range(self.maxLaunchCount if running else 1): 1561 self.ci.HandleCommand(cmd, self.res) 1562 1563 with recording(self, trace) as sbuf: 1564 print >> sbuf, "runCmd:", cmd 1565 if not check: 1566 print >> sbuf, "check of return status not required" 1567 if self.res.Succeeded(): 1568 print >> sbuf, "output:", self.res.GetOutput() 1569 else: 1570 print >> sbuf, "runCmd failed!" 1571 print >> sbuf, self.res.GetError() 1572 1573 if self.res.Succeeded(): 1574 break 1575 elif running: 1576 # For process launch, wait some time before possible next try. 1577 time.sleep(self.timeWaitNextLaunch) 1578 with recording(self, trace) as sbuf: 1579 print >> sbuf, "Command '" + cmd + "' failed!" 1580 1581 if check: 1582 self.assertTrue(self.res.Succeeded(), 1583 msg if msg else CMD_MSG(cmd)) 1584 1585 def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True): 1586 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 1587 1588 Otherwise, all the arguments have the same meanings as for the expect function""" 1589 1590 trace = (True if traceAlways else trace) 1591 1592 if exe: 1593 # First run the command. If we are expecting error, set check=False. 1594 # Pass the assert message along since it provides more semantic info. 1595 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error) 1596 1597 # Then compare the output against expected strings. 1598 output = self.res.GetError() if error else self.res.GetOutput() 1599 1600 # If error is True, the API client expects the command to fail! 1601 if error: 1602 self.assertFalse(self.res.Succeeded(), 1603 "Command '" + str + "' is expected to fail!") 1604 else: 1605 # No execution required, just compare str against the golden input. 1606 output = str 1607 with recording(self, trace) as sbuf: 1608 print >> sbuf, "looking at:", output 1609 1610 # The heading says either "Expecting" or "Not expecting". 1611 heading = "Expecting" if matching else "Not expecting" 1612 1613 for pattern in patterns: 1614 # Match Objects always have a boolean value of True. 1615 match_object = re.search(pattern, output) 1616 matched = bool(match_object) 1617 with recording(self, trace) as sbuf: 1618 print >> sbuf, "%s pattern: %s" % (heading, pattern) 1619 print >> sbuf, "Matched" if matched else "Not matched" 1620 if matched: 1621 break 1622 1623 self.assertTrue(matched if matching else not matched, 1624 msg if msg else EXP_MSG(str, exe)) 1625 1626 return match_object 1627 1628 def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True): 1629 """ 1630 Similar to runCmd; with additional expect style output matching ability. 1631 1632 Ask the command interpreter to handle the command and then check its 1633 return status. The 'msg' parameter specifies an informational assert 1634 message. We expect the output from running the command to start with 1635 'startstr', matches the substrings contained in 'substrs', and regexp 1636 matches the patterns contained in 'patterns'. 1637 1638 If the keyword argument error is set to True, it signifies that the API 1639 client is expecting the command to fail. In this case, the error stream 1640 from running the command is retrieved and compared against the golden 1641 input, instead. 1642 1643 If the keyword argument matching is set to False, it signifies that the API 1644 client is expecting the output of the command not to match the golden 1645 input. 1646 1647 Finally, the required argument 'str' represents the lldb command to be 1648 sent to the command interpreter. In case the keyword argument 'exe' is 1649 set to False, the 'str' is treated as a string to be matched/not-matched 1650 against the golden input. 1651 """ 1652 trace = (True if traceAlways else trace) 1653 1654 if exe: 1655 # First run the command. If we are expecting error, set check=False. 1656 # Pass the assert message along since it provides more semantic info. 1657 self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error) 1658 1659 # Then compare the output against expected strings. 1660 output = self.res.GetError() if error else self.res.GetOutput() 1661 1662 # If error is True, the API client expects the command to fail! 1663 if error: 1664 self.assertFalse(self.res.Succeeded(), 1665 "Command '" + str + "' is expected to fail!") 1666 else: 1667 # No execution required, just compare str against the golden input. 1668 if isinstance(str,lldb.SBCommandReturnObject): 1669 output = str.GetOutput() 1670 else: 1671 output = str 1672 with recording(self, trace) as sbuf: 1673 print >> sbuf, "looking at:", output 1674 1675 # The heading says either "Expecting" or "Not expecting". 1676 heading = "Expecting" if matching else "Not expecting" 1677 1678 # Start from the startstr, if specified. 1679 # If there's no startstr, set the initial state appropriately. 1680 matched = output.startswith(startstr) if startstr else (True if matching else False) 1681 1682 if startstr: 1683 with recording(self, trace) as sbuf: 1684 print >> sbuf, "%s start string: %s" % (heading, startstr) 1685 print >> sbuf, "Matched" if matched else "Not matched" 1686 1687 # Look for endstr, if specified. 1688 keepgoing = matched if matching else not matched 1689 if endstr: 1690 matched = output.endswith(endstr) 1691 with recording(self, trace) as sbuf: 1692 print >> sbuf, "%s end string: %s" % (heading, endstr) 1693 print >> sbuf, "Matched" if matched else "Not matched" 1694 1695 # Look for sub strings, if specified. 1696 keepgoing = matched if matching else not matched 1697 if substrs and keepgoing: 1698 for str in substrs: 1699 matched = output.find(str) != -1 1700 with recording(self, trace) as sbuf: 1701 print >> sbuf, "%s sub string: %s" % (heading, str) 1702 print >> sbuf, "Matched" if matched else "Not matched" 1703 keepgoing = matched if matching else not matched 1704 if not keepgoing: 1705 break 1706 1707 # Search for regular expression patterns, if specified. 1708 keepgoing = matched if matching else not matched 1709 if patterns and keepgoing: 1710 for pattern in patterns: 1711 # Match Objects always have a boolean value of True. 1712 matched = bool(re.search(pattern, output)) 1713 with recording(self, trace) as sbuf: 1714 print >> sbuf, "%s pattern: %s" % (heading, pattern) 1715 print >> sbuf, "Matched" if matched else "Not matched" 1716 keepgoing = matched if matching else not matched 1717 if not keepgoing: 1718 break 1719 1720 self.assertTrue(matched if matching else not matched, 1721 msg if msg else EXP_MSG(str, exe)) 1722 1723 def invoke(self, obj, name, trace=False): 1724 """Use reflection to call a method dynamically with no argument.""" 1725 trace = (True if traceAlways else trace) 1726 1727 method = getattr(obj, name) 1728 import inspect 1729 self.assertTrue(inspect.ismethod(method), 1730 name + "is a method name of object: " + str(obj)) 1731 result = method() 1732 with recording(self, trace) as sbuf: 1733 print >> sbuf, str(method) + ":", result 1734 return result 1735 1736 # ================================================= 1737 # Misc. helper methods for debugging test execution 1738 # ================================================= 1739 1740 def DebugSBValue(self, val): 1741 """Debug print a SBValue object, if traceAlways is True.""" 1742 from lldbutil import value_type_to_str 1743 1744 if not traceAlways: 1745 return 1746 1747 err = sys.stderr 1748 err.write(val.GetName() + ":\n") 1749 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 1750 err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') 1751 err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') 1752 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 1753 err.write('\t' + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned())+ '\n') 1754 err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n') 1755 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 1756 err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n') 1757 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 1758 1759 def DebugSBType(self, type): 1760 """Debug print a SBType object, if traceAlways is True.""" 1761 if not traceAlways: 1762 return 1763 1764 err = sys.stderr 1765 err.write(type.GetName() + ":\n") 1766 err.write('\t' + "ByteSize -> " + str(type.GetByteSize()) + '\n') 1767 err.write('\t' + "IsPointerType -> " + str(type.IsPointerType()) + '\n') 1768 err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n') 1769 1770 def DebugPExpect(self, child): 1771 """Debug the spwaned pexpect object.""" 1772 if not traceAlways: 1773 return 1774 1775 print child 1776 1777 @classmethod 1778 def RemoveTempFile(cls, file): 1779 if os.path.exists(file): 1780 os.remove(file) 1781