[NFC][LLVM][CodeGen] Move LiveDebugVariables.h into llvm/include/llvm/CodeGen (#88374)
[llvm-project.git] / lldb / packages / Python / lldbsuite / test / lldbtest.py
blobc28a78a2c4a27aa1a2d64ad7588a713c6882b266
1 """
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
12 ...
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
16 compilers=['clang']
18 Configuration: arch=x86_64 compiler=clang
19 ----------------------------------------------------------------------
20 Collected 72 tests
22 ........................................................................
23 ----------------------------------------------------------------------
24 Ran 72 tests in 135.468s
28 """
30 # System modules
31 import abc
32 from functools import wraps
33 import gc
34 import glob
35 import io
36 import json
37 import os.path
38 import re
39 import shutil
40 import signal
41 from subprocess import *
42 import sys
43 import time
44 import traceback
46 # Third-party modules
47 import unittest
49 # LLDB modules
50 import lldb
51 from . import configuration
52 from . import decorators
53 from . import lldbplatformutil
54 from . import lldbtest_config
55 from . import lldbutil
56 from . import test_categories
57 from lldbsuite.support import encoded_file
58 from lldbsuite.support import funcutils
59 from lldbsuite.support import seven
60 from lldbsuite.test_event import build_exception
62 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
63 # LLDB_COMMAND_TRACE is set from '-t' option.
65 # By default, traceAlways is False.
66 if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"] == "YES":
67 traceAlways = True
68 else:
69 traceAlways = False
71 # By default, doCleanup is True.
72 if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"] == "NO":
73 doCleanup = False
74 else:
75 doCleanup = True
79 # Some commonly used assert messages.
82 COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
84 CURRENT_EXECUTABLE_SET = "Current executable set successfully"
86 PROCESS_IS_VALID = "Process is valid"
88 PROCESS_KILLED = "Process is killed successfully"
90 PROCESS_EXITED = "Process exited successfully"
92 PROCESS_STOPPED = "Process status should be stopped"
94 RUN_SUCCEEDED = "Process is launched successfully"
96 RUN_COMPLETED = "Process exited successfully"
98 BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
100 BREAKPOINT_CREATED = "Breakpoint created successfully"
102 BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
104 BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
106 BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit count = 1"
108 BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit count = 2"
110 BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit count = 3"
112 MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable."
114 OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
116 SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
118 STEP_IN_SUCCEEDED = "Thread step-in succeeded"
120 STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
122 STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
124 STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion"
126 STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
128 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
129 STOPPED_DUE_TO_BREAKPOINT,
130 "instead, the actual stop reason is: '%s'",
133 STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
135 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
137 STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION = (
138 "Stopped due to breakpoint jitted condition"
141 STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
143 STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
145 STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
147 DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
149 VALID_BREAKPOINT = "Got a valid breakpoint"
151 VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
153 VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
155 VALID_FILESPEC = "Got a valid filespec"
157 VALID_MODULE = "Got a valid module"
159 VALID_PROCESS = "Got a valid process"
161 VALID_SYMBOL = "Got a valid symbol"
163 VALID_TARGET = "Got a valid target"
165 VALID_PLATFORM = "Got a valid platform"
167 VALID_TYPE = "Got a valid type"
169 VALID_VARIABLE = "Got a valid variable"
171 VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
173 WATCHPOINT_CREATED = "Watchpoint created successfully"
176 def CMD_MSG(str):
177 """A generic "Command '%s' did not return successfully" message generator."""
178 return "Command '%s' did not return successfully" % str
181 def COMPLETION_MSG(str_before, str_after, completions):
182 """A generic assertion failed message generator for the completion mechanism."""
183 return "'%s' successfully completes to '%s', but completions were:\n%s" % (
184 str_before,
185 str_after,
186 "\n".join(completions),
190 def EXP_MSG(str, actual, exe):
191 """A generic "'%s' returned unexpected result" message generator if exe.
192 Otherwise, it generates "'%s' does not match expected result" message."""
194 return "'%s' %s result, got '%s'" % (
195 str,
196 "returned unexpected" if exe else "does not match expected",
197 actual.strip(),
201 def SETTING_MSG(setting):
202 """A generic "Value of setting '%s' is not correct" message generator."""
203 return "Value of setting '%s' is not correct" % setting
206 def line_number(filename, string_to_match):
207 """Helper function to return the line number of the first matched string."""
208 with io.open(filename, mode="r", encoding="utf-8") as f:
209 for i, line in enumerate(f):
210 if line.find(string_to_match) != -1:
211 # Found our match.
212 return i + 1
213 raise Exception("Unable to find '%s' within file %s" % (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 def pointer_size():
223 """Return the pointer size of the host system."""
224 import ctypes
226 a_pointer = ctypes.c_void_p(0xFFFF)
227 return 8 * ctypes.sizeof(a_pointer)
230 def is_exe(fpath):
231 """Returns true if fpath is an executable."""
232 if fpath == None:
233 return False
234 if sys.platform == "win32":
235 if not fpath.endswith(".exe"):
236 fpath += ".exe"
237 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
240 def which(program):
241 """Returns the full path to a program; None otherwise."""
242 fpath, fname = os.path.split(program)
243 if fpath:
244 if is_exe(program):
245 return program
246 else:
247 for path in os.environ["PATH"].split(os.pathsep):
248 exe_file = os.path.join(path, program)
249 if is_exe(exe_file):
250 return exe_file
251 return None
254 class ValueCheck:
255 def __init__(
256 self,
257 name=None,
258 value=None,
259 type=None,
260 summary=None,
261 children=None,
262 dereference=None,
265 :param name: The name that the SBValue should have. None if the summary
266 should not be checked.
267 :param summary: The summary that the SBValue should have. None if the
268 summary should not be checked.
269 :param value: The value that the SBValue should have. None if the value
270 should not be checked.
271 :param type: The type that the SBValue result should have. None if the
272 type should not be checked.
273 :param children: A list of ValueChecks that need to match the children
274 of this SBValue. None if children shouldn't be checked.
275 The order of checks is the order of the checks in the
276 list. The number of checks has to match the number of
277 children.
278 :param dereference: A ValueCheck for the SBValue returned by the
279 `Dereference` function.
281 self.expect_name = name
282 self.expect_value = value
283 self.expect_type = type
284 self.expect_summary = summary
285 self.children = children
286 self.dereference = dereference
288 def check_value(self, test_base, val, error_msg=None):
290 Checks that the given value matches the currently set properties
291 of this ValueCheck. If a match failed, the given TestBase will
292 be used to emit an error. A custom error message can be specified
293 that will be used to describe failed check for this SBValue (but
294 not errors in the child values).
297 this_error_msg = error_msg if error_msg else ""
298 this_error_msg += "\nChecking SBValue: " + str(val)
300 test_base.assertSuccess(val.GetError())
302 # Python 3.6 doesn't declare a `re.Pattern` type, get the dynamic type.
303 pattern_type = type(re.compile(""))
305 if self.expect_name:
306 test_base.assertEqual(self.expect_name, val.GetName(), this_error_msg)
307 if self.expect_value:
308 if isinstance(self.expect_value, pattern_type):
309 test_base.assertRegex(val.GetValue(), self.expect_value, this_error_msg)
310 else:
311 test_base.assertEqual(self.expect_value, val.GetValue(), this_error_msg)
312 if self.expect_type:
313 test_base.assertEqual(
314 self.expect_type, val.GetDisplayTypeName(), this_error_msg
316 if self.expect_summary:
317 if isinstance(self.expect_summary, pattern_type):
318 test_base.assertRegex(
319 val.GetSummary(), self.expect_summary, this_error_msg
321 else:
322 test_base.assertEqual(
323 self.expect_summary, val.GetSummary(), this_error_msg
325 if self.children is not None:
326 self.check_value_children(test_base, val, error_msg)
328 if self.dereference is not None:
329 self.dereference.check_value(test_base, val.Dereference(), error_msg)
331 def check_value_children(self, test_base, val, error_msg=None):
333 Checks that the children of a SBValue match a certain structure and
334 have certain properties.
336 :param test_base: The current test's TestBase object.
337 :param val: The SBValue to check.
340 this_error_msg = error_msg if error_msg else ""
341 this_error_msg += "\nChecking SBValue: " + str(val)
343 test_base.assertEqual(len(self.children), val.GetNumChildren(), this_error_msg)
345 for i in range(0, val.GetNumChildren()):
346 expected_child = self.children[i]
347 actual_child = val.GetChildAtIndex(i)
348 child_error = "Checking child with index " + str(i) + ":\n" + error_msg
349 expected_child.check_value(test_base, actual_child, child_error)
352 class recording(io.StringIO):
354 A nice little context manager for recording the debugger interactions into
355 our session object. If trace flag is ON, it also emits the interactions
356 into the stderr.
359 def __init__(self, test, trace):
360 """Create a io.StringIO instance; record the session obj and trace flag."""
361 io.StringIO.__init__(self)
362 # The test might not have undergone the 'setUp(self)' phase yet, so that
363 # the attribute 'session' might not even exist yet.
364 self.session = getattr(test, "session", None) if test else None
365 self.trace = trace
367 def __enter__(self):
369 Context management protocol on entry to the body of the with statement.
370 Just return the io.StringIO object.
372 return self
374 def __exit__(self, type, value, tb):
376 Context management protocol on exit from the body of the with statement.
377 If trace is ON, it emits the recordings into stderr. Always add the
378 recordings to our session object. And close the io.StringIO object, too.
380 if self.trace:
381 print(self.getvalue(), file=sys.stderr)
382 if self.session:
383 print(self.getvalue(), file=self.session)
384 self.close()
387 class _BaseProcess(object, metaclass=abc.ABCMeta):
388 @abc.abstractproperty
389 def pid(self):
390 """Returns process PID if has been launched already."""
392 @abc.abstractmethod
393 def launch(self, executable, args, extra_env):
394 """Launches new process with given executable and args."""
396 @abc.abstractmethod
397 def terminate(self):
398 """Terminates previously launched process.."""
401 class _LocalProcess(_BaseProcess):
402 def __init__(self, trace_on):
403 self._proc = None
404 self._trace_on = trace_on
405 self._delayafterterminate = 0.1
407 @property
408 def pid(self):
409 return self._proc.pid
411 def launch(self, executable, args, extra_env):
412 env = None
413 if extra_env:
414 env = dict(os.environ)
415 env.update([kv.split("=", 1) for kv in extra_env])
417 self._proc = Popen(
418 [executable] + args,
419 stdout=open(os.devnull) if not self._trace_on else None,
420 stdin=PIPE,
421 env=env,
424 def terminate(self):
425 if self._proc.poll() is None:
426 # Terminate _proc like it does the pexpect
427 signals_to_try = [
428 sig for sig in ["SIGHUP", "SIGCONT", "SIGINT"] if sig in dir(signal)
430 for sig in signals_to_try:
431 try:
432 self._proc.send_signal(getattr(signal, sig))
433 time.sleep(self._delayafterterminate)
434 if self._proc.poll() is not None:
435 return
436 except ValueError:
437 pass # Windows says SIGINT is not a valid signal to send
438 self._proc.terminate()
439 time.sleep(self._delayafterterminate)
440 if self._proc.poll() is not None:
441 return
442 self._proc.kill()
443 time.sleep(self._delayafterterminate)
445 def poll(self):
446 return self._proc.poll()
448 def wait(self, timeout=None):
449 return self._proc.wait(timeout)
452 class _RemoteProcess(_BaseProcess):
453 def __init__(self, install_remote):
454 self._pid = None
455 self._install_remote = install_remote
457 @property
458 def pid(self):
459 return self._pid
461 def launch(self, executable, args, extra_env):
462 if self._install_remote:
463 src_path = executable
464 dst_path = lldbutil.join_remote_paths(
465 lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable)
468 dst_file_spec = lldb.SBFileSpec(dst_path, False)
469 err = lldb.remote_platform.Install(
470 lldb.SBFileSpec(src_path, True), dst_file_spec
472 if err.Fail():
473 raise Exception(
474 "remote_platform.Install('%s', '%s') failed: %s"
475 % (src_path, dst_path, err)
477 else:
478 dst_path = executable
479 dst_file_spec = lldb.SBFileSpec(executable, False)
481 launch_info = lldb.SBLaunchInfo(args)
482 launch_info.SetExecutableFile(dst_file_spec, True)
483 launch_info.SetWorkingDirectory(lldb.remote_platform.GetWorkingDirectory())
485 # Redirect stdout and stderr to /dev/null
486 launch_info.AddSuppressFileAction(1, False, True)
487 launch_info.AddSuppressFileAction(2, False, True)
489 if extra_env:
490 launch_info.SetEnvironmentEntries(extra_env, True)
492 err = lldb.remote_platform.Launch(launch_info)
493 if err.Fail():
494 raise Exception(
495 "remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err)
497 self._pid = launch_info.GetProcessID()
499 def terminate(self):
500 lldb.remote_platform.Kill(self._pid)
503 def getsource_if_available(obj):
505 Return the text of the source code for an object if available. Otherwise,
506 a print representation is returned.
508 import inspect
510 try:
511 return inspect.getsource(obj)
512 except:
513 return repr(obj)
516 def builder_module():
517 return lldbplatformutil.builder_module()
520 class Base(unittest.TestCase):
522 Abstract base for performing lldb (see TestBase) or other generic tests (see
523 BenchBase for one example). lldbtest.Base works with the test driver to
524 accomplish things.
528 # The concrete subclass should override this attribute.
529 mydir = None
531 # Keep track of the old current working directory.
532 oldcwd = None
534 @staticmethod
535 def compute_mydir(test_file):
536 """Subclasses should call this function to correctly calculate the
537 required "mydir" attribute as follows:
539 mydir = TestBase.compute_mydir(__file__)
541 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir
542 lldb_test_src = configuration.test_src_root
543 if not test_file.startswith(lldb_test_src):
544 raise Exception(
545 "Test file '%s' must reside within lldb_test_src "
546 "(which is '%s')." % (test_file, lldb_test_src)
548 return os.path.dirname(os.path.relpath(test_file, start=lldb_test_src))
550 def TraceOn(self):
551 """Returns True if we are in trace mode (tracing detailed test execution)."""
552 return traceAlways
554 def trace(self, *args, **kwargs):
555 with recording(self, self.TraceOn()) as sbuf:
556 print(*args, file=sbuf, **kwargs)
558 @classmethod
559 def setUpClass(cls):
561 Python unittest framework class setup fixture.
562 Do current directory manipulation.
564 # Fail fast if 'mydir' attribute is not overridden.
565 if not cls.mydir:
566 cls.mydir = Base.compute_mydir(sys.modules[cls.__module__].__file__)
567 if not cls.mydir:
568 raise Exception("Subclasses must override the 'mydir' attribute.")
570 # Save old working directory.
571 cls.oldcwd = os.getcwd()
573 full_dir = os.path.join(configuration.test_src_root, cls.mydir)
574 if traceAlways:
575 print("Change dir to:", full_dir, file=sys.stderr)
576 os.chdir(full_dir)
578 # Set platform context.
579 cls.platformContext = lldbplatformutil.createPlatformContext()
581 @classmethod
582 def tearDownClass(cls):
584 Python unittest framework class teardown fixture.
585 Do class-wide cleanup.
588 if doCleanup:
589 # First, let's do the platform-specific cleanup.
590 module = builder_module()
591 module.cleanup()
593 # Subclass might have specific cleanup function defined.
594 if getattr(cls, "classCleanup", None):
595 if traceAlways:
596 print(
597 "Call class-specific cleanup function for class:",
598 cls,
599 file=sys.stderr,
601 try:
602 cls.classCleanup()
603 except:
604 exc_type, exc_value, exc_tb = sys.exc_info()
605 traceback.print_exception(exc_type, exc_value, exc_tb)
607 # Restore old working directory.
608 if traceAlways:
609 print("Restore dir to:", cls.oldcwd, file=sys.stderr)
610 os.chdir(cls.oldcwd)
612 def enableLogChannelsForCurrentTest(self):
613 if len(lldbtest_config.channels) == 0:
614 return
616 # if debug channels are specified in lldbtest_config.channels,
617 # create a new set of log files for every test
618 log_basename = self.getLogBasenameForCurrentTest()
620 # confirm that the file is writeable
621 host_log_path = "{}-host.log".format(log_basename)
622 open(host_log_path, "w").close()
623 self.log_files.append(host_log_path)
625 log_enable = "log enable -Tpn -f {} ".format(host_log_path)
626 for channel_with_categories in lldbtest_config.channels:
627 channel_then_categories = channel_with_categories.split(" ", 1)
628 channel = channel_then_categories[0]
629 if len(channel_then_categories) > 1:
630 categories = channel_then_categories[1]
631 else:
632 categories = "default"
634 if channel == "gdb-remote" and lldb.remote_platform is None:
635 # communicate gdb-remote categories to debugserver
636 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
638 self.ci.HandleCommand(log_enable + channel_with_categories, self.res)
639 if not self.res.Succeeded():
640 raise Exception(
641 "log enable failed (check LLDB_LOG_OPTION env variable)"
644 # Communicate log path name to debugserver & lldb-server
645 # For remote debugging, these variables need to be set when starting the platform
646 # instance.
647 if lldb.remote_platform is None:
648 server_log_path = "{}-server.log".format(log_basename)
649 open(server_log_path, "w").close()
650 self.log_files.append(server_log_path)
651 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
653 # Communicate channels to lldb-server
654 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels)
656 self.addTearDownHook(self.disableLogChannelsForCurrentTest)
658 def disableLogChannelsForCurrentTest(self):
659 # close all log files that we opened
660 for channel_and_categories in lldbtest_config.channels:
661 # channel format - <channel-name> [<category0> [<category1> ...]]
662 channel = channel_and_categories.split(" ", 1)[0]
663 self.ci.HandleCommand("log disable " + channel, self.res)
664 if not self.res.Succeeded():
665 raise Exception(
666 "log disable failed (check LLDB_LOG_OPTION env variable)"
669 # Retrieve the server log (if any) from the remote system. It is assumed the server log
670 # is writing to the "server.log" file in the current test directory. This can be
671 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote
672 # platform.
673 if lldb.remote_platform:
674 server_log_path = self.getLogBasenameForCurrentTest() + "-server.log"
675 if lldb.remote_platform.Get(
676 lldb.SBFileSpec("server.log"), lldb.SBFileSpec(server_log_path)
677 ).Success():
678 self.log_files.append(server_log_path)
680 def setPlatformWorkingDir(self):
681 if not lldb.remote_platform or not configuration.lldb_platform_working_dir:
682 return
684 components = self.mydir.split(os.path.sep) + [
685 str(self.test_number),
686 self.getBuildDirBasename(),
688 remote_test_dir = configuration.lldb_platform_working_dir
689 for c in components:
690 remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c)
691 error = lldb.remote_platform.MakeDirectory(
692 remote_test_dir, 448
693 ) # 448 = 0o700
694 if error.Fail():
695 raise Exception(
696 "making remote directory '%s': %s" % (remote_test_dir, error)
699 lldb.remote_platform.SetWorkingDirectory(remote_test_dir)
701 # This function removes all files from the current working directory while leaving
702 # the directories in place. The cleanup is required to reduce the disk space required
703 # by the test suite while leaving the directories untouched is neccessary because
704 # sub-directories might belong to an other test
705 def clean_working_directory():
706 # TODO: Make it working on Windows when we need it for remote debugging support
707 # TODO: Replace the heuristic to remove the files with a logic what collects the
708 # list of files we have to remove during test runs.
709 shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir)
710 lldb.remote_platform.Run(shell_cmd)
712 self.addTearDownHook(clean_working_directory)
714 def getSourceDir(self):
715 """Return the full path to the current test."""
716 return os.path.join(configuration.test_src_root, self.mydir)
718 def getBuildDirBasename(self):
719 return self.__class__.__module__ + "." + self.testMethodName
721 def getBuildDir(self):
722 """Return the full path to the current test."""
723 return os.path.join(
724 configuration.test_build_dir, self.mydir, self.getBuildDirBasename()
727 def makeBuildDir(self):
728 """Create the test-specific working directory, deleting any previous
729 contents."""
730 bdir = self.getBuildDir()
731 if os.path.isdir(bdir):
732 shutil.rmtree(bdir)
733 lldbutil.mkdir_p(bdir)
735 def getBuildArtifact(self, name="a.out"):
736 """Return absolute path to an artifact in the test's build directory."""
737 return os.path.join(self.getBuildDir(), name)
739 def getSourcePath(self, name):
740 """Return absolute path to a file in the test's source directory."""
741 return os.path.join(self.getSourceDir(), name)
743 @classmethod
744 def setUpCommands(cls):
745 commands = [
746 # First of all, clear all settings to have clean state of global properties.
747 "settings clear -all",
748 # Disable Spotlight lookup. The testsuite creates
749 # different binaries with the same UUID, because they only
750 # differ in the debug info, which is not being hashed.
751 "settings set symbols.enable-external-lookup false",
752 # Inherit the TCC permissions from the inferior's parent.
753 "settings set target.inherit-tcc true",
754 # Kill rather than detach from the inferior if something goes wrong.
755 "settings set target.detach-on-error false",
756 # Disable fix-its by default so that incorrect expressions in tests don't
757 # pass just because Clang thinks it has a fix-it.
758 "settings set target.auto-apply-fixits false",
759 # Testsuite runs in parallel and the host can have also other load.
760 "settings set plugin.process.gdb-remote.packet-timeout 60",
761 'settings set symbols.clang-modules-cache-path "{}"'.format(
762 configuration.lldb_module_cache_dir
764 "settings set use-color false",
767 # Set any user-overridden settings.
768 for setting, value in configuration.settings:
769 commands.append("setting set %s %s" % (setting, value))
771 # Make sure that a sanitizer LLDB's environment doesn't get passed on.
772 if (
773 cls.platformContext
774 and cls.platformContext.shlib_environment_var in os.environ
776 commands.append(
777 "settings set target.env-vars {}=".format(
778 cls.platformContext.shlib_environment_var
782 # Set environment variables for the inferior.
783 if lldbtest_config.inferior_env:
784 commands.append(
785 "settings set target.env-vars {}".format(lldbtest_config.inferior_env)
787 return commands
789 def setUp(self):
790 """Fixture for unittest test case setup.
792 It works with the test driver to conditionally skip tests and does other
793 initializations."""
794 # import traceback
795 # traceback.print_stack()
797 if "LIBCXX_PATH" in os.environ:
798 self.libcxxPath = os.environ["LIBCXX_PATH"]
799 else:
800 self.libcxxPath = None
802 if "LLDBDAP_EXEC" in os.environ:
803 self.lldbDAPExec = os.environ["LLDBDAP_EXEC"]
804 else:
805 self.lldbDAPExec = None
807 self.lldbOption = " ".join("-o '" + s + "'" for s in self.setUpCommands())
809 # If we spawn an lldb process for test (via pexpect), do not load the
810 # init file unless told otherwise.
811 if os.environ.get("NO_LLDBINIT") != "NO":
812 self.lldbOption += " --no-lldbinit"
814 # Assign the test method name to self.testMethodName.
816 # For an example of the use of this attribute, look at test/types dir.
817 # There are a bunch of test cases under test/types and we don't want the
818 # module cacheing subsystem to be confused with executable name "a.out"
819 # used for all the test cases.
820 self.testMethodName = self._testMethodName
822 # This is for the case of directly spawning 'lldb'/'gdb' and interacting
823 # with it using pexpect.
824 self.child = None
825 self.child_prompt = "(lldb) "
826 # If the child is interacting with the embedded script interpreter,
827 # there are two exits required during tear down, first to quit the
828 # embedded script interpreter and second to quit the lldb command
829 # interpreter.
830 self.child_in_script_interpreter = False
832 # These are for customized teardown cleanup.
833 self.dict = None
834 self.doTearDownCleanup = False
835 # And in rare cases where there are multiple teardown cleanups.
836 self.dicts = []
837 self.doTearDownCleanups = False
839 # List of spawned subproces.Popen objects
840 self.subprocesses = []
842 # List of log files produced by the current test.
843 self.log_files = []
845 # Create the build directory.
846 # The logs are stored in the build directory, so we have to create it
847 # before creating the first log file.
848 self.makeBuildDir()
850 session_file = self.getLogBasenameForCurrentTest() + ".log"
851 self.log_files.append(session_file)
853 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered.
854 self.session = encoded_file.open(session_file, "utf-8", mode="w")
856 # Optimistically set __errored__, __failed__, __expected__ to False
857 # initially. If the test errored/failed, the session info
858 # (self.session) is then dumped into a session specific file for
859 # diagnosis.
860 self.__cleanup_errored__ = False
861 self.__errored__ = False
862 self.__failed__ = False
863 self.__expected__ = False
864 # We are also interested in unexpected success.
865 self.__unexpected__ = False
866 # And skipped tests.
867 self.__skipped__ = False
869 # See addTearDownHook(self, hook) which allows the client to add a hook
870 # function to be run during tearDown() time.
871 self.hooks = []
873 # See HideStdout(self).
874 self.sys_stdout_hidden = False
876 if self.platformContext:
877 # set environment variable names for finding shared libraries
878 self.dylibPath = self.platformContext.shlib_environment_var
880 # Create the debugger instance.
881 self.dbg = lldb.SBDebugger.Create()
882 # Copy selected platform from a global instance if it exists.
883 if lldb.selected_platform is not None:
884 self.dbg.SetSelectedPlatform(lldb.selected_platform)
886 if not self.dbg:
887 raise Exception("Invalid debugger instance")
889 # Retrieve the associated command interpreter instance.
890 self.ci = self.dbg.GetCommandInterpreter()
891 if not self.ci:
892 raise Exception("Could not get the command interpreter")
894 # And the result object.
895 self.res = lldb.SBCommandReturnObject()
897 self.setPlatformWorkingDir()
898 self.enableLogChannelsForCurrentTest()
900 self.lib_lldb = None
901 self.framework_dir = None
902 self.darwinWithFramework = False
904 if sys.platform.startswith("darwin") and configuration.lldb_framework_path:
905 framework = configuration.lldb_framework_path
906 lib = os.path.join(framework, "LLDB")
907 if os.path.exists(lib):
908 self.framework_dir = os.path.dirname(framework)
909 self.lib_lldb = lib
910 self.darwinWithFramework = self.platformIsDarwin()
912 def setAsync(self, value):
913 """Sets async mode to True/False and ensures it is reset after the testcase completes."""
914 old_async = self.dbg.GetAsync()
915 self.dbg.SetAsync(value)
916 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async))
918 def cleanupSubprocesses(self):
919 # Terminate subprocesses in reverse order from how they were created.
920 for p in reversed(self.subprocesses):
921 p.terminate()
922 del p
923 del self.subprocesses[:]
925 def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=True):
926 """Creates a subprocess.Popen object with the specified executable and arguments,
927 saves it in self.subprocesses, and returns the object.
929 proc = (
930 _RemoteProcess(install_remote)
931 if lldb.remote_platform
932 else _LocalProcess(self.TraceOn())
934 proc.launch(executable, args, extra_env=extra_env)
935 self.subprocesses.append(proc)
936 return proc
938 def HideStdout(self):
939 """Hide output to stdout from the user.
941 During test execution, there might be cases where we don't want to show the
942 standard output to the user. For example,
944 self.runCmd(r'''sc print("\n\n\tHello!\n")''')
946 tests whether command abbreviation for 'script' works or not. There is no
947 need to show the 'Hello' output to the user as long as the 'script' command
948 succeeds and we are not in TraceOn() mode (see the '-t' option).
950 In this case, the test method calls self.HideStdout(self) to redirect the
951 sys.stdout to a null device, and restores the sys.stdout upon teardown.
953 Note that you should only call this method at most once during a test case
954 execution. Any subsequent call has no effect at all."""
955 if self.sys_stdout_hidden:
956 return
958 self.sys_stdout_hidden = True
959 old_stdout = sys.stdout
960 sys.stdout = open(os.devnull, "w")
962 def restore_stdout():
963 sys.stdout = old_stdout
965 self.addTearDownHook(restore_stdout)
967 # =======================================================================
968 # Methods for customized teardown cleanups as well as execution of hooks.
969 # =======================================================================
971 def setTearDownCleanup(self, dictionary=None):
972 """Register a cleanup action at tearDown() time with a dictionary"""
973 self.dict = dictionary
974 self.doTearDownCleanup = True
976 def addTearDownCleanup(self, dictionary):
977 """Add a cleanup action at tearDown() time with a dictionary"""
978 self.dicts.append(dictionary)
979 self.doTearDownCleanups = True
981 def addTearDownHook(self, hook):
983 Add a function to be run during tearDown() time.
985 Hooks are executed in a first come first serve manner.
987 if callable(hook):
988 with recording(self, traceAlways) as sbuf:
989 print("Adding tearDown hook:", getsource_if_available(hook), file=sbuf)
990 self.hooks.append(hook)
992 return self
994 def deletePexpectChild(self):
995 # This is for the case of directly spawning 'lldb' and interacting with it
996 # using pexpect.
997 if self.child and self.child.isalive():
998 import pexpect
1000 with recording(self, traceAlways) as sbuf:
1001 print("tearing down the child process....", file=sbuf)
1002 try:
1003 if self.child_in_script_interpreter:
1004 self.child.sendline("quit()")
1005 self.child.expect_exact(self.child_prompt)
1006 self.child.sendline("settings set interpreter.prompt-on-quit false")
1007 self.child.sendline("quit")
1008 self.child.expect(pexpect.EOF)
1009 except (ValueError, pexpect.ExceptionPexpect):
1010 # child is already terminated
1011 pass
1012 except OSError as exception:
1013 import errno
1015 if exception.errno != errno.EIO:
1016 # unexpected error
1017 raise
1018 # child is already terminated
1019 finally:
1020 # Give it one final blow to make sure the child is terminated.
1021 self.child.close()
1023 def tearDown(self):
1024 """Fixture for unittest test case teardown."""
1025 self.deletePexpectChild()
1027 # Check and run any hook functions.
1028 for hook in reversed(self.hooks):
1029 with recording(self, traceAlways) as sbuf:
1030 print(
1031 "Executing tearDown hook:", getsource_if_available(hook), file=sbuf
1033 if funcutils.requires_self(hook):
1034 hook(self)
1035 else:
1036 hook() # try the plain call and hope it works
1038 del self.hooks
1040 # Perform registered teardown cleanup.
1041 if doCleanup and self.doTearDownCleanup:
1042 self.cleanup(dictionary=self.dict)
1044 # In rare cases where there are multiple teardown cleanups added.
1045 if doCleanup and self.doTearDownCleanups:
1046 if self.dicts:
1047 for dict in reversed(self.dicts):
1048 self.cleanup(dictionary=dict)
1050 # Remove subprocesses created by the test.
1051 self.cleanupSubprocesses()
1053 # This must be the last statement, otherwise teardown hooks or other
1054 # lines might depend on this still being active.
1055 lldb.SBDebugger.Destroy(self.dbg)
1056 del self.dbg
1058 # All modules should be orphaned now so that they can be cleared from
1059 # the shared module cache.
1060 lldb.SBModule.GarbageCollectAllocatedModules()
1062 # Assert that the global module cache is empty.
1063 # FIXME: This assert fails on Windows.
1064 if self.getPlatform() != "windows":
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):
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
1100 # stderr twice.
1101 # Once by the Python unittest framework, and a second time by us.
1102 print("expected failure", file=sbuf)
1104 def markSkippedTest(self):
1105 """Callback invoked when a test is skipped."""
1106 self.__skipped__ = True
1107 with recording(self, False) as sbuf:
1108 # False because there's no need to write "skipped test" to the
1109 # stderr twice.
1110 # Once by the Python unittest framework, and a second time by us.
1111 print("skipped test", file=sbuf)
1113 def markUnexpectedSuccess(self):
1114 """Callback invoked when an unexpected success occurred."""
1115 self.__unexpected__ = True
1116 with recording(self, False) as sbuf:
1117 # False because there's no need to write "unexpected success" to the
1118 # stderr twice.
1119 # Once by the Python unittest framework, and a second time by us.
1120 print("unexpected success", file=sbuf)
1122 def getRerunArgs(self):
1123 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName)
1125 def getLogBasenameForCurrentTest(self, prefix="Incomplete"):
1127 returns a partial path that can be used as the beginning of the name of multiple
1128 log files pertaining to this test
1130 return os.path.join(self.getBuildDir(), prefix)
1132 def dumpSessionInfo(self):
1134 Dump the debugger interactions leading to a test error/failure. This
1135 allows for more convenient postmortem analysis.
1137 See also LLDBTestResult (dotest.py) which is a singlton class derived
1138 from TextTestResult and overwrites addError, addFailure, and
1139 addExpectedFailure methods to allow us to to mark the test instance as
1140 such.
1143 # We are here because self.tearDown() detected that this test instance
1144 # either errored or failed. The lldb.test_result singleton contains
1145 # two lists (errors and failures) which get populated by the unittest
1146 # framework. Look over there for stack trace information.
1148 # The lists contain 2-tuples of TestCase instances and strings holding
1149 # formatted tracebacks.
1151 # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1153 # output tracebacks into session
1154 pairs = []
1155 if self.__errored__:
1156 pairs = configuration.test_result.errors
1157 prefix = "Error"
1158 elif self.__cleanup_errored__:
1159 pairs = configuration.test_result.cleanup_errors
1160 prefix = "CleanupError"
1161 elif self.__failed__:
1162 pairs = configuration.test_result.failures
1163 prefix = "Failure"
1164 elif self.__expected__:
1165 pairs = configuration.test_result.expectedFailures
1166 prefix = "ExpectedFailure"
1167 elif self.__skipped__:
1168 prefix = "SkippedTest"
1169 elif self.__unexpected__:
1170 prefix = "UnexpectedSuccess"
1171 else:
1172 prefix = "Success"
1174 if not self.__unexpected__ and not self.__skipped__:
1175 for test, traceback in pairs:
1176 if test is self:
1177 print(traceback, file=self.session)
1179 import datetime
1181 print(
1182 "Session info generated @",
1183 datetime.datetime.now().ctime(),
1184 file=self.session,
1186 self.session.close()
1187 del self.session
1189 # process the log files
1190 if prefix != "Success" or lldbtest_config.log_success:
1191 # keep all log files, rename them to include prefix
1192 src_log_basename = self.getLogBasenameForCurrentTest()
1193 dst_log_basename = self.getLogBasenameForCurrentTest(prefix)
1194 for src in self.log_files:
1195 if os.path.isfile(src):
1196 dst = src.replace(src_log_basename, dst_log_basename)
1197 if os.name == "nt" and os.path.isfile(dst):
1198 # On Windows, renaming a -> b will throw an exception if
1199 # b exists. On non-Windows platforms it silently
1200 # replaces the destination. Ultimately this means that
1201 # atomic renames are not guaranteed to be possible on
1202 # Windows, but we need this to work anyway, so just
1203 # remove the destination first if it already exists.
1204 remove_file(dst)
1206 lldbutil.mkdir_p(os.path.dirname(dst))
1207 os.rename(src, dst)
1208 else:
1209 # success! (and we don't want log files) delete log files
1210 for log_file in self.log_files:
1211 if os.path.isfile(log_file):
1212 remove_file(log_file)
1214 # ====================================================
1215 # Config. methods supported through a plugin interface
1216 # (enables reading of the current test configuration)
1217 # ====================================================
1219 def hasXMLSupport(self):
1220 """Returns True if lldb was built with XML support. Use this check to
1221 enable parts of tests, if you want to skip a whole test use skipIfXmlSupportMissing
1222 instead."""
1223 return (
1224 lldb.SBDebugger.GetBuildConfiguration()
1225 .GetValueForKey("xml")
1226 .GetValueForKey("value")
1227 .GetBooleanValue(False)
1230 def isMIPS(self):
1231 """Returns true if the architecture is MIPS."""
1232 arch = self.getArchitecture()
1233 if re.match("mips", arch):
1234 return True
1235 return False
1237 def isPPC64le(self):
1238 """Returns true if the architecture is PPC64LE."""
1239 arch = self.getArchitecture()
1240 if re.match("powerpc64le", arch):
1241 return True
1242 return False
1244 def getCPUInfo(self):
1245 triple = self.dbg.GetSelectedPlatform().GetTriple()
1247 # TODO other platforms, please implement this function
1248 if not re.match(".*-.*-linux", triple):
1249 return ""
1251 # Need to do something different for non-Linux/Android targets
1252 cpuinfo_path = self.getBuildArtifact("cpuinfo")
1253 if configuration.lldb_platform_name:
1254 self.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path)
1255 else:
1256 cpuinfo_path = "/proc/cpuinfo"
1258 try:
1259 with open(cpuinfo_path, "r") as f:
1260 cpuinfo = f.read()
1261 except:
1262 return ""
1264 return cpuinfo
1266 def isAArch64(self):
1267 """Returns true if the architecture is AArch64."""
1268 arch = self.getArchitecture().lower()
1269 return arch in ["aarch64", "arm64", "arm64e"]
1271 def isAArch64SVE(self):
1272 return self.isAArch64() and "sve" in self.getCPUInfo()
1274 def isAArch64SME(self):
1275 return self.isAArch64() and "sme" in self.getCPUInfo()
1277 def isAArch64SME2(self):
1278 # If you have sme2, you also have sme.
1279 return self.isAArch64() and "sme2" in self.getCPUInfo()
1281 def isAArch64SMEFA64(self):
1282 # smefa64 allows the use of the full A64 instruction set in streaming
1283 # mode. This is required by certain test programs to setup register
1284 # state.
1285 cpuinfo = self.getCPUInfo()
1286 return self.isAArch64() and "sme" in cpuinfo and "smefa64" in cpuinfo
1288 def isAArch64MTE(self):
1289 return self.isAArch64() and "mte" in self.getCPUInfo()
1291 def isAArch64PAuth(self):
1292 if self.getArchitecture() == "arm64e":
1293 return True
1294 return self.isAArch64() and "paca" in self.getCPUInfo()
1296 def isAArch64Windows(self):
1297 """Returns true if the architecture is AArch64 and platform windows."""
1298 if self.getPlatform() == "windows":
1299 arch = self.getArchitecture().lower()
1300 return arch in ["aarch64", "arm64", "arm64e"]
1301 return False
1303 def getArchitecture(self):
1304 """Returns the architecture in effect the test suite is running with."""
1305 return lldbplatformutil.getArchitecture()
1307 def getLldbArchitecture(self):
1308 """Returns the architecture of the lldb binary."""
1309 return lldbplatformutil.getLLDBArchitecture()
1311 def getCompiler(self):
1312 """Returns the compiler in effect the test suite is running with."""
1313 return lldbplatformutil.getCompiler()
1315 def getCompilerBinary(self):
1316 """Returns the compiler binary the test suite is running with."""
1317 return lldbplatformutil.getCompilerBinary()
1319 def getCompilerVersion(self):
1320 """Returns a string that represents the compiler version.
1321 Supports: llvm, clang.
1323 return lldbplatformutil.getCompilerVersion()
1325 def getDwarfVersion(self):
1326 """Returns the dwarf version generated by clang or '0'."""
1327 return lldbplatformutil.getDwarfVersion()
1329 def platformIsDarwin(self):
1330 """Returns true if the OS triple for the selected platform is any valid apple OS"""
1331 return lldbplatformutil.platformIsDarwin()
1333 def hasDarwinFramework(self):
1334 return self.darwinWithFramework
1336 def getPlatform(self):
1337 """Returns the target platform the test suite is running on."""
1338 return lldbplatformutil.getPlatform()
1340 def isIntelCompiler(self):
1341 """Returns true if using an Intel (ICC) compiler, false otherwise."""
1342 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]])
1344 def expectedCompilerVersion(self, compiler_version):
1345 """Returns True iff compiler_version[1] matches the current compiler version.
1346 Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1347 Any operator other than the following defaults to an equality test:
1348 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1350 If the current compiler version cannot be determined, we assume it is close to the top
1351 of trunk, so any less-than or equal-to comparisons will return False, and any
1352 greater-than or not-equal-to comparisons will return True.
1354 return lldbplatformutil.expectedCompilerVersion(compiler_version)
1356 def expectedCompiler(self, compilers):
1357 """Returns True iff any element of compilers is a sub-string of the current compiler."""
1358 return lldbplatformutil.expectedCompiler(compilers)
1360 def expectedArch(self, archs):
1361 """Returns True iff any element of archs is a sub-string of the current architecture."""
1362 if archs is None:
1363 return True
1365 for arch in archs:
1366 if arch in self.getArchitecture():
1367 return True
1369 return False
1371 def getRunOptions(self):
1372 """Command line option for -A and -C to run this test again, called from
1373 self.dumpSessionInfo()."""
1374 arch = self.getArchitecture()
1375 comp = self.getCompiler()
1376 option_str = ""
1377 if arch:
1378 option_str = "-A " + arch
1379 if comp:
1380 option_str += " -C " + comp
1381 return option_str
1383 def getDebugInfo(self):
1384 method = getattr(self, self.testMethodName)
1385 return getattr(method, "debug_info", None)
1387 def build(
1388 self,
1389 debug_info=None,
1390 architecture=None,
1391 compiler=None,
1392 dictionary=None,
1393 make_targets=None,
1395 """Platform specific way to build binaries."""
1396 if not architecture and configuration.arch:
1397 architecture = configuration.arch
1399 if debug_info is None:
1400 debug_info = self.getDebugInfo()
1402 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1404 testdir = self.mydir
1405 testname = self.getBuildDirBasename()
1407 module = builder_module()
1408 command = builder_module().getBuildCommand(
1409 debug_info,
1410 architecture,
1411 compiler,
1412 dictionary,
1413 testdir,
1414 testname,
1415 make_targets,
1417 if command is None:
1418 raise Exception("Don't know how to build binary")
1420 self.runBuildCommand(command)
1422 def runBuildCommand(self, command):
1423 self.trace(seven.join_for_shell(command))
1424 try:
1425 output = check_output(command, stderr=STDOUT, errors="replace")
1426 except CalledProcessError as cpe:
1427 raise build_exception.BuildError(cpe)
1428 self.trace(output)
1430 # ==================================================
1431 # Build methods supported through a plugin interface
1432 # ==================================================
1434 def getstdlibFlag(self):
1435 """Returns the proper -stdlib flag, or empty if not required."""
1436 if (
1437 self.platformIsDarwin()
1438 or self.getPlatform() == "freebsd"
1439 or self.getPlatform() == "openbsd"
1441 stdlibflag = "-stdlib=libc++"
1442 else: # this includes NetBSD
1443 stdlibflag = ""
1444 return stdlibflag
1446 def getstdFlag(self):
1447 """Returns the proper stdflag."""
1448 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
1449 stdflag = "-std=c++0x"
1450 else:
1451 stdflag = "-std=c++11"
1452 return stdflag
1454 def buildDriver(self, sources, exe_name):
1455 """Platform-specific way to build a program that links with LLDB (via the liblldb.so
1456 or LLDB.framework).
1458 stdflag = self.getstdFlag()
1459 stdlibflag = self.getstdlibFlag()
1461 lib_dir = configuration.lldb_libs_dir
1462 if self.hasDarwinFramework():
1463 d = {
1464 "CXX_SOURCES": sources,
1465 "EXE": exe_name,
1466 "CFLAGS_EXTRAS": "%s %s" % (stdflag, stdlibflag),
1467 "FRAMEWORK_INCLUDES": "-F%s" % self.framework_dir,
1468 "LD_EXTRAS": "%s -Wl,-rpath,%s" % (self.lib_lldb, self.framework_dir),
1470 elif sys.platform.startswith("win"):
1471 d = {
1472 "CXX_SOURCES": sources,
1473 "EXE": exe_name,
1474 "CFLAGS_EXTRAS": "%s %s -I%s"
1476 stdflag,
1477 stdlibflag,
1478 os.path.join(os.environ["LLDB_SRC"], "include"),
1480 "LD_EXTRAS": "-L%s -lliblldb" % lib_dir,
1482 else:
1483 d = {
1484 "CXX_SOURCES": sources,
1485 "EXE": exe_name,
1486 "CFLAGS_EXTRAS": "%s %s -I%s"
1488 stdflag,
1489 stdlibflag,
1490 os.path.join(os.environ["LLDB_SRC"], "include"),
1492 "LD_EXTRAS": "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir),
1494 if self.TraceOn():
1495 print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources))
1497 self.build(dictionary=d)
1499 def buildLibrary(self, sources, lib_name):
1500 """Platform specific way to build a default library."""
1502 stdflag = self.getstdFlag()
1504 lib_dir = configuration.lldb_libs_dir
1505 if self.hasDarwinFramework():
1506 d = {
1507 "DYLIB_CXX_SOURCES": sources,
1508 "DYLIB_NAME": lib_name,
1509 "CFLAGS_EXTRAS": "%s -stdlib=libc++" % stdflag,
1510 "FRAMEWORK_INCLUDES": "-F%s" % self.framework_dir,
1511 "LD_EXTRAS": "%s -Wl,-rpath,%s -dynamiclib"
1512 % (self.lib_lldb, self.framework_dir),
1514 elif self.getPlatform() == "windows":
1515 d = {
1516 "DYLIB_CXX_SOURCES": sources,
1517 "DYLIB_NAME": lib_name,
1518 "CFLAGS_EXTRAS": "%s -I%s "
1519 % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
1520 "LD_EXTRAS": "-shared -l%s\liblldb.lib" % lib_dir,
1522 else:
1523 d = {
1524 "DYLIB_CXX_SOURCES": sources,
1525 "DYLIB_NAME": lib_name,
1526 "CFLAGS_EXTRAS": "%s -I%s -fPIC"
1527 % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
1528 "LD_EXTRAS": "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir),
1530 if self.TraceOn():
1531 print("Building LLDB Library (%s) from sources %s" % (lib_name, sources))
1533 self.build(dictionary=d)
1535 def buildProgram(self, sources, exe_name):
1536 """Platform specific way to build an executable from C/C++ sources."""
1537 d = {"CXX_SOURCES": sources, "EXE": exe_name}
1538 self.build(dictionary=d)
1540 def findBuiltClang(self):
1541 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
1542 paths_to_try = [
1543 "llvm-build/Release+Asserts/x86_64/bin/clang",
1544 "llvm-build/Debug+Asserts/x86_64/bin/clang",
1545 "llvm-build/Release/x86_64/bin/clang",
1546 "llvm-build/Debug/x86_64/bin/clang",
1548 lldb_root_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")
1549 for p in paths_to_try:
1550 path = os.path.join(lldb_root_path, p)
1551 if os.path.exists(path):
1552 return path
1554 # Tries to find clang at the same folder as the lldb
1555 lldb_dir = os.path.dirname(lldbtest_config.lldbExec)
1556 path = shutil.which("clang", path=lldb_dir)
1557 if path is not None:
1558 return path
1560 return os.environ["CC"]
1562 def yaml2obj(self, yaml_path, obj_path, max_size=None):
1564 Create an object file at the given path from a yaml file.
1566 Throws subprocess.CalledProcessError if the object could not be created.
1568 yaml2obj_bin = configuration.get_yaml2obj_path()
1569 if not yaml2obj_bin:
1570 self.assertTrue(False, "No valid yaml2obj executable specified")
1571 command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path]
1572 if max_size is not None:
1573 command += ["--max-size=%d" % max_size]
1574 self.runBuildCommand(command)
1576 def cleanup(self, dictionary=None):
1577 """Platform specific way to do cleanup after build."""
1578 module = builder_module()
1579 if not module.cleanup(dictionary):
1580 raise Exception(
1581 "Don't know how to do cleanup with dictionary: " + dictionary
1584 def invoke(self, obj, name, trace=False):
1585 """Use reflection to call a method dynamically with no argument."""
1586 trace = True if traceAlways else trace
1588 method = getattr(obj, name)
1589 import inspect
1591 self.assertTrue(
1592 inspect.ismethod(method), name + "is a method name of object: " + str(obj)
1594 result = method()
1595 with recording(self, trace) as sbuf:
1596 print(str(method) + ":", result, file=sbuf)
1597 return result
1599 def getLibcPlusPlusLibs(self):
1600 if self.getPlatform() in ("freebsd", "linux", "netbsd", "openbsd"):
1601 return ["libc++.so.1"]
1602 else:
1603 return ["libc++.1.dylib", "libc++abi."]
1605 def run_platform_command(self, cmd):
1606 platform = self.dbg.GetSelectedPlatform()
1607 shell_command = lldb.SBPlatformShellCommand(cmd)
1608 err = platform.Run(shell_command)
1609 return (err, shell_command.GetStatus(), shell_command.GetOutput())
1611 def get_stats(self, options=None):
1613 Get the output of the "statistics dump" with optional extra options
1614 and return the JSON as a python dictionary.
1616 return_obj = lldb.SBCommandReturnObject()
1617 command = "statistics dump "
1618 if options is not None:
1619 command += options
1620 self.ci.HandleCommand(command, return_obj, False)
1621 metrics_json = return_obj.GetOutput()
1622 return json.loads(metrics_json)
1625 # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
1626 # We change the test methods to create a new test method for each test for each debug info we are
1627 # testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
1628 # the new test method we remove the old method at the same time. This functionality can be
1629 # supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test
1630 # level by using the decorator @no_debug_info_test.
1633 class LLDBTestCaseFactory(type):
1634 def __new__(cls, name, bases, attrs):
1635 original_testcase = super(LLDBTestCaseFactory, cls).__new__(
1636 cls, name, bases, attrs
1638 if original_testcase.NO_DEBUG_INFO_TESTCASE:
1639 return original_testcase
1641 # Default implementation for skip/xfail reason based on the debug category,
1642 # where "None" means to run the test as usual.
1643 def no_reason(_):
1644 return None
1646 newattrs = {}
1647 for attrname, attrvalue in attrs.items():
1648 if attrname.startswith("test") and not getattr(
1649 attrvalue, "__no_debug_info_test__", False
1651 # If any debug info categories were explicitly tagged, assume that list to be
1652 # authoritative. If none were specified, try with all debug
1653 # info formats.
1654 all_dbginfo_categories = set(
1655 test_categories.debug_info_categories.keys()
1657 categories = (
1658 set(getattr(attrvalue, "categories", [])) & all_dbginfo_categories
1660 if not categories:
1661 categories = [
1662 category
1663 for category, can_replicate in test_categories.debug_info_categories.items()
1664 if can_replicate
1667 xfail_for_debug_info_cat_fn = getattr(
1668 attrvalue, "__xfail_for_debug_info_cat_fn__", no_reason
1670 skip_for_debug_info_cat_fn = getattr(
1671 attrvalue, "__skip_for_debug_info_cat_fn__", no_reason
1673 for cat in categories:
1675 @decorators.add_test_categories([cat])
1676 @wraps(attrvalue)
1677 def test_method(self, attrvalue=attrvalue):
1678 return attrvalue(self)
1680 method_name = attrname + "_" + cat
1681 test_method.__name__ = method_name
1682 test_method.debug_info = cat
1684 xfail_reason = xfail_for_debug_info_cat_fn(cat)
1685 if xfail_reason:
1686 test_method = unittest.expectedFailure(test_method)
1688 skip_reason = skip_for_debug_info_cat_fn(cat)
1689 if skip_reason:
1690 test_method = unittest.skip(skip_reason)(test_method)
1692 newattrs[method_name] = test_method
1694 else:
1695 newattrs[attrname] = attrvalue
1696 return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs)
1699 # Setup the metaclass for this class to change the list of the test
1700 # methods when a new class is loaded
1703 class TestBase(Base, metaclass=LLDBTestCaseFactory):
1705 This abstract base class is meant to be subclassed. It provides default
1706 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1707 among other things.
1709 Important things for test class writers:
1711 - The setUp method sets up things to facilitate subsequent interactions
1712 with the debugger as part of the test. These include:
1713 - populate the test method name
1714 - create/get a debugger set with synchronous mode (self.dbg)
1715 - get the command interpreter from with the debugger (self.ci)
1716 - create a result object for use with the command interpreter
1717 (self.res)
1718 - plus other stuffs
1720 - The tearDown method tries to perform some necessary cleanup on behalf
1721 of the test to return the debugger to a good state for the next test.
1722 These include:
1723 - execute any tearDown hooks registered by the test method with
1724 TestBase.addTearDownHook(); examples can be found in
1725 settings/TestSettings.py
1726 - kill the inferior process associated with each target, if any,
1727 and, then delete the target from the debugger's target list
1728 - perform build cleanup before running the next test method in the
1729 same test class; examples of registering for this service can be
1730 found in types/TestIntegerTypes.py with the call:
1731 - self.setTearDownCleanup(dictionary=d)
1733 - Similarly setUpClass and tearDownClass perform classwise setup and
1734 teardown fixtures. The tearDownClass method invokes a default build
1735 cleanup for the entire test class; also, subclasses can implement the
1736 classmethod classCleanup(cls) to perform special class cleanup action.
1738 - The instance methods runCmd and expect are used heavily by existing
1739 test cases to send a command to the command interpreter and to perform
1740 string/pattern matching on the output of such command execution. The
1741 expect method also provides a mode to peform string/pattern matching
1742 without running a command.
1744 - The build method is used to build the binaries used during a
1745 particular test scenario. A plugin should be provided for the
1746 sys.platform running the test suite. The Mac OS X implementation is
1747 located in builders/darwin.py.
1750 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the
1751 # test multiple times with various debug info types.
1752 NO_DEBUG_INFO_TESTCASE = False
1754 # Maximum allowed attempts when launching the inferior process.
1755 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1756 maxLaunchCount = 1
1758 # Time to wait before the next launching attempt in second(s).
1759 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1760 timeWaitNextLaunch = 1.0
1762 def generateSource(self, source):
1763 template = source + ".template"
1764 temp = os.path.join(self.getSourceDir(), template)
1765 with open(temp, "r") as f:
1766 content = f.read()
1768 public_api_dir = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API")
1770 # Look under the include/lldb/API directory and add #include statements
1771 # for all the SB API headers.
1772 public_headers = os.listdir(public_api_dir)
1773 # For different platforms, the include statement can vary.
1774 if self.hasDarwinFramework():
1775 include_stmt = "'#include <%s>' % os.path.join('LLDB', header)"
1776 else:
1777 include_stmt = (
1778 "'#include <%s>' % os.path.join(r'" + public_api_dir + "', header)"
1780 list = [
1781 eval(include_stmt)
1782 for header in public_headers
1783 if (header.startswith("SB") and header.endswith(".h"))
1785 includes = "\n".join(list)
1786 new_content = content.replace("%include_SB_APIs%", includes)
1787 new_content = new_content.replace("%SOURCE_DIR%", self.getSourceDir())
1788 src = os.path.join(self.getBuildDir(), source)
1789 with open(src, "w") as f:
1790 f.write(new_content)
1792 self.addTearDownHook(lambda: os.remove(src))
1794 def setUp(self):
1795 # Works with the test driver to conditionally skip tests via
1796 # decorators.
1797 Base.setUp(self)
1799 for s in self.setUpCommands():
1800 self.runCmd(s)
1802 if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1803 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1805 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
1806 self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1808 # We want our debugger to be synchronous.
1809 self.dbg.SetAsync(False)
1811 # Retrieve the associated command interpreter instance.
1812 self.ci = self.dbg.GetCommandInterpreter()
1813 if not self.ci:
1814 raise Exception("Could not get the command interpreter")
1816 # And the result object.
1817 self.res = lldb.SBCommandReturnObject()
1819 def registerSharedLibrariesWithTarget(self, target, shlibs):
1820 """If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
1822 Any modules in the target that have their remote install file specification set will
1823 get uploaded to the remote host. This function registers the local copies of the
1824 shared libraries with the target and sets their remote install locations so they will
1825 be uploaded when the target is run.
1827 if not shlibs or not self.platformContext:
1828 return None
1830 shlib_environment_var = self.platformContext.shlib_environment_var
1831 shlib_prefix = self.platformContext.shlib_prefix
1832 shlib_extension = "." + self.platformContext.shlib_extension
1834 dirs = []
1835 # Add any shared libraries to our target if remote so they get
1836 # uploaded into the working directory on the remote side
1837 for name in shlibs:
1838 # The path can be a full path to a shared library, or a make file name like "Foo" for
1839 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
1840 # basename like "libFoo.so". So figure out which one it is and resolve the local copy
1841 # of the shared library accordingly
1842 if os.path.isfile(name):
1843 local_shlib_path = (
1844 name # name is the full path to the local shared library
1846 else:
1847 # Check relative names
1848 local_shlib_path = os.path.join(
1849 self.getBuildDir(), shlib_prefix + name + shlib_extension
1851 if not os.path.exists(local_shlib_path):
1852 local_shlib_path = os.path.join(
1853 self.getBuildDir(), name + shlib_extension
1855 if not os.path.exists(local_shlib_path):
1856 local_shlib_path = os.path.join(self.getBuildDir(), name)
1858 # Make sure we found the local shared library in the above code
1859 self.assertTrue(os.path.exists(local_shlib_path))
1861 # Add the shared library to our target
1862 shlib_module = target.AddModule(local_shlib_path, None, None, None)
1863 if lldb.remote_platform:
1864 # We must set the remote install location if we want the shared library
1865 # to get uploaded to the remote target
1866 remote_shlib_path = lldbutil.append_to_process_working_directory(
1867 self, os.path.basename(local_shlib_path)
1869 shlib_module.SetRemoteInstallFileSpec(
1870 lldb.SBFileSpec(remote_shlib_path, False)
1872 dir_to_add = self.get_process_working_directory()
1873 else:
1874 dir_to_add = os.path.dirname(local_shlib_path)
1876 if dir_to_add not in dirs:
1877 dirs.append(dir_to_add)
1879 env_value = self.platformContext.shlib_path_separator.join(dirs)
1880 return ["%s=%s" % (shlib_environment_var, env_value)]
1882 def registerSanitizerLibrariesWithTarget(self, target):
1883 runtimes = []
1884 for m in target.module_iter():
1885 libspec = m.GetFileSpec()
1886 if "clang_rt" in libspec.GetFilename():
1887 runtimes.append(
1888 os.path.join(libspec.GetDirectory(), libspec.GetFilename())
1890 return self.registerSharedLibrariesWithTarget(target, runtimes)
1892 # utility methods that tests can use to access the current objects
1893 def target(self):
1894 if not self.dbg:
1895 raise Exception("Invalid debugger instance")
1896 return self.dbg.GetSelectedTarget()
1898 def process(self):
1899 if not self.dbg:
1900 raise Exception("Invalid debugger instance")
1901 return self.dbg.GetSelectedTarget().GetProcess()
1903 def thread(self):
1904 if not self.dbg:
1905 raise Exception("Invalid debugger instance")
1906 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
1908 def frame(self):
1909 if not self.dbg:
1910 raise Exception("Invalid debugger instance")
1911 return (
1912 self.dbg.GetSelectedTarget()
1913 .GetProcess()
1914 .GetSelectedThread()
1915 .GetSelectedFrame()
1918 def get_process_working_directory(self):
1919 """Get the working directory that should be used when launching processes for local or remote processes."""
1920 if lldb.remote_platform:
1921 # Remote tests set the platform working directory up in
1922 # TestBase.setUp()
1923 return lldb.remote_platform.GetWorkingDirectory()
1924 else:
1925 # local tests change directory into each test subdirectory
1926 return self.getBuildDir()
1928 def tearDown(self):
1929 # Ensure all the references to SB objects have gone away so that we can
1930 # be sure that all test-specific resources have been freed before we
1931 # attempt to delete the targets.
1932 gc.collect()
1934 # Delete the target(s) from the debugger as a general cleanup step.
1935 # This includes terminating the process for each target, if any.
1936 # We'd like to reuse the debugger for our next test without incurring
1937 # the initialization overhead.
1938 targets = []
1939 for target in self.dbg:
1940 if target:
1941 targets.append(target)
1942 process = target.GetProcess()
1943 if process:
1944 rc = self.invoke(process, "Kill")
1945 assert rc.Success()
1946 for target in targets:
1947 self.dbg.DeleteTarget(target)
1949 # Assert that all targets are deleted.
1950 self.assertEqual(self.dbg.GetNumTargets(), 0)
1952 # Do this last, to make sure it's in reverse order from how we setup.
1953 Base.tearDown(self)
1955 def switch_to_thread_with_stop_reason(self, stop_reason):
1957 Run the 'thread list' command, and select the thread with stop reason as
1958 'stop_reason'. If no such thread exists, no select action is done.
1960 from .lldbutil import stop_reason_to_str
1962 self.runCmd("thread list")
1963 output = self.res.GetOutput()
1964 thread_line_pattern = re.compile(
1965 "^[ *] thread #([0-9]+):.*stop reason = %s"
1966 % stop_reason_to_str(stop_reason)
1968 for line in output.splitlines():
1969 matched = thread_line_pattern.match(line)
1970 if matched:
1971 self.runCmd("thread select %s" % matched.group(1))
1973 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False):
1975 Ask the command interpreter to handle the command and then check its
1976 return status.
1978 # Fail fast if 'cmd' is not meaningful.
1979 if cmd is None:
1980 raise Exception("Bad 'cmd' parameter encountered")
1982 trace = True if traceAlways else trace
1984 if cmd.startswith("target create "):
1985 cmd = cmd.replace("target create ", "file ")
1987 running = cmd.startswith("run") or cmd.startswith("process launch")
1989 for i in range(self.maxLaunchCount if running else 1):
1990 with recording(self, trace) as sbuf:
1991 print("runCmd:", cmd, file=sbuf)
1992 if not check:
1993 print("check of return status not required", file=sbuf)
1995 self.ci.HandleCommand(cmd, self.res, inHistory)
1997 with recording(self, trace) as sbuf:
1998 if self.res.Succeeded():
1999 print("output:", self.res.GetOutput(), file=sbuf)
2000 else:
2001 print("runCmd failed!", file=sbuf)
2002 print(self.res.GetError(), file=sbuf)
2004 if self.res.Succeeded():
2005 break
2006 elif running:
2007 # For process launch, wait some time before possible next try.
2008 time.sleep(self.timeWaitNextLaunch)
2009 with recording(self, trace) as sbuf:
2010 print("Command '" + cmd + "' failed!", file=sbuf)
2012 if check:
2013 output = ""
2014 if self.res.GetOutput():
2015 output += "\nCommand output:\n" + self.res.GetOutput()
2016 if self.res.GetError():
2017 output += "\nError output:\n" + self.res.GetError()
2018 if msg:
2019 msg += output
2020 if cmd:
2021 cmd += output
2022 self.assertTrue(self.res.Succeeded(), msg if (msg) else CMD_MSG(cmd))
2024 def match(
2025 self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True
2027 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2029 Otherwise, all the arguments have the same meanings as for the expect function
2032 trace = True if traceAlways else trace
2034 if exe:
2035 # First run the command. If we are expecting error, set check=False.
2036 # Pass the assert message along since it provides more semantic
2037 # info.
2038 self.runCmd(str, msg=msg, trace=(True if trace else False), check=not error)
2040 # Then compare the output against expected strings.
2041 output = self.res.GetError() if error else self.res.GetOutput()
2043 # If error is True, the API client expects the command to fail!
2044 if error:
2045 self.assertFalse(
2046 self.res.Succeeded(), "Command '" + str + "' is expected to fail!"
2048 else:
2049 # No execution required, just compare str against the golden input.
2050 output = str
2051 with recording(self, trace) as sbuf:
2052 print("looking at:", output, file=sbuf)
2054 # The heading says either "Expecting" or "Not expecting".
2055 heading = "Expecting" if matching else "Not expecting"
2057 for pattern in patterns:
2058 # Match Objects always have a boolean value of True.
2059 match_object = re.search(pattern, output)
2060 matched = bool(match_object)
2061 with recording(self, trace) as sbuf:
2062 print("%s pattern: %s" % (heading, pattern), file=sbuf)
2063 print("Matched" if matched else "Not matched", file=sbuf)
2064 if matched:
2065 break
2067 self.assertTrue(
2068 matched if matching else not matched,
2069 msg if msg else EXP_MSG(str, output, exe),
2072 return match_object
2074 def check_completion_with_desc(
2075 self, str_input, match_desc_pairs, enforce_order=False
2078 Checks that when the given input is completed at the given list of
2079 completions and descriptions is returned.
2080 :param str_input: The input that should be completed. The completion happens at the end of the string.
2081 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of
2082 completions returned by LLDB. The first element of the pair is the completion
2083 string that LLDB should generate and the second element the description.
2084 :param enforce_order: True iff the order in which the completions are returned by LLDB
2085 should match the order of the match_desc_pairs pairs.
2087 interp = self.dbg.GetCommandInterpreter()
2088 match_strings = lldb.SBStringList()
2089 description_strings = lldb.SBStringList()
2090 num_matches = interp.HandleCompletionWithDescriptions(
2091 str_input, len(str_input), 0, -1, match_strings, description_strings
2093 self.assertEqual(len(description_strings), len(match_strings))
2095 # The index of the last matched description in description_strings or
2096 # -1 if no description has been matched yet.
2097 last_found_index = -1
2098 out_of_order_errors = ""
2099 missing_pairs = []
2100 for pair in match_desc_pairs:
2101 found_pair = False
2102 for i in range(num_matches + 1):
2103 match_candidate = match_strings.GetStringAtIndex(i)
2104 description_candidate = description_strings.GetStringAtIndex(i)
2105 if match_candidate == pair[0] and description_candidate == pair[1]:
2106 found_pair = True
2107 if enforce_order and last_found_index > i:
2108 new_err = (
2109 "Found completion "
2110 + pair[0]
2111 + " at index "
2112 + str(i)
2113 + " in returned completion list but "
2114 + "should have been after completion "
2115 + match_strings.GetStringAtIndex(last_found_index)
2116 + " (index:"
2117 + str(last_found_index)
2118 + ")\n"
2120 out_of_order_errors += new_err
2121 last_found_index = i
2122 break
2123 if not found_pair:
2124 missing_pairs.append(pair)
2126 error_msg = ""
2127 got_failure = False
2128 if len(missing_pairs):
2129 got_failure = True
2130 error_msg += "Missing pairs:\n"
2131 for pair in missing_pairs:
2132 error_msg += " [" + pair[0] + ":" + pair[1] + "]\n"
2133 if len(out_of_order_errors):
2134 got_failure = True
2135 error_msg += out_of_order_errors
2136 if got_failure:
2137 error_msg += (
2138 "Got the following " + str(num_matches) + " completions back:\n"
2140 for i in range(num_matches + 1):
2141 match_candidate = match_strings.GetStringAtIndex(i)
2142 description_candidate = description_strings.GetStringAtIndex(i)
2143 error_msg += (
2145 + match_candidate
2146 + ":"
2147 + description_candidate
2148 + "] index "
2149 + str(i)
2150 + "\n"
2152 self.assertFalse(got_failure, error_msg)
2154 def complete_from_to(self, str_input, patterns):
2155 """Test that the completion mechanism completes str_input to patterns,
2156 where patterns could be a single pattern-string or a list of
2157 pattern-strings.
2159 If there is only one pattern and it is exactly equal to str_input, this
2160 assumes that there should be no completions provided and that the result
2161 should be the same as the input."""
2163 # Patterns should not be None in order to proceed.
2164 self.assertFalse(patterns is None)
2165 # And should be either a string or list of strings. Check for list type
2166 # below, if not, make a list out of the singleton string. If patterns
2167 # is not a string or not a list of strings, there'll be runtime errors
2168 # later on.
2169 if not isinstance(patterns, list):
2170 patterns = [patterns]
2172 interp = self.dbg.GetCommandInterpreter()
2173 match_strings = lldb.SBStringList()
2174 num_matches = interp.HandleCompletion(
2175 str_input, len(str_input), 0, -1, match_strings
2177 common_match = match_strings.GetStringAtIndex(0)
2178 if num_matches == 0:
2179 compare_string = str_input
2180 else:
2181 if common_match != None and len(common_match) > 0:
2182 compare_string = str_input + common_match
2183 else:
2184 compare_string = ""
2185 for idx in range(1, num_matches + 1):
2186 compare_string += match_strings.GetStringAtIndex(idx) + "\n"
2188 if len(patterns) == 1 and str_input == patterns[0] and num_matches:
2189 self.fail("Expected no completions but got:\n" + compare_string)
2191 for p in patterns:
2192 self.expect(
2193 compare_string,
2194 msg=COMPLETION_MSG(str_input, p, match_strings),
2195 exe=False,
2196 substrs=[p],
2199 def completions_match(self, command, completions):
2200 """Checks that the completions for the given command are equal to the
2201 given list of completions"""
2202 interp = self.dbg.GetCommandInterpreter()
2203 match_strings = lldb.SBStringList()
2204 interp.HandleCompletion(command, len(command), 0, -1, match_strings)
2205 # match_strings is a 1-indexed list, so we have to slice...
2206 self.assertCountEqual(
2207 completions, list(match_strings)[1:], "List of returned completion is wrong"
2210 def completions_contain(self, command, completions):
2211 """Checks that the completions for the given command contain the given
2212 list of completions."""
2213 interp = self.dbg.GetCommandInterpreter()
2214 match_strings = lldb.SBStringList()
2215 interp.HandleCompletion(command, len(command), 0, -1, match_strings)
2216 for completion in completions:
2217 # match_strings is a 1-indexed list, so we have to slice...
2218 self.assertIn(
2219 completion, list(match_strings)[1:], "Couldn't find expected completion"
2222 def filecheck(
2223 self, command, check_file, filecheck_options="", expect_cmd_failure=False
2225 # Run the command.
2226 self.runCmd(
2227 command,
2228 check=(not expect_cmd_failure),
2229 msg="FileCheck'ing result of `{0}`".format(command),
2232 self.assertTrue((not expect_cmd_failure) == self.res.Succeeded())
2234 # Get the error text if there was an error, and the regular text if not.
2235 output = self.res.GetOutput() if self.res.Succeeded() else self.res.GetError()
2237 # Assemble the absolute path to the check file. As a convenience for
2238 # LLDB inline tests, assume that the check file is a relative path to
2239 # a file within the inline test directory.
2240 if check_file.endswith(".pyc"):
2241 check_file = check_file[:-1]
2242 check_file_abs = os.path.abspath(check_file)
2244 # Run FileCheck.
2245 filecheck_bin = configuration.get_filecheck_path()
2246 if not filecheck_bin:
2247 self.assertTrue(False, "No valid FileCheck executable specified")
2248 filecheck_args = [filecheck_bin, check_file_abs]
2249 if filecheck_options:
2250 filecheck_args.append(filecheck_options)
2251 subproc = Popen(
2252 filecheck_args,
2253 stdin=PIPE,
2254 stdout=PIPE,
2255 stderr=PIPE,
2256 universal_newlines=True,
2258 cmd_stdout, cmd_stderr = subproc.communicate(input=output)
2259 cmd_status = subproc.returncode
2261 filecheck_cmd = " ".join(filecheck_args)
2262 filecheck_trace = """
2263 --- FileCheck trace (code={0}) ---
2266 FileCheck input:
2269 FileCheck output:
2272 """.format(
2273 cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr
2276 trace = cmd_status != 0 or traceAlways
2277 with recording(self, trace) as sbuf:
2278 print(filecheck_trace, file=sbuf)
2280 self.assertTrue(cmd_status == 0)
2282 def expect(
2283 self,
2284 string,
2285 msg=None,
2286 patterns=None,
2287 startstr=None,
2288 endstr=None,
2289 substrs=None,
2290 trace=False,
2291 error=False,
2292 ordered=True,
2293 matching=True,
2294 exe=True,
2295 inHistory=False,
2298 Similar to runCmd; with additional expect style output matching ability.
2300 Ask the command interpreter to handle the command and then check its
2301 return status. The 'msg' parameter specifies an informational assert
2302 message. We expect the output from running the command to start with
2303 'startstr', matches the substrings contained in 'substrs', and regexp
2304 matches the patterns contained in 'patterns'.
2306 When matching is true and ordered is true, which are both the default,
2307 the strings in the substrs array have to appear in the command output
2308 in the order in which they appear in the array.
2310 If the keyword argument error is set to True, it signifies that the API
2311 client is expecting the command to fail. In this case, the error stream
2312 from running the command is retrieved and compared against the golden
2313 input, instead.
2315 If the keyword argument matching is set to False, it signifies that the API
2316 client is expecting the output of the command not to match the golden
2317 input.
2319 Finally, the required argument 'string' represents the lldb command to be
2320 sent to the command interpreter. In case the keyword argument 'exe' is
2321 set to False, the 'string' is treated as a string to be matched/not-matched
2322 against the golden input.
2324 # Catch cases where `expect` has been miscalled. Specifically, prevent
2325 # this easy to make mistake:
2326 # self.expect("lldb command", "some substr")
2327 # The `msg` parameter is used only when a failed match occurs. A failed
2328 # match can only occur when one of `patterns`, `startstr`, `endstr`, or
2329 # `substrs` has been given. Thus, if a `msg` is given, it's an error to
2330 # not also provide one of the matcher parameters.
2331 if msg and not (patterns or startstr or endstr or substrs or error):
2332 assert False, "expect() missing a matcher argument"
2334 # Check `patterns` and `substrs` are not accidentally given as strings.
2335 assert not isinstance(patterns, str), "patterns must be a collection of strings"
2336 assert not isinstance(substrs, str), "substrs must be a collection of strings"
2338 trace = True if traceAlways else trace
2340 if exe:
2341 # First run the command. If we are expecting error, set check=False.
2342 # Pass the assert message along since it provides more semantic
2343 # info.
2344 self.runCmd(
2345 string,
2346 msg=msg,
2347 trace=(True if trace else False),
2348 check=not error,
2349 inHistory=inHistory,
2352 # Then compare the output against expected strings.
2353 output = self.res.GetError() if error else self.res.GetOutput()
2355 # If error is True, the API client expects the command to fail!
2356 if error:
2357 self.assertFalse(
2358 self.res.Succeeded(),
2359 "Command '" + string + "' is expected to fail!",
2361 else:
2362 # No execution required, just compare string against the golden input.
2363 if isinstance(string, lldb.SBCommandReturnObject):
2364 output = string.GetOutput()
2365 else:
2366 output = string
2367 with recording(self, trace) as sbuf:
2368 print("looking at:", output, file=sbuf)
2370 expecting_str = "Expecting" if matching else "Not expecting"
2372 def found_str(matched):
2373 return "was found" if matched else "was not found"
2375 # To be used as assert fail message and/or trace content
2376 log_lines = [
2377 "{}:".format("Ran command" if exe else "Checking string"),
2378 '"{}"'.format(string),
2379 # Space out command and output
2382 if exe:
2383 # Newline before output to make large strings more readable
2384 log_lines.append("Got output:\n{}".format(output))
2386 # Assume that we start matched if we want a match
2387 # Meaning if you have no conditions, matching or
2388 # not matching will always pass
2389 matched = matching
2391 # We will stop checking on first failure
2392 if startstr:
2393 matched = output.startswith(startstr)
2394 log_lines.append(
2395 '{} start string: "{}" ({})'.format(
2396 expecting_str, startstr, found_str(matched)
2400 if endstr and matched == matching:
2401 matched = output.endswith(endstr)
2402 log_lines.append(
2403 '{} end string: "{}" ({})'.format(
2404 expecting_str, endstr, found_str(matched)
2408 if substrs and matched == matching:
2409 start = 0
2410 for substr in substrs:
2411 index = output[start:].find(substr)
2412 start = start + index + len(substr) if ordered and matching else 0
2413 matched = index != -1
2414 log_lines.append(
2415 '{} sub string: "{}" ({})'.format(
2416 expecting_str, substr, found_str(matched)
2420 if matched != matching:
2421 break
2423 if patterns and matched == matching:
2424 for pattern in patterns:
2425 matched = re.search(pattern, output)
2427 pattern_line = '{} regex pattern: "{}" ({}'.format(
2428 expecting_str, pattern, found_str(matched)
2430 if matched:
2431 pattern_line += ', matched "{}"'.format(matched.group(0))
2432 pattern_line += ")"
2433 log_lines.append(pattern_line)
2435 # Convert to bool because match objects
2436 # are True-ish but != True itself
2437 matched = bool(matched)
2438 if matched != matching:
2439 break
2441 # If a check failed, add any extra assert message
2442 if msg is not None and matched != matching:
2443 log_lines.append(msg)
2445 log_msg = "\n".join(log_lines)
2446 with recording(self, trace) as sbuf:
2447 print(log_msg, file=sbuf)
2448 if matched != matching:
2449 self.fail(log_msg)
2451 def expect_expr(
2452 self,
2453 expr,
2454 result_summary=None,
2455 result_value=None,
2456 result_type=None,
2457 result_children=None,
2460 Evaluates the given expression and verifies the result.
2461 :param expr: The expression as a string.
2462 :param result_summary: The summary that the expression should have. None if the summary should not be checked.
2463 :param result_value: The value that the expression should have. None if the value should not be checked.
2464 :param result_type: The type that the expression result should have. None if the type should not be checked.
2465 :param result_children: The expected children of the expression result
2466 as a list of ValueChecks. None if the children shouldn't be checked.
2468 self.assertTrue(
2469 expr.strip() == expr,
2470 "Expression contains trailing/leading whitespace: '" + expr + "'",
2473 frame = self.frame()
2474 options = lldb.SBExpressionOptions()
2476 # Disable fix-its that tests don't pass by accident.
2477 options.SetAutoApplyFixIts(False)
2479 # Set the usual default options for normal expressions.
2480 options.SetIgnoreBreakpoints(True)
2482 if self.frame().IsValid():
2483 options.SetLanguage(frame.GuessLanguage())
2484 eval_result = self.frame().EvaluateExpression(expr, options)
2485 else:
2486 target = self.target()
2487 # If there is no selected target, run the expression in the dummy
2488 # target.
2489 if not target.IsValid():
2490 target = self.dbg.GetDummyTarget()
2491 eval_result = target.EvaluateExpression(expr, options)
2493 value_check = ValueCheck(
2494 type=result_type,
2495 value=result_value,
2496 summary=result_summary,
2497 children=result_children,
2499 value_check.check_value(self, eval_result, str(eval_result))
2500 return eval_result
2502 def expect_var_path(
2503 self, var_path, summary=None, value=None, type=None, children=None
2506 Evaluates the given variable path and verifies the result.
2507 See also 'frame variable' and SBFrame.GetValueForVariablePath.
2508 :param var_path: The variable path as a string.
2509 :param summary: The summary that the variable should have. None if the summary should not be checked.
2510 :param value: The value that the variable should have. None if the value should not be checked.
2511 :param type: The type that the variable result should have. None if the type should not be checked.
2512 :param children: The expected children of the variable as a list of ValueChecks.
2513 None if the children shouldn't be checked.
2515 self.assertTrue(
2516 var_path.strip() == var_path,
2517 "Expression contains trailing/leading whitespace: '" + var_path + "'",
2520 frame = self.frame()
2521 eval_result = frame.GetValueForVariablePath(var_path)
2523 value_check = ValueCheck(
2524 type=type, value=value, summary=summary, children=children
2526 value_check.check_value(self, eval_result, str(eval_result))
2527 return eval_result
2529 """Assert that an lldb.SBError is in the "success" state."""
2531 def assertSuccess(self, obj, msg=None):
2532 if not obj.Success():
2533 error = obj.GetCString()
2534 self.fail(self._formatMessage(msg, "'{}' is not success".format(error)))
2536 """Assert that an lldb.SBError is in the "failure" state."""
2538 def assertFailure(self, obj, error_str=None, msg=None):
2539 if obj.Success():
2540 self.fail(self._formatMessage(msg, "Error not in a fail state"))
2542 if error_str == None:
2543 return
2545 error = obj.GetCString()
2546 self.assertEqual(error, error_str, msg)
2548 """Assert that a command return object is successful"""
2550 def assertCommandReturn(self, obj, msg=None):
2551 if not obj.Succeeded():
2552 error = obj.GetError()
2553 self.fail(self._formatMessage(msg, "'{}' is not success".format(error)))
2555 """Assert two states are equal"""
2557 def assertState(self, first, second, msg=None):
2558 if first != second:
2559 error = "{} ({}) != {} ({})".format(
2560 lldbutil.state_type_to_str(first),
2561 first,
2562 lldbutil.state_type_to_str(second),
2563 second,
2565 self.fail(self._formatMessage(msg, error))
2567 """Assert two stop reasons are equal"""
2569 def assertStopReason(self, first, second, msg=None):
2570 if first != second:
2571 error = "{} ({}) != {} ({})".format(
2572 lldbutil.stop_reason_to_str(first),
2573 first,
2574 lldbutil.stop_reason_to_str(second),
2575 second,
2577 self.fail(self._formatMessage(msg, error))
2579 def createTestTarget(self, file_path=None, msg=None, load_dependent_modules=True):
2581 Creates a target from the file found at the given file path.
2582 Asserts that the resulting target is valid.
2583 :param file_path: The file path that should be used to create the target.
2584 The default argument opens the current default test
2585 executable in the current test directory.
2586 :param msg: A custom error message.
2588 if file_path is None:
2589 file_path = self.getBuildArtifact("a.out")
2590 error = lldb.SBError()
2591 triple = ""
2592 platform = ""
2593 target = self.dbg.CreateTarget(
2594 file_path, triple, platform, load_dependent_modules, error
2596 if error.Fail():
2597 err = "Couldn't create target for path '{}': {}".format(
2598 file_path, str(error)
2600 self.fail(self._formatMessage(msg, err))
2602 self.assertTrue(target.IsValid(), "Got invalid target without error")
2603 return target
2605 # =================================================
2606 # Misc. helper methods for debugging test execution
2607 # =================================================
2609 def DebugSBValue(self, val):
2610 """Debug print a SBValue object, if traceAlways is True."""
2611 from .lldbutil import value_type_to_str
2613 if not traceAlways:
2614 return
2616 err = sys.stderr
2617 err.write(val.GetName() + ":\n")
2618 err.write("\t" + "TypeName -> " + val.GetTypeName() + "\n")
2619 err.write("\t" + "ByteSize -> " + str(val.GetByteSize()) + "\n")
2620 err.write("\t" + "NumChildren -> " + str(val.GetNumChildren()) + "\n")
2621 err.write("\t" + "Value -> " + str(val.GetValue()) + "\n")
2622 err.write("\t" + "ValueAsUnsigned -> " + str(val.GetValueAsUnsigned()) + "\n")
2623 err.write(
2624 "\t" + "ValueType -> " + value_type_to_str(val.GetValueType()) + "\n"
2626 err.write("\t" + "Summary -> " + str(val.GetSummary()) + "\n")
2627 err.write("\t" + "IsPointerType -> " + str(val.TypeIsPointerType()) + "\n")
2628 err.write("\t" + "Location -> " + val.GetLocation() + "\n")
2630 def DebugSBType(self, type):
2631 """Debug print a SBType object, if traceAlways is True."""
2632 if not traceAlways:
2633 return
2635 err = sys.stderr
2636 err.write(type.GetName() + ":\n")
2637 err.write("\t" + "ByteSize -> " + str(type.GetByteSize()) + "\n")
2638 err.write("\t" + "IsAggregateType -> " + str(type.IsAggregateType()) + "\n")
2639 err.write("\t" + "IsPointerType -> " + str(type.IsPointerType()) + "\n")
2640 err.write("\t" + "IsReferenceType -> " + str(type.IsReferenceType()) + "\n")
2642 def DebugPExpect(self, child):
2643 """Debug the spwaned pexpect object."""
2644 if not traceAlways:
2645 return
2647 print(child)
2649 @classmethod
2650 def RemoveTempFile(cls, file):
2651 if os.path.exists(file):
2652 remove_file(file)
2655 # On Windows, the first attempt to delete a recently-touched file can fail
2656 # because of a race with antimalware scanners. This function will detect a
2657 # failure and retry.
2660 def remove_file(file, num_retries=1, sleep_duration=0.5):
2661 for i in range(num_retries + 1):
2662 try:
2663 os.remove(file)
2664 return True
2665 except:
2666 time.sleep(sleep_duration)
2667 continue
2668 return False