forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 338
/
Copy pathTestDAP_breakpointEvents.py
132 lines (120 loc) · 6.08 KB
/
TestDAP_breakpointEvents.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
Test lldb-dap setBreakpoints request
"""
import dap_server
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import lldbdap_testcase
import os
class TestDAP_breakpointEvents(lldbdap_testcase.DAPTestCaseBase):
@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-dap. 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
dap_breakpoint_ids = []
response = self.dap_server.request_setBreakpoints(
main_source_path, [main_bp_line]
)
self.assertTrue(response)
breakpoints = response["body"]["breakpoints"]
for breakpoint in breakpoints:
main_bp_id = breakpoint["id"]
dap_breakpoint_ids.append("%i" % (main_bp_id))
self.assertTrue(
breakpoint["verified"], "expect main breakpoint to be verified"
)
response = self.dap_server.request_setBreakpoints(
foo_source_path, [foo_bp1_line]
)
self.assertTrue(response)
breakpoints = response["body"]["breakpoints"]
for breakpoint in breakpoints:
foo_bp_id = breakpoint["id"]
dap_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 only
# the breakpoint in the main executable should be resolved.
self.assertEqual(len(self.dap_server.breakpoint_events), 1)
event = self.dap_server.breakpoint_events[0]
body = event["body"]
self.assertEqual(
body["reason"], "changed", "breakpoint event should say changed"
)
breakpoint = body["breakpoint"]
self.assertEqual(breakpoint["id"], main_bp_id)
self.assertTrue(breakpoint["verified"], "main breakpoint should be resolved")
# Clear the list of breakpoint events so we don't see this one again.
self.dap_server.breakpoint_events.clear()
# Continue to the breakpoint
self.continue_to_breakpoints(dap_breakpoint_ids)
# When the process launches, we first expect to see both the main and
# foo breakpoint as unresolved.
for event in self.dap_server.breakpoint_events[:2]:
body = event["body"]
self.assertEqual(
body["reason"], "changed", "breakpoint event should say changed"
)
breakpoint = body["breakpoint"]
self.assertIn(str(breakpoint["id"]), dap_breakpoint_ids)
self.assertFalse(breakpoint["verified"], "breakpoint should be unresolved")
# Then, once the dynamic loader has given us a load address, they
# should show up as resolved again.
for event in self.dap_server.breakpoint_events[3:]:
body = event["body"]
self.assertEqual(
body["reason"], "changed", "breakpoint event should say changed"
)
breakpoint = body["breakpoint"]
self.assertIn(str(breakpoint["id"]), dap_breakpoint_ids)
self.assertTrue(breakpoint["verified"], "breakpoint should be resolved")
self.assertNotIn(
"source",
breakpoint,
"breakpoint event should not return a source object",
)
self.assertIn("line", breakpoint, "breakpoint event should have line")