2 LLDB module which provides the abstract base class of lldb test case.
4 The concrete subclass can override lldbtest.TestBase in order to inherit the
5 common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
7 ./dotest.py provides a test driver which sets up the environment to run the
8 entire of part of the test suite . Example:
10 # Exercises the test suite in the types directory....
11 /Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types
14 Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42'
15 Command invoked: python ./dotest.py -A x86_64 types
18 Configuration: arch=x86_64 compiler=clang
19 ----------------------------------------------------------------------
22 ........................................................................
23 ----------------------------------------------------------------------
24 Ran 72 tests in 135.468s
32 from distutils
.version
import LooseVersion
33 from functools
import wraps
42 from subprocess
import *
52 from . import configuration
53 from . import decorators
54 from . import lldbplatformutil
55 from . import lldbtest_config
56 from . import lldbutil
57 from . import test_categories
58 from lldbsuite
.support
import encoded_file
59 from lldbsuite
.support
import funcutils
60 from lldbsuite
.support
import seven
61 from lldbsuite
.test
.builders
import get_builder
62 from lldbsuite
.test_event
import build_exception
64 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
65 # LLDB_COMMAND_TRACE is set from '-t' option.
67 # By default, traceAlways is False.
68 if "LLDB_COMMAND_TRACE" in os
.environ
and os
.environ
["LLDB_COMMAND_TRACE"] == "YES":
73 # By default, doCleanup is True.
74 if "LLDB_DO_CLEANUP" in os
.environ
and os
.environ
["LLDB_DO_CLEANUP"] == "NO":
81 # Some commonly used assert messages.
84 COMMAND_FAILED_AS_EXPECTED
= "Command has failed as expected"
86 CURRENT_EXECUTABLE_SET
= "Current executable set successfully"
88 PROCESS_IS_VALID
= "Process is valid"
90 PROCESS_KILLED
= "Process is killed successfully"
92 PROCESS_EXITED
= "Process exited successfully"
94 PROCESS_STOPPED
= "Process status should be stopped"
96 RUN_SUCCEEDED
= "Process is launched successfully"
98 RUN_COMPLETED
= "Process exited successfully"
100 BACKTRACE_DISPLAYED_CORRECTLY
= "Backtrace displayed correctly"
102 BREAKPOINT_CREATED
= "Breakpoint created successfully"
104 BREAKPOINT_STATE_CORRECT
= "Breakpoint state is correct"
106 BREAKPOINT_PENDING_CREATED
= "Pending breakpoint created successfully"
108 BREAKPOINT_HIT_ONCE
= "Breakpoint resolved with hit count = 1"
110 BREAKPOINT_HIT_TWICE
= "Breakpoint resolved with hit count = 2"
112 BREAKPOINT_HIT_THRICE
= "Breakpoint resolved with hit count = 3"
114 MISSING_EXPECTED_REGISTERS
= "At least one expected register is unavailable."
116 OBJECT_PRINTED_CORRECTLY
= "Object printed correctly"
118 SOURCE_DISPLAYED_CORRECTLY
= "Source code displayed correctly"
120 STEP_IN_SUCCEEDED
= "Thread step-in succeeded"
122 STEP_OUT_SUCCEEDED
= "Thread step-out succeeded"
124 STOPPED_DUE_TO_EXC_BAD_ACCESS
= "Process should be stopped due to bad access exception"
126 STOPPED_DUE_TO_ASSERT
= "Process should be stopped due to an assertion"
128 STOPPED_DUE_TO_BREAKPOINT
= "Process should be stopped due to breakpoint"
130 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS
= "%s, %s" % (
131 STOPPED_DUE_TO_BREAKPOINT
,
132 "instead, the actual stop reason is: '%s'",
135 STOPPED_DUE_TO_BREAKPOINT_CONDITION
= "Stopped due to breakpoint condition"
137 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT
= "Stopped due to breakpoint and ignore count"
139 STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION
= (
140 "Stopped due to breakpoint jitted condition"
143 STOPPED_DUE_TO_SIGNAL
= "Process state is stopped due to signal"
145 STOPPED_DUE_TO_STEP_IN
= "Process state is stopped due to step in"
147 STOPPED_DUE_TO_WATCHPOINT
= "Process should be stopped due to watchpoint"
149 DATA_TYPES_DISPLAYED_CORRECTLY
= "Data type(s) displayed correctly"
151 VALID_BREAKPOINT
= "Got a valid breakpoint"
153 VALID_BREAKPOINT_LOCATION
= "Got a valid breakpoint location"
155 VALID_COMMAND_INTERPRETER
= "Got a valid command interpreter"
157 VALID_FILESPEC
= "Got a valid filespec"
159 VALID_MODULE
= "Got a valid module"
161 VALID_PROCESS
= "Got a valid process"
163 VALID_SYMBOL
= "Got a valid symbol"
165 VALID_TARGET
= "Got a valid target"
167 VALID_PLATFORM
= "Got a valid platform"
169 VALID_TYPE
= "Got a valid type"
171 VALID_VARIABLE
= "Got a valid variable"
173 VARIABLES_DISPLAYED_CORRECTLY
= "Variable(s) displayed correctly"
175 WATCHPOINT_CREATED
= "Watchpoint created successfully"
179 """A generic "Command '%s' did not return successfully" message generator."""
180 return "Command '%s' did not return successfully" % str
183 def COMPLETION_MSG(str_before
, str_after
, completions
):
184 """A generic assertion failed message generator for the completion mechanism."""
185 return "'%s' successfully completes to '%s', but completions were:\n%s" % (
188 "\n".join(completions
),
192 def EXP_MSG(str, actual
, exe
):
193 """A generic "'%s' returned unexpected result" message generator if exe.
194 Otherwise, it generates "'%s' does not match expected result" message."""
196 return "'%s' %s result, got '%s'" % (
198 "returned unexpected" if exe
else "does not match expected",
203 def SETTING_MSG(setting
):
204 """A generic "Value of setting '%s' is not correct" message generator."""
205 return "Value of setting '%s' is not correct" % setting
208 def line_number(filename
, string_to_match
):
209 """Helper function to return the line number of the first matched string."""
210 with io
.open(filename
, mode
="r", encoding
="utf-8") as f
:
211 for i
, line
in enumerate(f
):
212 if line
.find(string_to_match
) != -1:
215 raise Exception("Unable to find '%s' within file %s" % (string_to_match
, filename
))
218 def get_line(filename
, line_number
):
219 """Return the text of the line at the 1-based line number."""
220 with io
.open(filename
, mode
="r", encoding
="utf-8") as f
:
221 return f
.readlines()[line_number
- 1]
225 """Return the pointer size of the host system."""
228 a_pointer
= ctypes
.c_void_p(0xFFFF)
229 return 8 * ctypes
.sizeof(a_pointer
)
233 """Returns true if fpath is an executable."""
236 if sys
.platform
== "win32":
237 if not fpath
.endswith(".exe"):
239 return os
.path
.isfile(fpath
) and os
.access(fpath
, os
.X_OK
)
243 """Returns the full path to a program; None otherwise."""
244 fpath
, fname
= os
.path
.split(program
)
249 for path
in os
.environ
["PATH"].split(os
.pathsep
):
250 exe_file
= os
.path
.join(path
, program
)
267 :param name: The name that the SBValue should have. None if the summary
268 should not be checked.
269 :param summary: The summary that the SBValue should have. None if the
270 summary should not be checked.
271 :param value: The value that the SBValue should have. None if the value
272 should not be checked.
273 :param type: The type that the SBValue result should have. None if the
274 type should not be checked.
275 :param children: A list of ValueChecks that need to match the children
276 of this SBValue. None if children shouldn't be checked.
277 The order of checks is the order of the checks in the
278 list. The number of checks has to match the number of
280 :param dereference: A ValueCheck for the SBValue returned by the
281 `Dereference` function.
283 self
.expect_name
= name
284 self
.expect_value
= value
285 self
.expect_type
= type
286 self
.expect_summary
= summary
287 self
.children
= children
288 self
.dereference
= dereference
290 def check_value(self
, test_base
, val
, error_msg
=None):
292 Checks that the given value matches the currently set properties
293 of this ValueCheck. If a match failed, the given TestBase will
294 be used to emit an error. A custom error message can be specified
295 that will be used to describe failed check for this SBValue (but
296 not errors in the child values).
299 this_error_msg
= error_msg
if error_msg
else ""
300 this_error_msg
+= "\nChecking SBValue: " + str(val
)
302 test_base
.assertSuccess(val
.GetError())
304 # Python 3.6 doesn't declare a `re.Pattern` type, get the dynamic type.
305 pattern_type
= type(re
.compile(""))
308 test_base
.assertEqual(self
.expect_name
, val
.GetName(), this_error_msg
)
309 if self
.expect_value
:
310 if isinstance(self
.expect_value
, pattern_type
):
311 test_base
.assertRegex(val
.GetValue(), self
.expect_value
, this_error_msg
)
313 test_base
.assertEqual(self
.expect_value
, val
.GetValue(), this_error_msg
)
315 test_base
.assertEqual(
316 self
.expect_type
, val
.GetDisplayTypeName(), this_error_msg
318 if self
.expect_summary
:
319 if isinstance(self
.expect_summary
, pattern_type
):
320 test_base
.assertRegex(
321 val
.GetSummary(), self
.expect_summary
, this_error_msg
324 test_base
.assertEqual(
325 self
.expect_summary
, val
.GetSummary(), this_error_msg
327 if self
.children
is not None:
328 self
.check_value_children(test_base
, val
, error_msg
)
330 if self
.dereference
is not None:
331 self
.dereference
.check_value(test_base
, val
.Dereference(), error_msg
)
333 def check_value_children(self
, test_base
, val
, error_msg
=None):
335 Checks that the children of a SBValue match a certain structure and
336 have certain properties.
338 :param test_base: The current test's TestBase object.
339 :param val: The SBValue to check.
342 this_error_msg
= error_msg
if error_msg
else ""
343 this_error_msg
+= "\nChecking SBValue: " + str(val
)
345 test_base
.assertEqual(len(self
.children
), val
.GetNumChildren(), this_error_msg
)
347 for i
in range(0, val
.GetNumChildren()):
348 expected_child
= self
.children
[i
]
349 actual_child
= val
.GetChildAtIndex(i
)
350 child_error
= "Checking child with index " + str(i
) + ":\n" + error_msg
351 expected_child
.check_value(test_base
, actual_child
, child_error
)
354 class recording(io
.StringIO
):
356 A nice little context manager for recording the debugger interactions into
357 our session object. If trace flag is ON, it also emits the interactions
361 def __init__(self
, test
, trace
):
362 """Create a io.StringIO instance; record the session obj and trace flag."""
363 io
.StringIO
.__init
__(self
)
364 # The test might not have undergone the 'setUp(self)' phase yet, so that
365 # the attribute 'session' might not even exist yet.
366 self
.session
= getattr(test
, "session", None) if test
else None
371 Context management protocol on entry to the body of the with statement.
372 Just return the io.StringIO object.
376 def __exit__(self
, type, value
, tb
):
378 Context management protocol on exit from the body of the with statement.
379 If trace is ON, it emits the recordings into stderr. Always add the
380 recordings to our session object. And close the io.StringIO object, too.
383 print(self
.getvalue(), file=sys
.stderr
)
385 print(self
.getvalue(), file=self
.session
)
389 class _BaseProcess(object, metaclass
=abc
.ABCMeta
):
390 @abc.abstractproperty
392 """Returns process PID if has been launched already."""
395 def launch(self
, executable
, args
, extra_env
):
396 """Launches new process with given executable and args."""
400 """Terminates previously launched process.."""
403 class _LocalProcess(_BaseProcess
):
404 def __init__(self
, trace_on
):
406 self
._trace
_on
= trace_on
407 self
._delayafterterminate
= 0.1
411 return self
._proc
.pid
413 def launch(self
, executable
, args
, extra_env
):
416 env
= dict(os
.environ
)
417 env
.update([kv
.split("=", 1) for kv
in extra_env
])
421 stdout
=open(os
.devnull
) if not self
._trace
_on
else None,
427 if self
._proc
.poll() is None:
428 # Terminate _proc like it does the pexpect
430 sig
for sig
in ["SIGHUP", "SIGCONT", "SIGINT"] if sig
in dir(signal
)
432 for sig
in signals_to_try
:
434 self
._proc
.send_signal(getattr(signal
, sig
))
435 time
.sleep(self
._delayafterterminate
)
436 if self
._proc
.poll() is not None:
439 pass # Windows says SIGINT is not a valid signal to send
440 self
._proc
.terminate()
441 time
.sleep(self
._delayafterterminate
)
442 if self
._proc
.poll() is not None:
445 time
.sleep(self
._delayafterterminate
)
448 return self
._proc
.poll()
450 def wait(self
, timeout
=None):
451 return self
._proc
.wait(timeout
)
454 class _RemoteProcess(_BaseProcess
):
455 def __init__(self
, install_remote
):
457 self
._install
_remote
= install_remote
463 def launch(self
, executable
, args
, extra_env
):
464 if self
._install
_remote
:
465 src_path
= executable
466 dst_path
= lldbutil
.join_remote_paths(
467 lldb
.remote_platform
.GetWorkingDirectory(), os
.path
.basename(executable
)
470 dst_file_spec
= lldb
.SBFileSpec(dst_path
, False)
471 err
= lldb
.remote_platform
.Install(
472 lldb
.SBFileSpec(src_path
, True), dst_file_spec
476 "remote_platform.Install('%s', '%s') failed: %s"
477 % (src_path
, dst_path
, err
)
480 dst_path
= executable
481 dst_file_spec
= lldb
.SBFileSpec(executable
, False)
483 launch_info
= lldb
.SBLaunchInfo(args
)
484 launch_info
.SetExecutableFile(dst_file_spec
, True)
485 launch_info
.SetWorkingDirectory(lldb
.remote_platform
.GetWorkingDirectory())
487 # Redirect stdout and stderr to /dev/null
488 launch_info
.AddSuppressFileAction(1, False, True)
489 launch_info
.AddSuppressFileAction(2, False, True)
492 launch_info
.SetEnvironmentEntries(extra_env
, True)
494 err
= lldb
.remote_platform
.Launch(launch_info
)
497 "remote_platform.Launch('%s', '%s') failed: %s" % (dst_path
, args
, err
)
499 self
._pid
= launch_info
.GetProcessID()
502 lldb
.remote_platform
.Kill(self
._pid
)
505 def getsource_if_available(obj
):
507 Return the text of the source code for an object if available. Otherwise,
508 a print representation is returned.
513 return inspect
.getsource(obj
)
518 def builder_module():
519 return get_builder(sys
.platform
)
522 class Base(unittest2
.TestCase
):
524 Abstract base for performing lldb (see TestBase) or other generic tests (see
525 BenchBase for one example). lldbtest.Base works with the test driver to
530 # The concrete subclass should override this attribute.
533 # Keep track of the old current working directory.
537 def compute_mydir(test_file
):
538 """Subclasses should call this function to correctly calculate the
539 required "mydir" attribute as follows:
541 mydir = TestBase.compute_mydir(__file__)
543 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir
544 lldb_test_src
= configuration
.test_src_root
545 if not test_file
.startswith(lldb_test_src
):
547 "Test file '%s' must reside within lldb_test_src "
548 "(which is '%s')." % (test_file
, lldb_test_src
)
550 return os
.path
.dirname(os
.path
.relpath(test_file
, start
=lldb_test_src
))
553 """Returns True if we are in trace mode (tracing detailed test execution)."""
556 def trace(self
, *args
, **kwargs
):
557 with
recording(self
, self
.TraceOn()) as sbuf
:
558 print(*args
, file=sbuf
, **kwargs
)
563 Python unittest framework class setup fixture.
564 Do current directory manipulation.
566 # Fail fast if 'mydir' attribute is not overridden.
568 cls
.mydir
= Base
.compute_mydir(sys
.modules
[cls
.__module
__].__file
__)
570 raise Exception("Subclasses must override the 'mydir' attribute.")
572 # Save old working directory.
573 cls
.oldcwd
= os
.getcwd()
575 full_dir
= os
.path
.join(configuration
.test_src_root
, cls
.mydir
)
577 print("Change dir to:", full_dir
, file=sys
.stderr
)
580 # Set platform context.
581 cls
.platformContext
= lldbplatformutil
.createPlatformContext()
584 def tearDownClass(cls
):
586 Python unittest framework class teardown fixture.
587 Do class-wide cleanup.
591 # First, let's do the platform-specific cleanup.
592 module
= builder_module()
595 # Subclass might have specific cleanup function defined.
596 if getattr(cls
, "classCleanup", None):
599 "Call class-specific cleanup function for class:",
606 exc_type
, exc_value
, exc_tb
= sys
.exc_info()
607 traceback
.print_exception(exc_type
, exc_value
, exc_tb
)
609 # Restore old working directory.
611 print("Restore dir to:", cls
.oldcwd
, file=sys
.stderr
)
614 def enableLogChannelsForCurrentTest(self
):
615 if len(lldbtest_config
.channels
) == 0:
618 # if debug channels are specified in lldbtest_config.channels,
619 # create a new set of log files for every test
620 log_basename
= self
.getLogBasenameForCurrentTest()
622 # confirm that the file is writeable
623 host_log_path
= "{}-host.log".format(log_basename
)
624 open(host_log_path
, "w").close()
625 self
.log_files
.append(host_log_path
)
627 log_enable
= "log enable -Tpn -f {} ".format(host_log_path
)
628 for channel_with_categories
in lldbtest_config
.channels
:
629 channel_then_categories
= channel_with_categories
.split(" ", 1)
630 channel
= channel_then_categories
[0]
631 if len(channel_then_categories
) > 1:
632 categories
= channel_then_categories
[1]
634 categories
= "default"
636 if channel
== "gdb-remote" and lldb
.remote_platform
is None:
637 # communicate gdb-remote categories to debugserver
638 os
.environ
["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
640 self
.ci
.HandleCommand(log_enable
+ channel_with_categories
, self
.res
)
641 if not self
.res
.Succeeded():
643 "log enable failed (check LLDB_LOG_OPTION env variable)"
646 # Communicate log path name to debugserver & lldb-server
647 # For remote debugging, these variables need to be set when starting the platform
649 if lldb
.remote_platform
is None:
650 server_log_path
= "{}-server.log".format(log_basename
)
651 open(server_log_path
, "w").close()
652 self
.log_files
.append(server_log_path
)
653 os
.environ
["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
655 # Communicate channels to lldb-server
656 os
.environ
["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config
.channels
)
658 self
.addTearDownHook(self
.disableLogChannelsForCurrentTest
)
660 def disableLogChannelsForCurrentTest(self
):
661 # close all log files that we opened
662 for channel_and_categories
in lldbtest_config
.channels
:
663 # channel format - <channel-name> [<category0> [<category1> ...]]
664 channel
= channel_and_categories
.split(" ", 1)[0]
665 self
.ci
.HandleCommand("log disable " + channel
, self
.res
)
666 if not self
.res
.Succeeded():
668 "log disable failed (check LLDB_LOG_OPTION env variable)"
671 # Retrieve the server log (if any) from the remote system. It is assumed the server log
672 # is writing to the "server.log" file in the current test directory. This can be
673 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote
675 if lldb
.remote_platform
:
676 server_log_path
= self
.getLogBasenameForCurrentTest() + "-server.log"
677 if lldb
.remote_platform
.Get(
678 lldb
.SBFileSpec("server.log"), lldb
.SBFileSpec(server_log_path
)
680 self
.log_files
.append(server_log_path
)
682 def setPlatformWorkingDir(self
):
683 if not lldb
.remote_platform
or not configuration
.lldb_platform_working_dir
:
686 components
= self
.mydir
.split(os
.path
.sep
) + [
687 str(self
.test_number
),
688 self
.getBuildDirBasename(),
690 remote_test_dir
= configuration
.lldb_platform_working_dir
692 remote_test_dir
= lldbutil
.join_remote_paths(remote_test_dir
, c
)
693 error
= lldb
.remote_platform
.MakeDirectory(
698 "making remote directory '%s': %s" % (remote_test_dir
, error
)
701 lldb
.remote_platform
.SetWorkingDirectory(remote_test_dir
)
703 # This function removes all files from the current working directory while leaving
704 # the directories in place. The cleanup is required to reduce the disk space required
705 # by the test suite while leaving the directories untouched is neccessary because
706 # sub-directories might belong to an other test
707 def clean_working_directory():
708 # TODO: Make it working on Windows when we need it for remote debugging support
709 # TODO: Replace the heuristic to remove the files with a logic what collects the
710 # list of files we have to remove during test runs.
711 shell_cmd
= lldb
.SBPlatformShellCommand("rm %s/*" % remote_test_dir
)
712 lldb
.remote_platform
.Run(shell_cmd
)
714 self
.addTearDownHook(clean_working_directory
)
716 def getSourceDir(self
):
717 """Return the full path to the current test."""
718 return os
.path
.join(configuration
.test_src_root
, self
.mydir
)
720 def getBuildDirBasename(self
):
721 return self
.__class
__.__module
__ + "." + self
.testMethodName
723 def getBuildDir(self
):
724 """Return the full path to the current test."""
726 configuration
.test_build_dir
, self
.mydir
, self
.getBuildDirBasename()
729 def makeBuildDir(self
):
730 """Create the test-specific working directory, deleting any previous
732 bdir
= self
.getBuildDir()
733 if os
.path
.isdir(bdir
):
735 lldbutil
.mkdir_p(bdir
)
737 def getBuildArtifact(self
, name
="a.out"):
738 """Return absolute path to an artifact in the test's build directory."""
739 return os
.path
.join(self
.getBuildDir(), name
)
741 def getSourcePath(self
, name
):
742 """Return absolute path to a file in the test's source directory."""
743 return os
.path
.join(self
.getSourceDir(), name
)
746 def setUpCommands(cls
):
748 # First of all, clear all settings to have clean state of global properties.
749 "settings clear -all",
750 # Disable Spotlight lookup. The testsuite creates
751 # different binaries with the same UUID, because they only
752 # differ in the debug info, which is not being hashed.
753 "settings set symbols.enable-external-lookup false",
754 # Inherit the TCC permissions from the inferior's parent.
755 "settings set target.inherit-tcc true",
756 # Kill rather than detach from the inferior if something goes wrong.
757 "settings set target.detach-on-error false",
758 # Disable fix-its by default so that incorrect expressions in tests don't
759 # pass just because Clang thinks it has a fix-it.
760 "settings set target.auto-apply-fixits false",
761 # Testsuite runs in parallel and the host can have also other load.
762 "settings set plugin.process.gdb-remote.packet-timeout 60",
763 'settings set symbols.clang-modules-cache-path "{}"'.format(
764 configuration
.lldb_module_cache_dir
766 "settings set use-color false",
769 # Set any user-overridden settings.
770 for setting
, value
in configuration
.settings
:
771 commands
.append("setting set %s %s" % (setting
, value
))
773 # Make sure that a sanitizer LLDB's environment doesn't get passed on.
776 and cls
.platformContext
.shlib_environment_var
in os
.environ
779 "settings set target.env-vars {}=".format(
780 cls
.platformContext
.shlib_environment_var
784 # Set environment variables for the inferior.
785 if lldbtest_config
.inferior_env
:
787 "settings set target.env-vars {}".format(lldbtest_config
.inferior_env
)
792 """Fixture for unittest test case setup.
794 It works with the test driver to conditionally skip tests and does other
797 # traceback.print_stack()
799 if "LIBCXX_PATH" in os
.environ
:
800 self
.libcxxPath
= os
.environ
["LIBCXX_PATH"]
802 self
.libcxxPath
= None
804 if "LLDBDAP_EXEC" in os
.environ
:
805 self
.lldbDAPExec
= os
.environ
["LLDBDAP_EXEC"]
807 self
.lldbDAPExec
= None
809 self
.lldbOption
= " ".join("-o '" + s
+ "'" for s
in self
.setUpCommands())
811 # If we spawn an lldb process for test (via pexpect), do not load the
812 # init file unless told otherwise.
813 if os
.environ
.get("NO_LLDBINIT") != "NO":
814 self
.lldbOption
+= " --no-lldbinit"
816 # Assign the test method name to self.testMethodName.
818 # For an example of the use of this attribute, look at test/types dir.
819 # There are a bunch of test cases under test/types and we don't want the
820 # module cacheing subsystem to be confused with executable name "a.out"
821 # used for all the test cases.
822 self
.testMethodName
= self
._testMethodName
824 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
825 # with it using pexpect.
827 self
.child_prompt
= "(lldb) "
828 # If the child is interacting with the embedded script interpreter,
829 # there are two exits required during tear down, first to quit the
830 # embedded script interpreter and second to quit the lldb command
832 self
.child_in_script_interpreter
= False
834 # These are for customized teardown cleanup.
836 self
.doTearDownCleanup
= False
837 # And in rare cases where there are multiple teardown cleanups.
839 self
.doTearDownCleanups
= False
841 # List of spawned subproces.Popen objects
842 self
.subprocesses
= []
844 # List of log files produced by the current test.
847 # Create the build directory.
848 # The logs are stored in the build directory, so we have to create it
849 # before creating the first log file.
852 session_file
= self
.getLogBasenameForCurrentTest() + ".log"
853 self
.log_files
.append(session_file
)
855 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered.
856 self
.session
= encoded_file
.open(session_file
, "utf-8", mode
="w")
858 # Optimistically set __errored__, __failed__, __expected__ to False
859 # initially. If the test errored/failed, the session info
860 # (self.session) is then dumped into a session specific file for
862 self
.__cleanup
_errored
__ = False
863 self
.__errored
__ = False
864 self
.__failed
__ = False
865 self
.__expected
__ = False
866 # We are also interested in unexpected success.
867 self
.__unexpected
__ = False
869 self
.__skipped
__ = False
871 # See addTearDownHook(self, hook) which allows the client to add a hook
872 # function to be run during tearDown() time.
875 # See HideStdout(self).
876 self
.sys_stdout_hidden
= False
878 if self
.platformContext
:
879 # set environment variable names for finding shared libraries
880 self
.dylibPath
= self
.platformContext
.shlib_environment_var
882 # Create the debugger instance.
883 self
.dbg
= lldb
.SBDebugger
.Create()
884 # Copy selected platform from a global instance if it exists.
885 if lldb
.selected_platform
is not None:
886 self
.dbg
.SetSelectedPlatform(lldb
.selected_platform
)
889 raise Exception("Invalid debugger instance")
891 # Retrieve the associated command interpreter instance.
892 self
.ci
= self
.dbg
.GetCommandInterpreter()
894 raise Exception("Could not get the command interpreter")
896 # And the result object.
897 self
.res
= lldb
.SBCommandReturnObject()
899 self
.setPlatformWorkingDir()
900 self
.enableLogChannelsForCurrentTest()
903 self
.framework_dir
= None
904 self
.darwinWithFramework
= False
906 if sys
.platform
.startswith("darwin") and configuration
.lldb_framework_path
:
907 framework
= configuration
.lldb_framework_path
908 lib
= os
.path
.join(framework
, "LLDB")
909 if os
.path
.exists(lib
):
910 self
.framework_dir
= os
.path
.dirname(framework
)
912 self
.darwinWithFramework
= self
.platformIsDarwin()
914 def setAsync(self
, value
):
915 """Sets async mode to True/False and ensures it is reset after the testcase completes."""
916 old_async
= self
.dbg
.GetAsync()
917 self
.dbg
.SetAsync(value
)
918 self
.addTearDownHook(lambda: self
.dbg
.SetAsync(old_async
))
920 def cleanupSubprocesses(self
):
921 # Terminate subprocesses in reverse order from how they were created.
922 for p
in reversed(self
.subprocesses
):
925 del self
.subprocesses
[:]
927 def spawnSubprocess(self
, executable
, args
=[], extra_env
=None, install_remote
=True):
928 """Creates a subprocess.Popen object with the specified executable and arguments,
929 saves it in self.subprocesses, and returns the object.
932 _RemoteProcess(install_remote
)
933 if lldb
.remote_platform
934 else _LocalProcess(self
.TraceOn())
936 proc
.launch(executable
, args
, extra_env
=extra_env
)
937 self
.subprocesses
.append(proc
)
940 def HideStdout(self
):
941 """Hide output to stdout from the user.
943 During test execution, there might be cases where we don't want to show the
944 standard output to the user. For example,
946 self.runCmd(r'''sc print("\n\n\tHello!\n")''')
948 tests whether command abbreviation for 'script' works or not. There is no
949 need to show the 'Hello' output to the user as long as the 'script' command
950 succeeds and we are not in TraceOn() mode (see the '-t' option).
952 In this case, the test method calls self.HideStdout(self) to redirect the
953 sys.stdout to a null device, and restores the sys.stdout upon teardown.
955 Note that you should only call this method at most once during a test case
956 execution. Any subsequent call has no effect at all."""
957 if self
.sys_stdout_hidden
:
960 self
.sys_stdout_hidden
= True
961 old_stdout
= sys
.stdout
962 sys
.stdout
= open(os
.devnull
, "w")
964 def restore_stdout():
965 sys
.stdout
= old_stdout
967 self
.addTearDownHook(restore_stdout
)
969 # =======================================================================
970 # Methods for customized teardown cleanups as well as execution of hooks.
971 # =======================================================================
973 def setTearDownCleanup(self
, dictionary
=None):
974 """Register a cleanup action at tearDown() time with a dictionary"""
975 self
.dict = dictionary
976 self
.doTearDownCleanup
= True
978 def addTearDownCleanup(self
, dictionary
):
979 """Add a cleanup action at tearDown() time with a dictionary"""
980 self
.dicts
.append(dictionary
)
981 self
.doTearDownCleanups
= True
983 def addTearDownHook(self
, hook
):
985 Add a function to be run during tearDown() time.
987 Hooks are executed in a first come first serve manner.
990 with
recording(self
, traceAlways
) as sbuf
:
991 print("Adding tearDown hook:", getsource_if_available(hook
), file=sbuf
)
992 self
.hooks
.append(hook
)
996 def deletePexpectChild(self
):
997 # This is for the case of directly spawning 'lldb' and interacting with it
999 if self
.child
and self
.child
.isalive():
1002 with
recording(self
, traceAlways
) as sbuf
:
1003 print("tearing down the child process....", file=sbuf
)
1005 if self
.child_in_script_interpreter
:
1006 self
.child
.sendline("quit()")
1007 self
.child
.expect_exact(self
.child_prompt
)
1008 self
.child
.sendline("settings set interpreter.prompt-on-quit false")
1009 self
.child
.sendline("quit")
1010 self
.child
.expect(pexpect
.EOF
)
1011 except (ValueError, pexpect
.ExceptionPexpect
):
1012 # child is already terminated
1014 except OSError as exception
:
1017 if exception
.errno
!= errno
.EIO
:
1020 # child is already terminated
1022 # Give it one final blow to make sure the child is terminated.
1026 """Fixture for unittest test case teardown."""
1027 self
.deletePexpectChild()
1029 # Check and run any hook functions.
1030 for hook
in reversed(self
.hooks
):
1031 with
recording(self
, traceAlways
) as sbuf
:
1033 "Executing tearDown hook:", getsource_if_available(hook
), file=sbuf
1035 if funcutils
.requires_self(hook
):
1038 hook() # try the plain call and hope it works
1042 # Perform registered teardown cleanup.
1043 if doCleanup
and self
.doTearDownCleanup
:
1044 self
.cleanup(dictionary
=self
.dict)
1046 # In rare cases where there are multiple teardown cleanups added.
1047 if doCleanup
and self
.doTearDownCleanups
:
1049 for dict in reversed(self
.dicts
):
1050 self
.cleanup(dictionary
=dict)
1052 # Remove subprocesses created by the test.
1053 self
.cleanupSubprocesses()
1055 # This must be the last statement, otherwise teardown hooks or other
1056 # lines might depend on this still being active.
1057 lldb
.SBDebugger
.Destroy(self
.dbg
)
1060 # All modules should be orphaned now so that they can be cleared from
1061 # the shared module cache.
1062 lldb
.SBModule
.GarbageCollectAllocatedModules()
1064 # Assert that the global module cache is empty.
1065 self
.assertEqual(lldb
.SBModule
.GetNumberAllocatedModules(), 0)
1067 # =========================================================
1068 # Various callbacks to allow introspection of test progress
1069 # =========================================================
1071 def markError(self
):
1072 """Callback invoked when an error (unexpected exception) errored."""
1073 self
.__errored
__ = True
1074 with
recording(self
, False) as sbuf
:
1075 # False because there's no need to write "ERROR" to the stderr twice.
1076 # Once by the Python unittest framework, and a second time by us.
1077 print("ERROR", file=sbuf
)
1079 def markCleanupError(self
):
1080 """Callback invoked when an error occurs while a test is cleaning up."""
1081 self
.__cleanup
_errored
__ = True
1082 with
recording(self
, False) as sbuf
:
1083 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice.
1084 # Once by the Python unittest framework, and a second time by us.
1085 print("CLEANUP_ERROR", file=sbuf
)
1087 def markFailure(self
):
1088 """Callback invoked when a failure (test assertion failure) occurred."""
1089 self
.__failed
__ = True
1090 with
recording(self
, False) as sbuf
:
1091 # False because there's no need to write "FAIL" to the stderr twice.
1092 # Once by the Python unittest framework, and a second time by us.
1093 print("FAIL", file=sbuf
)
1095 def markExpectedFailure(self
, err
, bugnumber
):
1096 """Callback invoked when an expected failure/error occurred."""
1097 self
.__expected
__ = True
1098 with
recording(self
, False) as sbuf
:
1099 # False because there's no need to write "expected failure" to the
1101 # Once by the Python unittest framework, and a second time by us.
1102 if bugnumber
is None:
1103 print("expected failure", file=sbuf
)
1105 print("expected failure (problem id:" + str(bugnumber
) + ")", file=sbuf
)
1107 def markSkippedTest(self
):
1108 """Callback invoked when a test is skipped."""
1109 self
.__skipped
__ = True
1110 with
recording(self
, False) as sbuf
:
1111 # False because there's no need to write "skipped test" to the
1113 # Once by the Python unittest framework, and a second time by us.
1114 print("skipped test", file=sbuf
)
1116 def markUnexpectedSuccess(self
, bugnumber
):
1117 """Callback invoked when an unexpected success occurred."""
1118 self
.__unexpected
__ = True
1119 with
recording(self
, False) as sbuf
:
1120 # False because there's no need to write "unexpected success" to the
1122 # Once by the Python unittest framework, and a second time by us.
1123 if bugnumber
is None:
1124 print("unexpected success", file=sbuf
)
1127 "unexpected success (problem id:" + str(bugnumber
) + ")", file=sbuf
1130 def getRerunArgs(self
):
1131 return " -f %s.%s" % (self
.__class
__.__name
__, self
._testMethodName
)
1133 def getLogBasenameForCurrentTest(self
, prefix
="Incomplete"):
1135 returns a partial path that can be used as the beginning of the name of multiple
1136 log files pertaining to this test
1138 return os
.path
.join(self
.getBuildDir(), prefix
)
1140 def dumpSessionInfo(self
):
1142 Dump the debugger interactions leading to a test error/failure. This
1143 allows for more convenient postmortem analysis.
1145 See also LLDBTestResult (dotest.py) which is a singlton class derived
1146 from TextTestResult and overwrites addError, addFailure, and
1147 addExpectedFailure methods to allow us to to mark the test instance as
1151 # We are here because self.tearDown() detected that this test instance
1152 # either errored or failed. The lldb.test_result singleton contains
1153 # two lists (errors and failures) which get populated by the unittest
1154 # framework. Look over there for stack trace information.
1156 # The lists contain 2-tuples of TestCase instances and strings holding
1157 # formatted tracebacks.
1159 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1161 # output tracebacks into session
1163 if self
.__errored
__:
1164 pairs
= configuration
.test_result
.errors
1166 elif self
.__cleanup
_errored
__:
1167 pairs
= configuration
.test_result
.cleanup_errors
1168 prefix
= "CleanupError"
1169 elif self
.__failed
__:
1170 pairs
= configuration
.test_result
.failures
1172 elif self
.__expected
__:
1173 pairs
= configuration
.test_result
.expectedFailures
1174 prefix
= "ExpectedFailure"
1175 elif self
.__skipped
__:
1176 prefix
= "SkippedTest"
1177 elif self
.__unexpected
__:
1178 prefix
= "UnexpectedSuccess"
1182 if not self
.__unexpected
__ and not self
.__skipped
__:
1183 for test
, traceback
in pairs
:
1185 print(traceback
, file=self
.session
)
1190 "Session info generated @",
1191 datetime
.datetime
.now().ctime(),
1194 self
.session
.close()
1197 # process the log files
1198 if prefix
!= "Success" or lldbtest_config
.log_success
:
1199 # keep all log files, rename them to include prefix
1200 src_log_basename
= self
.getLogBasenameForCurrentTest()
1201 dst_log_basename
= self
.getLogBasenameForCurrentTest(prefix
)
1202 for src
in self
.log_files
:
1203 if os
.path
.isfile(src
):
1204 dst
= src
.replace(src_log_basename
, dst_log_basename
)
1205 if os
.name
== "nt" and os
.path
.isfile(dst
):
1206 # On Windows, renaming a -> b will throw an exception if
1207 # b exists. On non-Windows platforms it silently
1208 # replaces the destination. Ultimately this means that
1209 # atomic renames are not guaranteed to be possible on
1210 # Windows, but we need this to work anyway, so just
1211 # remove the destination first if it already exists.
1214 lldbutil
.mkdir_p(os
.path
.dirname(dst
))
1217 # success! (and we don't want log files) delete log files
1218 for log_file
in self
.log_files
:
1219 if os
.path
.isfile(log_file
):
1220 remove_file(log_file
)
1222 # ====================================================
1223 # Config. methods supported through a plugin interface
1224 # (enables reading of the current test configuration)
1225 # ====================================================
1228 """Returns true if the architecture is MIPS."""
1229 arch
= self
.getArchitecture()
1230 if re
.match("mips", arch
):
1234 def isPPC64le(self
):
1235 """Returns true if the architecture is PPC64LE."""
1236 arch
= self
.getArchitecture()
1237 if re
.match("powerpc64le", arch
):
1241 def getCPUInfo(self
):
1242 triple
= self
.dbg
.GetSelectedPlatform().GetTriple()
1244 # TODO other platforms, please implement this function
1245 if not re
.match(".*-.*-linux", triple
):
1248 # Need to do something different for non-Linux/Android targets
1249 cpuinfo_path
= self
.getBuildArtifact("cpuinfo")
1250 if configuration
.lldb_platform_name
:
1251 self
.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path
)
1253 cpuinfo_path
= "/proc/cpuinfo"
1256 with
open(cpuinfo_path
, "r") as f
:
1263 def isAArch64(self
):
1264 """Returns true if the architecture is AArch64."""
1265 arch
= self
.getArchitecture().lower()
1266 return arch
in ["aarch64", "arm64", "arm64e"]
1268 def isAArch64SVE(self
):
1269 return self
.isAArch64() and "sve" in self
.getCPUInfo()
1271 def isAArch64SME(self
):
1272 return self
.isAArch64() and "sme" in self
.getCPUInfo()
1274 def isAArch64SME2(self
):
1275 # If you have sme2, you also have sme.
1276 return self
.isAArch64() and "sme2" in self
.getCPUInfo()
1278 def isAArch64SMEFA64(self
):
1279 # smefa64 allows the use of the full A64 instruction set in streaming
1280 # mode. This is required by certain test programs to setup register
1282 cpuinfo
= self
.getCPUInfo()
1283 return self
.isAArch64() and "sme" in cpuinfo
and "smefa64" in cpuinfo
1285 def isAArch64MTE(self
):
1286 return self
.isAArch64() and "mte" in self
.getCPUInfo()
1288 def isAArch64PAuth(self
):
1289 if self
.getArchitecture() == "arm64e":
1291 return self
.isAArch64() and "paca" in self
.getCPUInfo()
1293 def isAArch64Windows(self
):
1294 """Returns true if the architecture is AArch64 and platform windows."""
1295 if self
.getPlatform() == "windows":
1296 arch
= self
.getArchitecture().lower()
1297 return arch
in ["aarch64", "arm64", "arm64e"]
1300 def getArchitecture(self
):
1301 """Returns the architecture in effect the test suite is running with."""
1302 module
= builder_module()
1303 arch
= module
.getArchitecture()
1306 if arch
in ["armv7l", "armv8l"]:
1310 def getLldbArchitecture(self
):
1311 """Returns the architecture of the lldb binary."""
1312 if not hasattr(self
, "lldbArchitecture"):
1313 # These two target settings prevent lldb from doing setup that does
1314 # nothing but slow down the end goal of printing the architecture.
1316 lldbtest_config
.lldbExec
,
1320 "settings set target.preload-symbols false",
1322 "settings set target.load-script-from-symbol-file false",
1324 "file " + lldbtest_config
.lldbExec
,
1327 output
= check_output(command
)
1328 str = output
.decode()
1330 for line
in str.splitlines():
1331 m
= re
.search(r
"Current executable set to '.*' \((.*)\)\.", line
)
1333 self
.lldbArchitecture
= m
.group(1)
1336 return self
.lldbArchitecture
1338 def getCompiler(self
):
1339 """Returns the compiler in effect the test suite is running with."""
1340 module
= builder_module()
1341 return module
.getCompiler()
1343 def getCompilerBinary(self
):
1344 """Returns the compiler binary the test suite is running with."""
1345 return self
.getCompiler().split()[0]
1347 def getCompilerVersion(self
):
1348 """Returns a string that represents the compiler version.
1349 Supports: llvm, clang.
1351 compiler
= self
.getCompilerBinary()
1352 version_output
= check_output([compiler
, "--version"], errors
="replace")
1353 m
= re
.search("version ([0-9.]+)", version_output
)
1358 def getDwarfVersion(self
):
1359 """Returns the dwarf version generated by clang or '0'."""
1360 if configuration
.dwarf_version
:
1361 return str(configuration
.dwarf_version
)
1362 if "clang" in self
.getCompiler():
1364 triple
= builder_module().getTriple(self
.getArchitecture())
1365 target
= ["-target", triple
] if triple
else []
1366 driver_output
= check_output(
1367 [self
.getCompiler()] + target
+ "-g -c -x c - -o - -###".split(),
1370 driver_output
= driver_output
.decode("utf-8")
1371 for line
in driver_output
.split(os
.linesep
):
1372 m
= re
.search("dwarf-version=([0-9])", line
)
1375 except CalledProcessError
:
1379 def platformIsDarwin(self
):
1380 """Returns true if the OS triple for the selected platform is any valid apple OS"""
1381 return lldbplatformutil
.platformIsDarwin()
1383 def hasDarwinFramework(self
):
1384 return self
.darwinWithFramework
1386 def getPlatform(self
):
1387 """Returns the target platform the test suite is running on."""
1388 return lldbplatformutil
.getPlatform()
1390 def isIntelCompiler(self
):
1391 """Returns true if using an Intel (ICC) compiler, false otherwise."""
1392 return any([x
in self
.getCompiler() for x
in ["icc", "icpc", "icl"]])
1394 def expectedCompilerVersion(self
, compiler_version
):
1395 """Returns True iff compiler_version[1] matches the current compiler version.
1396 Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1397 Any operator other than the following defaults to an equality test:
1398 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1400 If the current compiler version cannot be determined, we assume it is close to the top
1401 of trunk, so any less-than or equal-to comparisons will return False, and any
1402 greater-than or not-equal-to comparisons will return True.
1404 if compiler_version
is None:
1406 operator
= str(compiler_version
[0])
1407 version
= compiler_version
[1]
1412 test_compiler_version
= self
.getCompilerVersion()
1413 if test_compiler_version
== "unknown":
1414 # Assume the compiler version is at or near the top of trunk.
1415 return operator
in [">", ">=", "!", "!=", "not"]
1418 return LooseVersion(test_compiler_version
) > LooseVersion(version
)
1419 if operator
== ">=" or operator
== "=>":
1420 return LooseVersion(test_compiler_version
) >= LooseVersion(version
)
1422 return LooseVersion(test_compiler_version
) < LooseVersion(version
)
1423 if operator
== "<=" or operator
== "=<":
1424 return LooseVersion(test_compiler_version
) <= LooseVersion(version
)
1425 if operator
== "!=" or operator
== "!" or operator
== "not":
1426 return str(version
) not in str(test_compiler_version
)
1427 return str(version
) in str(test_compiler_version
)
1429 def expectedCompiler(self
, compilers
):
1430 """Returns True iff any element of compilers is a sub-string of the current compiler."""
1431 if compilers
is None:
1434 for compiler
in compilers
:
1435 if compiler
in self
.getCompiler():
1440 def expectedArch(self
, archs
):
1441 """Returns True iff any element of archs is a sub-string of the current architecture."""
1446 if arch
in self
.getArchitecture():
1451 def getRunOptions(self
):
1452 """Command line option for -A and -C to run this test again, called from
1453 self.dumpSessionInfo()."""
1454 arch
= self
.getArchitecture()
1455 comp
= self
.getCompiler()
1458 option_str
= "-A " + arch
1460 option_str
+= " -C " + comp
1463 def getDebugInfo(self
):
1464 method
= getattr(self
, self
.testMethodName
)
1465 return getattr(method
, "debug_info", None)
1475 """Platform specific way to build binaries."""
1476 if not architecture
and configuration
.arch
:
1477 architecture
= configuration
.arch
1479 if debug_info
is None:
1480 debug_info
= self
.getDebugInfo()
1482 dictionary
= lldbplatformutil
.finalize_build_dictionary(dictionary
)
1484 testdir
= self
.mydir
1485 testname
= self
.getBuildDirBasename()
1487 module
= builder_module()
1488 command
= builder_module().getBuildCommand(
1498 raise Exception("Don't know how to build binary")
1500 self
.runBuildCommand(command
)
1502 def runBuildCommand(self
, command
):
1503 self
.trace(seven
.join_for_shell(command
))
1505 output
= check_output(command
, stderr
=STDOUT
, errors
="replace")
1506 except CalledProcessError
as cpe
:
1507 raise build_exception
.BuildError(cpe
)
1510 # ==================================================
1511 # Build methods supported through a plugin interface
1512 # ==================================================
1514 def getstdlibFlag(self
):
1515 """Returns the proper -stdlib flag, or empty if not required."""
1517 self
.platformIsDarwin()
1518 or self
.getPlatform() == "freebsd"
1519 or self
.getPlatform() == "openbsd"
1521 stdlibflag
= "-stdlib=libc++"
1522 else: # this includes NetBSD
1526 def getstdFlag(self
):
1527 """Returns the proper stdflag."""
1528 if "gcc" in self
.getCompiler() and "4.6" in self
.getCompilerVersion():
1529 stdflag
= "-std=c++0x"
1531 stdflag
= "-std=c++11"
1534 def buildDriver(self
, sources
, exe_name
):
1535 """Platform-specific way to build a program that links with LLDB (via the liblldb.so
1538 stdflag
= self
.getstdFlag()
1539 stdlibflag
= self
.getstdlibFlag()
1541 lib_dir
= configuration
.lldb_libs_dir
1542 if self
.hasDarwinFramework():
1544 "CXX_SOURCES": sources
,
1546 "CFLAGS_EXTRAS": "%s %s" % (stdflag
, stdlibflag
),
1547 "FRAMEWORK_INCLUDES": "-F%s" % self
.framework_dir
,
1548 "LD_EXTRAS": "%s -Wl,-rpath,%s" % (self
.lib_lldb
, self
.framework_dir
),
1550 elif sys
.platform
.startswith("win"):
1552 "CXX_SOURCES": sources
,
1554 "CFLAGS_EXTRAS": "%s %s -I%s"
1558 os
.path
.join(os
.environ
["LLDB_SRC"], "include"),
1560 "LD_EXTRAS": "-L%s -lliblldb" % lib_dir
,
1564 "CXX_SOURCES": sources
,
1566 "CFLAGS_EXTRAS": "%s %s -I%s"
1570 os
.path
.join(os
.environ
["LLDB_SRC"], "include"),
1572 "LD_EXTRAS": "-L%s -llldb -Wl,-rpath,%s" % (lib_dir
, lib_dir
),
1575 print("Building LLDB Driver (%s) from sources %s" % (exe_name
, sources
))
1577 self
.build(dictionary
=d
)
1579 def buildLibrary(self
, sources
, lib_name
):
1580 """Platform specific way to build a default library."""
1582 stdflag
= self
.getstdFlag()
1584 lib_dir
= configuration
.lldb_libs_dir
1585 if self
.hasDarwinFramework():
1587 "DYLIB_CXX_SOURCES": sources
,
1588 "DYLIB_NAME": lib_name
,
1589 "CFLAGS_EXTRAS": "%s -stdlib=libc++" % stdflag
,
1590 "FRAMEWORK_INCLUDES": "-F%s" % self
.framework_dir
,
1591 "LD_EXTRAS": "%s -Wl,-rpath,%s -dynamiclib"
1592 % (self
.lib_lldb
, self
.framework_dir
),
1594 elif self
.getPlatform() == "windows":
1596 "DYLIB_CXX_SOURCES": sources
,
1597 "DYLIB_NAME": lib_name
,
1598 "CFLAGS_EXTRAS": "%s -I%s "
1599 % (stdflag
, os
.path
.join(os
.environ
["LLDB_SRC"], "include")),
1600 "LD_EXTRAS": "-shared -l%s\liblldb.lib" % lib_dir
,
1604 "DYLIB_CXX_SOURCES": sources
,
1605 "DYLIB_NAME": lib_name
,
1606 "CFLAGS_EXTRAS": "%s -I%s -fPIC"
1607 % (stdflag
, os
.path
.join(os
.environ
["LLDB_SRC"], "include")),
1608 "LD_EXTRAS": "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir
, lib_dir
),
1611 print("Building LLDB Library (%s) from sources %s" % (lib_name
, sources
))
1613 self
.build(dictionary
=d
)
1615 def buildProgram(self
, sources
, exe_name
):
1616 """Platform specific way to build an executable from C/C++ sources."""
1617 d
= {"CXX_SOURCES": sources
, "EXE": exe_name
}
1618 self
.build(dictionary
=d
)
1620 def signBinary(self
, binary_path
):
1621 if sys
.platform
.startswith("darwin"):
1622 codesign_cmd
= 'codesign --force --sign "%s" %s' % (
1623 lldbtest_config
.codesign_identity
,
1626 call(codesign_cmd
, shell
=True)
1628 def findBuiltClang(self
):
1629 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
1631 "llvm-build/Release+Asserts/x86_64/bin/clang",
1632 "llvm-build/Debug+Asserts/x86_64/bin/clang",
1633 "llvm-build/Release/x86_64/bin/clang",
1634 "llvm-build/Debug/x86_64/bin/clang",
1636 lldb_root_path
= os
.path
.join(os
.path
.dirname(__file__
), "..", "..", "..", "..")
1637 for p
in paths_to_try
:
1638 path
= os
.path
.join(lldb_root_path
, p
)
1639 if os
.path
.exists(path
):
1642 # Tries to find clang at the same folder as the lldb
1643 lldb_dir
= os
.path
.dirname(lldbtest_config
.lldbExec
)
1644 path
= shutil
.which("clang", path
=lldb_dir
)
1645 if path
is not None:
1648 return os
.environ
["CC"]
1650 def yaml2obj(self
, yaml_path
, obj_path
, max_size
=None):
1652 Create an object file at the given path from a yaml file.
1654 Throws subprocess.CalledProcessError if the object could not be created.
1656 yaml2obj_bin
= configuration
.get_yaml2obj_path()
1657 if not yaml2obj_bin
:
1658 self
.assertTrue(False, "No valid yaml2obj executable specified")
1659 command
= [yaml2obj_bin
, "-o=%s" % obj_path
, yaml_path
]
1660 if max_size
is not None:
1661 command
+= ["--max-size=%d" % max_size
]
1662 self
.runBuildCommand(command
)
1664 def cleanup(self
, dictionary
=None):
1665 """Platform specific way to do cleanup after build."""
1666 module
= builder_module()
1667 if not module
.cleanup(dictionary
):
1669 "Don't know how to do cleanup with dictionary: " + dictionary
1672 def invoke(self
, obj
, name
, trace
=False):
1673 """Use reflection to call a method dynamically with no argument."""
1674 trace
= True if traceAlways
else trace
1676 method
= getattr(obj
, name
)
1680 inspect
.ismethod(method
), name
+ "is a method name of object: " + str(obj
)
1683 with
recording(self
, trace
) as sbuf
:
1684 print(str(method
) + ":", result
, file=sbuf
)
1687 def getLLDBLibraryEnvVal(self
):
1688 """Returns the path that the OS-specific library search environment variable
1689 (self.dylibPath) should be set to in order for a program to find the LLDB
1690 library. If an environment variable named self.dylibPath is already set,
1691 the new path is appended to it and returned.
1693 existing_library_path
= (
1694 os
.environ
[self
.dylibPath
] if self
.dylibPath
in os
.environ
else None
1696 if existing_library_path
:
1697 return "%s:%s" % (existing_library_path
, configuration
.lldb_libs_dir
)
1698 if sys
.platform
.startswith("darwin") and configuration
.lldb_framework_path
:
1699 return configuration
.lldb_framework_path
1700 return configuration
.lldb_libs_dir
1702 def getLibcPlusPlusLibs(self
):
1703 if self
.getPlatform() in ("freebsd", "linux", "netbsd", "openbsd"):
1704 return ["libc++.so.1"]
1706 return ["libc++.1.dylib", "libc++abi."]
1708 def run_platform_command(self
, cmd
):
1709 platform
= self
.dbg
.GetSelectedPlatform()
1710 shell_command
= lldb
.SBPlatformShellCommand(cmd
)
1711 err
= platform
.Run(shell_command
)
1712 return (err
, shell_command
.GetStatus(), shell_command
.GetOutput())
1714 def get_stats(self
, options
=None):
1716 Get the output of the "statistics dump" with optional extra options
1717 and return the JSON as a python dictionary.
1719 return_obj
= lldb
.SBCommandReturnObject()
1720 command
= "statistics dump "
1721 if options
is not None:
1723 self
.ci
.HandleCommand(command
, return_obj
, False)
1724 metrics_json
= return_obj
.GetOutput()
1725 return json
.loads(metrics_json
)
1728 # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
1729 # We change the test methods to create a new test method for each test for each debug info we are
1730 # testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
1731 # the new test method we remove the old method at the same time. This functionality can be
1732 # supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test
1733 # level by using the decorator @no_debug_info_test.
1736 class LLDBTestCaseFactory(type):
1737 def __new__(cls
, name
, bases
, attrs
):
1738 original_testcase
= super(LLDBTestCaseFactory
, cls
).__new
__(
1739 cls
, name
, bases
, attrs
1741 if original_testcase
.NO_DEBUG_INFO_TESTCASE
:
1742 return original_testcase
1745 for attrname
, attrvalue
in attrs
.items():
1746 if attrname
.startswith("test") and not getattr(
1747 attrvalue
, "__no_debug_info_test__", False
1749 # If any debug info categories were explicitly tagged, assume that list to be
1750 # authoritative. If none were specified, try with all debug
1752 all_dbginfo_categories
= set(
1753 test_categories
.debug_info_categories
.keys()
1756 set(getattr(attrvalue
, "categories", [])) & all_dbginfo_categories
1761 for category
, can_replicate
in test_categories
.debug_info_categories
.items()
1765 for cat
in categories
:
1767 @decorators.add_test_categories([cat
])
1769 def test_method(self
, attrvalue
=attrvalue
):
1770 return attrvalue(self
)
1772 method_name
= attrname
+ "_" + cat
1773 test_method
.__name
__ = method_name
1774 test_method
.debug_info
= cat
1775 newattrs
[method_name
] = test_method
1778 newattrs
[attrname
] = attrvalue
1779 return super(LLDBTestCaseFactory
, cls
).__new
__(cls
, name
, bases
, newattrs
)
1782 # Setup the metaclass for this class to change the list of the test
1783 # methods when a new class is loaded
1786 class TestBase(Base
, metaclass
=LLDBTestCaseFactory
):
1788 This abstract base class is meant to be subclassed. It provides default
1789 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1792 Important things for test class writers:
1794 - The setUp method sets up things to facilitate subsequent interactions
1795 with the debugger as part of the test. These include:
1796 - populate the test method name
1797 - create/get a debugger set with synchronous mode (self.dbg)
1798 - get the command interpreter from with the debugger (self.ci)
1799 - create a result object for use with the command interpreter
1803 - The tearDown method tries to perform some necessary cleanup on behalf
1804 of the test to return the debugger to a good state for the next test.
1806 - execute any tearDown hooks registered by the test method with
1807 TestBase.addTearDownHook(); examples can be found in
1808 settings/TestSettings.py
1809 - kill the inferior process associated with each target, if any,
1810 and, then delete the target from the debugger's target list
1811 - perform build cleanup before running the next test method in the
1812 same test class; examples of registering for this service can be
1813 found in types/TestIntegerTypes.py with the call:
1814 - self.setTearDownCleanup(dictionary=d)
1816 - Similarly setUpClass and tearDownClass perform classwise setup and
1817 teardown fixtures. The tearDownClass method invokes a default build
1818 cleanup for the entire test class; also, subclasses can implement the
1819 classmethod classCleanup(cls) to perform special class cleanup action.
1821 - The instance methods runCmd and expect are used heavily by existing
1822 test cases to send a command to the command interpreter and to perform
1823 string/pattern matching on the output of such command execution. The
1824 expect method also provides a mode to peform string/pattern matching
1825 without running a command.
1827 - The build method is used to build the binaries used during a
1828 particular test scenario. A plugin should be provided for the
1829 sys.platform running the test suite. The Mac OS X implementation is
1830 located in builders/darwin.py.
1833 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the
1834 # test multiple times with various debug info types.
1835 NO_DEBUG_INFO_TESTCASE
= False
1837 # Maximum allowed attempts when launching the inferior process.
1838 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1841 # Time to wait before the next launching attempt in second(s).
1842 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1843 timeWaitNextLaunch
= 1.0
1845 def generateSource(self
, source
):
1846 template
= source
+ ".template"
1847 temp
= os
.path
.join(self
.getSourceDir(), template
)
1848 with
open(temp
, "r") as f
:
1851 public_api_dir
= os
.path
.join(os
.environ
["LLDB_SRC"], "include", "lldb", "API")
1853 # Look under the include/lldb/API directory and add #include statements
1854 # for all the SB API headers.
1855 public_headers
= os
.listdir(public_api_dir
)
1856 # For different platforms, the include statement can vary.
1857 if self
.hasDarwinFramework():
1858 include_stmt
= "'#include <%s>' % os.path.join('LLDB', header)"
1861 "'#include <%s>' % os.path.join(r'" + public_api_dir
+ "', header)"
1865 for header
in public_headers
1866 if (header
.startswith("SB") and header
.endswith(".h"))
1868 includes
= "\n".join(list)
1869 new_content
= content
.replace("%include_SB_APIs%", includes
)
1870 new_content
= new_content
.replace("%SOURCE_DIR%", self
.getSourceDir())
1871 src
= os
.path
.join(self
.getBuildDir(), source
)
1872 with
open(src
, "w") as f
:
1873 f
.write(new_content
)
1875 self
.addTearDownHook(lambda: os
.remove(src
))
1878 # Works with the test driver to conditionally skip tests via
1882 for s
in self
.setUpCommands():
1885 if "LLDB_MAX_LAUNCH_COUNT" in os
.environ
:
1886 self
.maxLaunchCount
= int(os
.environ
["LLDB_MAX_LAUNCH_COUNT"])
1888 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os
.environ
:
1889 self
.timeWaitNextLaunch
= float(os
.environ
["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1891 # We want our debugger to be synchronous.
1892 self
.dbg
.SetAsync(False)
1894 # Retrieve the associated command interpreter instance.
1895 self
.ci
= self
.dbg
.GetCommandInterpreter()
1897 raise Exception("Could not get the command interpreter")
1899 # And the result object.
1900 self
.res
= lldb
.SBCommandReturnObject()
1902 def registerSharedLibrariesWithTarget(self
, target
, shlibs
):
1903 """If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
1905 Any modules in the target that have their remote install file specification set will
1906 get uploaded to the remote host. This function registers the local copies of the
1907 shared libraries with the target and sets their remote install locations so they will
1908 be uploaded when the target is run.
1910 if not shlibs
or not self
.platformContext
:
1913 shlib_environment_var
= self
.platformContext
.shlib_environment_var
1914 shlib_prefix
= self
.platformContext
.shlib_prefix
1915 shlib_extension
= "." + self
.platformContext
.shlib_extension
1918 # Add any shared libraries to our target if remote so they get
1919 # uploaded into the working directory on the remote side
1921 # The path can be a full path to a shared library, or a make file name like "Foo" for
1922 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
1923 # basename like "libFoo.so". So figure out which one it is and resolve the local copy
1924 # of the shared library accordingly
1925 if os
.path
.isfile(name
):
1926 local_shlib_path
= (
1927 name
# name is the full path to the local shared library
1930 # Check relative names
1931 local_shlib_path
= os
.path
.join(
1932 self
.getBuildDir(), shlib_prefix
+ name
+ shlib_extension
1934 if not os
.path
.exists(local_shlib_path
):
1935 local_shlib_path
= os
.path
.join(
1936 self
.getBuildDir(), name
+ shlib_extension
1938 if not os
.path
.exists(local_shlib_path
):
1939 local_shlib_path
= os
.path
.join(self
.getBuildDir(), name
)
1941 # Make sure we found the local shared library in the above code
1942 self
.assertTrue(os
.path
.exists(local_shlib_path
))
1944 # Add the shared library to our target
1945 shlib_module
= target
.AddModule(local_shlib_path
, None, None, None)
1946 if lldb
.remote_platform
:
1947 # We must set the remote install location if we want the shared library
1948 # to get uploaded to the remote target
1949 remote_shlib_path
= lldbutil
.append_to_process_working_directory(
1950 self
, os
.path
.basename(local_shlib_path
)
1952 shlib_module
.SetRemoteInstallFileSpec(
1953 lldb
.SBFileSpec(remote_shlib_path
, False)
1955 dir_to_add
= self
.get_process_working_directory()
1957 dir_to_add
= os
.path
.dirname(local_shlib_path
)
1959 if dir_to_add
not in dirs
:
1960 dirs
.append(dir_to_add
)
1962 env_value
= self
.platformContext
.shlib_path_separator
.join(dirs
)
1963 return ["%s=%s" % (shlib_environment_var
, env_value
)]
1965 def registerSanitizerLibrariesWithTarget(self
, target
):
1967 for m
in target
.module_iter():
1968 libspec
= m
.GetFileSpec()
1969 if "clang_rt" in libspec
.GetFilename():
1971 os
.path
.join(libspec
.GetDirectory(), libspec
.GetFilename())
1973 return self
.registerSharedLibrariesWithTarget(target
, runtimes
)
1975 # utility methods that tests can use to access the current objects
1978 raise Exception("Invalid debugger instance")
1979 return self
.dbg
.GetSelectedTarget()
1983 raise Exception("Invalid debugger instance")
1984 return self
.dbg
.GetSelectedTarget().GetProcess()
1988 raise Exception("Invalid debugger instance")
1989 return self
.dbg
.GetSelectedTarget().GetProcess().GetSelectedThread()
1993 raise Exception("Invalid debugger instance")
1995 self
.dbg
.GetSelectedTarget()
1997 .GetSelectedThread()
2001 def get_process_working_directory(self
):
2002 """Get the working directory that should be used when launching processes for local or remote processes."""
2003 if lldb
.remote_platform
:
2004 # Remote tests set the platform working directory up in
2006 return lldb
.remote_platform
.GetWorkingDirectory()
2008 # local tests change directory into each test subdirectory
2009 return self
.getBuildDir()
2012 # Ensure all the references to SB objects have gone away so that we can
2013 # be sure that all test-specific resources have been freed before we
2014 # attempt to delete the targets.
2017 # Delete the target(s) from the debugger as a general cleanup step.
2018 # This includes terminating the process for each target, if any.
2019 # We'd like to reuse the debugger for our next test without incurring
2020 # the initialization overhead.
2022 for target
in self
.dbg
:
2024 targets
.append(target
)
2025 process
= target
.GetProcess()
2027 rc
= self
.invoke(process
, "Kill")
2029 for target
in targets
:
2030 self
.dbg
.DeleteTarget(target
)
2032 # Assert that all targets are deleted.
2033 self
.assertEqual(self
.dbg
.GetNumTargets(), 0)
2035 # Do this last, to make sure it's in reverse order from how we setup.
2038 def switch_to_thread_with_stop_reason(self
, stop_reason
):
2040 Run the 'thread list' command, and select the thread with stop reason as
2041 'stop_reason'. If no such thread exists, no select action is done.
2043 from .lldbutil
import stop_reason_to_str
2045 self
.runCmd("thread list")
2046 output
= self
.res
.GetOutput()
2047 thread_line_pattern
= re
.compile(
2048 "^[ *] thread #([0-9]+):.*stop reason = %s"
2049 % stop_reason_to_str(stop_reason
)
2051 for line
in output
.splitlines():
2052 matched
= thread_line_pattern
.match(line
)
2054 self
.runCmd("thread select %s" % matched
.group(1))
2056 def runCmd(self
, cmd
, msg
=None, check
=True, trace
=False, inHistory
=False):
2058 Ask the command interpreter to handle the command and then check its
2061 # Fail fast if 'cmd' is not meaningful.
2063 raise Exception("Bad 'cmd' parameter encountered")
2065 trace
= True if traceAlways
else trace
2067 if cmd
.startswith("target create "):
2068 cmd
= cmd
.replace("target create ", "file ")
2070 running
= cmd
.startswith("run") or cmd
.startswith("process launch")
2072 for i
in range(self
.maxLaunchCount
if running
else 1):
2073 with
recording(self
, trace
) as sbuf
:
2074 print("runCmd:", cmd
, file=sbuf
)
2076 print("check of return status not required", file=sbuf
)
2078 self
.ci
.HandleCommand(cmd
, self
.res
, inHistory
)
2080 with
recording(self
, trace
) as sbuf
:
2081 if self
.res
.Succeeded():
2082 print("output:", self
.res
.GetOutput(), file=sbuf
)
2084 print("runCmd failed!", file=sbuf
)
2085 print(self
.res
.GetError(), file=sbuf
)
2087 if self
.res
.Succeeded():
2090 # For process launch, wait some time before possible next try.
2091 time
.sleep(self
.timeWaitNextLaunch
)
2092 with
recording(self
, trace
) as sbuf
:
2093 print("Command '" + cmd
+ "' failed!", file=sbuf
)
2097 if self
.res
.GetOutput():
2098 output
+= "\nCommand output:\n" + self
.res
.GetOutput()
2099 if self
.res
.GetError():
2100 output
+= "\nError output:\n" + self
.res
.GetError()
2105 self
.assertTrue(self
.res
.Succeeded(), msg
if (msg
) else CMD_MSG(cmd
))
2108 self
, str, patterns
, msg
=None, trace
=False, error
=False, matching
=True, exe
=True
2110 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2112 Otherwise, all the arguments have the same meanings as for the expect function
2115 trace
= True if traceAlways
else trace
2118 # First run the command. If we are expecting error, set check=False.
2119 # Pass the assert message along since it provides more semantic
2121 self
.runCmd(str, msg
=msg
, trace
=(True if trace
else False), check
=not error
)
2123 # Then compare the output against expected strings.
2124 output
= self
.res
.GetError() if error
else self
.res
.GetOutput()
2126 # If error is True, the API client expects the command to fail!
2129 self
.res
.Succeeded(), "Command '" + str + "' is expected to fail!"
2132 # No execution required, just compare str against the golden input.
2134 with
recording(self
, trace
) as sbuf
:
2135 print("looking at:", output
, file=sbuf
)
2137 # The heading says either "Expecting" or "Not expecting".
2138 heading
= "Expecting" if matching
else "Not expecting"
2140 for pattern
in patterns
:
2141 # Match Objects always have a boolean value of True.
2142 match_object
= re
.search(pattern
, output
)
2143 matched
= bool(match_object
)
2144 with
recording(self
, trace
) as sbuf
:
2145 print("%s pattern: %s" % (heading
, pattern
), file=sbuf
)
2146 print("Matched" if matched
else "Not matched", file=sbuf
)
2151 matched
if matching
else not matched
,
2152 msg
if msg
else EXP_MSG(str, output
, exe
),
2157 def check_completion_with_desc(
2158 self
, str_input
, match_desc_pairs
, enforce_order
=False
2161 Checks that when the given input is completed at the given list of
2162 completions and descriptions is returned.
2163 :param str_input: The input that should be completed. The completion happens at the end of the string.
2164 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of
2165 completions returned by LLDB. The first element of the pair is the completion
2166 string that LLDB should generate and the second element the description.
2167 :param enforce_order: True iff the order in which the completions are returned by LLDB
2168 should match the order of the match_desc_pairs pairs.
2170 interp
= self
.dbg
.GetCommandInterpreter()
2171 match_strings
= lldb
.SBStringList()
2172 description_strings
= lldb
.SBStringList()
2173 num_matches
= interp
.HandleCompletionWithDescriptions(
2174 str_input
, len(str_input
), 0, -1, match_strings
, description_strings
2176 self
.assertEqual(len(description_strings
), len(match_strings
))
2178 # The index of the last matched description in description_strings or
2179 # -1 if no description has been matched yet.
2180 last_found_index
= -1
2181 out_of_order_errors
= ""
2183 for pair
in match_desc_pairs
:
2185 for i
in range(num_matches
+ 1):
2186 match_candidate
= match_strings
.GetStringAtIndex(i
)
2187 description_candidate
= description_strings
.GetStringAtIndex(i
)
2188 if match_candidate
== pair
[0] and description_candidate
== pair
[1]:
2190 if enforce_order
and last_found_index
> i
:
2196 + " in returned completion list but "
2197 + "should have been after completion "
2198 + match_strings
.GetStringAtIndex(last_found_index
)
2200 + str(last_found_index
)
2203 out_of_order_errors
+= new_err
2204 last_found_index
= i
2207 missing_pairs
.append(pair
)
2211 if len(missing_pairs
):
2213 error_msg
+= "Missing pairs:\n"
2214 for pair
in missing_pairs
:
2215 error_msg
+= " [" + pair
[0] + ":" + pair
[1] + "]\n"
2216 if len(out_of_order_errors
):
2218 error_msg
+= out_of_order_errors
2221 "Got the following " + str(num_matches
) + " completions back:\n"
2223 for i
in range(num_matches
+ 1):
2224 match_candidate
= match_strings
.GetStringAtIndex(i
)
2225 description_candidate
= description_strings
.GetStringAtIndex(i
)
2230 + description_candidate
2235 self
.assertFalse(got_failure
, error_msg
)
2237 def complete_from_to(self
, str_input
, patterns
):
2238 """Test that the completion mechanism completes str_input to patterns,
2239 where patterns could be a single pattern-string or a list of
2242 If there is only one pattern and it is exactly equal to str_input, this
2243 assumes that there should be no completions provided and that the result
2244 should be the same as the input."""
2246 # Patterns should not be None in order to proceed.
2247 self
.assertFalse(patterns
is None)
2248 # And should be either a string or list of strings. Check for list type
2249 # below, if not, make a list out of the singleton string. If patterns
2250 # is not a string or not a list of strings, there'll be runtime errors
2252 if not isinstance(patterns
, list):
2253 patterns
= [patterns
]
2255 interp
= self
.dbg
.GetCommandInterpreter()
2256 match_strings
= lldb
.SBStringList()
2257 num_matches
= interp
.HandleCompletion(
2258 str_input
, len(str_input
), 0, -1, match_strings
2260 common_match
= match_strings
.GetStringAtIndex(0)
2261 if num_matches
== 0:
2262 compare_string
= str_input
2264 if common_match
!= None and len(common_match
) > 0:
2265 compare_string
= str_input
+ common_match
2268 for idx
in range(1, num_matches
+ 1):
2269 compare_string
+= match_strings
.GetStringAtIndex(idx
) + "\n"
2271 if len(patterns
) == 1 and str_input
== patterns
[0] and num_matches
:
2272 self
.fail("Expected no completions but got:\n" + compare_string
)
2277 msg
=COMPLETION_MSG(str_input
, p
, match_strings
),
2282 def completions_match(self
, command
, completions
):
2283 """Checks that the completions for the given command are equal to the
2284 given list of completions"""
2285 interp
= self
.dbg
.GetCommandInterpreter()
2286 match_strings
= lldb
.SBStringList()
2287 interp
.HandleCompletion(command
, len(command
), 0, -1, match_strings
)
2288 # match_strings is a 1-indexed list, so we have to slice...
2289 self
.assertItemsEqual(
2290 completions
, list(match_strings
)[1:], "List of returned completion is wrong"
2293 def completions_contain(self
, command
, completions
):
2294 """Checks that the completions for the given command contain the given
2295 list of completions."""
2296 interp
= self
.dbg
.GetCommandInterpreter()
2297 match_strings
= lldb
.SBStringList()
2298 interp
.HandleCompletion(command
, len(command
), 0, -1, match_strings
)
2299 for completion
in completions
:
2300 # match_strings is a 1-indexed list, so we have to slice...
2302 completion
, list(match_strings
)[1:], "Couldn't find expected completion"
2306 self
, command
, check_file
, filecheck_options
="", expect_cmd_failure
=False
2311 check
=(not expect_cmd_failure
),
2312 msg
="FileCheck'ing result of `{0}`".format(command
),
2315 self
.assertTrue((not expect_cmd_failure
) == self
.res
.Succeeded())
2317 # Get the error text if there was an error, and the regular text if not.
2318 output
= self
.res
.GetOutput() if self
.res
.Succeeded() else self
.res
.GetError()
2320 # Assemble the absolute path to the check file. As a convenience for
2321 # LLDB inline tests, assume that the check file is a relative path to
2322 # a file within the inline test directory.
2323 if check_file
.endswith(".pyc"):
2324 check_file
= check_file
[:-1]
2325 check_file_abs
= os
.path
.abspath(check_file
)
2328 filecheck_bin
= configuration
.get_filecheck_path()
2329 if not filecheck_bin
:
2330 self
.assertTrue(False, "No valid FileCheck executable specified")
2331 filecheck_args
= [filecheck_bin
, check_file_abs
]
2332 if filecheck_options
:
2333 filecheck_args
.append(filecheck_options
)
2339 universal_newlines
=True,
2341 cmd_stdout
, cmd_stderr
= subproc
.communicate(input=output
)
2342 cmd_status
= subproc
.returncode
2344 filecheck_cmd
= " ".join(filecheck_args
)
2345 filecheck_trace
= """
2346 --- FileCheck trace (code={0}) ---
2356 cmd_status
, filecheck_cmd
, output
, cmd_stdout
, cmd_stderr
2359 trace
= cmd_status
!= 0 or traceAlways
2360 with
recording(self
, trace
) as sbuf
:
2361 print(filecheck_trace
, file=sbuf
)
2363 self
.assertTrue(cmd_status
== 0)
2381 Similar to runCmd; with additional expect style output matching ability.
2383 Ask the command interpreter to handle the command and then check its
2384 return status. The 'msg' parameter specifies an informational assert
2385 message. We expect the output from running the command to start with
2386 'startstr', matches the substrings contained in 'substrs', and regexp
2387 matches the patterns contained in 'patterns'.
2389 When matching is true and ordered is true, which are both the default,
2390 the strings in the substrs array have to appear in the command output
2391 in the order in which they appear in the array.
2393 If the keyword argument error is set to True, it signifies that the API
2394 client is expecting the command to fail. In this case, the error stream
2395 from running the command is retrieved and compared against the golden
2398 If the keyword argument matching is set to False, it signifies that the API
2399 client is expecting the output of the command not to match the golden
2402 Finally, the required argument 'string' represents the lldb command to be
2403 sent to the command interpreter. In case the keyword argument 'exe' is
2404 set to False, the 'string' is treated as a string to be matched/not-matched
2405 against the golden input.
2407 # Catch cases where `expect` has been miscalled. Specifically, prevent
2408 # this easy to make mistake:
2409 # self.expect("lldb command", "some substr")
2410 # The `msg` parameter is used only when a failed match occurs. A failed
2411 # match can only occur when one of `patterns`, `startstr`, `endstr`, or
2412 # `substrs` has been given. Thus, if a `msg` is given, it's an error to
2413 # not also provide one of the matcher parameters.
2414 if msg
and not (patterns
or startstr
or endstr
or substrs
or error
):
2415 assert False, "expect() missing a matcher argument"
2417 # Check `patterns` and `substrs` are not accidentally given as strings.
2418 assert not isinstance(patterns
, str), "patterns must be a collection of strings"
2419 assert not isinstance(substrs
, str), "substrs must be a collection of strings"
2421 trace
= True if traceAlways
else trace
2424 # First run the command. If we are expecting error, set check=False.
2425 # Pass the assert message along since it provides more semantic
2430 trace
=(True if trace
else False),
2432 inHistory
=inHistory
,
2435 # Then compare the output against expected strings.
2436 output
= self
.res
.GetError() if error
else self
.res
.GetOutput()
2438 # If error is True, the API client expects the command to fail!
2441 self
.res
.Succeeded(),
2442 "Command '" + string
+ "' is expected to fail!",
2445 # No execution required, just compare string against the golden input.
2446 if isinstance(string
, lldb
.SBCommandReturnObject
):
2447 output
= string
.GetOutput()
2450 with
recording(self
, trace
) as sbuf
:
2451 print("looking at:", output
, file=sbuf
)
2453 expecting_str
= "Expecting" if matching
else "Not expecting"
2455 def found_str(matched
):
2456 return "was found" if matched
else "was not found"
2458 # To be used as assert fail message and/or trace content
2460 "{}:".format("Ran command" if exe
else "Checking string"),
2461 '"{}"'.format(string
),
2462 # Space out command and output
2466 # Newline before output to make large strings more readable
2467 log_lines
.append("Got output:\n{}".format(output
))
2469 # Assume that we start matched if we want a match
2470 # Meaning if you have no conditions, matching or
2471 # not matching will always pass
2474 # We will stop checking on first failure
2476 matched
= output
.startswith(startstr
)
2478 '{} start string: "{}" ({})'.format(
2479 expecting_str
, startstr
, found_str(matched
)
2483 if endstr
and matched
== matching
:
2484 matched
= output
.endswith(endstr
)
2486 '{} end string: "{}" ({})'.format(
2487 expecting_str
, endstr
, found_str(matched
)
2491 if substrs
and matched
== matching
:
2493 for substr
in substrs
:
2494 index
= output
[start
:].find(substr
)
2495 start
= start
+ index
+ len(substr
) if ordered
and matching
else 0
2496 matched
= index
!= -1
2498 '{} sub string: "{}" ({})'.format(
2499 expecting_str
, substr
, found_str(matched
)
2503 if matched
!= matching
:
2506 if patterns
and matched
== matching
:
2507 for pattern
in patterns
:
2508 matched
= re
.search(pattern
, output
)
2510 pattern_line
= '{} regex pattern: "{}" ({}'.format(
2511 expecting_str
, pattern
, found_str(matched
)
2514 pattern_line
+= ', matched "{}"'.format(matched
.group(0))
2516 log_lines
.append(pattern_line
)
2518 # Convert to bool because match objects
2519 # are True-ish but != True itself
2520 matched
= bool(matched
)
2521 if matched
!= matching
:
2524 # If a check failed, add any extra assert message
2525 if msg
is not None and matched
!= matching
:
2526 log_lines
.append(msg
)
2528 log_msg
= "\n".join(log_lines
)
2529 with
recording(self
, trace
) as sbuf
:
2530 print(log_msg
, file=sbuf
)
2531 if matched
!= matching
:
2537 result_summary
=None,
2540 result_children
=None,
2543 Evaluates the given expression and verifies the result.
2544 :param expr: The expression as a string.
2545 :param result_summary: The summary that the expression should have. None if the summary should not be checked.
2546 :param result_value: The value that the expression should have. None if the value should not be checked.
2547 :param result_type: The type that the expression result should have. None if the type should not be checked.
2548 :param result_children: The expected children of the expression result
2549 as a list of ValueChecks. None if the children shouldn't be checked.
2552 expr
.strip() == expr
,
2553 "Expression contains trailing/leading whitespace: '" + expr
+ "'",
2556 frame
= self
.frame()
2557 options
= lldb
.SBExpressionOptions()
2559 # Disable fix-its that tests don't pass by accident.
2560 options
.SetAutoApplyFixIts(False)
2562 # Set the usual default options for normal expressions.
2563 options
.SetIgnoreBreakpoints(True)
2565 if self
.frame().IsValid():
2566 options
.SetLanguage(frame
.GuessLanguage())
2567 eval_result
= self
.frame().EvaluateExpression(expr
, options
)
2569 target
= self
.target()
2570 # If there is no selected target, run the expression in the dummy
2572 if not target
.IsValid():
2573 target
= self
.dbg
.GetDummyTarget()
2574 eval_result
= target
.EvaluateExpression(expr
, options
)
2576 value_check
= ValueCheck(
2579 summary
=result_summary
,
2580 children
=result_children
,
2582 value_check
.check_value(self
, eval_result
, str(eval_result
))
2585 def expect_var_path(
2586 self
, var_path
, summary
=None, value
=None, type=None, children
=None
2589 Evaluates the given variable path and verifies the result.
2590 See also 'frame variable' and SBFrame.GetValueForVariablePath.
2591 :param var_path: The variable path as a string.
2592 :param summary: The summary that the variable should have. None if the summary should not be checked.
2593 :param value: The value that the variable should have. None if the value should not be checked.
2594 :param type: The type that the variable result should have. None if the type should not be checked.
2595 :param children: The expected children of the variable as a list of ValueChecks.
2596 None if the children shouldn't be checked.
2599 var_path
.strip() == var_path
,
2600 "Expression contains trailing/leading whitespace: '" + var_path
+ "'",
2603 frame
= self
.frame()
2604 eval_result
= frame
.GetValueForVariablePath(var_path
)
2606 value_check
= ValueCheck(
2607 type=type, value
=value
, summary
=summary
, children
=children
2609 value_check
.check_value(self
, eval_result
, str(eval_result
))
2612 """Assert that an lldb.SBError is in the "success" state."""
2614 def assertSuccess(self
, obj
, msg
=None):
2615 if not obj
.Success():
2616 error
= obj
.GetCString()
2617 self
.fail(self
._formatMessage
(msg
, "'{}' is not success".format(error
)))
2619 """Assert that an lldb.SBError is in the "failure" state."""
2621 def assertFailure(self
, obj
, error_str
=None, msg
=None):
2623 self
.fail(self
._formatMessage
(msg
, "Error not in a fail state"))
2625 if error_str
== None:
2628 error
= obj
.GetCString()
2629 self
.assertEqual(error
, error_str
, msg
)
2631 """Assert that a command return object is successful"""
2633 def assertCommandReturn(self
, obj
, msg
=None):
2634 if not obj
.Succeeded():
2635 error
= obj
.GetError()
2636 self
.fail(self
._formatMessage
(msg
, "'{}' is not success".format(error
)))
2638 """Assert two states are equal"""
2640 def assertState(self
, first
, second
, msg
=None):
2642 error
= "{} ({}) != {} ({})".format(
2643 lldbutil
.state_type_to_str(first
),
2645 lldbutil
.state_type_to_str(second
),
2648 self
.fail(self
._formatMessage
(msg
, error
))
2650 """Assert two stop reasons are equal"""
2652 def assertStopReason(self
, first
, second
, msg
=None):
2654 error
= "{} ({}) != {} ({})".format(
2655 lldbutil
.stop_reason_to_str(first
),
2657 lldbutil
.stop_reason_to_str(second
),
2660 self
.fail(self
._formatMessage
(msg
, error
))
2662 def createTestTarget(self
, file_path
=None, msg
=None, load_dependent_modules
=True):
2664 Creates a target from the file found at the given file path.
2665 Asserts that the resulting target is valid.
2666 :param file_path: The file path that should be used to create the target.
2667 The default argument opens the current default test
2668 executable in the current test directory.
2669 :param msg: A custom error message.
2671 if file_path
is None:
2672 file_path
= self
.getBuildArtifact("a.out")
2673 error
= lldb
.SBError()
2676 target
= self
.dbg
.CreateTarget(
2677 file_path
, triple
, platform
, load_dependent_modules
, error
2680 err
= "Couldn't create target for path '{}': {}".format(
2681 file_path
, str(error
)
2683 self
.fail(self
._formatMessage
(msg
, err
))
2685 self
.assertTrue(target
.IsValid(), "Got invalid target without error")
2688 # =================================================
2689 # Misc. helper methods for debugging test execution
2690 # =================================================
2692 def DebugSBValue(self
, val
):
2693 """Debug print a SBValue object, if traceAlways is True."""
2694 from .lldbutil
import value_type_to_str
2700 err
.write(val
.GetName() + ":\n")
2701 err
.write("\t" + "TypeName -> " + val
.GetTypeName() + "\n")
2702 err
.write("\t" + "ByteSize -> " + str(val
.GetByteSize()) + "\n")
2703 err
.write("\t" + "NumChildren -> " + str(val
.GetNumChildren()) + "\n")
2704 err
.write("\t" + "Value -> " + str(val
.GetValue()) + "\n")
2705 err
.write("\t" + "ValueAsUnsigned -> " + str(val
.GetValueAsUnsigned()) + "\n")
2707 "\t" + "ValueType -> " + value_type_to_str(val
.GetValueType()) + "\n"
2709 err
.write("\t" + "Summary -> " + str(val
.GetSummary()) + "\n")
2710 err
.write("\t" + "IsPointerType -> " + str(val
.TypeIsPointerType()) + "\n")
2711 err
.write("\t" + "Location -> " + val
.GetLocation() + "\n")
2713 def DebugSBType(self
, type):
2714 """Debug print a SBType object, if traceAlways is True."""
2719 err
.write(type.GetName() + ":\n")
2720 err
.write("\t" + "ByteSize -> " + str(type.GetByteSize()) + "\n")
2721 err
.write("\t" + "IsAggregateType -> " + str(type.IsAggregateType()) + "\n")
2722 err
.write("\t" + "IsPointerType -> " + str(type.IsPointerType()) + "\n")
2723 err
.write("\t" + "IsReferenceType -> " + str(type.IsReferenceType()) + "\n")
2725 def DebugPExpect(self
, child
):
2726 """Debug the spwaned pexpect object."""
2733 def RemoveTempFile(cls
, file):
2734 if os
.path
.exists(file):
2738 # On Windows, the first attempt to delete a recently-touched file can fail
2739 # because of a race with antimalware scanners. This function will detect a
2740 # failure and retry.
2743 def remove_file(file, num_retries
=1, sleep_duration
=0.5):
2744 for i
in range(num_retries
+ 1):
2749 time
.sleep(sleep_duration
)