Skip to content

Commit 8b98f3e

Browse files
committed
Add rich inspection tests
1 parent 46e6e32 commit 8b98f3e

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed

ipykernel/tests/test_debugger.py

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import pytest
2+
3+
from .utils import execute, new_kernel, get_reply
4+
5+
seq = 0
6+
7+
8+
def wait_for_debug_request(kernel, command, arguments=None):
9+
"""Carry out a debug request and return the reply content.
10+
11+
It does not check if the request was successful.
12+
"""
13+
global seq
14+
seq += 1
15+
16+
msg = kernel.session.msg(
17+
"debug_request",
18+
{
19+
"type": "request",
20+
"seq": seq,
21+
"command": command,
22+
"arguments": arguments or {},
23+
},
24+
)
25+
kernel.control_channel.send(msg)
26+
reply = get_reply(kernel, msg["header"]["msg_id"], channel="control")
27+
return reply["content"]
28+
29+
30+
@pytest.fixture
31+
def kernel():
32+
with new_kernel() as kc:
33+
yield kc
34+
35+
36+
@pytest.fixture
37+
def kernel_with_debug(kernel):
38+
# Initialize
39+
wait_for_debug_request(
40+
kernel,
41+
"initialize",
42+
{
43+
"clientID": "test-client",
44+
"clientName": "testClient",
45+
"adapterID": "",
46+
"pathFormat": "path",
47+
"linesStartAt1": True,
48+
"columnsStartAt1": True,
49+
"supportsVariableType": True,
50+
"supportsVariablePaging": True,
51+
"supportsRunInTerminalRequest": True,
52+
"locale": "en",
53+
},
54+
)
55+
56+
# Attach
57+
wait_for_debug_request(kernel, "attach")
58+
59+
try:
60+
yield kernel
61+
finally:
62+
# Detach
63+
wait_for_debug_request(
64+
kernel, "disconnect", {"restart": False, "terminateDebuggee": True}
65+
)
66+
67+
68+
def test_debug_initialize(kernel):
69+
reply = wait_for_debug_request(
70+
kernel,
71+
"initialize",
72+
{
73+
"clientID": "test-client",
74+
"clientName": "testClient",
75+
"adapterID": "",
76+
"pathFormat": "path",
77+
"linesStartAt1": True,
78+
"columnsStartAt1": True,
79+
"supportsVariableType": True,
80+
"supportsVariablePaging": True,
81+
"supportsRunInTerminalRequest": True,
82+
"locale": "en",
83+
},
84+
)
85+
assert reply["success"]
86+
87+
88+
def test_attach_debug(kernel_with_debug):
89+
reply = wait_for_debug_request(
90+
kernel_with_debug, "evaluate", {"expression": "'a' + 'b'", "context": "repl"}
91+
)
92+
assert reply["success"]
93+
assert reply["body"]["result"] == ""
94+
95+
96+
def test_set_breakpoints(kernel_with_debug):
97+
code = """def f(a, b):
98+
c = a + b
99+
return c
100+
101+
f(2, 3)"""
102+
103+
r = wait_for_debug_request(kernel_with_debug, "dumpCell", {"code": code})
104+
source = r["body"]["sourcePath"]
105+
106+
reply = wait_for_debug_request(
107+
kernel_with_debug,
108+
"setBreakpoints",
109+
{
110+
"breakpoints": [{"line": 2}],
111+
"source": {"path": source},
112+
"sourceModified": False,
113+
},
114+
)
115+
assert reply["success"]
116+
assert len(reply["body"]["breakpoints"]) == 1
117+
assert reply["body"]["breakpoints"][0]["verified"]
118+
assert reply["body"]["breakpoints"][0]["source"]["path"] == source
119+
120+
r = wait_for_debug_request(kernel_with_debug, "debugInfo")
121+
assert source in map(lambda b: b["source"], r["body"]["breakpoints"])
122+
123+
r = wait_for_debug_request(kernel_with_debug, "configurationDone")
124+
assert r["success"]
125+
126+
127+
def test_rich_inspect_not_at_breakpoint(kernel_with_debug):
128+
var_name = "text"
129+
value = "Hello the world"
130+
code = """{0}='{1}'
131+
print({0})
132+
""".format(var_name, value)
133+
134+
msg_id = kernel_with_debug.execute(code)
135+
get_reply(kernel_with_debug, msg_id)
136+
137+
r = wait_for_debug_request(kernel_with_debug, "inspectVariables")
138+
assert var_name in list(map(lambda v: v["name"], r["body"]["variables"]))
139+
140+
reply = wait_for_debug_request(
141+
kernel_with_debug,
142+
"richInspectVariables",
143+
{"variableName": var_name},
144+
)
145+
146+
assert reply["body"]["data"] == {"text/plain": "'{}'".format(value)}
147+
148+
149+
def test_rich_inspect_at_breakpoint(kernel_with_debug):
150+
code = """def f(a, b):
151+
c = a + b
152+
return c
153+
154+
f(2, 3)"""
155+
156+
r = wait_for_debug_request(kernel_with_debug, "dumpCell", {"code": code})
157+
source = r["body"]["sourcePath"]
158+
159+
wait_for_debug_request(
160+
kernel_with_debug,
161+
"setBreakpoints",
162+
{
163+
"breakpoints": [{"line": 2}],
164+
"source": {"path": source},
165+
"sourceModified": False,
166+
},
167+
)
168+
169+
r = wait_for_debug_request(kernel_with_debug, "debugInfo")
170+
171+
r = wait_for_debug_request(kernel_with_debug, "configurationDone")
172+
173+
kernel_with_debug.execute(code)
174+
175+
stacks = wait_for_debug_request(kernel_with_debug, "stackTrace", {"threadId": 1})[
176+
"body"
177+
]["stackFrames"]
178+
179+
scopes = wait_for_debug_request(
180+
kernel_with_debug, "scopes", {"frameId": stacks[0]["id"]}
181+
)["body"]["scopes"]
182+
183+
locals_ = wait_for_debug_request(
184+
kernel_with_debug,
185+
"variables",
186+
{
187+
"variablesReference": next(filter(lambda s: s["name"] == "Locals", scopes))[
188+
"variablesReference"
189+
]
190+
},
191+
)["body"]["variables"]
192+
193+
reply = wait_for_debug_request(
194+
kernel_with_debug,
195+
"richInspectVariables",
196+
{"variableName": locals_[0]["name"], "frameId": stacks[0]["id"]},
197+
)
198+
199+
assert reply["body"]["data"] == {"text/plain": locals_[0]["value"]}

0 commit comments

Comments
 (0)