119 lines
5.8 KiB
Python
119 lines
5.8 KiB
Python
"""
|
|
Test lldb-vscode setBreakpoints request
|
|
"""
|
|
|
|
|
|
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_breakpointEvents(lldbvscode_testcase.VSCodeTestCaseBase):
|
|
|
|
mydir = TestBase.compute_mydir(__file__)
|
|
|
|
@skipIfWindows
|
|
@skipUnlessDarwin
|
|
def test_breakpoint_events(self):
|
|
'''
|
|
This test sets a breakpoint in a shared library and runs and stops
|
|
at the entry point of a program. When we stop at the entry point,
|
|
the shared library won't be loaded yet. At this point the
|
|
breakpoint should set itself, but not be verified because no
|
|
locations are resolved. We will then continue and expect to get a
|
|
breakpoint event that informs us that the breakpoint in the shared
|
|
library is "changed" and the correct line number should be
|
|
supplied. We also set a breakpoint using a LLDB command using the
|
|
"preRunCommands" when launching our program. Any breakpoints set via
|
|
the command interpreter should not be have breakpoint events sent
|
|
back to VS Code as the UI isn't able to add new breakpoints to
|
|
their UI. Code has been added that tags breakpoints set from VS Code
|
|
DAP packets so we know the IDE knows about them. If VS Code is ever
|
|
able to register breakpoints that aren't initially set in the GUI,
|
|
then we will need to revise this.
|
|
'''
|
|
main_source_basename = 'main.cpp'
|
|
main_source_path = os.path.join(os.getcwd(), main_source_basename)
|
|
foo_source_basename = 'foo.cpp'
|
|
foo_source_path = os.path.join(os.getcwd(), foo_source_basename)
|
|
main_bp_line = line_number('main.cpp', 'main breakpoint 1')
|
|
foo_bp1_line = line_number('foo.cpp', 'foo breakpoint 1')
|
|
foo_bp2_line = line_number('foo.cpp', 'foo breakpoint 2')
|
|
|
|
# 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")
|
|
|
|
# Set a breakpoint after creating the target by running a command line
|
|
# command. It will eventually resolve and cause a breakpoint changed
|
|
# event to be sent to lldb-vscode. We want to make sure we don't send a
|
|
# breakpoint any breakpoints that were set from the command line.
|
|
# Breakpoints that are set via the VS code DAP packets will be
|
|
# registered and marked with a special keyword to ensure we deliver
|
|
# breakpoint events for these breakpoints but not for ones that are not
|
|
# set via the command interpreter.
|
|
bp_command = 'breakpoint set --file foo.cpp --line %u' % (foo_bp2_line)
|
|
self.build_and_launch(program, stopOnEntry=True,
|
|
preRunCommands=[bp_command])
|
|
main_bp_id = 0
|
|
foo_bp_id = 0
|
|
# Set breakpoints and verify that they got set correctly
|
|
vscode_breakpoint_ids = []
|
|
response = self.vscode.request_setBreakpoints(main_source_path,
|
|
[main_bp_line])
|
|
if response:
|
|
breakpoints = response['body']['breakpoints']
|
|
for breakpoint in breakpoints:
|
|
main_bp_id = breakpoint['id']
|
|
vscode_breakpoint_ids.append("%i" % (main_bp_id))
|
|
# line = breakpoint['line']
|
|
self.assertTrue(breakpoint['verified'],
|
|
"expect main breakpoint to be verified")
|
|
|
|
response = self.vscode.request_setBreakpoints(foo_source_path,
|
|
[foo_bp1_line])
|
|
if response:
|
|
breakpoints = response['body']['breakpoints']
|
|
for breakpoint in breakpoints:
|
|
foo_bp_id = breakpoint['id']
|
|
vscode_breakpoint_ids.append("%i" % (foo_bp_id))
|
|
self.assertFalse(breakpoint['verified'],
|
|
"expect foo breakpoint to not be verified")
|
|
|
|
# Get the stop at the entry point
|
|
self.continue_to_next_stop()
|
|
|
|
# We are now stopped at the entry point to the program. Shared
|
|
# libraries are not loaded yet (at least on macOS they aren't) and any
|
|
# breakpoints set in foo.cpp should not be resolved.
|
|
self.assertTrue(len(self.vscode.breakpoint_events) == 0,
|
|
"no breakpoint events when stopped at entry point")
|
|
|
|
# Continue to the breakpoint
|
|
self.continue_to_breakpoints(vscode_breakpoint_ids)
|
|
|
|
# Make sure we only get an event for the breakpoint we set via a call
|
|
# to self.vscode.request_setBreakpoints(...), not the breakpoint
|
|
# we set with with a LLDB command in preRunCommands.
|
|
self.assertTrue(len(self.vscode.breakpoint_events) == 1,
|
|
"make sure we got a breakpoint event")
|
|
event = self.vscode.breakpoint_events[0]
|
|
# Verify the details of the breakpoint changed notification.
|
|
body = event['body']
|
|
self.assertTrue(body['reason'] == 'changed',
|
|
"breakpoint event is says breakpoint is changed")
|
|
breakpoint = body['breakpoint']
|
|
self.assertTrue(breakpoint['verified'] == True,
|
|
"breakpoint event is says it is verified")
|
|
self.assertTrue(breakpoint['id'] == foo_bp_id,
|
|
"breakpoint event is for breakpoint %i" % (foo_bp_id))
|
|
self.assertTrue('line' in breakpoint and breakpoint['line'] > 0,
|
|
"breakpoint event is has a line number")
|
|
self.assertNotIn("source", breakpoint,
|
|
"breakpoint event should not return a source object")
|