summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2018-08-16 17:59:38 +0000
committerGreg Clayton <gclayton@apple.com>2018-08-16 17:59:38 +0000
commit2f5cf8511a3f0ad97db2acf51c6c9ea0ddc9da92 (patch)
tree43ad29bf650e6570830784ff0aa4cfc2ccab5807 /lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint
parentcecc9f5828615c07192a31c7ba8cfda5d26f3cfc (diff)
downloadbcm5719-llvm-2f5cf8511a3f0ad97db2acf51c6c9ea0ddc9da92.tar.gz
bcm5719-llvm-2f5cf8511a3f0ad97db2acf51c6c9ea0ddc9da92.zip
Add a new tool named "lldb-vscode" that implements the Visual Studio Code Debug Adaptor Protocol
This patch adds a new lldb-vscode tool that speaks the Microsoft Visual Studio Code debug adaptor protocol. It has full unit tests that test all packets. This tool can be easily packaged up into a native extension and used with Visual Studio Code, and it can also be used by Nuclide Differential Revision: https://reviews.llvm.org/D50365 llvm-svn: 339911
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint')
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py209
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py50
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py164
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp27
5 files changed, 455 insertions, 0 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile
new file mode 100644
index 00000000000..314f1cb2f07
--- /dev/null
+++ b/lldb/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/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py
new file mode 100644
index 00000000000..4a54ec4f6d7
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py
@@ -0,0 +1,209 @@
+"""
+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
+ @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
+ @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/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py
new file mode 100644
index 00000000000..17c87de0880
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py
@@ -0,0 +1,50 @@
+"""
+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
+ @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/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py
new file mode 100644
index 00000000000..8f07cb07dcf
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py
@@ -0,0 +1,164 @@
+"""
+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
+ @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
+ @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/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp
new file mode 100644
index 00000000000..e859b04e3a9
--- /dev/null
+++ b/lldb/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;
+}
OpenPOWER on IntegriCloud