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