2 LLDB module which provides the abstract base class of lldb test case.
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.
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.
11 ./dotest.py provides a test driver which sets up the environment to run the
12 entire of part of the test suite . Example:
14 # Exercises the test suite in the types directory....
15 /Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types
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
22 Configuration: arch=x86_64 compiler=clang
23 ----------------------------------------------------------------------
26 ........................................................................
27 ----------------------------------------------------------------------
28 Ran 72 tests in 135.468s
34 from __future__
import absolute_import
35 from __future__
import print_function
39 from distutils
.version
import LooseVersion
40 from functools
import wraps
48 from subprocess
import *
52 import distutils
.spawn
56 from six
import add_metaclass
57 from six
import StringIO
as SixStringIO
62 from . import configuration
63 from . import decorators
64 from . import lldbplatformutil
65 from . import lldbtest_config
66 from . import lldbutil
67 from . import test_categories
68 from lldbsuite
.support
import encoded_file
69 from lldbsuite
.support
import funcutils
71 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
72 # LLDB_COMMAND_TRACE is set from '-t' option.
74 # By default, traceAlways is False.
75 if "LLDB_COMMAND_TRACE" in os
.environ
and os
.environ
[
76 "LLDB_COMMAND_TRACE"] == "YES":
81 # By default, doCleanup is True.
82 if "LLDB_DO_CLEANUP" in os
.environ
and os
.environ
["LLDB_DO_CLEANUP"] == "NO":
89 # Some commonly used assert messages.
92 COMMAND_FAILED_AS_EXPECTED
= "Command has failed as expected"
94 CURRENT_EXECUTABLE_SET
= "Current executable set successfully"
96 PROCESS_IS_VALID
= "Process is valid"
98 PROCESS_KILLED
= "Process is killed successfully"
100 PROCESS_EXITED
= "Process exited successfully"
102 PROCESS_STOPPED
= "Process status should be stopped"
104 RUN_SUCCEEDED
= "Process is launched successfully"
106 RUN_COMPLETED
= "Process exited successfully"
108 BACKTRACE_DISPLAYED_CORRECTLY
= "Backtrace displayed correctly"
110 BREAKPOINT_CREATED
= "Breakpoint created successfully"
112 BREAKPOINT_STATE_CORRECT
= "Breakpoint state is correct"
114 BREAKPOINT_PENDING_CREATED
= "Pending breakpoint created successfully"
116 BREAKPOINT_HIT_ONCE
= "Breakpoint resolved with hit count = 1"
118 BREAKPOINT_HIT_TWICE
= "Breakpoint resolved with hit count = 2"
120 BREAKPOINT_HIT_THRICE
= "Breakpoint resolved with hit count = 3"
122 MISSING_EXPECTED_REGISTERS
= "At least one expected register is unavailable."
124 OBJECT_PRINTED_CORRECTLY
= "Object printed correctly"
126 SOURCE_DISPLAYED_CORRECTLY
= "Source code displayed correctly"
128 STEP_OUT_SUCCEEDED
= "Thread step-out succeeded"
130 STOPPED_DUE_TO_EXC_BAD_ACCESS
= "Process should be stopped due to bad access exception"
132 STOPPED_DUE_TO_ASSERT
= "Process should be stopped due to an assertion"
134 STOPPED_DUE_TO_BREAKPOINT
= "Process should be stopped due to breakpoint"
136 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS
= "%s, %s" % (
137 STOPPED_DUE_TO_BREAKPOINT
, "instead, the actual stop reason is: '%s'")
139 STOPPED_DUE_TO_BREAKPOINT_CONDITION
= "Stopped due to breakpoint condition"
141 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT
= "Stopped due to breakpoint and ignore count"
143 STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION
= "Stopped due to breakpoint jitted condition"
145 STOPPED_DUE_TO_SIGNAL
= "Process state is stopped due to signal"
147 STOPPED_DUE_TO_STEP_IN
= "Process state is stopped due to step in"
149 STOPPED_DUE_TO_WATCHPOINT
= "Process should be stopped due to watchpoint"
151 DATA_TYPES_DISPLAYED_CORRECTLY
= "Data type(s) displayed correctly"
153 VALID_BREAKPOINT
= "Got a valid breakpoint"
155 VALID_BREAKPOINT_LOCATION
= "Got a valid breakpoint location"
157 VALID_COMMAND_INTERPRETER
= "Got a valid command interpreter"
159 VALID_FILESPEC
= "Got a valid filespec"
161 VALID_MODULE
= "Got a valid module"
163 VALID_PROCESS
= "Got a valid process"
165 VALID_SYMBOL
= "Got a valid symbol"
167 VALID_TARGET
= "Got a valid target"
169 VALID_PLATFORM
= "Got a valid platform"
171 VALID_TYPE
= "Got a valid type"
173 VALID_VARIABLE
= "Got a valid variable"
175 VARIABLES_DISPLAYED_CORRECTLY
= "Variable(s) displayed correctly"
177 WATCHPOINT_CREATED
= "Watchpoint created successfully"
181 '''A generic "Command '%s' returns successfully" message generator.'''
182 return "Command '%s' returns successfully" % str
185 def COMPLETION_MSG(str_before
, str_after
, completions
):
186 '''A generic message generator for the completion mechanism.'''
187 return ("'%s' successfully completes to '%s', but completions were:\n%s"
188 % (str_before
, str_after
, "\n".join(completions
)))
191 def EXP_MSG(str, actual
, exe
):
192 '''A generic "'%s' returns expected result" message generator if exe.
193 Otherwise, it generates "'%s' matches expected result" message.'''
195 return "'%s' %s expected result, got '%s'" % (
196 str, 'returns' if exe
else 'matches', actual
.strip())
199 def SETTING_MSG(setting
):
200 '''A generic "Value of setting '%s' is correct" message generator.'''
201 return "Value of setting '%s' is correct" % setting
204 def line_number(filename
, string_to_match
):
205 """Helper function to return the line number of the first matched string."""
206 with io
.open(filename
, mode
='r', encoding
="utf-8") as f
:
207 for i
, line
in enumerate(f
):
208 if line
.find(string_to_match
) != -1:
212 "Unable to find '%s' within file %s" %
213 (string_to_match
, filename
))
215 def get_line(filename
, line_number
):
216 """Return the text of the line at the 1-based line number."""
217 with io
.open(filename
, mode
='r', encoding
="utf-8") as f
:
218 return f
.readlines()[line_number
- 1]
221 """Return the pointer size of the host system."""
223 a_pointer
= ctypes
.c_void_p(0xffff)
224 return 8 * ctypes
.sizeof(a_pointer
)
228 """Returns true if fpath is an executable."""
229 return os
.path
.isfile(fpath
) and os
.access(fpath
, os
.X_OK
)
233 """Returns the full path to a program; None otherwise."""
234 fpath
, fname
= os
.path
.split(program
)
239 for path
in os
.environ
["PATH"].split(os
.pathsep
):
240 exe_file
= os
.path
.join(path
, program
)
246 class recording(SixStringIO
):
248 A nice little context manager for recording the debugger interactions into
249 our session object. If trace flag is ON, it also emits the interactions
253 def __init__(self
, test
, trace
):
254 """Create a SixStringIO instance; record the session obj and trace flag."""
255 SixStringIO
.__init
__(self
)
256 # The test might not have undergone the 'setUp(self)' phase yet, so that
257 # the attribute 'session' might not even exist yet.
258 self
.session
= getattr(test
, "session", None) if test
else None
263 Context management protocol on entry to the body of the with statement.
264 Just return the SixStringIO object.
268 def __exit__(self
, type, value
, tb
):
270 Context management protocol on exit from the body of the with statement.
271 If trace is ON, it emits the recordings into stderr. Always add the
272 recordings to our session object. And close the SixStringIO object, too.
275 print(self
.getvalue(), file=sys
.stderr
)
277 print(self
.getvalue(), file=self
.session
)
281 @add_metaclass(abc
.ABCMeta
)
282 class _BaseProcess(object):
284 @abc.abstractproperty
286 """Returns process PID if has been launched already."""
289 def launch(self
, executable
, args
):
290 """Launches new process with given executable and args."""
294 """Terminates previously launched process.."""
297 class _LocalProcess(_BaseProcess
):
299 def __init__(self
, trace_on
):
301 self
._trace
_on
= trace_on
302 self
._delayafterterminate
= 0.1
306 return self
._proc
.pid
308 def launch(self
, executable
, args
):
312 os
.devnull
) if not self
._trace
_on
else None,
316 if self
._proc
.poll() is None:
317 # Terminate _proc like it does the pexpect
322 'SIGINT'] if sig
in dir(signal
)]
323 for sig
in signals_to_try
:
325 self
._proc
.send_signal(getattr(signal
, sig
))
326 time
.sleep(self
._delayafterterminate
)
327 if self
._proc
.poll() is not None:
330 pass # Windows says SIGINT is not a valid signal to send
331 self
._proc
.terminate()
332 time
.sleep(self
._delayafterterminate
)
333 if self
._proc
.poll() is not None:
336 time
.sleep(self
._delayafterterminate
)
339 return self
._proc
.poll()
342 class _RemoteProcess(_BaseProcess
):
344 def __init__(self
, install_remote
):
346 self
._install
_remote
= install_remote
352 def launch(self
, executable
, args
):
353 if self
._install
_remote
:
354 src_path
= executable
355 dst_path
= lldbutil
.join_remote_paths(
356 lldb
.remote_platform
.GetWorkingDirectory(), os
.path
.basename(executable
))
358 dst_file_spec
= lldb
.SBFileSpec(dst_path
, False)
359 err
= lldb
.remote_platform
.Install(
360 lldb
.SBFileSpec(src_path
, True), dst_file_spec
)
363 "remote_platform.Install('%s', '%s') failed: %s" %
364 (src_path
, dst_path
, err
))
366 dst_path
= executable
367 dst_file_spec
= lldb
.SBFileSpec(executable
, False)
369 launch_info
= lldb
.SBLaunchInfo(args
)
370 launch_info
.SetExecutableFile(dst_file_spec
, True)
371 launch_info
.SetWorkingDirectory(
372 lldb
.remote_platform
.GetWorkingDirectory())
374 # Redirect stdout and stderr to /dev/null
375 launch_info
.AddSuppressFileAction(1, False, True)
376 launch_info
.AddSuppressFileAction(2, False, True)
378 err
= lldb
.remote_platform
.Launch(launch_info
)
381 "remote_platform.Launch('%s', '%s') failed: %s" %
382 (dst_path
, args
, err
))
383 self
._pid
= launch_info
.GetProcessID()
386 lldb
.remote_platform
.Kill(self
._pid
)
388 # From 2.7's subprocess.check_output() convenience function.
389 # Return a tuple (stdoutdata, stderrdata).
392 def system(commands
, **kwargs
):
393 r
"""Run an os command with arguments and return its output as a byte string.
395 If the exit code was non-zero it raises a CalledProcessError. The
396 CalledProcessError object will have the return code in the returncode
397 attribute and output in the output attribute.
399 The arguments are the same as for the Popen constructor. Example:
401 >>> check_output(["ls", "-l", "/dev/null"])
402 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
404 The stdout argument is not allowed as it is used internally.
405 To capture standard error in the result, use stderr=STDOUT.
407 >>> check_output(["/bin/sh", "-c",
408 ... "ls -l non_existent_file ; exit 0"],
410 'ls: non_existent_file: No such file or directory\n'
413 # Assign the sender object to variable 'test' and remove it from kwargs.
414 test
= kwargs
.pop('sender', None)
416 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo']
417 commandList
= [' '.join(x
) for x
in commands
]
420 for shellCommand
in commandList
:
421 if 'stdout' in kwargs
:
423 'stdout argument not allowed, it will be overridden.')
424 if 'shell' in kwargs
and kwargs
['shell'] == False:
425 raise ValueError('shell=False not allowed')
433 this_output
, this_error
= process
.communicate()
434 retcode
= process
.poll()
437 cmd
= kwargs
.get("args")
440 cpe
= CalledProcessError(retcode
, cmd
)
441 # Ensure caller can access the stdout/stderr.
442 cpe
.lldb_extensions
= {
443 "stdout_content": this_output
,
444 "stderr_content": this_error
,
445 "command": shellCommand
448 output
= output
+ this_output
.decode("utf-8")
449 error
= error
+ this_error
.decode("utf-8")
450 return (output
, error
)
453 def getsource_if_available(obj
):
455 Return the text of the source code for an object if available. Otherwise,
456 a print representation is returned.
460 return inspect
.getsource(obj
)
465 def builder_module():
466 if sys
.platform
.startswith("freebsd"):
467 return __import__("builder_freebsd")
468 if sys
.platform
.startswith("openbsd"):
469 return __import__("builder_openbsd")
470 if sys
.platform
.startswith("netbsd"):
471 return __import__("builder_netbsd")
472 if sys
.platform
.startswith("linux"):
473 # sys.platform with Python-3.x returns 'linux', but with
474 # Python-2.x it returns 'linux2'.
475 return __import__("builder_linux")
476 return __import__("builder_" + sys
.platform
)
479 class Base(unittest2
.TestCase
):
481 Abstract base for performing lldb (see TestBase) or other generic tests (see
482 BenchBase for one example). lldbtest.Base works with the test driver to
487 # The concrete subclass should override this attribute.
490 # Keep track of the old current working directory.
494 def compute_mydir(test_file
):
495 '''Subclasses should call this function to correctly calculate the
496 required "mydir" attribute as follows:
498 mydir = TestBase.compute_mydir(__file__)
500 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir
501 rel_prefix
= test_file
[len(os
.environ
["LLDB_TEST"]) + 1:]
502 return os
.path
.dirname(rel_prefix
)
505 """Returns True if we are in trace mode (tracing detailed test execution)."""
511 Python unittest framework class setup fixture.
512 Do current directory manipulation.
514 # Fail fast if 'mydir' attribute is not overridden.
515 if not cls
.mydir
or len(cls
.mydir
) == 0:
516 raise Exception("Subclasses must override the 'mydir' attribute.")
518 # Save old working directory.
519 cls
.oldcwd
= os
.getcwd()
521 # Change current working directory if ${LLDB_TEST} is defined.
522 # See also dotest.py which sets up ${LLDB_TEST}.
523 if ("LLDB_TEST" in os
.environ
):
524 full_dir
= os
.path
.join(os
.environ
["LLDB_TEST"],
527 print("Change dir to:", full_dir
, file=sys
.stderr
)
530 # Set platform context.
531 cls
.platformContext
= lldbplatformutil
.createPlatformContext()
534 def tearDownClass(cls
):
536 Python unittest framework class teardown fixture.
537 Do class-wide cleanup.
541 # First, let's do the platform-specific cleanup.
542 module
= builder_module()
545 # Subclass might have specific cleanup function defined.
546 if getattr(cls
, "classCleanup", None):
549 "Call class-specific cleanup function for class:",
555 exc_type
, exc_value
, exc_tb
= sys
.exc_info()
556 traceback
.print_exception(exc_type
, exc_value
, exc_tb
)
558 # Restore old working directory.
560 print("Restore dir to:", cls
.oldcwd
, file=sys
.stderr
)
563 def enableLogChannelsForCurrentTest(self
):
564 if len(lldbtest_config
.channels
) == 0:
567 # if debug channels are specified in lldbtest_config.channels,
568 # create a new set of log files for every test
569 log_basename
= self
.getLogBasenameForCurrentTest()
571 # confirm that the file is writeable
572 host_log_path
= "{}-host.log".format(log_basename
)
573 open(host_log_path
, 'w').close()
575 log_enable
= "log enable -Tpn -f {} ".format(host_log_path
)
576 for channel_with_categories
in lldbtest_config
.channels
:
577 channel_then_categories
= channel_with_categories
.split(' ', 1)
578 channel
= channel_then_categories
[0]
579 if len(channel_then_categories
) > 1:
580 categories
= channel_then_categories
[1]
582 categories
= "default"
584 if channel
== "gdb-remote" and lldb
.remote_platform
is None:
585 # communicate gdb-remote categories to debugserver
586 os
.environ
["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
588 self
.ci
.HandleCommand(
589 log_enable
+ channel_with_categories
, self
.res
)
590 if not self
.res
.Succeeded():
592 'log enable failed (check LLDB_LOG_OPTION env variable)')
594 # Communicate log path name to debugserver & lldb-server
595 # For remote debugging, these variables need to be set when starting the platform
597 if lldb
.remote_platform
is None:
598 server_log_path
= "{}-server.log".format(log_basename
)
599 open(server_log_path
, 'w').close()
600 os
.environ
["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
602 # Communicate channels to lldb-server
603 os
.environ
["LLDB_SERVER_LOG_CHANNELS"] = ":".join(
604 lldbtest_config
.channels
)
606 self
.addTearDownHook(self
.disableLogChannelsForCurrentTest
)
608 def disableLogChannelsForCurrentTest(self
):
609 # close all log files that we opened
610 for channel_and_categories
in lldbtest_config
.channels
:
611 # channel format - <channel-name> [<category0> [<category1> ...]]
612 channel
= channel_and_categories
.split(' ', 1)[0]
613 self
.ci
.HandleCommand("log disable " + channel
, self
.res
)
614 if not self
.res
.Succeeded():
616 'log disable failed (check LLDB_LOG_OPTION env variable)')
618 # Retrieve the server log (if any) from the remote system. It is assumed the server log
619 # is writing to the "server.log" file in the current test directory. This can be
620 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote
621 # platform. If the remote logging is not enabled, then just let the Get() command silently
623 if lldb
.remote_platform
:
624 lldb
.remote_platform
.Get(
625 lldb
.SBFileSpec("server.log"), lldb
.SBFileSpec(
626 self
.getLogBasenameForCurrentTest() + "-server.log"))
628 def setPlatformWorkingDir(self
):
629 if not lldb
.remote_platform
or not configuration
.lldb_platform_working_dir
:
632 components
= self
.mydir
.split(os
.path
.sep
) + [str(self
.test_number
), self
.getBuildDirBasename()]
633 remote_test_dir
= configuration
.lldb_platform_working_dir
635 remote_test_dir
= lldbutil
.join_remote_paths(remote_test_dir
, c
)
636 error
= lldb
.remote_platform
.MakeDirectory(
637 remote_test_dir
, 448) # 448 = 0o700
639 raise Exception("making remote directory '%s': %s" % (
640 remote_test_dir
, error
))
642 lldb
.remote_platform
.SetWorkingDirectory(remote_test_dir
)
644 # This function removes all files from the current working directory while leaving
645 # the directories in place. The cleaup is required to reduce the disk space required
646 # by the test suite while leaving the directories untouched is neccessary because
647 # sub-directories might belong to an other test
648 def clean_working_directory():
649 # TODO: Make it working on Windows when we need it for remote debugging support
650 # TODO: Replace the heuristic to remove the files with a logic what collects the
651 # list of files we have to remove during test runs.
652 shell_cmd
= lldb
.SBPlatformShellCommand(
653 "rm %s/*" % remote_test_dir
)
654 lldb
.remote_platform
.Run(shell_cmd
)
655 self
.addTearDownHook(clean_working_directory
)
657 def getSourceDir(self
):
658 """Return the full path to the current test."""
659 return os
.path
.join(os
.environ
["LLDB_TEST"], self
.mydir
)
661 def getBuildDirBasename(self
):
662 return self
.__class
__.__module
__ + "." + self
.testMethodName
664 def getBuildDir(self
):
665 """Return the full path to the current test."""
666 return os
.path
.join(os
.environ
["LLDB_BUILD"], self
.mydir
,
667 self
.getBuildDirBasename())
670 def makeBuildDir(self
):
671 """Create the test-specific working directory, deleting any previous
673 # See also dotest.py which sets up ${LLDB_BUILD}.
674 bdir
= self
.getBuildDir()
675 if os
.path
.isdir(bdir
):
677 lldbutil
.mkdir_p(bdir
)
679 def getBuildArtifact(self
, name
="a.out"):
680 """Return absolute path to an artifact in the test's build directory."""
681 return os
.path
.join(self
.getBuildDir(), name
)
683 def getSourcePath(self
, name
):
684 """Return absolute path to a file in the test's source directory."""
685 return os
.path
.join(self
.getSourceDir(), name
)
688 def setUpCommands(cls
):
690 # Disable Spotlight lookup. The testsuite creates
691 # different binaries with the same UUID, because they only
692 # differ in the debug info, which is not being hashed.
693 "settings set symbols.enable-external-lookup false",
695 # Testsuite runs in parallel and the host can have also other load.
696 "settings set plugin.process.gdb-remote.packet-timeout 60",
698 'settings set symbols.clang-modules-cache-path "{}"'.format(
699 configuration
.lldb_module_cache_dir
),
700 "settings set use-color false",
702 # Make sure that a sanitizer LLDB's environment doesn't get passed on.
703 if cls
.platformContext
and cls
.platformContext
.shlib_environment_var
in os
.environ
:
704 commands
.append('settings set target.env-vars {}='.format(
705 cls
.platformContext
.shlib_environment_var
))
707 # Set environment variables for the inferior.
708 if lldbtest_config
.inferior_env
:
709 commands
.append('settings set target.env-vars {}'.format(
710 lldbtest_config
.inferior_env
))
714 """Fixture for unittest test case setup.
716 It works with the test driver to conditionally skip tests and does other
719 # traceback.print_stack()
721 if "LIBCXX_PATH" in os
.environ
:
722 self
.libcxxPath
= os
.environ
["LIBCXX_PATH"]
724 self
.libcxxPath
= None
726 if "LLDBVSCODE_EXEC" in os
.environ
:
727 self
.lldbVSCodeExec
= os
.environ
["LLDBVSCODE_EXEC"]
729 self
.lldbVSCodeExec
= None
731 self
.lldbOption
= " ".join(
732 "-o '" + s
+ "'" for s
in self
.setUpCommands())
734 # If we spawn an lldb process for test (via pexpect), do not load the
735 # init file unless told otherwise.
736 if os
.environ
.get("NO_LLDBINIT") != "NO":
737 self
.lldbOption
+= " --no-lldbinit"
739 # Assign the test method name to self.testMethodName.
741 # For an example of the use of this attribute, look at test/types dir.
742 # There are a bunch of test cases under test/types and we don't want the
743 # module cacheing subsystem to be confused with executable name "a.out"
744 # used for all the test cases.
745 self
.testMethodName
= self
._testMethodName
747 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
748 # with it using pexpect.
750 self
.child_prompt
= "(lldb) "
751 # If the child is interacting with the embedded script interpreter,
752 # there are two exits required during tear down, first to quit the
753 # embedded script interpreter and second to quit the lldb command
755 self
.child_in_script_interpreter
= False
757 # These are for customized teardown cleanup.
759 self
.doTearDownCleanup
= False
760 # And in rare cases where there are multiple teardown cleanups.
762 self
.doTearDownCleanups
= False
764 # List of spawned subproces.Popen objects
765 self
.subprocesses
= []
767 # List of forked process PIDs
768 self
.forkedProcessPids
= []
770 # Create a string buffer to record the session info, to be dumped into a
771 # test case specific file if test failure is encountered.
772 self
.log_basename
= self
.getLogBasenameForCurrentTest()
774 session_file
= "{}.log".format(self
.log_basename
)
775 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered.
776 self
.session
= encoded_file
.open(session_file
, "utf-8", mode
="w")
778 # Optimistically set __errored__, __failed__, __expected__ to False
779 # initially. If the test errored/failed, the session info
780 # (self.session) is then dumped into a session specific file for
782 self
.__cleanup
_errored
__ = False
783 self
.__errored
__ = False
784 self
.__failed
__ = False
785 self
.__expected
__ = False
786 # We are also interested in unexpected success.
787 self
.__unexpected
__ = False
789 self
.__skipped
__ = False
791 # See addTearDownHook(self, hook) which allows the client to add a hook
792 # function to be run during tearDown() time.
795 # See HideStdout(self).
796 self
.sys_stdout_hidden
= False
798 if self
.platformContext
:
799 # set environment variable names for finding shared libraries
800 self
.dylibPath
= self
.platformContext
.shlib_environment_var
802 # Create the debugger instance if necessary.
805 except AttributeError:
806 self
.dbg
= lldb
.SBDebugger
.Create()
809 raise Exception('Invalid debugger instance')
811 # Retrieve the associated command interpreter instance.
812 self
.ci
= self
.dbg
.GetCommandInterpreter()
814 raise Exception('Could not get the command interpreter')
816 # And the result object.
817 self
.res
= lldb
.SBCommandReturnObject()
819 self
.setPlatformWorkingDir()
820 self
.enableLogChannelsForCurrentTest()
822 lib_dir
= os
.environ
["LLDB_LIB_DIR"]
824 self
.framework_dir
= None
825 self
.darwinWithFramework
= self
.platformIsDarwin()
826 if sys
.platform
.startswith("darwin"):
827 # Handle the framework environment variable if it is set
828 if hasattr(lldbtest_config
, 'lldb_framework_path'):
829 framework_path
= lldbtest_config
.lldb_framework_path
830 # Framework dir should be the directory containing the framework
831 self
.framework_dir
= framework_path
[:framework_path
.rfind('LLDB.framework')]
832 # If a framework dir was not specified assume the Xcode build
833 # directory layout where the framework is in LLDB_LIB_DIR.
835 self
.framework_dir
= lib_dir
836 self
.dsym
= os
.path
.join(self
.framework_dir
, 'LLDB.framework', 'LLDB')
837 # If the framework binary doesn't exist, assume we didn't actually
838 # build a framework, and fallback to standard *nix behavior by
839 # setting framework_dir and dsym to None.
840 if not os
.path
.exists(self
.dsym
):
841 self
.framework_dir
= None
843 self
.darwinWithFramework
= False
846 def setAsync(self
, value
):
847 """ Sets async mode to True/False and ensures it is reset after the testcase completes."""
848 old_async
= self
.dbg
.GetAsync()
849 self
.dbg
.SetAsync(value
)
850 self
.addTearDownHook(lambda: self
.dbg
.SetAsync(old_async
))
852 def cleanupSubprocesses(self
):
853 # Ensure any subprocesses are cleaned up
854 for p
in self
.subprocesses
:
857 del self
.subprocesses
[:]
858 # Ensure any forked processes are cleaned up
859 for pid
in self
.forkedProcessPids
:
860 if os
.path
.exists("/proc/" + str(pid
)):
861 os
.kill(pid
, signal
.SIGTERM
)
863 def spawnSubprocess(self
, executable
, args
=[], install_remote
=True):
864 """ Creates a subprocess.Popen object with the specified executable and arguments,
865 saves it in self.subprocesses, and returns the object.
866 NOTE: if using this function, ensure you also call:
868 self.addTearDownHook(self.cleanupSubprocesses)
870 otherwise the test suite will leak processes.
872 proc
= _RemoteProcess(
873 install_remote
) if lldb
.remote_platform
else _LocalProcess(self
.TraceOn())
874 proc
.launch(executable
, args
)
875 self
.subprocesses
.append(proc
)
878 def forkSubprocess(self
, executable
, args
=[]):
879 """ Fork a subprocess with its own group ID.
880 NOTE: if using this function, ensure you also call:
882 self.addTearDownHook(self.cleanupSubprocesses)
884 otherwise the test suite will leak processes.
886 child_pid
= os
.fork()
888 # If more I/O support is required, this can be beefed up.
889 fd
= os
.open(os
.devnull
, os
.O_RDWR
)
892 # This call causes the child to have its of group ID
894 os
.execvp(executable
, [executable
] + args
)
895 # Give the child time to get through the execvp() call
897 self
.forkedProcessPids
.append(child_pid
)
900 def HideStdout(self
):
901 """Hide output to stdout from the user.
903 During test execution, there might be cases where we don't want to show the
904 standard output to the user. For example,
906 self.runCmd(r'''sc print("\n\n\tHello!\n")''')
908 tests whether command abbreviation for 'script' works or not. There is no
909 need to show the 'Hello' output to the user as long as the 'script' command
910 succeeds and we are not in TraceOn() mode (see the '-t' option).
912 In this case, the test method calls self.HideStdout(self) to redirect the
913 sys.stdout to a null device, and restores the sys.stdout upon teardown.
915 Note that you should only call this method at most once during a test case
916 execution. Any subsequent call has no effect at all."""
917 if self
.sys_stdout_hidden
:
920 self
.sys_stdout_hidden
= True
921 old_stdout
= sys
.stdout
922 sys
.stdout
= open(os
.devnull
, 'w')
924 def restore_stdout():
925 sys
.stdout
= old_stdout
926 self
.addTearDownHook(restore_stdout
)
928 # =======================================================================
929 # Methods for customized teardown cleanups as well as execution of hooks.
930 # =======================================================================
932 def setTearDownCleanup(self
, dictionary
=None):
933 """Register a cleanup action at tearDown() time with a dictinary"""
934 self
.dict = dictionary
935 self
.doTearDownCleanup
= True
937 def addTearDownCleanup(self
, dictionary
):
938 """Add a cleanup action at tearDown() time with a dictinary"""
939 self
.dicts
.append(dictionary
)
940 self
.doTearDownCleanups
= True
942 def addTearDownHook(self
, hook
):
944 Add a function to be run during tearDown() time.
946 Hooks are executed in a first come first serve manner.
948 if six
.callable(hook
):
949 with
recording(self
, traceAlways
) as sbuf
:
951 "Adding tearDown hook:",
952 getsource_if_available(hook
),
954 self
.hooks
.append(hook
)
958 def deletePexpectChild(self
):
959 # This is for the case of directly spawning 'lldb' and interacting with it
961 if self
.child
and self
.child
.isalive():
963 with
recording(self
, traceAlways
) as sbuf
:
964 print("tearing down the child process....", file=sbuf
)
966 if self
.child_in_script_interpreter
:
967 self
.child
.sendline('quit()')
968 self
.child
.expect_exact(self
.child_prompt
)
970 'settings set interpreter.prompt-on-quit false')
971 self
.child
.sendline('quit')
972 self
.child
.expect(pexpect
.EOF
)
973 except (ValueError, pexpect
.ExceptionPexpect
):
974 # child is already terminated
976 except OSError as exception
:
978 if exception
.errno
!= errno
.EIO
:
981 # child is already terminated
983 # Give it one final blow to make sure the child is terminated.
987 """Fixture for unittest test case teardown."""
989 # traceback.print_stack()
991 self
.deletePexpectChild()
993 # Check and run any hook functions.
994 for hook
in reversed(self
.hooks
):
995 with
recording(self
, traceAlways
) as sbuf
:
997 "Executing tearDown hook:",
998 getsource_if_available(hook
),
1000 if funcutils
.requires_self(hook
):
1003 hook() # try the plain call and hope it works
1007 # Perform registered teardown cleanup.
1008 if doCleanup
and self
.doTearDownCleanup
:
1009 self
.cleanup(dictionary
=self
.dict)
1011 # In rare cases where there are multiple teardown cleanups added.
1012 if doCleanup
and self
.doTearDownCleanups
:
1014 for dict in reversed(self
.dicts
):
1015 self
.cleanup(dictionary
=dict)
1017 # =========================================================
1018 # Various callbacks to allow introspection of test progress
1019 # =========================================================
1021 def markError(self
):
1022 """Callback invoked when an error (unexpected exception) errored."""
1023 self
.__errored
__ = True
1024 with
recording(self
, False) as sbuf
:
1025 # False because there's no need to write "ERROR" to the stderr twice.
1026 # Once by the Python unittest framework, and a second time by us.
1027 print("ERROR", file=sbuf
)
1029 def markCleanupError(self
):
1030 """Callback invoked when an error occurs while a test is cleaning up."""
1031 self
.__cleanup
_errored
__ = True
1032 with
recording(self
, False) as sbuf
:
1033 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice.
1034 # Once by the Python unittest framework, and a second time by us.
1035 print("CLEANUP_ERROR", file=sbuf
)
1037 def markFailure(self
):
1038 """Callback invoked when a failure (test assertion failure) occurred."""
1039 self
.__failed
__ = True
1040 with
recording(self
, False) as sbuf
:
1041 # False because there's no need to write "FAIL" to the stderr twice.
1042 # Once by the Python unittest framework, and a second time by us.
1043 print("FAIL", file=sbuf
)
1045 def markExpectedFailure(self
, err
, bugnumber
):
1046 """Callback invoked when an expected failure/error occurred."""
1047 self
.__expected
__ = True
1048 with
recording(self
, False) as sbuf
:
1049 # False because there's no need to write "expected failure" to the
1051 # Once by the Python unittest framework, and a second time by us.
1052 if bugnumber
is None:
1053 print("expected failure", file=sbuf
)
1056 "expected failure (problem id:" + str(bugnumber
) + ")",
1059 def markSkippedTest(self
):
1060 """Callback invoked when a test is skipped."""
1061 self
.__skipped
__ = True
1062 with
recording(self
, False) as sbuf
:
1063 # False because there's no need to write "skipped test" to the
1065 # Once by the Python unittest framework, and a second time by us.
1066 print("skipped test", file=sbuf
)
1068 def markUnexpectedSuccess(self
, bugnumber
):
1069 """Callback invoked when an unexpected success occurred."""
1070 self
.__unexpected
__ = True
1071 with
recording(self
, False) as sbuf
:
1072 # False because there's no need to write "unexpected success" to the
1074 # Once by the Python unittest framework, and a second time by us.
1075 if bugnumber
is None:
1076 print("unexpected success", file=sbuf
)
1079 "unexpected success (problem id:" + str(bugnumber
) + ")",
1082 def getRerunArgs(self
):
1083 return " -f %s.%s" % (self
.__class
__.__name
__, self
._testMethodName
)
1085 def getLogBasenameForCurrentTest(self
, prefix
=None):
1087 returns a partial path that can be used as the beginning of the name of multiple
1088 log files pertaining to this test
1090 <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method>
1092 dname
= os
.path
.join(os
.environ
["LLDB_TEST"],
1093 os
.environ
["LLDB_SESSION_DIRNAME"])
1094 if not os
.path
.isdir(dname
):
1098 if prefix
is not None:
1099 components
.append(prefix
)
1100 for c
in configuration
.session_file_format
:
1102 components
.append(self
.__class
__.__module
__)
1104 components
.append(self
.__class
__.__name
__)
1106 compiler
= self
.getCompiler()
1108 if compiler
[1] == ':':
1109 compiler
= compiler
[2:]
1110 if os
.path
.altsep
is not None:
1111 compiler
= compiler
.replace(os
.path
.altsep
, os
.path
.sep
)
1112 path_components
= [x
for x
in compiler
.split(os
.path
.sep
) if x
!= ""]
1114 # Add at most 4 path components to avoid generating very long
1116 components
.extend(path_components
[-4:])
1118 components
.append(self
.getArchitecture())
1120 components
.append(self
.testMethodName
)
1121 fname
= "-".join(components
)
1123 return os
.path
.join(dname
, fname
)
1125 def dumpSessionInfo(self
):
1127 Dump the debugger interactions leading to a test error/failure. This
1128 allows for more convenient postmortem analysis.
1130 See also LLDBTestResult (dotest.py) which is a singlton class derived
1131 from TextTestResult and overwrites addError, addFailure, and
1132 addExpectedFailure methods to allow us to to mark the test instance as
1136 # We are here because self.tearDown() detected that this test instance
1137 # either errored or failed. The lldb.test_result singleton contains
1138 # two lists (erros and failures) which get populated by the unittest
1139 # framework. Look over there for stack trace information.
1141 # The lists contain 2-tuples of TestCase instances and strings holding
1142 # formatted tracebacks.
1144 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1146 # output tracebacks into session
1148 if self
.__errored
__:
1149 pairs
= configuration
.test_result
.errors
1151 elif self
.__cleanup
_errored
__:
1152 pairs
= configuration
.test_result
.cleanup_errors
1153 prefix
= 'CleanupError'
1154 elif self
.__failed
__:
1155 pairs
= configuration
.test_result
.failures
1157 elif self
.__expected
__:
1158 pairs
= configuration
.test_result
.expectedFailures
1159 prefix
= 'ExpectedFailure'
1160 elif self
.__skipped
__:
1161 prefix
= 'SkippedTest'
1162 elif self
.__unexpected
__:
1163 prefix
= 'UnexpectedSuccess'
1167 if not self
.__unexpected
__ and not self
.__skipped
__:
1168 for test
, traceback
in pairs
:
1170 print(traceback
, file=self
.session
)
1174 "Session info generated @",
1175 datetime
.datetime
.now().ctime(),
1177 self
.session
.close()
1180 # process the log files
1181 log_files_for_this_test
= glob
.glob(self
.log_basename
+ "*")
1183 if prefix
!= 'Success' or lldbtest_config
.log_success
:
1184 # keep all log files, rename them to include prefix
1185 dst_log_basename
= self
.getLogBasenameForCurrentTest(prefix
)
1186 for src
in log_files_for_this_test
:
1187 if os
.path
.isfile(src
):
1188 dst
= src
.replace(self
.log_basename
, dst_log_basename
)
1189 if os
.name
== "nt" and os
.path
.isfile(dst
):
1190 # On Windows, renaming a -> b will throw an exception if
1191 # b exists. On non-Windows platforms it silently
1192 # replaces the destination. Ultimately this means that
1193 # atomic renames are not guaranteed to be possible on
1194 # Windows, but we need this to work anyway, so just
1195 # remove the destination first if it already exists.
1198 lldbutil
.mkdir_p(os
.path
.dirname(dst
))
1201 # success! (and we don't want log files) delete log files
1202 for log_file
in log_files_for_this_test
:
1203 remove_file(log_file
)
1205 # ====================================================
1206 # Config. methods supported through a plugin interface
1207 # (enables reading of the current test configuration)
1208 # ====================================================
1211 """Returns true if the architecture is MIPS."""
1212 arch
= self
.getArchitecture()
1213 if re
.match("mips", arch
):
1217 def isPPC64le(self
):
1218 """Returns true if the architecture is PPC64LE."""
1219 arch
= self
.getArchitecture()
1220 if re
.match("powerpc64le", arch
):
1224 def getArchitecture(self
):
1225 """Returns the architecture in effect the test suite is running with."""
1226 module
= builder_module()
1227 arch
= module
.getArchitecture()
1232 def getLldbArchitecture(self
):
1233 """Returns the architecture of the lldb binary."""
1234 if not hasattr(self
, 'lldbArchitecture'):
1236 # spawn local process
1238 lldbtest_config
.lldbExec
,
1240 "file " + lldbtest_config
.lldbExec
,
1245 output
= check_output(command
)
1246 str = output
.decode("utf-8")
1248 for line
in str.splitlines():
1250 "Current executable set to '.*' \\((.*)\\)\\.", line
)
1252 self
.lldbArchitecture
= m
.group(1)
1255 return self
.lldbArchitecture
1257 def getCompiler(self
):
1258 """Returns the compiler in effect the test suite is running with."""
1259 module
= builder_module()
1260 return module
.getCompiler()
1262 def getCompilerBinary(self
):
1263 """Returns the compiler binary the test suite is running with."""
1264 return self
.getCompiler().split()[0]
1266 def getCompilerVersion(self
):
1267 """ Returns a string that represents the compiler version.
1268 Supports: llvm, clang.
1272 compiler
= self
.getCompilerBinary()
1273 version_output
= system([[compiler
, "-v"]])[1]
1274 for line
in version_output
.split(os
.linesep
):
1275 m
= re
.search('version ([0-9\.]+)', line
)
1277 version
= m
.group(1)
1280 def getDwarfVersion(self
):
1281 """ Returns the dwarf version generated by clang or '0'. """
1282 if configuration
.dwarf_version
:
1283 return str(configuration
.dwarf_version
)
1284 if 'clang' in self
.getCompiler():
1286 driver_output
= check_output(
1287 [self
.getCompiler()] + '-g -c -x c - -o - -###'.split(),
1289 driver_output
= driver_output
.decode("utf-8")
1290 for line
in driver_output
.split(os
.linesep
):
1291 m
= re
.search('dwarf-version=([0-9])', line
)
1297 def platformIsDarwin(self
):
1298 """Returns true if the OS triple for the selected platform is any valid apple OS"""
1299 return lldbplatformutil
.platformIsDarwin()
1301 def hasDarwinFramework(self
):
1302 return self
.darwinWithFramework
1304 def getPlatform(self
):
1305 """Returns the target platform the test suite is running on."""
1306 return lldbplatformutil
.getPlatform()
1308 def isIntelCompiler(self
):
1309 """ Returns true if using an Intel (ICC) compiler, false otherwise. """
1310 return any([x
in self
.getCompiler() for x
in ["icc", "icpc", "icl"]])
1312 def expectedCompilerVersion(self
, compiler_version
):
1313 """Returns True iff compiler_version[1] matches the current compiler version.
1314 Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1315 Any operator other than the following defaults to an equality test:
1316 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1318 if (compiler_version
is None):
1320 operator
= str(compiler_version
[0])
1321 version
= compiler_version
[1]
1323 if (version
is None):
1325 if (operator
== '>'):
1326 return LooseVersion(self
.getCompilerVersion()) > LooseVersion(version
)
1327 if (operator
== '>=' or operator
== '=>'):
1328 return LooseVersion(self
.getCompilerVersion()) >= LooseVersion(version
)
1329 if (operator
== '<'):
1330 return LooseVersion(self
.getCompilerVersion()) < LooseVersion(version
)
1331 if (operator
== '<=' or operator
== '=<'):
1332 return LooseVersion(self
.getCompilerVersion()) <= LooseVersion(version
)
1333 if (operator
== '!=' or operator
== '!' or operator
== 'not'):
1334 return str(version
) not in str(self
.getCompilerVersion())
1335 return str(version
) in str(self
.getCompilerVersion())
1337 def expectedCompiler(self
, compilers
):
1338 """Returns True iff any element of compilers is a sub-string of the current compiler."""
1339 if (compilers
is None):
1342 for compiler
in compilers
:
1343 if compiler
in self
.getCompiler():
1348 def expectedArch(self
, archs
):
1349 """Returns True iff any element of archs is a sub-string of the current architecture."""
1354 if arch
in self
.getArchitecture():
1359 def getRunOptions(self
):
1360 """Command line option for -A and -C to run this test again, called from
1361 self.dumpSessionInfo()."""
1362 arch
= self
.getArchitecture()
1363 comp
= self
.getCompiler()
1366 option_str
= "-A " + arch
1368 option_str
+= " -C " + comp
1371 def getDebugInfo(self
):
1372 method
= getattr(self
, self
.testMethodName
)
1373 return getattr(method
, "debug_info", None)
1375 # ==================================================
1376 # Build methods supported through a plugin interface
1377 # ==================================================
1379 def getstdlibFlag(self
):
1380 """ Returns the proper -stdlib flag, or empty if not required."""
1381 if self
.platformIsDarwin() or self
.getPlatform() == "freebsd" or self
.getPlatform() == "openbsd":
1382 stdlibflag
= "-stdlib=libc++"
1383 else: # this includes NetBSD
1387 def getstdFlag(self
):
1388 """ Returns the proper stdflag. """
1389 if "gcc" in self
.getCompiler() and "4.6" in self
.getCompilerVersion():
1390 stdflag
= "-std=c++0x"
1392 stdflag
= "-std=c++11"
1395 def buildDriver(self
, sources
, exe_name
):
1396 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so
1399 stdflag
= self
.getstdFlag()
1400 stdlibflag
= self
.getstdlibFlag()
1402 lib_dir
= os
.environ
["LLDB_LIB_DIR"]
1403 if self
.hasDarwinFramework():
1404 d
= {'CXX_SOURCES': sources
,
1406 'CFLAGS_EXTRAS': "%s %s" % (stdflag
, stdlibflag
),
1407 'FRAMEWORK_INCLUDES': "-F%s" % self
.framework_dir
,
1408 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self
.dsym
, self
.framework_dir
),
1410 elif sys
.platform
.startswith('win'):
1412 'CXX_SOURCES': sources
,
1414 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag
,
1417 os
.environ
["LLDB_SRC"],
1419 'LD_EXTRAS': "-L%s -lliblldb" % os
.environ
["LLDB_IMPLIB_DIR"]}
1422 'CXX_SOURCES': sources
,
1424 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag
,
1427 os
.environ
["LLDB_SRC"],
1429 'LD_EXTRAS': "-L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir
, lib_dir
)}
1432 "Building LLDB Driver (%s) from sources %s" %
1433 (exe_name
, sources
))
1435 self
.buildDefault(dictionary
=d
)
1437 def buildLibrary(self
, sources
, lib_name
):
1438 """Platform specific way to build a default library. """
1440 stdflag
= self
.getstdFlag()
1442 lib_dir
= os
.environ
["LLDB_LIB_DIR"]
1443 if self
.hasDarwinFramework():
1444 d
= {'DYLIB_CXX_SOURCES': sources
,
1445 'DYLIB_NAME': lib_name
,
1446 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag
,
1447 'FRAMEWORK_INCLUDES': "-F%s" % self
.framework_dir
,
1448 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self
.dsym
, self
.framework_dir
),
1450 elif self
.getPlatform() == 'windows':
1452 'DYLIB_CXX_SOURCES': sources
,
1453 'DYLIB_NAME': lib_name
,
1454 'CFLAGS_EXTRAS': "%s -I%s " % (stdflag
,
1456 os
.environ
["LLDB_SRC"],
1458 'LD_EXTRAS': "-shared -l%s\liblldb.lib" % self
.os
.environ
["LLDB_IMPLIB_DIR"]}
1461 'DYLIB_CXX_SOURCES': sources
,
1462 'DYLIB_NAME': lib_name
,
1463 'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag
,
1465 os
.environ
["LLDB_SRC"],
1467 'LD_EXTRAS': "-shared -L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir
, lib_dir
)}
1470 "Building LLDB Library (%s) from sources %s" %
1471 (lib_name
, sources
))
1473 self
.buildDefault(dictionary
=d
)
1475 def buildProgram(self
, sources
, exe_name
):
1476 """ Platform specific way to build an executable from C/C++ sources. """
1477 d
= {'CXX_SOURCES': sources
,
1479 self
.buildDefault(dictionary
=d
)
1486 """Platform specific way to build the default binaries."""
1487 testdir
= self
.mydir
1488 testname
= self
.getBuildDirBasename()
1489 if self
.getDebugInfo():
1490 raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE")
1491 module
= builder_module()
1492 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1493 if not module
.buildDefault(self
, architecture
, compiler
,
1494 dictionary
, testdir
, testname
):
1495 raise Exception("Don't know how to build default binary")
1502 """Platform specific way to build binaries with dsym info."""
1503 testdir
= self
.mydir
1504 testname
= self
.getBuildDirBasename()
1505 if self
.getDebugInfo() != "dsym":
1506 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1508 module
= builder_module()
1509 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1510 if not module
.buildDsym(self
, architecture
, compiler
,
1511 dictionary
, testdir
, testname
):
1512 raise Exception("Don't know how to build binary with dsym")
1519 """Platform specific way to build binaries with dwarf maps."""
1520 testdir
= self
.mydir
1521 testname
= self
.getBuildDirBasename()
1522 if self
.getDebugInfo() != "dwarf":
1523 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1525 module
= builder_module()
1526 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1527 if not module
.buildDwarf(self
, architecture
, compiler
,
1528 dictionary
, testdir
, testname
):
1529 raise Exception("Don't know how to build binary with dwarf")
1536 """Platform specific way to build binaries with dwarf maps."""
1537 testdir
= self
.mydir
1538 testname
= self
.getBuildDirBasename()
1539 if self
.getDebugInfo() != "dwo":
1540 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1542 module
= builder_module()
1543 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1544 if not module
.buildDwo(self
, architecture
, compiler
,
1545 dictionary
, testdir
, testname
):
1546 raise Exception("Don't know how to build binary with dwo")
1553 """Platform specific way to build binaries with gmodules info."""
1554 testdir
= self
.mydir
1555 testname
= self
.getBuildDirBasename()
1556 if self
.getDebugInfo() != "gmodules":
1557 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1559 module
= builder_module()
1560 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1561 if not module
.buildGModules(self
, architecture
, compiler
,
1562 dictionary
, testdir
, testname
):
1563 raise Exception("Don't know how to build binary with gmodules")
1565 def signBinary(self
, binary_path
):
1566 if sys
.platform
.startswith("darwin"):
1567 codesign_cmd
= "codesign --force --sign \"%s\" %s" % (
1568 lldbtest_config
.codesign_identity
, binary_path
)
1569 call(codesign_cmd
, shell
=True)
1571 def findBuiltClang(self
):
1572 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
1574 "llvm-build/Release+Asserts/x86_64/bin/clang",
1575 "llvm-build/Debug+Asserts/x86_64/bin/clang",
1576 "llvm-build/Release/x86_64/bin/clang",
1577 "llvm-build/Debug/x86_64/bin/clang",
1579 lldb_root_path
= os
.path
.join(
1580 os
.path
.dirname(__file__
), "..", "..", "..", "..")
1581 for p
in paths_to_try
:
1582 path
= os
.path
.join(lldb_root_path
, p
)
1583 if os
.path
.exists(path
):
1586 # Tries to find clang at the same folder as the lldb
1587 lldb_dir
= os
.path
.dirname(lldbtest_config
.lldbExec
)
1588 path
= distutils
.spawn
.find_executable("clang", lldb_dir
)
1589 if path
is not None:
1592 return os
.environ
["CC"]
1594 def findYaml2obj(self
):
1596 Get the path to the yaml2obj executable, which can be used to create
1597 test object files from easy to write yaml instructions.
1599 Throws an Exception if the executable cannot be found.
1601 # Tries to find yaml2obj at the same folder as clang
1602 clang_dir
= os
.path
.dirname(self
.findBuiltClang())
1603 path
= distutils
.spawn
.find_executable("yaml2obj", clang_dir
)
1604 if path
is not None:
1606 raise Exception("yaml2obj executable not found")
1609 def yaml2obj(self
, yaml_path
, obj_path
):
1611 Create an object file at the given path from a yaml file.
1613 Throws subprocess.CalledProcessError if the object could not be created.
1615 yaml2obj
= self
.findYaml2obj()
1616 command
= [yaml2obj
, "-o=%s" % obj_path
, yaml_path
]
1623 use_libstdcxx
=False):
1624 """ Returns a dictionary (which can be provided to build* functions above) which
1625 contains OS-specific build flags.
1630 # On Mac OS X, unless specifically requested to use libstdc++, use
1632 if not use_libstdcxx
and self
.platformIsDarwin():
1635 if use_libcxx
and self
.libcxxPath
:
1636 cflags
+= "-stdlib=libc++ "
1638 libcxxInclude
= os
.path
.join(self
.libcxxPath
, "include")
1639 libcxxLib
= os
.path
.join(self
.libcxxPath
, "lib")
1640 if os
.path
.isdir(libcxxInclude
) and os
.path
.isdir(libcxxLib
):
1641 cflags
+= "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (
1642 libcxxInclude
, libcxxLib
, libcxxLib
)
1646 if "gcc" in self
.getCompiler() and "4.6" in self
.getCompilerVersion():
1650 if self
.platformIsDarwin() or self
.getPlatform() == "freebsd":
1651 cflags
+= " -stdlib=libc++"
1652 elif self
.getPlatform() == "openbsd":
1653 cflags
+= " -stdlib=libc++"
1654 elif self
.getPlatform() == "netbsd":
1655 # NetBSD defaults to libc++
1657 elif "clang" in self
.getCompiler():
1658 cflags
+= " -stdlib=libstdc++"
1660 return {'CFLAGS_EXTRAS': cflags
,
1661 'LD_EXTRAS': ldflags
,
1664 def cleanup(self
, dictionary
=None):
1665 """Platform specific way to do cleanup after build."""
1666 module
= builder_module()
1667 if not module
.cleanup(self
, dictionary
):
1669 "Don't know how to do cleanup with dictionary: " +
1672 def getLLDBLibraryEnvVal(self
):
1673 """ Returns the path that the OS-specific library search environment variable
1674 (self.dylibPath) should be set to in order for a program to find the LLDB
1675 library. If an environment variable named self.dylibPath is already set,
1676 the new path is appended to it and returned.
1678 existing_library_path
= os
.environ
[
1679 self
.dylibPath
] if self
.dylibPath
in os
.environ
else None
1680 lib_dir
= os
.environ
["LLDB_LIB_DIR"]
1681 if existing_library_path
:
1682 return "%s:%s" % (existing_library_path
, lib_dir
)
1683 elif sys
.platform
.startswith("darwin"):
1684 return os
.path
.join(lib_dir
, 'LLDB.framework')
1688 def getLibcPlusPlusLibs(self
):
1689 if self
.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'):
1690 return ['libc++.so.1']
1692 return ['libc++.1.dylib', 'libc++abi.']
1694 # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
1695 # We change the test methods to create a new test method for each test for each debug info we are
1696 # testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
1697 # the new test method we remove the old method at the same time. This functionality can be
1698 # supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test
1699 # level by using the decorator @no_debug_info_test.
1702 class LLDBTestCaseFactory(type):
1704 def __new__(cls
, name
, bases
, attrs
):
1705 original_testcase
= super(
1706 LLDBTestCaseFactory
, cls
).__new
__(
1707 cls
, name
, bases
, attrs
)
1708 if original_testcase
.NO_DEBUG_INFO_TESTCASE
:
1709 return original_testcase
1712 for attrname
, attrvalue
in attrs
.items():
1713 if attrname
.startswith("test") and not getattr(
1714 attrvalue
, "__no_debug_info_test__", False):
1716 # If any debug info categories were explicitly tagged, assume that list to be
1717 # authoritative. If none were specified, try with all debug
1719 all_dbginfo_categories
= set(test_categories
.debug_info_categories
)
1724 [])) & all_dbginfo_categories
1726 categories
= all_dbginfo_categories
1728 for cat
in categories
:
1729 @decorators.add_test_categories([cat
])
1731 def test_method(self
, attrvalue
=attrvalue
):
1732 return attrvalue(self
)
1734 method_name
= attrname
+ "_" + cat
1735 test_method
.__name
__ = method_name
1736 test_method
.debug_info
= cat
1737 newattrs
[method_name
] = test_method
1740 newattrs
[attrname
] = attrvalue
1742 LLDBTestCaseFactory
,
1749 # Setup the metaclass for this class to change the list of the test
1750 # methods when a new class is loaded
1753 @add_metaclass(LLDBTestCaseFactory
)
1754 class TestBase(Base
):
1756 This abstract base class is meant to be subclassed. It provides default
1757 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1760 Important things for test class writers:
1762 - Overwrite the mydir class attribute, otherwise your test class won't
1763 run. It specifies the relative directory to the top level 'test' so
1764 the test harness can change to the correct working directory before
1767 - The setUp method sets up things to facilitate subsequent interactions
1768 with the debugger as part of the test. These include:
1769 - populate the test method name
1770 - create/get a debugger set with synchronous mode (self.dbg)
1771 - get the command interpreter from with the debugger (self.ci)
1772 - create a result object for use with the command interpreter
1776 - The tearDown method tries to perform some necessary cleanup on behalf
1777 of the test to return the debugger to a good state for the next test.
1779 - execute any tearDown hooks registered by the test method with
1780 TestBase.addTearDownHook(); examples can be found in
1781 settings/TestSettings.py
1782 - kill the inferior process associated with each target, if any,
1783 and, then delete the target from the debugger's target list
1784 - perform build cleanup before running the next test method in the
1785 same test class; examples of registering for this service can be
1786 found in types/TestIntegerTypes.py with the call:
1787 - self.setTearDownCleanup(dictionary=d)
1789 - Similarly setUpClass and tearDownClass perform classwise setup and
1790 teardown fixtures. The tearDownClass method invokes a default build
1791 cleanup for the entire test class; also, subclasses can implement the
1792 classmethod classCleanup(cls) to perform special class cleanup action.
1794 - The instance methods runCmd and expect are used heavily by existing
1795 test cases to send a command to the command interpreter and to perform
1796 string/pattern matching on the output of such command execution. The
1797 expect method also provides a mode to peform string/pattern matching
1798 without running a command.
1800 - The build methods buildDefault, buildDsym, and buildDwarf are used to
1801 build the binaries used during a particular test scenario. A plugin
1802 should be provided for the sys.platform running the test suite. The
1803 Mac OS X implementation is located in plugins/darwin.py.
1806 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the
1807 # test multiple times with various debug info types.
1808 NO_DEBUG_INFO_TESTCASE
= False
1810 # Maximum allowed attempts when launching the inferior process.
1811 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1814 # Time to wait before the next launching attempt in second(s).
1815 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1816 timeWaitNextLaunch
= 1.0
1818 def generateSource(self
, source
):
1819 template
= source
+ '.template'
1820 temp
= os
.path
.join(self
.getSourceDir(), template
)
1821 with
open(temp
, 'r') as f
:
1824 public_api_dir
= os
.path
.join(
1825 os
.environ
["LLDB_SRC"], "include", "lldb", "API")
1827 # Look under the include/lldb/API directory and add #include statements
1828 # for all the SB API headers.
1829 public_headers
= os
.listdir(public_api_dir
)
1830 # For different platforms, the include statement can vary.
1831 if self
.hasDarwinFramework():
1832 include_stmt
= "'#include <%s>' % os.path.join('LLDB', header)"
1834 include_stmt
= "'#include <%s>' % os.path.join('" + public_api_dir
+ "', header)"
1835 list = [eval(include_stmt
) for header
in public_headers
if (
1836 header
.startswith("SB") and header
.endswith(".h"))]
1837 includes
= '\n'.join(list)
1838 new_content
= content
.replace('%include_SB_APIs%', includes
)
1839 src
= os
.path
.join(self
.getBuildDir(), source
)
1840 with
open(src
, 'w') as f
:
1841 f
.write(new_content
)
1843 self
.addTearDownHook(lambda: os
.remove(src
))
1847 # traceback.print_stack()
1849 # Works with the test driver to conditionally skip tests via
1853 for s
in self
.setUpCommands():
1856 if "LLDB_MAX_LAUNCH_COUNT" in os
.environ
:
1857 self
.maxLaunchCount
= int(os
.environ
["LLDB_MAX_LAUNCH_COUNT"])
1859 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os
.environ
:
1860 self
.timeWaitNextLaunch
= float(
1861 os
.environ
["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1863 # We want our debugger to be synchronous.
1864 self
.dbg
.SetAsync(False)
1866 # Retrieve the associated command interpreter instance.
1867 self
.ci
= self
.dbg
.GetCommandInterpreter()
1869 raise Exception('Could not get the command interpreter')
1871 # And the result object.
1872 self
.res
= lldb
.SBCommandReturnObject()
1874 def registerSharedLibrariesWithTarget(self
, target
, shlibs
):
1875 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
1877 Any modules in the target that have their remote install file specification set will
1878 get uploaded to the remote host. This function registers the local copies of the
1879 shared libraries with the target and sets their remote install locations so they will
1880 be uploaded when the target is run.
1882 if not shlibs
or not self
.platformContext
:
1885 shlib_environment_var
= self
.platformContext
.shlib_environment_var
1886 shlib_prefix
= self
.platformContext
.shlib_prefix
1887 shlib_extension
= '.' + self
.platformContext
.shlib_extension
1889 working_dir
= self
.get_process_working_directory()
1890 environment
= ['%s=%s' % (shlib_environment_var
, working_dir
)]
1891 # Add any shared libraries to our target if remote so they get
1892 # uploaded into the working directory on the remote side
1894 # The path can be a full path to a shared library, or a make file name like "Foo" for
1895 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
1896 # basename like "libFoo.so". So figure out which one it is and resolve the local copy
1897 # of the shared library accordingly
1898 if os
.path
.isfile(name
):
1899 local_shlib_path
= name
# name is the full path to the local shared library
1901 # Check relative names
1902 local_shlib_path
= os
.path
.join(
1903 self
.getBuildDir(), shlib_prefix
+ name
+ shlib_extension
)
1904 if not os
.path
.exists(local_shlib_path
):
1905 local_shlib_path
= os
.path
.join(
1906 self
.getBuildDir(), name
+ shlib_extension
)
1907 if not os
.path
.exists(local_shlib_path
):
1908 local_shlib_path
= os
.path
.join(self
.getBuildDir(), name
)
1910 # Make sure we found the local shared library in the above code
1911 self
.assertTrue(os
.path
.exists(local_shlib_path
))
1913 # Add the shared library to our target
1914 shlib_module
= target
.AddModule(local_shlib_path
, None, None, None)
1915 if lldb
.remote_platform
:
1916 # We must set the remote install location if we want the shared library
1917 # to get uploaded to the remote target
1918 remote_shlib_path
= lldbutil
.append_to_process_working_directory(self
,
1919 os
.path
.basename(local_shlib_path
))
1920 shlib_module
.SetRemoteInstallFileSpec(
1921 lldb
.SBFileSpec(remote_shlib_path
, False))
1925 def registerSanitizerLibrariesWithTarget(self
, target
):
1927 for m
in target
.module_iter():
1928 libspec
= m
.GetFileSpec()
1929 if "clang_rt" in libspec
.GetFilename():
1930 runtimes
.append(os
.path
.join(libspec
.GetDirectory(),
1931 libspec
.GetFilename()))
1932 return self
.registerSharedLibrariesWithTarget(target
, runtimes
)
1934 # utility methods that tests can use to access the current objects
1937 raise Exception('Invalid debugger instance')
1938 return self
.dbg
.GetSelectedTarget()
1942 raise Exception('Invalid debugger instance')
1943 return self
.dbg
.GetSelectedTarget().GetProcess()
1947 raise Exception('Invalid debugger instance')
1948 return self
.dbg
.GetSelectedTarget().GetProcess().GetSelectedThread()
1952 raise Exception('Invalid debugger instance')
1953 return self
.dbg
.GetSelectedTarget().GetProcess(
1954 ).GetSelectedThread().GetSelectedFrame()
1956 def get_process_working_directory(self
):
1957 '''Get the working directory that should be used when launching processes for local or remote processes.'''
1958 if lldb
.remote_platform
:
1959 # Remote tests set the platform working directory up in
1961 return lldb
.remote_platform
.GetWorkingDirectory()
1963 # local tests change directory into each test subdirectory
1964 return self
.getBuildDir()
1968 # traceback.print_stack()
1970 # Ensure all the references to SB objects have gone away so that we can
1971 # be sure that all test-specific resources have been freed before we
1972 # attempt to delete the targets.
1975 # Delete the target(s) from the debugger as a general cleanup step.
1976 # This includes terminating the process for each target, if any.
1977 # We'd like to reuse the debugger for our next test without incurring
1978 # the initialization overhead.
1980 for target
in self
.dbg
:
1982 targets
.append(target
)
1983 process
= target
.GetProcess()
1985 rc
= self
.invoke(process
, "Kill")
1986 self
.assertTrue(rc
.Success(), PROCESS_KILLED
)
1987 for target
in targets
:
1988 self
.dbg
.DeleteTarget(target
)
1990 # Do this last, to make sure it's in reverse order from how we setup.
1993 # This must be the last statement, otherwise teardown hooks or other
1994 # lines might depend on this still being active.
1997 def switch_to_thread_with_stop_reason(self
, stop_reason
):
1999 Run the 'thread list' command, and select the thread with stop reason as
2000 'stop_reason'. If no such thread exists, no select action is done.
2002 from .lldbutil
import stop_reason_to_str
2003 self
.runCmd('thread list')
2004 output
= self
.res
.GetOutput()
2005 thread_line_pattern
= re
.compile(
2006 "^[ *] thread #([0-9]+):.*stop reason = %s" %
2007 stop_reason_to_str(stop_reason
))
2008 for line
in output
.splitlines():
2009 matched
= thread_line_pattern
.match(line
)
2011 self
.runCmd('thread select %s' % matched
.group(1))
2013 def runCmd(self
, cmd
, msg
=None, check
=True, trace
=False, inHistory
=False):
2015 Ask the command interpreter to handle the command and then check its
2018 # Fail fast if 'cmd' is not meaningful.
2019 if not cmd
or len(cmd
) == 0:
2020 raise Exception("Bad 'cmd' parameter encountered")
2022 trace
= (True if traceAlways
else trace
)
2024 if cmd
.startswith("target create "):
2025 cmd
= cmd
.replace("target create ", "file ")
2027 running
= (cmd
.startswith("run") or cmd
.startswith("process launch"))
2029 for i
in range(self
.maxLaunchCount
if running
else 1):
2030 self
.ci
.HandleCommand(cmd
, self
.res
, inHistory
)
2032 with
recording(self
, trace
) as sbuf
:
2033 print("runCmd:", cmd
, file=sbuf
)
2035 print("check of return status not required", file=sbuf
)
2036 if self
.res
.Succeeded():
2037 print("output:", self
.res
.GetOutput(), file=sbuf
)
2039 print("runCmd failed!", file=sbuf
)
2040 print(self
.res
.GetError(), file=sbuf
)
2042 if self
.res
.Succeeded():
2045 # For process launch, wait some time before possible next try.
2046 time
.sleep(self
.timeWaitNextLaunch
)
2047 with
recording(self
, trace
) as sbuf
:
2048 print("Command '" + cmd
+ "' failed!", file=sbuf
)
2052 if self
.res
.GetOutput():
2053 output
+= "\nCommand output:\n" + self
.res
.GetOutput()
2054 if self
.res
.GetError():
2055 output
+= "\nError output:\n" + self
.res
.GetError()
2060 self
.assertTrue(self
.res
.Succeeded(),
2061 msg
if (msg
) else CMD_MSG(cmd
))
2072 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2074 Otherwise, all the arguments have the same meanings as for the expect function"""
2076 trace
= (True if traceAlways
else trace
)
2079 # First run the command. If we are expecting error, set check=False.
2080 # Pass the assert message along since it provides more semantic
2086 True if trace
else False),
2089 # Then compare the output against expected strings.
2090 output
= self
.res
.GetError() if error
else self
.res
.GetOutput()
2092 # If error is True, the API client expects the command to fail!
2094 self
.assertFalse(self
.res
.Succeeded(),
2095 "Command '" + str + "' is expected to fail!")
2097 # No execution required, just compare str against the golden input.
2099 with
recording(self
, trace
) as sbuf
:
2100 print("looking at:", output
, file=sbuf
)
2102 # The heading says either "Expecting" or "Not expecting".
2103 heading
= "Expecting" if matching
else "Not expecting"
2105 for pattern
in patterns
:
2106 # Match Objects always have a boolean value of True.
2107 match_object
= re
.search(pattern
, output
)
2108 matched
= bool(match_object
)
2109 with
recording(self
, trace
) as sbuf
:
2110 print("%s pattern: %s" % (heading
, pattern
), file=sbuf
)
2111 print("Matched" if matched
else "Not matched", file=sbuf
)
2115 self
.assertTrue(matched
if matching
else not matched
,
2116 msg
if msg
else EXP_MSG(str, output
, exe
))
2120 def check_completion_with_desc(self
, str_input
, match_desc_pairs
):
2121 interp
= self
.dbg
.GetCommandInterpreter()
2122 match_strings
= lldb
.SBStringList()
2123 description_strings
= lldb
.SBStringList()
2124 num_matches
= interp
.HandleCompletionWithDescriptions(str_input
, len(str_input
), 0, -1, match_strings
, description_strings
)
2125 self
.assertEqual(len(description_strings
), len(match_strings
))
2128 for pair
in match_desc_pairs
:
2130 for i
in range(num_matches
+ 1):
2131 match_candidate
= match_strings
.GetStringAtIndex(i
)
2132 description_candidate
= description_strings
.GetStringAtIndex(i
)
2133 if match_candidate
== pair
[0] and description_candidate
== pair
[1]:
2137 missing_pairs
.append(pair
)
2139 if len(missing_pairs
):
2140 error_msg
= "Missing pairs:\n"
2141 for pair
in missing_pairs
:
2142 error_msg
+= " [" + pair
[0] + ":" + pair
[1] + "]\n"
2143 error_msg
+= "Got the following " + str(num_matches
) + " completions back:\n"
2144 for i
in range(num_matches
+ 1):
2145 match_candidate
= match_strings
.GetStringAtIndex(i
)
2146 description_candidate
= description_strings
.GetStringAtIndex(i
)
2147 error_msg
+= "[" + match_candidate
+ ":" + description_candidate
+ "]\n"
2148 self
.assertEqual(0, len(missing_pairs
), error_msg
)
2150 def complete_exactly(self
, str_input
, patterns
):
2151 self
.complete_from_to(str_input
, patterns
, True)
2153 def complete_from_to(self
, str_input
, patterns
, turn_off_re_match
=False):
2154 """Test that the completion mechanism completes str_input to patterns,
2155 where patterns could be a pattern-string or a list of pattern-strings"""
2156 # Patterns should not be None in order to proceed.
2157 self
.assertFalse(patterns
is None)
2158 # And should be either a string or list of strings. Check for list type
2159 # below, if not, make a list out of the singleton string. If patterns
2160 # is not a string or not a list of strings, there'll be runtime errors
2162 if not isinstance(patterns
, list):
2163 patterns
= [patterns
]
2165 interp
= self
.dbg
.GetCommandInterpreter()
2166 match_strings
= lldb
.SBStringList()
2167 num_matches
= interp
.HandleCompletion(str_input
, len(str_input
), 0, -1, match_strings
)
2168 common_match
= match_strings
.GetStringAtIndex(0)
2169 if num_matches
== 0:
2170 compare_string
= str_input
2172 if common_match
!= None and len(common_match
) > 0:
2173 compare_string
= str_input
+ common_match
2176 for idx
in range(1, num_matches
+1):
2177 compare_string
+= match_strings
.GetStringAtIndex(idx
) + "\n"
2180 if turn_off_re_match
:
2182 compare_string
, msg
=COMPLETION_MSG(
2183 str_input
, p
, match_strings
), exe
=False, substrs
=[p
])
2186 compare_string
, msg
=COMPLETION_MSG(
2187 str_input
, p
, match_strings
), exe
=False, patterns
=[p
])
2189 def completions_match(self
, command
, completions
):
2190 """Checks that the completions for the given command are equal to the
2191 given list of completions"""
2192 interp
= self
.dbg
.GetCommandInterpreter()
2193 match_strings
= lldb
.SBStringList()
2194 interp
.HandleCompletion(command
, len(command
), 0, -1, match_strings
)
2195 # match_strings is a 1-indexed list, so we have to slice...
2196 self
.assertItemsEqual(completions
, list(match_strings
)[1:],
2197 "List of returned completion is wrong")
2203 filecheck_options
= '',
2204 expect_cmd_failure
= False):
2208 check
=(not expect_cmd_failure
),
2209 msg
="FileCheck'ing result of `{0}`".format(command
))
2211 self
.assertTrue((not expect_cmd_failure
) == self
.res
.Succeeded())
2213 # Get the error text if there was an error, and the regular text if not.
2214 output
= self
.res
.GetOutput() if self
.res
.Succeeded() \
2215 else self
.res
.GetError()
2217 # Assemble the absolute path to the check file. As a convenience for
2218 # LLDB inline tests, assume that the check file is a relative path to
2219 # a file within the inline test directory.
2220 if check_file
.endswith('.pyc'):
2221 check_file
= check_file
[:-1]
2222 check_file_abs
= os
.path
.abspath(check_file
)
2225 filecheck_bin
= configuration
.get_filecheck_path()
2226 if not filecheck_bin
:
2227 self
.assertTrue(False, "No valid FileCheck executable specified")
2228 filecheck_args
= [filecheck_bin
, check_file_abs
]
2229 if filecheck_options
:
2230 filecheck_args
.append(filecheck_options
)
2231 subproc
= Popen(filecheck_args
, stdin
=PIPE
, stdout
=PIPE
, stderr
=PIPE
, universal_newlines
= True)
2232 cmd_stdout
, cmd_stderr
= subproc
.communicate(input=output
)
2233 cmd_status
= subproc
.returncode
2235 filecheck_cmd
= " ".join(filecheck_args
)
2236 filecheck_trace
= """
2237 --- FileCheck trace (code={0}) ---
2246 """.format(cmd_status
, filecheck_cmd
, output
, cmd_stdout
, cmd_stderr
)
2248 trace
= cmd_status
!= 0 or traceAlways
2249 with
recording(self
, trace
) as sbuf
:
2250 print(filecheck_trace
, file=sbuf
)
2252 self
.assertTrue(cmd_status
== 0)
2268 Similar to runCmd; with additional expect style output matching ability.
2270 Ask the command interpreter to handle the command and then check its
2271 return status. The 'msg' parameter specifies an informational assert
2272 message. We expect the output from running the command to start with
2273 'startstr', matches the substrings contained in 'substrs', and regexp
2274 matches the patterns contained in 'patterns'.
2276 If the keyword argument error is set to True, it signifies that the API
2277 client is expecting the command to fail. In this case, the error stream
2278 from running the command is retrieved and compared against the golden
2281 If the keyword argument matching is set to False, it signifies that the API
2282 client is expecting the output of the command not to match the golden
2285 Finally, the required argument 'str' represents the lldb command to be
2286 sent to the command interpreter. In case the keyword argument 'exe' is
2287 set to False, the 'str' is treated as a string to be matched/not-matched
2288 against the golden input.
2290 trace
= (True if traceAlways
else trace
)
2293 # First run the command. If we are expecting error, set check=False.
2294 # Pass the assert message along since it provides more semantic
2300 True if trace
else False),
2302 inHistory
=inHistory
)
2304 # Then compare the output against expected strings.
2305 output
= self
.res
.GetError() if error
else self
.res
.GetOutput()
2307 # If error is True, the API client expects the command to fail!
2309 self
.assertFalse(self
.res
.Succeeded(),
2310 "Command '" + str + "' is expected to fail!")
2312 # No execution required, just compare str against the golden input.
2313 if isinstance(str, lldb
.SBCommandReturnObject
):
2314 output
= str.GetOutput()
2317 with
recording(self
, trace
) as sbuf
:
2318 print("looking at:", output
, file=sbuf
)
2320 # The heading says either "Expecting" or "Not expecting".
2321 heading
= "Expecting" if matching
else "Not expecting"
2323 # Start from the startstr, if specified.
2324 # If there's no startstr, set the initial state appropriately.
2325 matched
= output
.startswith(startstr
) if startstr
else (
2326 True if matching
else False)
2329 with
recording(self
, trace
) as sbuf
:
2330 print("%s start string: %s" % (heading
, startstr
), file=sbuf
)
2331 print("Matched" if matched
else "Not matched", file=sbuf
)
2333 # Look for endstr, if specified.
2334 keepgoing
= matched
if matching
else not matched
2336 matched
= output
.endswith(endstr
)
2337 with
recording(self
, trace
) as sbuf
:
2338 print("%s end string: %s" % (heading
, endstr
), file=sbuf
)
2339 print("Matched" if matched
else "Not matched", file=sbuf
)
2341 # Look for sub strings, if specified.
2342 keepgoing
= matched
if matching
else not matched
2343 if substrs
and keepgoing
:
2344 for substr
in substrs
:
2345 matched
= output
.find(substr
) != -1
2346 with
recording(self
, trace
) as sbuf
:
2347 print("%s sub string: %s" % (heading
, substr
), file=sbuf
)
2348 print("Matched" if matched
else "Not matched", file=sbuf
)
2349 keepgoing
= matched
if matching
else not matched
2353 # Search for regular expression patterns, if specified.
2354 keepgoing
= matched
if matching
else not matched
2355 if patterns
and keepgoing
:
2356 for pattern
in patterns
:
2357 # Match Objects always have a boolean value of True.
2358 matched
= bool(re
.search(pattern
, output
))
2359 with
recording(self
, trace
) as sbuf
:
2360 print("%s pattern: %s" % (heading
, pattern
), file=sbuf
)
2361 print("Matched" if matched
else "Not matched", file=sbuf
)
2362 keepgoing
= matched
if matching
else not matched
2366 self
.assertTrue(matched
if matching
else not matched
,
2367 msg
if msg
else EXP_MSG(str, output
, exe
))
2372 result_summary
=None,
2378 Evaluates the given expression and verifies the result.
2379 :param expr: The expression as a string.
2380 :param result_summary: The summary that the expression should have. None if the summary should not be checked.
2381 :param result_value: The value that the expression should have. None if the value should not be checked.
2382 :param result_type: The type that the expression result should have. None if the type should not be checked.
2383 :param error_msg: The error message the expression should return. None if the error output should not be checked.
2385 self
.assertTrue(expr
.strip() == expr
, "Expression contains trailing/leading whitespace: '" + expr
+ "'")
2387 frame
= self
.frame()
2388 eval_result
= frame
.EvaluateExpression(expr
)
2391 self
.assertFalse(eval_result
.IsValid())
2392 self
.assertEqual(error_msg
, eval_result
.GetError().GetCString())
2395 if not eval_result
.GetError().Success():
2396 self
.assertTrue(eval_result
.GetError().Success(),
2397 "Unexpected failure with msg: " + eval_result
.GetError().GetCString())
2400 self
.assertEqual(result_type
, eval_result
.GetTypeName())
2403 self
.assertEqual(result_value
, eval_result
.GetValue())
2406 self
.assertEqual(result_summary
, eval_result
.GetSummary())
2408 def invoke(self
, obj
, name
, trace
=False):
2409 """Use reflection to call a method dynamically with no argument."""
2410 trace
= (True if traceAlways
else trace
)
2412 method
= getattr(obj
, name
)
2414 self
.assertTrue(inspect
.ismethod(method
),
2415 name
+ "is a method name of object: " + str(obj
))
2417 with
recording(self
, trace
) as sbuf
:
2418 print(str(method
) + ":", result
, file=sbuf
)
2426 """Platform specific way to build the default binaries."""
2427 module
= builder_module()
2429 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
2430 if self
.getDebugInfo() is None:
2431 return self
.buildDefault(architecture
, compiler
, dictionary
)
2432 elif self
.getDebugInfo() == "dsym":
2433 return self
.buildDsym(architecture
, compiler
, dictionary
)
2434 elif self
.getDebugInfo() == "dwarf":
2435 return self
.buildDwarf(architecture
, compiler
, dictionary
)
2436 elif self
.getDebugInfo() == "dwo":
2437 return self
.buildDwo(architecture
, compiler
, dictionary
)
2438 elif self
.getDebugInfo() == "gmodules":
2439 return self
.buildGModules(architecture
, compiler
, dictionary
)
2441 self
.fail("Can't build for debug info: %s" % self
.getDebugInfo())
2443 def run_platform_command(self
, cmd
):
2444 platform
= self
.dbg
.GetSelectedPlatform()
2445 shell_command
= lldb
.SBPlatformShellCommand(cmd
)
2446 err
= platform
.Run(shell_command
)
2447 return (err
, shell_command
.GetStatus(), shell_command
.GetOutput())
2449 # =================================================
2450 # Misc. helper methods for debugging test execution
2451 # =================================================
2453 def DebugSBValue(self
, val
):
2454 """Debug print a SBValue object, if traceAlways is True."""
2455 from .lldbutil
import value_type_to_str
2461 err
.write(val
.GetName() + ":\n")
2462 err
.write('\t' + "TypeName -> " + val
.GetTypeName() + '\n')
2463 err
.write('\t' + "ByteSize -> " +
2464 str(val
.GetByteSize()) + '\n')
2465 err
.write('\t' + "NumChildren -> " +
2466 str(val
.GetNumChildren()) + '\n')
2467 err
.write('\t' + "Value -> " + str(val
.GetValue()) + '\n')
2468 err
.write('\t' + "ValueAsUnsigned -> " +
2469 str(val
.GetValueAsUnsigned()) + '\n')
2474 val
.GetValueType()) +
2476 err
.write('\t' + "Summary -> " + str(val
.GetSummary()) + '\n')
2477 err
.write('\t' + "IsPointerType -> " +
2478 str(val
.TypeIsPointerType()) + '\n')
2479 err
.write('\t' + "Location -> " + val
.GetLocation() + '\n')
2481 def DebugSBType(self
, type):
2482 """Debug print a SBType object, if traceAlways is True."""
2487 err
.write(type.GetName() + ":\n")
2488 err
.write('\t' + "ByteSize -> " +
2489 str(type.GetByteSize()) + '\n')
2490 err
.write('\t' + "IsPointerType -> " +
2491 str(type.IsPointerType()) + '\n')
2492 err
.write('\t' + "IsReferenceType -> " +
2493 str(type.IsReferenceType()) + '\n')
2495 def DebugPExpect(self
, child
):
2496 """Debug the spwaned pexpect object."""
2503 def RemoveTempFile(cls
, file):
2504 if os
.path
.exists(file):
2507 # On Windows, the first attempt to delete a recently-touched file can fail
2508 # because of a race with antimalware scanners. This function will detect a
2509 # failure and retry.
2512 def remove_file(file, num_retries
=1, sleep_duration
=0.5):
2513 for i
in range(num_retries
+ 1):
2518 time
.sleep(sleep_duration
)