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 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
70 from lldbsuite.test.builders import get_builder
72 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
73 # LLDB_COMMAND_TRACE is set from '-t' option.
75 # By default, traceAlways is False.
76 if "LLDB_COMMAND_TRACE" in os.environ and os.environ[
77 "LLDB_COMMAND_TRACE"] == "YES":
82 # By default, doCleanup is True.
83 if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"] == "NO":
90 # Some commonly used assert messages.
93 COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
95 CURRENT_EXECUTABLE_SET = "Current executable set successfully"
97 PROCESS_IS_VALID = "Process is valid"
99 PROCESS_KILLED = "Process is killed successfully"
101 PROCESS_EXITED = "Process exited successfully"
103 PROCESS_STOPPED = "Process status should be stopped"
105 RUN_SUCCEEDED = "Process is launched successfully"
107 RUN_COMPLETED = "Process exited successfully"
109 BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
111 BREAKPOINT_CREATED = "Breakpoint created successfully"
113 BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
115 BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
117 BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit count = 1"
119 BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit count = 2"
121 BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit count = 3"
123 MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable."
125 OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
127 SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
129 STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
131 STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
133 STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion"
135 STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
137 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
138 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
140 STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
142 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
144 STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION = "Stopped due to breakpoint jitted condition"
146 STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
148 STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
150 STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
152 DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
154 VALID_BREAKPOINT = "Got a valid breakpoint"
156 VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
158 VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
160 VALID_FILESPEC = "Got a valid filespec"
162 VALID_MODULE = "Got a valid module"
164 VALID_PROCESS = "Got a valid process"
166 VALID_SYMBOL = "Got a valid symbol"
168 VALID_TARGET = "Got a valid target"
170 VALID_PLATFORM = "Got a valid platform"
172 VALID_TYPE = "Got a valid type"
174 VALID_VARIABLE = "Got a valid variable"
176 VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
178 WATCHPOINT_CREATED = "Watchpoint created successfully"
182 '''A generic "Command '%s' did not return successfully" message generator.'''
183 return "Command '%s' did not return successfully" % str
186 def COMPLETION_MSG(str_before, str_after, completions):
187 '''A generic assertion failed message generator for the completion mechanism.'''
188 return ("'%s' successfully completes to '%s', but completions were:\n%s"
189 % (str_before, str_after, "\n".join(completions)))
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'" % (
197 str, 'returned unexpected' if exe else 'does not match expected', actual.strip())
200 def SETTING_MSG(setting):
201 '''A generic "Value of setting '%s' is not correct" message generator.'''
202 return "Value of setting '%s' is not correct" % setting
205 def line_number(filename, string_to_match):
206 """Helper function to return the line number of the first matched string."""
207 with io.open(filename, mode='r', encoding="utf-8") as f:
208 for i, line in enumerate(f):
209 if line.find(string_to_match) != -1:
213 "Unable to find '%s' within file %s" %
214 (string_to_match, filename))
216 def get_line(filename, line_number):
217 """Return the text of the line at the 1-based line number."""
218 with io.open(filename, mode='r', encoding="utf-8") as f:
219 return f.readlines()[line_number - 1]
222 """Return the pointer size of the host system."""
224 a_pointer = ctypes.c_void_p(0xffff)
225 return 8 * ctypes.sizeof(a_pointer)
229 """Returns true if fpath is an executable."""
230 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
234 """Returns the full path to a program; None otherwise."""
235 fpath, fname = os.path.split(program)
240 for path in os.environ["PATH"].split(os.pathsep):
241 exe_file = os.path.join(path, program)
247 def __init__(self, name=None, value=None, type=None, summary=None,
250 :param name: The name that the SBValue should have. None if the summary
251 should not be checked.
252 :param summary: The summary that the SBValue should have. None if the
253 summary should not be checked.
254 :param value: The value that the SBValue should have. None if the value
255 should not be checked.
256 :param type: The type that the SBValue result should have. None if the
257 type should not be checked.
258 :param children: A list of ValueChecks that need to match the children
259 of this SBValue. None if children shouldn't be checked.
260 The order of checks is the order of the checks in the
261 list. The number of checks has to match the number of
264 self.expect_name = name
265 self.expect_value = value
266 self.expect_type = type
267 self.expect_summary = summary
268 self.children = children
270 def check_value(self, test_base, val, error_msg=None):
272 Checks that the given value matches the currently set properties
273 of this ValueCheck. If a match failed, the given TestBase will
274 be used to emit an error. A custom error message can be specified
275 that will be used to describe failed check for this SBValue (but
276 not errors in the child values).
279 this_error_msg = error_msg if error_msg else ""
280 this_error_msg += "\nChecking SBValue: " + str(val)
282 test_base.assertSuccess(val.GetError())
285 test_base.assertEqual(self.expect_name, val.GetName(),
287 if self.expect_value:
288 test_base.assertEqual(self.expect_value, val.GetValue(),
291 test_base.assertEqual(self.expect_type, val.GetDisplayTypeName(),
293 if self.expect_summary:
294 test_base.assertEqual(self.expect_summary, val.GetSummary(),
296 if self.children is not None:
297 self.check_value_children(test_base, val, error_msg)
299 def check_value_children(self, test_base, val, error_msg=None):
301 Checks that the children of a SBValue match a certain structure and
302 have certain properties.
304 :param test_base: The current test's TestBase object.
305 :param val: The SBValue to check.
308 this_error_msg = error_msg if error_msg else ""
309 this_error_msg += "\nChecking SBValue: " + str(val)
311 test_base.assertEqual(len(self.children), val.GetNumChildren(), this_error_msg)
313 for i in range(0, val.GetNumChildren()):
314 expected_child = self.children[i]
315 actual_child = val.GetChildAtIndex(i)
316 expected_child.check_value(test_base, actual_child, error_msg)
318 class recording(SixStringIO):
320 A nice little context manager for recording the debugger interactions into
321 our session object. If trace flag is ON, it also emits the interactions
325 def __init__(self, test, trace):
326 """Create a SixStringIO instance; record the session obj and trace flag."""
327 SixStringIO.__init__(self)
328 # The test might not have undergone the 'setUp(self)' phase yet, so that
329 # the attribute 'session' might not even exist yet.
330 self.session = getattr(test, "session", None) if test else None
335 Context management protocol on entry to the body of the with statement.
336 Just return the SixStringIO object.
340 def __exit__(self, type, value, tb):
342 Context management protocol on exit from the body of the with statement.
343 If trace is ON, it emits the recordings into stderr. Always add the
344 recordings to our session object. And close the SixStringIO object, too.
347 print(self.getvalue(), file=sys.stderr)
349 print(self.getvalue(), file=self.session)
353 @add_metaclass(abc.ABCMeta)
354 class _BaseProcess(object):
356 @abc.abstractproperty
358 """Returns process PID if has been launched already."""
361 def launch(self, executable, args):
362 """Launches new process with given executable and args."""
366 """Terminates previously launched process.."""
369 class _LocalProcess(_BaseProcess):
371 def __init__(self, trace_on):
373 self._trace_on = trace_on
374 self._delayafterterminate = 0.1
378 return self._proc.pid
380 def launch(self, executable, args):
384 os.devnull) if not self._trace_on else None,
388 if self._proc.poll() is None:
389 # Terminate _proc like it does the pexpect
394 'SIGINT'] if sig in dir(signal)]
395 for sig in signals_to_try:
397 self._proc.send_signal(getattr(signal, sig))
398 time.sleep(self._delayafterterminate)
399 if self._proc.poll() is not None:
402 pass # Windows says SIGINT is not a valid signal to send
403 self._proc.terminate()
404 time.sleep(self._delayafterterminate)
405 if self._proc.poll() is not None:
408 time.sleep(self._delayafterterminate)
411 return self._proc.poll()
414 class _RemoteProcess(_BaseProcess):
416 def __init__(self, install_remote):
418 self._install_remote = install_remote
424 def launch(self, executable, args):
425 if self._install_remote:
426 src_path = executable
427 dst_path = lldbutil.join_remote_paths(
428 lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable))
430 dst_file_spec = lldb.SBFileSpec(dst_path, False)
431 err = lldb.remote_platform.Install(
432 lldb.SBFileSpec(src_path, True), dst_file_spec)
435 "remote_platform.Install('%s', '%s') failed: %s" %
436 (src_path, dst_path, err))
438 dst_path = executable
439 dst_file_spec = lldb.SBFileSpec(executable, False)
441 launch_info = lldb.SBLaunchInfo(args)
442 launch_info.SetExecutableFile(dst_file_spec, True)
443 launch_info.SetWorkingDirectory(
444 lldb.remote_platform.GetWorkingDirectory())
446 # Redirect stdout and stderr to /dev/null
447 launch_info.AddSuppressFileAction(1, False, True)
448 launch_info.AddSuppressFileAction(2, False, True)
450 err = lldb.remote_platform.Launch(launch_info)
453 "remote_platform.Launch('%s', '%s') failed: %s" %
454 (dst_path, args, err))
455 self._pid = launch_info.GetProcessID()
458 lldb.remote_platform.Kill(self._pid)
460 # From 2.7's subprocess.check_output() convenience function.
461 # Return a tuple (stdoutdata, stderrdata).
464 def system(commands, **kwargs):
465 r"""Run an os command with arguments and return its output as a byte string.
467 If the exit code was non-zero it raises a CalledProcessError. The
468 CalledProcessError object will have the return code in the returncode
469 attribute and output in the output attribute.
471 The arguments are the same as for the Popen constructor. Example:
473 >>> check_output(["ls", "-l", "/dev/null"])
474 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
476 The stdout argument is not allowed as it is used internally.
477 To capture standard error in the result, use stderr=STDOUT.
479 >>> check_output(["/bin/sh", "-c",
480 ... "ls -l non_existent_file ; exit 0"],
482 'ls: non_existent_file: No such file or directory\n'
485 # Assign the sender object to variable 'test' and remove it from kwargs.
486 test = kwargs.pop('sender', None)
488 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo']
489 commandList = [' '.join(x) for x in commands]
492 for shellCommand in commandList:
493 if 'stdout' in kwargs:
495 'stdout argument not allowed, it will be overridden.')
496 if 'shell' in kwargs and kwargs['shell'] == False:
497 raise ValueError('shell=False not allowed')
505 this_output, this_error = process.communicate()
506 retcode = process.poll()
509 cmd = kwargs.get("args")
512 cpe = CalledProcessError(retcode, cmd)
513 # Ensure caller can access the stdout/stderr.
514 cpe.lldb_extensions = {
515 "combined_output": this_output,
516 "command": shellCommand
519 output = output + this_output.decode("utf-8", errors='ignore')
523 def getsource_if_available(obj):
525 Return the text of the source code for an object if available. Otherwise,
526 a print representation is returned.
530 return inspect.getsource(obj)
535 def builder_module():
536 return get_builder(sys.platform)
539 class Base(unittest2.TestCase):
541 Abstract base for performing lldb (see TestBase) or other generic tests (see
542 BenchBase for one example). lldbtest.Base works with the test driver to
547 # The concrete subclass should override this attribute.
550 # Keep track of the old current working directory.
554 def compute_mydir(test_file):
555 '''Subclasses should call this function to correctly calculate the
556 required "mydir" attribute as follows:
558 mydir = TestBase.compute_mydir(__file__)
560 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir
561 lldb_test_src = configuration.test_src_root
562 if not test_file.startswith(lldb_test_src):
564 "Test file '%s' must reside within lldb_test_src "
565 "(which is '%s')." % (test_file, lldb_test_src))
566 return os.path.dirname(os.path.relpath(test_file, start=lldb_test_src))
569 """Returns True if we are in trace mode (tracing detailed test execution)."""
572 def trace(self, *args,**kwargs):
573 with recording(self, self.TraceOn()) as sbuf:
574 print(*args, file=sbuf, **kwargs)
579 Python unittest framework class setup fixture.
580 Do current directory manipulation.
582 # Fail fast if 'mydir' attribute is not overridden.
583 if not cls.mydir or len(cls.mydir) == 0:
584 raise Exception("Subclasses must override the 'mydir' attribute.")
586 # Save old working directory.
587 cls.oldcwd = os.getcwd()
589 full_dir = os.path.join(configuration.test_src_root, cls.mydir)
591 print("Change dir to:", full_dir, file=sys.stderr)
593 lldb.SBReproducer.SetWorkingDirectory(full_dir)
595 # Set platform context.
596 cls.platformContext = lldbplatformutil.createPlatformContext()
599 def tearDownClass(cls):
601 Python unittest framework class teardown fixture.
602 Do class-wide cleanup.
606 # First, let's do the platform-specific cleanup.
607 module = builder_module()
610 # Subclass might have specific cleanup function defined.
611 if getattr(cls, "classCleanup", None):
614 "Call class-specific cleanup function for class:",
620 exc_type, exc_value, exc_tb = sys.exc_info()
621 traceback.print_exception(exc_type, exc_value, exc_tb)
623 # Restore old working directory.
625 print("Restore dir to:", cls.oldcwd, file=sys.stderr)
628 def enableLogChannelsForCurrentTest(self):
629 if len(lldbtest_config.channels) == 0:
632 # if debug channels are specified in lldbtest_config.channels,
633 # create a new set of log files for every test
634 log_basename = self.getLogBasenameForCurrentTest()
636 # confirm that the file is writeable
637 host_log_path = "{}-host.log".format(log_basename)
638 open(host_log_path, 'w').close()
639 self.log_files.append(host_log_path)
641 log_enable = "log enable -Tpn -f {} ".format(host_log_path)
642 for channel_with_categories in lldbtest_config.channels:
643 channel_then_categories = channel_with_categories.split(' ', 1)
644 channel = channel_then_categories[0]
645 if len(channel_then_categories) > 1:
646 categories = channel_then_categories[1]
648 categories = "default"
650 if channel == "gdb-remote" and lldb.remote_platform is None:
651 # communicate gdb-remote categories to debugserver
652 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
654 self.ci.HandleCommand(
655 log_enable + channel_with_categories, self.res)
656 if not self.res.Succeeded():
658 'log enable failed (check LLDB_LOG_OPTION env variable)')
660 # Communicate log path name to debugserver & lldb-server
661 # For remote debugging, these variables need to be set when starting the platform
663 if lldb.remote_platform is None:
664 server_log_path = "{}-server.log".format(log_basename)
665 open(server_log_path, 'w').close()
666 self.log_files.append(server_log_path)
667 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
669 # Communicate channels to lldb-server
670 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(
671 lldbtest_config.channels)
673 self.addTearDownHook(self.disableLogChannelsForCurrentTest)
675 def disableLogChannelsForCurrentTest(self):
676 # close all log files that we opened
677 for channel_and_categories in lldbtest_config.channels:
678 # channel format - <channel-name> [<category0> [<category1> ...]]
679 channel = channel_and_categories.split(' ', 1)[0]
680 self.ci.HandleCommand("log disable " + channel, self.res)
681 if not self.res.Succeeded():
683 'log disable failed (check LLDB_LOG_OPTION env variable)')
685 # Retrieve the server log (if any) from the remote system. It is assumed the server log
686 # is writing to the "server.log" file in the current test directory. This can be
687 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote
689 if lldb.remote_platform:
690 server_log_path = self.getLogBasenameForCurrentTest() + "-server.log"
691 if lldb.remote_platform.Get(
692 lldb.SBFileSpec("server.log"),
693 lldb.SBFileSpec(server_log_path)).Success():
694 self.log_files.append(server_log_path)
696 def setPlatformWorkingDir(self):
697 if not lldb.remote_platform or not configuration.lldb_platform_working_dir:
700 components = self.mydir.split(os.path.sep) + [str(self.test_number), self.getBuildDirBasename()]
701 remote_test_dir = configuration.lldb_platform_working_dir
703 remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c)
704 error = lldb.remote_platform.MakeDirectory(
705 remote_test_dir, 448) # 448 = 0o700
707 raise Exception("making remote directory '%s': %s" % (
708 remote_test_dir, error))
710 lldb.remote_platform.SetWorkingDirectory(remote_test_dir)
712 # This function removes all files from the current working directory while leaving
713 # the directories in place. The cleanup is required to reduce the disk space required
714 # by the test suite while leaving the directories untouched is neccessary because
715 # sub-directories might belong to an other test
716 def clean_working_directory():
717 # TODO: Make it working on Windows when we need it for remote debugging support
718 # TODO: Replace the heuristic to remove the files with a logic what collects the
719 # list of files we have to remove during test runs.
720 shell_cmd = lldb.SBPlatformShellCommand(
721 "rm %s/*" % remote_test_dir)
722 lldb.remote_platform.Run(shell_cmd)
723 self.addTearDownHook(clean_working_directory)
725 def getSourceDir(self):
726 """Return the full path to the current test."""
727 return os.path.join(configuration.test_src_root, self.mydir)
729 def getBuildDirBasename(self):
730 return self.__class__.__module__ + "." + self.testMethodName
732 def getBuildDir(self):
733 """Return the full path to the current test."""
734 return os.path.join(configuration.test_build_dir, self.mydir,
735 self.getBuildDirBasename())
737 def getReproducerDir(self):
738 """Return the full path to the reproducer if enabled."""
739 if configuration.capture_path:
740 return configuration.capture_path
741 if configuration.replay_path:
742 return configuration.replay_path
745 def makeBuildDir(self):
746 """Create the test-specific working directory, deleting any previous
748 bdir = self.getBuildDir()
749 if os.path.isdir(bdir):
751 lldbutil.mkdir_p(bdir)
753 def getBuildArtifact(self, name="a.out"):
754 """Return absolute path to an artifact in the test's build directory."""
755 return os.path.join(self.getBuildDir(), name)
757 def getSourcePath(self, name):
758 """Return absolute path to a file in the test's source directory."""
759 return os.path.join(self.getSourceDir(), name)
761 def getReproducerArtifact(self, name):
762 lldbutil.mkdir_p(self.getReproducerDir())
763 return os.path.join(self.getReproducerDir(), name)
765 def getReproducerRemappedPath(self, path):
766 assert configuration.replay_path
767 assert os.path.isabs(path)
768 path = os.path.relpath(path, '/')
769 return os.path.join(configuration.replay_path, 'root', path)
772 def setUpCommands(cls):
774 # First of all, clear all settings to have clean state of global properties.
775 "settings clear -all",
777 # Disable Spotlight lookup. The testsuite creates
778 # different binaries with the same UUID, because they only
779 # differ in the debug info, which is not being hashed.
780 "settings set symbols.enable-external-lookup false",
782 # Inherit the TCC permissions from the inferior's parent.
783 "settings set target.inherit-tcc true",
785 # Disable fix-its by default so that incorrect expressions in tests don't
786 # pass just because Clang thinks it has a fix-it.
787 "settings set target.auto-apply-fixits false",
789 # Testsuite runs in parallel and the host can have also other load.
790 "settings set plugin.process.gdb-remote.packet-timeout 60",
792 'settings set symbols.clang-modules-cache-path "{}"'.format(
793 configuration.lldb_module_cache_dir),
794 "settings set use-color false",
797 # Set any user-overridden settings.
798 for setting, value in configuration.settings:
799 commands.append('setting set %s %s'%(setting, value))
801 # Make sure that a sanitizer LLDB's environment doesn't get passed on.
802 if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ:
803 commands.append('settings set target.env-vars {}='.format(
804 cls.platformContext.shlib_environment_var))
806 # Set environment variables for the inferior.
807 if lldbtest_config.inferior_env:
808 commands.append('settings set target.env-vars {}'.format(
809 lldbtest_config.inferior_env))
813 """Fixture for unittest test case setup.
815 It works with the test driver to conditionally skip tests and does other
818 # traceback.print_stack()
820 if "LIBCXX_PATH" in os.environ:
821 self.libcxxPath = os.environ["LIBCXX_PATH"]
823 self.libcxxPath = None
825 if "LLDBVSCODE_EXEC" in os.environ:
826 self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"]
828 self.lldbVSCodeExec = None
830 self.lldbOption = " ".join(
831 "-o '" + s + "'" for s in self.setUpCommands())
833 # If we spawn an lldb process for test (via pexpect), do not load the
834 # init file unless told otherwise.
835 if os.environ.get("NO_LLDBINIT") != "NO":
836 self.lldbOption += " --no-lldbinit"
838 # Assign the test method name to self.testMethodName.
840 # For an example of the use of this attribute, look at test/types dir.
841 # There are a bunch of test cases under test/types and we don't want the
842 # module cacheing subsystem to be confused with executable name "a.out"
843 # used for all the test cases.
844 self.testMethodName = self._testMethodName
846 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
847 # with it using pexpect.
849 self.child_prompt = "(lldb) "
850 # If the child is interacting with the embedded script interpreter,
851 # there are two exits required during tear down, first to quit the
852 # embedded script interpreter and second to quit the lldb command
854 self.child_in_script_interpreter = False
856 # These are for customized teardown cleanup.
858 self.doTearDownCleanup = False
859 # And in rare cases where there are multiple teardown cleanups.
861 self.doTearDownCleanups = False
863 # List of spawned subproces.Popen objects
864 self.subprocesses = []
866 # List of log files produced by the current test.
869 session_file = self.getLogBasenameForCurrentTest()+".log"
870 self.log_files.append(session_file)
872 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered.
873 self.session = encoded_file.open(session_file, "utf-8", mode="w")
875 # Optimistically set __errored__, __failed__, __expected__ to False
876 # initially. If the test errored/failed, the session info
877 # (self.session) is then dumped into a session specific file for
879 self.__cleanup_errored__ = False
880 self.__errored__ = False
881 self.__failed__ = False
882 self.__expected__ = False
883 # We are also interested in unexpected success.
884 self.__unexpected__ = False
886 self.__skipped__ = False
888 # See addTearDownHook(self, hook) which allows the client to add a hook
889 # function to be run during tearDown() time.
892 # See HideStdout(self).
893 self.sys_stdout_hidden = False
895 if self.platformContext:
896 # set environment variable names for finding shared libraries
897 self.dylibPath = self.platformContext.shlib_environment_var
899 # Create the debugger instance.
900 self.dbg = lldb.SBDebugger.Create()
901 # Copy selected platform from a global instance if it exists.
902 if lldb.selected_platform is not None:
903 self.dbg.SetSelectedPlatform(lldb.selected_platform)
906 raise Exception('Invalid debugger instance')
908 # Retrieve the associated command interpreter instance.
909 self.ci = self.dbg.GetCommandInterpreter()
911 raise Exception('Could not get the command interpreter')
913 # And the result object.
914 self.res = lldb.SBCommandReturnObject()
916 self.setPlatformWorkingDir()
917 self.enableLogChannelsForCurrentTest()
920 self.framework_dir = None
921 self.darwinWithFramework = False
923 if sys.platform.startswith("darwin") and configuration.lldb_framework_path:
924 framework = configuration.lldb_framework_path
925 lib = os.path.join(framework, 'LLDB')
926 if os.path.exists(lib):
927 self.framework_dir = os.path.dirname(framework)
929 self.darwinWithFramework = self.platformIsDarwin()
933 def setAsync(self, value):
934 """ Sets async mode to True/False and ensures it is reset after the testcase completes."""
935 old_async = self.dbg.GetAsync()
936 self.dbg.SetAsync(value)
937 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async))
939 def cleanupSubprocesses(self):
940 # Terminate subprocesses in reverse order from how they were created.
941 for p in reversed(self.subprocesses):
944 del self.subprocesses[:]
946 def spawnSubprocess(self, executable, args=[], install_remote=True):
947 """ Creates a subprocess.Popen object with the specified executable and arguments,
948 saves it in self.subprocesses, and returns the object.
950 proc = _RemoteProcess(
951 install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn())
952 proc.launch(executable, args)
953 self.subprocesses.append(proc)
956 def HideStdout(self):
957 """Hide output to stdout from the user.
959 During test execution, there might be cases where we don't want to show the
960 standard output to the user. For example,
962 self.runCmd(r'''sc print("\n\n\tHello!\n")''')
964 tests whether command abbreviation for 'script' works or not. There is no
965 need to show the 'Hello' output to the user as long as the 'script' command
966 succeeds and we are not in TraceOn() mode (see the '-t' option).
968 In this case, the test method calls self.HideStdout(self) to redirect the
969 sys.stdout to a null device, and restores the sys.stdout upon teardown.
971 Note that you should only call this method at most once during a test case
972 execution. Any subsequent call has no effect at all."""
973 if self.sys_stdout_hidden:
976 self.sys_stdout_hidden = True
977 old_stdout = sys.stdout
978 sys.stdout = open(os.devnull, 'w')
980 def restore_stdout():
981 sys.stdout = old_stdout
982 self.addTearDownHook(restore_stdout)
984 # =======================================================================
985 # Methods for customized teardown cleanups as well as execution of hooks.
986 # =======================================================================
988 def setTearDownCleanup(self, dictionary=None):
989 """Register a cleanup action at tearDown() time with a dictionary"""
990 self.dict = dictionary
991 self.doTearDownCleanup = True
993 def addTearDownCleanup(self, dictionary):
994 """Add a cleanup action at tearDown() time with a dictionary"""
995 self.dicts.append(dictionary)
996 self.doTearDownCleanups = True
998 def addTearDownHook(self, hook):
1000 Add a function to be run during tearDown() time.
1002 Hooks are executed in a first come first serve manner.
1004 if six.callable(hook):
1005 with recording(self, traceAlways) as sbuf:
1007 "Adding tearDown hook:",
1008 getsource_if_available(hook),
1010 self.hooks.append(hook)
1014 def deletePexpectChild(self):
1015 # This is for the case of directly spawning 'lldb' and interacting with it
1017 if self.child and self.child.isalive():
1019 with recording(self, traceAlways) as sbuf:
1020 print("tearing down the child process....", file=sbuf)
1022 if self.child_in_script_interpreter:
1023 self.child.sendline('quit()')
1024 self.child.expect_exact(self.child_prompt)
1025 self.child.sendline(
1026 'settings set interpreter.prompt-on-quit false')
1027 self.child.sendline('quit')
1028 self.child.expect(pexpect.EOF)
1029 except (ValueError, pexpect.ExceptionPexpect):
1030 # child is already terminated
1032 except OSError as exception:
1034 if exception.errno != errno.EIO:
1037 # child is already terminated
1039 # Give it one final blow to make sure the child is terminated.
1043 """Fixture for unittest test case teardown."""
1044 self.deletePexpectChild()
1046 # Check and run any hook functions.
1047 for hook in reversed(self.hooks):
1048 with recording(self, traceAlways) as sbuf:
1050 "Executing tearDown hook:",
1051 getsource_if_available(hook),
1053 if funcutils.requires_self(hook):
1056 hook() # try the plain call and hope it works
1060 # Perform registered teardown cleanup.
1061 if doCleanup and self.doTearDownCleanup:
1062 self.cleanup(dictionary=self.dict)
1064 # In rare cases where there are multiple teardown cleanups added.
1065 if doCleanup and self.doTearDownCleanups:
1067 for dict in reversed(self.dicts):
1068 self.cleanup(dictionary=dict)
1070 # Remove subprocesses created by the test.
1071 self.cleanupSubprocesses()
1073 # This must be the last statement, otherwise teardown hooks or other
1074 # lines might depend on this still being active.
1075 lldb.SBDebugger.Destroy(self.dbg)
1078 # All modules should be orphaned now so that they can be cleared from
1079 # the shared module cache.
1080 lldb.SBModule.GarbageCollectAllocatedModules()
1082 # Modules are not orphaned during reproducer replay because they're
1083 # leaked on purpose.
1084 if not configuration.is_reproducer():
1085 # Assert that the global module cache is empty.
1086 self.assertEqual(lldb.SBModule.GetNumberAllocatedModules(), 0)
1089 # =========================================================
1090 # Various callbacks to allow introspection of test progress
1091 # =========================================================
1093 def markError(self):
1094 """Callback invoked when an error (unexpected exception) errored."""
1095 self.__errored__ = True
1096 with recording(self, False) as sbuf:
1097 # False because there's no need to write "ERROR" to the stderr twice.
1098 # Once by the Python unittest framework, and a second time by us.
1099 print("ERROR", file=sbuf)
1101 def markCleanupError(self):
1102 """Callback invoked when an error occurs while a test is cleaning up."""
1103 self.__cleanup_errored__ = True
1104 with recording(self, False) as sbuf:
1105 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice.
1106 # Once by the Python unittest framework, and a second time by us.
1107 print("CLEANUP_ERROR", file=sbuf)
1109 def markFailure(self):
1110 """Callback invoked when a failure (test assertion failure) occurred."""
1111 self.__failed__ = True
1112 with recording(self, False) as sbuf:
1113 # False because there's no need to write "FAIL" to the stderr twice.
1114 # Once by the Python unittest framework, and a second time by us.
1115 print("FAIL", file=sbuf)
1117 def markExpectedFailure(self, err, bugnumber):
1118 """Callback invoked when an expected failure/error occurred."""
1119 self.__expected__ = True
1120 with recording(self, False) as sbuf:
1121 # False because there's no need to write "expected failure" to the
1123 # Once by the Python unittest framework, and a second time by us.
1124 if bugnumber is None:
1125 print("expected failure", file=sbuf)
1128 "expected failure (problem id:" + str(bugnumber) + ")",
1131 def markSkippedTest(self):
1132 """Callback invoked when a test is skipped."""
1133 self.__skipped__ = True
1134 with recording(self, False) as sbuf:
1135 # False because there's no need to write "skipped test" to the
1137 # Once by the Python unittest framework, and a second time by us.
1138 print("skipped test", file=sbuf)
1140 def markUnexpectedSuccess(self, bugnumber):
1141 """Callback invoked when an unexpected success occurred."""
1142 self.__unexpected__ = True
1143 with recording(self, False) as sbuf:
1144 # False because there's no need to write "unexpected success" to the
1146 # Once by the Python unittest framework, and a second time by us.
1147 if bugnumber is None:
1148 print("unexpected success", file=sbuf)
1151 "unexpected success (problem id:" + str(bugnumber) + ")",
1154 def getRerunArgs(self):
1155 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName)
1157 def getLogBasenameForCurrentTest(self, prefix=None):
1159 returns a partial path that can be used as the beginning of the name of multiple
1160 log files pertaining to this test
1162 <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method>
1164 dname = os.path.join(configuration.test_src_root,
1165 os.environ["LLDB_SESSION_DIRNAME"])
1166 if not os.path.isdir(dname):
1170 if prefix is not None:
1171 components.append(prefix)
1172 for c in configuration.session_file_format:
1174 components.append(self.__class__.__module__)
1176 components.append(self.__class__.__name__)
1178 compiler = self.getCompiler()
1180 if compiler[1] == ':':
1181 compiler = compiler[2:]
1182 if os.path.altsep is not None:
1183 compiler = compiler.replace(os.path.altsep, os.path.sep)
1184 path_components = [x for x in compiler.split(os.path.sep) if x != ""]
1186 # Add at most 4 path components to avoid generating very long
1188 components.extend(path_components[-4:])
1190 components.append(self.getArchitecture())
1192 components.append(self.testMethodName)
1193 fname = "-".join(components)
1195 return os.path.join(dname, fname)
1197 def dumpSessionInfo(self):
1199 Dump the debugger interactions leading to a test error/failure. This
1200 allows for more convenient postmortem analysis.
1202 See also LLDBTestResult (dotest.py) which is a singlton class derived
1203 from TextTestResult and overwrites addError, addFailure, and
1204 addExpectedFailure methods to allow us to to mark the test instance as
1208 # We are here because self.tearDown() detected that this test instance
1209 # either errored or failed. The lldb.test_result singleton contains
1210 # two lists (errors and failures) which get populated by the unittest
1211 # framework. Look over there for stack trace information.
1213 # The lists contain 2-tuples of TestCase instances and strings holding
1214 # formatted tracebacks.
1216 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1218 # output tracebacks into session
1220 if self.__errored__:
1221 pairs = configuration.test_result.errors
1223 elif self.__cleanup_errored__:
1224 pairs = configuration.test_result.cleanup_errors
1225 prefix = 'CleanupError'
1226 elif self.__failed__:
1227 pairs = configuration.test_result.failures
1229 elif self.__expected__:
1230 pairs = configuration.test_result.expectedFailures
1231 prefix = 'ExpectedFailure'
1232 elif self.__skipped__:
1233 prefix = 'SkippedTest'
1234 elif self.__unexpected__:
1235 prefix = 'UnexpectedSuccess'
1239 if not self.__unexpected__ and not self.__skipped__:
1240 for test, traceback in pairs:
1242 print(traceback, file=self.session)
1246 "Session info generated @",
1247 datetime.datetime.now().ctime(),
1249 self.session.close()
1252 # process the log files
1253 if prefix != 'Success' or lldbtest_config.log_success:
1254 # keep all log files, rename them to include prefix
1255 src_log_basename = self.getLogBasenameForCurrentTest(None)
1256 dst_log_basename = self.getLogBasenameForCurrentTest(prefix)
1257 for src in self.log_files:
1258 if os.path.isfile(src):
1259 dst = src.replace(src_log_basename, dst_log_basename)
1260 if os.name == "nt" and os.path.isfile(dst):
1261 # On Windows, renaming a -> b will throw an exception if
1262 # b exists. On non-Windows platforms it silently
1263 # replaces the destination. Ultimately this means that
1264 # atomic renames are not guaranteed to be possible on
1265 # Windows, but we need this to work anyway, so just
1266 # remove the destination first if it already exists.
1269 lldbutil.mkdir_p(os.path.dirname(dst))
1272 # success! (and we don't want log files) delete log files
1273 for log_file in self.log_files:
1274 if os.path.isfile(log_file):
1275 remove_file(log_file)
1277 # ====================================================
1278 # Config. methods supported through a plugin interface
1279 # (enables reading of the current test configuration)
1280 # ====================================================
1283 """Returns true if the architecture is MIPS."""
1284 arch = self.getArchitecture()
1285 if re.match("mips", arch):
1289 def isPPC64le(self):
1290 """Returns true if the architecture is PPC64LE."""
1291 arch = self.getArchitecture()
1292 if re.match("powerpc64le", arch):
1296 def isAArch64SVE(self):
1297 triple = self.dbg.GetSelectedPlatform().GetTriple()
1299 # TODO other platforms, please implement this function
1300 if not re.match(".*-.*-linux", triple):
1303 # Need to do something different for non-Linux/Android targets
1304 cpuinfo_path = self.getBuildArtifact("cpuinfo")
1305 if configuration.lldb_platform_name:
1306 self.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path)
1308 cpuinfo_path = "/proc/cpuinfo"
1311 f = open(cpuinfo_path, 'r')
1317 return " sve " in cpuinfo
1319 def getArchitecture(self):
1320 """Returns the architecture in effect the test suite is running with."""
1321 module = builder_module()
1322 arch = module.getArchitecture()
1325 if arch in ['armv7l', 'armv8l'] :
1329 def getLldbArchitecture(self):
1330 """Returns the architecture of the lldb binary."""
1331 if not hasattr(self, 'lldbArchitecture'):
1333 # spawn local process
1335 lldbtest_config.lldbExec,
1337 "file " + lldbtest_config.lldbExec,
1342 output = check_output(command)
1343 str = output.decode("utf-8")
1345 for line in str.splitlines():
1347 "Current executable set to '.*' \\((.*)\\)\\.", line)
1349 self.lldbArchitecture = m.group(1)
1352 return self.lldbArchitecture
1354 def getCompiler(self):
1355 """Returns the compiler in effect the test suite is running with."""
1356 module = builder_module()
1357 return module.getCompiler()
1359 def getCompilerBinary(self):
1360 """Returns the compiler binary the test suite is running with."""
1361 return self.getCompiler().split()[0]
1363 def getCompilerVersion(self):
1364 """ Returns a string that represents the compiler version.
1365 Supports: llvm, clang.
1367 compiler = self.getCompilerBinary()
1368 version_output = system([[compiler, "--version"]])
1369 for line in version_output.split(os.linesep):
1370 m = re.search('version ([0-9.]+)', line)
1375 def getDwarfVersion(self):
1376 """ Returns the dwarf version generated by clang or '0'. """
1377 if configuration.dwarf_version:
1378 return str(configuration.dwarf_version)
1379 if 'clang' in self.getCompiler():
1381 driver_output = check_output(
1382 [self.getCompiler()] + '-g -c -x c - -o - -###'.split(),
1384 driver_output = driver_output.decode("utf-8")
1385 for line in driver_output.split(os.linesep):
1386 m = re.search('dwarf-version=([0-9])', line)
1392 def platformIsDarwin(self):
1393 """Returns true if the OS triple for the selected platform is any valid apple OS"""
1394 return lldbplatformutil.platformIsDarwin()
1396 def hasDarwinFramework(self):
1397 return self.darwinWithFramework
1399 def getPlatform(self):
1400 """Returns the target platform the test suite is running on."""
1401 return lldbplatformutil.getPlatform()
1403 def isIntelCompiler(self):
1404 """ Returns true if using an Intel (ICC) compiler, false otherwise. """
1405 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]])
1407 def expectedCompilerVersion(self, compiler_version):
1408 """Returns True iff compiler_version[1] matches the current compiler version.
1409 Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1410 Any operator other than the following defaults to an equality test:
1411 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1413 If the current compiler version cannot be determined, we assume it is close to the top
1414 of trunk, so any less-than or equal-to comparisons will return False, and any
1415 greater-than or not-equal-to comparisons will return True.
1417 if compiler_version is None:
1419 operator = str(compiler_version[0])
1420 version = compiler_version[1]
1425 test_compiler_version = self.getCompilerVersion()
1426 if test_compiler_version == 'unknown':
1427 # Assume the compiler version is at or near the top of trunk.
1428 return operator in ['>', '>=', '!', '!=', 'not']
1431 return LooseVersion(test_compiler_version) > LooseVersion(version)
1432 if operator == '>=' or operator == '=>':
1433 return LooseVersion(test_compiler_version) >= LooseVersion(version)
1435 return LooseVersion(test_compiler_version) < LooseVersion(version)
1436 if operator == '<=' or operator == '=<':
1437 return LooseVersion(test_compiler_version) <= LooseVersion(version)
1438 if operator == '!=' or operator == '!' or operator == 'not':
1439 return str(version) not in str(test_compiler_version)
1440 return str(version) in str(test_compiler_version)
1442 def expectedCompiler(self, compilers):
1443 """Returns True iff any element of compilers is a sub-string of the current compiler."""
1444 if (compilers is None):
1447 for compiler in compilers:
1448 if compiler in self.getCompiler():
1453 def expectedArch(self, archs):
1454 """Returns True iff any element of archs is a sub-string of the current architecture."""
1459 if arch in self.getArchitecture():
1464 def getRunOptions(self):
1465 """Command line option for -A and -C to run this test again, called from
1466 self.dumpSessionInfo()."""
1467 arch = self.getArchitecture()
1468 comp = self.getCompiler()
1471 option_str = "-A " + arch
1473 option_str += " -C " + comp
1476 def getDebugInfo(self):
1477 method = getattr(self, self.testMethodName)
1478 return getattr(method, "debug_info", None)
1480 # ==================================================
1481 # Build methods supported through a plugin interface
1482 # ==================================================
1484 def getstdlibFlag(self):
1485 """ Returns the proper -stdlib flag, or empty if not required."""
1486 if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd":
1487 stdlibflag = "-stdlib=libc++"
1488 else: # this includes NetBSD
1492 def getstdFlag(self):
1493 """ Returns the proper stdflag. """
1494 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
1495 stdflag = "-std=c++0x"
1497 stdflag = "-std=c++11"
1500 def buildDriver(self, sources, exe_name):
1501 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so
1504 stdflag = self.getstdFlag()
1505 stdlibflag = self.getstdlibFlag()
1507 lib_dir = configuration.lldb_libs_dir
1508 if self.hasDarwinFramework():
1509 d = {'CXX_SOURCES': sources,
1511 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag),
1512 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir,
1513 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.lib_lldb, self.framework_dir),
1515 elif sys.platform.startswith('win'):
1517 'CXX_SOURCES': sources,
1519 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag,
1522 os.environ["LLDB_SRC"],
1524 'LD_EXTRAS': "-L%s -lliblldb" % lib_dir}
1527 'CXX_SOURCES': sources,
1529 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag,
1532 os.environ["LLDB_SRC"],
1534 'LD_EXTRAS': "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)}
1537 "Building LLDB Driver (%s) from sources %s" %
1538 (exe_name, sources))
1540 self.buildDefault(dictionary=d)
1542 def buildLibrary(self, sources, lib_name):
1543 """Platform specific way to build a default library. """
1545 stdflag = self.getstdFlag()
1547 lib_dir = configuration.lldb_libs_dir
1548 if self.hasDarwinFramework():
1549 d = {'DYLIB_CXX_SOURCES': sources,
1550 'DYLIB_NAME': lib_name,
1551 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag,
1552 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir,
1553 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.lib_lldb, self.framework_dir),
1555 elif self.getPlatform() == 'windows':
1557 'DYLIB_CXX_SOURCES': sources,
1558 'DYLIB_NAME': lib_name,
1559 'CFLAGS_EXTRAS': "%s -I%s " % (stdflag,
1561 os.environ["LLDB_SRC"],
1563 'LD_EXTRAS': "-shared -l%s\liblldb.lib" % lib_dir}
1566 'DYLIB_CXX_SOURCES': sources,
1567 'DYLIB_NAME': lib_name,
1568 'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag,
1570 os.environ["LLDB_SRC"],
1572 'LD_EXTRAS': "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)}
1575 "Building LLDB Library (%s) from sources %s" %
1576 (lib_name, sources))
1578 self.buildDefault(dictionary=d)
1580 def buildProgram(self, sources, exe_name):
1581 """ Platform specific way to build an executable from C/C++ sources. """
1582 d = {'CXX_SOURCES': sources,
1584 self.buildDefault(dictionary=d)
1591 """Platform specific way to build the default binaries."""
1592 testdir = self.mydir
1593 testname = self.getBuildDirBasename()
1594 if self.getDebugInfo():
1595 raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE")
1596 module = builder_module()
1597 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1598 if not module.buildDefault(self, architecture, compiler,
1599 dictionary, testdir, testname):
1600 raise Exception("Don't know how to build default binary")
1607 """Platform specific way to build binaries with dsym info."""
1608 testdir = self.mydir
1609 testname = self.getBuildDirBasename()
1610 if self.getDebugInfo() != "dsym":
1611 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1613 module = builder_module()
1614 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1615 if not module.buildDsym(self, architecture, compiler,
1616 dictionary, testdir, testname):
1617 raise Exception("Don't know how to build binary with dsym")
1624 """Platform specific way to build binaries with dwarf maps."""
1625 testdir = self.mydir
1626 testname = self.getBuildDirBasename()
1627 if self.getDebugInfo() != "dwarf":
1628 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1630 module = builder_module()
1631 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1632 if not module.buildDwarf(self, architecture, compiler,
1633 dictionary, testdir, testname):
1634 raise Exception("Don't know how to build binary with dwarf")
1641 """Platform specific way to build binaries with dwarf maps."""
1642 testdir = self.mydir
1643 testname = self.getBuildDirBasename()
1644 if self.getDebugInfo() != "dwo":
1645 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1647 module = builder_module()
1648 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1649 if not module.buildDwo(self, architecture, compiler,
1650 dictionary, testdir, testname):
1651 raise Exception("Don't know how to build binary with dwo")
1658 """Platform specific way to build binaries with gmodules info."""
1659 testdir = self.mydir
1660 testname = self.getBuildDirBasename()
1661 if self.getDebugInfo() != "gmodules":
1662 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1664 module = builder_module()
1665 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1666 if not module.buildGModules(self, architecture, compiler,
1667 dictionary, testdir, testname):
1668 raise Exception("Don't know how to build binary with gmodules")
1670 def signBinary(self, binary_path):
1671 if sys.platform.startswith("darwin"):
1672 codesign_cmd = "codesign --force --sign \"%s\" %s" % (
1673 lldbtest_config.codesign_identity, binary_path)
1674 call(codesign_cmd, shell=True)
1676 def findBuiltClang(self):
1677 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
1679 "llvm-build/Release+Asserts/x86_64/bin/clang",
1680 "llvm-build/Debug+Asserts/x86_64/bin/clang",
1681 "llvm-build/Release/x86_64/bin/clang",
1682 "llvm-build/Debug/x86_64/bin/clang",
1684 lldb_root_path = os.path.join(
1685 os.path.dirname(__file__), "..", "..", "..", "..")
1686 for p in paths_to_try:
1687 path = os.path.join(lldb_root_path, p)
1688 if os.path.exists(path):
1691 # Tries to find clang at the same folder as the lldb
1692 lldb_dir = os.path.dirname(lldbtest_config.lldbExec)
1693 path = distutils.spawn.find_executable("clang", lldb_dir)
1694 if path is not None:
1697 return os.environ["CC"]
1700 def yaml2obj(self, yaml_path, obj_path):
1702 Create an object file at the given path from a yaml file.
1704 Throws subprocess.CalledProcessError if the object could not be created.
1706 yaml2obj_bin = configuration.get_yaml2obj_path()
1707 if not yaml2obj_bin:
1708 self.assertTrue(False, "No valid yaml2obj executable specified")
1709 command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path]
1716 use_libstdcxx=False):
1717 """ Returns a dictionary (which can be provided to build* functions above) which
1718 contains OS-specific build flags.
1723 # On Mac OS X, unless specifically requested to use libstdc++, use
1725 if not use_libstdcxx and self.platformIsDarwin():
1728 if use_libcxx and self.libcxxPath:
1729 cflags += "-stdlib=libc++ "
1731 libcxxInclude = os.path.join(self.libcxxPath, "include")
1732 libcxxLib = os.path.join(self.libcxxPath, "lib")
1733 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib):
1734 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (
1735 libcxxInclude, libcxxLib, libcxxLib)
1739 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
1743 if self.platformIsDarwin() or self.getPlatform() == "freebsd":
1744 cflags += " -stdlib=libc++"
1745 elif self.getPlatform() == "openbsd":
1746 cflags += " -stdlib=libc++"
1747 elif self.getPlatform() == "netbsd":
1748 # NetBSD defaults to libc++
1750 elif "clang" in self.getCompiler():
1751 cflags += " -stdlib=libstdc++"
1753 return {'CFLAGS_EXTRAS': cflags,
1754 'LD_EXTRAS': ldflags,
1757 def cleanup(self, dictionary=None):
1758 """Platform specific way to do cleanup after build."""
1759 module = builder_module()
1760 if not module.cleanup(self, dictionary):
1762 "Don't know how to do cleanup with dictionary: " +
1765 def getLLDBLibraryEnvVal(self):
1766 """ Returns the path that the OS-specific library search environment variable
1767 (self.dylibPath) should be set to in order for a program to find the LLDB
1768 library. If an environment variable named self.dylibPath is already set,
1769 the new path is appended to it and returned.
1771 existing_library_path = os.environ[
1772 self.dylibPath] if self.dylibPath in os.environ else None
1773 if existing_library_path:
1774 return "%s:%s" % (existing_library_path, configuration.lldb_libs_dir)
1775 if sys.platform.startswith("darwin") and configuration.lldb_framework_path:
1776 return configuration.lldb_framework_path
1777 return configuration.lldb_libs_dir
1779 def getLibcPlusPlusLibs(self):
1780 if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'):
1781 return ['libc++.so.1']
1783 return ['libc++.1.dylib', 'libc++abi.']
1785 # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
1786 # We change the test methods to create a new test method for each test for each debug info we are
1787 # testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
1788 # the new test method we remove the old method at the same time. This functionality can be
1789 # supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test
1790 # level by using the decorator @no_debug_info_test.
1793 class LLDBTestCaseFactory(type):
1795 def __new__(cls, name, bases, attrs):
1796 original_testcase = super(
1797 LLDBTestCaseFactory, cls).__new__(
1798 cls, name, bases, attrs)
1799 if original_testcase.NO_DEBUG_INFO_TESTCASE:
1800 return original_testcase
1803 for attrname, attrvalue in attrs.items():
1804 if attrname.startswith("test") and not getattr(
1805 attrvalue, "__no_debug_info_test__", False):
1807 # If any debug info categories were explicitly tagged, assume that list to be
1808 # authoritative. If none were specified, try with all debug
1810 all_dbginfo_categories = set(test_categories.debug_info_categories)
1815 [])) & all_dbginfo_categories
1817 categories = all_dbginfo_categories
1819 for cat in categories:
1820 @decorators.add_test_categories([cat])
1822 def test_method(self, attrvalue=attrvalue):
1823 return attrvalue(self)
1825 method_name = attrname + "_" + cat
1826 test_method.__name__ = method_name
1827 test_method.debug_info = cat
1828 newattrs[method_name] = test_method
1831 newattrs[attrname] = attrvalue
1833 LLDBTestCaseFactory,
1840 # Setup the metaclass for this class to change the list of the test
1841 # methods when a new class is loaded
1844 @add_metaclass(LLDBTestCaseFactory)
1845 class TestBase(Base):
1847 This abstract base class is meant to be subclassed. It provides default
1848 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1851 Important things for test class writers:
1853 - Overwrite the mydir class attribute, otherwise your test class won't
1854 run. It specifies the relative directory to the top level 'test' so
1855 the test harness can change to the correct working directory before
1858 - The setUp method sets up things to facilitate subsequent interactions
1859 with the debugger as part of the test. These include:
1860 - populate the test method name
1861 - create/get a debugger set with synchronous mode (self.dbg)
1862 - get the command interpreter from with the debugger (self.ci)
1863 - create a result object for use with the command interpreter
1867 - The tearDown method tries to perform some necessary cleanup on behalf
1868 of the test to return the debugger to a good state for the next test.
1870 - execute any tearDown hooks registered by the test method with
1871 TestBase.addTearDownHook(); examples can be found in
1872 settings/TestSettings.py
1873 - kill the inferior process associated with each target, if any,
1874 and, then delete the target from the debugger's target list
1875 - perform build cleanup before running the next test method in the
1876 same test class; examples of registering for this service can be
1877 found in types/TestIntegerTypes.py with the call:
1878 - self.setTearDownCleanup(dictionary=d)
1880 - Similarly setUpClass and tearDownClass perform classwise setup and
1881 teardown fixtures. The tearDownClass method invokes a default build
1882 cleanup for the entire test class; also, subclasses can implement the
1883 classmethod classCleanup(cls) to perform special class cleanup action.
1885 - The instance methods runCmd and expect are used heavily by existing
1886 test cases to send a command to the command interpreter and to perform
1887 string/pattern matching on the output of such command execution. The
1888 expect method also provides a mode to peform string/pattern matching
1889 without running a command.
1891 - The build methods buildDefault, buildDsym, and buildDwarf are used to
1892 build the binaries used during a particular test scenario. A plugin
1893 should be provided for the sys.platform running the test suite. The
1894 Mac OS X implementation is located in builders/darwin.py.
1897 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the
1898 # test multiple times with various debug info types.
1899 NO_DEBUG_INFO_TESTCASE = False
1901 # Maximum allowed attempts when launching the inferior process.
1902 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1905 # Time to wait before the next launching attempt in second(s).
1906 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1907 timeWaitNextLaunch = 1.0
1909 def generateSource(self, source):
1910 template = source + '.template'
1911 temp = os.path.join(self.getSourceDir(), template)
1912 with open(temp, 'r') as f:
1915 public_api_dir = os.path.join(
1916 os.environ["LLDB_SRC"], "include", "lldb", "API")
1918 # Look under the include/lldb/API directory and add #include statements
1919 # for all the SB API headers.
1920 public_headers = os.listdir(public_api_dir)
1921 # For different platforms, the include statement can vary.
1922 if self.hasDarwinFramework():
1923 include_stmt = "'#include <%s>' % os.path.join('LLDB', header)"
1925 include_stmt = "'#include <%s>' % os.path.join('" + public_api_dir + "', header)"
1926 list = [eval(include_stmt) for header in public_headers if (
1927 header.startswith("SB") and header.endswith(".h"))]
1928 includes = '\n'.join(list)
1929 new_content = content.replace('%include_SB_APIs%', includes)
1930 new_content = new_content.replace('%SOURCE_DIR%', self.getSourceDir())
1931 src = os.path.join(self.getBuildDir(), source)
1932 with open(src, 'w') as f:
1933 f.write(new_content)
1935 self.addTearDownHook(lambda: os.remove(src))
1938 # Works with the test driver to conditionally skip tests via
1942 for s in self.setUpCommands():
1945 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1946 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1948 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
1949 self.timeWaitNextLaunch = float(
1950 os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1952 # We want our debugger to be synchronous.
1953 self.dbg.SetAsync(False)
1955 # Retrieve the associated command interpreter instance.
1956 self.ci = self.dbg.GetCommandInterpreter()
1958 raise Exception('Could not get the command interpreter')
1960 # And the result object.
1961 self.res = lldb.SBCommandReturnObject()
1963 def registerSharedLibrariesWithTarget(self, target, shlibs):
1964 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
1966 Any modules in the target that have their remote install file specification set will
1967 get uploaded to the remote host. This function registers the local copies of the
1968 shared libraries with the target and sets their remote install locations so they will
1969 be uploaded when the target is run.
1971 if not shlibs or not self.platformContext:
1974 shlib_environment_var = self.platformContext.shlib_environment_var
1975 shlib_prefix = self.platformContext.shlib_prefix
1976 shlib_extension = '.' + self.platformContext.shlib_extension
1979 # Add any shared libraries to our target if remote so they get
1980 # uploaded into the working directory on the remote side
1982 # The path can be a full path to a shared library, or a make file name like "Foo" for
1983 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
1984 # basename like "libFoo.so". So figure out which one it is and resolve the local copy
1985 # of the shared library accordingly
1986 if os.path.isfile(name):
1987 local_shlib_path = name # name is the full path to the local shared library
1989 # Check relative names
1990 local_shlib_path = os.path.join(
1991 self.getBuildDir(), shlib_prefix + name + shlib_extension)
1992 if not os.path.exists(local_shlib_path):
1993 local_shlib_path = os.path.join(
1994 self.getBuildDir(), name + shlib_extension)
1995 if not os.path.exists(local_shlib_path):
1996 local_shlib_path = os.path.join(self.getBuildDir(), name)
1998 # Make sure we found the local shared library in the above code
1999 self.assertTrue(os.path.exists(local_shlib_path))
2002 # Add the shared library to our target
2003 shlib_module = target.AddModule(local_shlib_path, None, None, None)
2004 if lldb.remote_platform:
2005 # We must set the remote install location if we want the shared library
2006 # to get uploaded to the remote target
2007 remote_shlib_path = lldbutil.append_to_process_working_directory(self,
2008 os.path.basename(local_shlib_path))
2009 shlib_module.SetRemoteInstallFileSpec(
2010 lldb.SBFileSpec(remote_shlib_path, False))
2011 dir_to_add = self.get_process_working_directory()
2013 dir_to_add = os.path.dirname(local_shlib_path)
2015 if dir_to_add not in dirs:
2016 dirs.append(dir_to_add)
2018 env_value = self.platformContext.shlib_path_separator.join(dirs)
2019 return ['%s=%s' % (shlib_environment_var, env_value)]
2021 def registerSanitizerLibrariesWithTarget(self, target):
2023 for m in target.module_iter():
2024 libspec = m.GetFileSpec()
2025 if "clang_rt" in libspec.GetFilename():
2026 runtimes.append(os.path.join(libspec.GetDirectory(),
2027 libspec.GetFilename()))
2028 return self.registerSharedLibrariesWithTarget(target, runtimes)
2030 # utility methods that tests can use to access the current objects
2033 raise Exception('Invalid debugger instance')
2034 return self.dbg.GetSelectedTarget()
2038 raise Exception('Invalid debugger instance')
2039 return self.dbg.GetSelectedTarget().GetProcess()
2043 raise Exception('Invalid debugger instance')
2044 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
2048 raise Exception('Invalid debugger instance')
2049 return self.dbg.GetSelectedTarget().GetProcess(
2050 ).GetSelectedThread().GetSelectedFrame()
2052 def get_process_working_directory(self):
2053 '''Get the working directory that should be used when launching processes for local or remote processes.'''
2054 if lldb.remote_platform:
2055 # Remote tests set the platform working directory up in
2057 return lldb.remote_platform.GetWorkingDirectory()
2059 # local tests change directory into each test subdirectory
2060 return self.getBuildDir()
2063 # Ensure all the references to SB objects have gone away so that we can
2064 # be sure that all test-specific resources have been freed before we
2065 # attempt to delete the targets.
2068 # Delete the target(s) from the debugger as a general cleanup step.
2069 # This includes terminating the process for each target, if any.
2070 # We'd like to reuse the debugger for our next test without incurring
2071 # the initialization overhead.
2073 for target in self.dbg:
2075 targets.append(target)
2076 process = target.GetProcess()
2078 rc = self.invoke(process, "Kill")
2080 for target in targets:
2081 self.dbg.DeleteTarget(target)
2083 if not configuration.is_reproducer():
2084 # Assert that all targets are deleted.
2085 self.assertEqual(self.dbg.GetNumTargets(), 0)
2087 # Do this last, to make sure it's in reverse order from how we setup.
2090 def switch_to_thread_with_stop_reason(self, stop_reason):
2092 Run the 'thread list' command, and select the thread with stop reason as
2093 'stop_reason'. If no such thread exists, no select action is done.
2095 from .lldbutil import stop_reason_to_str
2096 self.runCmd('thread list')
2097 output = self.res.GetOutput()
2098 thread_line_pattern = re.compile(
2099 "^[ *] thread #([0-9]+):.*stop reason = %s" %
2100 stop_reason_to_str(stop_reason))
2101 for line in output.splitlines():
2102 matched = thread_line_pattern.match(line)
2104 self.runCmd('thread select %s' % matched.group(1))
2106 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False):
2108 Ask the command interpreter to handle the command and then check its
2111 # Fail fast if 'cmd' is not meaningful.
2112 if not cmd or len(cmd) == 0:
2113 raise Exception("Bad 'cmd' parameter encountered")
2115 trace = (True if traceAlways else trace)
2117 if cmd.startswith("target create "):
2118 cmd = cmd.replace("target create ", "file ")
2120 running = (cmd.startswith("run") or cmd.startswith("process launch"))
2122 for i in range(self.maxLaunchCount if running else 1):
2123 self.ci.HandleCommand(cmd, self.res, inHistory)
2125 with recording(self, trace) as sbuf:
2126 print("runCmd:", cmd, file=sbuf)
2128 print("check of return status not required", file=sbuf)
2129 if self.res.Succeeded():
2130 print("output:", self.res.GetOutput(), file=sbuf)
2132 print("runCmd failed!", file=sbuf)
2133 print(self.res.GetError(), file=sbuf)
2135 if self.res.Succeeded():
2138 # For process launch, wait some time before possible next try.
2139 time.sleep(self.timeWaitNextLaunch)
2140 with recording(self, trace) as sbuf:
2141 print("Command '" + cmd + "' failed!", file=sbuf)
2145 if self.res.GetOutput():
2146 output += "\nCommand output:\n" + self.res.GetOutput()
2147 if self.res.GetError():
2148 output += "\nError output:\n" + self.res.GetError()
2153 self.assertTrue(self.res.Succeeded(),
2154 msg if (msg) else CMD_MSG(cmd))
2165 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2167 Otherwise, all the arguments have the same meanings as for the expect function"""
2169 trace = (True if traceAlways else trace)
2172 # First run the command. If we are expecting error, set check=False.
2173 # Pass the assert message along since it provides more semantic
2179 True if trace else False),
2182 # Then compare the output against expected strings.
2183 output = self.res.GetError() if error else self.res.GetOutput()
2185 # If error is True, the API client expects the command to fail!
2187 self.assertFalse(self.res.Succeeded(),
2188 "Command '" + str + "' is expected to fail!")
2190 # No execution required, just compare str against the golden input.
2192 with recording(self, trace) as sbuf:
2193 print("looking at:", output, file=sbuf)
2195 # The heading says either "Expecting" or "Not expecting".
2196 heading = "Expecting" if matching else "Not expecting"
2198 for pattern in patterns:
2199 # Match Objects always have a boolean value of True.
2200 match_object = re.search(pattern, output)
2201 matched = bool(match_object)
2202 with recording(self, trace) as sbuf:
2203 print("%s pattern: %s" % (heading, pattern), file=sbuf)
2204 print("Matched" if matched else "Not matched", file=sbuf)
2208 self.assertTrue(matched if matching else not matched,
2209 msg if msg else EXP_MSG(str, output, exe))
2213 def check_completion_with_desc(self, str_input, match_desc_pairs, enforce_order=False):
2215 Checks that when the given input is completed at the given list of
2216 completions and descriptions is returned.
2217 :param str_input: The input that should be completed. The completion happens at the end of the string.
2218 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of
2219 completions returned by LLDB. The first element of the pair is the completion
2220 string that LLDB should generate and the second element the description.
2221 :param enforce_order: True iff the order in which the completions are returned by LLDB
2222 should match the order of the match_desc_pairs pairs.
2224 interp = self.dbg.GetCommandInterpreter()
2225 match_strings = lldb.SBStringList()
2226 description_strings = lldb.SBStringList()
2227 num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings)
2228 self.assertEqual(len(description_strings), len(match_strings))
2230 # The index of the last matched description in description_strings or
2231 # -1 if no description has been matched yet.
2232 last_found_index = -1
2233 out_of_order_errors = ""
2235 for pair in match_desc_pairs:
2237 for i in range(num_matches + 1):
2238 match_candidate = match_strings.GetStringAtIndex(i)
2239 description_candidate = description_strings.GetStringAtIndex(i)
2240 if match_candidate == pair[0] and description_candidate == pair[1]:
2242 if enforce_order and last_found_index > i:
2243 new_err = ("Found completion " + pair[0] + " at index " +
2244 str(i) + " in returned completion list but " +
2245 "should have been after completion " +
2246 match_strings.GetStringAtIndex(last_found_index) +
2247 " (index:" + str(last_found_index) + ")\n")
2248 out_of_order_errors += new_err
2249 last_found_index = i
2252 missing_pairs.append(pair)
2256 if len(missing_pairs):
2258 error_msg += "Missing pairs:\n"
2259 for pair in missing_pairs:
2260 error_msg += " [" + pair[0] + ":" + pair[1] + "]\n"
2261 if len(out_of_order_errors):
2263 error_msg += out_of_order_errors
2265 error_msg += "Got the following " + str(num_matches) + " completions back:\n"
2266 for i in range(num_matches + 1):
2267 match_candidate = match_strings.GetStringAtIndex(i)
2268 description_candidate = description_strings.GetStringAtIndex(i)
2269 error_msg += "[" + match_candidate + ":" + description_candidate + "] index " + str(i) + "\n"
2270 self.assertFalse(got_failure, error_msg)
2272 def complete_exactly(self, str_input, patterns):
2273 self.complete_from_to(str_input, patterns, True)
2275 def complete_from_to(self, str_input, patterns, turn_off_re_match=False):
2276 """Test that the completion mechanism completes str_input to patterns,
2277 where patterns could be a pattern-string or a list of pattern-strings"""
2278 # Patterns should not be None in order to proceed.
2279 self.assertFalse(patterns is None)
2280 # And should be either a string or list of strings. Check for list type
2281 # below, if not, make a list out of the singleton string. If patterns
2282 # is not a string or not a list of strings, there'll be runtime errors
2284 if not isinstance(patterns, list):
2285 patterns = [patterns]
2287 interp = self.dbg.GetCommandInterpreter()
2288 match_strings = lldb.SBStringList()
2289 num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
2290 common_match = match_strings.GetStringAtIndex(0)
2291 if num_matches == 0:
2292 compare_string = str_input
2294 if common_match != None and len(common_match) > 0:
2295 compare_string = str_input + common_match
2298 for idx in range(1, num_matches+1):
2299 compare_string += match_strings.GetStringAtIndex(idx) + "\n"
2302 if turn_off_re_match:
2304 compare_string, msg=COMPLETION_MSG(
2305 str_input, p, match_strings), exe=False, substrs=[p])
2308 compare_string, msg=COMPLETION_MSG(
2309 str_input, p, match_strings), exe=False, patterns=[p])
2311 def completions_match(self, command, completions):
2312 """Checks that the completions for the given command are equal to the
2313 given list of completions"""
2314 interp = self.dbg.GetCommandInterpreter()
2315 match_strings = lldb.SBStringList()
2316 interp.HandleCompletion(command, len(command), 0, -1, match_strings)
2317 # match_strings is a 1-indexed list, so we have to slice...
2318 self.assertItemsEqual(completions, list(match_strings)[1:],
2319 "List of returned completion is wrong")
2321 def completions_contain(self, command, completions):
2322 """Checks that the completions for the given command contain the given
2323 list of completions."""
2324 interp = self.dbg.GetCommandInterpreter()
2325 match_strings = lldb.SBStringList()
2326 interp.HandleCompletion(command, len(command), 0, -1, match_strings)
2327 for completion in completions:
2328 # match_strings is a 1-indexed list, so we have to slice...
2329 self.assertIn(completion, list(match_strings)[1:],
2330 "Couldn't find expected completion")
2336 filecheck_options = '',
2337 expect_cmd_failure = False):
2341 check=(not expect_cmd_failure),
2342 msg="FileCheck'ing result of `{0}`".format(command))
2344 self.assertTrue((not expect_cmd_failure) == self.res.Succeeded())
2346 # Get the error text if there was an error, and the regular text if not.
2347 output = self.res.GetOutput() if self.res.Succeeded() \
2348 else self.res.GetError()
2350 # Assemble the absolute path to the check file. As a convenience for
2351 # LLDB inline tests, assume that the check file is a relative path to
2352 # a file within the inline test directory.
2353 if check_file.endswith('.pyc'):
2354 check_file = check_file[:-1]
2355 check_file_abs = os.path.abspath(check_file)
2358 filecheck_bin = configuration.get_filecheck_path()
2359 if not filecheck_bin:
2360 self.assertTrue(False, "No valid FileCheck executable specified")
2361 filecheck_args = [filecheck_bin, check_file_abs]
2362 if filecheck_options:
2363 filecheck_args.append(filecheck_options)
2364 subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True)
2365 cmd_stdout, cmd_stderr = subproc.communicate(input=output)
2366 cmd_status = subproc.returncode
2368 filecheck_cmd = " ".join(filecheck_args)
2369 filecheck_trace = """
2370 --- FileCheck trace (code={0}) ---
2379 """.format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr)
2381 trace = cmd_status != 0 or traceAlways
2382 with recording(self, trace) as sbuf:
2383 print(filecheck_trace, file=sbuf)
2385 self.assertTrue(cmd_status == 0)
2402 Similar to runCmd; with additional expect style output matching ability.
2404 Ask the command interpreter to handle the command and then check its
2405 return status. The 'msg' parameter specifies an informational assert
2406 message. We expect the output from running the command to start with
2407 'startstr', matches the substrings contained in 'substrs', and regexp
2408 matches the patterns contained in 'patterns'.
2410 When matching is true and ordered is true, which are both the default,
2411 the strings in the substrs array have to appear in the command output
2412 in the order in which they appear in the array.
2414 If the keyword argument error is set to True, it signifies that the API
2415 client is expecting the command to fail. In this case, the error stream
2416 from running the command is retrieved and compared against the golden
2419 If the keyword argument matching is set to False, it signifies that the API
2420 client is expecting the output of the command not to match the golden
2423 Finally, the required argument 'str' represents the lldb command to be
2424 sent to the command interpreter. In case the keyword argument 'exe' is
2425 set to False, the 'str' is treated as a string to be matched/not-matched
2426 against the golden input.
2428 # Catch cases where `expect` has been miscalled. Specifically, prevent
2429 # this easy to make mistake:
2430 # self.expect("lldb command", "some substr")
2431 # The `msg` parameter is used only when a failed match occurs. A failed
2432 # match can only occur when one of `patterns`, `startstr`, `endstr`, or
2433 # `substrs` has been given. Thus, if a `msg` is given, it's an error to
2434 # not also provide one of the matcher parameters.
2435 if msg and not (patterns or startstr or endstr or substrs or error):
2436 assert False, "expect() missing a matcher argument"
2438 # Check `patterns` and `substrs` are not accidentally given as strings.
2439 assert not isinstance(patterns, six.string_types), \
2440 "patterns must be a collection of strings"
2441 assert not isinstance(substrs, six.string_types), \
2442 "substrs must be a collection of strings"
2444 trace = (True if traceAlways else trace)
2447 # First run the command. If we are expecting error, set check=False.
2448 # Pass the assert message along since it provides more semantic
2454 True if trace else False),
2456 inHistory=inHistory)
2458 # Then compare the output against expected strings.
2459 output = self.res.GetError() if error else self.res.GetOutput()
2461 # If error is True, the API client expects the command to fail!
2463 self.assertFalse(self.res.Succeeded(),
2464 "Command '" + str + "' is expected to fail!")
2466 # No execution required, just compare str against the golden input.
2467 if isinstance(str, lldb.SBCommandReturnObject):
2468 output = str.GetOutput()
2471 with recording(self, trace) as sbuf:
2472 print("looking at:", output, file=sbuf)
2474 expecting_str = "Expecting" if matching else "Not expecting"
2475 def found_str(matched):
2476 return "was found" if matched else "was not found"
2478 # To be used as assert fail message and/or trace content
2480 "{}:".format("Ran command" if exe else "Checking string"),
2481 "\"{}\"".format(str),
2482 # Space out command and output
2486 # Newline before output to make large strings more readable
2487 log_lines.append("Got output:\n{}".format(output))
2489 # Assume that we start matched if we want a match
2490 # Meaning if you have no conditions, matching or
2491 # not matching will always pass
2494 # We will stop checking on first failure
2496 matched = output.startswith(startstr)
2497 log_lines.append("{} start string: \"{}\" ({})".format(
2498 expecting_str, startstr, found_str(matched)))
2500 if endstr and matched == matching:
2501 matched = output.endswith(endstr)
2502 log_lines.append("{} end string: \"{}\" ({})".format(
2503 expecting_str, endstr, found_str(matched)))
2505 if substrs and matched == matching:
2507 for substr in substrs:
2508 index = output[start:].find(substr)
2509 start = start + index if ordered and matching else 0
2510 matched = index != -1
2511 log_lines.append("{} sub string: \"{}\" ({})".format(
2512 expecting_str, substr, found_str(matched)))
2514 if matched != matching:
2517 if patterns and matched == matching:
2518 for pattern in patterns:
2519 matched = re.search(pattern, output)
2521 pattern_line = "{} regex pattern: \"{}\" ({}".format(
2522 expecting_str, pattern, found_str(matched))
2524 pattern_line += ", matched \"{}\"".format(
2527 log_lines.append(pattern_line)
2529 # Convert to bool because match objects
2530 # are True-ish but != True itself
2531 matched = bool(matched)
2532 if matched != matching:
2535 # If a check failed, add any extra assert message
2536 if msg is not None and matched != matching:
2537 log_lines.append(msg)
2539 log_msg = "\n".join(log_lines)
2540 with recording(self, trace) as sbuf:
2541 print(log_msg, file=sbuf)
2542 if matched != matching:
2548 result_summary=None,
2551 result_children=None
2554 Evaluates the given expression and verifies the result.
2555 :param expr: The expression as a string.
2556 :param result_summary: The summary that the expression should have. None if the summary should not be checked.
2557 :param result_value: The value that the expression should have. None if the value should not be checked.
2558 :param result_type: The type that the expression result should have. None if the type should not be checked.
2559 :param result_children: The expected children of the expression result
2560 as a list of ValueChecks. None if the children shouldn't be checked.
2562 self.assertTrue(expr.strip() == expr, "Expression contains trailing/leading whitespace: '" + expr + "'")
2564 frame = self.frame()
2565 options = lldb.SBExpressionOptions()
2567 # Disable fix-its that tests don't pass by accident.
2568 options.SetAutoApplyFixIts(False)
2570 # Set the usual default options for normal expressions.
2571 options.SetIgnoreBreakpoints(True)
2573 if self.frame().IsValid():
2574 options.SetLanguage(frame.GuessLanguage())
2575 eval_result = self.frame().EvaluateExpression(expr, options)
2577 target = self.target()
2578 # If there is no selected target, run the expression in the dummy
2580 if not target.IsValid():
2581 target = self.dbg.GetDummyTarget()
2582 eval_result = target.EvaluateExpression(expr, options)
2584 value_check = ValueCheck(type=result_type, value=result_value,
2585 summary=result_summary, children=result_children)
2586 value_check.check_value(self, eval_result, str(eval_result))
2589 def invoke(self, obj, name, trace=False):
2590 """Use reflection to call a method dynamically with no argument."""
2591 trace = (True if traceAlways else trace)
2593 method = getattr(obj, name)
2595 self.assertTrue(inspect.ismethod(method),
2596 name + "is a method name of object: " + str(obj))
2598 with recording(self, trace) as sbuf:
2599 print(str(method) + ":", result, file=sbuf)
2607 """Platform specific way to build the default binaries."""
2608 module = builder_module()
2610 if not architecture and configuration.arch:
2611 architecture = configuration.arch
2613 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
2614 if self.getDebugInfo() is None:
2615 return self.buildDefault(architecture, compiler, dictionary)
2616 elif self.getDebugInfo() == "dsym":
2617 return self.buildDsym(architecture, compiler, dictionary)
2618 elif self.getDebugInfo() == "dwarf":
2619 return self.buildDwarf(architecture, compiler, dictionary)
2620 elif self.getDebugInfo() == "dwo":
2621 return self.buildDwo(architecture, compiler, dictionary)
2622 elif self.getDebugInfo() == "gmodules":
2623 return self.buildGModules(architecture, compiler, dictionary)
2625 self.fail("Can't build for debug info: %s" % self.getDebugInfo())
2627 def run_platform_command(self, cmd):
2628 platform = self.dbg.GetSelectedPlatform()
2629 shell_command = lldb.SBPlatformShellCommand(cmd)
2630 err = platform.Run(shell_command)
2631 return (err, shell_command.GetStatus(), shell_command.GetOutput())
2633 """Assert that an lldb.SBError is in the "success" state."""
2634 def assertSuccess(self, obj, msg=None):
2635 if not obj.Success():
2636 error = obj.GetCString()
2637 self.fail(self._formatMessage(msg,
2638 "'{}' is not success".format(error)))
2640 # =================================================
2641 # Misc. helper methods for debugging test execution
2642 # =================================================
2644 def DebugSBValue(self, val):
2645 """Debug print a SBValue object, if traceAlways is True."""
2646 from .lldbutil import value_type_to_str
2652 err.write(val.GetName() + ":\n")
2653 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n')
2654 err.write('\t' + "ByteSize -> " +
2655 str(val.GetByteSize()) + '\n')
2656 err.write('\t' + "NumChildren -> " +
2657 str(val.GetNumChildren()) + '\n')
2658 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n')
2659 err.write('\t' + "ValueAsUnsigned -> " +
2660 str(val.GetValueAsUnsigned()) + '\n')
2665 val.GetValueType()) +
2667 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n')
2668 err.write('\t' + "IsPointerType -> " +
2669 str(val.TypeIsPointerType()) + '\n')
2670 err.write('\t' + "Location -> " + val.GetLocation() + '\n')
2672 def DebugSBType(self, type):
2673 """Debug print a SBType object, if traceAlways is True."""
2678 err.write(type.GetName() + ":\n")
2679 err.write('\t' + "ByteSize -> " +
2680 str(type.GetByteSize()) + '\n')
2681 err.write('\t' + "IsPointerType -> " +
2682 str(type.IsPointerType()) + '\n')
2683 err.write('\t' + "IsReferenceType -> " +
2684 str(type.IsReferenceType()) + '\n')
2686 def DebugPExpect(self, child):
2687 """Debug the spwaned pexpect object."""
2694 def RemoveTempFile(cls, file):
2695 if os.path.exists(file):
2698 # On Windows, the first attempt to delete a recently-touched file can fail
2699 # because of a race with antimalware scanners. This function will detect a
2700 # failure and retry.
2703 def remove_file(file, num_retries=1, sleep_duration=0.5):
2704 for i in range(num_retries + 1):
2709 time.sleep(sleep_duration)