diff options
Diffstat (limited to 'packages/Python/lldbsuite/test')
305 files changed, 8121 insertions, 2432 deletions
diff --git a/packages/Python/lldbsuite/test/README-TestSuite b/packages/Python/lldbsuite/test/README-TestSuite index 92649fc9963c..8ea64c0aa3d5 100644 --- a/packages/Python/lldbsuite/test/README-TestSuite +++ b/packages/Python/lldbsuite/test/README-TestSuite @@ -1,7 +1,7 @@ -This README file describes the files and directories related to the Python test -suite under the current 'test' directory. +This README file describes the files and directories related -*- rst -*- +to the Python test suite under the current 'test' directory. -o dotest.py +- dotest.py Provides the test driver for the test suite. To invoke it, cd to the 'test' directory and issue the './dotest.py' command or './dotest.py -v' for more @@ -20,7 +20,7 @@ o dotest.py This runs the test suite, with logging turned on for the lldb as well as the process.gdb-remote channels and directs the run log to a file. -o lldbtest.py +- lldbtest.py Provides an abstract base class of lldb test case named 'TestBase', which in turn inherits from Python's unittest.TestCase. The concrete subclass can @@ -41,7 +41,7 @@ o lldbtest.py test case on its own. To run the whole test suite, 'dotest.py' is all you need to do. -o subdirectories of 'test' +- subdirectories of 'test' Most of them predate the introduction of the python test suite and contain example C/C++/ObjC source files which get compiled into executables which are @@ -58,7 +58,7 @@ o subdirectories of 'test' testcase that run a process to a breakpoint and check a local variable. These are convenient starting points for adding new tests. -o make directory +- make directory Contains Makefile.rules, which can be utilized by test cases to write Makefile based rules to build binaries for the inferiors. @@ -95,12 +95,12 @@ o make directory The exe names for the two test methods are equal to the test method names and are therefore guaranteed different. -o plugins directory +- plugins directory Contains platform specific plugin to build binaries with dsym/dwarf debugging info. Other platform specific functionalities may be added in the future. -o unittest2 directory +- unittest2 directory Many new features were added to unittest in Python 2.7, including test discovery. unittest2 allows you to use these features with earlier versions of @@ -114,7 +114,7 @@ o unittest2 directory Later versions of unittest2 include changes in unittest made in Python 3.2 and onwards after the release of Python 2.7. -o dotest.pl +- dotest.pl In case you wonder, there is also a 'dotest.pl' perl script file. It was created to visit each Python test case under the specified directory and @@ -127,47 +127,56 @@ o dotest.pl Note: dotest.pl has been moved to the attic directory. -o Profiling dotest.py runs +- Profiling dotest.py runs I used the following command line thingy to do the profiling on a SnowLeopard machine: -$ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log + $ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log After that, I used the pstats.py module to browse the statistics: -$ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile - -o Writing test cases: - - We strongly prefer writing test cases using the SB API's rather than the runCmd & expect. - Unless you are actually testing some feature of the command line, please don't write - command based tests. For historical reasons there are plenty of examples of tests in the - test suite that use runCmd where they shouldn't, but don't copy them, copy the plenty that - do use the SB API's instead. - - The reason for this is that our policy is that we will maintain compatibility with the - SB API's. But we don't make any similar guarantee about the details of command result format. - If your test is using the command line, it is going to have to check against the command result - text, and you either end up writing your check pattern by checking as little as possible so - you won't be exposed to random changes in the text; in which case you can end up missing some - failure, or you test too much and it means irrelevant changes break your tests. - - However, if you use the Python API's it is possible to check all the results you want - to check in a very explicit way, which makes the tests much more robust. - - Even if you are testing that a command-line command does some specific thing, it is still - better in general to use the SB API's to drive to the point where you want to run the test, - then use SBInterpreter::HandleCommand to run the command. You get the full result text - from the command in the command return object, and all the part where you are driving the - debugger to the point you want to test will be more robust. - - The sample_test directory contains a standard and an "inline" test that are good starting - points for writing a new test. - -o Attaching in test cases: - - If you need to attach to inferiors in your tests, you must make sure the inferior calls - lldb_enable_attach(), before the debugger attempts to attach. This function performs any - platform-specific processing needed to enable attaching to this process (e.g., on Linux, we - execute prctl(PR_SET_TRACER) syscall to disable protections present in some Linux systems). + $ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile + +- Writing test cases: + + We strongly prefer writing test cases using the SB API's rather than + the runCmd & expect. Unless you are actually testing some feature + of the command line, please don't write command based tests. For + historical reasons there are plenty of examples of tests in the test + suite that use runCmd where they shouldn't, but don't copy them, + copy the plenty that do use the SB API's instead. + + The reason for this is that our policy is that we will maintain + compatibility with the SB API's. But we don't make any similar + guarantee about the details of command result format. If your test + is using the command line, it is going to have to check against the + command result text, and you either end up writing your check + pattern by checking as little as possible so you won't be exposed to + random changes in the text; in which case you can end up missing + some failure, or you test too much and it means irrelevant changes + break your tests. + + However, if you use the Python API's it is possible to check all the + results you want to check in a very explicit way, which makes the + tests much more robust. + + Even if you are testing that a command-line command does some + specific thing, it is still better in general to use the SB API's to + drive to the point where you want to run the test, then use + SBInterpreter::HandleCommand to run the command. You get the full + result text from the command in the command return object, and all + the part where you are driving the debugger to the point you want to + test will be more robust. + + The sample_test directory contains a standard and an "inline" test + that are good starting points for writing a new test. + +- Attaching in test cases: + + If you need to attach to inferiors in your tests, you must make sure + the inferior calls lldb_enable_attach(), before the debugger + attempts to attach. This function performs any platform-specific + processing needed to enable attaching to this process (e.g., on + Linux, we execute prctl(PR_SET_TRACER) syscall to disable + protections present in some Linux systems). diff --git a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py index dd03fcf31e87..d91eec1fd51b 100644 --- a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py +++ b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py @@ -68,7 +68,7 @@ class SBBreakpointCallbackCase(TestBase): # clang-cl does not support throw or catch (llvm.org/pr24538) @skipIfWindows @expectedFlakeyFreeBSD - @expectedFailureAll(oslist=["linux"]) + @skipIf(oslist=["linux"]) # flakey def test_sb_api_listener_resume(self): """ Test that a process can be resumed from a non-main thread. """ self.build_and_test( diff --git a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py index 30510638f096..e9dbe670dc0b 100644 --- a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py +++ b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py @@ -19,6 +19,7 @@ class TestBreakpointIt(TestBase): NO_DEBUG_INFO_TESTCASE = True @skipIf(archs=no_match(["arm"])) + @skipIf(archs=["arm64", "arm64e"]) def test_false(self): self.build() exe = self.getBuildArtifact("a.out") @@ -32,6 +33,7 @@ class TestBreakpointIt(TestBase): "Breakpoint does not get hit") @skipIf(archs=no_match(["arm"])) + @skipIf(archs=["arm64", "arm64e"]) def test_true(self): self.build() exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py deleted file mode 100644 index 8bce4815894d..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py +++ /dev/null @@ -1,165 +0,0 @@ -"""Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -def is_exe(fpath): - """Returns true if fpath is an executable.""" - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - -class DisassembleDriverMainLoop(BenchBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - """ - Note that lldbtest_config.lldbExec can be specified with the LLDB_EXEC env variable (see - dotest.py), and gdbExec can be specified with the GDB_EXEC env variable. - This provides a flexibility in specifying different versions of gdb for - comparison purposes. - """ - BenchBase.setUp(self) - # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your - # PATH env var. - if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]): - self.gdbExec = os.environ["GDB_EXEC"] - else: - self.gdbExec = "gdb" - - self.exe = lldbtest_config.lldbExec - self.function = 'Driver::MainLoop()' - self.lldb_avg = None - self.gdb_avg = None - self.count = 5 - - @benchmarks_test - @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_run_lldb_then_gdb(self): - """Test disassembly on a large function with lldb vs. gdb.""" - print() - print("lldb path: %s" % lldbtest_config.lldbExec) - print("gdb path: %s" % self.gdbExec) - - print() - self.run_lldb_disassembly(self.exe, self.function, self.count) - print("lldb benchmark:", self.stopwatch) - self.run_gdb_disassembly(self.exe, self.function, self.count) - print("gdb benchmark:", self.stopwatch) - print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg)) - - @benchmarks_test - @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_run_gdb_then_lldb(self): - """Test disassembly on a large function with lldb vs. gdb.""" - print() - print("lldb path: %s" % lldbtest_config.lldbExec) - print("gdb path: %s" % self.gdbExec) - - print() - self.run_gdb_disassembly(self.exe, self.function, self.count) - print("gdb benchmark:", self.stopwatch) - self.run_lldb_disassembly(self.exe, self.function, self.count) - print("lldb benchmark:", self.stopwatch) - print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg)) - - def run_lldb_disassembly(self, exe, function, count): - import pexpect - # Set self.child_prompt, which is "(lldb) ". - self.child_prompt = '(lldb) ' - prompt = self.child_prompt - - # So that the child gets torn down after the test. - self.child = pexpect.spawn( - '%s %s %s' % - (lldbtest_config.lldbExec, self.lldbOption, exe)) - child = self.child - - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - child.expect_exact(prompt) - child.sendline('breakpoint set -F %s' % function) - child.expect_exact(prompt) - child.sendline('run') - child.expect_exact(prompt) - - # Reset the stopwatch now. - self.stopwatch.reset() - for i in range(count): - with self.stopwatch: - # Disassemble the function. - child.sendline('disassemble -f') - child.expect_exact(prompt) - child.sendline('next') - child.expect_exact(prompt) - - child.sendline('quit') - try: - self.child.expect(pexpect.EOF) - except: - pass - - self.lldb_avg = self.stopwatch.avg() - if self.TraceOn(): - print("lldb disassembly benchmark:", str(self.stopwatch)) - self.child = None - - def run_gdb_disassembly(self, exe, function, count): - import pexpect - # Set self.child_prompt, which is "(gdb) ". - self.child_prompt = '(gdb) ' - prompt = self.child_prompt - - # So that the child gets torn down after the test. - self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe)) - child = self.child - - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - child.expect_exact(prompt) - child.sendline('break %s' % function) - child.expect_exact(prompt) - child.sendline('run') - child.expect_exact(prompt) - - # Reset the stopwatch now. - self.stopwatch.reset() - for i in range(count): - with self.stopwatch: - # Disassemble the function. - child.sendline('disassemble') - child.expect_exact(prompt) - child.sendline('next') - child.expect_exact(prompt) - - child.sendline('quit') - child.expect_exact('The program is running. Exit anyway?') - child.sendline('y') - try: - self.child.expect(pexpect.EOF) - except: - pass - - self.gdb_avg = self.stopwatch.avg() - if self.TraceOn(): - print("gdb disassembly benchmark:", str(self.stopwatch)) - self.child = None diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py deleted file mode 100644 index 36f23572648d..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Test lldb's disassemblt speed. This bench deliberately attaches to an lldb -inferior and traverses the stack for thread0 to arrive at frame with function -'MainLoop'. It is important to specify an lldb executable as the inferior.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * - - -class AttachThenDisassemblyBench(BenchBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - BenchBase.setUp(self) - self.exe = lldbtest_config.lldbExec - self.count = 10 - - @benchmarks_test - @no_debug_info_test - def test_attach_then_disassembly(self): - """Attach to a spawned lldb process then run disassembly benchmarks.""" - print() - self.run_lldb_attach_then_disassembly(self.exe, self.count) - print("lldb disassembly benchmark:", self.stopwatch) - - def run_lldb_attach_then_disassembly(self, exe, count): - target = self.dbg.CreateTarget(exe) - - # Spawn a new process and don't display the stdout if not in TraceOn() - # mode. - import subprocess - popen = subprocess.Popen([exe, self.lldbOption], stdout=open( - os.devnull, 'w') if not self.TraceOn() else None) - if self.TraceOn(): - print("pid of spawned process: %d" % popen.pid) - - # Attach to the launched lldb process. - listener = lldb.SBListener("my.attach.listener") - error = lldb.SBError() - process = target.AttachToProcessWithID(listener, popen.pid, error) - - # Set thread0 as the selected thread, followed by the 'MainLoop' frame - # as the selected frame. Then do disassembly on the function. - thread0 = process.GetThreadAtIndex(0) - process.SetSelectedThread(thread0) - i = 0 - found = False - for f in thread0: - # print("frame#%d %s" % (i, f.GetFunctionName())) - if "MainLoop" in f.GetFunctionName(): - found = True - thread0.SetSelectedFrame(i) - if self.TraceOn(): - print("Found frame#%d for function 'MainLoop'" % i) - break - i += 1 - - # Reset the stopwatch now. - self.stopwatch.reset() - for i in range(count): - with self.stopwatch: - # Disassemble the function. - self.runCmd("disassemble -f") diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py deleted file mode 100644 index fd91bb441d9f..000000000000 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Disassemble lldb's Driver::MainLoop() functions comparing Xcode 4.1 vs. 4.2's gdb.""" - -from __future__ import print_function - - -import os -import sys -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbbench import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import configuration -from lldbsuite.test import lldbutil - - -class XCode41Vs42GDBDisassembly(BenchBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - BenchBase.setUp(self) - self.gdb_41_exe = '/Xcode41/usr/bin/gdb' - self.gdb_42_exe = '/Developer/usr/bin/gdb' - self.exe = lldbtest_config.lldbExec - self.function = 'Driver::MainLoop()' - self.gdb_41_avg = None - self.gdb_42_avg = None - self.count = 5 - - @benchmarks_test - @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_run_41_then_42(self): - """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" - print() - self.run_gdb_disassembly( - self.gdb_41_exe, - self.exe, - self.function, - self.count) - print("4.1 gdb benchmark:", self.stopwatch) - self.gdb_41_avg = self.stopwatch.avg() - self.run_gdb_disassembly( - self.gdb_42_exe, - self.exe, - self.function, - self.count) - print("4.2 gdb benchmark:", self.stopwatch) - self.gdb_42_avg = self.stopwatch.avg() - print("gdb_42_avg/gdb_41_avg: %f" % - (self.gdb_42_avg / self.gdb_41_avg)) - - @benchmarks_test - @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_run_42_then_41(self): - """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" - print() - self.run_gdb_disassembly( - self.gdb_42_exe, - self.exe, - self.function, - self.count) - print("4.2 gdb benchmark:", self.stopwatch) - self.gdb_42_avg = self.stopwatch.avg() - self.run_gdb_disassembly( - self.gdb_41_exe, - self.exe, - self.function, - self.count) - print("4.1 gdb benchmark:", self.stopwatch) - self.gdb_41_avg = self.stopwatch.avg() - print("gdb_42_avg/gdb_41_avg: %f" % - (self.gdb_42_avg / self.gdb_41_avg)) - - def run_gdb_disassembly(self, gdb_exe_path, exe, function, count): - import pexpect - # Set self.child_prompt, which is "(gdb) ". - self.child_prompt = '(gdb) ' - prompt = self.child_prompt - - # So that the child gets torn down after the test. - self.child = pexpect.spawn('%s --nx %s' % (gdb_exe_path, exe)) - child = self.child - - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - child.expect_exact(prompt) - child.sendline('break %s' % function) - child.expect_exact(prompt) - child.sendline('run') - child.expect_exact(prompt) - - # Reset the stopwatch now. - self.stopwatch.reset() - for i in range(count): - with self.stopwatch: - # Disassemble the function. - child.sendline('disassemble') - child.expect_exact(prompt) - child.sendline('next') - child.expect_exact(prompt) - - child.sendline('quit') - child.expect_exact('The program is running. Exit anyway?') - child.sendline('y') - try: - self.child.expect(pexpect.EOF) - except: - pass - - if self.TraceOn(): - print("gdb disassembly benchmark:", str(self.stopwatch)) - self.child = None diff --git a/packages/Python/lldbsuite/test/configuration.py b/packages/Python/lldbsuite/test/configuration.py index 94781050dc4b..a7f4ac7efe2b 100644 --- a/packages/Python/lldbsuite/test/configuration.py +++ b/packages/Python/lldbsuite/test/configuration.py @@ -46,6 +46,9 @@ count = 1 arch = None # Must be initialized after option parsing compiler = None # Must be initialized after option parsing +# Path to the FileCheck testing tool. Not optional. +filecheck = None + # The arch might dictate some specific CFLAGS to be passed to the toolchain to build # the inferior programs. The global variable cflags_extras provides a hook to do # just that. @@ -110,9 +113,13 @@ lldb_platform_working_dir = None # The base directory in which the tests are being built. test_build_dir = None +# The only directory to scan for tests. If multiple test directories are +# specified, and an exclusive test subdirectory is specified, the latter option +# takes precedence. +exclusive_test_subdir = None + # Parallel execution settings is_inferior_test_runner = False -multiprocess_test_subdir = None num_threads = None no_multiprocess_test_runner = False test_runner_name = None @@ -144,3 +151,42 @@ def shouldSkipBecauseOfCategories(test_categories): return True return False + + +def get_absolute_path_to_exclusive_test_subdir(): + """ + If an exclusive test subdirectory is specified, return its absolute path. + Otherwise return None. + """ + test_directory = os.path.dirname(os.path.realpath(__file__)) + + if not exclusive_test_subdir: + return + + if len(exclusive_test_subdir) > 0: + test_subdir = os.path.join(test_directory, exclusive_test_subdir) + if os.path.isdir(test_subdir): + return test_subdir + + print('specified test subdirectory {} is not a valid directory\n' + .format(test_subdir)) + + +def get_absolute_path_to_root_test_dir(): + """ + If an exclusive test subdirectory is specified, return its absolute path. + Otherwise, return the absolute path of the root test directory. + """ + test_subdir = get_absolute_path_to_exclusive_test_subdir() + if test_subdir: + return test_subdir + + return os.path.dirname(os.path.realpath(__file__)) + + +def get_filecheck_path(): + """ + Get the path to the FileCheck testing tool. + """ + if filecheck and os.path.lexists(filecheck): + return filecheck diff --git a/packages/Python/lldbsuite/test/decorators.py b/packages/Python/lldbsuite/test/decorators.py index 8b33cad3d1ba..2458a6f8745e 100644 --- a/packages/Python/lldbsuite/test/decorators.py +++ b/packages/Python/lldbsuite/test/decorators.py @@ -74,13 +74,14 @@ def _check_expected_version(comparison, expected, actual): LooseVersion(expected_str)) +_re_pattern_type = type(re.compile('')) def _match_decorator_property(expected, actual): if actual is None or expected is None: return True if isinstance(expected, no_match): return not _match_decorator_property(expected.item, actual) - elif isinstance(expected, (re._pattern_type,) + six.string_types): + elif isinstance(expected, (_re_pattern_type,) + six.string_types): return re.search(expected, actual) is not None elif hasattr(expected, "__iter__"): return any([x is not None and _match_decorator_property(x, actual) @@ -192,10 +193,10 @@ def _decorateTest(mode, py_version is None) or _check_expected_version( py_version[0], py_version[1], sys.version_info) skip_for_macos_version = (macos_version is None) or ( - _check_expected_version( + (platform.mac_ver()[0] != "") and (_check_expected_version( macos_version[0], macos_version[1], - platform.mac_ver()[0])) + platform.mac_ver()[0]))) # For the test to be skipped, all specified (e.g. not None) parameters must be True. # An unspecified parameter means "any", so those are marked skip by default. And we skip @@ -457,12 +458,6 @@ def expectedFlakey(expected_fn, bugnumber=None): return expectedFailure_impl -def expectedFlakeyDsym(bugnumber=None): - def fn(self): - return self.getDebugInfo() == "dwarf" - return expectedFlakey(fn, bugnumber) - - def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): def fn(self): return (self.getPlatform() in oslist and @@ -600,28 +595,6 @@ def skipUnlessDarwin(func): return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) -def skipUnlessGoInstalled(func): - """Decorate the item to skip tests when no Go compiler is available.""" - - def is_go_missing(self): - compiler = self.getGoCompilerVersion() - if not compiler: - return "skipping because go compiler not found" - match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) - if not match_version: - # Couldn't determine version. - return "skipping because go version could not be parsed out of {}".format( - compiler) - else: - min_strict_version = StrictVersion("1.4.0") - compiler_strict_version = StrictVersion(match_version.group(1)) - if compiler_strict_version < min_strict_version: - return "skipping because available version ({}) does not meet minimum required version ({})".format( - compiler_strict_version, min_strict_version) - return None - return skipTestIfFn(is_go_missing)(func) - - def skipIfHostIncompatibleWithRemote(func): """Decorate the item to skip tests if binaries built on this host are incompatible.""" @@ -687,6 +660,30 @@ def skipUnlessSupportedTypeAttribute(attr): return None return skipTestIfFn(compiler_doesnt_support_struct_attribute) +def skipUnlessHasCallSiteInfo(func): + """Decorate the function to skip testing unless call site info from clang is available.""" + + def is_compiler_clang_with_call_site_info(self): + compiler_path = self.getCompiler() + compiler = os.path.basename(compiler_path) + if not compiler.startswith("clang"): + return "Test requires clang as compiler" + + f = tempfile.NamedTemporaryFile() + cmd = "echo 'int main() {}' | " \ + "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name) + if os.popen(cmd).close() is not None: + return "Compiler can't compile with call site info enabled" + + with open(f.name, 'r') as ir_output_file: + buf = ir_output_file.read() + + if 'DIFlagAllCallsDescribed' not in buf: + return "Compiler did not introduce DIFlagAllCallsDescribed IR flag" + + return None + return skipTestIfFn(is_compiler_clang_with_call_site_info)(func) + def skipUnlessThreadSanitizer(func): """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" @@ -810,3 +807,10 @@ def skipUnlessFeature(feature): except subprocess.CalledProcessError: return "%s is not supported on this system." % feature return skipTestIfFn(is_feature_enabled) + +def skipIfSanitized(func): + """Skip this test if the environment is set up to run LLDB itself under ASAN.""" + def is_sanitized(): + return (('DYLD_INSERT_LIBRARIES' in os.environ) and + 'libclang_rt.asan' in os.environ['DYLD_INSERT_LIBRARIES']) + return skipTestIfFn(is_sanitized)(func) diff --git a/packages/Python/lldbsuite/test/dosep.py b/packages/Python/lldbsuite/test/dosep.py index 616fbf381edf..21010c28a78c 100644 --- a/packages/Python/lldbsuite/test/dosep.py +++ b/packages/Python/lldbsuite/test/dosep.py @@ -1558,7 +1558,7 @@ def rerun_tests(test_subdir, tests_for_rerun, dotest_argv, session_dir, print("\nTest rerun complete\n") -def main(num_threads, test_subdir, test_runner_name, results_formatter): +def main(num_threads, test_runner_name, results_formatter): """Run dotest.py in inferior mode in parallel. @param num_threads the parsed value of the num-threads command line @@ -1600,16 +1600,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter): session_dir = os.path.join(os.getcwd(), dotest_options.s) - # The root directory was specified on the command line - test_directory = os.path.dirname(os.path.realpath(__file__)) - if test_subdir and len(test_subdir) > 0: - test_subdir = os.path.join(test_directory, test_subdir) - if not os.path.isdir(test_subdir): - print( - 'specified test subdirectory {} is not a valid directory\n' - .format(test_subdir)) - else: - test_subdir = test_directory + test_subdir = configuration.get_absolute_path_to_root_test_dir() # clean core files in test tree from previous runs (Linux) cores = find('core.*', test_subdir) @@ -1698,7 +1689,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter): # move core files into session dir cores = find('core.*', test_subdir) for core in cores: - dst = core.replace(test_directory, "")[1:] + dst = core.replace(test_subdir, "")[1:] dst = dst.replace(os.path.sep, "-") os.rename(core, os.path.join(session_dir, dst)) diff --git a/packages/Python/lldbsuite/test/dotest.py b/packages/Python/lldbsuite/test/dotest.py index d28c5ef069b7..644f63576c06 100644 --- a/packages/Python/lldbsuite/test/dotest.py +++ b/packages/Python/lldbsuite/test/dotest.py @@ -307,6 +307,24 @@ def parseOptionsAndInitTestdirs(): os.environ['DSYMUTIL'] = seven.get_command_output( 'xcrun -find -toolchain default dsymutil') + if args.filecheck: + # The lldb-dotest script produced by the CMake build passes in a path + # to a working FileCheck binary. So does one specific Xcode project + # target. However, when invoking dotest.py directly, a valid --filecheck + # option needs to be given. + configuration.filecheck = os.path.abspath(args.filecheck) + else: + outputPaths = get_llvm_bin_dirs() + for outputPath in outputPaths: + candidatePath = os.path.join(outputPath, 'FileCheck') + if is_exe(candidatePath): + configuration.filecheck = candidatePath + break + + if not configuration.get_filecheck_path(): + logging.warning('No valid FileCheck executable; some tests may fail...') + logging.warning('(Double-check the --filecheck argument to dotest.py)') + if args.channels: lldbtest_config.channels = args.channels @@ -439,7 +457,7 @@ def parseOptionsAndInitTestdirs(): configuration.num_threads = args.num_threads if args.test_subdir: - configuration.multiprocess_test_subdir = args.test_subdir + configuration.exclusive_test_subdir = args.test_subdir if args.test_runner_name: configuration.test_runner_name = args.test_runner_name @@ -616,6 +634,31 @@ def getOutputPaths(lldbRootDirectory): return result +def get_llvm_bin_dirs(): + """ + Returns an array of paths that may have the llvm/clang/etc binaries + in them, relative to this current file. + Returns an empty array if none are found. + """ + result = [] + + lldb_root_path = os.path.join( + os.path.dirname(__file__), "..", "..", "..", "..") + paths_to_try = [ + "llvm-build/Release+Asserts/x86_64/bin", + "llvm-build/Debug+Asserts/x86_64/bin", + "llvm-build/Release/x86_64/bin", + "llvm-build/Debug/x86_64/bin", + "llvm-build/Ninja-DebugAssert/llvm-macosx-x86_64/bin", + "llvm-build/Ninja-ReleaseAssert/llvm-macosx-x86_64/bin", + "llvm-build/Ninja-RelWithDebInfoAssert/llvm-macosx-x86_64/bin", + ] + for p in paths_to_try: + path = os.path.join(lldb_root_path, p) + if os.path.exists(path): + result.append(path) + + return result def setupSysPath(): """ @@ -646,6 +689,7 @@ def setupSysPath(): pluginPath = os.path.join(scriptPath, 'plugins') toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi') + toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode') toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server') # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the @@ -654,6 +698,9 @@ def setupSysPath(): # Adding test/tools/lldb-mi to the path makes it easy sys.path.insert(0, toolsLLDBMIPath) # to "import lldbmi_testcase" from the MI tests + # Adding test/tools/lldb-vscode to the path makes it easy to + # "import lldb_vscode_testcase" from the VSCode tests + sys.path.insert(0, toolsLLDBVSCode) # Adding test/tools/lldb-server to the path makes it easy sys.path.insert(0, toolsLLDBServerPath) # to "import lldbgdbserverutils" from the lldb-server tests @@ -723,6 +770,15 @@ def setupSysPath(): "The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.") configuration.skipCategories.append("lldb-mi") + lldbVSCodeExec = os.path.join(lldbDir, "lldb-vscode") + if is_exe(lldbVSCodeExec): + os.environ["LLDBVSCODE_EXEC"] = lldbVSCodeExec + else: + if not configuration.shouldSkipBecauseOfCategories(["lldb-vscode"]): + print( + "The 'lldb-vscode' executable cannot be located. The lldb-vscode tests can not be run as a result.") + configuration.skipCategories.append("lldb-vscode") + lldbPythonDir = None # The directory that contains 'lldb/__init__.py' if not configuration.lldbFrameworkPath and os.path.exists(os.path.join(lldbLibDir, "LLDB.framework")): configuration.lldbFrameworkPath = os.path.join(lldbLibDir, "LLDB.framework") @@ -882,6 +938,7 @@ def visit_file(dir, name): unittest2.defaultTestLoader.loadTestsFromName(base)) +# TODO: This should be replaced with a call to find_test_files_in_dir_tree. def visit(prefix, dir, names): """Visitor function for os.path.walk(path, visit, arg).""" @@ -1004,14 +1061,15 @@ def getMyCommandLine(): def checkDsymForUUIDIsNotOn(): cmd = ["defaults", "read", "com.apple.DebugSymbols"] - pipe = subprocess.Popen( + process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - cmd_output = pipe.stdout.read() - if cmd_output and "DBGFileMappedPaths = " in cmd_output: + cmd_output = process.stdout.read() + output_str = cmd_output.decode("utf-8") + if "DBGFileMappedPaths = " in output_str: print("%s =>" % ' '.join(cmd)) - print(cmd_output) + print(output_str) print( "Disable automatic lookup and caching of dSYMs before running the test suite!") print("Exiting...") @@ -1159,7 +1217,6 @@ def run_suite(): from . import dosep dosep.main( configuration.num_threads, - configuration.multiprocess_test_subdir, configuration.test_runner_name, configuration.results_formatter_object) raise Exception("should never get here") @@ -1254,10 +1311,15 @@ def run_suite(): # Don't do lldb-server (llgs) tests on anything except Linux. configuration.dont_do_llgs_test = not ("linux" in target_platform) - # - # Walk through the testdirs while collecting tests. - # - for testdir in configuration.testdirs: + # Collect tests from the specified testing directories. If a test + # subdirectory filter is explicitly specified, limit the search to that + # subdirectory. + exclusive_test_subdir = configuration.get_absolute_path_to_exclusive_test_subdir() + if exclusive_test_subdir: + dirs_to_search = [exclusive_test_subdir] + else: + dirs_to_search = configuration.testdirs + for testdir in dirs_to_search: for (dirpath, dirnames, filenames) in os.walk(testdir): visit('Test', dirpath, filenames) diff --git a/packages/Python/lldbsuite/test/dotest_args.py b/packages/Python/lldbsuite/test/dotest_args.py index 58190d8c75ee..225ccf1181cc 100644 --- a/packages/Python/lldbsuite/test/dotest_args.py +++ b/packages/Python/lldbsuite/test/dotest_args.py @@ -85,6 +85,8 @@ def create_parser(): group.add_argument('--dsymutil', metavar='dsymutil', dest='dsymutil', help=textwrap.dedent('Specify which dsymutil to use.')) + group.add_argument('--filecheck', metavar='filecheck', dest='filecheck', help=textwrap.dedent('Specify which FileCheck binary to use.')) + # Test filtering options group = parser.add_argument_group('Test filtering options') group.add_argument( diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py index 6a8fb5db5439..1108b1215329 100644 --- a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py +++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py @@ -23,7 +23,6 @@ class TestExprLookupAnonStructTypedef(TestBase): # Find the breakpoint self.line = line_number('main.cpp', '// lldb testsuite break') - @expectedFailureAll(oslist=["windows"]) @expectedFailureAll( oslist=['linux'], archs=['arm'], diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py new file mode 100644 index 000000000000..87787f3479a2 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py @@ -0,0 +1,53 @@ +""" +Tests calling builtin functions using expression evaluation. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallBuiltinFunction(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # Builtins are expanded by Clang, so debug info shouldn't matter. + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test these expressions while stopped at this line:') + + def test(self): + self.build() + + # Set breakpoint in main and run exe + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + + # Test different builtin functions. + + interp.HandleCommand("expr __builtin_isinf(0.0f)", result) + self.assertEqual(result.GetOutput(), "(int) $0 = 0\n") + + interp.HandleCommand("expr __builtin_isnormal(0.0f)", result) + self.assertEqual(result.GetOutput(), "(int) $1 = 0\n") + + interp.HandleCommand("expr __builtin_constant_p(1)", result) + self.assertEqual(result.GetOutput(), "(int) $2 = 1\n") + + interp.HandleCommand("expr __builtin_abs(-14)", result) + self.assertEqual(result.GetOutput(), "(int) $3 = 14\n") diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py index 63511779a927..d832983bdb64 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py @@ -6,7 +6,6 @@ from __future__ import print_function import lldb -from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil @@ -24,10 +23,6 @@ class ExprCommandCallStopContinueTestCase(TestBase): '// Please test these expressions while stopped at this line:') self.func_line = line_number('main.cpp', '{5, "five"}') - @expectedFlakeyDarwin("llvm.org/pr20274") - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test(self): """Test gathering result from interrupted function call.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py index ff3bd99ced99..0eb7086b6160 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py @@ -28,10 +28,6 @@ class ExprCommandCallUserDefinedFunction(TestBase): 'main.cpp', '// Please test these expressions while stopped at this line:') - @expectedFlakeyDsym("llvm.org/pr20274") - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test(self): """Test return values of user defined function calls.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py index b328ece6d39c..a9679b7dd368 100644 --- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py +++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py @@ -41,7 +41,6 @@ class ExprCharTestCase(TestBase): self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsSigned(0), 3) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_default_char(self): self.do_test() @@ -52,7 +51,6 @@ class ExprCharTestCase(TestBase): "powerpc64le", "s390x"], bugnumber="llvm.org/pr23069") - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_signed_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'}) @@ -64,7 +62,6 @@ class ExprCharTestCase(TestBase): 'armv7', 'armv7k'], bugnumber="llvm.org/pr23069, <rdar://problem/28721938>") - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") @expectedFailureAll(triple='mips*', bugnumber="llvm.org/pr23069") def test_unsigned_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'}) diff --git a/packages/Python/lldbsuite/test/expression_command/completion/.categories b/packages/Python/lldbsuite/test/expression_command/completion/.categories new file mode 100644 index 000000000000..3a3f4df6416b --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/.categories @@ -0,0 +1 @@ +cmdline diff --git a/packages/Python/lldbsuite/test/expression_command/completion/Makefile b/packages/Python/lldbsuite/test/expression_command/completion/Makefile new file mode 100644 index 000000000000..6fc26a9193f0 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp other.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py new file mode 100644 index 000000000000..536b9e0abcdd --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py @@ -0,0 +1,257 @@ +""" +Test the lldb command line completion mechanism for the 'expr' command. +""" + +from __future__ import print_function + +import random +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + +class CommandLineExprCompletionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_expr_completion(self): + self.build() + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + # Try the completion before we have a context to complete on. + self.assume_no_completions('expr some_expr') + self.assume_no_completions('expr ') + self.assume_no_completions('expr f') + + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + + # Completing member functions + self.complete_exactly('expr some_expr.FooNoArgs', + 'expr some_expr.FooNoArgsBar()') + self.complete_exactly('expr some_expr.FooWithArgs', + 'expr some_expr.FooWithArgsBar(') + self.complete_exactly('expr some_expr.FooWithMultipleArgs', + 'expr some_expr.FooWithMultipleArgsBar(') + self.complete_exactly('expr some_expr.FooUnderscore', + 'expr some_expr.FooUnderscoreBar_()') + self.complete_exactly('expr some_expr.FooNumbers', + 'expr some_expr.FooNumbersBar1()') + self.complete_exactly('expr some_expr.StaticMemberMethod', + 'expr some_expr.StaticMemberMethodBar()') + + # Completing static functions + self.complete_exactly('expr Expr::StaticMemberMethod', + 'expr Expr::StaticMemberMethodBar()') + + # Completing member variables + self.complete_exactly('expr some_expr.MemberVariab', + 'expr some_expr.MemberVariableBar') + + # Multiple completions + self.completions_contain('expr some_expr.', + ['some_expr.FooNumbersBar1()', + 'some_expr.FooUnderscoreBar_()', + 'some_expr.FooWithArgsBar(', + 'some_expr.MemberVariableBar']) + + self.completions_contain('expr some_expr.Foo', + ['some_expr.FooNumbersBar1()', + 'some_expr.FooUnderscoreBar_()', + 'some_expr.FooWithArgsBar(']) + + self.completions_contain('expr ', + ['static_cast', + 'reinterpret_cast', + 'dynamic_cast']) + + self.completions_contain('expr 1 + ', + ['static_cast', + 'reinterpret_cast', + 'dynamic_cast']) + + # Completion expr without spaces + # This is a bit awkward looking for the user, but that's how + # the completion API works at the moment. + self.completions_contain('expr 1+', + ['1+some_expr', "1+static_cast"]) + + # Test with spaces + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr. FooNoArgs', + 'expr some_expr. FooNoArgsBar()') + self.complete_exactly('expr some_expr . FooNoArgs', + 'expr some_expr . FooNoArgsBar()') + self.complete_exactly('expr Expr :: StaticMemberMethod', + 'expr Expr :: StaticMemberMethodBar()') + self.complete_exactly('expr Expr ::StaticMemberMethod', + 'expr Expr ::StaticMemberMethodBar()') + self.complete_exactly('expr Expr:: StaticMemberMethod', + 'expr Expr:: StaticMemberMethodBar()') + + # Test that string literals don't break our parsing logic. + self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst', + 'expr const char *cstr = "some_e"; char c = *cstr') + self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst', + 'expr const char *cstr = "some_e" ; char c = *cstr') + # Requesting completions inside an incomplete string doesn't provide any + # completions. + self.complete_exactly('expr const char *cstr = "some_e', + 'expr const char *cstr = "some_e') + + # Completing inside double dash should do nothing + self.assume_no_completions('expr -i0 -- some_expr.', 10) + self.assume_no_completions('expr -i0 -- some_expr.', 11) + + # Test with expr arguments + self.complete_exactly('expr -i0 -- some_expr .FooNoArgs', + 'expr -i0 -- some_expr .FooNoArgsBar()') + self.complete_exactly('expr -i0 -- some_expr .FooNoArgs', + 'expr -i0 -- some_expr .FooNoArgsBar()') + + # Addrof and deref + self.complete_exactly('expr (*(&some_expr)).FooNoArgs', + 'expr (*(&some_expr)).FooNoArgsBar()') + self.complete_exactly('expr (*(&some_expr)) .FooNoArgs', + 'expr (*(&some_expr)) .FooNoArgsBar()') + self.complete_exactly('expr (* (&some_expr)) .FooNoArgs', + 'expr (* (&some_expr)) .FooNoArgsBar()') + self.complete_exactly('expr (* (& some_expr)) .FooNoArgs', + 'expr (* (& some_expr)) .FooNoArgsBar()') + + # Addrof and deref (part 2) + self.complete_exactly('expr (&some_expr)->FooNoArgs', + 'expr (&some_expr)->FooNoArgsBar()') + self.complete_exactly('expr (&some_expr) ->FooNoArgs', + 'expr (&some_expr) ->FooNoArgsBar()') + self.complete_exactly('expr (&some_expr) -> FooNoArgs', + 'expr (&some_expr) -> FooNoArgsBar()') + self.complete_exactly('expr (&some_expr)-> FooNoArgs', + 'expr (&some_expr)-> FooNoArgsBar()') + + # Builtin arg + self.complete_exactly('expr static_ca', + 'expr static_cast') + + # From other files + self.complete_exactly('expr fwd_decl_ptr->Hidden', + 'expr fwd_decl_ptr->HiddenMember') + + + # Types + self.complete_exactly('expr LongClassNa', + 'expr LongClassName') + self.complete_exactly('expr LongNamespaceName::NestedCla', + 'expr LongNamespaceName::NestedClass') + + # Namespaces + self.complete_exactly('expr LongNamespaceNa', + 'expr LongNamespaceName::') + + # Multiple arguments + self.complete_exactly('expr &some_expr + &some_e', + 'expr &some_expr + &some_expr') + self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName', + 'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals') + self.complete_exactly('expr SomeIntVar + SomeIntV', + 'expr SomeIntVar + SomeIntVar') + + # Multiple statements + self.complete_exactly('expr long LocalVariable = 0; LocalVaria', + 'expr long LocalVariable = 0; LocalVariable') + + # Custom Decls + self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS', + 'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide') + self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem', + 'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName') + + # Completing function call arguments + self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp', + 'expr some_expr.FooWithArgsBar(some_expr') + self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV', + 'expr some_expr.FooWithArgsBar(SomeIntVar') + self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa', + 'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar') + + # Function return values + self.complete_exactly('expr some_expr.Self().FooNoArgs', + 'expr some_expr.Self().FooNoArgsBar()') + self.complete_exactly('expr some_expr.Self() .FooNoArgs', + 'expr some_expr.Self() .FooNoArgsBar()') + self.complete_exactly('expr some_expr.Self(). FooNoArgs', + 'expr some_expr.Self(). FooNoArgsBar()') + + def test_expr_completion_with_descriptions(self): + self.build() + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + + self.check_completion_with_desc("expr ", [ + # VarDecls have their type as description. + ["some_expr", "Expr &"], + # builtin types have no description. + ["int", ""], + ["float", ""] + ]) + self.check_completion_with_desc("expr some_expr.", [ + # Functions have their signature as description. + ["some_expr.Self()", "Expr &Self()"], + ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"], + ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"], + ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"], + ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"], + ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"], + ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"], + ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"], + ["some_expr.~Expr()", "inline ~Expr()"], + # FieldDecls have their type as description. + ["some_expr.MemberVariableBar", "int"], + ]) + + def assume_no_completions(self, str_input, cursor_pos = None): + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + if cursor_pos is None: + cursor_pos = len(str_input) + num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings) + + available_completions = [] + for m in match_strings: + available_completions.append(m) + + self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions)) + + def completions_contain(self, str_input, items): + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) + common_match = match_strings.GetStringAtIndex(0) + + for item in items: + found = False + for m in match_strings: + if m == item: + found = True + if not found: + # Transform match_strings to a python list with strings + available_completions = [] + for m in match_strings: + available_completions.append(m) + self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions)) diff --git a/packages/Python/lldbsuite/test/expression_command/completion/main.cpp b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp new file mode 100644 index 000000000000..908bebbebff5 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp @@ -0,0 +1,35 @@ +namespace LongNamespaceName { class NestedClass { long m; }; } + +// Defined in other.cpp, we only have a forward declaration here. +struct ForwardDecl; +extern ForwardDecl fwd_decl; + +class LongClassName { long i ; }; + +class Expr { +public: + int FooNoArgsBar() { return 1; } + int FooWithArgsBar(int i) { return i; } + int FooWithMultipleArgsBar(int i, int j) { return i + j; } + int FooUnderscoreBar_() { return 4; } + int FooNumbersBar1() { return 8; } + int MemberVariableBar = 0; + Expr &Self() { return *this; } + static int StaticMemberMethodBar() { return 82; } +}; + +int main() +{ + LongClassName a; + LongNamespaceName::NestedClass NestedFoo; + long SomeLongVarNameWithCapitals = 44; + int SomeIntVar = 33; + Expr some_expr; + some_expr.FooNoArgsBar(); + some_expr.FooWithArgsBar(1); + some_expr.FooUnderscoreBar_(); + some_expr.FooNumbersBar1(); + Expr::StaticMemberMethodBar(); + ForwardDecl *fwd_decl_ptr = &fwd_decl; + return 0; // Break here +} diff --git a/packages/Python/lldbsuite/test/expression_command/completion/other.cpp b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp new file mode 100644 index 000000000000..1f8a488639b9 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp @@ -0,0 +1,4 @@ +struct ForwardDecl { + long HiddenMemberName; +}; +ForwardDecl fwd_decl; diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile new file mode 100644 index 000000000000..50d4ab65a6ec --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py new file mode 100644 index 000000000000..05c67902a3ab --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py @@ -0,0 +1,90 @@ +""" +Test that --allow-jit=false does disallow JITting: +""" + +from __future__ import print_function + + +import os +import time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + +class TestAllowJIT(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def test_allow_jit_expr_command(self): + """Test the --allow-jit command line flag""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.expr_cmd_test() + + def test_allow_jit_options(self): + """Test the SetAllowJIT SBExpressionOption setting""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.expr_options_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def expr_cmd_test(self): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + + # First make sure we can call the function with + interp = self.dbg.GetCommandInterpreter() + self.expect("expr --allow-jit 1 -- call_me(10)", + substrs = ["(int) $", "= 18"]) + # Now make sure it fails with the "can't IR interpret message" if allow-jit is false: + self.expect("expr --allow-jit 0 -- call_me(10)", + error=True, + substrs = ["Can't run the expression locally"]) + + def expr_options_test(self): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + + # First make sure we can call the function with the default option set. + options = lldb.SBExpressionOptions() + # Check that the default is to allow JIT: + self.assertEqual(options.GetAllowJIT(), True, "Default is true") + + # Now use the options: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Success(), "expression succeeded") + self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + + # Now disallow JIT and make sure it fails: + options.SetAllowJIT(False) + # Check that we got the right value: + self.assertEqual(options.GetAllowJIT(), False, "Got False after setting to False") + + # Again use it and ensure we fail: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Fail(), "expression failed with no JIT") + self.assertTrue("Can't run the expression locally" in result.GetError().GetCString(), "Got right error") + + # Finally set the allow JIT value back to true and make sure that works: + options.SetAllowJIT(True) + self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly") + + # And again, make sure this works: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Success(), "expression succeeded") + self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c new file mode 100644 index 000000000000..ebd8ae11a73a --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int +call_me(int input) +{ + return printf("I was called: %d.\n", input); +} + +int +main() +{ + int test_var = 10; + printf ("Set a breakpoint here: %d.\n", test_var); + return call_me(100); +} diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py index f14b02bbd7c4..ee5c4a0ee1df 100644 --- a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py +++ b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py @@ -57,14 +57,21 @@ class ExprFormattersTestCase(TestBase): self.runCmd("frame variable foo1.b --show-types") self.runCmd("frame variable foo1.b.b_ref --show-types") - self.expect( - "expression --show-types -- *(new foo(47))", - substrs=[ - '(int) a = 47', - '(bar) b = {', - '(int) i = 94', - '(baz) b = {', - '(int) k = 99']) + self.filecheck("expression --show-types -- *(new foo(47))", __file__, + '-check-prefix=EXPR-TYPES-NEW-FOO') + # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) a = 47 + # EXPR-TYPES-NEW-FOO-NEXT: (int *) a_ptr = 0x + # EXPR-TYPES-NEW-FOO-NEXT: (bar) b = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) i = 94 + # EXPR-TYPES-NEW-FOO-NEXT: (int *) i_ptr = 0x + # EXPR-TYPES-NEW-FOO-NEXT: (baz) b = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) h = 97 + # EXPR-TYPES-NEW-FOO-NEXT: (int) k = 99 + # EXPR-TYPES-NEW-FOO-NEXT: } + # EXPR-TYPES-NEW-FOO-NEXT: (baz &) b_ref = 0x + # EXPR-TYPES-NEW-FOO-NEXT: } + # EXPR-TYPES-NEW-FOO-NEXT: } self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") @@ -80,68 +87,49 @@ class ExprFormattersTestCase(TestBase): self.expect("expression foo1.a_ptr", substrs=['(int *) $', '= 0x', ' -> 13']) - self.expect( - "expression foo1", - substrs=[ - '(foo) $', - ' a = 12', - 'a_ptr = ', - ' -> 13', - 'i = 24', - 'i_ptr = ', - ' -> 25']) - - self.expect( - "expression --ptr-depth=1 -- new foo(47)", - substrs=[ - '(foo *) $', - 'a = 47', - 'a_ptr = ', - ' -> 48', - 'i = 94', - 'i_ptr = ', - ' -> 95']) - - self.expect( - "expression foo2", - substrs=[ - '(foo) $', - 'a = 121', - 'a_ptr = ', - ' -> 122', - 'i = 242', - 'i_ptr = ', - ' -> 243']) + self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1') + # EXPR-FOO1: (foo) $ + # EXPR-FOO1-SAME: a = 12 + # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13 + # EXPR-FOO1-SAME: i = 24 + # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25 + # EXPR-FOO1-SAME: b_ref = {{[0-9]+}} + # EXPR-FOO1-SAME: h = 27 + # EXPR-FOO1-SAME: k = 29 + + self.filecheck("expression --ptr-depth=1 -- new foo(47)", __file__, + '-check-prefix=EXPR-PTR-DEPTH1') + # EXPR-PTR-DEPTH1: (foo *) $ + # EXPR-PTR-DEPTH1-SAME: a = 47 + # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48 + # EXPR-PTR-DEPTH1-SAME: i = 94 + # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95 + + self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2') + # EXPR-FOO2: (foo) $ + # EXPR-FOO2-SAME: a = 121 + # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 + # EXPR-FOO2-SAME: i = 242 + # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 + # EXPR-FOO2-SAME: h = 245 + # EXPR-FOO2-SAME: k = 247 object_name = self.res.GetOutput() object_name = object_name[7:] object_name = object_name[0:object_name.find(' =')] - self.expect( - "frame variable foo2", - substrs=[ - '(foo)', - 'foo2', - 'a = 121', - 'a_ptr = ', - ' -> 122', - 'i = 242', - 'i_ptr = ', - ' -> 243']) - - self.expect( - "expression $" + - object_name, - substrs=[ - '(foo) $', - 'a = 121', - 'a_ptr = ', - ' -> 122', - 'i = 242', - 'i_ptr = ', - ' -> 243', - 'h = 245', - 'k = 247']) + self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2') + # VAR-FOO2: (foo) foo2 + # VAR-FOO2-SAME: a = 121 + # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 + # VAR-FOO2-SAME: i = 242 + # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 + # VAR-FOO2-SAME: h = 245 + # VAR-FOO2-SAME: k = 247 + + # The object is the same as foo2, so use the EXPR-FOO2 checks. + self.filecheck("expression $" + object_name, __file__, + '-check-prefix=EXPR-FOO2') self.runCmd("type summary delete foo") self.runCmd( diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp index 4c3b180f3709..1b8ce48041f9 100644 --- a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp +++ b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp @@ -45,4 +45,4 @@ int main(int argc, char** argv) return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py b/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py deleted file mode 100644 index 7f639a462201..000000000000 --- a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Test multiline expressions.""" - -from __future__ import print_function - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class MultilineExpressionsTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - NO_DEBUG_INFO_TESTCASE = True - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line number to break on inside main.cpp. - self.line = line_number('main.c', 'break') - - @skipIfRemote - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_with_run_commands(self): - """Test that multiline expressions work correctly""" - self.build() - import pexpect - exe = self.getBuildArtifact("a.out") - prompt = "(lldb) " - - # So that the child gets torn down after the test. - self.child = pexpect.spawn( - '%s %s %s' % - (lldbtest_config.lldbExec, self.lldbOption, exe)) - child = self.child - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - # Set the breakpoint, run the inferior, when it breaks, issue print on - # the various convenience variables. - child.expect_exact(prompt) - child.sendline('breakpoint set -f main.c -l %d' % self.line) - child.expect_exact(prompt) - child.sendline('run') - child.expect_exact("stop reason = breakpoint 1.1") - child.expect_exact(prompt) - child.sendline('expr') - child.expect_exact('1:') - - child.sendline('2+') - child.expect_exact('2:') - - child.sendline('3') - child.expect_exact('3:') - - child.sendline('') - child.expect_exact(prompt) - self.expect(child.before, exe=False, - patterns=['= 5']) - - @skipIfRemote - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_empty_list(self): - """Test printing an empty list of expressions""" - import pexpect - prompt = "(lldb) " - - # So that the child gets torn down after the test - self.child = pexpect.spawn( - "%s %s" % - (lldbtest_config.lldbExec, self.lldbOption)) - child = self.child - - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - # We expect a prompt, then send "print" to start a list of expressions, - # then an empty line. We expect a prompt back. - child.expect_exact(prompt) - child.sendline("print") - child.expect_exact('1:') - child.sendline("") - child.expect_exact(prompt) diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/main.c b/packages/Python/lldbsuite/test/expression_command/multiline/main.c deleted file mode 100644 index da16b1e7846f..000000000000 --- a/packages/Python/lldbsuite/test/expression_command/multiline/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(int argc, char const *argv[]) { - printf("Hello world.\n"); // break here - return 0; -} diff --git a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py index 1dbafc36a82a..13bc3b7ce2ac 100644 --- a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py +++ b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py @@ -14,6 +14,7 @@ import os import time import lldb import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -63,3 +64,30 @@ class ExprOptionsTestCase(TestBase): val = frame.EvaluateExpression('foo != nullptr', options) self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success()) + + @skipIfDarwin + def test_expr_options_lang(self): + """These expression language options should work as expected.""" + self.build() + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, '// breakpoint_in_main', self.main_source_spec) + + frame = thread.GetFrameAtIndex(0) + options = lldb.SBExpressionOptions() + + # Make sure we can retrieve `id` variable if language is set to C++11: + options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) + val = frame.EvaluateExpression('id == 0', options) + self.assertTrue(val.IsValid()) + self.assertTrue(val.GetError().Success()) + self.DebugSBValue(val) + + # Make sure we can't retrieve `id` variable if language is set to ObjC: + options.SetLanguage(lldb.eLanguageTypeObjC) + val = frame.EvaluateExpression('id == 0', options) + self.assertTrue(val.IsValid()) + self.assertFalse(val.GetError().Success()) diff --git a/packages/Python/lldbsuite/test/expression_command/options/main.cpp b/packages/Python/lldbsuite/test/expression_command/options/main.cpp index ecd9a90f6626..0d30c79bd229 100644 --- a/packages/Python/lldbsuite/test/expression_command/options/main.cpp +++ b/packages/Python/lldbsuite/test/expression_command/options/main.cpp @@ -1,11 +1,13 @@ extern "C" int foo(void); static int static_value = 0; +static int id = 1234; int bar() { static_value++; - return static_value; + id++; + return static_value + id; } int main (int argc, char const *argv[]) diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py index f4ee1b0fb625..8630d6f41b34 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py @@ -17,7 +17,6 @@ class NestedPersistentTypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_persistent_types(self): """Test that nested persistent types work.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py index f56cb11a80d8..403d24246a9d 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py @@ -17,7 +17,6 @@ class PersistenttypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_persistent_types(self): """Test that lldb persistent types works correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py index dd3d06fd672f..6d019c7415fc 100644 --- a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py +++ b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py @@ -16,7 +16,6 @@ class ExprBug35310(TestBase): self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_issue35310(self): """Test invoking functions with non-standard linkage names. diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile new file mode 100644 index 000000000000..83b24da17b4d --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py new file mode 100644 index 000000000000..028047fc46bf --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py @@ -0,0 +1,44 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ScopedEnumType(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Set break point at this line.', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + self.expect("expr f == Foo::FooBar", + substrs=['(bool) $0 = true']) + + value = frame.EvaluateExpression("f == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsUnsigned(), 1) + + value = frame.EvaluateExpression("b == BarBar") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsUnsigned(), 1) + + ## b is not a Foo + value = frame.EvaluateExpression("b == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + ## integral is not implicitly convertible to a scoped enum + value = frame.EvaluateExpression("1 == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp new file mode 100644 index 000000000000..b0d67d23dc5e --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp @@ -0,0 +1,16 @@ +enum class Foo { + FooBar = 42 +}; + +enum Bar { + BarBar = 3, + BarBarBar = 42 +}; + +int main(int argc, const char **argv) { + Foo f = Foo::FooBar; + Bar b = BarBar; + bool b1 = f == Foo::FooBar; + bool b2 = b == BarBar; + return 0; // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py index c44cb6fc39da..dc8ee77fd6fb 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py @@ -18,7 +18,6 @@ class Radar9531204TestCase(TestBase): mydir = TestBase.compute_mydir(__file__) # rdar://problem/9531204 - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands(self): """The evaluating printf(...) after break stop and then up a stack frame.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py index dfef8735071b..d18720ccf3f1 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py @@ -24,7 +24,6 @@ class Radar9673644TestCase(TestBase): self.main_source = "main.c" self.line = line_number(self.main_source, '// Set breakpoint here.') - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands(self): """The following expression commands should just work.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile new file mode 100644 index 000000000000..f5a47fcc46cc --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py new file mode 100644 index 000000000000..c8308c16011e --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c new file mode 100644 index 000000000000..156dbf04a1b7 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c @@ -0,0 +1,8 @@ +int main(void) +{ + __int128_t n = 1; + n = n + n; + return n; //%self.expect("p n", substrs=['(__int128_t) $0 = 2']) + //%self.expect("p n + 6", substrs=['(__int128) $1 = 8']) + //%self.expect("p n + n", substrs=['(__int128) $2 = 4']) +} diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py index 3af7d808e128..deae7feb3ac1 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py @@ -102,7 +102,6 @@ class BasicExprCommandsTestCase(TestBase): # (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out" @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_evaluate_expression_python(self): """Test SBFrame.EvaluateExpression() API for evaluating an expression.""" self.build() @@ -203,7 +202,6 @@ class BasicExprCommandsTestCase(TestBase): # rdar://problem/8686536 # CommandInterpreter::HandleCommand is stripping \'s from input for # WantsRawCommand commands - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands_can_handle_quotes(self): """Throw some expression commands with quotes at lldb.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py index f5ec4f027866..88412e6b7c82 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py @@ -24,9 +24,6 @@ class ExprCommands2TestCase(TestBase): 'main.cpp', '// Please test many expressions while stopped at this line:') - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_more_expr_commands(self): """Test some more expression commands.""" self.build() @@ -60,9 +57,7 @@ class ExprCommands2TestCase(TestBase): # (int) $5 = 6 @skipIfLinux - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489") def test_expr_symbols(self): """Test symbols.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py index c942427a8e66..108de8867d50 100644 --- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py @@ -55,7 +55,6 @@ class UnwindFromExpressionTest(TestBase): @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"]) def test_unwind_expression(self): """Test unwinding from an expression.""" self.build_and_run_to_bkpt() diff --git a/packages/Python/lldbsuite/test/functionalities/asan/Makefile b/packages/Python/lldbsuite/test/functionalities/asan/Makefile index 26654a023ed1..dc8d682f831a 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/asan/Makefile @@ -1,6 +1,6 @@ LEVEL = ../../make C_SOURCES := main.c -CFLAGS_EXTRAS := -fsanitize=address -g +CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py index d7c511021863..ca070fa97dfa 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py +++ b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py @@ -37,6 +37,7 @@ class AsanTestReportDataCase(TestBase): self.line_free = line_number('main.c', '// free line') self.line_breakpoint = line_number('main.c', '// break line') self.line_crash = line_number('main.c', '// BOOM line') + self.col_crash = 16 def asan_tests(self): exe = self.getBuildArtifact("a.out") @@ -63,7 +64,7 @@ class AsanTestReportDataCase(TestBase): lldb.eStopReasonInstrumentation) self.expect("bt", "The backtrace should show the crashing line", - substrs=['main.c:%d' % self.line_crash]) + substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)]) self.expect( "thread info -s", diff --git a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py index ad87796766c3..754acade015a 100644 --- a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py +++ b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py @@ -21,7 +21,7 @@ class AttachResumeTestCase(TestBase): @skipIfRemote @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr19310') - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @skipIfWindows # llvm.org/pr24778, llvm.org/pr21753 def test_attach_continue_interrupt_detach(self): """Test attach/continue/interrupt/detach""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile new file mode 100644 index 000000000000..6c22351dc3b5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 -gcolumn-info + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py new file mode 100644 index 000000000000..07032cc0380c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py @@ -0,0 +1,48 @@ +""" +Test setting a breakpoint by line and column. +""" + +from __future__ import print_function + + +import os +import time +import re +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointByLineAndColumnTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLineAndColumn(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, + main_c, 20, 50) + self.expect("fr v did_call", substrs='1') + in_then = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 20) + in_then |= b_loc.GetColumn() == 50 + self.assertTrue(in_then) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLine(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, main_c, 20) + self.expect("fr v did_call", substrs='0') + in_condition = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 20) + in_condition |= b_loc.GetColumn() < 30 + self.assertTrue(in_condition) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c new file mode 100644 index 000000000000..921bc382023f --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c @@ -0,0 +1,23 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int square(int x) +{ + return x * x; +} + +int main (int argc, char const *argv[]) +{ + int did_call = 0; + + // Line 20. v Column 50. + if(square(argc+1) != 0) { did_call = 1; return square(argc); } + // ^ + return square(0); +} diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py index 7a2dc61b1b69..8143fa96433f 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -25,7 +25,6 @@ class BreakpointCommandTestCase(TestBase): self.build() self.breakpoint_command_sequence() - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") def test_script_parameters(self): """Test a sequence of breakpoint command add, list, and delete.""" self.build() @@ -45,7 +44,6 @@ class BreakpointCommandTestCase(TestBase): self.addTearDownHook( lambda: self.runCmd("settings clear auto-confirm")) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") def test_delete_all_breakpoints(self): """Test that deleting all breakpoints works.""" self.build() @@ -133,9 +131,9 @@ class BreakpointCommandTestCase(TestBase): patterns=[ "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % self.line, - "1.1: .+at main.c:%d, .+unresolved, hit count = 0" % + "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % self.line, - "2.1: .+at main.c:%d, .+unresolved, hit count = 0" % + "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % self.line]) self.expect("breakpoint command list 1", "Breakpoint 1 command ok", diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py index eb4bac7e6e66..e3bf4c27f31e 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py @@ -18,12 +18,14 @@ class BreakpointIgnoreCountTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + @skipIfWindows # This test will hang on windows llvm.org/pr21753 def test_with_run_command(self): """Exercise breakpoint ignore count with 'breakpoint set -i <count>'.""" self.build() self.breakpoint_ignore_count() @add_test_categories(['pyapi']) + @skipIfWindows # This test will hang on windows llvm.org/pr21753 def test_with_python_api(self): """Use Python APIs to set breakpoint ignore count.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py index 16d5bc75473c..b8281e9c85bd 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py @@ -18,6 +18,8 @@ class TestMoveNearest(TestBase): # Find the line number to break inside main(). self.line1 = line_number('foo.h', '// !BR1') self.line2 = line_number('foo.h', '// !BR2') + self.line_between = line_number('main.cpp', "// BR_Between") + print("BR_Between found at", self.line_between) self.line_main = line_number('main.cpp', '// !BR_main') def test(self): @@ -61,3 +63,7 @@ class TestMoveNearest(TestBase): # "return .." lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', self.line_main+2, extra_options="-m 1") + + # Make sure we don't put move the breakpoint if it is set between two functions: + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_between, extra_options="-m 1", num_expected_locations=0) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp index c9295a5c7d3c..76a22a5420fe 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp @@ -1,7 +1,7 @@ #include "foo.h" int call_foo2() { return foo2(); } - +// BR_Between int main() // !BR_main { diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile new file mode 100644 index 000000000000..7934cd5db427 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py new file mode 100644 index 000000000000..cda15fee84b8 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py @@ -0,0 +1,106 @@ +""" +Test require hardware breakpoints. +""" + +from __future__ import print_function + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointLocationsTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoint(self): + """Test regular breakpoints when hardware breakpoints are required.""" + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + breakpoint = target.BreakpointCreateByLocation("main.c", 1) + self.assertTrue(breakpoint.IsHardware()) + + @skipIfWindows + def test_step_range(self): + """Test stepping when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure we fail in the interpreter. + self.expect("thread step-in") + self.expect("thread step-in", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepInto('', 4, error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + def test_step_out(self): + """Test stepping out when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure this fails in the command interpreter. + self.expect("thread step-out", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepOut(error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + def test_step_over(self): + """Test stepping over when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Step over doesn't fail immediately but fails later on. + self.expect("thread step-over") + self.expect( + "process status", + substrs=[ + 'step over failed', + 'Could not create hardware breakpoint for thread plan' + ]) + + @skipIfWindows + def test_step_until(self): + """Test stepping until when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + self.expect("thread until 5", error=True) + + # Ensure we fail when stepping through the API. + error = thread.StepOverUntil(lldb.SBFrame(), lldb.SBFileSpec(), 5) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c new file mode 100644 index 000000000000..7d49a57d4c7b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c @@ -0,0 +1,9 @@ +int break_on_me() { + int i = 10; + i++; + return i; +} + +int main() { + return break_on_me(); +} diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile new file mode 100644 index 000000000000..6067ee45e984 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py new file mode 100644 index 000000000000..0eb9033e754b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -0,0 +1,199 @@ +""" +Test setting breakpoints using a scripted resolver +""" + +from __future__ import print_function + + +import os +import time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class TestScriptedResolver(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_scripted_resolver(self): + """Use a scripted resolver to set a by symbol name breakpoint""" + self.build() + self.do_test() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_search_depths(self): + """ Make sure we are called at the right depths depending on what we return + from __get_depth__""" + self.build() + self.do_test_depths() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_command_line(self): + """ Make sure we are called at the right depths depending on what we return + from __get_depth__""" + self.build() + self.do_test_cli() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def make_target_and_import(self): + target = lldbutil.run_to_breakpoint_make_target(self) + interp = self.dbg.GetCommandInterpreter() + error = lldb.SBError() + + script_name = os.path.join(self.getSourceDir(), "resolver.py") + source_name = os.path.join(self.getSourceDir(), "main.c") + + command = "command script import " + script_name + result = lldb.SBCommandReturnObject() + interp.HandleCommand(command, result) + self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) + return target + + def make_extra_args(self): + json_string = '{"symbol":"break_on_me", "test1": "value1"}' + json_stream = lldb.SBStream() + json_stream.Print(json_string) + extra_args = lldb.SBStructuredData() + error = extra_args.SetFromJSON(json_stream) + self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) + return extra_args + + def do_test(self): + """This reads in a python file and sets a breakpoint using it.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + + # Make breakpoints with this resolver using different filters, first ones that will take: + right = [] + # one with no file or module spec - this one should fire: + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the right source file and no module - should also fire: + file_list.Append(lldb.SBFileSpec("main.c")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + # Make sure the help text shows up in the "break list" output: + self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") + + # one with the right source file and right module - should also fire: + module_list.Append(lldb.SBFileSpec("a.out")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # And one with no source file but the right module: + file_list.Clear() + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Make sure these all got locations: + for i in range (0, len(right)): + self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) + + # Now some ones that won't take: + + module_list.Clear() + file_list.Clear() + wrong = [] + + # one with the wrong module - should not fire: + module_list.Append(lldb.SBFileSpec("noSuchModule")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the wrong file - also should not fire: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Now make sure the CU level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # Now make sure the Function level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # Make sure these didn't get locations: + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) + + # Now run to main and ensure we hit the breakpoints we should have: + + lldbutil.run_to_breakpoint_do_run(self, target, right[0]) + + # Test the hit counts: + for i in range(0, len(right)): + self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) + + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i)) + + def do_test_depths(self): + """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw + compile unit and 2 if we only saw modules. If the search depth is module, you get passed just + the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use + this to test that our callback gets called at the right depth.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec("a.out")) + + # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule: + bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for modules, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for compile units, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["1"], msg="Was passed compile units") + + # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that searches at function depth: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") + self.expect("script print resolver.Resolver.got_files", substrs=["3"], msg="Was only passed modules") + self.expect("script print resolver.Resolver.func_list", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions") + + def do_test_cli(self): + target = self.make_target_and_import() + + lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me") diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c new file mode 100644 index 000000000000..b91ccfc1b43e --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +int +test_func() +{ + return printf("I am a test function."); +} + +void +break_on_me() +{ + printf("I was called.\n"); +} + +int +main() +{ + break_on_me(); + test_func(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py new file mode 100644 index 000000000000..61f5f2df20ac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -0,0 +1,54 @@ +import lldb + +class Resolver: + got_files = 0 + func_list = [] + + def __init__(self, bkpt, extra_args, dict): + self.bkpt = bkpt + self.extra_args = extra_args + Resolver.func_list = [] + Resolver.got_files = 0 + + def __callback__(self, sym_ctx): + sym_name = "not_a_real_function_name" + sym_item = self.extra_args.GetValueForKey("symbol") + if sym_item.IsValid(): + sym_name = sym_item.GetStringValue(1000) + + if sym_ctx.compile_unit.IsValid(): + Resolver.got_files = 1 + else: + Resolver.got_files = 2 + + if sym_ctx.function.IsValid(): + Resolver.got_files = 3 + func_name = sym_ctx.function.GetName() + Resolver.func_list.append(func_name) + if sym_name == func_name: + self.bkpt.AddLocation(sym_ctx.function.GetStartAddress()) + return + + if sym_ctx.module.IsValid(): + sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode) + if sym.IsValid(): + self.bkpt.AddLocation(sym.GetStartAddress()) + + def get_short_help(self): + return "I am a python breakpoint resolver" + +class ResolverModuleDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthModule + +class ResolverCUDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthCompUnit + +class ResolverFuncDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthFunction + +class ResolverBadDepth(Resolver): + def __get_depth__ (self): + return lldb.kLastSearchDepthKind + 1 diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py index c615278e8d48..943998a421be 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py @@ -180,7 +180,8 @@ class BreakpointSerialization(TestBase): # actually have locations. source_bps = lldb.SBBreakpointList(self.orig_target) - bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) bkpt.SetEnabled(False) bkpt.SetOneShot(True) bkpt.SetThreadID(10) @@ -226,7 +227,8 @@ class BreakpointSerialization(TestBase): all_bps = lldb.SBBreakpointList(self.orig_target) source_bps = lldb.SBBreakpointList(self.orig_target) - bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) bkpt.SetEnabled(False) bkpt.SetOneShot(True) bkpt.SetThreadID(10) @@ -260,7 +262,8 @@ class BreakpointSerialization(TestBase): self.check_equivalence(all_bps) def do_check_names(self): - bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666) + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) good_bkpt_name = "GoodBreakpoint" write_bps = lldb.SBBreakpointList(self.orig_target) bkpt.AddName(good_bkpt_name) diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py index c6ad75f014ee..c1595cf25515 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py @@ -28,6 +28,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest): oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") + @skipIfDarwin def test_command_script_immediate_output_console(self): """Test that LLDB correctly allows scripted commands to set immediate output to the console.""" self.launch(timeout=10) @@ -50,6 +51,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest): oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") + @skipIfDarwin def test_command_script_immediate_output_file(self): """Test that LLDB correctly allows scripted commands to set immediate output to a file.""" self.launch(timeout=10) diff --git a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py index 5d4fcf64511b..c073425a93fb 100644 --- a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py +++ b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -43,7 +43,6 @@ class CommandLineCompletionTestCase(TestBase): self.build() self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) - self.dbg.CreateTarget(self.getBuildArtifact("a.out")) (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) @@ -177,8 +176,8 @@ class CommandLineCompletionTestCase(TestBase): @skipIfFreeBSD # timing out on the FreeBSD buildbot def test_settings_s_dash(self): - """Test that 'settings set -' completes to 'settings set -g'.""" - self.complete_from_to('settings set -', 'settings set -g') + """Test that 'settings set --g' completes to 'settings set --global'.""" + self.complete_from_to('settings set --g', 'settings set --global') @skipIfFreeBSD # timing out on the FreeBSD buildbot def test_settings_clear_th(self): @@ -275,6 +274,22 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to("watchpoint set variable foo --watch w", "watchpoint set variable foo --watch write") self.complete_from_to('watchpoint set variable foo -w read_', 'watchpoint set variable foo -w read_write') + def test_completion_description_commands(self): + """Test descriptions of top-level command completions""" + self.check_completion_with_desc("", [ + ["command", "Commands for managing custom LLDB commands."], + ["bugreport", "Commands for creating domain-specific bug reports."] + ]) + + self.check_completion_with_desc("pl", [ + ["platform", "Commands to manage and create platforms."], + ["plugin", "Commands for managing LLDB plugins."] + ]) + + # Just check that this doesn't crash. + self.check_completion_with_desc("comman", []) + self.check_completion_with_desc("non-existent-command", []) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489") def test_symbol_name(self): self.build() @@ -282,39 +297,3 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to('breakpoint set -n Fo', 'breakpoint set -n Foo::Bar(int,\\ int)', turn_off_re_match=True) - - def complete_from_to(self, str_input, patterns, turn_off_re_match=False): - """Test that the completion mechanism completes str_input to patterns, - where patterns could be a pattern-string or a list of pattern-strings""" - # Patterns should not be None in order to proceed. - self.assertFalse(patterns is None) - # And should be either a string or list of strings. Check for list type - # below, if not, make a list out of the singleton string. If patterns - # is not a string or not a list of strings, there'll be runtime errors - # later on. - if not isinstance(patterns, list): - patterns = [patterns] - - interp = self.dbg.GetCommandInterpreter() - match_strings = lldb.SBStringList() - num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) - common_match = match_strings.GetStringAtIndex(0) - if num_matches == 0: - compare_string = str_input - else: - if common_match != None and len(common_match) > 0: - compare_string = str_input + common_match - else: - compare_string = "" - for idx in range(1, num_matches+1): - compare_string += match_strings.GetStringAtIndex(idx) + "\n" - - for p in patterns: - if turn_off_re_match: - self.expect( - compare_string, msg=COMPLETION_MSG( - str_input, p, match_strings), exe=False, substrs=[p]) - else: - self.expect( - compare_string, msg=COMPLETION_MSG( - str_input, p, match_strings), exe=False, patterns=[p]) diff --git a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py index 904fb4c90372..7b123950c23d 100644 --- a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py @@ -34,9 +34,6 @@ class ConditionalBreakTestCase(TestBase): self.build() self.simulate_conditional_break_by_user() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr26265: args in frames other than #0 are not evaluated correctly") def do_conditional_break(self): """Exercise some thread and frame APIs to break if c() is called by a().""" exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py index 9749061f42d5..4b9de961724b 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -23,9 +23,6 @@ class CppDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24462: Data formatters have problems on Windows") @skipIf(debug_info="gmodules", bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") def test_with_run_command(self): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp index aaccb6329acf..1c98f3db24c8 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp @@ -50,4 +50,4 @@ int main (int argc, const char * argv[]) int dummy = 1; return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp index 82ffb2c20d47..665c9fe75d1c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp @@ -54,4 +54,4 @@ int main() DeepData_2 data2; return 0; // Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py index 13b38cbfa702..54e9c346df31 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py @@ -17,9 +17,6 @@ class SmartArrayDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") def test_with_run_command(self): """Test data formatter commands.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py index 81a76cc65d63..e44ea61d120f 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py @@ -40,13 +40,17 @@ class LibCxxFunctionTestCase(TestBase): substrs=['stopped', 'stop reason = breakpoint']) - f1 = self.get_variable('f1') - f2 = self.get_variable('f2') + self.expect("frame variable f1", + substrs=['f1 = Function = foo(int, int)']) - if self.TraceOn(): - print(f1) - if self.TraceOn(): - print(f2) + self.expect("frame variable f2", + substrs=['f2 = Lambda in File main.cpp at Line 27']) - self.assertTrue(f1.GetValueAsUnsigned(0) != 0, 'f1 has a valid value') - self.assertTrue(f2.GetValueAsUnsigned(0) != 0, 'f2 has a valid value') + self.expect("frame variable f3", + substrs=['f3 = Lambda in File main.cpp at Line 31']) + + self.expect("frame variable f4", + substrs=['f4 = Function in File main.cpp at Line 17']) + + self.expect("frame variable f5", + substrs=['f5 = Function = Bar::add_num(int) const']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp index cfe689b29b01..541fdaca2afa 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp @@ -13,13 +13,28 @@ int foo(int x, int y) { return x + y - 1; } -int main () +struct Bar { + int operator()() { + return 66 ; + } + int add_num(int i) const { return i + 3 ; } +} ; + +int main (int argc, char *argv[]) { int acc = 42; std::function<int (int,int)> f1 = foo; std::function<int (int)> f2 = [acc,f1] (int x) -> int { return x+f1(acc,x); }; - return f1(acc,acc) + f2(acc); // Set break point at this line. -} + auto f = [](int x, int y) { return x + y; }; + auto g = [](int x, int y) { return x * y; } ; + std::function<int (int,int)> f3 = argc %2 ? f : g ; + + Bar bar1 ; + std::function<int ()> f4( bar1 ) ; + std::function<int (const Bar&, int)> f5 = &Bar::add_num; + + return f1(acc,acc) + f2(acc) + f3(acc+1,acc+2) + f4() + f5(bar1, 10); // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py index 90a7e119fb84..86248d1cac24 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py @@ -190,6 +190,7 @@ class LibcxxListDataFormatterTestCase(TestBase): self.runCmd("n") # This gets us past the printf self.runCmd("n") + self.runCmd("n") # check access-by-index self.expect("frame variable text_list[0]", diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp index 6247ca8b2412..da6eca985d20 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp @@ -74,4 +74,4 @@ int main() ss.clear(); thefoo_rw(1); // Set break point at this line. return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp index e8385994125d..27bdc0a57729 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp @@ -74,4 +74,4 @@ int main() ss.clear(); thefoo_rw(1); // Set break point at this line. return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile new file mode 100644 index 000000000000..19d6fc3e3c25 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include $(LEVEL)/Makefile.rules +CXXFLAGS += -std=c++17 -fno-exceptions diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py new file mode 100644 index 000000000000..7826305931da --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py @@ -0,0 +1,75 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibcxxOptionalDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libc++"]) + ## We are skipping clang version less that 5.0 since this test requires -std=c++17 + @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0']) + ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 + @skipIf(compiler="gcc", compiler_version=['<', '5.1']) + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + bkpt = self.target().FindBreakpointByID( + lldbutil.run_break_set_by_source_regexp( + self, "break here")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + self.runCmd( "frame variable has_optional" ) + + output = self.res.GetOutput() + + ## The variable has_optional tells us if the test program + ## detected we have a sufficient libc++ version to support optional + ## false means we do not and therefore should skip the test + if output.find("(bool) has_optional = false") != -1 : + self.skipTest( "Optional not supported" ) + + lldbutil.continue_to_breakpoint(self.process(), bkpt) + + self.expect("frame variable number_not_engaged", + substrs=['Has Value=false']) + + self.expect("frame variable number_engaged", + substrs=['Has Value=true', + 'Value = 42', + '}']) + + self.expect("frame var numbers", + substrs=['(optional_int_vect) numbers = Has Value=true {', + 'Value = size=4 {', + '[0] = 1', + '[1] = 2', + '[2] = 3', + '[3] = 4', + '}', + '}']) + + self.expect("frame var ostring", + substrs=['(optional_string) ostring = Has Value=true {', + 'Value = "hello"', + '}']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp new file mode 100644 index 000000000000..16bb98c61056 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp @@ -0,0 +1,42 @@ +#include <cstdio> +#include <string> +#include <vector> + +// If we have libc++ 4.0 or greater we should have <optional> +// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html +#if _LIBCPP_VERSION >= 4000 +#include <optional> +#define HAVE_OPTIONAL 1 +#else +#define HAVE_OPTIONAL 0 +#endif + + +int main() +{ + bool has_optional = HAVE_OPTIONAL ; + + printf( "%d\n", has_optional ) ; // break here + +#if HAVE_OPTIONAL == 1 + using int_vect = std::vector<int> ; + using optional_int = std::optional<int> ; + using optional_int_vect = std::optional<int_vect> ; + using optional_string = std::optional<std::string> ; + + optional_int number_not_engaged ; + optional_int number_engaged = 42 ; + + printf( "%d\n", *number_engaged) ; + + optional_int_vect numbers{{1,2,3,4}} ; + + printf( "%d %d\n", numbers.value()[0], numbers.value()[1] ) ; + + optional_string ostring = "hello" ; + + printf( "%s\n", ostring->c_str() ) ; +#endif + + return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile index 1f609a41d908..937b47ea06b0 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile @@ -4,4 +4,4 @@ CXX_SOURCES := main.cpp USE_LIBCPP := 1 include $(LEVEL)/Makefile.rules -CXXFLAGS += -O0 +CXXFLAGS += -std=c++11 -O0 diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py index 4574a044488c..63164f78e00e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -68,7 +68,9 @@ class LibcxxStringDataFormatterTestCase(TestBase): '(%s::string) q = "hello world"'%ns, '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, - '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns]) + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string) u16_string = u"ß水氶"'%ns, + '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns]) self.runCmd("n") @@ -98,4 +100,6 @@ class LibcxxStringDataFormatterTestCase(TestBase): '(%s::string) q = "hello world"'%ns, '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, - '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns]) + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string) u16_string = u"ß水氶"'%ns, + '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp index 9ca0da39cfc8..838a4c71be1a 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp @@ -10,6 +10,8 @@ int main() std::string TheVeryLongOne("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890someText1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); std::string IHaveEmbeddedZeros("a\0b\0c\0d",7); std::wstring IHaveEmbeddedZerosToo(L"hello world!\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監", 38); + std::u16string u16_string(u"ß水氶"); + std::u32string u32_string(U"🍄🍅🍆🍌"); S.assign(L"!!!!!"); // Set break point at this line. return 0; } diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile new file mode 100644 index 000000000000..a6ea665ef63c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 +include $(LEVEL)/Makefile.rules +CXXFLAGS += -std=c++17 diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py new file mode 100644 index 000000000000..e1f6961b465d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py @@ -0,0 +1,83 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class LibcxxVariantDataFormatterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libc++"]) + ## We are skipping clang version less that 5.0 since this test requires -std=c++17 + @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0']) + ## We are skipping gcc version less that 5.1 since this test requires -std=c++17 + @skipIf(compiler="gcc", compiler_version=['<', '5.1']) + ## std::get is unavailable for std::variant before macOS 10.14 + @skipIf(macos_version=["<", "10.14"]) + + def test_with_run_command(self): + """Test that that file and class static variables display correctly.""" + self.build() + + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.runCmd( "frame variable has_variant" ) + + output = self.res.GetOutput() + + ## The variable has_variant tells us if the test program + ## detected we have a sufficient libc++ version to support variant + ## false means we do not and therefore should skip the test + if output.find("(bool) has_variant = false") != -1 : + self.skipTest( "std::variant not supported" ) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v1", + substrs=['v1 = Active Type = int {', + 'Value = 12', + '}']) + + self.expect("frame variable v1_ref", + substrs=['v1_ref = Active Type = int : {', + 'Value = 12', + '}']) + + self.expect("frame variable v_v1", + substrs=['v_v1 = Active Type = std::__1::variant<int, double, char> {', + 'Value = Active Type = int {', + 'Value = 12', + '}', + '}']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v1", + substrs=['v1 = Active Type = double {', + 'Value = 2', + '}']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("frame variable v2", + substrs=['v2 = Active Type = double {', + 'Value = 2', + '}']) + + self.expect("frame variable v3", + substrs=['v3 = Active Type = char {', + 'Value = \'A\'', + '}']) + + self.expect("frame variable v_no_value", + substrs=['v_no_value = No Value']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp new file mode 100644 index 000000000000..c0bc4ae12c1a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp @@ -0,0 +1,60 @@ +#include <cstdio> +#include <string> +#include <vector> + +// If we have libc++ 4.0 or greater we should have <variant> +// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html +#if _LIBCPP_VERSION >= 4000 +#include <variant> +#define HAVE_VARIANT 1 +#else +#define HAVE_VARIANT 0 +#endif + +struct S { + operator int() { throw 42; } +} ; + + +int main() +{ + bool has_variant = HAVE_VARIANT ; + + printf( "%d\n", has_variant ) ; // break here + +#if HAVE_VARIANT == 1 + std::variant<int, double, char> v1; + std::variant<int, double, char> &v1_ref = v1; + std::variant<int, double, char> v2; + std::variant<int, double, char> v3; + std::variant<std::variant<int,double,char>> v_v1 ; + std::variant<int, double, char> v_no_value; + + v1 = 12; // v contains int + v_v1 = v1 ; + int i = std::get<int>(v1); + printf( "%d\n", i ); // break here + + v2 = 2.0 ; + double d = std::get<double>(v2) ; + printf( "%f\n", d ); + + v3 = 'A' ; + char c = std::get<char>(v3) ; + printf( "%d\n", c ); + + // Checking v1 above and here to make sure we done maintain the incorrect + // state when we change its value. + v1 = 2.0; + d = std::get<double>(v1) ; + printf( "%f\n", d ); // break here + + try { + v_no_value.emplace<0>(S()); + } catch( ... ) {} + + printf( "%zu\n", v_no_value.index() ) ; +#endif + + return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py index 237e27fe1f31..06d3cda61be2 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py @@ -51,8 +51,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase): substrs=['1234']) @add_test_categories(["libc++"]) - @skipIf(debug_info="gmodules", - bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() @@ -180,8 +178,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase): substrs=['vector has 0 items']) @add_test_categories(["libc++"]) - @skipIf(debug_info="gmodules", - bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048") def test_ref_and_ptr(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp index d7b046c5bff8..7ddffd19012e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp @@ -35,4 +35,4 @@ int main() svter svI = sv.begin(); return 0; // Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp index 568c35efe072..d5e5b212782d 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp @@ -52,4 +52,4 @@ int main() ss.clear();// Set break point at this line. return 0;// Set break point at this line. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp index 4a9b4fc7d0db..f6e56cf12456 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp @@ -9,4 +9,4 @@ int main() std::string Q("quite a long std::strin with lots of info inside it"); S.assign(L"!!!!!"); // Set break point at this line. return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py index 5d05418a8b49..f782a2a8baea 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py @@ -66,6 +66,7 @@ class StdUniquePtrDataFormatterTestCase(TestBase): @skipIfWindows # libstdcpp not ported to Windows @skipIfDarwin # doesn't compile on Darwin @skipIfwatchOS # libstdcpp not ported to watchos + @add_test_categories(["libstdcxx"]) def test_recursive_unique_ptr(self): # Tests that LLDB can handle when we have a loop in the unique_ptr # reference chain and that it correctly handles the different options diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py index 08768a61bd9d..138b32802951 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py @@ -24,9 +24,6 @@ class DataFormatterSynthValueTestCase(TestBase): self.line = line_number('main.cpp', 'break here') @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") def test_with_run_command(self): """Test using Python synthetic children provider to provide a value.""" self.build() @@ -107,7 +104,7 @@ class DataFormatterSynthValueTestCase(TestBase): # check that an aptly defined synthetic provider does not affect # one-lining self.expect( - "expression struct S { myInt theInt{12}; }; S()", + "expression struct Struct { myInt theInt{12}; }; Struct()", substrs=['(theInt = 12)']) # check that we can use a synthetic value in a summary diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp index fec7907e0031..90571b59f81e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp @@ -59,4 +59,4 @@ int main() 256*256*256*'D'); return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp index 649c1e09a6a5..5b43102c268c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp @@ -9,6 +9,11 @@ typedef int Foo; int main() { + // CHECK: (Foo [3]) array = { + // CHECK-NEXT: (Foo) [0] = 1 + // CHECK-NEXT: (Foo) [1] = 2 + // CHECK-NEXT: (Foo) [2] = 3 + // CHECK-NEXT: } Foo array[3] = {1,2,3}; - return 0; //% self.expect("frame variable array --show-types --", substrs = ['(Foo [3]) array = {','(Foo) [0] = 1','(Foo) [1] = 2','(Foo) [2] = 3']) + return 0; //% self.filecheck("frame variable array --show-types --", 'main.cpp') } diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py index d3c04afe91eb..670edad37f9e 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py @@ -14,7 +14,7 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -class PythonSynthDataFormatterTestCase(TestBase): +class DataFormatterVarScriptFormatting(TestBase): mydir = TestBase.compute_mydir(__file__) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp index 4dc94af3566c..e9a36f911964 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp @@ -5,4 +5,4 @@ int main() { something<int> x; something<void*> y; return 0; // Set breakpoint here. -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile index 8a7102e347af..8a7102e347af 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py new file mode 100644 index 000000000000..1eeaeeffa87b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py @@ -0,0 +1,31 @@ +""" +Test process attach/resume. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDeletedExecutable(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIfWindows # cannot delete a running executable + @expectedFailureAll(oslist=["linux"]) # determining the architecture of the process fails + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + + popen = self.spawnSubprocess(exe) + self.addTearDownHook(self.cleanupSubprocesses) + os.remove(exe) + + self.runCmd("process attach -p " + str(popen.pid)) + self.runCmd("kill") diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp new file mode 100644 index 000000000000..ad5d18732eac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp @@ -0,0 +1,9 @@ +#include <chrono> +#include <thread> + +int main(int argc, char const *argv[]) +{ + lldb_enable_attach(); + + std::this_thread::sleep_for(std::chrono::seconds(30)); +} diff --git a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py index 52f9daf6bd45..91b858b4665a 100644 --- a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py @@ -18,9 +18,6 @@ class DisassemblyTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) NO_DEBUG_INFO_TESTCASE = True - @expectedFailureAll( - oslist=["windows"], - bugnumber="function names print fully demangled instead of name-only") def test(self): self.build() target, _, _, bkpt = lldbutil.run_to_source_breakpoint(self, diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py deleted file mode 100644 index 0f130b3ecbab..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Test convenience variables when you drop in from lldb prompt into an embedded interpreter.""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class ConvenienceVariablesCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line number to break on inside main.cpp. - self.line = line_number('main.c', 'Hello world.') - - @skipIfFreeBSD # llvm.org/pr17228 - @skipIfRemote - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_with_run_commands(self): - """Test convenience variables lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame.""" - self.build() - import pexpect - exe = self.getBuildArtifact("a.out") - prompt = "(lldb) " - python_prompt = ">>> " - - # So that the child gets torn down after the test. - self.child = pexpect.spawn( - '%s %s %s' % - (lldbtest_config.lldbExec, self.lldbOption, exe)) - child = self.child - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - # Set the breakpoint, run the inferior, when it breaks, issue print on - # the various convenience variables. - child.expect_exact(prompt) - child.sendline('breakpoint set -f main.c -l %d' % self.line) - child.expect_exact(prompt) - child.sendline('run') - child.expect_exact("stop reason = breakpoint 1.1") - child.expect_exact(prompt) - child.sendline('script') - child.expect_exact(python_prompt) - - # Set a flag so that we know during teardown time, we need to exit the - # Python interpreter, then the lldb interpreter. - self.child_in_script_interpreter = True - - child.sendline('print(lldb.debugger)') - child.expect_exact(python_prompt) - self.expect(child.before, exe=False, - patterns=['Debugger \(instance: .*, id: \d\)']) - - child.sendline('print(lldb.target)') - child.expect_exact(python_prompt) - self.expect(child.before, exe=False, - substrs=['a.out']) - - child.sendline('print(lldb.process)') - child.expect_exact(python_prompt) - self.expect(child.before, exe=False, patterns=[ - 'SBProcess: pid = \d+, state = stopped, threads = \d, executable = a.out']) - - child.sendline('print(lldb.thread.GetStopDescription(100))') - child.expect_exact(python_prompt) - self.expect( - child.before, - exe=False, - patterns=[ - 'breakpoint 1\.1']) - - child.sendline('lldb.frame.GetLineEntry().GetLine()') - child.expect_exact(python_prompt) - line_number = "%d"%(self.line) - self.expect( - child.before, - exe=False, - substrs=[ - line_number]) - - child.sendline('lldb.frame.GetLineEntry().GetFileSpec().GetFilename()') - child.expect_exact(python_prompt) - line_number = "%d"%(self.line) - self.expect( - child.before, - exe=False, - substrs=[ - "main.c"]) - - child.sendline('lldb.frame.GetFunctionName()') - child.expect_exact(python_prompt) - line_number = "%d"%(self.line) - self.expect( - child.before, - exe=False, - substrs=[ - "main"]) diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c deleted file mode 100644 index 277aa54a4eea..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(int argc, char const *argv[]) { - printf("Hello world.\n"); - return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py index 8126a7ec750c..2cec254acc0c 100644 --- a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py +++ b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py @@ -31,12 +31,14 @@ class ExecTestCase(TestBase): @skipUnlessDarwin @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems + @skipIfSanitized # rdar://problem/43756823 def test_hitting_exec (self): self.do_test(False) @skipUnlessDarwin @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems + @skipIfSanitized # rdar://problem/43756823 def test_skipping_exec (self): self.do_test(True) @@ -61,6 +63,8 @@ class ExecTestCase(TestBase): None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) + if self.TraceOn(): + self.runCmd("settings show target.process.stop-on-exec", check=False) if skip_exec: self.dbg.HandleCommand("settings set target.process.stop-on-exec false") def cleanup(): @@ -94,6 +98,8 @@ class ExecTestCase(TestBase): process.Continue() if not skip_exec: + self.assertFalse(process.GetState() == lldb.eStateExited, + "Process should not have exited!") self.assertTrue(process.GetState() == lldb.eStateStopped, "Process should be stopped at __dyld_start") diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile index 0d70f2595019..0d70f2595019 100644 --- a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py new file mode 100644 index 000000000000..56abc19f4f30 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py @@ -0,0 +1,34 @@ +""" +Tests expressions evaluation when the breakpoint on module's entry is set. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ExprEntryBPTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_expr_entry_bp(self): + """Tests expressions evaluation when the breakpoint on module's entry is set.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) + + self.assertEqual(1, bkpt.GetNumLocations()) + entry = bkpt.GetLocationAtIndex(0).GetAddress().GetModule().GetObjectFileEntryPointAddress() + self.assertTrue(entry.IsValid(), "Can't get a module entry point") + + entry_bp = target.BreakpointCreateBySBAddress(entry) + self.assertTrue(entry_bp.IsValid(), "Can't set a breakpoint on the module entry point") + + result = target.EvaluateExpression("sum(7, 1)") + self.assertTrue(result.IsValid(), "Can't evaluate expression") + self.assertEqual(8, result.GetValueAsSigned()) + + def setUp(self): + TestBase.setUp(self) diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c new file mode 100644 index 000000000000..168fc9c8ccbf --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int sum(int x, int y) { + return x + y; +} + +int main() { + printf("Set a breakpoint here.\n"); + return sum(-1, 1); +} diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile new file mode 100644 index 000000000000..45f00b3e9861 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS += -g0 # No debug info. +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py new file mode 100644 index 000000000000..1162157bad57 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py @@ -0,0 +1,117 @@ +# encoding: utf-8 +""" +Test lldb's frame recognizers. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +import recognizer + +class FrameRecognizerTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessDarwin + def test_frame_recognizer_1(self): + self.build() + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py")) + + self.expect("frame recognizer list", + substrs=['no matching results found.']) + + self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") + + self.expect("frame recognizer list", + substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo']) + + self.runCmd("frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x") + + self.expect("frame recognizer list", + substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo', + '1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)' + ]) + + self.runCmd("frame recognizer delete 0") + + self.expect("frame recognizer list", + substrs=['1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)']) + + self.runCmd("frame recognizer clear") + + self.expect("frame recognizer list", + substrs=['no matching results found.']) + + self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo") + + lldbutil.run_break_set_by_symbol(self, "foo") + self.runCmd("r") + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.assertEqual(frame.GetSymbol().GetName(), "foo") + self.assertFalse(frame.GetLineEntry().IsValid()) + + self.expect("frame variable", + substrs=['(int) a = 42', '(int) b = 56']) + + # Recognized arguments don't show up by default... + variables = frame.GetVariables(lldb.SBVariablesOptions()) + self.assertEqual(variables.GetSize(), 0) + + # ...unless you set target.display-recognized-arguments to 1... + self.runCmd("settings set target.display-recognized-arguments 1") + variables = frame.GetVariables(lldb.SBVariablesOptions()) + self.assertEqual(variables.GetSize(), 2) + + # ...and you can reset it back to 0 to hide them again... + self.runCmd("settings set target.display-recognized-arguments 0") + variables = frame.GetVariables(lldb.SBVariablesOptions()) + self.assertEqual(variables.GetSize(), 0) + + # ... or explicitly ask for them with SetIncludeRecognizedArguments(True). + opts = lldb.SBVariablesOptions() + opts.SetIncludeRecognizedArguments(True) + variables = frame.GetVariables(opts) + + self.assertEqual(variables.GetSize(), 2) + self.assertEqual(variables.GetValueAtIndex(0).name, "a") + self.assertEqual(variables.GetValueAtIndex(0).signed, 42) + self.assertEqual(variables.GetValueAtIndex(1).name, "b") + self.assertEqual(variables.GetValueAtIndex(1).signed, 56) + + self.expect("frame recognizer info 0", + substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer']) + + self.expect("frame recognizer info 999", error=True, + substrs=['no frame with index 999']) + + self.expect("frame recognizer info 1", + substrs=['frame 1 not recognized by any recognizer']) + + # FIXME: The following doesn't work yet, but should be fixed. + """ + lldbutil.run_break_set_by_symbol(self, "bar") + self.runCmd("c") + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("frame variable -t", + substrs=['(int *) a = ']) + + self.expect("frame variable -t *a", + substrs=['*a = 78']) + """ diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m new file mode 100644 index 000000000000..51103ae038ac --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m @@ -0,0 +1,28 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +void foo(int a, int b) +{ + printf("%d %d\n", a, b); +} + +void bar(int *ptr) +{ + printf("%d\n", *ptr); +} + +int main (int argc, const char * argv[]) +{ + foo(42, 56); + int i = 78; + bar(&i); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py new file mode 100644 index 000000000000..a8a506745118 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py @@ -0,0 +1,21 @@ +# encoding: utf-8 + +import lldb + +class MyFrameRecognizer(object): + def get_recognized_arguments(self, frame): + if frame.name == "foo": + arg1 = frame.EvaluateExpression("$arg1").signed + arg2 = frame.EvaluateExpression("$arg2").signed + val1 = lldb.target.CreateValueFromExpression("a", "%d" % arg1) + val2 = lldb.target.CreateValueFromExpression("b", "%d" % arg2) + return [val1, val2] + elif frame.name == "bar": + arg1 = frame.EvaluateExpression("$arg1").signed + val1 = lldb.target.CreateValueFromExpression("a", "(int *)%d" % arg1) + return [val1] + return [] + +class MyOtherFrameRecognizer(object): + def get_recognized_arguments(self, frame): + return [] diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py new file mode 100644 index 000000000000..6e28d5b54052 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py @@ -0,0 +1,130 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestArmRegisterDefinition(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + class MyResponder(MockGDBServerResponder): + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <!DOCTYPE feature SYSTEM "gdb-target.dtd"> + <target> + <architecture>arm</architecture> + <feature name="org.gnu.gdb.arm.m-profile"> + <reg name="r0" bitsize="32" type="uint32" group="general"/> + <reg name="r1" bitsize="32" type="uint32" group="general"/> + <reg name="r2" bitsize="32" type="uint32" group="general"/> + <reg name="r3" bitsize="32" type="uint32" group="general"/> + <reg name="r4" bitsize="32" type="uint32" group="general"/> + <reg name="r5" bitsize="32" type="uint32" group="general"/> + <reg name="r6" bitsize="32" type="uint32" group="general"/> + <reg name="r7" bitsize="32" type="uint32" group="general"/> + <reg name="r8" bitsize="32" type="uint32" group="general"/> + <reg name="r9" bitsize="32" type="uint32" group="general"/> + <reg name="r10" bitsize="32" type="uint32" group="general"/> + <reg name="r11" bitsize="32" type="uint32" group="general"/> + <reg name="r12" bitsize="32" type="uint32" group="general"/> + <reg name="sp" bitsize="32" type="data_ptr" group="general"/> + <reg name="lr" bitsize="32" type="uint32" group="general"/> + <reg name="pc" bitsize="32" type="code_ptr" group="general"/> + <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/> + <reg name="MSP" bitsize="32" regnum="26" type="uint32" group="general"/> + <reg name="PSP" bitsize="32" regnum="27" type="uint32" group="general"/> + <reg name="PRIMASK" bitsize="32" regnum="28" type="uint32" group="general"/> + <reg name="BASEPRI" bitsize="32" regnum="29" type="uint32" group="general"/> + <reg name="FAULTMASK" bitsize="32" regnum="30" type="uint32" group="general"/> + <reg name="CONTROL" bitsize="32" regnum="31" type="uint32" group="general"/> + <reg name="FPSCR" bitsize="32" type="uint32" group="float"/> + <reg name="s0" bitsize="32" type="float" group="float"/> + <reg name="s1" bitsize="32" type="float" group="float"/> + <reg name="s2" bitsize="32" type="float" group="float"/> + <reg name="s3" bitsize="32" type="float" group="float"/> + <reg name="s4" bitsize="32" type="float" group="float"/> + <reg name="s5" bitsize="32" type="float" group="float"/> + <reg name="s6" bitsize="32" type="float" group="float"/> + <reg name="s7" bitsize="32" type="float" group="float"/> + <reg name="s8" bitsize="32" type="float" group="float"/> + <reg name="s9" bitsize="32" type="float" group="float"/> + <reg name="s10" bitsize="32" type="float" group="float"/> + <reg name="s11" bitsize="32" type="float" group="float"/> + <reg name="s12" bitsize="32" type="float" group="float"/> + <reg name="s13" bitsize="32" type="float" group="float"/> + <reg name="s14" bitsize="32" type="float" group="float"/> + <reg name="s15" bitsize="32" type="float" group="float"/> + <reg name="s16" bitsize="32" type="float" group="float"/> + <reg name="s17" bitsize="32" type="float" group="float"/> + <reg name="s18" bitsize="32" type="float" group="float"/> + <reg name="s19" bitsize="32" type="float" group="float"/> + <reg name="s20" bitsize="32" type="float" group="float"/> + <reg name="s21" bitsize="32" type="float" group="float"/> + <reg name="s22" bitsize="32" type="float" group="float"/> + <reg name="s23" bitsize="32" type="float" group="float"/> + <reg name="s24" bitsize="32" type="float" group="float"/> + <reg name="s25" bitsize="32" type="float" group="float"/> + <reg name="s26" bitsize="32" type="float" group="float"/> + <reg name="s27" bitsize="32" type="float" group="float"/> + <reg name="s28" bitsize="32" type="float" group="float"/> + <reg name="s29" bitsize="32" type="float" group="float"/> + <reg name="s30" bitsize="32" type="float" group="float"/> + <reg name="s31" bitsize="32" type="float" group="float"/> + </feature> + </target>""", False + else: + return None, False + + def readRegister(self, regnum): + return "E01" + + def readRegisters(self): + return "20000000f8360020001000002fcb0008f8360020a0360020200c0020000000000000000000000000000000000000000000000000b87f0120b7d100082ed2000800000001b87f01200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + def haltReason(self): + return "S05" + + def qfThreadInfo(self): + return "mdead" + + def qC(self): + return "" + + def qSupported(self, client_supported): + return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;qXfer:threads:read+;hwbreak+;qXfer:features:read+" + + def QThreadSuffixSupported(self): + return "OK" + + def QListThreadsInStopReply(self): + return "OK" + + self.server.responder = MyResponder() + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("log enable gdb-remote packets", result) + self.dbg.SetDefaultArchitecture("armv7em") + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + r0_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r0") + self.assertEqual(r0_valobj.GetValueAsUnsigned(), 0x20) + + pc_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("pc") + self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800d22e) diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py new file mode 100644 index 000000000000..66a271e126dc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py @@ -0,0 +1,64 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + +class TestNoWatchpointSupportInfo(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + def test(self): + """ + Test lldb's parsing of the <architecture> tag in the target.xml register + description packet. + """ + class MyResponder(MockGDBServerResponder): + + def haltReason(self): + return "T02thread:1ff0d;thread-pcs:10001bc00;" + + def threadStopInfo(self, threadnum): + if threadnum == 0x1ff0d: + return "T02thread:1ff0d;thread-pcs:10001bc00;" + + def setBreakpoint(self, packet): + if packet.startswith("Z2,"): + return "OK" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", False + else: + return None, False + + self.server.responder = MyResponder() + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("log enable gdb-remote packets", result) + self.dbg.SetDefaultArchitecture("x86_64") + target = self.dbg.CreateTargetWithFileAndArch(None, None) + + process = self.connect(target) + + if self.TraceOn(): + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("target list", result) + print(result.GetOutput()) + + + err = lldb.SBError() + wp = target.WatchAddress(0x100, 8, False, True, err) + if self.TraceOn() and (err.Fail() or wp.IsValid == False): + strm = lldb.SBStream() + err.GetDescription(strm) + print("watchpoint failed: %s" % strm.GetData()) + self.assertTrue(wp.IsValid()) diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py new file mode 100644 index 000000000000..7b733e77e679 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py @@ -0,0 +1,46 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestStopPCs(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + def test(self): + class MyResponder(MockGDBServerResponder): + def haltReason(self): + return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + + def threadStopInfo(self, threadnum): + if threadnum == 0x1ff0d: + return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + if threadnum == 0x2ff0d: + return "T00thread:2ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;" + + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <target version="1.0"> + <architecture>i386:x86-64</architecture> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> + </feature> + </target>""", False + else: + return None, False + + self.server.responder = MyResponder() + target = self.dbg.CreateTarget('') + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + process = self.connect(target) + + self.assertEqual(process.GetNumThreads(), 2) + th0 = process.GetThreadAtIndex(0) + th1 = process.GetThreadAtIndex(1) + self.assertEqual(th0.GetThreadID(), 0x1ff0d) + self.assertEqual(th1.GetThreadID(), 0x2ff0d) + self.assertEqual(th0.GetFrameAtIndex(0).GetPC(), 0x10001bc00) + self.assertEqual(th1.GetFrameAtIndex(0).GetPC(), 0x10002bc00) diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py index 184867e480b4..57c5ff0aac25 100644 --- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py @@ -121,4 +121,4 @@ class TestTargetXMLArch(GDBRemoteTestBase): if self.TraceOn(): interp.HandleCommand("target list", result) print(result.GetOutput()) - self.assertTrue(target.GetTriple().startswith('x86_64--')) + self.assertTrue(target.GetTriple().startswith('x86_64-unknown-unknown')) diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py index d8d759a5dd58..a9e553cbb7d5 100644 --- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py +++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py @@ -102,12 +102,13 @@ class MockGDBServerResponder: return self.interrupt() if packet == "c": return self.cont() - if packet == "g": + if packet[0] == "g": return self.readRegisters() if packet[0] == "G": return self.writeRegisters(packet[1:]) if packet[0] == "p": - return self.readRegister(int(packet[1:], 16)) + regnum = packet[1:].split(';')[0] + return self.readRegister(int(regnum, 16)) if packet[0] == "P": register, value = packet[1:].split("=") return self.readRegister(int(register, 16), value) @@ -124,12 +125,16 @@ class MockGDBServerResponder: return self.qSupported(packet[11:].split(";")) if packet == "qfThreadInfo": return self.qfThreadInfo() + if packet == "qsThreadInfo": + return self.qsThreadInfo() if packet == "qC": return self.qC() if packet == "QEnableErrorStrings": return self.QEnableErrorStrings() if packet == "?": return self.haltReason() + if packet == "s": + return self.haltReason() if packet[0] == "H": return self.selectThread(packet[1], int(packet[2:], 16)) if packet[0:6] == "qXfer:": @@ -144,6 +149,16 @@ class MockGDBServerResponder: return self.vAttach(int(pid, 16)) if packet[0] == "Z": return self.setBreakpoint(packet) + if packet.startswith("qThreadStopInfo"): + threadnum = int (packet[15:], 16) + return self.threadStopInfo(threadnum) + if packet == "QThreadSuffixSupported": + return self.QThreadSuffixSupported() + if packet == "QListThreadsInStopReply": + return self.QListThreadsInStopReply() + if packet.startswith("qMemoryRegionInfo:"): + return self.qMemoryRegionInfo() + return self.other(packet) def interrupt(self): @@ -179,6 +194,9 @@ class MockGDBServerResponder: def qfThreadInfo(self): return "l" + def qsThreadInfo(self): + return "l" + def qC(self): return "QC0" @@ -204,10 +222,22 @@ class MockGDBServerResponder: def setBreakpoint(self, packet): raise self.UnexpectedPacketException() + def threadStopInfo(self, threadnum): + return "" + def other(self, packet): # empty string means unsupported return "" + def QThreadSuffixSupported(self): + return "" + + def QListThreadsInStopReply(self): + return "" + + def qMemoryRegionInfo(self): + return "" + """ Raised when we receive a packet for which there is no default action. Override the responder class to implement behavior suitable for the test at @@ -246,7 +276,7 @@ class MockGDBServer: addr = ("127.0.0.1", self.port) self._socket.bind(addr) self.port = self._socket.getsockname()[1] - self._socket.listen(0) + self._socket.listen(1) self._thread = threading.Thread(target=self._run) self._thread.start() diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py index 4f54f5d4103b..528192519513 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py @@ -16,59 +16,42 @@ class CrashingInferiorTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_inferior_crashing(self): """Test that lldb reliably catches the inferior crashing (command).""" self.build() self.inferior_crashing() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_inferior_crashing_register(self): """Test that lldb reliably reads registers from the inferior after crashing (command).""" self.build() self.inferior_crashing_registers() @add_test_categories(['pyapi']) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_python(self): """Test that lldb reliably catches the inferior crashing (Python API).""" self.build() self.inferior_crashing_python() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_expr(self): """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" self.build() self.inferior_crashing_expr() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_inferior_crashing_step(self): """Test that stepping after a crash behaves correctly.""" self.build() self.inferior_crashing_step() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") @skipIfTargetAndroid() # debuggerd interferes with this test on Android + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_inferior_crashing_step_after_break(self): """Test that lldb functions correctly after stepping through a crash.""" self.build() self.inferior_crashing_step_after_break() - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") # Inferior exits after stepping after a segfault. This is working as # intended IMHO. @skipIfLinux diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py index d8efe65dc7f6..2cd4d46a7ca8 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py @@ -29,13 +29,11 @@ class CrashingRecursiveInferiorTestCase(TestBase): self.recursive_inferior_crashing_registers() @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_python(self): """Test that lldb reliably catches the inferior crashing (Python API).""" self.build() self.recursive_inferior_crashing_python() - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_expr(self): """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" self.build() @@ -47,8 +45,8 @@ class CrashingRecursiveInferiorTestCase(TestBase): self.build() self.recursive_inferior_crashing_step() - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @skipIfTargetAndroid() # debuggerd interferes with this test on Android + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_step_after_break(self): """Test that lldb functions correctly after stepping through a crash.""" self.build() @@ -58,7 +56,6 @@ class CrashingRecursiveInferiorTestCase(TestBase): # intended IMHO. @skipIfLinux @skipIfFreeBSD - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_expr_step_and_expr(self): """Test that lldb expressions work before and after stepping after a crash.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py index ab5791c614af..7bc5d205a94f 100644 --- a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py +++ b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py @@ -158,6 +158,7 @@ class LoadUnloadTestCase(TestBase): @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support @expectedFailureAndroid # wrong source file shows up for hidden library @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently + @skipIfDarwinEmbedded def test_dyld_library_path(self): """Test (DY)LD_LIBRARY_PATH after moving libd.dylib, which defines d_function, somewhere else.""" self.copy_shlibs_to_remote(hidden_dir=True) diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile new file mode 100644 index 000000000000..9d4f3b7f1412 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +clean:: + rm -rf $(wildcard *.o *.d *.dSYM) diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py new file mode 100644 index 000000000000..4d10e68672e0 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py @@ -0,0 +1,59 @@ +""" +Test the 'memory region' command. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MemoryCommandRegion(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Run here before printing memory regions') + + def test(self): + self.build() + + # Set breakpoint in main and run + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + + # Test that the first 'memory region' command prints the usage. + interp.HandleCommand("memory region", result) + self.assertFalse(result.Succeeded()) + self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR") + + # Now let's print the memory region starting at 0 which should always work. + interp.HandleCommand("memory region 0x0", result) + self.assertTrue(result.Succeeded()) + self.assertRegexpMatches(result.GetOutput(), "\\[0x0+-") + + # Keep printing memory regions until we printed all of them. + while True: + interp.HandleCommand("memory region", result) + if not result.Succeeded(): + break + + # Now that we reached the end, 'memory region' should again print the usage. + interp.HandleCommand("memory region", result) + self.assertFalse(result.Succeeded()) + self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR") diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp b/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp new file mode 100644 index 000000000000..116c10a6c3ea --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp @@ -0,0 +1,6 @@ +#include <iostream> + +int main (int argc, char const **argv) { + std::cout << "Program with sections" << std::endl; + return 0; // Run here before printing memory regions +} diff --git a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py index f45479bee0bf..56984885104e 100644 --- a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py +++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py @@ -24,7 +24,7 @@ class MemoryCacheTestCase(TestBase): # Find the line number to break inside main(). self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFlakeyOS(oslist=["windows"]) + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_memory_cache(self): """Test the MemoryCache class with a sequence of 'memory read' and 'memory write' operations.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py index 8e0fbaa32018..245aaa819c7f 100644 --- a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py +++ b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py @@ -24,7 +24,6 @@ class MemoryFindTestCase(TestBase): # Find the line number to break inside main(). self.line = line_number('main.cpp', '// break here') - @expectedFailureAll(oslist=["windows"]) def test_memory_find(self): """Test the 'memory find' command.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py index 879f1adebc6a..2c25ccc253fd 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -6,6 +6,7 @@ from __future__ import print_function import shutil import struct +import os import lldb from lldbsuite.test.decorators import * @@ -203,6 +204,30 @@ class LinuxCoreTestCase(TestBase): for regname, value in values.iteritems(): self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)]) + @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + def test_i386_sysroot(self): + """Test that lldb can find the exe for an i386 linux core file using the sysroot.""" + + # Copy linux-i386.out to tmp_sysroot/home/labath/test/a.out (since it was compiled as + # /home/labath/test/a.out) + tmp_sysroot = os.path.join(self.getBuildDir(), "lldb_i386_mock_sysroot") + executable = os.path.join(tmp_sysroot, "home", "labath", "test", "a.out") + lldbutil.mkdir_p(os.path.dirname(executable)) + shutil.copyfile("linux-i386.out", executable) + + # Set sysroot and load core + self.runCmd("platform select remote-linux --sysroot '%s'" % tmp_sysroot) + target = self.dbg.CreateTarget(None) + self.assertTrue(target, VALID_TARGET) + process = target.LoadCore("linux-i386.core") + + # Check that we found a.out from the sysroot + self.check_all(process, self._i386_pid, self._i386_regions, "a.out") + + self.dbg.DeleteTarget(target) + def check_memory_regions(self, process, region_count): region_list = process.GetMemoryRegions() self.assertEqual(region_list.GetSize(), region_count) @@ -299,15 +324,7 @@ class LinuxCoreTestCase(TestBase): self.dbg.SetOutputFileHandle(None, False) self.dbg.SetErrorFileHandle(None, False) - def do_test(self, filename, pid, region_count, thread_name): - target = self.dbg.CreateTarget(filename + ".out") - process = target.LoadCore(filename + ".core") - self.assertTrue(process, PROCESS_IS_VALID) - self.assertEqual(process.GetNumThreads(), 1) - self.assertEqual(process.GetProcessID(), pid) - - self.check_state(process) - + def check_stack(self, process, pid, thread_name): thread = process.GetSelectedThread() self.assertTrue(thread) self.assertEqual(thread.GetThreadID(), pid) @@ -324,6 +341,21 @@ class LinuxCoreTestCase(TestBase): frame.FindVariable("F").GetValueAsUnsigned(), ord( backtrace[i][0])) + def check_all(self, process, pid, region_count, thread_name): + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 1) + self.assertEqual(process.GetProcessID(), pid) + + self.check_state(process) + + self.check_stack(process, pid, thread_name) + self.check_memory_regions(process, region_count) + def do_test(self, filename, pid, region_count, thread_name): + target = self.dbg.CreateTarget(filename + ".out") + process = target.LoadCore(filename + ".core") + + self.check_all(process, pid, region_count, thread_name) + self.dbg.DeleteTarget(target) diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py index 5960215f8047..46398e39a0e0 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py @@ -88,6 +88,36 @@ class MiniDumpNewTestCase(TestBase): self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid) self.check_state() + def test_memory_region_name(self): + self.dbg.CreateTarget(None) + self.target = self.dbg.GetSelectedTarget() + self.process = self.target.LoadCore("regions-linux-map.dmp") + result = lldb.SBCommandReturnObject() + addr_region_name_pairs = [ + ("0x400d9000", "/system/bin/app_process"), + ("0x400db000", "/system/bin/app_process"), + ("0x400dd000", "/system/bin/linker"), + ("0x400ed000", "/system/bin/linker"), + ("0x400ee000", "/system/bin/linker"), + ("0x400fb000", "/system/lib/liblog.so"), + ("0x400fc000", "/system/lib/liblog.so"), + ("0x400fd000", "/system/lib/liblog.so"), + ("0x400ff000", "/system/lib/liblog.so"), + ("0x40100000", "/system/lib/liblog.so"), + ("0x40101000", "/system/lib/libc.so"), + ("0x40122000", "/system/lib/libc.so"), + ("0x40123000", "/system/lib/libc.so"), + ("0x40167000", "/system/lib/libc.so"), + ("0x40169000", "/system/lib/libc.so"), + ] + ci = self.dbg.GetCommandInterpreter() + for (addr, region_name) in addr_region_name_pairs: + command = 'memory region ' + addr + ci.HandleCommand(command, result, False) + message = 'Ensure memory "%s" shows up in output for "%s"' % ( + region_name, command) + self.assertTrue(region_name in result.GetOutput(), message) + def test_modules_in_mini_dump(self): """Test that lldb can read the list of modules from the minidump.""" # target create -c linux-x86_64.dmp @@ -97,14 +127,18 @@ class MiniDumpNewTestCase(TestBase): self.assertTrue(self.process, PROCESS_IS_VALID) expected_modules = [ { - 'filename' : 'linux-gate.so', - 'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F', + 'filename' : 'linux-x86_64', + 'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448', }, { 'filename' : 'libm-2.19.so', 'uuid' : 'D144258E-6149-00B2-55A3-1F3FD2283A87-8670D5BC', }, { + 'filename' : 'libgcc_s.so.1', + 'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92', + }, + { 'filename' : 'libstdc++.so.6.0.19', 'uuid' : '76190E92-2AF7-457D-078F-75C9B15FA184-E83EB506', }, @@ -113,24 +147,20 @@ class MiniDumpNewTestCase(TestBase): 'uuid' : 'CF699A15-CAAE-64F5-0311-FC4655B86DC3-9A479789', }, { - 'filename' : 'linux-x86_64', - 'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448', - }, - { - 'filename' : 'libgcc_s.so.1', - 'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92', - }, - { 'filename' : 'libpthread-2.19.so', 'uuid' : '31E9F21A-E8C1-0396-171F-1E13DA157809-86FA696C', }, { + 'filename' : 'libbreakpad.so', + 'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A', + }, + { 'filename' : 'ld-2.19.so', 'uuid' : 'D0F53790-4076-D73F-29E4-A37341F8A449-E2EF6CD0', }, { - 'filename' : 'libbreakpad.so', - 'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A', + 'filename' : 'linux-gate.so', + 'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F', }, ] self.assertEqual(self.target.GetNumModules(), len(expected_modules)) @@ -189,6 +219,161 @@ class MiniDumpNewTestCase(TestBase): stop_description = thread.GetStopDescription(256) self.assertEqual(stop_description, "") + def check_register_unsigned(self, set, name, expected): + reg_value = set.GetChildMemberWithName(name) + self.assertTrue(reg_value.IsValid(), + 'Verify we have a register named "%s"' % (name)) + self.assertEqual(reg_value.GetValueAsUnsigned(), expected, + 'Verify "%s" == %i' % (name, expected)) + + def check_register_string_value(self, set, name, expected, format): + reg_value = set.GetChildMemberWithName(name) + self.assertTrue(reg_value.IsValid(), + 'Verify we have a register named "%s"' % (name)) + if format is not None: + reg_value.SetFormat(format) + self.assertEqual(reg_value.GetValue(), expected, + 'Verify "%s" has string value "%s"' % (name, + expected)) + + def test_arm64_registers(self): + """Test ARM64 registers from a breakpad created minidump.""" + # target create -c arm64-macos.dmp + self.dbg.CreateTarget(None) + self.target = self.dbg.GetSelectedTarget() + self.process = self.target.LoadCore("arm64-macos.dmp") + self.check_state() + self.assertEqual(self.process.GetNumThreads(), 1) + thread = self.process.GetThreadAtIndex(0) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone) + stop_description = thread.GetStopDescription(256) + self.assertEqual(stop_description, "") + registers = thread.GetFrameAtIndex(0).GetRegisters() + # Verify the GPR registers are all correct + # Verify x0 - x31 register values + gpr = registers.GetValueAtIndex(0) + for i in range(32): + v = i+1 | i+2 << 32 | i+3 << 48 + w = i+1 + self.check_register_unsigned(gpr, 'x%i' % (i), v) + self.check_register_unsigned(gpr, 'w%i' % (i), w) + # Verify arg1 - arg8 register values + for i in range(1, 9): + v = i | i+1 << 32 | i+2 << 48 + self.check_register_unsigned(gpr, 'arg%i' % (i), v) + i = 29 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'fp', v) + i = 30 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'lr', v) + i = 31 + v = i+1 | i+2 << 32 | i+3 << 48 + self.check_register_unsigned(gpr, 'sp', v) + self.check_register_unsigned(gpr, 'pc', 0x1000) + self.check_register_unsigned(gpr, 'cpsr', 0x11223344) + self.check_register_unsigned(gpr, 'psr', 0x11223344) + + # Verify the FPR registers are all correct + fpr = registers.GetValueAtIndex(1) + for i in range(32): + v = "0x" + d = "0x" + s = "0x" + h = "0x" + for j in range(i+15, i-1, -1): + v += "%2.2x" % (j) + for j in range(i+7, i-1, -1): + d += "%2.2x" % (j) + for j in range(i+3, i-1, -1): + s += "%2.2x" % (j) + for j in range(i+1, i-1, -1): + h += "%2.2x" % (j) + self.check_register_string_value(fpr, "v%i" % (i), v, + lldb.eFormatHex) + self.check_register_string_value(fpr, "d%i" % (i), d, + lldb.eFormatHex) + self.check_register_string_value(fpr, "s%i" % (i), s, + lldb.eFormatHex) + self.check_register_string_value(fpr, "h%i" % (i), h, + lldb.eFormatHex) + self.check_register_unsigned(gpr, 'fpsr', 0x55667788) + self.check_register_unsigned(gpr, 'fpcr', 0x99aabbcc) + + def verify_arm_registers(self, apple=False): + """ + Verify values of all ARM registers from a breakpad created + minidump. + """ + self.dbg.CreateTarget(None) + self.target = self.dbg.GetSelectedTarget() + if apple: + self.process = self.target.LoadCore("arm-macos.dmp") + else: + self.process = self.target.LoadCore("arm-linux.dmp") + self.check_state() + self.assertEqual(self.process.GetNumThreads(), 1) + thread = self.process.GetThreadAtIndex(0) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone) + stop_description = thread.GetStopDescription(256) + self.assertEqual(stop_description, "") + registers = thread.GetFrameAtIndex(0).GetRegisters() + # Verify the GPR registers are all correct + # Verify x0 - x31 register values + gpr = registers.GetValueAtIndex(0) + for i in range(1, 16): + self.check_register_unsigned(gpr, 'r%i' % (i), i+1) + # Verify arg1 - arg4 register values + for i in range(1, 5): + self.check_register_unsigned(gpr, 'arg%i' % (i), i) + if apple: + self.check_register_unsigned(gpr, 'fp', 0x08) + else: + self.check_register_unsigned(gpr, 'fp', 0x0c) + self.check_register_unsigned(gpr, 'lr', 0x0f) + self.check_register_unsigned(gpr, 'sp', 0x0e) + self.check_register_unsigned(gpr, 'pc', 0x10) + self.check_register_unsigned(gpr, 'cpsr', 0x11223344) + + # Verify the FPR registers are all correct + fpr = registers.GetValueAtIndex(1) + # Check d0 - d31 + self.check_register_unsigned(gpr, 'fpscr', 0x55667788aabbccdd) + for i in range(32): + value = (i+1) | (i+1) << 8 | (i+1) << 32 | (i+1) << 48 + self.check_register_unsigned(fpr, "d%i" % (i), value) + # Check s0 - s31 + for i in range(32): + i_val = (i >> 1) + 1 + if i & 1: + value = "%#8.8x" % (i_val | i_val << 16) + else: + value = "%#8.8x" % (i_val | i_val << 8) + self.check_register_string_value(fpr, "s%i" % (i), value, + lldb.eFormatHex) + # Check q0 - q15 + for i in range(15): + a = i * 2 + 1 + b = a + 1 + value = ("0x00%2.2x00%2.2x0000%2.2x%2.2x" + "00%2.2x00%2.2x0000%2.2x%2.2x") % (b, b, b, b, a, a, a, a) + self.check_register_string_value(fpr, "q%i" % (i), value, + lldb.eFormatHex) + + def test_linux_arm_registers(self): + """Test Linux ARM registers from a breakpad created minidump. + + The frame pointer is R11 for linux. + """ + self.verify_arm_registers(apple=False) + + def test_apple_arm_registers(self): + """Test Apple ARM registers from a breakpad created minidump. + + The frame pointer is R7 for linux. + """ + self.verify_arm_registers(apple=True) + def do_test_deeper_stack(self, binary, core, pid): target = self.dbg.CreateTarget(binary) process = target.LoadCore(core) @@ -263,3 +448,65 @@ class MiniDumpNewTestCase(TestBase): frame = thread.GetFrameAtIndex(1) value = frame.EvaluateExpression('x') self.assertEqual(value.GetValueAsSigned(), 3) + + def test_memory_regions_in_minidump(self): + """Test memory regions from a Minidump""" + # target create -c regions-linux-map.dmp + self.dbg.CreateTarget(None) + self.target = self.dbg.GetSelectedTarget() + self.process = self.target.LoadCore("regions-linux-map.dmp") + self.check_state() + + regions_count = 19 + region_info_list = self.process.GetMemoryRegions() + self.assertEqual(region_info_list.GetSize(), regions_count) + + def check_region(index, start, end, read, write, execute, mapped, name): + region_info = lldb.SBMemoryRegionInfo() + self.assertTrue( + self.process.GetMemoryRegionInfo(start, region_info).Success()) + self.assertEqual(start, region_info.GetRegionBase()) + self.assertEqual(end, region_info.GetRegionEnd()) + self.assertEqual(read, region_info.IsReadable()) + self.assertEqual(write, region_info.IsWritable()) + self.assertEqual(execute, region_info.IsExecutable()) + self.assertEqual(mapped, region_info.IsMapped()) + self.assertEqual(name, region_info.GetName()) + + # Ensure we have the same regions as SBMemoryRegionInfoList contains. + if index >= 0 and index < regions_count: + region_info_from_list = lldb.SBMemoryRegionInfo() + self.assertTrue(region_info_list.GetMemoryRegionAtIndex( + index, region_info_from_list)) + self.assertEqual(region_info_from_list, region_info) + + a = "/system/bin/app_process" + b = "/system/bin/linker" + c = "/system/lib/liblog.so" + d = "/system/lib/libc.so" + n = None + max_int = 0xffffffffffffffff + + # Test address before the first entry comes back with nothing mapped up + # to first valid region info + check_region(-1, 0x00000000, 0x400d9000, False, False, False, False, n) + check_region( 0, 0x400d9000, 0x400db000, True, False, True, True, a) + check_region( 1, 0x400db000, 0x400dc000, True, False, False, True, a) + check_region( 2, 0x400dc000, 0x400dd000, True, True, False, True, n) + check_region( 3, 0x400dd000, 0x400ec000, True, False, True, True, b) + check_region( 4, 0x400ec000, 0x400ed000, True, False, False, True, n) + check_region( 5, 0x400ed000, 0x400ee000, True, False, False, True, b) + check_region( 6, 0x400ee000, 0x400ef000, True, True, False, True, b) + check_region( 7, 0x400ef000, 0x400fb000, True, True, False, True, n) + check_region( 8, 0x400fb000, 0x400fc000, True, False, True, True, c) + check_region( 9, 0x400fc000, 0x400fd000, True, True, True, True, c) + check_region(10, 0x400fd000, 0x400ff000, True, False, True, True, c) + check_region(11, 0x400ff000, 0x40100000, True, False, False, True, c) + check_region(12, 0x40100000, 0x40101000, True, True, False, True, c) + check_region(13, 0x40101000, 0x40122000, True, False, True, True, d) + check_region(14, 0x40122000, 0x40123000, True, True, True, True, d) + check_region(15, 0x40123000, 0x40167000, True, False, True, True, d) + check_region(16, 0x40167000, 0x40169000, True, False, False, True, d) + check_region(17, 0x40169000, 0x4016b000, True, True, False, True, d) + check_region(18, 0x4016b000, 0x40176000, True, True, False, True, n) + check_region(-1, 0x40176000, max_int, False, False, False, False, n) diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp Binary files differnew file mode 100644 index 000000000000..3b0cb8268def --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp Binary files differnew file mode 100644 index 000000000000..9ff6a8396ec5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp Binary files differnew file mode 100644 index 000000000000..ba658dd48feb --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp Binary files differnew file mode 100644 index 000000000000..3f1dd53d98fa --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py index 61e2adee41d5..fe13871ddac9 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py @@ -50,28 +50,28 @@ class MiniDumpTestCase(TestBase): self.assertTrue(self.process, PROCESS_IS_VALID) expected_modules = [ { - 'filename' : r"C:\Windows\System32/MSVCP120D.dll", - 'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000', - }, - { - 'filename' : r"C:\Windows\SysWOW64/kernel32.dll", - 'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000', - }, - { 'filename' : r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug/fizzbuzz.exe", 'uuid' : '91B7450F-969A-F946-BF8F-2D6076EA421A-11000000', }, { - 'filename' : r"C:\Windows\System32/MSVCR120D.dll", - 'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000', + 'filename' : r"C:\Windows\SysWOW64/ntdll.dll", + 'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000', + }, + { + 'filename' : r"C:\Windows\SysWOW64/kernel32.dll", + 'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000', }, { 'filename' : r"C:\Windows\SysWOW64/KERNELBASE.dll", 'uuid' : '4152F90B-0DCB-D44B-AC5D-186A6452E522-01000000', }, { - 'filename' : r"C:\Windows\SysWOW64/ntdll.dll", - 'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000', + 'filename' : r"C:\Windows\System32/MSVCP120D.dll", + 'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000', + }, + { + 'filename' : r"C:\Windows\System32/MSVCR120D.dll", + 'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000', }, ] self.assertEqual(self.target.GetNumModules(), len(expected_modules)) @@ -80,7 +80,6 @@ class MiniDumpTestCase(TestBase): self.assertEqual(module.file.fullpath, expected['filename']) self.assertEqual(module.GetUUIDString(), expected['uuid']) - @expectedFailureAll(bugnumber="llvm.org/pr35193", hostoslist=["windows"]) def test_stack_info_in_mini_dump(self): """Test that we can see a trivial stack in a VS-generate mini dump.""" # target create -c fizzbuzz_no_heap.dmp diff --git a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py index 617b4bcfaec3..f485c13fa9f1 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py @@ -23,7 +23,6 @@ class ProcessAttachTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @skipIfiOSSimulator - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_attach_to_process_by_id(self): """Test attach by process id""" self.build() @@ -40,7 +39,6 @@ class ProcessAttachTestCase(TestBase): process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_attach_to_process_from_different_dir_by_id(self): """Test attach by process id""" newdir = self.getBuildArtifact("newdir") @@ -67,7 +65,6 @@ class ProcessAttachTestCase(TestBase): process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_attach_to_process_by_name(self): """Test attach by process name""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py index 8496ce6c04d7..d3b153270119 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py +++ b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py @@ -24,7 +24,6 @@ class ChangeProcessGroupTestCase(TestBase): @skipIfFreeBSD # Times out on FreeBSD llvm.org/pr23731 @skipIfWindows # setpgid call does not exist on Windows @expectedFailureAndroid("http://llvm.org/pr23762", api_levels=[16]) - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_setpgid(self): self.build() exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py index d362e6a8ae3d..1919d4b1ac6d 100644 --- a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py +++ b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py @@ -21,7 +21,6 @@ class TestYMMRegister(TestBase): @skipIfiOSSimulator @skipIfTargetAndroid() @skipIf(archs=no_match(['i386', 'x86_64'])) - @expectedFailureAll(oslist=["linux"], bugnumber="rdar://30523153") @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") def test(self): self.build(dictionary={"CFLAGS_EXTRAS": "-march=haswell"}) diff --git a/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py new file mode 100644 index 000000000000..a56282efd77d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py @@ -0,0 +1,34 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + +# This test checks that source code location is shown correctly +# when DWARF5 debug information is used. + +class TestTargetSourceMap(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_source_map(self): + # Set the target soure map to map "./" to the current test directory. + yaml_path = os.path.join(self.getSourceDir(), "a.yaml") + yaml_base, ext = os.path.splitext(yaml_path) + obj_path = self.getBuildArtifact(yaml_base) + self.yaml2obj(yaml_path, obj_path) + + def cleanup(): + if os.path.exists(obj_path): + os.unlink(obj_path) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Create a target with the object file we just created from YAML + target = self.dbg.CreateTarget(obj_path) + + # Check we are able to show the locations properly. + self.expect("b main", VALID_BREAKPOINT_LOCATION, + substrs=['main + 13 at test.cpp:2:3, address = 0x000000000040052d']) + + self.expect("b foo", VALID_BREAKPOINT_LOCATION, + substrs=['foo() + 4 at test.cpp:6:1, address = 0x0000000000400534']) diff --git a/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml b/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml new file mode 100644 index 000000000000..27b119d3df63 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml @@ -0,0 +1,58 @@ +# This file is a shorten version of the output +# produced with the following invocations and input: +# ./clang test.cpp -g -gdwarf-5 -o test.exe +# ./obj2yaml test.exe > test.yaml +# +# // test.cpp +# int main() { +# return 0; +# } +# +# void foo() { +# } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000400440 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x0000000000400440 + AddressAlign: 0x0000000000000010 + Content: 31ED4989D15E4889E24883E4F0505449C7C0B005400048C7C14005400048C7C720054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000554889E531C0C745FC000000005DC390554889E55DC3662E0F1F840000000000415741564189FF415541544C8D25B618000055488D2DB6180000534989F64989D54C29E54883EC0848C1FD03E87FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 200000000500000000000000230000002C0000004A0000004F000000530000005B000000 + - Name: .debug_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334313935382900746573742E637070002F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E006D61696E00696E74005F5A33666F6F7600666F6F00 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 011101252513050325721710171B25110112060000022E0011011206401803253A0B3B0B49133F190000032E001101120640186E2503253A0B3B0B3F19000004240003253E0B0B0B000000 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 50000000050001080000000001000400010800000000000000022005400000000000160000000220054000000000000F00000001560301014F000000033005400000000000060000000156050601050404050400 + - Name: .debug_macinfo + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '00' + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: 70000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E021E00000000FD7C0F2E46BA561F7BDA351B04E677091E00000000FD7C0F2E46BA561F7BDA351B04E6770900090220054000000000000105030AC905003F05010A4B0202000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 2F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E00746573742E63707000 +... diff --git a/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py index a6c38ca1d091..f2027eb131c5 100644 --- a/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py +++ b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py @@ -17,6 +17,15 @@ class TestStatsAPI(TestBase): self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) + + # Test enabling/disabling stats + self.assertFalse(target.GetCollectingStats()) + target.SetCollectingStats(True) + self.assertTrue(target.GetCollectingStats()) + target.SetCollectingStats(False) + self.assertFalse(target.GetCollectingStats()) + + # Test the function to get the statistics in JSON'ish. stats = target.GetStatistics() stream = lldb.SBStream() res = stats.GetAsJSON(stream) diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile index 0d70f2595019..0d70f2595019 100644 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py new file mode 100644 index 000000000000..1383a03f4647 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py @@ -0,0 +1,37 @@ +import lldb + +class StepWithChild: + def __init__(self, thread_plan): + self.thread_plan = thread_plan + self.child_thread_plan = self.queue_child_thread_plan() + + def explains_stop(self, event): + return False + + def should_stop(self, event): + if not self.child_thread_plan.IsPlanComplete(): + return False + + self.thread_plan.SetPlanComplete(True) + + return True + + def should_step(self): + return False + + def queue_child_thread_plan(self): + return None + +class StepOut(StepWithChild): + def __init__(self, thread_plan, dict): + StepWithChild.__init__(self, thread_plan) + + def queue_child_thread_plan(self): + return self.thread_plan.QueueThreadPlanForStepOut(0) + +class StepScripted(StepWithChild): + def __init__(self, thread_plan, dict): + StepWithChild.__init__(self, thread_plan) + + def queue_child_thread_plan(self): + return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut") diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py new file mode 100644 index 000000000000..a111ede6739c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py @@ -0,0 +1,41 @@ +""" +Tests stepping with scripted thread plans. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class StepScriptedTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_standard_step_out(self): + """Tests stepping with the scripted thread plan laying over a standard thread plan for stepping out.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.step_out_with_scripted_plan("Steps.StepOut") + + def test_scripted_step_out(self): + """Tests stepping with the scripted thread plan laying over an another scripted thread plan for stepping out.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.step_out_with_scripted_plan("Steps.StepScripted") + + def setUp(self): + TestBase.setUp(self) + self.runCmd("command script import Steps.py") + + def step_out_with_scripted_plan(self, name): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + self.assertEqual("foo", frame.GetFunctionName()) + + err = thread.StepUsingScriptedThreadPlan(name) + self.assertTrue(err.Success(), err.GetCString()) + + frame = thread.GetFrameAtIndex(0) + self.assertEqual("main", frame.GetFunctionName()) diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c new file mode 100644 index 000000000000..88b3c17125db --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +void foo() { + printf("Set a breakpoint here.\n"); +} + +int main() { + foo(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py deleted file mode 100644 index 767b368cc7dc..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Test lldb target stop-hook command. -""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class StopHookCmdTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers inside main.cpp. - self.begl = line_number( - 'main.cpp', - '// Set breakpoint here to test target stop-hook.') - self.endl = line_number( - 'main.cpp', - '// End of the line range for which stop-hook is to be run.') - self.line = line_number( - 'main.cpp', - '// Another breakpoint which is outside of the stop-hook range.') - - @no_debug_info_test - def test_not_crashing_if_no_target(self): - """target stop-hook list should not crash if no target has been set.""" - self.runCmd("target stop-hook list", check=False) - - def test(self): - """Test a sequence of target stop-hook commands.""" - self.build() - exe = self.getBuildArtifact("a.out") - self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - - lldbutil.run_break_set_by_file_and_line( - self, "main.cpp", self.begl, num_expected_locations=1, loc_exact=True) - - lldbutil.run_break_set_by_file_and_line( - self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) - - self.runCmd( - "target stop-hook add -f main.cpp -l %d -e %d -o 'expr ptr'" % - (self.begl, self.endl)) - - self.expect('target stop-hook list', 'Stop Hook added successfully', - substrs=['State: enabled', - 'expr ptr']) - - self.runCmd('target stop-hook disable') - - self.expect('target stop-hook list', 'Stop Hook disabled successfully', - substrs=['State: disabled', - 'expr ptr']) - - self.runCmd('target stop-hook enable') - - self.expect('target stop-hook list', 'Stop Hook enabled successfully', - substrs=['State: enabled', - 'expr ptr']) - - self.runCmd("settings set auto-confirm true") - self.addTearDownHook( - lambda: self.runCmd("settings clear auto-confirm")) - - self.runCmd('target stop-hook delete') - - self.expect('target stop-hook list', 'Stop Hook deleted successfully', - substrs=['No stop hooks.']) diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py deleted file mode 100644 index b76d98a333c2..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -Test lldb target stop-hook mechanism to see whether it fires off correctly . -""" - -from __future__ import print_function - - -import os -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import configuration -from lldbsuite.test import lldbutil - - -class StopHookMechanismTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers inside main.cpp. - self.begl = line_number( - 'main.cpp', - '// Set breakpoint here to test target stop-hook.') - self.endl = line_number( - 'main.cpp', - '// End of the line range for which stop-hook is to be run.') - self.correct_step_line = line_number( - 'main.cpp', '// We should stop here after stepping.') - self.line = line_number( - 'main.cpp', - '// Another breakpoint which is outside of the stop-hook range.') - - @skipIfFreeBSD # llvm.org/pr15037 - # stop-hooks sometimes fail to fire on Linux - @expectedFlakeyLinux('llvm.org/pr15037') - @expectedFailureAll( - hostoslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - @skipIf(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k']) # <rdar://problem/34582291> problem with armv7 and step-over and stop-hook firing on ios etc systems - def test(self): - """Test the stop-hook mechanism.""" - self.build() - - import pexpect - exe = self.getBuildArtifact("a.out") - prompt = "(lldb) " - add_prompt = "Enter your stop hook command(s). Type 'DONE' to end." - add_prompt1 = "> " - - # So that the child gets torn down after the test. - self.child = pexpect.spawn('%s %s' % - (lldbtest_config.lldbExec, self.lldbOption)) - child = self.child - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - if lldb.remote_platform: - child.expect_exact(prompt) - child.sendline( - 'platform select %s' % - lldb.remote_platform.GetName()) - child.expect_exact(prompt) - child.sendline( - 'platform connect %s' % - configuration.lldb_platform_url) - child.expect_exact(prompt) - child.sendline( - 'platform settings -w %s' % - configuration.lldb_platform_working_dir) - - child.expect_exact(prompt) - child.sendline('target create %s' % exe) - - # Set the breakpoint, followed by the target stop-hook commands. - child.expect_exact(prompt) - child.sendline('breakpoint set -f main.cpp -l %d' % self.begl) - child.expect_exact(prompt) - child.sendline('breakpoint set -f main.cpp -l %d' % self.line) - child.expect_exact(prompt) - child.sendline( - 'target stop-hook add -f main.cpp -l %d -e %d' % - (self.begl, self.endl)) - child.expect_exact(add_prompt) - child.expect_exact(add_prompt1) - child.sendline('expr ptr') - child.expect_exact(add_prompt1) - child.sendline('DONE') - child.expect_exact(prompt) - child.sendline('target stop-hook list') - - # Now run the program, expect to stop at the first breakpoint which is - # within the stop-hook range. - child.expect_exact(prompt) - child.sendline('run') - # Make sure we see the stop hook text from the stop of the process from - # the run hitting the first breakpoint - child.expect_exact('(void *) $') - child.expect_exact(prompt) - child.sendline('thread step-over') - # Expecting to find the output emitted by the firing of our stop hook. - child.expect_exact('(void *) $') - # This is orthogonal to the main stop hook test, but this example shows a bug in - # CLANG where the line table entry for the "return -1" actually includes some code - # from the other branch of the if/else, so we incorrectly stop at the "return -1" line. - # I fixed that in lldb and I'm sticking in a test here because I don't want to have to - # make up a whole nother test case for it. - child.sendline('frame info') - at_line = 'at main.cpp:%d' % (self.correct_step_line) - print('expecting "%s"' % at_line) - child.expect_exact(at_line) - - # Now continue the inferior, we'll stop at another breakpoint which is - # outside the stop-hook range. - child.sendline('process continue') - child.expect_exact( - '// Another breakpoint which is outside of the stop-hook range.') - # self.DebugPExpect(child) - child.sendline('thread step-over') - child.expect_exact( - '// Another breakpoint which is outside of the stop-hook range.') - # self.DebugPExpect(child) - # Verify that the 'Stop Hooks' mechanism is NOT BEING fired off. - self.expect(child.before, exe=False, matching=False, - substrs=['(void *) $']) diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp b/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp deleted file mode 100644 index c10c1e5ef0d2..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -//===-- main.c --------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#include <stdio.h> -#include <stdlib.h> - -int a(int); -int b(int); -int c(int); - -int a(int val) -{ - if (val <= 1) - return b(val); - else if (val >= 3) - return c(val); - - return val; -} - -int b(int val) -{ - int rc = c(val); - void *ptr = malloc(1024); - if (!ptr) // Set breakpoint here to test target stop-hook. - return -1; - else - printf("ptr=%p\n", ptr); // We should stop here after stepping. - return rc; // End of the line range for which stop-hook is to be run. -} - -int c(int val) -{ - return val + 3; -} - -int main (int argc, char const *argv[]) -{ - int A1 = a(1); - printf("a(1) returns %d\n", A1); - - int C2 = c(2); // Another breakpoint which is outside of the stop-hook range. - printf("c(2) returns %d\n", C2); - - int A3 = a(3); - printf("a(3) returns %d\n", A3); - - return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py deleted file mode 100644 index 88267b60b978..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Test that lldb stop-hook works for multiple threads. -""" - -from __future__ import print_function - - -import os -import time -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import configuration -from lldbsuite.test import lldbutil - - -class StopHookForMultipleThreadsTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Our simple source filename. - self.source = 'main.cpp' - # Find the line number to break inside main(). - self.first_stop = line_number( - self.source, '// Set break point at this line, and add a stop-hook.') - self.thread_function = line_number( - self.source, - '// Break here to test that the stop-hook mechanism works for multiple threads.') - # Build dictionary to have unique executable names for each test - # method. - self.exe_name = self.testMethodName - self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} - - @expectedFlakeyFreeBSD("llvm.org/pr15037") - # stop hooks sometimes fail to fire on Linux - @expectedFlakeyLinux("llvm.org/pr15037") - @expectedFailureAll( - hostoslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") - def test_stop_hook_multiple_threads(self): - """Test that lldb stop-hook works for multiple threads.""" - self.build(dictionary=self.d) - self.setTearDownCleanup(dictionary=self.d) - - import pexpect - exe = self.getBuildArtifact(self.exe_name) - prompt = "(lldb) " - - # So that the child gets torn down after the test. - self.child = pexpect.spawn('%s %s' % - (lldbtest_config.lldbExec, self.lldbOption)) - child = self.child - # Turn on logging for what the child sends back. - if self.TraceOn(): - child.logfile_read = sys.stdout - - if lldb.remote_platform: - child.expect_exact(prompt) - child.sendline( - 'platform select %s' % - lldb.remote_platform.GetName()) - child.expect_exact(prompt) - child.sendline( - 'platform connect %s' % - configuration.lldb_platform_url) - child.expect_exact(prompt) - child.sendline( - 'platform settings -w %s' % - configuration.lldb_platform_working_dir) - - child.expect_exact(prompt) - child.sendline('target create %s' % exe) - - # Set the breakpoint, followed by the target stop-hook commands. - child.expect_exact(prompt) - child.sendline('breakpoint set -f main.cpp -l %d' % self.first_stop) - child.expect_exact(prompt) - child.sendline( - 'breakpoint set -f main.cpp -l %d' % - self.thread_function) - child.expect_exact(prompt) - - # Now run the program, expect to stop at the first breakpoint which is - # within the stop-hook range. - child.sendline('run') - # 'Process 2415 launched', 'Process 2415 stopped' - child.expect_exact("Process") - child.expect_exact(prompt) - child.sendline( - 'target stop-hook add -o "frame variable --show-globals g_val"') - child.expect_exact("Stop hook") # 'Stop hook #1 added.' - child.expect_exact(prompt) - - # Continue and expect to find the output emitted by the firing of our - # stop hook. - child.sendline('continue') - child.expect_exact('(uint32_t) ::g_val = ') diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp deleted file mode 100644 index e193ae18e2c1..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===-- main.cpp ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <chrono> -#include <cstdio> -#include <mutex> -#include <random> -#include <thread> - -std::default_random_engine g_random_engine{std::random_device{}()}; -std::uniform_int_distribution<> g_distribution{0, 3000000}; - -uint32_t g_val = 0; - -uint32_t -access_pool (bool flag = false) -{ - static std::mutex g_access_mutex; - if (!flag) - g_access_mutex.lock(); - - uint32_t old_val = g_val; - if (flag) - g_val = old_val + 1; - - if (!flag) - g_access_mutex.unlock(); - return g_val; -} - -void -thread_func (uint32_t thread_index) -{ - // Break here to test that the stop-hook mechanism works for multiple threads. - printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); - - uint32_t count = 0; - uint32_t val; - while (count++ < 15) - { - // random micro second sleep from zero to 3 seconds - int usec = g_distribution(g_random_engine); - printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); - std::this_thread::sleep_for(std::chrono::microseconds{usec}); - - if (count < 7) - val = access_pool (); - else - val = access_pool (true); - - printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); - } - printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); -} - - -int main (int argc, char const *argv[]) -{ - std::thread threads[3]; - - printf ("Before turning all three threads loose...\n"); // Set break point at this line, and add a stop-hook. - // Create 3 threads - for (auto &thread : threads) - thread = std::thread{thread_func, std::distance(threads, &thread)}; - - // Join all of our threads - for (auto &thread : threads) - thread.join(); - - return 0; -} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp new file mode 100644 index 000000000000..48190184be10 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp @@ -0,0 +1,33 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp") + // CHECK-NOT: func{{[23]}}_amb +} + +void __attribute__((noinline)) func3_amb() { sink(); /* tail */ } + +void __attribute__((noinline)) func2_amb() { sink(); /* tail */ } + +void __attribute__((noinline)) func1() { + if (x > 0) + func2_amb(); /* tail */ + else + func3_amb(); /* tail */ +} + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> func1 -> f{2,3}_amb -> sink` are both plausible. Test + // that lldb doesn't attempt to guess which one occurred. + func1(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp new file mode 100644 index 000000000000..1651db2ea4a1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp") + // CHECK-NOT: func{{[23]}} +} + +void func2(); + +void __attribute__((noinline)) func1() { + if (x < 1) + func2(); + else + sink(); +} + +void __attribute__((noinline)) func2() { + if (x < 1) + sink(); + else + func1(); +} + +int main() { + // Tail recursion creates ambiguous execution histories. + x = 0; + func1(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp new file mode 100644 index 000000000000..d3aef19f7a4f --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp @@ -0,0 +1,32 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: func2{{.*}} [opt] [artificial] + // CHECK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func2() { + sink(); /* tail */ +} + +void __attribute__((noinline)) func1() { sink(); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> f{1,2} -> sink` are both plausible. Test that + // return-pc call site info allows lldb to pick the correct sequence. + func2(); + if (argc == 100) + func1(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp new file mode 100644 index 000000000000..5189218c4ef4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink2() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-FUNC1") + // FROM-FUNC1: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt] + // FROM-FUNC1-NEXT: sink({{.*}} [opt] + // FROM-FUNC1-NEXT: func1{{.*}} [opt] [artificial] + // FROM-FUNC1-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) sink(bool called_from_main) { + if (called_from_main) { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-MAIN") + // FROM-MAIN: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt] + // FROM-MAIN-NEXT: main{{.*}} [opt] + } else { + sink2(); + } +} + +void __attribute__((noinline)) func1() { sink(false); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // When func1 tail-calls sink, make sure that the former appears in the + // backtrace. + sink(true); + func1(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp new file mode 100644 index 000000000000..3c723b8a3ee3 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp @@ -0,0 +1,31 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: func3{{.*}} [opt] [artificial] + // CHECK-NEXT: func1{{.*}} [opt] [artificial] + // CHECK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((noinline)) func2() { sink(); /* tail */ } + +void __attribute__((noinline)) func1() { func3(); /* tail */ } + +int __attribute__((disable_tail_calls)) main(int argc, char **) { + // The sequences `main -> func1 -> f{2,3} -> sink` are both plausible. Test + // that lldb picks the latter sequence. + func1(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp new file mode 100644 index 000000000000..e4504ad151fa --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp @@ -0,0 +1,50 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) tail_call_sink() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK") + // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4 [opt] + // TAIL-CALL-SINK-NEXT: func3{{.*}} [opt] [artificial] + // TAIL-CALL-SINK-NEXT: main{{.*}} [opt] + + // TODO: The backtrace should include inlinable_function_which_tail_calls. +} + +void __attribute__((always_inline)) inlinable_function_which_tail_calls() { + tail_call_sink(); +} + +void __attribute__((noinline)) func3() { + inlinable_function_which_tail_calls(); +} + +void __attribute__((always_inline)) inline_sink() { + x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK") + // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] inline_sink() at main.cpp:[[@LINE-1]]:4 [opt] + // INLINE-SINK-NEXT: func2{{.*}} [opt] + // INLINE-SINK-NEXT: func1{{.*}} [opt] [artificial] + // INLINE-SINK-NEXT: main{{.*}} [opt] +} + +void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + // First, call a function that tail-calls a function, which itself inlines + // a third function. + func1(); + + // Next, call a function which contains an inlined tail-call. + func3(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py new file mode 100644 index 000000000000..038a0c45bf42 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py @@ -0,0 +1,73 @@ +""" +Test SB API support for identifying artificial (tail call) frames. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class TestTailCallFrameSBAPI(TestBase): + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + @skipIf(compiler="clang", compiler_version=['<', '7.0']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_tail_call_frame_sbapi(self): + self.build() + self.do_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def do_test(self): + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateBySourceRegex("break here", + lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + threads = lldbutil.get_threads_stopped_at_breakpoint(process, + breakpoint) + self.assertEqual( + len(threads), 1, + "There should be a thread stopped at our breakpoint") + + self.assertEqual(breakpoint.GetHitCount(), 1) + + thread = threads[0] + + # Here's what we expect to see in the backtrace: + # frame #0: ... a.out`sink() at main.cpp:13:4 [opt] + # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial] + # frame #2: ... a.out`func2() at main.cpp:18:62 [opt] + # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial] + # frame #4: ... a.out`main at main.cpp:23:3 [opt] + names = ["sink", "func3", "func2", "func1", "main"] + artificiality = [False, True, False, True, False] + for idx, (name, is_artificial) in enumerate(zip(names, artificiality)): + frame = thread.GetFrameAtIndex(idx) + + # Use a relaxed substring check because function dislpay names are + # platform-dependent. E.g we see "void sink(void)" on Windows, but + # "sink()" on Darwin. This seems like a bug -- just work around it + # for now. + self.assertTrue(name in frame.GetDisplayFunctionName()) + self.assertEqual(frame.IsArtificial(), is_artificial) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp new file mode 100644 index 000000000000..f9e84da51739 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; /* break here */ +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp new file mode 100644 index 000000000000..f2f11365df7a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp @@ -0,0 +1,28 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("finish", "main.cpp", "-implicit-check-not=artificial") + // CHECK: stop reason = step out + // CHECK-NEXT: Stepped out past: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial] + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py new file mode 100644 index 000000000000..2b432e56a740 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py @@ -0,0 +1,95 @@ +""" +Test SB API support for identifying artificial (tail call) frames. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class TestArtificialFrameThreadStepOut1(TestBase): + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def prepare_thread(self): + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateBySourceRegex("break here", + lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + threads = lldbutil.get_threads_stopped_at_breakpoint(process, + breakpoint) + self.assertEqual( + len(threads), 1, + "There should be a thread stopped at our breakpoint") + + self.assertEqual(breakpoint.GetHitCount(), 1) + + thread = threads[0] + + # Here's what we expect to see in the backtrace: + # frame #0: ... a.out`sink() at main.cpp:13:4 [opt] + # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial] + # frame #2: ... a.out`func2() at main.cpp:18:62 [opt] + # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial] + # frame #4: ... a.out`main at main.cpp:23:3 [opt] + return thread + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_stepping_out_past_artificial_frame(self): + self.build() + thread = self.prepare_thread() + + # Frame #0's ancestor is artificial. Stepping out should move to + # frame #2, because we behave as-if artificial frames were not present. + thread.StepOut() + frame2 = thread.GetSelectedFrame() + self.assertEqual(frame2.GetDisplayFunctionName(), "func2()") + self.assertFalse(frame2.IsArtificial()) + + # Ditto: stepping out of frame #2 should move to frame #4. + thread.StepOut() + frame4 = thread.GetSelectedFrame() + self.assertEqual(frame4.GetDisplayFunctionName(), "main") + self.assertFalse(frame2.IsArtificial()) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") + def test_return_past_artificial_frame(self): + self.build() + thread = self.prepare_thread() + + value = lldb.SBValue() + + # Frame #0's ancestor is artificial. Returning from frame #0 should move + # to frame #2. + thread.ReturnFromFrame(thread.GetSelectedFrame(), value) + frame2 = thread.GetSelectedFrame() + self.assertEqual(frame2.GetDisplayFunctionName(), "func2()") + self.assertFalse(frame2.IsArtificial()) + + # Ditto: stepping out of frame #2 should move to frame #4. + thread.ReturnFromFrame(thread.GetSelectedFrame(), value) + frame4 = thread.GetSelectedFrame() + self.assertEqual(frame4.GetDisplayFunctionName(), "main") + self.assertFalse(frame2.IsArtificial()) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp new file mode 100644 index 000000000000..f7a81873906e --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; // break here +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile new file mode 100644 index 000000000000..15bc2e7f415b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules +CXXFLAGS += -g -O1 -glldb diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py new file mode 100644 index 000000000000..aec4d503fd73 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [decorators.skipUnlessHasCallSiteInfo]) diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp new file mode 100644 index 000000000000..c180d45b9de6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp @@ -0,0 +1,30 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +volatile int x; + +void __attribute__((noinline)) sink() { + x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial") + // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt] + // CHECK-NEXT: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial] + // CHECK-NEXT: frame #2: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt] + // CHECK-NEXT: frame #3: 0x{{[0-9a-f]+}} a.out`func1{{.*}} [opt] [artificial] + // CHECK-NEXT: frame #4: 0x{{[0-9a-f]+}} a.out`main{{.*}} [opt] +} + +void __attribute__((noinline)) func3() { sink(); /* tail */ } + +void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ } + +void __attribute__((noinline)) func1() { func2(); /* tail */ } + +int __attribute__((disable_tail_calls)) main() { + func1(); /* regular */ + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile new file mode 100644 index 000000000000..15cb0b64f218 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile @@ -0,0 +1,16 @@ +LEVEL := ../../make + +LIB_PREFIX := load_ + +LD_EXTRAS := -L. -l$(LIB_PREFIX)a +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +a.out: lib_a + +lib_%: + $(MAKE) VPATH=$(SRCDIR) -I $(SRCDIR) -f $(SRCDIR)/$*.mk + +clean:: + $(MAKE) -f $(SRCDIR)/a.mk clean diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py new file mode 100644 index 000000000000..a6c383ce3c80 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py @@ -0,0 +1,100 @@ +""" +Test that loading of dependents works correctly for all the potential +combinations. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +@skipIfWindows # Windows deals differently with shared libs. +class TargetDependentsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + self.build() + + def has_exactly_one_image(self, matching, msg=""): + self.expect( + "image list", + "image list should contain at least one image", + substrs=['[ 0]']) + should_match = not matching + self.expect( + "image list", msg, matching=should_match, substrs=['[ 1]']) + + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files + def test_dependents_implicit_default_exe(self): + """Test default behavior""" + exe = self.getBuildArtifact("a.out") + self.runCmd("target create " + exe, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(False) + + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files + def test_dependents_explicit_default_exe(self): + """Test default behavior""" + exe = self.getBuildArtifact("a.out") + self.runCmd("target create -ddefault " + exe, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(False) + + def test_dependents_explicit_true_exe(self): + """Test default behavior""" + exe = self.getBuildArtifact("a.out") + self.runCmd("target create -dtrue " + exe, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) + + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files + def test_dependents_explicit_false_exe(self): + """Test default behavior""" + exe = self.getBuildArtifact("a.out") + self.runCmd("target create -dfalse " + exe, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(False) + + def test_dependents_implicit_false_exe(self): + """Test default behavior""" + exe = self.getBuildArtifact("a.out") + self.runCmd("target create -d " + exe, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) + + def test_dependents_implicit_default_lib(self): + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension + lib = self.getBuildArtifact(dylibName) + self.runCmd("target create " + lib, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) + + def test_dependents_explicit_default_lib(self): + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension + lib = self.getBuildArtifact(dylibName) + self.runCmd("target create -ddefault " + lib, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) + + def test_dependents_explicit_true_lib(self): + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension + lib = self.getBuildArtifact(dylibName) + self.runCmd("target create -dtrue " + lib, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) + + @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files + def test_dependents_explicit_false_lib(self): + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension + lib = self.getBuildArtifact(dylibName) + self.runCmd("target create -dfalse " + lib, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(False) + + def test_dependents_implicit_false_lib(self): + ctx = self.platformContext + dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension + lib = self.getBuildArtifact(dylibName) + self.runCmd("target create -d " + lib, CURRENT_EXECUTABLE_SET) + self.has_exactly_one_image(True) diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp new file mode 100644 index 000000000000..c0dac40d0eed --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp @@ -0,0 +1,13 @@ +//===-- b.c -----------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int a_function () +{ + return 500; +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk new file mode 100644 index 000000000000..f199bfed5b0d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk @@ -0,0 +1,9 @@ +LEVEL := ../../make + +LIB_PREFIX := load_ + +DYLIB_NAME := $(LIB_PREFIX)a +DYLIB_CXX_SOURCES := a.cpp +DYLIB_ONLY := YES + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp new file mode 100644 index 000000000000..08fbb59d8a58 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp @@ -0,0 +1,17 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +extern int a_function (); +extern int b_function (); + +int +main (int argc, char const *argv[]) +{ + return a_function(); +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/Makefile b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile new file mode 100644 index 000000000000..bb9cc4f2f66d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +include $(LEVEL)/Makefile.rules + +a.out: globals.ll + $(CC) $(CFLAGS) -g -c $^ -o globals.o + $(LD) $(LDFLAGS) -g globals.o -o $@ + +clean:: + rm -rf globals.o a.out *.dSYM diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py new file mode 100644 index 000000000000..d3afacca72f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py @@ -0,0 +1,23 @@ +""" +Test that target var can resolve complex DWARF expressions. +""" + +import lldb +import sys +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class targetCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @skipIfDarwinEmbedded # needs x86_64 + @skipIf(debug_info="gmodules") # not relevant + @skipIf(compiler="clang", compiler_version=['<', '7.0']) + def testTargetVarExpr(self): + self.build() + lldbutil.run_to_name_breakpoint(self, 'main') + self.expect("target variable i", substrs=['i', '42']) diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/globals.c b/packages/Python/lldbsuite/test/functionalities/target_var/globals.c new file mode 100644 index 000000000000..266192849641 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/globals.c @@ -0,0 +1,6 @@ +int i = 42; +int *p = &i; + +int main() { + return *p; +} diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll b/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll new file mode 100644 index 000000000000..192d4e126981 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll @@ -0,0 +1,42 @@ +source_filename = "globals.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +@i = global i32 42, align 4 +@p = global i32* @i, align 8, !dbg !0, !dbg !6 + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @main() #0 !dbg !15 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + %0 = load i32*, i32** @p, align 8, !dbg !18 + %1 = load i32, i32* %0, align 4, !dbg !18 + ret i32 %1, !dbg !18 +} + +attributes #0 = { noinline nounwind optnone ssp uwtable } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_deref)) +!1 = distinct !DIGlobalVariable(name: "i", scope: !2, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !5) +!3 = !DIFile(filename: "globals.c", directory: "/") +!4 = !{} +!5 = !{!0, !6} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{i32 7, !"PIC Level", i32 2} +!14 = !{!"clang version 8.0.0 (trunk 340838) (llvm/trunk 340843)"} +!15 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 4, type: !16, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !2, retainedNodes: !4) +!16 = !DISubroutineType(types: !17) +!17 = !{!9} +!18 = !DILocation(line: 5, scope: !15) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile new file mode 100644 index 000000000000..f0bcf9752de2 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +CXXFLAGS += -std=c++11 +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py new file mode 100644 index 000000000000..4e595ea4c5f6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py @@ -0,0 +1,31 @@ +""" +Test that the target.process.thread.max-backtrace-depth setting works. +""" + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BacktraceLimitSettingTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def test_backtrace_depth(self): + """Test that the max-backtrace-depth setting limits backtraces.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand("settings set target.process.thread.max-backtrace-depth 30", result) + self.assertEqual(True, result.Succeeded()) + self.assertEqual(30, thread.GetNumFrames()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp new file mode 100644 index 000000000000..eca1eadc8e45 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp @@ -0,0 +1,13 @@ +int bottom () { + return 1; // Set a breakpoint here +} +int foo(int in) { + if (in > 0) + return foo(--in) + 5; + else + return bottom(); +} +int main() +{ + return foo(500); +} diff --git a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py index b20b738825a2..fa96db06a59d 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py @@ -20,7 +20,6 @@ class CrashDuringStepTestCase(TestBase): TestBase.setUp(self) self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") # IO error due to breakpoint at invalid address @expectedFailureAll(triple=re.compile('^mips')) def test_step_inst_with(self): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py index 3f26d8c76579..2afa77d34b5e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py @@ -23,7 +23,6 @@ class CreateAfterAttachTestCase(TestBase): # Occasionally hangs on Windows, may be same as other issues. @skipIfWindows @skipIfiOSSimulator - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_create_after_attach_with_popen(self): """Test thread creation after process attach.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) @@ -34,7 +33,6 @@ class CreateAfterAttachTestCase(TestBase): @skipIfRemote @skipIfWindows # Windows doesn't have fork. @skipIfiOSSimulator - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_create_after_attach_with_fork(self): """Test thread creation after process attach.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py index c62990ccc93a..76c2c47da2cf 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -23,9 +23,6 @@ class ExitDuringBreakpointTestCase(TestBase): # Find the line number for our breakpoint. self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureAll( - oslist=["linux"], - bugnumber="llvm.org/pr15824 thread states not properly maintained") def test(self): """Test thread exit during breakpoint handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py index 0343a888a0f1..76488a7185de 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -18,6 +18,7 @@ class ExitDuringStepTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test(self): """Test thread exit during step handling.""" self.build(dictionary=self.getBuildFlags()) @@ -27,6 +28,7 @@ class ExitDuringStepTestCase(TestBase): True) @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_step_over(self): """Test thread exit during step-over handling.""" self.build(dictionary=self.getBuildFlags()) @@ -36,6 +38,7 @@ class ExitDuringStepTestCase(TestBase): False) @skipIfFreeBSD # llvm.org/pr21411: test is hanging + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_step_in(self): """Test thread exit during step-in handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py index 3300078e8c60..7194dafe0ac1 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py @@ -17,7 +17,6 @@ class ThreadJumpTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr32343") def test(self): """Test thread jump handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py index cff9b5a8d5e5..3d7e26816f84 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py @@ -32,9 +32,7 @@ class MultipleBreakpointTestCase(TestBase): @expectedFailureAll( oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @skipIfWindows # This is flakey on Windows: llvm.org/pr24668, llvm.org/pr38373 def test(self): """Test simultaneous breakpoints in multiple threads.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py index 724b9d8be907..9aa4a831a745 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py @@ -64,7 +64,7 @@ class NumberOfThreadsTestCase(TestBase): 'Number of expected threads and actual threads do not match.') @skipIfDarwin # rdar://33462362 - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37658") + @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373 def test_unique_stacks(self): """Test backtrace unique with multiple threads executing the same stack.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py index 0cbd94e199dc..4b1247316e18 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py @@ -52,17 +52,6 @@ class ThreadStateTestCase(TestBase): self.thread_state_after_expression_test() # thread states not properly maintained - @unittest2.expectedFailure("llvm.org/pr16712") - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") - @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> - def test_process_interrupt(self): - """Test process interrupt.""" - self.build(dictionary=self.getBuildFlags(use_cpp11=False)) - self.process_interrupt_test() - - # thread states not properly maintained @unittest2.expectedFailure("llvm.org/pr15824 and <rdar://problem/28557237>") @expectedFailureAll( oslist=["windows"], @@ -198,13 +187,19 @@ class ThreadStateTestCase(TestBase): # Let the process run to completion self.runCmd("process continue") - def process_interrupt_test(self): + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") + @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> + @no_debug_info_test + def test_process_interrupt(self): """Test process interrupt and continue.""" + self.build(dictionary=self.getBuildFlags(use_cpp11=False)) exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # This should create a breakpoint in the main thread. - lldbutil.run_break_set_by_file_and_line( + bpno = lldbutil.run_break_set_by_file_and_line( self, "main.cpp", self.break_1, num_expected_locations=1) # Run the program. @@ -218,6 +213,10 @@ class ThreadStateTestCase(TestBase): process, lldb.eStopReasonBreakpoint) self.assertIsNotNone(thread) + # Remove the breakpoint to avoid the single-step-over-bkpt dance in the + # "continue" below + self.assertTrue(target.BreakpointDelete(bpno)) + # Continue, the inferior will go into an infinite loop waiting for # 'g_test' to change. self.dbg.SetAsync(True) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py index 238b18837884..e786e8d7ff1e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py @@ -25,6 +25,7 @@ class ThreadStepOutTestCase(TestBase): @expectedFailureAll( oslist=["freebsd"], bugnumber="llvm.org/pr18066 inferior does not exit") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 @expectedFailureAll(oslist=["windows"]) def test_step_single_thread(self): """Test thread step out on one thread via command interpreter. """ @@ -39,6 +40,7 @@ class ThreadStepOutTestCase(TestBase): @expectedFailureAll( oslist=["freebsd"], bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 @expectedFailureAll(oslist=["windows"]) @expectedFailureAll(oslist=["watchos"], archs=['armv7k'], bugnumber="rdar://problem/34674488") # stop reason is trace when it should be step-out def test_step_all_threads(self): @@ -54,6 +56,7 @@ class ThreadStepOutTestCase(TestBase): @expectedFailureAll( oslist=["freebsd"], bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681") def test_python(self): """Test thread step out on one thread via Python API (dwarf).""" diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py index 07ceb3f5f6b7..c8b6e675b8a9 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py @@ -8,6 +8,7 @@ from __future__ import print_function import os import time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil @@ -25,6 +26,7 @@ class ThreadExitTestCase(TestBase): self.break_3 = line_number('main.cpp', '// Set third breakpoint here') self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here') + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test(self): """Test thread exit handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py index 7302f76c1fbc..a6d77924892b 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py @@ -22,6 +22,7 @@ class MultipleHitsTestCase(TestBase): oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") @skipIf(bugnumber="llvm.org/pr30758", oslist=["linux"], archs=["arm", "aarch64", "powerpc64le"]) + @skipIfwatchOS def test(self): self.build() exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/help/TestHelp.py b/packages/Python/lldbsuite/test/help/TestHelp.py index 2b89b49a6229..7d66b08b86a2 100644 --- a/packages/Python/lldbsuite/test/help/TestHelp.py +++ b/packages/Python/lldbsuite/test/help/TestHelp.py @@ -231,6 +231,17 @@ class HelpCommandTestCase(TestBase): self.expect("help averyfriendlyalias", matching=True, substrs=['I am a very friendly alias']) @no_debug_info_test + def test_alias_prints_origin(self): + """Test that 'help <unique_match_to_alias>' prints the alias origin.""" + def cleanup(): + self.runCmd('command unalias alongaliasname', check=False) + + self.addTearDownHook(cleanup) + self.runCmd('command alias alongaliasname help') + self.expect("help alongaliasna", matching=True, + substrs=["'alongaliasna' is an abbreviation for 'help'"]) + + @no_debug_info_test def test_help_format_output(self): """Test that help output reaches TerminalWidth.""" self.runCmd( diff --git a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py index 930a09412eab..e3ae93d3a5ba 100644 --- a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py +++ b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py @@ -70,7 +70,6 @@ class AnonymousTestCase(TestBase): self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY, substrs=["(type_y) $", "dummy = 2"]) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21550") def test_expr_null(self): self.build() self.common_setup(self.line2) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py index 22b8a2991001..ba924683ad75 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py @@ -116,6 +116,38 @@ class BitfieldsTestCase(TestBase): self.expect("expr/x (packed.c)", VARIABLES_DISPLAYED_CORRECTLY, substrs=['uint32_t', "7112233"]) + for bit in range(1,18): + expected = "1" if bit in [1, 5, 7, 13] else "0" + self.expect("expr even_more_bits.b" + str(bit), VARIABLES_DISPLAYED_CORRECTLY, + substrs=['uint8_t', expected]) + + for bit in [3, 10, 14]: + self.expect("expr even_more_bits.b" + str(bit) + " = 1", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['uint8_t', "1"]) + + self.expect( + "frame variable --show-types even_more_bits", + VARIABLES_DISPLAYED_CORRECTLY, + substrs=[ + '(uint8_t:1) b1 = \'\\x01\'', + '(uint8_t:1) b2 = \'\\0\'', + '(uint8_t:1) b3 = \'\\x01\'', + '(uint8_t:1) b4 = \'\\0\'', + '(uint8_t:1) b5 = \'\\x01\'', + '(uint8_t:1) b6 = \'\\0\'', + '(uint8_t:1) b7 = \'\\x01\'', + '(uint8_t:1) b8 = \'\\0\'', + '(uint8_t:1) b9 = \'\\0\'', + '(uint8_t:1) b10 = \'\\x01\'', + '(uint8_t:1) b12 = \'\\0\'', + '(uint8_t:1) b13 = \'\\x01\'', + '(uint8_t:1) b14 = \'\\x01\'', + '(uint8_t:1) b15 = \'\\0\'', + '(uint8_t:1) b16 = \'\\0\'', + '(uint8_t:1) b17 = \'\\0\'', + ]) + + @add_test_categories(['pyapi']) # BitFields exhibit crashes in record layout on Windows # (http://llvm.org/pr21800) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c index 236c926d81bd..fe972dbbe856 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include <stdint.h> #include <stdio.h> +#include <string.h> int main (int argc, char const *argv[]) { @@ -63,6 +64,20 @@ int main (int argc, char const *argv[]) more_bits.c = 1; more_bits.d = 0; + struct EvenMoreBits + { + uint8_t b1 : 1, b2 : 1, b3 : 1, b4 : 1, b5 : 1, b6 : 1, + b7 : 1, b8 : 1, b9 : 1, b10 : 1, b11 : 1, b12 : 1, + b13 : 1, b14 : 1, b15 : 1, b16 : 1, b17 : 1; + }; + + struct EvenMoreBits even_more_bits; + memset(&even_more_bits, 0, sizeof(even_more_bits)); + even_more_bits.b1 = 1; + even_more_bits.b5 = 1; + even_more_bits.b7 = 1; + even_more_bits.b13 = 1; + #pragma pack(1) struct PackedBits { diff --git a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py index fa14e5ef62e6..b0fde47a2c0b 100644 --- a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py +++ b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py @@ -93,6 +93,7 @@ class TestConflictingSymbols(TestBase): "Multiple internal symbols"]) @expectedFailureAll(bugnumber="llvm.org/pr35043") + @skipIfWindows # This test is "passing" on Windows, but it is a false positive. def test_shadowed(self): self.build() exe = self.getBuildArtifact("a.out") diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py index 576e9ecd52ad..311c5ec8e120 100644 --- a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py +++ b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py @@ -3,9 +3,7 @@ from lldbsuite.test import decorators lldbinline.MakeInlineTest(__file__, globals(), - [decorators.expectedFailureAll(oslist=["windows"], - bugnumber="llvm.org/pr27845"), - decorators.expectedFailureAll(compiler="clang", - compiler_version=["<", - "3.5"], - bugnumber="llvm.org/pr27845")]) + [decorators.expectedFailureAll(compiler="clang", + compiler_version=["<", + "3.5"], + bugnumber="llvm.org/pr27845")]) diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile new file mode 100644 index 000000000000..fd7201886586 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +CFLAGS_EXTRAS += -O1 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py new file mode 100644 index 000000000000..7071b675f3bc --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py @@ -0,0 +1,55 @@ +"""Show local variables and check that they can be inspected. + +This test was added after we made a change in clang to normalize +DW_OP_constu(X < 32) to DW_OP_litX which broke the debugger because +it didn't read the value as an unsigned. +""" + +from __future__ import print_function + + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LocalVariablesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.source = 'main.c' + self.line = line_number( + self.source, '// Set break point at this line.') + + def test_c_local_variables(self): + """Test local variable value.""" + self.build() + + # Create a target by the debugger. + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + # Break inside the main. + lldbutil.run_break_set_by_file_and_line( + self, self.source, self.line, num_expected_locations=1, loc_exact=True) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=[' resolved, hit count = 1']) + + self.expect("frame variable i", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['(unsigned int) i = 10']) diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/main.c b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c new file mode 100644 index 000000000000..2ab579a71a75 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +void bar(unsigned i) +{ + printf("%d\n", i); +} + +void foo(unsigned j) +{ + unsigned i = j; + bar(i); + i = 10; + bar(i); // Set break point at this line. +} + +int main(int argc, char** argv) +{ + foo(argc); +} diff --git a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py index f53a19138356..d1595163f6e3 100644 --- a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py +++ b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py @@ -35,12 +35,10 @@ class SharedLibTestCase(TestBase): "expression GetMeASubFoo(my_foo_ptr)", startstr="(sub_foo *) $") - @expectedFailureAll(oslist=["windows"]) def test_expr(self): """Test that types work when defined in a shared library and forward-declared in the main executable""" self.common_test_expr(True) - @expectedFailureAll(oslist=["windows"]) def test_expr_no_preload(self): """Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled""" self.common_test_expr(False) diff --git a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py index b1c8a5ecf4bf..597a247178e4 100644 --- a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py +++ b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py @@ -11,7 +11,6 @@ class CStringsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): """Tests that C strings work as expected in expressions""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py @@ -1,7 +1,4 @@ from lldbsuite.test import lldbinline from lldbsuite.test import decorators -lldbinline.MakeInlineTest( - __file__, globals(), [ - decorators.expectedFailureAll( - oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py index b2c9bbb83c0f..9eb25e4d1050 100644 --- a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py +++ b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py @@ -9,6 +9,7 @@ class TestUnicodeSymbols(TestBase): mydir = TestBase.compute_mydir(__file__) + @skipIf(compiler="clang", compiler_version=['<', '7.0']) def test_union_members(self): self.build() spec = lldb.SBModuleSpec() diff --git a/packages/Python/lldbsuite/test/lang/c/vla/Makefile b/packages/Python/lldbsuite/test/lang/c/vla/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py new file mode 100644 index 000000000000..f6341ec24fa6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py @@ -0,0 +1,27 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import decorators +import lldbsuite.test.lldbutil as lldbutil + + +class TestVLA(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @decorators.skipIf(compiler="clang", compiler_version=['<', '8.0']) + def test_vla(self): + self.build() + _, process, _, _ = lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec('main.c')) + + def test(a, array): + for i in range(a): + self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)]) + self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)]) + self.expect("frame var vla", substrs=array) + self.expect("expr vla", error=True, substrs=["incomplete"]) + + test(2, ["int []", "[0] = 2, [1] = 1"]) + process.Continue() + test(4, ["int []", "[0] = 4, [1] = 3, [2] = 2, [3] = 1"]) + diff --git a/packages/Python/lldbsuite/test/lang/c/vla/main.c b/packages/Python/lldbsuite/test/lang/c/vla/main.c new file mode 100644 index 000000000000..ba9cc1855607 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/vla/main.c @@ -0,0 +1,15 @@ +void pause() {} + +int foo(int a) { + int vla[a]; + + for (int i = 0; i < a; ++i) + vla[i] = a-i; + + pause(); // break here + return vla[a-1]; +} + +int main (void) { + return foo(2) + foo(4); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py index 9b227bc8d3c8..b6274b3d2669 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py @@ -16,9 +16,6 @@ class CallCPPFunctionTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// breakpoint') - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test calling a function by basename""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py index a344c4f7d18a..080c051de98f 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py @@ -8,7 +8,6 @@ class TestCppChainedCalls(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py index aad2ea20c133..7e67f73b7092 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py @@ -4,6 +4,4 @@ from lldbsuite.test import decorators lldbinline.MakeInlineTest( __file__, globals(), [ decorators.expectedFailureAll( - oslist=["windows"], bugnumber="llvm.org/pr24764"), - decorators.expectedFailureAll( compiler="gcc")]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py index 97b0bfd8aee0..eead3c509ff0 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py @@ -23,7 +23,6 @@ class StaticVariableTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_with_run_command(self): """Test that file and class static variables display correctly.""" self.build() @@ -63,7 +62,6 @@ class StaticVariableTestCase(TestBase): compiler=["clang"], compiler_version=["<", "3.9"], bugnumber='llvm.org/pr20550') - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_with_run_command_complete(self): """ Test that file and class static variables display correctly with @@ -108,8 +106,8 @@ class StaticVariableTestCase(TestBase): compiler=["clang"], compiler_version=["<", "3.9"], bugnumber='llvm.org/pr20550') - @add_test_categories(['pyapi']) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + @add_test_categories(['pyapi']) def test_with_python_api(self): """Test Python APIs on file and class static variables.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py index fa68d0a15021..4ead709cf565 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py @@ -49,7 +49,6 @@ class TestCppGlobalOperators(TestBase): return thread.GetSelectedFrame() - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_equals_operator(self): frame = self.prepare_executable_and_get_frame() @@ -87,7 +86,6 @@ class TestCppGlobalOperators(TestBase): self.assertTrue(got_type.IsPointerType()) self.assertEqual(got_type.GetPointeeType().GetName(), "Struct") - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_operator_new(self): frame = self.prepare_executable_and_get_frame() diff --git a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py index 284caabbc17b..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py +++ b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py @@ -1,7 +1,4 @@ from lldbsuite.test import lldbinline from lldbsuite.test import decorators -lldbinline.MakeInlineTest( - __file__, globals(), [ - lldbinline.expectedFailureAll( - oslist=["windows"])]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py +++ b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py @@ -1,7 +1,4 @@ from lldbsuite.test import lldbinline from lldbsuite.test import decorators -lldbinline.MakeInlineTest( - __file__, globals(), [ - decorators.expectedFailureAll( - oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py index 2837cfd9244e..9c65966b348a 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py @@ -42,11 +42,9 @@ class NamespaceLookupTestCase(TestBase): 'stop reason = breakpoint']) @expectedFailureAll( - oslist=[ - "windows", - "linux", - "freebsd"], + oslist=["freebsd"], bugnumber="llvm.org/pr25819") + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_scope_lookup_with_run_command(self): """Test scope lookup of functions in lldb.""" self.build() @@ -185,6 +183,7 @@ class NamespaceLookupTestCase(TestBase): self.expect("expr -- foo()", startstr="(int) $2 = 42") @unittest2.expectedFailure("lldb file scope lookup bugs") + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_file_scope_lookup_with_run_command(self): """Test file scope lookup in lldb.""" self.build() @@ -204,7 +203,7 @@ class NamespaceLookupTestCase(TestBase): # finds the global ::func(). self.expect("expr -- func()", startstr="(int) $0 = 2") - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr25819") + @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 def test_scope_lookup_before_using_with_run_command(self): """Test scope lookup before using in lldb.""" self.build() @@ -230,10 +229,7 @@ class NamespaceLookupTestCase(TestBase): oslist=["linux"], debug_info=["dwo"]) # Skip to avoid crash @expectedFailureAll( - oslist=[ - "windows", - "linux", - "freebsd"], + oslist=["freebsd"], bugnumber="llvm.org/pr25819") def test_scope_after_using_directive_lookup_with_run_command(self): """Test scope lookup after using directive in lldb.""" @@ -297,10 +293,7 @@ class NamespaceLookupTestCase(TestBase): self.expect("expr -- func()", startstr="error") @expectedFailureAll( - oslist=[ - "windows", - "linux", - "freebsd"], + oslist=["freebsd"], bugnumber="llvm.org/pr25819") def test_scope_lookup_shadowed_by_using_with_run_command(self): """Test scope lookup shadowed by using in lldb.""" diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py index af362f5be5d7..c8308c16011e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py @@ -1,7 +1,4 @@ from lldbsuite.test import lldbinline from lldbsuite.test import decorators -lldbinline.MakeInlineTest( - __file__, globals(), [ - decorators.expectedFailureAll( - oslist=["windows"], bugnumber="llvm.org/pr24764")]) +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py index 7f68eb8923eb..ad969ef3d088 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py @@ -16,9 +16,6 @@ class OverloadedFunctionsTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// breakpoint') - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test that functions with the same name are resolved correctly""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py index cc79366c7149..5e31d93eb163 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py @@ -16,9 +16,6 @@ class RvalueReferencesTestCase(TestBase): @expectedFailureAll( compiler="icc", bugnumber="ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.") - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test that rvalues are supported in the C++ expression parser""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py index c7afeb2dbb6f..213e7fbe9022 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py @@ -15,7 +15,7 @@ class TestCppScopes(TestBase): def test_all_but_c(self): self.do_test(False) - @expectedFailureAll(oslist=["windows"]) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_c(self): self.do_test(True) diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py index 404ef22a0b8c..4b422674134c 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py @@ -16,7 +16,6 @@ class CPPStaticMethodsTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// Break at this line') - @expectedFailureAll(oslist=["windows"]) def test_with_run_command(self): """Test that static methods are properly distinguished from regular methods""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile new file mode 100644 index 000000000000..a42bb089d15a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 +USE_LIBCPP := 1 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py new file mode 100644 index 000000000000..abd35acd15bb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py @@ -0,0 +1,71 @@ +""" +Test stepping into std::function +""" + +from __future__ import print_function + + +import lldb +import sys +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LibCxxFunctionSteppingIntoCallableTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(["libc++"]) + def test(self): + """Test that std::function as defined by libc++ is correctly printed by LLDB""" + self.build() + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.source_foo_line = line_number( + self.main_source, '// Source foo start line') + self.source_lambda_f2_line = line_number( + self.main_source, '// Source lambda used by f2 start line') + self.source_lambda_f3_line = line_number( + self.main_source, '// Source lambda used by f3 start line') + self.source_bar_operator_line = line_number( + self.main_source, '// Source Bar::operator()() start line') + self.source_bar_add_num_line = line_number( + self.main_source, '// Source Bar::add_num start line') + self.source_main_invoking_f1 = line_number( + self.main_source, '// Source main invoking f1') + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "// Set break point at this line.", self.main_source_spec) + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_main_invoking_f1 ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_foo_line ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + process.Continue() + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f2_line ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + process.Continue() + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f3_line ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + process.Continue() + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_operator_line ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + process.Continue() + + thread.StepInto() + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_add_num_line ) ; + self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ; + process.Continue() diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp new file mode 100644 index 000000000000..a85e77db040e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp @@ -0,0 +1,38 @@ +#include <functional> + +int foo(int x, int y) { + return x + y - 1; // Source foo start line +} + +struct Bar { + int operator()() { + return 66 ; // Source Bar::operator()() start line + } + int add_num(int i) const { return i + 3 ; } // Source Bar::add_num start line + int num_ = 0 ; +} ; + +int main (int argc, char *argv[]) +{ + int acc = 42; + std::function<int (int,int)> f1 = foo; + std::function<int (int)> f2 = [acc,f1] (int x) -> int { + return x+f1(acc,x); // Source lambda used by f2 start line + }; + + auto f = [](int x, int y) { return x + y; }; // Source lambda used by f3 start line + auto g = [](int x, int y) { return x * y; } ; + std::function<int (int,int)> f3 = argc %2 ? f : g ; + + Bar bar1 ; + std::function<int ()> f4( bar1 ) ; + std::function<int (const Bar&, int)> f5 = &Bar::add_num; + std::function<int(Bar const&)> f_mem = &Bar::num_; + + return f_mem(bar1) + // Set break point at this line. + f1(acc,acc) + // Source main invoking f1 + f2(acc) + // Set break point at this line. + f3(acc+1,acc+2) + // Set break point at this line. + f4() + // Set break point at this line. + f5(bar1, 10); // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py index 42c372489c63..d11004e66d0a 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py @@ -26,6 +26,7 @@ class STLTestCase(TestBase): self.line = line_number( self.source, '// Set break point at this line.') + @skipIf @expectedFailureAll(bugnumber="llvm.org/PR36713") def test(self): """Test some expressions involving STL data types.""" diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py index 054bc93c3189..8f2ab56488f7 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py +++ b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py @@ -47,7 +47,6 @@ class TemplateArgsTestCase(TestBase): # Get frame for current thread return thread.GetSelectedFrame() - @expectedFailureAll(oslist=["windows"]) def test_integer_args(self): frame = self.prepareProcess() @@ -111,11 +110,9 @@ class TemplateArgsTestCase(TestBase): self.assertTrue(f4.GetType().GetName() == 'int') self.assertTrue(f4.GetValue() == '42') - # Gcc does not generate the necessary DWARF attribute for enum template # parameters. @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc") - @expectedFailureAll(oslist=["windows"]) def test_enum_args(self): frame = self.prepareProcess() diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py index 94d52e368e8c..7fa3f95ae9a7 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py +++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py @@ -52,23 +52,23 @@ class TestCppTypeLookup(TestBase): self.assertTrue(expr_result.GetError().Fail(), "'namespace_only' exists in namespace only") - # Make sure we can find the correct type in a namespace "a" - expr_result = frame.EvaluateExpression("*((a::namespace_only *)&i)") + # Make sure we can find the correct type in a namespace "nsp_a" + expr_result = frame.EvaluateExpression("*((nsp_a::namespace_only *)&i)") self.check_value(expr_result, "a", 123) - # Make sure we can find the correct type in a namespace "b" - expr_result = frame.EvaluateExpression("*((b::namespace_only *)&i)") + # Make sure we can find the correct type in a namespace "nsp_b" + expr_result = frame.EvaluateExpression("*((nsp_b::namespace_only *)&i)") self.check_value(expr_result, "b", 123) # Make sure we can find the correct type in the root namespace expr_result = frame.EvaluateExpression("*((namespace_and_file *)&i)") self.check_value(expr_result, "ff", 123) - # Make sure we can find the correct type in a namespace "a" + # Make sure we can find the correct type in a namespace "nsp_a" expr_result = frame.EvaluateExpression( - "*((a::namespace_and_file *)&i)") + "*((nsp_a::namespace_and_file *)&i)") self.check_value(expr_result, "aa", 123) - # Make sure we can find the correct type in a namespace "b" + # Make sure we can find the correct type in a namespace "nsp_b" expr_result = frame.EvaluateExpression( - "*((b::namespace_and_file *)&i)") + "*((nsp_b::namespace_and_file *)&i)") self.check_value(expr_result, "bb", 123) # Make sure we don't accidentally accept structures that exist only @@ -84,11 +84,11 @@ class TestCppTypeLookup(TestBase): expr_result = frame.EvaluateExpression( "*((contains_type::in_contains_type *)&i)") self.check_value(expr_result, "fff", 123) - # Make sure we can find the correct type in a namespace "a" + # Make sure we can find the correct type in a namespace "nsp_a" expr_result = frame.EvaluateExpression( - "*((a::contains_type::in_contains_type *)&i)") + "*((nsp_a::contains_type::in_contains_type *)&i)") self.check_value(expr_result, "aaa", 123) - # Make sure we can find the correct type in a namespace "b" + # Make sure we can find the correct type in a namespace "nsp_b" expr_result = frame.EvaluateExpression( - "*((b::contains_type::in_contains_type *)&i)") + "*((nsp_b::contains_type::in_contains_type *)&i)") self.check_value(expr_result, "bbb", 123) diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp index b244e80962c8..ae44bfa7c7d5 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp +++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp @@ -11,7 +11,7 @@ // levels in the code and test that we can properly locate these types with // a varienty of different expressions. -namespace a { +namespace nsp_a { struct namespace_only { int a; }; @@ -24,7 +24,7 @@ namespace a { }; }; }; -namespace b { +namespace nsp_b { struct namespace_only { int b; }; @@ -50,12 +50,12 @@ struct contains_type { int main (int argc, char const *argv[]) { - a::namespace_only a_namespace_only = { 1 }; - a::namespace_and_file a_namespace_and_file = { 2 }; - a::contains_type::in_contains_type a_in_contains_type = { 3 }; - b::namespace_only b_namespace_only = { 11 }; - b::namespace_and_file b_namespace_and_file = { 22 }; - b::contains_type::in_contains_type b_in_contains_type = { 33 }; + nsp_a::namespace_only a_namespace_only = { 1 }; + nsp_a::namespace_and_file a_namespace_and_file = { 2 }; + nsp_a::contains_type::in_contains_type a_in_contains_type = { 3 }; + nsp_b::namespace_only b_namespace_only = { 11 }; + nsp_b::namespace_and_file b_namespace_and_file = { 22 }; + nsp_b::contains_type::in_contains_type b_in_contains_type = { 33 }; namespace_and_file file_namespace_and_file = { 44 }; contains_type::in_contains_type file_in_contains_type = { 55 }; int i = 123; // Provide an integer that can be used for casting diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py index 216f86064dca..1a50c9dfc69f 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py +++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py @@ -31,25 +31,16 @@ class UnicodeLiteralsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_expr1(self): """Test that the expression parser returns proper Unicode strings.""" self.build() self.rdar12991846(expr=1) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_expr2(self): """Test that the expression parser returns proper Unicode strings.""" self.build() self.rdar12991846(expr=2) - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_expr3(self): """Test that the expression parser returns proper Unicode strings.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py index b3fe9c40c198..365eb829ba64 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py @@ -36,6 +36,7 @@ class CppVirtualMadness(TestBase): @expectedFailureAll( compiler="icc", bugnumber="llvm.org/pr16808 lldb does not call the correct virtual function with icc.") + @skipIfWindows # This test will hang on windows llvm.org/pr21753 def test_virtual_madness(self): """Test that expression works correctly with virtual inheritance as well as virtual function.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py b/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py deleted file mode 100644 index 963e0676100d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py +++ /dev/null @@ -1,123 +0,0 @@ -"""Test the go expression parser/interpreter.""" - -import os -import time -import unittest2 -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoUserExpression(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @add_test_categories(['pyapi']) - @skipIfRemote # Not remote test suit ready - @skipIfFreeBSD # Test hanging on FreeBSD - llvm.org/pr37194 - @skipUnlessGoInstalled - def test_with_dsym_and_python_api(self): - """Test GoASTUserExpress.""" - self.buildGo() - self.launchProcess() - self.go_expressions() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break inside main(). - self.main_source = "main.go" - self.break_line = line_number( - self.main_source, '// Set breakpoint here.') - - def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin): - tl = self.target().FindTypes(name) - self.assertEqual(1, len(tl)) - t = list(tl)[0] - self.assertEqual(name, t.name) - self.assertEqual(typeclass, t.type) - if size > 0: - self.assertEqual(size, t.size) - - def launchProcess(self): - exe = self.getBuildArtifact("a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - bpt = target.BreakpointCreateByLocation( - self.main_source, self.break_line) - self.assertTrue(bpt, VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt) - - # Make sure we stopped at the first breakpoint. - self.assertTrue( - len(thread_list) != 0, - "No thread stopped at our breakpoint.") - self.assertTrue(len(thread_list) == 1, - "More than one thread stopped at our breakpoint.") - - frame = thread_list[0].GetFrameAtIndex(0) - self.assertTrue(frame, "Got a valid frame 0 frame.") - - def go_expressions(self): - frame = self.frame() - v = frame.EvaluateExpression("1") - self.assertEqual(1, v.GetValueAsSigned()) - x = frame.EvaluateExpression("x") - self.assertEqual(22, x.GetValueAsSigned()) - - a = frame.EvaluateExpression("a") - self.assertEqual(3, a.GetNumChildren()) - a0 = a.GetChildAtIndex(0) - self.assertEqual(8, a0.GetValueAsSigned()) - - # Array indexing - a0 = frame.EvaluateExpression("a[0]") - self.assertEqual(8, a0.GetValueAsSigned()) - - # Slice indexing - b1 = frame.EvaluateExpression("b[1]") - self.assertEqual(9, b1.GetValueAsSigned()) - - # Test global in this package - g = frame.EvaluateExpression("myGlobal") - self.assertEqual(17, g.GetValueAsSigned(), str(g)) - - # Global with package name - g = frame.EvaluateExpression("main.myGlobal") - self.assertEqual(17, g.GetValueAsSigned(), str(g)) - - # Global with quoted package name - g = frame.EvaluateExpression('"main".myGlobal') - self.assertEqual(17, g.GetValueAsSigned(), str(g)) - - # Casting with package local type - s = frame.EvaluateExpression("*(*myStruct)(i.data)") - sb = s.GetChildMemberWithName("a") - self.assertEqual(2, sb.GetValueAsSigned()) - - # casting with explicit package - s = frame.EvaluateExpression("*(*main.myStruct)(i.data)") - sb = s.GetChildMemberWithName("a") - self.assertEqual(2, sb.GetValueAsSigned()) - - # Casting quoted package - s = frame.EvaluateExpression('*(*"main".myStruct)(i.data)') - sb = s.GetChildMemberWithName("b") - self.assertEqual(-1, sb.GetValueAsSigned()) - -if __name__ == '__main__': - import atexit - lldb.SBDebugger.Initialize() - atexit.register(lambda: lldb.SBDebugger.Terminate()) - unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/main.go b/packages/Python/lldbsuite/test/lang/go/expressions/main.go deleted file mode 100644 index c8b97fe07d7d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/expressions/main.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "fmt" - -type myStruct struct { - a, b int -} - -var myGlobal = 17 - -func myFunc(i interface{}) { - a := [...]int{8, 9, 10} - b := a[:] - x := 22 - fmt.Println(a, b, x, i, myGlobal) // Set breakpoint here. -} - -func main() { - s := myStruct {2, -1} - myFunc(s) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py b/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py deleted file mode 100644 index b31ac35be46c..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Test the Go Data Formatter Plugin.""" - -import os -import time -import unittest2 -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoLanguage(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure - @skipIfRemote # Not remote test suite ready - @no_debug_info_test - @skipUnlessGoInstalled - def test_go_formatter_plugin(self): - """Test go data formatters.""" - self.buildGo() - self.launchProcess() - self.check_formatters() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break inside main(). - self.main_source = "main.go" - self.break_line = line_number(self.main_source, '// stop here') - - def launchProcess(self): - exe = self.getBuildArtifact("a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - self.bpt = target.BreakpointCreateByLocation( - self.main_source, self.break_line) - self.assertTrue(self.bpt, VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - thread_list = lldbutil.get_threads_stopped_at_breakpoint( - process, self.bpt) - - # Make sure we stopped at the first breakpoint. - self.assertTrue( - len(thread_list) != 0, - "No thread stopped at our breakpoint.") - self.assertTrue(len(thread_list) == 1, - "More than one thread stopped at our breakpoint.") - - frame = thread_list[0].GetFrameAtIndex(0) - self.assertTrue(frame, "Got a valid frame 0 frame.") - - def check_formatters(self): - a = self.frame().FindVariable('a') - self.assertEqual('(string) a = "my string"', str(a)) - b = self.frame().FindVariable('b') - self.assertEqual( - "([]int) b = (len 2, cap 7) {\n [0] = 0\n [1] = 0\n}", - str(b)) - - -if __name__ == '__main__': - import atexit - lldb.SBDebugger.Initialize() - atexit.register(lambda: lldb.SBDebugger.Terminate()) - unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/main.go b/packages/Python/lldbsuite/test/lang/go/formatters/main.go deleted file mode 100644 index 7956ad66bcb4..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/formatters/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "fmt" - -func main() { - a := "my string" - b := make([]int, 2, 7) - fmt.Println(a, b) // stop here -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py b/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py deleted file mode 100644 index 027fb3adc0cf..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Test the Go OS Plugin.""" - -from __future__ import print_function - - -import os -import time -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoASTContext(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @add_test_categories(['pyapi']) - @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure - @skipIfRemote # Not remote test suite ready - @no_debug_info_test - @skipUnlessGoInstalled - def test_goroutine_plugin(self): - """Test goroutine as threads support.""" - self.buildGo() - self.launchProcess() - self.check_goroutines() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break inside main(). - self.main_source = "main.go" - self.break_line1 = line_number(self.main_source, '// stop1') - self.break_line2 = line_number(self.main_source, '// stop2') - self.break_line3 = line_number(self.main_source, '// stop3') - - def launchProcess(self): - exe = self.getBuildArtifact("a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - self.bpt1 = target.BreakpointCreateByLocation( - self.main_source, self.break_line1) - self.assertTrue(self.bpt1, VALID_BREAKPOINT) - self.bpt2 = target.BreakpointCreateByLocation( - self.main_source, self.break_line2) - self.assertTrue(self.bpt2, VALID_BREAKPOINT) - self.bpt3 = target.BreakpointCreateByLocation( - self.main_source, self.break_line3) - self.assertTrue(self.bpt3, VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - thread_list = lldbutil.get_threads_stopped_at_breakpoint( - process, self.bpt1) - - # Make sure we stopped at the first breakpoint. - self.assertTrue( - len(thread_list) != 0, - "No thread stopped at our breakpoint.") - self.assertTrue(len(thread_list) == 1, - "More than one thread stopped at our breakpoint.") - - frame = thread_list[0].GetFrameAtIndex(0) - self.assertTrue(frame, "Got a valid frame 0 frame.") - - def check_goroutines(self): - self.assertLess(len(self.process().threads), 20) - self.process().Continue() - - # Make sure we stopped at the 2nd breakpoint - thread_list = lldbutil.get_threads_stopped_at_breakpoint( - self.process(), self.bpt2) - self.assertTrue( - len(thread_list) != 0, - "No thread stopped at our breakpoint.") - self.assertTrue(len(thread_list) == 1, - "More than one thread stopped at our breakpoint.") - - # There's (at least) 21 goroutines. - self.assertGreater(len(self.process().threads), 20) - # self.dbg.HandleCommand("log enable lldb os") - - # Now test that stepping works if the memory thread moves to a - # different backing thread. - for i in list(range(11)): - self.thread().StepOver() - self.assertEqual( - lldb.eStopReasonPlanComplete, - self.thread().GetStopReason(), - self.thread().GetStopDescription(100)) - - # Disable the plugin and make sure the goroutines disappear - self.dbg.HandleCommand( - "settings set plugin.os.goroutines.enable false") - self.thread().StepInstruction(False) - self.assertLess(len(self.process().threads), 20) diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go b/packages/Python/lldbsuite/test/lang/go/goroutines/main.go deleted file mode 100644 index bb44f7b8b716..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "fmt" - "runtime" -) - -type philosopher struct { - i int - forks [2]chan bool - eating chan int - done chan struct{} -} - -func (p philosopher) run() { - for { - select { - case <-p.done: - return - case <-p.forks[0]: - p.eat() - } - } -} - -func (p philosopher) eat() { - select { - case <-p.done: - return - case <-p.forks[1]: - p.eating <- p.i - p.forks[0] <- true - p.forks[1] <- true - runtime.Gosched() - } -} - -func startPhilosophers(n int) (chan struct{}, chan int) { - philosophers := make([]*philosopher, n) - chans := make([]chan bool, n) - for i := range chans { - chans[i] = make(chan bool, 1) - chans[i] <- true - } - eating := make(chan int, n) - done := make(chan struct{}) - for i := range philosophers { - var min, max int - if i == n - 1 { - min = 0 - max = i - } else { - min = i - max = i + 1 - } - philosophers[i] = &philosopher{i: i, forks: [2]chan bool{chans[min], chans[max]}, eating: eating, done: done} - go philosophers[i].run() - } - return done, eating -} - -func wait(c chan int) { - fmt.Println(<- c) - runtime.Gosched() -} - -func main() { - // Restrict go to 1 real thread so we can be sure we're seeing goroutines - // and not threads. - runtime.GOMAXPROCS(1) - // Create a bunch of goroutines - done, eating := startPhilosophers(20) // stop1 - // Now turn up the number of threads so this goroutine is likely to get - // scheduled on a different thread. - runtime.GOMAXPROCS(runtime.NumCPU()) // stop2 - // Now let things run. Hopefully we'll bounce around - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - wait(eating) - close(done) - fmt.Println("done") // stop3 -} diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime b/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime deleted file mode 100644 index b06aa656aaa3..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime +++ /dev/null @@ -1,80 +0,0 @@ -"""Test the go dynamic type handling.""" - -import os, time -import unittest2 -import lldb -import lldbutil -from lldbtest import * - -class TestGoLanguageRuntime(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @python_api_test - @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24895') - @skipIfRemote # Not remote test suite ready - @skipUnlessGoInstalled - def test_with_dsym_and_python_api(self): - """Test GoASTContext dwarf parsing.""" - self.buildGo() - self.launchProcess() - self.go_interface_types() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break inside main(). - self.main_source = "main.go" - self.break_line1 = line_number(self.main_source, '// Set breakpoint 1') - self.break_line2 = line_number(self.main_source, '// Set breakpoint 2') - - - def launchProcess(self): - exe = self.getBuildArtifact("a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - bpt1 = target.BreakpointCreateByLocation(self.main_source, self.break_line1) - self.assertTrue(bpt1, VALID_BREAKPOINT) - bpt2 = target.BreakpointCreateByLocation(self.main_source, self.break_line2) - self.assertTrue(bpt2, VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple (None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt1) - - # Make sure we stopped at the first breakpoint. - self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") - self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") - - frame = thread_list[0].GetFrameAtIndex(0) - self.assertTrue (frame, "Got a valid frame 0 frame.") - - def go_interface_types(self): - f = self.frame() - v = f.FindVariable("a", lldb.eDynamicCanRunTarget) - self.assertEqual("*int", v.GetType().name) - self.assertEqual(1, v.Dereference().GetValueAsSigned()) - v = f.FindVariable("b", lldb.eDynamicCanRunTarget) - self.assertEqual("*float64", v.GetType().name) - err = lldb.SBError() - self.assertEqual(2.0, v.Dereference().GetData().GetDouble(err, 0)) - v = f.FindVariable("c", lldb.eDynamicCanRunTarget) - self.assertEqual("*main.SomeFooer", v.GetType().name) - self.assertEqual(9, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) - v = f.FindVariable("d", lldb.eDynamicCanRunTarget) - self.assertEqual("*main.AnotherFooer", v.GetType().name) - self.assertEqual(-1, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) - self.assertEqual(-2, v.Dereference().GetChildAtIndex(1).GetValueAsSigned()) - self.assertEqual(-3, v.Dereference().GetChildAtIndex(2).GetValueAsSigned()) - -if __name__ == '__main__': - import atexit - lldb.SBDebugger.Initialize() - atexit.register(lambda: lldb.SBDebugger.Terminate()) - unittest2.main() diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/main.go b/packages/Python/lldbsuite/test/lang/go/runtime/main.go deleted file mode 100644 index 227c8c377ed7..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/runtime/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import "fmt" - -type Fooer interface { - Foo() int -} - -type SomeFooer struct { - val int -} - -func (s SomeFooer) Foo() int { - return s.val -} - -type AnotherFooer struct { - a, b, c int -} - -func (s AnotherFooer) Foo() int { - return s.a -} - - -func printEface(a, b, c, d interface{}) { - fmt.Println(a, b, c, d) // Set breakpoint 1 -} - -func printIface(a, b Fooer) { - fmt.Println(a, b) // Set breakpoint 2 -} -func main() { - sf := SomeFooer{9} - af := AnotherFooer{-1, -2, -3} - printEface(1,2.0, sf, af) - printIface(sf, af) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py deleted file mode 100644 index 8fb56b9577af..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py +++ /dev/null @@ -1,145 +0,0 @@ -"""Test the go DWARF type parsing.""" - -from __future__ import print_function - - -import os -import time -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestGoASTContext(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @add_test_categories(['pyapi']) - @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure - @skipIfRemote # Not remote test suit ready - @no_debug_info_test - @skipUnlessGoInstalled - @expectedFailureAll(bugnumber="llvm.org/pr33643") - def test_with_dsym_and_python_api(self): - """Test GoASTContext dwarf parsing.""" - self.buildGo() - self.launchProcess() - self.go_builtin_types() - self.check_main_vars() - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break inside main(). - self.main_source = "main.go" - self.break_line = line_number( - self.main_source, '// Set breakpoint here.') - - def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin): - tl = self.target().FindTypes(name) - self.assertEqual(1, len(tl)) - t = list(tl)[0] - self.assertEqual(name, t.name) - self.assertEqual(typeclass, t.type) - if size > 0: - self.assertEqual(size, t.size) - - def launchProcess(self): - exe = self.getBuildArtifact("a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - bpt = target.BreakpointCreateByLocation( - self.main_source, self.break_line) - self.assertTrue(bpt, VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt) - - # Make sure we stopped at the first breakpoint. - self.assertTrue( - len(thread_list) != 0, - "No thread stopped at our breakpoint.") - self.assertTrue(len(thread_list) == 1, - "More than one thread stopped at our breakpoint.") - - frame = thread_list[0].GetFrameAtIndex(0) - self.assertTrue(frame, "Got a valid frame 0 frame.") - - def go_builtin_types(self): - address_size = self.target().GetAddressByteSize() - self.check_builtin('bool') - self.check_builtin('uint8', 1) - self.check_builtin('int8', 1) - self.check_builtin('uint16', 2) - self.check_builtin('int16', 2) - self.check_builtin('uint32', 4) - self.check_builtin('int32', 4) - self.check_builtin('uint64', 8) - self.check_builtin('int64', 8) - self.check_builtin('uintptr', address_size) - self.check_builtin('int', address_size) - self.check_builtin('uint', address_size) - self.check_builtin('float32', 4) - self.check_builtin('float64', 8) - self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat) - self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat) - - def var(self, name): - var = self.frame().FindVariable(name) - self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name)) - return var - - def check_main_vars(self): - v = self.var('theBool') - self.assertEqual('true', v.value) - - v = self.var('theInt') - self.assertEqual('-7', v.value) - - v = self.var('theComplex') - self.assertEqual('1 + 2i', v.value) - - v = self.var('thePointer') - self.assertTrue(v.TypeIsPointerType()) - self.assertEqual('-10', v.Dereference().value) - self.assertEqual(1, v.GetNumChildren()) - self.assertEqual('-10', v.GetChildAtIndex(0).value) - - # print() - # print(os.getpid()) - # time.sleep(60) - v = self.var('theStruct') - if v.TypeIsPointerType(): - v = v.Dereference() - self.assertEqual(2, v.GetNumChildren()) - self.assertEqual('7', v.GetChildAtIndex(0).value) - self.assertEqual('7', v.GetChildMemberWithName('myInt').value) - self.assertEqual( - v.load_addr, - v.GetChildAtIndex(1).GetValueAsUnsigned()) - self.assertEqual(v.load_addr, v.GetChildMemberWithName( - 'myPointer').GetValueAsUnsigned()) - - # Test accessing struct fields through pointers. - v = v.GetChildMemberWithName('myPointer') - self.assertTrue(v.TypeIsPointerType()) - self.assertEqual(2, v.GetNumChildren()) - self.assertEqual('7', v.GetChildAtIndex(0).value) - c = v.GetChildMemberWithName('myPointer') - self.assertTrue(c.TypeIsPointerType()) - self.assertEqual(2, c.GetNumChildren()) - self.assertEqual('7', c.GetChildAtIndex(0).value) - - v = self.var('theArray') - self.assertEqual(5, v.GetNumChildren()) - for i in list(range(5)): - self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value) diff --git a/packages/Python/lldbsuite/test/lang/go/types/main.go b/packages/Python/lldbsuite/test/lang/go/types/main.go deleted file mode 100644 index c74650721d7d..000000000000 --- a/packages/Python/lldbsuite/test/lang/go/types/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import "fmt" - -type Fooer interface { - Foo() int -} - -type SomeFooer struct { - val int -} - -func (s SomeFooer) Foo() int { - return s.val -} - -type mystruct struct { - myInt int - myPointer *mystruct -} - -func main() { - theBool := true - theInt := -7 - theComplex := 1 + 2i - pointee := -10 - thePointer := &pointee - theStruct := &mystruct { myInt: 7} - theStruct.myPointer = theStruct - theArray := [5]byte{1, 2, 3, 4, 5} - theSlice := theArray[1:2] - theString := "abc" - - f := SomeFooer {9} - var theEface interface{} = f - var theFooer Fooer = f - - theChan := make(chan int) - theMap := make(map[int]string) - theMap[1] = "1" - - fmt.Println(theBool) // Set breakpoint here. - // Reference all the variables so the compiler is happy. - fmt.Println(theInt, theComplex, thePointer, theStruct.myInt) - fmt.Println(theArray[0], theSlice[0], theString) - fmt.Println(theEface, theFooer, theChan, theMap) -}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py index 2ba57e61349f..a69e8a7aa1f9 100644 --- a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py +++ b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py @@ -35,7 +35,7 @@ class MixedLanguagesTestCase(TestBase): self.format_string = m.group(1) # Change the default format to print the language. - format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, lang=${language}}\n" + format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{, lang=${language}}\n" self.runCmd("settings set frame-format %s" % format_string) self.expect("settings show frame-format", SETTING_MSG("frame-format"), substrs=[format_string]) diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile new file mode 100644 index 000000000000..261658b10ae8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py new file mode 100644 index 000000000000..92b32504cf20 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py @@ -0,0 +1,205 @@ +# encoding: utf-8 +""" +Test lldb Obj-C exception support. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ObjCExceptionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_objc_exceptions_at_throw(self): + self.build() + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + launch_info = lldb.SBLaunchInfo(["a.out", "0"]) + lldbutil.run_to_name_breakpoint(self, "objc_exception_throw", launch_info=launch_info) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect('thread exception', substrs=[ + '(NSException *) exception = ', + 'name: "ThrownException" - reason: "SomeReason"', + ]) + + target = self.dbg.GetSelectedTarget() + thread = target.GetProcess().GetSelectedThread() + frame = thread.GetSelectedFrame() + + opts = lldb.SBVariablesOptions() + opts.SetIncludeRecognizedArguments(True) + variables = frame.GetVariables(opts) + + self.assertEqual(variables.GetSize(), 1) + self.assertEqual(variables.GetValueAtIndex(0).name, "exception") + + lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.mm"), launch_info=launch_info) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + target = self.dbg.GetSelectedTarget() + thread = target.GetProcess().GetSelectedThread() + frame = thread.GetSelectedFrame() + + # No exception being currently thrown/caught at this point + self.assertFalse(thread.GetCurrentException().IsValid()) + self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) + + self.expect( + 'frame variable e1', + substrs=[ + '(NSException *) e1 = ', + 'name: "ExceptionName" - reason: "SomeReason"' + ]) + + self.expect( + 'frame variable --dynamic-type no-run-target *e1', + substrs=[ + '(NSException) *e1 = ', + 'name = ', '"ExceptionName"', + 'reason = ', '"SomeReason"', + 'userInfo = ', '1 key/value pair', + 'reserved = ', 'nil', + ]) + + e1 = frame.FindVariable("e1") + self.assertTrue(e1) + self.assertEqual(e1.type.name, "NSException *") + self.assertEqual(e1.GetSummary(), 'name: "ExceptionName" - reason: "SomeReason"') + self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName") + self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason") + userInfo = e1.GetChildMemberWithName("userInfo").dynamic + self.assertEqual(userInfo.summary, "1 key/value pair") + self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") + self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") + self.assertEqual(e1.GetChildMemberWithName("reserved").description, "<nil>") + + self.expect( + 'frame variable e2', + substrs=[ + '(NSException *) e2 = ', + 'name: "ThrownException" - reason: "SomeReason"' + ]) + + self.expect( + 'frame variable --dynamic-type no-run-target *e2', + substrs=[ + '(NSException) *e2 = ', + 'name = ', '"ThrownException"', + 'reason = ', '"SomeReason"', + 'userInfo = ', '1 key/value pair', + 'reserved = ', + ]) + + e2 = frame.FindVariable("e2") + self.assertTrue(e2) + self.assertEqual(e2.type.name, "NSException *") + self.assertEqual(e2.GetSummary(), 'name: "ThrownException" - reason: "SomeReason"') + self.assertEqual(e2.GetChildMemberWithName("name").description, "ThrownException") + self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason") + userInfo = e2.GetChildMemberWithName("userInfo").dynamic + self.assertEqual(userInfo.summary, "1 key/value pair") + self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") + self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") + reserved = e2.GetChildMemberWithName("reserved").dynamic + self.assertGreater(reserved.num_children, 0) + callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren()) + if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic + children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)] + + pcs = [i.unsigned for i in children] + names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs] + for n in ["objc_exception_throw", "foo(int)", "main"]: + self.assertTrue(n in names, "%s is in the exception backtrace (%s)" % (n, names)) + + @skipUnlessDarwin + def test_objc_exceptions_at_abort(self): + self.build() + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + self.runCmd("run 0") + + # We should be stopped at pthread_kill because of an unhandled exception + self.expect("thread list", + substrs=['stopped', 'stop reason = signal SIGABRT']) + + self.expect('thread exception', substrs=[ + '(NSException *) exception = ', + 'name: "ThrownException" - reason: "SomeReason"', + 'libobjc.A.dylib`objc_exception_throw', + 'a.out`foo', 'at main.mm:25', + 'a.out`rethrow', 'at main.mm:36', + 'a.out`main', + ]) + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + + # There is an exception being currently processed at this point + self.assertTrue(thread.GetCurrentException().IsValid()) + self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid()) + + history_thread = thread.GetCurrentExceptionBacktrace() + self.assertGreaterEqual(history_thread.num_frames, 4) + for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: + self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) + + self.runCmd("kill") + + self.runCmd("run 1") + # We should be stopped at pthread_kill because of an unhandled exception + self.expect("thread list", + substrs=['stopped', 'stop reason = signal SIGABRT']) + + self.expect('thread exception', substrs=[ + '(MyCustomException *) exception = ', + 'libobjc.A.dylib`objc_exception_throw', + 'a.out`foo', 'at main.mm:27', + 'a.out`rethrow', 'at main.mm:36', + 'a.out`main', + ]) + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + + history_thread = thread.GetCurrentExceptionBacktrace() + self.assertGreaterEqual(history_thread.num_frames, 4) + for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: + self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) + + @skipUnlessDarwin + def test_cxx_exceptions_at_abort(self): + self.build() + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + self.runCmd("run 2") + + # We should be stopped at pthread_kill because of an unhandled exception + self.expect("thread list", + substrs=['stopped', 'stop reason = signal SIGABRT']) + + self.expect('thread exception', substrs=[]) + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + + # C++ exceptions are not exposed in the API (yet). + self.assertFalse(thread.GetCurrentException().IsValid()) + self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm new file mode 100644 index 000000000000..5683882486d8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm @@ -0,0 +1,63 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +#import <exception> +#import <stdexcept> + +@interface MyCustomException: NSException +@end +@implementation MyCustomException +@end + +void foo(int n) +{ + NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil]; + switch (n) { + case 0: + @throw [[NSException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info]; + case 1: + @throw [[MyCustomException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info]; + case 2: + throw std::runtime_error("C++ exception"); + } +} + +void rethrow(int n) +{ + @try { + foo(n); + } @catch(NSException *e) { + @throw; + } +} + +int main(int argc, const char * argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil]; + NSException *e1 = [[NSException alloc] initWithName:@"ExceptionName" reason:@"SomeReason" userInfo:info]; + NSException *e2; + + @try { + foo(atoi(argv[1])); + } @catch(NSException *e) { + e2 = e; + } + + NSLog(@"1"); // Set break point at this line. + + rethrow(atoi(argv[1])); + + [pool drain]; + return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py index 29d386253fb4..e9dbe6af864f 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py @@ -23,8 +23,6 @@ class ModulesInlineFunctionsTestCase(TestBase): def setUp(self): # Call super's setUp(). TestBase.setUp(self) - # Find the line number to break inside main(). - self.line = line_number('main.m', '// Set breakpoint here.') @skipUnlessDarwin @skipIf(macos_version=["<", "10.12"], debug_info=no_match(["gmodules"])) @@ -34,19 +32,8 @@ class ModulesInlineFunctionsTestCase(TestBase): self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # Break inside the foo function which takes a bar_ptr argument. - lldbutil.run_break_set_by_file_and_line( - self, "main.m", self.line, num_expected_locations=1, loc_exact=True) - - self.runCmd("run", RUN_SUCCEEDED) - - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs=['stopped', - 'stop reason = breakpoint']) - - # The breakpoint should have a hit count of 1. - self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, - substrs=[' resolved, hit count = 1']) + lldbutil.run_to_source_breakpoint( + self, '// Set breakpoint here.', lldb.SBFileSpec('main.m')) self.runCmd( "settings set target.clang-module-search-paths \"" + diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h index 20a81faa1017..5ee6acb2425e 100644 --- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h @@ -9,4 +9,4 @@ - (NSString *)description; -@end
\ No newline at end of file +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h index 14ff9eed50fd..d58da600765a 100644 --- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h @@ -8,4 +8,4 @@ - (NSString *)description; -@end
\ No newline at end of file +@end diff --git a/packages/Python/lldbsuite/test/lldbinline.py b/packages/Python/lldbsuite/test/lldbinline.py index bb925ef908f5..c01fef00fe44 100644 --- a/packages/Python/lldbsuite/test/lldbinline.py +++ b/packages/Python/lldbsuite/test/lldbinline.py @@ -195,7 +195,6 @@ def MakeInlineTest(__file, __globals, decorators=None): # Derive the test name from the current file name file_basename = os.path.basename(__file) - InlineTest.mydir = TestBase.compute_mydir(__file) test_name, _ = os.path.splitext(file_basename) @@ -209,4 +208,5 @@ def MakeInlineTest(__file, __globals, decorators=None): # Keep track of the original test filename so we report it # correctly in test results. test_class.test_filename = __file + test_class.mydir = TestBase.compute_mydir(__file) return test_class diff --git a/packages/Python/lldbsuite/test/lldbtest.py b/packages/Python/lldbsuite/test/lldbtest.py index 1b6302ae96a6..161e8c61349d 100644 --- a/packages/Python/lldbsuite/test/lldbtest.py +++ b/packages/Python/lldbsuite/test/lldbtest.py @@ -72,8 +72,7 @@ from lldbsuite.support import encoded_file from lldbsuite.support import funcutils # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables -# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' -# options. +# LLDB_COMMAND_TRACE is set from '-t' option. # By default, traceAlways is False. if "LLDB_COMMAND_TRACE" in os.environ and os.environ[ @@ -740,6 +739,11 @@ class Base(unittest2.TestCase): else: self.lldbMiExec = None + if "LLDBVSCODE_EXEC" in os.environ: + self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] + else: + self.lldbVSCodeExec = None + # If we spawn an lldb process for test (via pexpect), do not load the # init file unless told otherwise. if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: @@ -1215,12 +1219,15 @@ class Base(unittest2.TestCase): if os.path.isfile(src): dst = src.replace(self.log_basename, dst_log_basename) if os.name == "nt" and os.path.isfile(dst): - # On Windows, renaming a -> b will throw an exception if b exists. On non-Windows platforms - # it silently replaces the destination. Ultimately this means that atomic renames are not - # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the - # destination first if it already exists. + # On Windows, renaming a -> b will throw an exception if + # b exists. On non-Windows platforms it silently + # replaces the destination. Ultimately this means that + # atomic renames are not guaranteed to be possible on + # Windows, but we need this to work anyway, so just + # remove the destination first if it already exists. remove_file(dst) + lldbutil.mkdir_p(os.path.dirname(dst)) os.rename(src, dst) else: # success! (and we don't want log files) delete log files @@ -1302,18 +1309,6 @@ class Base(unittest2.TestCase): version = m.group(1) return version - def getGoCompilerVersion(self): - """ Returns a string that represents the go compiler version, or None if go is not found. - """ - compiler = which("go") - if compiler: - version_output = system([[compiler, "version"]])[0] - for line in version_output.split(os.linesep): - m = re.search('go version (devel|go\\S+)', line) - if m: - return m.group(1) - return None - def platformIsDarwin(self): """Returns true if the OS triple for the selected platform is any valid apple OS""" return lldbplatformutil.platformIsDarwin() @@ -1582,12 +1577,6 @@ class Base(unittest2.TestCase): dictionary, testdir, testname): raise Exception("Don't know how to build binary with gmodules") - def buildGo(self): - """Build the default go binary. - """ - exe = self.getBuildArtifact("a.out") - system([[which('go'), 'build -gcflags "-N -l" -o %s main.go' % exe]]) - def signBinary(self, binary_path): if sys.platform.startswith("darwin"): codesign_cmd = "codesign --force --sign \"%s\" %s" % ( @@ -1875,18 +1864,16 @@ class TestBase(Base): # decorators. Base.setUp(self) - if self.child: - # Set the clang modules cache path. - assert(self.getDebugInfo() == 'default') - mod_cache = os.path.join(self.getBuildDir(), "module-cache") - self.runCmd('settings set symbols.clang-modules-cache-path "%s"' - % mod_cache) - - # Disable Spotlight lookup. The testsuite creates - # different binaries with the same UUID, because they only - # differ in the debug info, which is not being hashed. - self.runCmd('settings set symbols.enable-external-lookup false') + # Set the clang modules cache path used by LLDB. + mod_cache = os.path.join(os.path.join(os.environ["LLDB_BUILD"], + "module-cache-lldb")) + self.runCmd('settings set symbols.clang-modules-cache-path "%s"' + % mod_cache) + # Disable Spotlight lookup. The testsuite creates + # different binaries with the same UUID, because they only + # differ in the debug info, which is not being hashed. + self.runCmd('settings set symbols.enable-external-lookup false') if "LLDB_MAX_LAUNCH_COUNT" in os.environ: self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) @@ -2074,8 +2061,17 @@ class TestBase(Base): print("Command '" + cmd + "' failed!", file=sbuf) if check: + output = "" + if self.res.GetOutput(): + output += "\nCommand output:\n" + self.res.GetOutput() + if self.res.GetError(): + output += "\nError output:\n" + self.res.GetError() + if msg: + msg += output + if cmd: + cmd += output self.assertTrue(self.res.Succeeded(), - msg if msg else CMD_MSG(cmd)) + msg if (msg) else CMD_MSG(cmd)) def match( self, @@ -2134,6 +2130,126 @@ class TestBase(Base): return match_object + def check_completion_with_desc(self, str_input, match_desc_pairs): + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + description_strings = lldb.SBStringList() + num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) + self.assertEqual(len(description_strings), len(match_strings)) + + missing_pairs = [] + for pair in match_desc_pairs: + found_pair = False + for i in range(num_matches + 1): + match_candidate = match_strings.GetStringAtIndex(i) + description_candidate = description_strings.GetStringAtIndex(i) + if match_candidate == pair[0] and description_candidate == pair[1]: + found_pair = True + break + if not found_pair: + missing_pairs.append(pair) + + if len(missing_pairs): + error_msg = "Missing pairs:\n" + for pair in missing_pairs: + error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" + error_msg += "Got the following " + str(num_matches) + " completions back:\n" + for i in range(num_matches + 1): + match_candidate = match_strings.GetStringAtIndex(i) + description_candidate = description_strings.GetStringAtIndex(i) + error_msg += "[" + match_candidate + ":" + description_candidate + "]\n" + self.assertEqual(0, len(missing_pairs), error_msg) + + def complete_exactly(self, str_input, patterns): + self.complete_from_to(str_input, patterns, True) + + def complete_from_to(self, str_input, patterns, turn_off_re_match=False): + """Test that the completion mechanism completes str_input to patterns, + where patterns could be a pattern-string or a list of pattern-strings""" + # Patterns should not be None in order to proceed. + self.assertFalse(patterns is None) + # And should be either a string or list of strings. Check for list type + # below, if not, make a list out of the singleton string. If patterns + # is not a string or not a list of strings, there'll be runtime errors + # later on. + if not isinstance(patterns, list): + patterns = [patterns] + + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) + common_match = match_strings.GetStringAtIndex(0) + if num_matches == 0: + compare_string = str_input + else: + if common_match != None and len(common_match) > 0: + compare_string = str_input + common_match + else: + compare_string = "" + for idx in range(1, num_matches+1): + compare_string += match_strings.GetStringAtIndex(idx) + "\n" + + for p in patterns: + if turn_off_re_match: + self.expect( + compare_string, msg=COMPLETION_MSG( + str_input, p, match_strings), exe=False, substrs=[p]) + else: + self.expect( + compare_string, msg=COMPLETION_MSG( + str_input, p, match_strings), exe=False, patterns=[p]) + + def filecheck( + self, + command, + check_file, + filecheck_options = ''): + # Run the command. + self.runCmd( + command, + msg="FileCheck'ing result of `{0}`".format(command)) + + # Get the error text if there was an error, and the regular text if not. + output = self.res.GetOutput() if self.res.Succeeded() \ + else self.res.GetError() + + # Assemble the absolute path to the check file. As a convenience for + # LLDB inline tests, assume that the check file is a relative path to + # a file within the inline test directory. + if check_file.endswith('.pyc'): + check_file = check_file[:-1] + check_file_abs = os.path.abspath(check_file) + + # Run FileCheck. + filecheck_bin = configuration.get_filecheck_path() + if not filecheck_bin: + self.assertTrue(False, "No valid FileCheck executable specified") + filecheck_args = [filecheck_bin, check_file_abs] + if filecheck_options: + filecheck_args.append(filecheck_options) + subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) + cmd_stdout, cmd_stderr = subproc.communicate(input=output) + cmd_status = subproc.returncode + + filecheck_cmd = " ".join(filecheck_args) + filecheck_trace = """ +--- FileCheck trace (code={0}) --- +{1} + +FileCheck input: +{2} + +FileCheck output: +{3} +{4} +""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) + + trace = cmd_status != 0 or traceAlways + with recording(self, trace) as sbuf: + print(filecheck_trace, file=sbuf) + + self.assertTrue(cmd_status == 0) + def expect( self, str, diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py index dc84383333ee..16950d7b5cdb 100644 --- a/packages/Python/lldbsuite/test/lldbutil.py +++ b/packages/Python/lldbsuite/test/lldbutil.py @@ -330,6 +330,20 @@ def sort_stopped_threads(process, # Utility functions for setting breakpoints # ================================================== +def run_break_set_by_script( + test, + class_name, + extra_options=None, + num_expected_locations=1): + """Set a scripted breakpoint. Check that it got the right number of locations.""" + test.assertTrue(class_name is not None, "Must pass in a class name.") + command = "breakpoint set -P " + class_name + if extra_options is not None: + command += " " + extra_options + + break_results = run_break_set_command(test, command) + check_breakpoint_result(test, break_results, num_locations=num_expected_locations) + return get_bpno_from_match(break_results) def run_break_set_by_file_and_line( test, @@ -511,7 +525,7 @@ def run_break_set_command(test, command): patterns = [ r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$", r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.", - r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$", + r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$", r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"] match_object = test.match(command, patterns) break_results = match_object.groupdict() @@ -722,6 +736,8 @@ def is_thread_crashed(test, thread): elif test.getPlatform() == "linux": return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex( 0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV") + elif test.getPlatform() == "windows": + return "Exception 0xc0000005" in thread.GetStopDescription(100) else: return "invalid address" in thread.GetStopDescription(100) @@ -737,7 +753,7 @@ def get_crashed_threads(test, process): # Helper functions for run_to_{source,name}_breakpoint: -def run_to_breakpoint_make_target(test, exe_name, in_cwd): +def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True): if in_cwd: exe = test.getBuildArtifact(exe_name) @@ -746,7 +762,7 @@ def run_to_breakpoint_make_target(test, exe_name, in_cwd): test.assertTrue(target, "Target: %s is not valid."%(exe_name)) return target -def run_to_breakpoint_do_run(test, target, bkpt, launch_info): +def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None): # Launch the process, and do not stop at the entry point. if not launch_info: @@ -819,9 +835,31 @@ def run_to_source_breakpoint(test, bkpt_pattern, source_spec, breakpoint = target.BreakpointCreateBySourceRegex( bkpt_pattern, source_spec, bkpt_module) test.assertTrue(breakpoint.GetNumLocations() > 0, - 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'%(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) + 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"' + %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory())) return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) +def run_to_line_breakpoint(test, source_spec, line_number, column = 0, + launch_info = None, exe_name = "a.out", + bkpt_module = None, + in_cwd = True): + """Start up a target, using exe_name as the executable, and run it to + a breakpoint set by (source_spec, line_number(, column)). + + The rest of the behavior is the same as run_to_name_breakpoint. + """ + + target = run_to_breakpoint_make_target(test, exe_name, in_cwd) + # Set the breakpoints + breakpoint = target.BreakpointCreateByLocation( + source_spec, line_number, column, 0, lldb.SBFileSpecList()) + test.assertTrue(breakpoint.GetNumLocations() > 0, + 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"' + %(source_spec.GetFilename(), line_number, column, + source_spec.GetDirectory())) + return run_to_breakpoint_do_run(test, target, breakpoint, launch_info) + + def continue_to_breakpoint(process, bkpt): """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" process.Continue() diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/Makefile b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile new file mode 100644 index 000000000000..091876d51c35 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp +EXE := StripMe +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules + +main.o: main.cpp + $(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@ diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py new file mode 100644 index 000000000000..ae3b825f95cb --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py @@ -0,0 +1,76 @@ +""" +Test that we read the function starts section. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +exe_name = "StripMe" # Must match Makefile + +class FunctionStartsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @skipIfRemote + @skipUnlessDarwin + def test_function_starts_binary(self): + """Test that we make synthetic symbols when we have the binary.""" + self.build() + self.do_function_starts(False) + + @skipIfRemote + @skipUnlessDarwin + def test_function_starts_no_binary(self): + """Test that we make synthetic symbols when we don't have the binary""" + self.build() + self.do_function_starts(True) + + def do_function_starts(self, in_memory): + """Run the binary, stop at our unstripped function, + make sure the caller has synthetic symbols""" + + exe = self.getBuildArtifact(exe_name) + # Now strip the binary, but leave externals so we can break on dont_strip_me. + try: + fail_str = system([["strip", "-u", "-x", "-S", exe]]) + except CalledProcessError as cmd_error: + self.fail("Strip failed: %d"%(cmd_error.returncode)) + + popen = self.spawnSubprocess(exe) + self.addTearDownHook(self.cleanupSubprocesses) + if in_memory: + remove_file(exe) + + target = self.dbg.CreateTarget(None) + self.assertTrue(target.IsValid(), "Got a vaid empty target.") + error = lldb.SBError() + attach_info = lldb.SBAttachInfo() + attach_info.SetProcessID(popen.pid) + attach_info.SetIgnoreExisting(False) + process = target.Attach(attach_info, error) + self.assertTrue(error.Success(), "Didn't attach successfully to %d: %s"%(popen.pid, error.GetCString())) + + bkpt = target.BreakpointCreateByName("dont_strip_me", exe) + self.assertTrue(bkpt.GetNumLocations() > 0, "Didn't set the dont_strip_me bkpt.") + + threads = lldbutil.continue_to_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.") + + # Our caller frame should have been stripped. Make sure we made a synthetic symbol + # for it: + thread = threads[0] + self.assertTrue(thread.num_frames > 1, "Couldn't backtrace.") + name = thread.frame[1].GetFunctionName() + self.assertEqual("___lldb_unnamed_symbol1$$StripMe", name, "Frame name not synthetic") + + + diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp new file mode 100644 index 000000000000..5a14506d6913 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <fcntl.h> + +#include <chrono> +#include <thread> + +extern void dont_strip_me() +{ + printf("I wasn't stripped\n"); +} + +static void *a_function() +{ + while (1) + { + std::this_thread::sleep_for(std::chrono::microseconds(100)); + dont_strip_me(); + } + return 0; +} + +int main(int argc, char const *argv[]) +{ + a_function(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py new file mode 100644 index 000000000000..1bd5ec020dbe --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py @@ -0,0 +1,38 @@ +""" +Test loading of a kext binary. +""" + +from __future__ import print_function + +import shutil +import struct + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LoadKextTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + #super(LoadKextTestCase, self).setUp() + #self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def test_load_kext(self): + """Test that lldb can load a kext binary.""" + + # Create kext from YAML. + self.yaml2obj("mykext.yaml", self.getBuildArtifact("mykext")) + + target = self.dbg.CreateTarget(self.getBuildArtifact("mykext")) + + self.assertTrue(target.IsValid()) + + self.assertEqual(target.GetNumModules(), 1) + mod = target.GetModuleAtIndex(0) + self.assertEqual(mod.GetFileSpec().GetFilename(), "mykext") diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml new file mode 100644 index 000000000000..ccf016304c84 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml @@ -0,0 +1,222 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000B + ncmds: 7 + sizeofcmds: 520 + flags: 0x00000085 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __TEXT + vmaddr: 0 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 7 + initprot: 5 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000F60 + size: 158 + offset: 0x00000F60 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 4096 + vmsize: 4096 + fileoff: 4096 + filesize: 4096 + maxprot: 7 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x0000000000001000 + size: 220 + offset: 0x00001000 + align: 3 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 800 + maxprot: 7 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8224 + nsyms: 19 + stroff: 8528 + strsize: 464 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 16 + iextdefsym: 16 + nextdefsym: 3 + iundefsym: 19 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 8192 + nlocrel: 4 + - cmd: LC_UUID + cmdsize: 24 + uuid: 17A97B33-09B7-3195-9408-DBD965D578A5 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + version: 0 +LinkEditData: + NameList: + - n_strx: 40 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 141 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 155 + n_type: 0x66 + n_sect: 3 + n_desc: 1 + n_value: 1543540349 + - n_strx: 276 + n_type: 0x20 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 287 + n_type: 0x20 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 298 + n_type: 0x20 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 309 + n_type: 0x20 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 1 + n_type: 0x64 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 325 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 3992 + - n_strx: 333 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4018 + - n_strx: 361 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4035 + - n_strx: 392 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4052 + - n_strx: 417 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4068 + - n_strx: 424 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4296 + - n_strx: 435 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4304 + - n_strx: 446 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4312 + - n_strx: 2 + n_type: 0x0F + n_sect: 2 + n_desc: 0 + n_value: 4096 + - n_strx: 13 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 3936 + - n_strx: 27 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 3968 + StringTable: + - ' ' + - _kmod_info + - _mykext_start + - _mykext_stop + - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/DerivedSources/ + - mykext_info.c + - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/Objects-normal/x86_64/mykext_info.o + - _kmod_info + - __realmain + - __antimain + - __kext_apple_cc + - __start + - _OSKextGetCurrentIdentifier + - _OSKextGetCurrentVersionString + - _OSKextGetCurrentLoadTag + - __stop + - __realmain + - __antimain + - __kext_apple_cc + - '' + - '' +... diff --git a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py index 59b325f57984..287c1c1b87b3 100644 --- a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py +++ b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py @@ -95,7 +95,8 @@ class DarwinNSLogOutputTestCase(TestBase): self.expect(re.compile(r"stop reason = breakpoint")) def runCmd(self, cmd): - self.child.sendline(cmd) + if self.child: + self.child.sendline(cmd) def expect_prompt(self, exactly=True): self.expect(self.child_prompt, exactly=exactly) diff --git a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py index ba58372ce5b7..cdc9606c377a 100644 --- a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py +++ b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py @@ -18,10 +18,16 @@ class TestQueues(TestBase): @skipUnlessDarwin @add_test_categories(['pyapi']) - def test_with_python_api(self): + def test_with_python_api_queues(self): """Test queues inspection SB APIs.""" self.build() self.queues() + + @skipUnlessDarwin + @add_test_categories(['pyapi']) + def test_with_python_api_queues_with_backtrace(self): + """Test queues inspection SB APIs.""" + self.build() self.queues_with_libBacktraceRecording() def setUp(self): @@ -113,7 +119,7 @@ class TestQueues(TestBase): break1 = target.BreakpointCreateByName("stopper", 'a.out') self.assertTrue(break1, VALID_BREAKPOINT) process = target.LaunchSimple( - None, None, self.get_process_working_directory()) + [], None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1) if len(threads) != 1: @@ -267,10 +273,14 @@ class TestQueues(TestBase): self.assertTrue(break1, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. + libbtr_path = "/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib" + if self.getArchitecture() in ['arm', 'arm64', 'arm64e', 'arm64_32', 'armv7', 'armv7k']: + libbtr_path = "/Developer/usr/lib/libBacktraceRecording.dylib" + process = target.LaunchSimple( - None, + [], [ - 'DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib', + 'DYLD_INSERT_LIBRARIES=%s' % (libbtr_path), 'DYLD_LIBRARY_PATH=/usr/lib/system/introspection'], self.get_process_working_directory()) diff --git a/packages/Python/lldbsuite/test/macosx/queues/main.c b/packages/Python/lldbsuite/test/macosx/queues/main.c index 715a3f3af52c..3978b92bff1a 100644 --- a/packages/Python/lldbsuite/test/macosx/queues/main.c +++ b/packages/Python/lldbsuite/test/macosx/queues/main.c @@ -1,13 +1,18 @@ -#include <stdio.h> +#include <stdatomic.h> +#include <string.h> #include <unistd.h> #include <dispatch/dispatch.h> #include <pthread.h> -int finished_enqueueing_work = 0; +atomic_int finished_enqueueing_work = 0; +atomic_int thread_count = 0; void doing_the_work_1(void *in) { + // This is only counted once because the first job in the queue + // starves all the others. + atomic_fetch_add(&thread_count, 1); while (1) sleep (1); } @@ -26,13 +31,15 @@ submit_work_1b(void *in) dispatch_queue_t *work_performer_1 = (dispatch_queue_t*) in; dispatch_async_f (*work_performer_1, NULL, doing_the_work_1); dispatch_async_f (*work_performer_1, NULL, doing_the_work_1); + atomic_fetch_add(&thread_count, 1); while (1) - sleep (1); + sleep (1); } void doing_the_work_2(void *in) { + atomic_fetch_add(&thread_count, 1); while (1) sleep (1); } @@ -42,20 +49,22 @@ submit_work_2(void *in) { dispatch_queue_t *work_performer_2 = (dispatch_queue_t*) in; int i = 0; - while (i++ < 5000) + while (i++ < 5000) { dispatch_async_f (*work_performer_2, NULL, doing_the_work_2); dispatch_async_f (*work_performer_2, NULL, doing_the_work_2); } - finished_enqueueing_work = 1; + atomic_fetch_add(&finished_enqueueing_work, 1); } void doing_the_work_3(void *in) { + // This counts four times, since the queue is marked as CONCURRENT. + atomic_fetch_add(&thread_count, 1); while (1) - sleep(1); + sleep (1); } void @@ -77,7 +86,7 @@ stopper () } -int main () +int main (int argc, const char **argv) { dispatch_queue_t work_submittor_1 = dispatch_queue_create ("com.apple.work_submittor_1", DISPATCH_QUEUE_SERIAL); dispatch_queue_t work_submittor_2 = dispatch_queue_create ("com.apple.work_submittor_and_quit_2", DISPATCH_QUEUE_SERIAL); @@ -97,41 +106,46 @@ int main () // Spin up threads with each of the different libdispatch QoS values. - dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ pthread_setname_np ("user initiated QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{ pthread_setname_np ("user interactive QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); dispatch_async (dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ pthread_setname_np ("default QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); dispatch_async (dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ pthread_setname_np ("utility QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); dispatch_async (dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ pthread_setname_np ("background QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); dispatch_async (dispatch_get_global_queue(QOS_CLASS_UNSPECIFIED, 0), ^{ pthread_setname_np ("unspecified QoS"); + atomic_fetch_add(&thread_count, 1); while (1) sleep (10); - }); + }); - - while (finished_enqueueing_work == 0) + // Unfortunately there is no pthread_barrier on darwin. + while ((atomic_load(&thread_count) < 13) || (finished_enqueueing_work == 0)) sleep (1); - stopper (); + stopper (); } diff --git a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c index 613384ff73b3..586500876288 100644 --- a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c +++ b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c @@ -1,3 +1,4 @@ +#include <sys/time.h> // work around module map issue with iOS sdk, <rdar://problem/35159346> #include <sys/select.h> #include <stdio.h> #include <pthread.h> diff --git a/packages/Python/lldbsuite/test/macosx/universal/Makefile b/packages/Python/lldbsuite/test/macosx/universal/Makefile index d74ed26f50ab..a83de2a6c7e6 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/Makefile +++ b/packages/Python/lldbsuite/test/macosx/universal/Makefile @@ -1,21 +1,25 @@ -CC ?= clang +LEVEL := ../../make + +EXE := testit + +include $(LEVEL)/Makefile.rules all: testit -testit: testit.i386 testit.x86_64 +testit: testit.x86_64h testit.x86_64 lipo -create -o testit $^ -testit.i386: testit.i386.o - $(CC) -arch i386 -o testit.i386 $< +testit.x86_64h: testit.x86_64h.o + $(CC) -arch x86_64h -o testit.x86_64h $< testit.x86_64: testit.x86_64.o $(CC) -arch x86_64 -o testit.x86_64 $< -testit.i386.o: main.c - $(CC) -g -O0 -arch i386 -c -o testit.i386.o $< +testit.x86_64h.o: main.c + $(CC) -g -O0 -arch x86_64h -c -o testit.x86_64h.o $< testit.x86_64.o: main.c $(CC) -g -O0 -arch x86_64 -c -o testit.x86_64.o $< -clean: +clean:: rm -rf $(wildcard testit* *~) diff --git a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py index ca4f3ce9b137..93fb358f4c84 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py +++ b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py @@ -11,9 +11,13 @@ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +def haswellOrLater(): + features = subprocess.check_output(["sysctl", "machdep.cpu"]) + return "AVX2" in features.split() class UniversalTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True mydir = TestBase.compute_mydir(__file__) def setUp(self): @@ -24,8 +28,8 @@ class UniversalTestCase(TestBase): @add_test_categories(['pyapi']) @skipUnlessDarwin - @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ - 'i386', 'x86_64'], "requires i386 or x86_64") + @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in + ['x86_64'], "requires x86_64") @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system def test_sbdebugger_create_target_with_file_and_target_triple(self): """Test the SBDebugger.CreateTargetWithFileAndTargetTriple() API.""" @@ -37,8 +41,9 @@ class UniversalTestCase(TestBase): # Create a target by the debugger. target = self.dbg.CreateTargetWithFileAndTargetTriple( - exe, "i386-apple-macosx") + exe, "x86_64-apple-macosx") self.assertTrue(target, VALID_TARGET) + self.expect("image list -A -b", substrs=["x86_64 testit"]) # Now launch the process, and do not stop at entry point. process = target.LaunchSimple( @@ -46,13 +51,16 @@ class UniversalTestCase(TestBase): self.assertTrue(process, PROCESS_IS_VALID) @skipUnlessDarwin - @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ - 'i386', 'x86_64'], "requires i386 or x86_64") + @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in + ['x86_64'], "requires x86_64") @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system def test_process_launch_for_universal(self): """Test process launch of a universal binary.""" from lldbsuite.test.lldbutil import print_registers + if not haswellOrLater(): + return + # Invoke the default build rule. self.build() @@ -62,69 +70,54 @@ class UniversalTestCase(TestBase): # By default, x86_64 is assumed if no architecture is specified. self.expect("file " + exe, CURRENT_EXECUTABLE_SET, startstr="Current executable set to ", - substrs=["testit' (x86_64)."]) + substrs=["testit' (x86_64h)."]) # Break inside the main. lldbutil.run_break_set_by_file_and_line( self, "main.c", self.line, num_expected_locations=1, loc_exact=True) - # We should be able to launch the x86_64 executable. + # We should be able to launch the x86_64h executable. self.runCmd("run", RUN_SUCCEEDED) - # Check whether we have a 64-bit process launched. + # Check whether we have a x86_64h process launched. target = self.dbg.GetSelectedTarget() process = target.GetProcess() - self.assertTrue(target and process and - self.invoke(process, 'GetAddressByteSize') == 8, - "64-bit process launched") - - frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0) - registers = print_registers(frame, string_buffer=True) - self.expect(registers, exe=False, - substrs=['Name: rax']) - + self.expect("image list -A -b", substrs=["x86_64h testit"]) self.runCmd("continue") - # Now specify i386 as the architecture for "testit". - self.expect("file -a i386 " + exe, CURRENT_EXECUTABLE_SET, + # Now specify x86_64 as the architecture for "testit". + self.expect("file -a x86_64 " + exe, CURRENT_EXECUTABLE_SET, startstr="Current executable set to ", - substrs=["testit' (i386)."]) + substrs=["testit' (x86_64)."]) # Break inside the main. lldbutil.run_break_set_by_file_and_line( self, "main.c", self.line, num_expected_locations=1, loc_exact=True) - # We should be able to launch the i386 executable as well. + # We should be able to launch the x86_64 executable as well. self.runCmd("run", RUN_SUCCEEDED) - # Check whether we have a 32-bit process launched. - target = self.dbg.GetSelectedTarget() - process = target.GetProcess() - self.assertTrue(target and process, - "32-bit process launched") - - pointerSize = self.invoke(process, 'GetAddressByteSize') - self.assertTrue( - pointerSize == 4, - "AddressByteSize of 32-bit process should be 4, got %d instead." % - pointerSize) - - frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0) - registers = print_registers(frame, string_buffer=True) - self.expect(registers, exe=False, - substrs=['Name: eax']) - + # Check whether we have a x86_64 process launched. + + # FIXME: This wrong. We are expecting x86_64, but spawning a + # new process currently doesn't allow specifying a *sub*-architecture. + # <rdar://problem/46101466> + self.expect("image list -A -b", substrs=["x86_64h testit"]) self.runCmd("continue") @skipUnlessDarwin - @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [ - 'i386', 'x86_64'], "requires i386 or x86_64") + @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in + ['x86_64'], "requires x86_64") @skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system def test_process_attach_with_wrong_arch(self): - """Test that when we attach to a binary from the wrong fork of a universal binary, we fix up the ABI correctly.""" - # Now keep the architecture at 32 bit, but switch the binary we launch to - # 64 bit, and make sure on attach we switch to the correct - # architecture. + """Test that when we attach to a binary from the wrong fork of + a universal binary, we fix up the ABI correctly.""" + if not haswellOrLater(): + return + + # Now keep the architecture at x86_64, but switch the binary + # we launch to x86_64h, and make sure on attach we switch to + # the correct architecture. # Invoke the default build rule. self.build() @@ -134,10 +127,9 @@ class UniversalTestCase(TestBase): # Create a target by the debugger. target = self.dbg.CreateTargetWithFileAndTargetTriple( - exe, "i386-apple-macosx") + exe, "x86_64-apple-macosx") self.assertTrue(target, VALID_TARGET) - pointer_size = target.GetAddressByteSize() - self.assertTrue(pointer_size == 4, "Initially we were 32 bit.") + self.expect("image list -A -b", substrs=["x86_64 testit"]) bkpt = target.BreakpointCreateBySourceRegex( "sleep", lldb.SBFileSpec("main.c")) @@ -155,14 +147,14 @@ class UniversalTestCase(TestBase): empty_listener, popen.pid, error) self.assertTrue(error.Success(), "Attached to process.") - pointer_size = target.GetAddressByteSize() - self.assertTrue(pointer_size == 8, "We switched to 64 bit.") + self.expect("image list -A -b", substrs=["x86_64h testit"]) - # It may seem odd that I am checking the number of frames, but the bug that - # motivated this test was that we eventually fixed the architecture, but we - # left the ABI set to the original value. In that case, if you asked the - # process for its architecture, it would look right, but since the ABI was - # wrong, backtracing failed. + # It may seem odd to check the number of frames, but the bug + # that motivated this test was that we eventually fixed the + # architecture, but we left the ABI set to the original value. + # In that case, if you asked the process for its architecture, + # it would look right, but since the ABI was wrong, + # backtracing failed. threads = lldbutil.continue_to_breakpoint(process, bkpt) self.assertTrue(len(threads) == 1) diff --git a/packages/Python/lldbsuite/test/make/Makefile.rules b/packages/Python/lldbsuite/test/make/Makefile.rules index 32f41b24d5dc..a2dc6cc66595 100644 --- a/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/packages/Python/lldbsuite/test/make/Makefile.rules @@ -29,10 +29,10 @@ # SHELL = /bin/sh -x SRCDIR := $(shell dirname $(firstword $(MAKEFILE_LIST)))/ +BUILDDIR := $(shell pwd) THIS_FILE_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))/ LLDB_BASE_DIR := $(THIS_FILE_DIR)../../../../../ - #---------------------------------------------------------------------- # If OS is not defined, use 'uname -s' to determine the OS name. # @@ -50,6 +50,33 @@ ifeq "$(OS)" "" endif #---------------------------------------------------------------------- +# If OS is Windows, force SHELL to be cmd +# +# Some versions of make on Windows will search for other shells such as +# C:\cygwin\bin\sh.exe. This shell fails for numerous different reasons +# so default to using cmd.exe. +#---------------------------------------------------------------------- +ifeq "$(OS)" "Windows_NT" + SHELL = $(WINDIR)\system32\cmd.exe +endif + +#---------------------------------------------------------------------- +# If the OS is Windows use double-quotes in commands +# +# For other operating systems, single-quotes work fine, but on Windows +# we strictly required double-quotes +#---------------------------------------------------------------------- +ifeq "$(HOST_OS)" "Windows_NT" + JOIN_CMD = & + QUOTE = " + FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = " +else + JOIN_CMD = ; + QUOTE = ' + FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = ' +endif + +#---------------------------------------------------------------------- # If TRIPLE is not defined try to set the ARCH, CC, CFLAGS, and more # from the triple alone #---------------------------------------------------------------------- @@ -63,7 +90,8 @@ ifneq "$(TRIPLE)" "" TRIPLE_VERSION =$(word 2, $(triple_os_and_version)) ifeq "$(TRIPLE_VENDOR)" "apple" ifeq "$(TRIPLE_OS)" "ios" - ifeq "$(SDKROOT)" "" + CODESIGN := codesign + ifeq "$(SDKROOT)" "" # Set SDKROOT if it wasn't set ifneq (,$(findstring arm,$(ARCH))) SDKROOT = $(shell xcrun --sdk iphoneos --show-sdk-path) @@ -81,7 +109,8 @@ ifneq "$(TRIPLE)" "" endif endif ifeq "$(TRIPLE_OS)" "watchos" - ifeq "$(SDKROOT)" "" + CODESIGN := codesign + ifeq "$(SDKROOT)" "" # Set SDKROOT if it wasn't set ifneq (,$(findstring arm,$(ARCH))) SDKROOT = $(shell xcrun --sdk watchos --show-sdk-path) @@ -228,6 +257,12 @@ endif CFLAGS += -I$(SRCDIR) -include $(THIS_FILE_DIR)test_common.h -I$(THIS_FILE_DIR) CFLAGS += $(NO_LIMIT_DEBUG_INFO_FLAGS) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS) +# If the OS is Windows, we need to pass -gdwarf to clang, otherwise it will build +# with codeview by default but all the tests rely on dwarf. +ifeq "$(OS)" "Windows_NT" + CFLAGS += -gdwarf +endif + # Use this one if you want to build one part of the result without debug information: ifeq "$(OS)" "Darwin" CFLAGS_NO_DEBUG = -O0 $(ARCHFLAG) $(ARCH) $(FRAMEWORK_INCLUDES) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS) @@ -239,12 +274,22 @@ ifeq "$(MAKE_DWO)" "YES" CFLAGS += -gsplit-dwarf endif -CLANG_MODULE_CACHE_DIR := module-cache +# Use a shared module cache when building in the default test build directory. +CLANG_MODULE_CACHE_DIR := $(shell echo "$(BUILDDIR)" | sed $(QUOTE)s/lldb-test-build.noindex.*/lldb-test-build.noindex\/module-cache-clang/$(QUOTE)) + +ifeq "$(findstring lldb-test-build.noindex, $(BUILDDIR))" "" +CLANG_MODULE_CACHE_DIR := $(BUILDDIR)/module-cache +$(warning failed to set the shared clang module cache dir) +endif MANDATORY_MODULE_BUILD_CFLAGS := -fmodules -gmodules -fmodules-cache-path=$(CLANG_MODULE_CACHE_DIR) ifeq "$(MAKE_GMODULES)" "YES" CFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS) + CXXFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS) + ifeq "$(OS)" "Darwin" + CXXFLAGS += -fcxx-modules + endif endif CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS) @@ -315,7 +360,7 @@ ifneq "$(OS)" "Darwin" endif ifdef PIE - LDFLAGS += -pie + LDFLAGS += -pie endif #---------------------------------------------------------------------- @@ -380,17 +425,17 @@ ifneq "$(strip $(DYLIB_OBJC_SOURCES))" "" endif ifneq "$(strip $(DYLIB_CXX_SOURCES))" "" - DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o)) - CXX = $(call cxx_compiler,$(CC)) - LD = $(call cxx_linker,$(CC)) + DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o)) + CXX = $(call cxx_compiler,$(CC)) + LD = $(call cxx_linker,$(CC)) endif #---------------------------------------------------------------------- # Check if we have a precompiled header #---------------------------------------------------------------------- ifneq "$(strip $(PCH_CXX_SOURCE))" "" - PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch) - PCHFLAGS = -include $(PCH_CXX_SOURCE) + PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch) + PCHFLAGS = -include $(PCH_CXX_SOURCE) endif #---------------------------------------------------------------------- @@ -472,21 +517,21 @@ ifneq "$(strip $(CXX_SOURCES) $(OBJCXX_SOURCES))" "" ifneq "$(filter g++,$(CXX))" "" CXXVERSION = $(shell $(CXX) -dumpversion | cut -b 1-3) ifeq "$(CXXVERSION)" "4.6" - # GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x - # instead. FIXME: remove once GCC version is upgraded. + # GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x + # instead. FIXME: remove once GCC version is upgraded. override CXXFLAGS := $(subst -std=c++11,-std=c++0x,$(CXXFLAGS)) endif endif endif ifeq ($(findstring clang, $(CXX)), clang) - CXXFLAGS += --driver-mode=g++ + CXXFLAGS += --driver-mode=g++ endif ifneq "$(CXX)" "" - ifeq ($(findstring clang, $(LD)), clang) - LDFLAGS += --driver-mode=g++ - endif + ifeq ($(findstring clang, $(LD)), clang) + LDFLAGS += --driver-mode=g++ + endif endif #---------------------------------------------------------------------- @@ -508,6 +553,9 @@ endif else $(EXE) : $(OBJECTS) $(ARCHIVE_NAME) $(LD) $(OBJECTS) $(LDFLAGS) $(ARCHIVE_NAME) -o "$(EXE)" +ifneq "$(CODESIGN)" "" + $(CODESIGN) -s - "$(EXE)" +endif endif #---------------------------------------------------------------------- @@ -552,6 +600,9 @@ endif $(DYLIB_FILENAME) : $(DYLIB_OBJECTS) ifeq "$(OS)" "Darwin" $(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -install_name "$(DYLIB_EXECUTABLE_PATH)/$(DYLIB_FILENAME)" -dynamiclib -o "$(DYLIB_FILENAME)" +ifneq "$(CODESIGN)" "" + $(CODESIGN) -s - "$(DYLIB_FILENAME)" +endif ifneq "$(MAKE_DSYM)" "NO" ifneq "$(DS)" "" "$(DS)" $(DSFLAGS) "$(DYLIB_FILENAME)" @@ -594,14 +645,6 @@ endif # the compiler -MM option. The -M option will list all system headers, # and the -MM option will list all non-system dependencies. #---------------------------------------------------------------------- -ifeq "$(HOST_OS)" "Windows_NT" - JOIN_CMD = & - QUOTE = " -else - JOIN_CMD = ; - QUOTE = ' -endif - %.d: %.c @rm -f $@ $(JOIN_CMD) \ $(CC) -M $(CFLAGS) $< > $@.tmp && \ diff --git a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py index 8a9e456f3458..f5d143fbd40b 100644 --- a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py +++ b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py @@ -119,7 +119,6 @@ class EventAPITestCase(TestBase): @add_test_categories(['pyapi']) @expectedFlakeyLinux("llvm.org/pr23730") # Flaky, fails ~1/100 cases - @expectedFlakeyOS(oslist=["windows"]) def test_wait_for_event(self): """Exercise SBListener.WaitForEvent() API.""" self.build() @@ -198,7 +197,6 @@ class EventAPITestCase(TestBase): @expectedFailureAll( oslist=["linux"], bugnumber="llvm.org/pr23617 Flaky, fails ~1/10 cases") - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_add_listener_to_broadcaster(self): """Exercise some SBBroadcaster APIs.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py index 85e915ad3a48..fc2f03f9e617 100644 --- a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py +++ b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py @@ -20,7 +20,6 @@ class FrameAPITestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_get_arg_vals_for_call_stack(self): """Exercise SBFrame.GetVariables() API to get argument vals.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py index b0f09d2fa7b5..33f4a790aacf 100644 --- a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py +++ b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py @@ -10,8 +10,7 @@ import time import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - +import lldbsuite.test.lldbutil as lldbutil class HelloWorldTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @@ -35,7 +34,7 @@ class HelloWorldTestCase(TestBase): def test_with_process_launch_api(self): """Create target, breakpoint, launch a process, and then kill it.""" # Get the full path to our executable to be attached/debugged. - exe = self.getBuildArtifact(self.testMethodName) + exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid()) d = {'EXE': exe} self.build(dictionary=d) self.setTearDownCleanup(dictionary=d) @@ -77,23 +76,22 @@ class HelloWorldTestCase(TestBase): self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE) @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600") @skipIfiOSSimulator - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails def test_with_attach_to_process_with_id_api(self): """Create target, spawn a process, and attach to it with process id.""" - exe = self.getBuildArtifact(self.testMethodName) + exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid()) d = {'EXE': exe} self.build(dictionary=d) self.setTearDownCleanup(dictionary=d) target = self.dbg.CreateTarget(exe) # Spawn a new process - popen = self.spawnSubprocess(exe, ["abc", "xyz"]) + token = exe+'.token' + if os.path.exists(token): + os.remove(token) + popen = self.spawnSubprocess(exe, [token]) self.addTearDownHook(self.cleanupSubprocesses) - - # Give the subprocess time to start and wait for user input - time.sleep(0.25) + lldbutil.wait_for_file_on_target(self, token) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() @@ -102,30 +100,29 @@ class HelloWorldTestCase(TestBase): self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # Let's check the stack traces of the attached process. - import lldbsuite.test.lldbutil as lldbutil stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) self.expect(stacktraces, exe=False, substrs=['main.c:%d' % self.line2, - '(int)argc=3']) + '(int)argc=2']) @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600") @skipIfiOSSimulator - @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails + @skipIfSanitized # FIXME: Hangs indefinitely. def test_with_attach_to_process_with_name_api(self): """Create target, spawn a process, and attach to it with process name.""" - exe = self.getBuildArtifact(self.testMethodName) + exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid()) d = {'EXE': exe} self.build(dictionary=d) self.setTearDownCleanup(dictionary=d) target = self.dbg.CreateTarget(exe) - # Spawn a new process - popen = self.spawnSubprocess(exe, ["abc", "xyz"]) + # Spawn a new process. + token = exe+'.token' + if os.path.exists(token): + os.remove(token) + popen = self.spawnSubprocess(exe, [token]) self.addTearDownHook(self.cleanupSubprocesses) - - # Give the subprocess time to start and wait for user input - time.sleep(0.25) + lldbutil.wait_for_file_on_target(self, token) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() @@ -140,7 +137,6 @@ class HelloWorldTestCase(TestBase): target.ConnectRemote(listener, None, None, error) process = target.AttachToProcessWithName(listener, name, False, error) - self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # Verify that after attach, our selected target indeed matches name. @@ -150,8 +146,7 @@ class HelloWorldTestCase(TestBase): startstr=name) # Let's check the stack traces of the attached process. - import lldbsuite.test.lldbutil as lldbutil stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) self.expect(stacktraces, exe=False, substrs=['main.c:%d' % self.line2, - '(int)argc=3']) + '(int)argc=2']) diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/main.c b/packages/Python/lldbsuite/test/python_api/hello_world/main.c index 32b0446517c5..c516f923614f 100644 --- a/packages/Python/lldbsuite/test/python_api/hello_world/main.c +++ b/packages/Python/lldbsuite/test/python_api/hello_world/main.c @@ -8,16 +8,22 @@ int main(int argc, char const *argv[]) { - lldb_enable_attach(); + lldb_enable_attach(); - printf("Hello world.\n"); // Set break point at this line. - if (argc == 1) - return 0; + printf("Hello world.\n"); // Set break point at this line. + if (argc == 1) + return 1; - // Waiting to be attached by the debugger, otherwise. - char line[100]; - while (1) - sleep (1); // Waiting to be attached... + // Create the synchronization token. + FILE *f; + if (f = fopen(argv[1], "wx")) { + fputs("\n", f); + fflush(f); + fclose(f); + } else + return 1; - printf("Exiting now\n"); + // Waiting to be attached by the debugger, otherwise. + while (1) + sleep(1); // Waiting to be attached... } diff --git a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp index 79aa2d0452f4..b38208ce2a35 100644 --- a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp +++ b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp @@ -51,4 +51,4 @@ int main (int argc, char const *argv[]) g.unique_function_name(); g.unique_function_name(argc); return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp index 650d87acd6e6..c54339f3bba6 100644 --- a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp @@ -11,4 +11,4 @@ int main() { f(); // break here f(); // break here return 0; -}
\ No newline at end of file +} diff --git a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py index 8a4af0cc2b94..2299f1f1432d 100644 --- a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py +++ b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py @@ -153,6 +153,9 @@ class ValueAPITestCase(TestBase): val_s = target.EvaluateExpression('s') val_a = target.EvaluateExpression('a') self.assertTrue( + val_s.GetChildMemberWithName('a').GetAddress().IsValid(), + VALID_VARIABLE) + self.assertTrue( val_s.GetChildMemberWithName('a').AddressOf(), VALID_VARIABLE) self.assertTrue( diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py index d5862d274ceb..3c19c589b7a7 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -108,7 +108,6 @@ class TargetWatchAddressAPITestCase(TestBase): # No size constraint on MIPS for watches @skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el']) @skipIf(archs=['s390x']) # Likewise on SystemZ - @expectedFailureAll(oslist=["windows"]) def test_watch_address_with_invalid_watch_size(self): """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size.""" self.build() diff --git a/packages/Python/lldbsuite/test/settings/TestSettings.py b/packages/Python/lldbsuite/test/settings/TestSettings.py index d6fa5a93b72c..b46e3b4103c6 100644 --- a/packages/Python/lldbsuite/test/settings/TestSettings.py +++ b/packages/Python/lldbsuite/test/settings/TestSettings.py @@ -132,7 +132,7 @@ class SettingsCommandTestCase(TestBase): # Change the default format to print function.name rather than # function.name-with-args - format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n" + format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n" self.runCmd("settings set frame-format %s" % format_string) # Immediately test the setting. @@ -418,11 +418,11 @@ class SettingsCommandTestCase(TestBase): # Set to known value self.runCmd("settings set target.language c89") # Set to new value with trailing whitespace - self.runCmd("settings set target.language go ") + self.runCmd("settings set target.language c11 ") self.expect( "settings show target.language", SETTING_MSG("target.language"), - startstr="target.language (language) = go") + startstr="target.language (language) = c11") self.runCmd("settings clear target.language", check=False) # arguments self.runCmd("settings set target.run-args 1 2 3") # Set to known value diff --git a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py index 0df4f8b2d2a8..ea822decdb6f 100644 --- a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py +++ b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py @@ -22,6 +22,8 @@ def ansi_underline_surround_regex(inner_regex_text): # return re.compile(r"\[4m%s\[0m" % inner_regex_text) return "4.+\033\\[4m%s\033\\[0m" % inner_regex_text +def ansi_color_surround_regex(inner_regex_text): + return "\033\\[3[0-7]m%s\033\\[0m" % inner_regex_text class SourceManagerTestCase(TestBase): @@ -47,7 +49,7 @@ class SourceManagerTestCase(TestBase): # the character column after the initial whitespace. return len(stop_line) - len(stop_line.lstrip()) + 1 - def do_display_source_python_api(self, use_color, column_marker_regex): + def do_display_source_python_api(self, use_color, needle_regex, highlight_source=False): self.build() exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -69,6 +71,9 @@ class SourceManagerTestCase(TestBase): # Setup whether we should use ansi escape sequences, including color # and styles such as underline. self.dbg.SetUseColor(use_color) + # Disable syntax highlighting if needed. + + self.runCmd("settings set highlight-source " + str(highlight_source).lower()) filespec = lldb.SBFileSpec(self.file, False) source_mgr = self.dbg.GetSourceManager() @@ -87,10 +92,10 @@ class SourceManagerTestCase(TestBase): # => 4 printf("Hello world.\n"); // Set break point at this line. # 5 return 0; # 6 } - self.expect(stream.GetData(), "Source code displayed correctly", + self.expect(stream.GetData(), "Source code displayed correctly:\n" + stream.GetData(), exe=False, patterns=['=> %d.*Hello world' % self.line, - column_marker_regex]) + needle_regex]) # Boundary condition testings for SBStream(). LLDB should not crash! stream.Print(None) @@ -108,9 +113,28 @@ class SourceManagerTestCase(TestBase): """Test display of source using the SBSourceManager API, using a dumb terminal and thus no color support (the default).""" use_color = True - underline_regex = ansi_underline_surround_regex(r".") + underline_regex = ansi_underline_surround_regex(r"printf") self.do_display_source_python_api(use_color, underline_regex) + @add_test_categories(['pyapi']) + def test_display_source_python_ansi_terminal_syntax_highlighting(self): + """Test display of source using the SBSourceManager API and check for + the syntax highlighted output""" + use_color = True + syntax_highlighting = True; + + # Just pick 'int' as something that should be colored. + color_regex = ansi_color_surround_regex("int") + self.do_display_source_python_api(use_color, color_regex, syntax_highlighting) + + # Same for 'char'. + color_regex = ansi_color_surround_regex("char") + self.do_display_source_python_api(use_color, color_regex, syntax_highlighting) + + # Test that we didn't color unrelated identifiers. + self.do_display_source_python_api(use_color, r" main\(", syntax_highlighting) + self.do_display_source_python_api(use_color, r"\);", syntax_highlighting) + def test_move_and_then_display_source(self): """Test that target.source-map settings work by moving main.c to hidden/main.c.""" self.build() diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py index ccd7eba8bfe3..848bd3852393 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py @@ -18,6 +18,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_target_create(self): """Test that 'lldb-mi --interpreter' can create target by 'target create' command.""" @@ -39,6 +40,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfRemote # We do not currently support remote debugging via the MI. @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows. @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races. + @skipIfDarwin def test_lldbmi_target_list(self): """Test that 'lldb-mi --interpreter' can list targets by 'target list' command.""" @@ -58,6 +60,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_breakpoint_set(self): """Test that 'lldb-mi --interpreter' can set breakpoint by 'breakpoint set' command.""" @@ -82,6 +85,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @expectedFlakeyLinux(bugnumber="llvm.org/pr25470") @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_settings_set_target_run_args_before(self): """Test that 'lldb-mi --interpreter' can set target arguments by 'setting set target.run-args' command before than target was created.""" @@ -115,6 +119,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_process_launch(self): """Test that 'lldb-mi --interpreter' can launch process by "process launch" command.""" @@ -138,6 +143,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_thread_step_in(self): """Test that 'lldb-mi --interpreter' can step in by "thread step-in" command.""" @@ -170,6 +176,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_thread_step_over(self): """Test that 'lldb-mi --interpreter' can step over by "thread step-over" command.""" @@ -196,6 +203,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @expectedFlakeyLinux("llvm.org/pr25470") @skipIfRemote # We do not currently support remote debugging via the MI. + @skipIfDarwin def test_lldbmi_thread_continue(self): """Test that 'lldb-mi --interpreter' can continue execution by "thread continue" command.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py index 7b6ee55b250e..59a5b324465f 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py @@ -40,7 +40,7 @@ class MiTestCaseBase(Base): pass Base.tearDown(self) - def spawnLldbMi(self, args=None): + def spawnLldbMi(self, exe=None, args=None, preconfig=True): import pexpect self.child = pexpect.spawn("%s --interpreter %s" % ( self.lldbMiExec, args if args else ""), cwd=self.getBuildDir()) @@ -49,6 +49,14 @@ class MiTestCaseBase(Base): self.child.logfile_read = open(self.mylog, "w") # wait until lldb-mi has started up and is ready to go self.expect(self.child_prompt, exactly=True) + if preconfig: + self.runCmd("settings set symbols.enable-external-lookup false") + self.expect("\^done") + self.expect(self.child_prompt, exactly=True) + if exe: + self.runCmd("-file-exec-and-symbols \"%s\"" % exe) + # Testcases expect to be able to match output of this command, + # see test_lldbmi_specialchars. def runCmd(self, cmd): self.child.sendline(cmd) diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py index 467952db7eba..b78f4762ddf9 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py @@ -22,7 +22,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): def test_lldbmi_executable_option_file(self): """Test that 'lldb-mi --interpreter %s' loads executable file.""" - self.spawnLldbMi(args="%s" % self.myexe) + self.spawnLldbMi(exe=self.myexe) # Test that the executable is loaded when file was specified self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) @@ -52,7 +52,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): # Prepare path to executable path = "unknown_file" - self.spawnLldbMi(args="%s" % path) + self.spawnLldbMi(exe=path) # Test that the executable isn't loaded when unknown file was specified self.expect("-file-exec-and-symbols \"%s\"" % path) @@ -71,7 +71,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): """Test that 'lldb-mi --interpreter %s' loads executable which is specified via absolute path.""" # Prepare path to executable - self.spawnLldbMi(args="%s" % self.myexe) + self.spawnLldbMi(exe=self.myexe) # Test that the executable is loaded when file was specified using # absolute path @@ -95,7 +95,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): # Prepare path to executable path = os.path.relpath(self.myexe, self.getBuildDir()) - self.spawnLldbMi(args="%s" % path) + self.spawnLldbMi(exe=path) # Test that the executable is loaded when file was specified using # relative path @@ -119,7 +119,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): # Prepare path to executable path = "unknown_dir" + self.myexe - self.spawnLldbMi(args="%s" % path) + self.spawnLldbMi(exe=path) # Test that the executable isn't loaded when file was specified using # unknown path @@ -237,7 +237,11 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): # Prepared source file sourceFile = self.copyScript("start_script_error") - self.spawnLldbMi(args="--source %s" % sourceFile) + self.spawnLldbMi(args="--source %s" % sourceFile, preconfig=False) + + # After 'settings set symbols.enable-external-lookup false' + self.expect("settings set symbols.enable-external-lookup false") + self.expect("\^done") # After '-file-exec-and-symbols a.out' self.expect("-file-exec-and-symbols %s" % self.myexe) @@ -259,7 +263,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): """Test that 'lldb-mi --log' creates a log file in the current directory.""" logDirectory = self.getBuildDir() - self.spawnLldbMi(args="%s --log" % self.myexe) + self.spawnLldbMi(exe=self.myexe, args="--log") # Test that the executable is loaded when file was specified self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) @@ -296,9 +300,8 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): import tempfile logDirectory = tempfile.gettempdir() - self.spawnLldbMi( - args="%s --log --log-dir=%s" % - (self.myexe, logDirectory)) + self.spawnLldbMi(exe=self.myexe, + args="--log --log-dir=%s" % logDirectory) # Test that the executable is loaded when file was specified self.expect("-file-exec-and-symbols \"%s\"" % self.myexe) diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error index d834e7407c57..a1c581b08e0e 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error @@ -1,2 +1,3 @@ +settings set symbols.enable-external-lookup false -file-exec-and-symbols a.out -break-ins -f main diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py index 50a94b53a18b..74d194e6dee2 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py @@ -53,7 +53,7 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase): os.symlink(self.myexe, complicated_myexe) self.addTearDownHook(lambda: os.unlink(complicated_myexe)) - self.spawnLldbMi(args="\"%s\"" % complicated_myexe) + self.spawnLldbMi(exe=complicated_myexe) # Test that the executable was loaded self.expect( diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py index 8c8fed8e44e0..62c948c36cf7 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py @@ -19,7 +19,13 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase): sim_devices = json.loads(sim_devices_str)['devices'] # Find an available simulator for the requested platform deviceUDID = None - for (runtime,devices) in sim_devices.items(): + for simulator in sim_devices: + if isinstance(simulator,dict): + runtime = simulator['name'] + devices = simulator['devices'] + else: + runtime = simulator + devices = sim_devices[simulator] if not platform in runtime.lower(): continue for device in devices: @@ -95,18 +101,21 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase): @apple_simulator_test('iphone') @debugserver_test + @skipIfDarwinEmbedded def test_simulator_ostype_ios(self): self.check_simulator_ostype(sdk='iphonesimulator', platform='ios') @apple_simulator_test('appletv') @debugserver_test + @skipIfDarwinEmbedded def test_simulator_ostype_tvos(self): self.check_simulator_ostype(sdk='appletvsimulator', platform='tvos') @apple_simulator_test('watch') @debugserver_test + @skipIfDarwinEmbedded def test_simulator_ostype_watchos(self): self.check_simulator_ostype(sdk='watchsimulator', platform='watchos', arch='i386') diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py index 76910758fa91..cfadbc8f7d0f 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py @@ -35,6 +35,7 @@ class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase): @skipIfOutOfTreeDebugserver @debugserver_test + @skipIfDarwinEmbedded def test_g_packet_debugserver(self): self.init_debugserver_test() self.run_test_g_packet() diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories new file mode 100644 index 000000000000..ce2cfd048e38 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories @@ -0,0 +1 @@ +lldb-vscode diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py new file mode 100644 index 000000000000..67cd05b83c3b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py @@ -0,0 +1,192 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os +import shutil +import subprocess +import tempfile +import threading +import time + + +def spawn_and_wait(program, delay): + if delay: + time.sleep(delay) + process = subprocess.Popen([program], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + process.wait() + + +class TestVSCode_attach(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + def set_and_hit_breakpoint(self, continueToExit=True): + source = 'main.c' + breakpoint1_line = line_number(source, '// breakpoint 1') + lines = [breakpoint1_line] + # Set breakoint in the thread function so we can step the threads + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.assertEqual(len(breakpoint_ids), len(lines), + "expect correct number of breakpoints") + self.continue_to_breakpoints(breakpoint_ids) + if continueToExit: + self.continue_to_exit() + + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_by_pid(self): + ''' + Tests attaching to a process by process ID. + ''' + self.build_and_create_debug_adaptor() + program = self.getBuildArtifact("a.out") + self.process = subprocess.Popen([program], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + self.attach(pid=self.process.pid) + self.set_and_hit_breakpoint(continueToExit=True) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_by_name(self): + ''' + Tests attaching to a process by process name. + ''' + self.build_and_create_debug_adaptor() + orig_program = self.getBuildArtifact("a.out") + # Since we are going to attach by process name, we need a unique + # process name that has minimal chance to match a process that is + # already running. To do this we use tempfile.mktemp() to give us a + # full path to a location where we can copy our executable. We then + # run this copy to ensure we don't get the error "more that one + # process matches 'a.out'". + program = tempfile.mktemp() + shutil.copyfile(orig_program, program) + shutil.copymode(orig_program, program) + + def cleanup(): + if os.path.exists(program): + os.unlink(program) + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.process = subprocess.Popen([program], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + # Wait for a bit to ensure the process is launched + time.sleep(5) + self.attach(program=program) + self.set_and_hit_breakpoint(continueToExit=True) + + @skipUnlessDarwin + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_by_name_waitFor(self): + ''' + Tests attaching to a process by process name and waiting for the + next instance of a process to be launched, ingoring all current + ones. + ''' + self.build_and_create_debug_adaptor() + program = self.getBuildArtifact("a.out") + self.spawn_thread = threading.Thread(target=spawn_and_wait, + args=(program, 1.0,)) + self.spawn_thread.start() + self.attach(program=program, waitFor=True) + self.set_and_hit_breakpoint(continueToExit=True) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_commands(self): + ''' + Tests the "initCommands", "preRunCommands", "stopCommands", + "exitCommands", and "attachCommands" that can be passed during + attach. + + "initCommands" are a list of LLDB commands that get executed + before the targt is created. + "preRunCommands" are a list of LLDB commands that get executed + after the target has been created and before the launch. + "stopCommands" are a list of LLDB commands that get executed each + time the program stops. + "exitCommands" are a list of LLDB commands that get executed when + the process exits + "attachCommands" are a list of LLDB commands that get executed and + must have a valid process in the selected target in LLDB after + they are done executing. This allows custom commands to create any + kind of debug session. + ''' + self.build_and_create_debug_adaptor() + program = self.getBuildArtifact("a.out") + # Here we just create a target and launch the process as a way to test + # if we are able to use attach commands to create any kind of a target + # and use it for debugging + attachCommands = [ + 'target create -d "%s"' % (program), + 'process launch -- arg1' + ] + initCommands = ['target list', 'platform list'] + preRunCommands = ['image list a.out', 'image dump sections a.out'] + stopCommands = ['frame variable', 'bt'] + exitCommands = ['expr 2+3', 'expr 3+4'] + self.attach(program=program, + attachCommands=attachCommands, + initCommands=initCommands, + preRunCommands=preRunCommands, + stopCommands=stopCommands, + exitCommands=exitCommands) + + # Get output from the console. This should contain both the + # "initCommands" and the "preRunCommands". + output = self.get_console() + # Verify all "initCommands" were found in console output + self.verify_commands('initCommands', output, initCommands) + # Verify all "preRunCommands" were found in console output + self.verify_commands('preRunCommands', output, preRunCommands) + + functions = ['main'] + breakpoint_ids = self.set_function_breakpoints(functions) + self.assertTrue(len(breakpoint_ids) == len(functions), + "expect one breakpoint") + self.continue_to_breakpoints(breakpoint_ids) + output = self.get_console(timeout=1.0) + self.verify_commands('stopCommands', output, stopCommands) + + # Continue after launch and hit the "pause()" call and stop the target. + # Get output from the console. This should contain both the + # "stopCommands" that were run after we stop. + self.vscode.request_continue() + time.sleep(0.5) + self.vscode.request_pause() + self.vscode.wait_for_stopped() + output = self.get_console(timeout=1.0) + self.verify_commands('stopCommands', output, stopCommands) + + # Continue until the program exits + self.continue_to_exit() + # Get output from the console. This should contain both the + # "exitCommands" that were run after the second breakpoint was hit + output = self.get_console(timeout=1.0) + self.verify_commands('exitCommands', output, exitCommands) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c new file mode 100644 index 000000000000..a078d42203eb --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char const *argv[]) { + printf("pid = %i\n", getpid()); + sleep(5); + return 0; // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py new file mode 100644 index 000000000000..1ebf2b8981ab --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py @@ -0,0 +1,211 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setBreakpoints(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_set_and_clear(self): + '''Tests setting and clearing source file and line breakpoints. + This packet is a bit tricky on the debug adaptor side since there + is no "clearBreakpoints" packet. Source file and line breakpoints + are set by sending a "setBreakpoints" packet with a source file + specified and zero or more source lines. If breakpoints have been + set in the source file before, any exising breakpoints must remain + set, and any new breakpoints must be created, and any breakpoints + that were in previous requests and are not in the current request + must be removed. This function tests this setting and clearing + and makes sure things happen correctly. It doesn't test hitting + breakpoints and the functionality of each breakpoint, like + 'conditions' and 'hitCondition' settings.''' + source_basename = 'main.cpp' + source_path = os.path.join(os.getcwd(), source_basename) + first_line = line_number('main.cpp', 'break 12') + second_line = line_number('main.cpp', 'break 13') + third_line = line_number('main.cpp', 'break 14') + lines = [first_line, second_line, third_line] + + # Visual Studio Code Debug Adaptors have no way to specify the file + # without launching or attaching to a process, so we must start a + # process in order to be able to set breakpoints. + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + + # Set 3 breakoints and verify that they got set correctly + response = self.vscode.request_setBreakpoints(source_path, lines) + line_to_id = {} + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + for breakpoint in breakpoints: + line = breakpoint['line'] + # Store the "id" of the breakpoint that was set for later + line_to_id[line] = breakpoint['id'] + self.assertTrue(line in lines, "line expected in lines array") + self.assertTrue(breakpoint['verified'], + "expect breakpoint verified") + + # There is no breakpoint delete packet, clients just send another + # setBreakpoints packet with the same source file with fewer lines. + # Below we remove the second line entry and call the setBreakpoints + # function again. We want to verify that any breakpoints that were set + # before still have the same "id". This means we didn't clear the + # breakpoint and set it again at the same location. We also need to + # verify that the second line location was actually removed. + lines.remove(second_line) + # Set 2 breakoints and verify that the previous breakoints that were + # set above are still set. + response = self.vscode.request_setBreakpoints(source_path, lines) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + for breakpoint in breakpoints: + line = breakpoint['line'] + # Verify the same breakpoints are still set within LLDB by + # making sure the breakpoint ID didn't change + self.assertTrue(line_to_id[line] == breakpoint['id'], + "verify previous breakpoints stayed the same") + self.assertTrue(line in lines, "line expected in lines array") + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + # Now get the full list of breakpoints set in the target and verify + # we have only 2 breakpoints set. The response above could have told + # us about 2 breakpoints, but we want to make sure we don't have the + # third one still set in the target + response = self.vscode.request_testGetTargetBreakpoints() + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + for breakpoint in breakpoints: + line = breakpoint['line'] + # Verify the same breakpoints are still set within LLDB by + # making sure the breakpoint ID didn't change + self.assertTrue(line_to_id[line] == breakpoint['id'], + "verify previous breakpoints stayed the same") + self.assertTrue(line in lines, "line expected in lines array") + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + # Now clear all breakpoints for the source file by passing down an + # empty lines array + lines = [] + response = self.vscode.request_setBreakpoints(source_path, lines) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + + # Verify with the target that all breakpoints have been cleared + response = self.vscode.request_testGetTargetBreakpoints() + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + + # Now set a breakpoint again in the same source file and verify it + # was added. + lines = [second_line] + response = self.vscode.request_setBreakpoints(source_path, lines) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + for breakpoint in breakpoints: + line = breakpoint['line'] + self.assertTrue(line in lines, "line expected in lines array") + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + # Now get the full list of breakpoints set in the target and verify + # we have only 2 breakpoints set. The response above could have told + # us about 2 breakpoints, but we want to make sure we don't have the + # third one still set in the target + response = self.vscode.request_testGetTargetBreakpoints() + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(lines), + "expect %u source breakpoints" % (len(lines))) + for breakpoint in breakpoints: + line = breakpoint['line'] + self.assertTrue(line in lines, "line expected in lines array") + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_functionality(self): + '''Tests hitting breakpoints and the functionality of a single + breakpoint, like 'conditions' and 'hitCondition' settings.''' + source_basename = 'main.cpp' + source_path = os.path.join(os.getcwd(), source_basename) + loop_line = line_number('main.cpp', '// break loop') + + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + # Set a breakpoint at the loop line with no condition and no + # hitCondition + breakpoint_ids = self.set_source_breakpoints(source_path, [loop_line]) + self.assertTrue(len(breakpoint_ids) == 1, "expect one breakpoint") + self.vscode.request_continue() + + # Verify we hit the breakpoint we just set + self.verify_breakpoint_hit(breakpoint_ids) + + # Make sure i is zero at first breakpoint + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 0, 'i != 0 after hitting breakpoint') + + # Update the condition on our breakpoint + new_breakpoint_ids = self.set_source_breakpoints(source_path, + [loop_line], + condition="i==4") + self.assertTrue(breakpoint_ids == new_breakpoint_ids, + "existing breakpoint should have its condition " + "updated") + + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 4, + 'i != 4 showing conditional works') + + new_breakpoint_ids = self.set_source_breakpoints(source_path, + [loop_line], + hitCondition="2") + + self.assertTrue(breakpoint_ids == new_breakpoint_ids, + "existing breakpoint should have its condition " + "updated") + + # Continue with a hitContidtion of 2 and expect it to skip 1 value + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 6, + 'i != 6 showing hitCondition works') + + # continue after hitting our hitCondition and make sure it only goes + # up by 1 + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 7, + 'i != 7 showing post hitCondition hits every time') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py new file mode 100644 index 000000000000..fdba683760e0 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py @@ -0,0 +1,51 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setExceptionBreakpoints( + lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_functionality(self): + '''Tests setting and clearing exception breakpoints. + This packet is a bit tricky on the debug adaptor side since there + is no "clear exception breakpoints" packet. Exception breakpoints + are set by sending a "setExceptionBreakpoints" packet with zero or + more exception filters. If exception breakpoints have been set + before, any exising breakpoints must remain set, and any new + breakpoints must be created, and any breakpoints that were in + previous requests and are not in the current request must be + removed. This exception tests this setting and clearing and makes + sure things happen correctly. It doesn't test hitting breakpoints + and the functionality of each breakpoint, like 'conditions' and + x'hitCondition' settings. + ''' + # Visual Studio Code Debug Adaptors have no way to specify the file + # without launching or attaching to a process, so we must start a + # process in order to be able to set breakpoints. + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + + filters = ['cpp_throw', 'cpp_catch'] + response = self.vscode.request_setExceptionBreakpoints(filters) + if response: + self.assertTrue(response['success']) + + self.continue_to_exception_breakpoint('C++ Throw') + self.continue_to_exception_breakpoint('C++ Catch') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py new file mode 100644 index 000000000000..c7c67597c86b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py @@ -0,0 +1,167 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_setFunctionBreakpoints( + lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # test hangs on linux under heavy load + @no_debug_info_test + def test_set_and_clear(self): + '''Tests setting and clearing function breakpoints. + This packet is a bit tricky on the debug adaptor side since there + is no "clearFunction Breakpoints" packet. Function breakpoints + are set by sending a "setFunctionBreakpoints" packet with zero or + more function names. If function breakpoints have been set before, + any exising breakpoints must remain set, and any new breakpoints + must be created, and any breakpoints that were in previous requests + and are not in the current request must be removed. This function + tests this setting and clearing and makes sure things happen + correctly. It doesn't test hitting breakpoints and the functionality + of each breakpoint, like 'conditions' and 'hitCondition' settings. + ''' + # Visual Studio Code Debug Adaptors have no way to specify the file + # without launching or attaching to a process, so we must start a + # process in order to be able to set breakpoints. + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + bp_id_12 = None + functions = ['twelve'] + # Set a function breakpoint at 'twelve' + response = self.vscode.request_setFunctionBreakpoints(functions) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + for breakpoint in breakpoints: + bp_id_12 = breakpoint['id'] + self.assertTrue(breakpoint['verified'], + "expect breakpoint verified") + + # Add an extra name and make sure we have two breakpoints after this + functions.append('thirteen') + response = self.vscode.request_setFunctionBreakpoints(functions) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + for breakpoint in breakpoints: + self.assertTrue(breakpoint['verified'], + "expect breakpoint verified") + + # There is no breakpoint delete packet, clients just send another + # setFunctionBreakpoints packet with the different function names. + functions.remove('thirteen') + response = self.vscode.request_setFunctionBreakpoints(functions) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + for breakpoint in breakpoints: + bp_id = breakpoint['id'] + self.assertTrue(bp_id == bp_id_12, + 'verify "twelve" breakpoint ID is same') + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + # Now get the full list of breakpoints set in the target and verify + # we have only 1 breakpoints set. The response above could have told + # us about 1 breakpoints, but we want to make sure we don't have the + # second one still set in the target + response = self.vscode.request_testGetTargetBreakpoints() + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + for breakpoint in breakpoints: + bp_id = breakpoint['id'] + self.assertTrue(bp_id == bp_id_12, + 'verify "twelve" breakpoint ID is same') + self.assertTrue(breakpoint['verified'], + "expect breakpoint still verified") + + # Now clear all breakpoints for the source file by passing down an + # empty lines array + functions = [] + response = self.vscode.request_setFunctionBreakpoints(functions) + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + + # Verify with the target that all breakpoints have been cleared + response = self.vscode.request_testGetTargetBreakpoints() + if response: + breakpoints = response['body']['breakpoints'] + self.assertTrue(len(breakpoints) == len(functions), + "expect %u source breakpoints" % (len(functions))) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_functionality(self): + '''Tests hitting breakpoints and the functionality of a single + breakpoint, like 'conditions' and 'hitCondition' settings.''' + + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + # Set a breakpoint on "twelve" with no condition and no hitCondition + functions = ['twelve'] + breakpoint_ids = self.set_function_breakpoints(functions) + + self.assertTrue(len(breakpoint_ids) == len(functions), + "expect one breakpoint") + + # Verify we hit the breakpoint we just set + self.continue_to_breakpoints(breakpoint_ids) + + # Make sure i is zero at first breakpoint + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 0, 'i != 0 after hitting breakpoint') + + # Update the condition on our breakpoint + new_breakpoint_ids = self.set_function_breakpoints(functions, + condition="i==4") + self.assertTrue(breakpoint_ids == new_breakpoint_ids, + "existing breakpoint should have its condition " + "updated") + + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 4, + 'i != 4 showing conditional works') + new_breakpoint_ids = self.set_function_breakpoints(functions, + hitCondition="2") + + self.assertTrue(breakpoint_ids == new_breakpoint_ids, + "existing breakpoint should have its condition " + "updated") + + # Continue with a hitContidtion of 2 and expect it to skip 1 value + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 6, + 'i != 6 showing hitCondition works') + + # continue after hitting our hitCondition and make sure it only goes + # up by 1 + self.continue_to_breakpoints(breakpoint_ids) + i = int(self.vscode.get_local_variable_value('i')) + self.assertTrue(i == 7, + 'i != 7 showing post hitCondition hits every time') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp new file mode 100644 index 000000000000..e859b04e3a99 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <stdexcept> + +int twelve(int i) { + return 12 + i; // break 12 +} + +int thirteen(int i) { + return 13 + i; // break 13 +} + +namespace a { + int fourteen(int i) { + return 14 + i; // break 14 + } +} +int main(int argc, char const *argv[]) { + for (int i=0; i<10; ++i) { + int x = twelve(i) + thirteen(i) + a::fourteen(i); // break loop + } + try { + throw std::invalid_argument( "throwing exception for testing" ); + } catch (...) { + puts("caught exception..."); + } + return 0; +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py new file mode 100644 index 000000000000..064cf9a6783e --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py @@ -0,0 +1,352 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import pprint +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os +import time + + +class TestVSCode_launch(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_default(self): + ''' + Tests the default launch of a simple program. No arguments, + environment, or anything else is specified. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + self.continue_to_exit() + # Now get the STDOUT and verify our program argument is correct + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect program output") + lines = output.splitlines() + self.assertTrue(program in lines[0], + "make sure program path is in first argument") + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_stopOnEntry(self): + ''' + Tests the default launch of a simple program that stops at the + entry point instead of continuing. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program, stopOnEntry=True) + self.set_function_breakpoints(['main']) + stopped_events = self.continue_to_next_stop() + for stopped_event in stopped_events: + if 'body' in stopped_event: + body = stopped_event['body'] + if 'reason' in body: + reason = body['reason'] + self.assertTrue( + reason != 'breakpoint', + 'verify stop isn\'t "main" breakpoint') + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_cwd(self): + ''' + Tests the default launch of a simple program with a current working + directory. + ''' + program = self.getBuildArtifact("a.out") + program_parent_dir = os.path.split(os.path.split(program)[0])[0] + self.build_and_launch(program, + cwd=program_parent_dir) + self.continue_to_exit() + # Now get the STDOUT and verify our program argument is correct + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect program output") + lines = output.splitlines() + found = False + for line in lines: + if line.startswith('cwd = \"'): + quote_path = '"%s"' % (program_parent_dir) + found = True + self.assertTrue(quote_path in line, + "working directory '%s' not in '%s'" % ( + program_parent_dir, line)) + self.assertTrue(found, "verified program working directory") + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_debuggerRoot(self): + ''' + Tests the "debuggerRoot" will change the working directory of + the lldb-vscode debug adaptor. + ''' + program = self.getBuildArtifact("a.out") + program_parent_dir = os.path.split(os.path.split(program)[0])[0] + commands = ['platform shell echo cwd = $PWD'] + self.build_and_launch(program, + debuggerRoot=program_parent_dir, + initCommands=commands) + output = self.get_console() + self.assertTrue(output and len(output) > 0, + "expect console output") + lines = output.splitlines() + prefix = 'cwd = ' + found = False + for line in lines: + if line.startswith(prefix): + found = True + self.assertTrue(program_parent_dir == line[len(prefix):], + "lldb-vscode working dir '%s' == '%s'" % ( + program_parent_dir, line[6:])) + self.assertTrue(found, "verified lldb-vscode working directory") + self.continue_to_exit() + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_sourcePath(self): + ''' + Tests the "sourcePath" will set the target.source-map. + ''' + program = self.getBuildArtifact("a.out") + program_dir = os.path.split(program)[0] + self.build_and_launch(program, + sourcePath=program_dir) + output = self.get_console() + self.assertTrue(output and len(output) > 0, + "expect console output") + lines = output.splitlines() + prefix = '(lldb) settings set target.source-map "." ' + found = False + for line in lines: + if line.startswith(prefix): + found = True + quoted_path = '"%s"' % (program_dir) + self.assertTrue(quoted_path == line[len(prefix):], + "lldb-vscode working dir %s == %s" % ( + quoted_path, line[6:])) + self.assertTrue(found, 'found "sourcePath" in console output') + self.continue_to_exit() + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_disableSTDIO(self): + ''' + Tests the default launch of a simple program with STDIO disabled. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program, + disableSTDIO=True) + self.continue_to_exit() + # Now get the STDOUT and verify our program argument is correct + output = self.get_stdout() + self.assertTrue(output is None or len(output) == 0, + "expect no program output") + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_shellExpandArguments_enabled(self): + ''' + Tests the default launch of a simple program with shell expansion + enabled. + ''' + program = self.getBuildArtifact("a.out") + program_dir = os.path.split(program)[0] + glob = os.path.join(program_dir, '*.out') + self.build_and_launch(program, args=[glob], shellExpandArguments=True) + self.continue_to_exit() + # Now get the STDOUT and verify our program argument is correct + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect no program output") + lines = output.splitlines() + for line in lines: + quote_path = '"%s"' % (program) + if line.startswith("arg[1] ="): + self.assertTrue(quote_path in line, + 'verify "%s" expanded to "%s"' % ( + glob, program)) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_shellExpandArguments_disabled(self): + ''' + Tests the default launch of a simple program with shell expansion + disabled. + ''' + program = self.getBuildArtifact("a.out") + program_dir = os.path.split(program)[0] + glob = os.path.join(program_dir, '*.out') + self.build_and_launch(program, + args=[glob], + shellExpandArguments=False) + self.continue_to_exit() + # Now get the STDOUT and verify our program argument is correct + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect no program output") + lines = output.splitlines() + for line in lines: + quote_path = '"%s"' % (glob) + if line.startswith("arg[1] ="): + self.assertTrue(quote_path in line, + 'verify "%s" stayed to "%s"' % ( + glob, glob)) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_args(self): + ''' + Tests launch of a simple program with arguments + ''' + program = self.getBuildArtifact("a.out") + args = ["one", "with space", "'with single quotes'", + '"with double quotes"'] + self.build_and_launch(program, + args=args) + self.continue_to_exit() + + # Now get the STDOUT and verify our arguments got passed correctly + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect program output") + lines = output.splitlines() + # Skip the first argument that contains the program name + lines.pop(0) + # Make sure arguments we specified are correct + for (i, arg) in enumerate(args): + quoted_arg = '"%s"' % (arg) + self.assertTrue(quoted_arg in lines[i], + 'arg[%i] "%s" not in "%s"' % (i+1, quoted_arg, lines[i])) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_environment(self): + ''' + Tests launch of a simple program with environment variables + ''' + program = self.getBuildArtifact("a.out") + env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=", + "SPACE=Hello World"] + self.build_and_launch(program, + env=env) + self.continue_to_exit() + + # Now get the STDOUT and verify our arguments got passed correctly + output = self.get_stdout() + self.assertTrue(output and len(output) > 0, + "expect program output") + lines = output.splitlines() + # Skip the all arguments so we have only environment vars left + while len(lines) and lines[0].startswith("arg["): + lines.pop(0) + # Make sure each environment variable in "env" is actually set in the + # program environment that was printed to STDOUT + for var in env: + found = False + for program_var in lines: + if var in program_var: + found = True + break + self.assertTrue(found, + '"%s" must exist in program environment (%s)' % ( + var, lines)) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin + @no_debug_info_test + def test_commands(self): + ''' + Tests the "initCommands", "preRunCommands", "stopCommands" and + "exitCommands" that can be passed during launch. + + "initCommands" are a list of LLDB commands that get executed + before the targt is created. + "preRunCommands" are a list of LLDB commands that get executed + after the target has been created and before the launch. + "stopCommands" are a list of LLDB commands that get executed each + time the program stops. + "exitCommands" are a list of LLDB commands that get executed when + the process exits + ''' + program = self.getBuildArtifact("a.out") + initCommands = ['target list', 'platform list'] + preRunCommands = ['image list a.out', 'image dump sections a.out'] + stopCommands = ['frame variable', 'bt'] + exitCommands = ['expr 2+3', 'expr 3+4'] + self.build_and_launch(program, + initCommands=initCommands, + preRunCommands=preRunCommands, + stopCommands=stopCommands, + exitCommands=exitCommands) + + # Get output from the console. This should contain both the + # "initCommands" and the "preRunCommands". + output = self.get_console() + # Verify all "initCommands" were found in console output + self.verify_commands('initCommands', output, initCommands) + # Verify all "preRunCommands" were found in console output + self.verify_commands('preRunCommands', output, preRunCommands) + + source = 'main.c' + first_line = line_number(source, '// breakpoint 1') + second_line = line_number(source, '// breakpoint 2') + lines = [first_line, second_line] + + # Set 2 breakoints so we can verify that "stopCommands" get run as the + # breakpoints get hit + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.assertTrue(len(breakpoint_ids) == len(lines), + "expect correct number of breakpoints") + + # Continue after launch and hit the first breakpoint. + # Get output from the console. This should contain both the + # "stopCommands" that were run after the first breakpoint was hit + self.continue_to_breakpoints(breakpoint_ids) + output = self.get_console(timeout=1.0) + self.verify_commands('stopCommands', output, stopCommands) + + # Continue again and hit the second breakpoint. + # Get output from the console. This should contain both the + # "stopCommands" that were run after the second breakpoint was hit + self.continue_to_breakpoints(breakpoint_ids) + output = self.get_console(timeout=1.0) + self.verify_commands('stopCommands', output, stopCommands) + + # Continue until the program exits + self.continue_to_exit() + # Get output from the console. This should contain both the + # "exitCommands" that were run after the second breakpoint was hit + output = self.get_console(timeout=1.0) + self.verify_commands('exitCommands', output, exitCommands) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c new file mode 100644 index 000000000000..aed2af9828f3 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main(int argc, char const *argv[], char const *envp[]) { + for (int i=0; i<argc; ++i) + printf("arg[%i] = \"%s\"\n", i, argv[i]); + for (int i=0; envp[i]; ++i) + printf("env[%i] = \"%s\"\n", i, envp[i]); + char *cwd = getcwd(NULL, 0); + printf("cwd = \"%s\"\n", cwd); // breakpoint 1 + free(cwd); + cwd = NULL; + return 0; // breakpoint 2 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py new file mode 100644 index 000000000000..c66c6bb7af6b --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py @@ -0,0 +1,288 @@ +from __future__ import print_function + +from lldbsuite.test.lldbtest import * +import os +import vscode + + +class VSCodeTestCaseBase(TestBase): + + def create_debug_adaptor(self): + '''Create the Visual Studio Code debug adaptor''' + self.assertTrue(os.path.exists(self.lldbVSCodeExec), + 'lldb-vscode must exist') + self.vscode = vscode.DebugAdaptor(executable=self.lldbVSCodeExec) + + def build_and_create_debug_adaptor(self): + self.build() + self.create_debug_adaptor() + + def set_source_breakpoints(self, source_path, lines, condition=None, + hitCondition=None): + '''Sets source breakpoints and returns an array of strings containing + the breakpoint location IDs ("1.1", "1.2") for each breakpoint + that was set. + ''' + response = self.vscode.request_setBreakpoints( + source_path, lines, condition=condition, hitCondition=hitCondition) + if response is None: + return [] + breakpoints = response['body']['breakpoints'] + breakpoint_ids = [] + for breakpoint in breakpoints: + response_id = breakpoint['id'] + bp_id = response_id >> 32 + bp_loc_id = response_id & 0xffffffff + breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id)) + return breakpoint_ids + + def set_function_breakpoints(self, functions, condition=None, + hitCondition=None): + '''Sets breakpoints by function name given an array of function names + and returns an array of strings containing the breakpoint location + IDs ("1.1", "1.2") for each breakpoint that was set. + ''' + response = self.vscode.request_setFunctionBreakpoints( + functions, condition=condition, hitCondition=hitCondition) + if response is None: + return [] + breakpoints = response['body']['breakpoints'] + breakpoint_ids = [] + for breakpoint in breakpoints: + response_id = breakpoint['id'] + bp_id = response_id >> 32 + bp_loc_id = response_id & 0xffffffff + breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id)) + return breakpoint_ids + + def verify_breakpoint_hit(self, breakpoint_ids): + '''Wait for the process we are debugging to stop, and verify we hit + any breakpoint location in the "breakpoint_ids" array. + "breakpoint_ids" should be a list of breakpoint location ID strings + (["1.1", "2.1"]). The return value from + self.set_source_breakpoints() can be passed to this function''' + stopped_events = self.vscode.wait_for_stopped() + for stopped_event in stopped_events: + if 'body' in stopped_event: + body = stopped_event['body'] + if 'reason' not in body: + continue + if body['reason'] != 'breakpoint': + continue + if 'description' not in body: + continue + # Description is "breakpoint 1.1", so look for any location id + # ("1.1") in the description field as verification that one of + # the breakpoint locations was hit + description = body['description'] + for breakpoint_id in breakpoint_ids: + if breakpoint_id in description: + return True + return False + + def verify_exception_breakpoint_hit(self, filter_label): + '''Wait for the process we are debugging to stop, and verify the stop + reason is 'exception' and that the description matches + 'filter_label' + ''' + stopped_events = self.vscode.wait_for_stopped() + for stopped_event in stopped_events: + if 'body' in stopped_event: + body = stopped_event['body'] + if 'reason' not in body: + continue + if body['reason'] != 'exception': + continue + if 'description' not in body: + continue + description = body['description'] + if filter_label == description: + return True + return False + + def verify_commands(self, flavor, output, commands): + self.assertTrue(output and len(output) > 0, "expect console output") + lines = output.splitlines() + prefix = '(lldb) ' + for cmd in commands: + found = False + for line in lines: + if line.startswith(prefix) and cmd in line: + found = True + break + self.assertTrue(found, + "verify '%s' found in console output for '%s'" % ( + cmd, flavor)) + + def get_dict_value(self, d, key_path): + '''Verify each key in the key_path array is in contained in each + dictionary within "d". Assert if any key isn't in the + corresponding dictionary. This is handy for grabbing values from VS + Code response dictionary like getting + response['body']['stackFrames'] + ''' + value = d + for key in key_path: + if key in value: + value = value[key] + else: + self.assertTrue(key in value, + 'key "%s" from key_path "%s" not in "%s"' % ( + key, key_path, d)) + return value + + def get_stackFrames(self, threadId=None, startFrame=None, levels=None, + dump=False): + response = self.vscode.request_stackTrace(threadId=threadId, + startFrame=startFrame, + levels=levels, + dump=dump) + if response: + return self.get_dict_value(response, ['body', 'stackFrames']) + return None + + def get_source_and_line(self, threadId=None, frameIndex=0): + stackFrames = self.get_stackFrames(threadId=threadId, + startFrame=frameIndex, + levels=1) + if stackFrames is not None: + stackFrame = stackFrames[0] + ['source', 'path'] + if 'source' in stackFrame: + source = stackFrame['source'] + if 'path' in source: + if 'line' in stackFrame: + return (source['path'], stackFrame['line']) + return ('', 0) + + def get_stdout(self, timeout=0.0): + return self.vscode.get_output('stdout', timeout=timeout) + + def get_console(self, timeout=0.0): + return self.vscode.get_output('console', timeout=timeout) + + def get_local_as_int(self, name, threadId=None): + value = self.vscode.get_local_variable_value(name, threadId=threadId) + if value.startswith('0x'): + return int(value, 16) + elif value.startswith('0'): + return int(value, 8) + else: + return int(value) + + def set_local(self, name, value, id=None): + '''Set a top level local variable only.''' + return self.vscode.request_setVariable(1, name, str(value), id=id) + + def set_global(self, name, value, id=None): + '''Set a top level global variable only.''' + return self.vscode.request_setVariable(2, name, str(value), id=id) + + def stepIn(self, threadId=None, waitForStop=True): + self.vscode.request_stepIn(threadId=threadId) + if waitForStop: + return self.vscode.wait_for_stopped() + return None + + def stepOver(self, threadId=None, waitForStop=True): + self.vscode.request_next(threadId=threadId) + if waitForStop: + return self.vscode.wait_for_stopped() + return None + + def stepOut(self, threadId=None, waitForStop=True): + self.vscode.request_stepOut(threadId=threadId) + if waitForStop: + return self.vscode.wait_for_stopped() + return None + + def continue_to_next_stop(self): + self.vscode.request_continue() + return self.vscode.wait_for_stopped() + + def continue_to_breakpoints(self, breakpoint_ids): + self.vscode.request_continue() + self.verify_breakpoint_hit(breakpoint_ids) + + def continue_to_exception_breakpoint(self, filter_label): + self.vscode.request_continue() + self.assertTrue(self.verify_exception_breakpoint_hit(filter_label), + 'verify we got "%s"' % (filter_label)) + + def continue_to_exit(self, exitCode=0): + self.vscode.request_continue() + stopped_events = self.vscode.wait_for_stopped() + self.assertTrue(len(stopped_events) == 1, + "expecting single 'exited' event") + self.assertTrue(stopped_events[0]['event'] == 'exited', + 'make sure program ran to completion') + self.assertTrue(stopped_events[0]['body']['exitCode'] == exitCode, + 'exitCode == %i' % (exitCode)) + + def attach(self, program=None, pid=None, waitFor=None, trace=None, + initCommands=None, preRunCommands=None, stopCommands=None, + exitCommands=None, attachCommands=None): + '''Build the default Makefile target, create the VSCode debug adaptor, + and attach to the process. + ''' + # Make sure we disconnect and terminate the VSCode debug adaptor even + # if we throw an exception during the test case. + def cleanup(): + self.vscode.request_disconnect(terminateDebuggee=True) + self.vscode.terminate() + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + # Initialize and launch the program + self.vscode.request_initialize() + response = self.vscode.request_attach( + program=program, pid=pid, waitFor=waitFor, trace=trace, + initCommands=initCommands, preRunCommands=preRunCommands, + stopCommands=stopCommands, exitCommands=exitCommands, + attachCommands=attachCommands) + if not (response and response['success']): + self.assertTrue(response['success'], + 'attach failed (%s)' % (response['message'])) + + def build_and_launch(self, program, args=None, cwd=None, env=None, + stopOnEntry=False, disableASLR=True, + disableSTDIO=False, shellExpandArguments=False, + trace=False, initCommands=None, preRunCommands=None, + stopCommands=None, exitCommands=None, + sourcePath=None, debuggerRoot=None): + '''Build the default Makefile target, create the VSCode debug adaptor, + and launch the process. + ''' + self.build_and_create_debug_adaptor() + self.assertTrue(os.path.exists(program), 'executable must exist') + + # Make sure we disconnect and terminate the VSCode debug adaptor even + # if we throw an exception during the test case. + def cleanup(): + self.vscode.request_disconnect(terminateDebuggee=True) + self.vscode.terminate() + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Initialize and launch the program + self.vscode.request_initialize() + response = self.vscode.request_launch( + program, + args=args, + cwd=cwd, + env=env, + stopOnEntry=stopOnEntry, + disableASLR=disableASLR, + disableSTDIO=disableSTDIO, + shellExpandArguments=shellExpandArguments, + trace=trace, + initCommands=initCommands, + preRunCommands=preRunCommands, + stopCommands=stopCommands, + exitCommands=exitCommands, + sourcePath=sourcePath, + debuggerRoot=debuggerRoot) + if not (response and response['success']): + self.assertTrue(response['success'], + 'launch failed (%s)' % (response['message'])) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py new file mode 100644 index 000000000000..4bb061881c47 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py @@ -0,0 +1,160 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_stackTrace(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + name_key_path = ['name'] + source_key_path = ['source', 'path'] + line_key_path = ['line'] + + def verify_stackFrames(self, start_idx, stackFrames): + frame_idx = start_idx + for stackFrame in stackFrames: + # Don't care about frame above main + if frame_idx > 20: + return + self.verify_stackFrame(frame_idx, stackFrame) + frame_idx += 1 + + def verify_stackFrame(self, frame_idx, stackFrame): + frame_name = self.get_dict_value(stackFrame, self.name_key_path) + frame_source = self.get_dict_value(stackFrame, self.source_key_path) + frame_line = self.get_dict_value(stackFrame, self.line_key_path) + if frame_idx == 0: + expected_line = self.recurse_end + expected_name = 'recurse' + elif frame_idx < 20: + expected_line = self.recurse_call + expected_name = 'recurse' + else: + expected_line = self.recurse_invocation + expected_name = 'main' + self.assertTrue(frame_name == expected_name, + 'frame #%i name "%s" == "%s"' % ( + frame_idx, frame_name, expected_name)) + self.assertTrue(frame_source == self.source_path, + 'frame #%i source "%s" == "%s"' % ( + frame_idx, frame_source, self.source_path)) + self.assertTrue(frame_line == expected_line, + 'frame #%i line %i == %i' % (frame_idx, frame_line, + expected_line)) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_stackTrace(self): + ''' + Tests the 'stackTrace' packet and all its variants. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + source = 'main.c' + self.source_path = os.path.join(os.getcwd(), source) + self.recurse_end = line_number(source, 'recurse end') + self.recurse_call = line_number(source, 'recurse call') + self.recurse_invocation = line_number(source, 'recurse invocation') + + lines = [self.recurse_end] + + # Set breakoint at a point of deepest recuusion + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.assertTrue(len(breakpoint_ids) == len(lines), + "expect correct number of breakpoints") + + self.continue_to_breakpoints(breakpoint_ids) + startFrame = 0 + # Verify we get all stack frames with no arguments + stackFrames = self.get_stackFrames() + frameCount = len(stackFrames) + self.assertTrue(frameCount >= 20, + 'verify we get at least 20 frames for all frames') + self.verify_stackFrames(startFrame, stackFrames) + + # Verify all stack frames by specifying startFrame = 0 and levels not + # specified + stackFrames = self.get_stackFrames(startFrame=startFrame) + self.assertTrue(frameCount == len(stackFrames), + ('verify same number of frames with startFrame=%i') % ( + startFrame)) + self.verify_stackFrames(startFrame, stackFrames) + + # Verify all stack frames by specifying startFrame = 0 and levels = 0 + levels = 0 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(frameCount == len(stackFrames), + ('verify same number of frames with startFrame=%i and' + ' levels=%i') % (startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Get only the first stack frame by sepcifying startFrame = 0 and + # levels = 1 + levels = 1 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(levels == len(stackFrames), + ('verify one frame with startFrame=%i and' + ' levels=%i') % (startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Get only the first 3 stack frames by sepcifying startFrame = 0 and + # levels = 3 + levels = 3 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(levels == len(stackFrames), + ('verify %i frames with startFrame=%i and' + ' levels=%i') % (levels, startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Get only the first 15 stack frames by sepcifying startFrame = 5 and + # levels = 16 + startFrame = 5 + levels = 16 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(levels == len(stackFrames), + ('verify %i frames with startFrame=%i and' + ' levels=%i') % (levels, startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Verify we cap things correctly when we ask for too many frames + startFrame = 5 + levels = 1000 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(len(stackFrames) == frameCount - startFrame, + ('verify less than 1000 frames with startFrame=%i and' + ' levels=%i') % (startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Verify level=0 works with non-zerp start frame + startFrame = 5 + levels = 0 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(len(stackFrames) == frameCount - startFrame, + ('verify less than 1000 frames with startFrame=%i and' + ' levels=%i') % (startFrame, levels)) + self.verify_stackFrames(startFrame, stackFrames) + + # Verify we get not frames when startFrame is too high + startFrame = 1000 + levels = 1 + stackFrames = self.get_stackFrames(startFrame=startFrame, + levels=levels) + self.assertTrue(0 == len(stackFrames), + 'verify zero frames with startFrame out of bounds') diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c new file mode 100644 index 000000000000..85b41c492817 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <unistd.h> + +int recurse(int x) { + if (x <= 1) + return 1; // recurse end + return recurse(x-1) + x; // recurse call +} + +int main(int argc, char const *argv[]) { + recurse(20); // recurse invocation + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile index 035413ff763d..f24bb9f4d267 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile @@ -1,6 +1,7 @@ LEVEL = ../../../make -CXX_SOURCES := main.cpp ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py new file mode 100644 index 000000000000..87ec71a513f6 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py @@ -0,0 +1,79 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +class TestVSCode_step(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_step(self): + ''' + Tests the stepping in/out/over in threads. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + source = 'main.cpp' + # source_path = os.path.join(os.getcwd(), source) + breakpoint1_line = line_number(source, '// breakpoint 1') + lines = [breakpoint1_line] + # Set breakoint in the thread function so we can step the threads + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.assertTrue(len(breakpoint_ids) == len(lines), + "expect correct number of breakpoints") + self.continue_to_breakpoints(breakpoint_ids) + threads = self.vscode.get_threads() + for thread in threads: + if 'reason' in thread: + reason = thread['reason'] + if reason == 'breakpoint': + # We have a thread that is stopped at our breakpoint. + # Get the value of "x" and get the source file and line. + # These will help us determine if we are stepping + # correctly. If we step a thread correctly we will verify + # the correct falue for x as it progresses through the + # program. + tid = thread['id'] + x1 = self.get_local_as_int('x', threadId=tid) + (src1, line1) = self.get_source_and_line(threadId=tid) + + # Now step into the "recurse()" function call again and + # verify, using the new value of "x" and the source file + # and line if we stepped correctly + self.stepIn(threadId=tid, waitForStop=True) + x2 = self.get_local_as_int('x', threadId=tid) + (src2, line2) = self.get_source_and_line(threadId=tid) + self.assertTrue(x1 == x2 + 1, 'verify step in variable') + self.assertTrue(line2 < line1, 'verify step in line') + self.assertTrue(src1 == src2, 'verify step in source') + + # Now step out and verify + self.stepOut(threadId=tid, waitForStop=True) + x3 = self.get_local_as_int('x', threadId=tid) + (src3, line3) = self.get_source_and_line(threadId=tid) + self.assertTrue(x1 == x3, 'verify step out variable') + self.assertTrue(line3 >= line1, 'verify step out line') + self.assertTrue(src1 == src3, 'verify step in source') + + # Step over and verify + self.stepOver(threadId=tid, waitForStop=True) + x4 = self.get_local_as_int('x', threadId=tid) + (src4, line4) = self.get_source_and_line(threadId=tid) + self.assertTrue(x4 == x3, 'verify step over variable') + self.assertTrue(line4 > line3, 'verify step over line') + self.assertTrue(src1 == src4, 'verify step over source') + # only step one thread that is at the breakpoint and stop + break diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp new file mode 100644 index 000000000000..2fd063113875 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp @@ -0,0 +1,16 @@ +#include <thread> + +int function(int x) { + if ((x % 2) == 0) + return function(x-1) + x; // breakpoint 1 + else + return x; +} + +int main(int argc, char const *argv[]) { + std::thread thread1(function, 2); + std::thread thread2(function, 4); + thread1.join(); + thread2.join(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py new file mode 100644 index 000000000000..0a8906f1c6c8 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py @@ -0,0 +1,225 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase +import os + + +def make_buffer_verify_dict(start_idx, count, offset=0): + verify_dict = {} + for i in range(start_idx, start_idx + count): + verify_dict['[%i]' % (i)] = {'type': 'int', 'value': str(i+offset)} + return verify_dict + + +class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + def verify_values(self, verify_dict, actual, varref_dict=None): + if 'equals' in verify_dict: + verify = verify_dict['equals'] + for key in verify: + verify_value = verify[key] + actual_value = actual[key] + self.assertTrue(verify_value == actual_value, + '"%s" keys don\'t match (%s != %s)' % ( + key, actual_value, verify_value)) + if 'startswith' in verify_dict: + verify = verify_dict['startswith'] + for key in verify: + verify_value = verify[key] + actual_value = actual[key] + startswith = actual_value.startswith(verify_value) + self.assertTrue(startswith, + ('"%s" value "%s" doesn\'t start with' + ' "%s")') % ( + key, actual_value, + verify_value)) + hasVariablesReference = 'variablesReference' in actual + varRef = None + if hasVariablesReference: + # Remember variable references in case we want to test further + # by using the evaluate name. + varRef = actual['variablesReference'] + if varRef != 0 and varref_dict is not None: + varref_dict[actual['evaluateName']] = varRef + if ('hasVariablesReference' in verify_dict and + verify_dict['hasVariablesReference']): + self.assertTrue(hasVariablesReference, + "verify variable reference") + if 'children' in verify_dict: + self.assertTrue(hasVariablesReference and varRef is not None and + varRef != 0, + ("children verify values specified for " + "variable without children")) + + response = self.vscode.request_variables(varRef) + self.verify_variables(verify_dict['children'], + response['body']['variables'], + varref_dict) + + def verify_variables(self, verify_dict, variables, varref_dict=None): + for variable in variables: + name = variable['name'] + self.assertTrue(name in verify_dict, + 'variable "%s" in verify dictionary' % (name)) + self.verify_values(verify_dict[name], variable, varref_dict) + + @skipIfWindows + @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots + @no_debug_info_test + def test_scopes_variables_setVariable_evaluate(self): + ''' + Tests the "scopes", "variables", "setVariable", and "evaluate" + packets. + ''' + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + source = 'main.cpp' + breakpoint1_line = line_number(source, '// breakpoint 1') + lines = [breakpoint1_line] + # Set breakoint in the thread function so we can step the threads + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.assertTrue(len(breakpoint_ids) == len(lines), + "expect correct number of breakpoints") + self.continue_to_breakpoints(breakpoint_ids) + locals = self.vscode.get_local_variables() + globals = self.vscode.get_global_variables() + buffer_children = make_buffer_verify_dict(0, 32) + verify_locals = { + 'argc': { + 'equals': {'type': 'int', 'value': '1'} + }, + 'argv': { + 'equals': {'type': 'const char **'}, + 'startswith': {'value': '0x'}, + 'hasVariablesReference': True + }, + 'pt': { + 'equals': {'type': 'PointType'}, + 'hasVariablesReference': True, + 'children': { + 'x': {'equals': {'type': 'int', 'value': '11'}}, + 'y': {'equals': {'type': 'int', 'value': '22'}}, + 'buffer': {'children': buffer_children} + } + } + } + verify_globals = { + 's_local': { + 'equals': {'type': 'float', 'value': '2.25'} + }, + '::g_global': { + 'equals': {'type': 'int', 'value': '123'} + }, + 's_global': { + 'equals': {'type': 'int', 'value': '234'} + }, + } + varref_dict = {} + self.verify_variables(verify_locals, locals, varref_dict) + self.verify_variables(verify_globals, globals, varref_dict) + # pprint.PrettyPrinter(indent=4).pprint(varref_dict) + # We need to test the functionality of the "variables" request as it + # has optional parameters like "start" and "count" to limit the number + # of variables that are fetched + varRef = varref_dict['pt.buffer'] + response = self.vscode.request_variables(varRef) + self.verify_variables(buffer_children, response['body']['variables']) + # Verify setting start=0 in the arguments still gets all children + response = self.vscode.request_variables(varRef, start=0) + self.verify_variables(buffer_children, response['body']['variables']) + # Verify setting count=0 in the arguments still gets all children. + # If count is zero, it means to get all children. + response = self.vscode.request_variables(varRef, count=0) + self.verify_variables(buffer_children, response['body']['variables']) + # Verify setting count to a value that is too large in the arguments + # still gets all children, and no more + response = self.vscode.request_variables(varRef, count=1000) + self.verify_variables(buffer_children, response['body']['variables']) + # Verify setting the start index and count gets only the children we + # want + response = self.vscode.request_variables(varRef, start=5, count=5) + self.verify_variables(make_buffer_verify_dict(5, 5), + response['body']['variables']) + # Verify setting the start index to a value that is out of range + # results in an empty list + response = self.vscode.request_variables(varRef, start=32, count=1) + self.assertTrue(len(response['body']['variables']) == 0, + 'verify we get no variable back for invalid start') + + # Test evaluate + expressions = { + 'pt.x': { + 'equals': {'result': '11', 'type': 'int'}, + 'hasVariablesReference': False + }, + 'pt.buffer[2]': { + 'equals': {'result': '2', 'type': 'int'}, + 'hasVariablesReference': False + }, + 'pt': { + 'equals': {'type': 'PointType'}, + 'startswith': {'result': 'PointType @ 0x'}, + 'hasVariablesReference': True + }, + 'pt.buffer': { + 'equals': {'type': 'int [32]'}, + 'startswith': {'result': 'int [32] @ 0x'}, + 'hasVariablesReference': True + }, + 'argv': { + 'equals': {'type': 'const char **'}, + 'startswith': {'result': '0x'}, + 'hasVariablesReference': True + }, + 'argv[0]': { + 'equals': {'type': 'const char *'}, + 'startswith': {'result': '0x'}, + 'hasVariablesReference': True + }, + '2+3': { + 'equals': {'result': '5', 'type': 'int'}, + 'hasVariablesReference': False + }, + } + for expression in expressions: + response = self.vscode.request_evaluate(expression) + self.verify_values(expressions[expression], response['body']) + + # Test setting variables + self.set_local('argc', 123) + argc = self.get_local_as_int('argc') + self.assertTrue(argc == 123, + 'verify argc was set to 123 (123 != %i)' % (argc)) + + self.set_local('argv', 0x1234) + argv = self.get_local_as_int('argv') + self.assertTrue(argv == 0x1234, + 'verify argv was set to 0x1234 (0x1234 != %#x)' % ( + argv)) + + # Set a variable value whose name is synthetic, like a variable index + # and verify the value by reading it + self.vscode.request_setVariable(varRef, "[0]", 100) + response = self.vscode.request_variables(varRef, start=0, count=1) + self.verify_variables(make_buffer_verify_dict(0, 1, 100), + response['body']['variables']) + + # Set a variable value whose name is a real child value, like "pt.x" + # and verify the value by reading it + varRef = varref_dict['pt'] + self.vscode.request_setVariable(varRef, "x", 111) + response = self.vscode.request_variables(varRef, start=0, count=1) + value = response['body']['variables'][0]['value'] + self.assertTrue(value == '111', + 'verify pt.x got set to 111 (111 != %s)' % (value)) diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp new file mode 100644 index 000000000000..0223bd0a75ea --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp @@ -0,0 +1,18 @@ + +#define BUFFER_SIZE 32 +struct PointType { + int x; + int y; + int buffer[BUFFER_SIZE]; +}; + +int g_global = 123; +static int s_global = 234; + +int main(int argc, char const *argv[]) { + static float s_local = 2.25; + PointType pt = { 11,22, {0}}; + for (int i=0; i<BUFFER_SIZE; ++i) + pt.buffer[i] = i; + return s_global - g_global - pt.y; // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py new file mode 100644 index 000000000000..066158d0877f --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py @@ -0,0 +1,1084 @@ +#!/usr/bin/env python + +import binascii +import json +import optparse +import os +import pprint +import socket +import string +import subprocess +import sys +import threading + + +def dump_memory(base_addr, data, num_per_line, outfile): + + data_len = len(data) + hex_string = binascii.hexlify(data) + addr = base_addr + ascii_str = '' + i = 0 + while i < data_len: + outfile.write('0x%8.8x: ' % (addr + i)) + bytes_left = data_len - i + if bytes_left >= num_per_line: + curr_data_len = num_per_line + else: + curr_data_len = bytes_left + hex_start_idx = i * 2 + hex_end_idx = hex_start_idx + curr_data_len * 2 + curr_hex_str = hex_string[hex_start_idx:hex_end_idx] + # 'curr_hex_str' now contains the hex byte string for the + # current line with no spaces between bytes + t = iter(curr_hex_str) + # Print hex bytes separated by space + outfile.write(' '.join(a + b for a, b in zip(t, t))) + # Print two spaces + outfile.write(' ') + # Calculate ASCII string for bytes into 'ascii_str' + ascii_str = '' + for j in range(i, i + curr_data_len): + ch = data[j] + if ch in string.printable and ch not in string.whitespace: + ascii_str += '%c' % (ch) + else: + ascii_str += '.' + # Print ASCII representation and newline + outfile.write(ascii_str) + i = i + curr_data_len + outfile.write('\n') + + +def read_packet(f, verbose=False, trace_file=None): + '''Decode a JSON packet that starts with the content length and is + followed by the JSON bytes from a file 'f' + ''' + line = f.readline() + if len(line) == 0: + return None + + # Watch for line that starts with the prefix + prefix = 'Content-Length: ' + if line.startswith(prefix): + # Decode length of JSON bytes + if verbose: + print('content: "%s"' % (line)) + length = int(line[len(prefix):]) + if verbose: + print('length: "%u"' % (length)) + # Skip empty line + line = f.readline() + if verbose: + print('empty: "%s"' % (line)) + # Read JSON bytes + json_str = f.read(length) + if verbose: + print('json: "%s"' % (json_str)) + if trace_file: + trace_file.write('from adaptor:\n%s\n' % (json_str)) + # Decode the JSON bytes into a python dictionary + return json.loads(json_str) + + return None + + +def packet_type_is(packet, packet_type): + return 'type' in packet and packet['type'] == packet_type + + +def read_packet_thread(vs_comm): + done = False + while not done: + packet = read_packet(vs_comm.recv, trace_file=vs_comm.trace_file) + if packet: + done = not vs_comm.handle_recv_packet(packet) + else: + done = True + + +class DebugCommunication(object): + + def __init__(self, recv, send): + self.trace_file = None + self.send = send + self.recv = recv + self.recv_packets = [] + self.recv_condition = threading.Condition() + self.recv_thread = threading.Thread(target=read_packet_thread, + args=(self,)) + self.process_event_body = None + self.exit_status = None + self.initialize_body = None + self.thread_stop_reasons = {} + self.sequence = 1 + self.threads = None + self.recv_thread.start() + self.output_condition = threading.Condition() + self.output = {} + self.configuration_done_sent = False + self.frame_scopes = {} + + @classmethod + def encode_content(cls, s): + return "Content-Length: %u\r\n\r\n%s" % (len(s), s) + + @classmethod + def validate_response(cls, command, response): + if command['command'] != response['command']: + raise ValueError('command mismatch in response') + if command['seq'] != response['request_seq']: + raise ValueError('seq mismatch in response') + + def get_output(self, category, timeout=0.0, clear=True): + self.output_condition.acquire() + output = None + if category in self.output: + output = self.output[category] + if clear: + del self.output[category] + elif timeout != 0.0: + self.output_condition.wait(timeout) + if category in self.output: + output = self.output[category] + if clear: + del self.output[category] + self.output_condition.release() + return output + + def handle_recv_packet(self, packet): + '''Called by the read thread that is waiting for all incoming packets + to store the incoming packet in "self.recv_packets" in a thread safe + way. This function will then signal the "self.recv_condition" to + indicate a new packet is available. Returns True if the caller + should keep calling this function for more packets. + ''' + # Check the packet to see if is an event packet + keepGoing = True + packet_type = packet['type'] + if packet_type == 'event': + event = packet['event'] + body = None + if 'body' in packet: + body = packet['body'] + # Handle the event packet and cache information from these packets + # as they come in + if event == 'output': + # Store any output we receive so clients can retrieve it later. + category = body['category'] + output = body['output'] + self.output_condition.acquire() + if category in self.output: + self.output[category] += output + else: + self.output[category] = output + self.output_condition.notify() + self.output_condition.release() + # no need to add 'output' packets to our packets list + return keepGoing + elif event == 'process': + # When a new process is attached or launched, remember the + # details that are available in the body of the event + self.process_event_body = body + elif event == 'stopped': + # Each thread that stops with a reason will send a + # 'stopped' event. We need to remember the thread stop + # reasons since the 'threads' command doesn't return + # that information. + self._process_stopped() + tid = body['threadId'] + self.thread_stop_reasons[tid] = body + elif packet_type == 'response': + if packet['command'] == 'disconnect': + keepGoing = False + self.recv_condition.acquire() + self.recv_packets.append(packet) + self.recv_condition.notify() + self.recv_condition.release() + return keepGoing + + def send_packet(self, command_dict, set_sequence=True): + '''Take the "command_dict" python dictionary and encode it as a JSON + string and send the contents as a packet to the VSCode debug + adaptor''' + # Set the sequence ID for this command automatically + if set_sequence: + command_dict['seq'] = self.sequence + self.sequence += 1 + # Encode our command dictionary as a JSON string + json_str = json.dumps(command_dict, separators=(',', ':')) + if self.trace_file: + self.trace_file.write('to adaptor:\n%s\n' % (json_str)) + length = len(json_str) + if length > 0: + # Send the encoded JSON packet and flush the 'send' file + self.send.write(self.encode_content(json_str)) + self.send.flush() + + def recv_packet(self, filter_type=None, filter_event=None, timeout=None): + '''Get a JSON packet from the VSCode debug adaptor. This function + assumes a thread that reads packets is running and will deliver + any received packets by calling handle_recv_packet(...). This + function will wait for the packet to arrive and return it when + it does.''' + while True: + self.recv_condition.acquire() + packet = None + while True: + for (i, curr_packet) in enumerate(self.recv_packets): + packet_type = curr_packet['type'] + if filter_type is None or packet_type in filter_type: + if (filter_event is None or + (packet_type == 'event' and + curr_packet['event'] in filter_event)): + packet = self.recv_packets.pop(i) + break + if packet: + break + # Sleep until packet is received + len_before = len(self.recv_packets) + self.recv_condition.wait(timeout) + len_after = len(self.recv_packets) + if len_before == len_after: + return None # Timed out + self.recv_condition.release() + return packet + + return None + + def send_recv(self, command): + '''Send a command python dictionary as JSON and receive the JSON + response. Validates that the response is the correct sequence and + command in the reply. Any events that are received are added to the + events list in this object''' + self.send_packet(command) + done = False + while not done: + response = self.recv_packet(filter_type='response') + if response is None: + desc = 'no response for "%s"' % (command['command']) + raise ValueError(desc) + self.validate_response(command, response) + return response + return None + + def wait_for_event(self, filter=None, timeout=None): + while True: + return self.recv_packet(filter_type='event', filter_event=filter, + timeout=timeout) + return None + + def wait_for_stopped(self, timeout=None): + stopped_events = [] + stopped_event = self.wait_for_event(filter=['stopped', 'exited'], + timeout=timeout) + exited = False + while stopped_event: + stopped_events.append(stopped_event) + # If we exited, then we are done + if stopped_event['event'] == 'exited': + self.exit_status = stopped_event['body']['exitCode'] + exited = True + break + # Otherwise we stopped and there might be one or more 'stopped' + # events for each thread that stopped with a reason, so keep + # checking for more 'stopped' events and return all of them + stopped_event = self.wait_for_event(filter='stopped', timeout=0.25) + if exited: + self.threads = [] + return stopped_events + + def wait_for_exited(self): + event_dict = self.wait_for_event('exited') + if event_dict is None: + raise ValueError("didn't get stopped event") + return event_dict + + def get_initialize_value(self, key): + '''Get a value for the given key if it there is a key/value pair in + the "initialize" request response body. + ''' + if self.initialize_body and key in self.initialize_body: + return self.initialize_body[key] + return None + + def get_threads(self): + if self.threads is None: + self.request_threads() + return self.threads + + def get_thread_id(self, threadIndex=0): + '''Utility function to get the first thread ID in the thread list. + If the thread list is empty, then fetch the threads. + ''' + if self.threads is None: + self.request_threads() + if self.threads and threadIndex < len(self.threads): + return self.threads[threadIndex]['id'] + return None + + def get_stackFrame(self, frameIndex=0, threadId=None): + '''Get a single "StackFrame" object from a "stackTrace" request and + return the "StackFrame as a python dictionary, or None on failure + ''' + if threadId is None: + threadId = self.get_thread_id() + if threadId is None: + print('invalid threadId') + return None + response = self.request_stackTrace(threadId, startFrame=frameIndex, + levels=1) + if response: + return response['body']['stackFrames'][0] + print('invalid response') + return None + + def get_scope_variables(self, scope_name, frameIndex=0, threadId=None): + stackFrame = self.get_stackFrame(frameIndex=frameIndex, + threadId=threadId) + if stackFrame is None: + return [] + frameId = stackFrame['id'] + if frameId in self.frame_scopes: + frame_scopes = self.frame_scopes[frameId] + else: + scopes_response = self.request_scopes(frameId) + frame_scopes = scopes_response['body']['scopes'] + self.frame_scopes[frameId] = frame_scopes + for scope in frame_scopes: + if scope['name'] == scope_name: + varRef = scope['variablesReference'] + variables_response = self.request_variables(varRef) + if variables_response: + if 'body' in variables_response: + body = variables_response['body'] + if 'variables' in body: + vars = body['variables'] + return vars + return [] + + def get_global_variables(self, frameIndex=0, threadId=None): + return self.get_scope_variables('Globals', frameIndex=frameIndex, + threadId=threadId) + + def get_local_variables(self, frameIndex=0, threadId=None): + return self.get_scope_variables('Locals', frameIndex=frameIndex, + threadId=threadId) + + def get_local_variable(self, name, frameIndex=0, threadId=None): + locals = self.get_local_variables(frameIndex=frameIndex, + threadId=threadId) + for local in locals: + if 'name' in local and local['name'] == name: + return local + return None + + def get_local_variable_value(self, name, frameIndex=0, threadId=None): + variable = self.get_local_variable(name, frameIndex=frameIndex, + threadId=threadId) + if variable and 'value' in variable: + return variable['value'] + return None + + def replay_packets(self, replay_file_path): + f = open(replay_file_path, 'r') + mode = 'invalid' + set_sequence = False + command_dict = None + while mode != 'eof': + if mode == 'invalid': + line = f.readline() + if line.startswith('to adapter:'): + mode = 'send' + elif line.startswith('from adapter:'): + mode = 'recv' + elif mode == 'send': + command_dict = read_packet(f) + # Skip the end of line that follows the JSON + f.readline() + if command_dict is None: + raise ValueError('decode packet failed from replay file') + print('Sending:') + pprint.PrettyPrinter(indent=2).pprint(command_dict) + # raw_input('Press ENTER to send:') + self.send_packet(command_dict, set_sequence) + mode = 'invalid' + elif mode == 'recv': + print('Replay response:') + replay_response = read_packet(f) + # Skip the end of line that follows the JSON + f.readline() + pprint.PrettyPrinter(indent=2).pprint(replay_response) + actual_response = self.recv_packet() + if actual_response: + type = actual_response['type'] + print('Actual response:') + if type == 'response': + self.validate_response(command_dict, actual_response) + pprint.PrettyPrinter(indent=2).pprint(actual_response) + else: + print("error: didn't get a valid response") + mode = 'invalid' + + def request_attach(self, program=None, pid=None, waitFor=None, trace=None, + initCommands=None, preRunCommands=None, + stopCommands=None, exitCommands=None, + attachCommands=None): + args_dict = {} + if pid is not None: + args_dict['pid'] = pid + if program is not None: + args_dict['program'] = program + if waitFor is not None: + args_dict['waitFor'] = waitFor + if trace: + args_dict['trace'] = trace + if initCommands: + args_dict['initCommands'] = initCommands + if preRunCommands: + args_dict['preRunCommands'] = preRunCommands + if stopCommands: + args_dict['stopCommands'] = stopCommands + if exitCommands: + args_dict['exitCommands'] = exitCommands + if attachCommands: + args_dict['attachCommands'] = attachCommands + command_dict = { + 'command': 'attach', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_configurationDone(self): + command_dict = { + 'command': 'configurationDone', + 'type': 'request', + 'arguments': {} + } + response = self.send_recv(command_dict) + if response: + self.configuration_done_sent = True + return response + + def _process_stopped(self): + self.threads = None + self.frame_scopes = {} + + def request_continue(self, threadId=None): + if self.exit_status is not None: + raise ValueError('request_continue called after process exited') + # If we have launched or attached, then the first continue is done by + # sending the 'configurationDone' request + if not self.configuration_done_sent: + return self.request_configurationDone() + args_dict = {} + if threadId is None: + threadId = self.get_thread_id() + args_dict['threadId'] = threadId + command_dict = { + 'command': 'continue', + 'type': 'request', + 'arguments': args_dict + } + response = self.send_recv(command_dict) + recv_packets = [] + self.recv_condition.acquire() + for event in self.recv_packets: + if event['event'] != 'stopped': + recv_packets.append(event) + self.recv_packets = recv_packets + self.recv_condition.release() + return response + + def request_disconnect(self, terminateDebuggee=None): + args_dict = {} + if terminateDebuggee is not None: + if terminateDebuggee: + args_dict['terminateDebuggee'] = True + else: + args_dict['terminateDebuggee'] = False + command_dict = { + 'command': 'disconnect', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_evaluate(self, expression, frameIndex=0, threadId=None): + stackFrame = self.get_stackFrame(frameIndex=frameIndex, + threadId=threadId) + if stackFrame is None: + return [] + args_dict = { + 'expression': expression, + 'frameId': stackFrame['id'], + } + command_dict = { + 'command': 'evaluate', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_initialize(self): + command_dict = { + 'command': 'initialize', + 'type': 'request', + 'arguments': { + 'adapterID': 'lldb-native', + 'clientID': 'vscode', + 'columnsStartAt1': True, + 'linesStartAt1': True, + 'locale': 'en-us', + 'pathFormat': 'path', + 'supportsRunInTerminalRequest': True, + 'supportsVariablePaging': True, + 'supportsVariableType': True + } + } + response = self.send_recv(command_dict) + if response: + if 'body' in response: + self.initialize_body = response['body'] + return response + + def request_launch(self, program, args=None, cwd=None, env=None, + stopOnEntry=False, disableASLR=True, + disableSTDIO=False, shellExpandArguments=False, + trace=False, initCommands=None, preRunCommands=None, + stopCommands=None, exitCommands=None, sourcePath=None, + debuggerRoot=None): + args_dict = { + 'program': program + } + if args: + args_dict['args'] = args + if cwd: + args_dict['cwd'] = cwd + if env: + args_dict['env'] = env + if stopOnEntry: + args_dict['stopOnEntry'] = stopOnEntry + if disableASLR: + args_dict['disableASLR'] = disableASLR + if disableSTDIO: + args_dict['disableSTDIO'] = disableSTDIO + if shellExpandArguments: + args_dict['shellExpandArguments'] = shellExpandArguments + if trace: + args_dict['trace'] = trace + if initCommands: + args_dict['initCommands'] = initCommands + if preRunCommands: + args_dict['preRunCommands'] = preRunCommands + if stopCommands: + args_dict['stopCommands'] = stopCommands + if exitCommands: + args_dict['exitCommands'] = exitCommands + if sourcePath: + args_dict['sourcePath'] = sourcePath + if debuggerRoot: + args_dict['debuggerRoot'] = debuggerRoot + command_dict = { + 'command': 'launch', + 'type': 'request', + 'arguments': args_dict + } + response = self.send_recv(command_dict) + + # Wait for a 'process' and 'initialized' event in any order + self.wait_for_event(filter=['process', 'initialized']) + self.wait_for_event(filter=['process', 'initialized']) + return response + + def request_next(self, threadId): + if self.exit_status is not None: + raise ValueError('request_continue called after process exited') + args_dict = {'threadId': threadId} + command_dict = { + 'command': 'next', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_stepIn(self, threadId): + if self.exit_status is not None: + raise ValueError('request_continue called after process exited') + args_dict = {'threadId': threadId} + command_dict = { + 'command': 'stepIn', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_stepOut(self, threadId): + if self.exit_status is not None: + raise ValueError('request_continue called after process exited') + args_dict = {'threadId': threadId} + command_dict = { + 'command': 'stepOut', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_pause(self, threadId=None): + if self.exit_status is not None: + raise ValueError('request_continue called after process exited') + if threadId is None: + threadId = self.get_thread_id() + args_dict = {'threadId': threadId} + command_dict = { + 'command': 'pause', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_scopes(self, frameId): + args_dict = {'frameId': frameId} + command_dict = { + 'command': 'scopes', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_setBreakpoints(self, file_path, line_array, condition=None, + hitCondition=None): + (dir, base) = os.path.split(file_path) + breakpoints = [] + for line in line_array: + bp = {'line': line} + if condition is not None: + bp['condition'] = condition + if hitCondition is not None: + bp['hitCondition'] = hitCondition + breakpoints.append(bp) + source_dict = { + 'name': base, + 'path': file_path + } + args_dict = { + 'source': source_dict, + 'breakpoints': breakpoints, + 'lines': '%s' % (line_array), + 'sourceModified': False, + } + command_dict = { + 'command': 'setBreakpoints', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_setExceptionBreakpoints(self, filters): + args_dict = {'filters': filters} + command_dict = { + 'command': 'setExceptionBreakpoints', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_setFunctionBreakpoints(self, names, condition=None, + hitCondition=None): + breakpoints = [] + for name in names: + bp = {'name': name} + if condition is not None: + bp['condition'] = condition + if hitCondition is not None: + bp['hitCondition'] = hitCondition + breakpoints.append(bp) + args_dict = {'breakpoints': breakpoints} + command_dict = { + 'command': 'setFunctionBreakpoints', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_stackTrace(self, threadId=None, startFrame=None, levels=None, + dump=False): + if threadId is None: + threadId = self.get_thread_id() + args_dict = {'threadId': threadId} + if startFrame is not None: + args_dict['startFrame'] = startFrame + if levels is not None: + args_dict['levels'] = levels + command_dict = { + 'command': 'stackTrace', + 'type': 'request', + 'arguments': args_dict + } + response = self.send_recv(command_dict) + if dump: + for (idx, frame) in enumerate(response['body']['stackFrames']): + name = frame['name'] + if 'line' in frame and 'source' in frame: + source = frame['source'] + if 'sourceReference' not in source: + if 'name' in source: + source_name = source['name'] + line = frame['line'] + print("[%3u] %s @ %s:%u" % (idx, name, source_name, + line)) + continue + print("[%3u] %s" % (idx, name)) + return response + + def request_threads(self): + '''Request a list of all threads and combine any information from any + "stopped" events since those contain more information about why a + thread actually stopped. Returns an array of thread dictionaries + with information about all threads''' + command_dict = { + 'command': 'threads', + 'type': 'request', + 'arguments': {} + } + response = self.send_recv(command_dict) + body = response['body'] + # Fill in "self.threads" correctly so that clients that call + # self.get_threads() or self.get_thread_id(...) can get information + # on threads when the process is stopped. + if 'threads' in body: + self.threads = body['threads'] + for thread in self.threads: + # Copy the thread dictionary so we can add key/value pairs to + # it without affecfting the original info from the "threads" + # command. + tid = thread['id'] + if tid in self.thread_stop_reasons: + thread_stop_info = self.thread_stop_reasons[tid] + copy_keys = ['reason', 'description', 'text'] + for key in copy_keys: + if key in thread_stop_info: + thread[key] = thread_stop_info[key] + else: + self.threads = None + return response + + def request_variables(self, variablesReference, start=None, count=None): + args_dict = {'variablesReference': variablesReference} + if start is not None: + args_dict['start'] = start + if count is not None: + args_dict['count'] = count + command_dict = { + 'command': 'variables', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_setVariable(self, containingVarRef, name, value, id=None): + args_dict = { + 'variablesReference': containingVarRef, + 'name': name, + 'value': str(value) + } + if id is not None: + args_dict['id'] = id + command_dict = { + 'command': 'setVariable', + 'type': 'request', + 'arguments': args_dict + } + return self.send_recv(command_dict) + + def request_testGetTargetBreakpoints(self): + '''A request packet used in the LLDB test suite to get all currently + set breakpoint infos for all breakpoints currently set in the + target. + ''' + command_dict = { + 'command': '_testGetTargetBreakpoints', + 'type': 'request', + 'arguments': {} + } + return self.send_recv(command_dict) + + def terminate(self): + self.send.close() + # self.recv.close() + + +class DebugAdaptor(DebugCommunication): + def __init__(self, executable=None, port=None): + self.process = None + if executable is not None: + self.process = subprocess.Popen([executable], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + DebugCommunication.__init__(self, self.process.stdout, + self.process.stdin) + elif port is not None: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(('127.0.0.1', port)) + DebugCommunication.__init__(self, s.makefile('r'), s.makefile('w')) + + def get_pid(self): + if self.process: + return self.process.pid + return -1 + + def terminate(self): + super(DebugAdaptor, self).terminate() + if self.process is not None: + self.process.terminate() + self.process.wait() + self.process = None + + +def attach_options_specified(options): + if options.pid is not None: + return True + if options.waitFor: + return True + if options.attach: + return True + if options.attachCmds: + return True + return False + + +def run_vscode(dbg, args, options): + dbg.request_initialize() + if attach_options_specified(options): + response = dbg.request_attach(program=options.program, + pid=options.pid, + waitFor=options.waitFor, + attachCommands=options.attachCmds, + initCommands=options.initCmds, + preRunCommands=options.preRunCmds, + stopCommands=options.stopCmds, + exitCommands=options.exitCmds) + else: + response = dbg.request_launch(options.program, + args=args, + env=options.envs, + cwd=options.workingDir, + debuggerRoot=options.debuggerRoot, + sourcePath=options.sourcePath, + initCommands=options.initCmds, + preRunCommands=options.preRunCmds, + stopCommands=options.stopCmds, + exitCommands=options.exitCmds) + + if response['success']: + if options.sourceBreakpoints: + source_to_lines = {} + for file_line in options.sourceBreakpoints: + (path, line) = file_line.split(':') + if len(path) == 0 or len(line) == 0: + print('error: invalid source with line "%s"' % + (file_line)) + + else: + if path in source_to_lines: + source_to_lines[path].append(int(line)) + else: + source_to_lines[path] = [int(line)] + for source in source_to_lines: + dbg.request_setBreakpoints(source, source_to_lines[source]) + if options.funcBreakpoints: + dbg.request_setFunctionBreakpoints(options.funcBreakpoints) + dbg.request_configurationDone() + dbg.wait_for_stopped() + else: + if 'message' in response: + print(response['message']) + dbg.request_disconnect(terminateDebuggee=True) + + +def main(): + parser = optparse.OptionParser( + description=('A testing framework for the Visual Studio Code Debug ' + 'Adaptor protocol')) + + parser.add_option( + '--vscode', + type='string', + dest='vscode_path', + help=('The path to the command line program that implements the ' + 'Visual Studio Code Debug Adaptor protocol.'), + default=None) + + parser.add_option( + '--program', + type='string', + dest='program', + help='The path to the program to debug.', + default=None) + + parser.add_option( + '--workingDir', + type='string', + dest='workingDir', + default=None, + help='Set the working directory for the process we launch.') + + parser.add_option( + '--sourcePath', + type='string', + dest='sourcePath', + default=None, + help=('Set the relative source root for any debug info that has ' + 'relative paths in it.')) + + parser.add_option( + '--debuggerRoot', + type='string', + dest='debuggerRoot', + default=None, + help=('Set the working directory for lldb-vscode for any object files ' + 'with relative paths in the Mach-o debug map.')) + + parser.add_option( + '-r', '--replay', + type='string', + dest='replay', + help=('Specify a file containing a packet log to replay with the ' + 'current Visual Studio Code Debug Adaptor executable.'), + default=None) + + parser.add_option( + '-g', '--debug', + action='store_true', + dest='debug', + default=False, + help='Pause waiting for a debugger to attach to the debug adaptor') + + parser.add_option( + '--port', + type='int', + dest='port', + help="Attach a socket to a port instead of using STDIN for VSCode", + default=None) + + parser.add_option( + '--pid', + type='int', + dest='pid', + help="The process ID to attach to", + default=None) + + parser.add_option( + '--attach', + action='store_true', + dest='attach', + default=False, + help=('Specify this option to attach to a process by name. The ' + 'process name is the basanme of the executable specified with ' + 'the --program option.')) + + parser.add_option( + '-f', '--function-bp', + type='string', + action='append', + dest='funcBreakpoints', + help=('Specify the name of a function to break at. ' + 'Can be specified more than once.'), + default=[]) + + parser.add_option( + '-s', '--source-bp', + type='string', + action='append', + dest='sourceBreakpoints', + default=[], + help=('Specify source breakpoints to set in the format of ' + '<source>:<line>. ' + 'Can be specified more than once.')) + + parser.add_option( + '--attachCommand', + type='string', + action='append', + dest='attachCmds', + default=[], + help=('Specify a LLDB command that will attach to a process. ' + 'Can be specified more than once.')) + + parser.add_option( + '--initCommand', + type='string', + action='append', + dest='initCmds', + default=[], + help=('Specify a LLDB command that will be executed before the target ' + 'is created. Can be specified more than once.')) + + parser.add_option( + '--preRunCommand', + type='string', + action='append', + dest='preRunCmds', + default=[], + help=('Specify a LLDB command that will be executed after the target ' + 'has been created. Can be specified more than once.')) + + parser.add_option( + '--stopCommand', + type='string', + action='append', + dest='stopCmds', + default=[], + help=('Specify a LLDB command that will be executed each time the' + 'process stops. Can be specified more than once.')) + + parser.add_option( + '--exitCommand', + type='string', + action='append', + dest='exitCmds', + default=[], + help=('Specify a LLDB command that will be executed when the process ' + 'exits. Can be specified more than once.')) + + parser.add_option( + '--env', + type='string', + action='append', + dest='envs', + default=[], + help=('Specify environment variables to pass to the launched ' + 'process.')) + + parser.add_option( + '--waitFor', + action='store_true', + dest='waitFor', + default=False, + help=('Wait for the next process to be launched whose name matches ' + 'the basename of the program specified with the --program ' + 'option')) + + (options, args) = parser.parse_args(sys.argv[1:]) + + if options.vscode_path is None and options.port is None: + print('error: must either specify a path to a Visual Studio Code ' + 'Debug Adaptor vscode executable path using the --vscode ' + 'option, or a port to attach to for an existing lldb-vscode ' + 'using the --port option') + return + dbg = DebugAdaptor(executable=options.vscode_path, port=options.port) + if options.debug: + raw_input('Waiting for debugger to attach pid "%i"' % ( + dbg.get_pid())) + if options.replay: + dbg.replay_packets(options.replay) + else: + run_vscode(dbg, args, options) + dbg.terminate() + + +if __name__ == '__main__': + main() |