mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Track threads more carefully.
This commit is contained in:
parent
024906202d
commit
43bea57b03
2 changed files with 157 additions and 180 deletions
|
|
@ -1,6 +1,5 @@
|
|||
from collections import namedtuple
|
||||
import contextlib
|
||||
import itertools
|
||||
import platform
|
||||
try:
|
||||
import urllib.parse as urllib
|
||||
|
|
@ -343,7 +342,7 @@ class VSCLifecycle(object):
|
|||
start()
|
||||
yield
|
||||
|
||||
def _handshake(self, command, threads=None, config=None,
|
||||
def _handshake(self, command, threadnames=None, config=None,
|
||||
default_threads=True, process=True, reset=True,
|
||||
**kwargs):
|
||||
initargs = dict(
|
||||
|
|
@ -354,8 +353,8 @@ class VSCLifecycle(object):
|
|||
self._initialize(**initargs)
|
||||
self._fix.send_request(command, **kwargs)
|
||||
|
||||
if threads:
|
||||
self._fix.set_threads(*threads,
|
||||
if threadnames:
|
||||
self._fix.set_threads(*threadnames,
|
||||
**dict(default_threads=default_threads))
|
||||
|
||||
self._handle_config(**config or {})
|
||||
|
|
@ -473,13 +472,16 @@ class PyDevdFixture(FixtureBase):
|
|||
if new_fake is None:
|
||||
new_fake = self.FAKE
|
||||
super(PyDevdFixture, self).__init__(new_fake, self.MSGS)
|
||||
self._default_threads = None
|
||||
self._threads = Threads()
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
return self._threads
|
||||
|
||||
def notify_main_thread(self):
|
||||
main = (1, 'MainThead')
|
||||
self.send_event(
|
||||
CMD_THREAD_CREATE,
|
||||
self.msgs.format_threads(main),
|
||||
self.msgs.format_threads(self._threads.main),
|
||||
)
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
|
@ -497,39 +499,9 @@ class PyDevdFixture(FixtureBase):
|
|||
event = self.msgs.new_event(cmdid, payload)
|
||||
self.fake.send_event(event)
|
||||
|
||||
def set_threads_response(self, threads, default_threads=True):
|
||||
threads = [Thread.from_raw(t) for t in threads]
|
||||
if default_threads:
|
||||
threads = self._add_default_threads(threads)
|
||||
|
||||
text = self.msgs.format_threads(*threads)
|
||||
def set_threads_response(self):
|
||||
text = self.msgs.format_threads(*self._threads.alive)
|
||||
self.set_response(CMD_RETURN, text, reqid=CMD_LIST_THREADS)
|
||||
return threads
|
||||
|
||||
def _add_default_threads(self, threads):
|
||||
if self._default_threads is not None:
|
||||
return threads
|
||||
defaults = {
|
||||
'MainThread',
|
||||
'ptvsd.Server',
|
||||
'pydevd.thread1',
|
||||
'pydevd.thread2',
|
||||
}
|
||||
seen = set()
|
||||
for thread in threads:
|
||||
tid, tname = thread
|
||||
seen.add(tid)
|
||||
if tname in defaults:
|
||||
defaults.remove(tname)
|
||||
ids = (id for id in itertools.count(1) if id not in seen)
|
||||
allthreads = []
|
||||
for tname in defaults:
|
||||
tid = next(ids)
|
||||
thread = Thread(tid, tname)
|
||||
allthreads.append(thread)
|
||||
self._default_threads = list(allthreads)
|
||||
allthreads.extend(threads)
|
||||
return allthreads
|
||||
|
||||
def send_suspend_event(self, thread, reason, *stack):
|
||||
thread = Thread.from_raw(thread)
|
||||
|
|
@ -664,7 +636,13 @@ class HighlevelFixture(object):
|
|||
DAEMON = FakeVSC
|
||||
DEBUGGER = FakePyDevd
|
||||
|
||||
def __init__(self, vsc=None, pydevd=None):
|
||||
DEFAULT_THREADS = [
|
||||
'ptvsd.Server',
|
||||
'pydevd.thread1',
|
||||
'pydevd.thread2',
|
||||
]
|
||||
|
||||
def __init__(self, vsc=None, pydevd=None, mainthread=True):
|
||||
if vsc is None:
|
||||
self._new_vsc = self.DAEMON
|
||||
vsc = VSCFixture(new_fake=self._new_fake_vsc)
|
||||
|
|
@ -686,6 +664,11 @@ class HighlevelFixture(object):
|
|||
return _cls(fix, pydevd, self.hidden)
|
||||
vsc.LIFECYCLE = highlevel_lifecycle
|
||||
|
||||
self._default_threads = None
|
||||
self._known_threads = set()
|
||||
if mainthread:
|
||||
self._known_threads.add(self._pydevd.threads.main)
|
||||
|
||||
def _new_fake_vsc(self, start_adapter=None, handler=None):
|
||||
if start_adapter is None:
|
||||
try:
|
||||
|
|
@ -717,6 +700,10 @@ class HighlevelFixture(object):
|
|||
def lifecycle(self):
|
||||
return self._vsc.lifecycle
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
return self._pydevd.threads
|
||||
|
||||
@property
|
||||
def ishidden(self):
|
||||
return self._vsc.ishidden and self._pydevd.ishidden
|
||||
|
|
@ -744,6 +731,14 @@ class HighlevelFixture(object):
|
|||
|
||||
# wrappers
|
||||
|
||||
def set_default_threads(self):
|
||||
if self._default_threads is not None:
|
||||
return
|
||||
self._default_threads = {}
|
||||
for name in self.DEFAULT_THREADS:
|
||||
thread = self._pydevd.threads.add(name)
|
||||
self._default_threads[name] = thread
|
||||
|
||||
def send_request(self, command, args=None, handle_response=None):
|
||||
return self._vsc.send_request(command, args, handle_response)
|
||||
|
||||
|
|
@ -778,46 +773,54 @@ class HighlevelFixture(object):
|
|||
self.send_debugger_event(cmdid, text)
|
||||
return None
|
||||
|
||||
def set_threads(self, _thread, *threads, **kwargs):
|
||||
first = Thread.from_raw(_thread)
|
||||
threads = [first] + [Thread.from_raw(t) for t in threads]
|
||||
return self._set_threads(threads, **kwargs)
|
||||
def set_threads(self, _threadname, *threadnames, **kwargs):
|
||||
threadnames = (_threadname,) + threadnames
|
||||
return self._set_threads(threadnames, **kwargs)
|
||||
|
||||
def set_thread(self, thread):
|
||||
thread = Thread.from_raw(thread)
|
||||
threads = (thread,)
|
||||
return self._set_threads(threads)[thread]
|
||||
def set_thread(self, threadname):
|
||||
threadnames = (threadname,)
|
||||
return self._set_threads(threadnames)[0]
|
||||
|
||||
def _set_threads(self, threads, default_threads=True):
|
||||
# Set up and send messages.
|
||||
allthreads = self._pydevd.set_threads_response(
|
||||
threads,
|
||||
default_threads=default_threads,
|
||||
)
|
||||
def _set_threads(self, threadnames, default_threads=True):
|
||||
# Update the list of "alive" threads.
|
||||
self._pydevd.threads.clear(keep=self.DEFAULT_THREADS)
|
||||
if default_threads:
|
||||
self.set_default_threads()
|
||||
request = {}
|
||||
threads = []
|
||||
for i, name in enumerate(threadnames):
|
||||
thread = self._pydevd.threads.add(name)
|
||||
threads.append(thread)
|
||||
request[thread.name] = i
|
||||
ignored = ('ptvsd.', 'pydevd.')
|
||||
supported = [t for t in allthreads if not t.name.startswith(ignored)]
|
||||
with self._vsc._wait_for_events(['thread' for _ in supported]):
|
||||
newthreads = [t
|
||||
for t in self._pydevd.threads.alive
|
||||
if not t.name.startswith(ignored) and
|
||||
t not in self._known_threads]
|
||||
|
||||
# Send and handle messages.
|
||||
self._pydevd.set_threads_response()
|
||||
with self._vsc._wait_for_events(['thread' for _ in newthreads]):
|
||||
self.send_request('threads')
|
||||
self._known_threads.update(newthreads)
|
||||
|
||||
# Extract thread info from the response.
|
||||
request = {t.name: t for t in threads}
|
||||
response = {t: None for t in threads}
|
||||
for msg in reversed(self.vsc.received):
|
||||
if msg.type == 'response':
|
||||
if msg.command == 'threads':
|
||||
break
|
||||
else:
|
||||
assert False, 'we waited for the response in send_request()'
|
||||
response = [(None, t) for t in threads]
|
||||
for tinfo in msg.body['threads']:
|
||||
try:
|
||||
thread = request[tinfo['name']]
|
||||
i = request.pop(tinfo['name'])
|
||||
except KeyError:
|
||||
continue
|
||||
response[thread] = tinfo['id']
|
||||
response[i] = (tinfo['id'], threads[i])
|
||||
return response
|
||||
|
||||
def suspend(self, thread, reason, *stack):
|
||||
ptid, _ = thread
|
||||
with self.wait_for_event('stopped'):
|
||||
if isinstance(reason, Exception):
|
||||
exc = reason
|
||||
|
|
@ -826,21 +829,19 @@ class HighlevelFixture(object):
|
|||
else:
|
||||
self._pydevd.send_suspend_event(thread, reason, *stack)
|
||||
|
||||
def pause(self, thread, *stack):
|
||||
thread = Thread.from_raw(thread)
|
||||
tid = self.set_thread(thread)
|
||||
def pause(self, threadname, *stack):
|
||||
tid, thread = self.set_thread(threadname)
|
||||
self._pydevd.send_pause_event(thread, *stack)
|
||||
if self._vsc._hidden:
|
||||
self._vsc.msgs.next_event()
|
||||
self.send_request('stackTrace', {'threadId': tid})
|
||||
self.send_request('scopes', {'frameId': 1})
|
||||
return tid
|
||||
return tid, thread
|
||||
|
||||
def error(self, thread, exc, frame):
|
||||
thread = Thread.from_raw(thread)
|
||||
tid = self.set_thread(thread)
|
||||
def error(self, threadname, exc, frame):
|
||||
tid, thread = self.set_thread(threadname)
|
||||
self.suspend(thread, exc, frame)
|
||||
return tid
|
||||
return tid, thread
|
||||
|
||||
|
||||
class VSCTest(object):
|
||||
|
|
@ -873,7 +874,10 @@ class VSCTest(object):
|
|||
vsc = self._new_daemon(*args, **kwargs)
|
||||
self.addCleanup(vsc.close)
|
||||
return vsc
|
||||
self._fix = self._new_fixture(new_daemon)
|
||||
try:
|
||||
self._fix = self._new_fixture(new_daemon)
|
||||
except AttributeError:
|
||||
raise Exception
|
||||
return self._fix
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -217,9 +217,10 @@ class ThreadsTests(NormalRequestTest, unittest.TestCase):
|
|||
def test_few(self):
|
||||
with self.launched(default_threads=False):
|
||||
self.set_debugger_response(
|
||||
(1, 'MainThread'),
|
||||
(10, 'spam'),
|
||||
(11, 'pydevd.eggs'),
|
||||
(12, ''),
|
||||
(12, 'Thread-12'),
|
||||
)
|
||||
self.send_request()
|
||||
received = self.vsc.received
|
||||
|
|
@ -230,9 +231,10 @@ class ThreadsTests(NormalRequestTest, unittest.TestCase):
|
|||
self.new_event('thread', threadId=3, reason='started'),
|
||||
self.expected_response(
|
||||
threads=[
|
||||
{'id': 1, 'name': 'MainThread'},
|
||||
{'id': 2, 'name': 'spam'},
|
||||
# Threads named 'pydevd.*' are ignored.
|
||||
{'id': 3, 'name': ''},
|
||||
{'id': 3, 'name': 'Thread-12'},
|
||||
],
|
||||
),
|
||||
# no events
|
||||
|
|
@ -263,10 +265,9 @@ class StackTraceTests(NormalRequestTest, unittest.TestCase):
|
|||
COMMAND = 'stackTrace'
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.set_thread(thread)
|
||||
tid, thread = self.set_thread('x')
|
||||
self.suspend(thread, CMD_THREAD_SUSPEND, *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
|
|
@ -314,10 +315,9 @@ class StackTraceTests(NormalRequestTest, unittest.TestCase):
|
|||
self.assert_received(self.debugger, [])
|
||||
|
||||
def test_unknown_thread(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.set_threads(thread)[thread]
|
||||
tid, _ = self.set_thread('x')
|
||||
req = self.send_request(
|
||||
threadId=tid + 1,
|
||||
)
|
||||
|
|
@ -332,10 +332,9 @@ class ScopesTests(NormalRequestTest, unittest.TestCase):
|
|||
COMMAND = 'scopes'
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
self.pause('x', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -372,11 +371,10 @@ class VariablesTests(NormalRequestTest, unittest.TestCase):
|
|||
class MyType(object):
|
||||
pass
|
||||
obj = MyType()
|
||||
thread = (10, 'x')
|
||||
self.PYDEVD_CMD = CMD_GET_FRAME
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('t', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -429,15 +427,14 @@ class VariablesTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10\t2\tFRAME'),
|
||||
self.expected_pydevd_request('{}\t2\tFRAME'.format(thread.id)),
|
||||
])
|
||||
|
||||
def test_container(self):
|
||||
thread = (10, 'x')
|
||||
self.PYDEVD_CMD = CMD_GET_FRAME
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('t', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -487,7 +484,8 @@ class VariablesTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10\t2\tFRAME\tspam'),
|
||||
self.expected_pydevd_request(
|
||||
'{}\t2\tFRAME\tspam'.format(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -511,10 +509,9 @@ class SetVariableTests(NormalRequestTest, unittest.TestCase):
|
|||
))
|
||||
|
||||
def test_local(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('t', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -526,7 +523,7 @@ class SetVariableTests(NormalRequestTest, unittest.TestCase):
|
|||
self.PYDEVD_CMD = CMD_EXEC_EXPRESSION
|
||||
self.PYDEVD_RESP = CMD_EVALUATE_EXPRESSION
|
||||
expected = self.expected_pydevd_request(
|
||||
'10\t2\tLOCAL\tspam = eggs\t1')
|
||||
'{}\t2\tLOCAL\tspam = eggs\t1'.format(thread.id))
|
||||
self.set_debugger_response(
|
||||
('spam', 'eggs'),
|
||||
)
|
||||
|
|
@ -550,14 +547,14 @@ class SetVariableTests(NormalRequestTest, unittest.TestCase):
|
|||
])
|
||||
self.assert_received(self.debugger, [
|
||||
expected,
|
||||
self.expected_pydevd_request('10\t2\tLOCAL\tspam\t1'),
|
||||
self.expected_pydevd_request(
|
||||
'{}\t2\tLOCAL\tspam\t1'.format(thread.id)),
|
||||
])
|
||||
|
||||
def test_container(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('t', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -569,7 +566,7 @@ class SetVariableTests(NormalRequestTest, unittest.TestCase):
|
|||
self.PYDEVD_CMD = CMD_EXEC_EXPRESSION
|
||||
self.PYDEVD_RESP = CMD_EVALUATE_EXPRESSION
|
||||
expected = self.expected_pydevd_request(
|
||||
'10\t2\tLOCAL\tspam.x = 2\t1')
|
||||
'{}\t2\tLOCAL\tspam.x = 2\t1'.format(thread.id))
|
||||
self.set_debugger_response(
|
||||
('x', 2),
|
||||
)
|
||||
|
|
@ -593,7 +590,8 @@ class SetVariableTests(NormalRequestTest, unittest.TestCase):
|
|||
])
|
||||
self.assert_received(self.debugger, [
|
||||
expected,
|
||||
self.expected_pydevd_request('10\t2\tLOCAL\tspam.x\t1'),
|
||||
self.expected_pydevd_request(
|
||||
'{}\t2\tLOCAL\tspam.x\t1'.format(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -606,10 +604,9 @@ class EvaluateTests(NormalRequestTest, unittest.TestCase):
|
|||
return self.debugger_msgs.format_variables(variable)
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('x', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -632,14 +629,14 @@ class EvaluateTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10\t5\tLOCAL\tspam + 1\t1'),
|
||||
self.expected_pydevd_request(
|
||||
'{}\t5\tLOCAL\tspam + 1\t1'.format(thread.id)),
|
||||
])
|
||||
|
||||
def test_hover(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('x', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10), # VSC frame ID 1
|
||||
(5, 'eggs', 'xyz.py', 2), # VSC frame ID 2
|
||||
|
|
@ -662,7 +659,8 @@ class EvaluateTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10\t5\tLOCAL\tspam + 1\t1'),
|
||||
self.expected_pydevd_request(
|
||||
'{}\t5\tLOCAL\tspam + 1\t1'.format(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -673,15 +671,12 @@ class PauseTests(NormalRequestTest, unittest.TestCase):
|
|||
PYDEVD_RESP = None
|
||||
|
||||
def test_pause_one(self):
|
||||
thread = (10, 'spam')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tids = self.set_threads(
|
||||
thread,
|
||||
(11, 'eggs'),
|
||||
)
|
||||
threads = self.set_threads('spam', 'eggs')
|
||||
tid, thread = threads[0]
|
||||
self.send_request(
|
||||
threadId=tids[thread],
|
||||
threadId=tid,
|
||||
)
|
||||
received = self.vsc.received
|
||||
|
||||
|
|
@ -690,7 +685,7 @@ class PauseTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10'),
|
||||
self.expected_pydevd_request(str(thread.id)),
|
||||
])
|
||||
|
||||
# TODO: finish!
|
||||
|
|
@ -706,10 +701,9 @@ class ContinueTests(NormalRequestTest, unittest.TestCase):
|
|||
PYDEVD_RESP = None
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.pause(thread, *[
|
||||
tid, thread = self.pause('x', *[
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
])
|
||||
self.send_request(
|
||||
|
|
@ -722,7 +716,7 @@ class ContinueTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10'),
|
||||
self.expected_pydevd_request(str(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -733,10 +727,9 @@ class NextTests(NormalRequestTest, unittest.TestCase):
|
|||
PYDEVD_RESP = None
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.pause(thread, *[
|
||||
tid, thread = self.pause('x', *[
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
])
|
||||
self.send_request(
|
||||
|
|
@ -749,7 +742,7 @@ class NextTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10'),
|
||||
self.expected_pydevd_request(str(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -760,10 +753,9 @@ class StepInTests(NormalRequestTest, unittest.TestCase):
|
|||
PYDEVD_RESP = None
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.pause(thread, *[
|
||||
tid, thread = self.pause('x', *[
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
])
|
||||
self.send_request(
|
||||
|
|
@ -776,7 +768,7 @@ class StepInTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10'),
|
||||
self.expected_pydevd_request(str(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -787,10 +779,9 @@ class StepOutTests(NormalRequestTest, unittest.TestCase):
|
|||
PYDEVD_RESP = None
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.pause(thread, *[
|
||||
tid, thread = self.pause('x', *[
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
])
|
||||
self.send_request(
|
||||
|
|
@ -803,7 +794,7 @@ class StepOutTests(NormalRequestTest, unittest.TestCase):
|
|||
# no events
|
||||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.expected_pydevd_request('10'),
|
||||
self.expected_pydevd_request(str(thread.id)),
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -1600,12 +1591,11 @@ class ExceptionInfoTests(NormalRequestTest, unittest.TestCase):
|
|||
# ),
|
||||
|
||||
def test_active_exception(self):
|
||||
thread = (10, 'x')
|
||||
exc = RuntimeError('something went wrong')
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.error(thread, exc, frame)
|
||||
tid, _ = self.error('x', exc, frame)
|
||||
self.send_request(
|
||||
threadId=tid,
|
||||
)
|
||||
|
|
@ -1637,10 +1627,9 @@ class ExceptionInfoTests(NormalRequestTest, unittest.TestCase):
|
|||
# TODO: verify behavior
|
||||
@unittest.skip('poorly specified (broken?)')
|
||||
def test_no_exception(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.pause(thread)
|
||||
tid, _ = self.pause('x')
|
||||
self.send_request(
|
||||
threadId=tid,
|
||||
)
|
||||
|
|
@ -1655,15 +1644,14 @@ class ExceptionInfoTests(NormalRequestTest, unittest.TestCase):
|
|||
# TODO: verify behavior
|
||||
@unittest.skip('poorly specified (broken?)')
|
||||
def test_exception_cleared(self):
|
||||
thread = (10, 'x')
|
||||
exc = RuntimeError('something went wrong')
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.error(thread, exc, frame)
|
||||
tid, thread = self.error('x', exc, frame)
|
||||
self.send_debugger_event(
|
||||
CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED,
|
||||
str(thread[0]),
|
||||
str(thread.id),
|
||||
)
|
||||
self.send_request(
|
||||
threadId=tid,
|
||||
|
|
@ -1976,11 +1964,10 @@ class ThreadCreateEventTests(ThreadEventTest, unittest.TestCase):
|
|||
# TODO: verify behavior
|
||||
@unittest.skip('poorly specified')
|
||||
def test_exists(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
self.send_event(10, 'spam')
|
||||
_, thread = self.set_thread('x')
|
||||
self.send_event(thread.id, 'spam')
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [])
|
||||
|
|
@ -2014,11 +2001,10 @@ class ThreadKillEventTests(ThreadEventTest, unittest.TestCase):
|
|||
return str(threadid)
|
||||
|
||||
def test_known(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.set_thread(thread)
|
||||
self.send_event(10)
|
||||
tid, thread = self.set_thread('x')
|
||||
self.send_event(thread.id)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2040,11 +2026,10 @@ class ThreadKillEventTests(ThreadEventTest, unittest.TestCase):
|
|||
|
||||
def test_pydevd_name(self):
|
||||
self.EVENT = None
|
||||
thread = (10, 'pydevd.spam')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
self.send_event(10)
|
||||
_, thread = self.set_thread('pydevd.spam')
|
||||
self.send_event(thread.id)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [])
|
||||
|
|
@ -2052,11 +2037,10 @@ class ThreadKillEventTests(ThreadEventTest, unittest.TestCase):
|
|||
|
||||
def test_ptvsd_name(self):
|
||||
self.EVENT = None
|
||||
thread = (10, 'ptvsd.spam')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
self.send_event(10)
|
||||
_, thread = self.set_thread('ptvsd.spam')
|
||||
self.send_event(thread.id)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [])
|
||||
|
|
@ -2078,11 +2062,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
return self.debugger_msgs.format_frames(threadid, reason, *frames)
|
||||
|
||||
def test_step_into(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, CMD_STEP_INTO)
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, CMD_STEP_INTO)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2096,11 +2079,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
self.assert_received(self.debugger, [])
|
||||
|
||||
def test_step_over(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, CMD_STEP_OVER)
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, CMD_STEP_OVER)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2114,11 +2096,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
self.assert_received(self.debugger, [])
|
||||
|
||||
def test_step_return(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, CMD_STEP_RETURN)
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, CMD_STEP_RETURN)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2133,10 +2114,9 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
|
||||
def test_caught_exception(self):
|
||||
exc = RuntimeError('something went wrong')
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
_, thread = self.set_thread('x')
|
||||
self.set_debugger_response(
|
||||
CMD_GET_VARIABLE,
|
||||
self.debugger_msgs.format_variables(
|
||||
|
|
@ -2144,7 +2124,7 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
('???', exc),
|
||||
),
|
||||
)
|
||||
tid = self.send_event(10, CMD_STEP_CAUGHT_EXCEPTION)
|
||||
tid = self.send_event(thread.id, CMD_STEP_CAUGHT_EXCEPTION)
|
||||
received = self.vsc.received
|
||||
|
||||
# TODO: Is this the right str?
|
||||
|
|
@ -2161,15 +2141,15 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.debugger_msgs.new_request(
|
||||
CMD_GET_VARIABLE, '10', '2', 'FRAME', '__exception__'),
|
||||
CMD_GET_VARIABLE,
|
||||
str(thread.id), '2', 'FRAME', '__exception__'),
|
||||
])
|
||||
|
||||
def test_exception_break(self):
|
||||
exc = RuntimeError('something went wrong')
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
_, thread = self.set_thread('x')
|
||||
self.set_debugger_response(
|
||||
CMD_GET_VARIABLE,
|
||||
self.debugger_msgs.format_variables(
|
||||
|
|
@ -2177,7 +2157,7 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
('???', exc),
|
||||
),
|
||||
)
|
||||
tid = self.send_event(10, CMD_ADD_EXCEPTION_BREAK)
|
||||
tid = self.send_event(thread.id, CMD_ADD_EXCEPTION_BREAK)
|
||||
received = self.vsc.received
|
||||
|
||||
# TODO: Is this the right str?
|
||||
|
|
@ -2194,15 +2174,15 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
])
|
||||
self.assert_received(self.debugger, [
|
||||
self.debugger_msgs.new_request(
|
||||
CMD_GET_VARIABLE, '10', '2', 'FRAME', '__exception__'),
|
||||
CMD_GET_VARIABLE,
|
||||
str(thread.id), '2', 'FRAME', '__exception__'),
|
||||
])
|
||||
|
||||
def test_suspend(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, CMD_THREAD_SUSPEND)
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, CMD_THREAD_SUSPEND)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2216,11 +2196,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
self.assert_received(self.debugger, [])
|
||||
|
||||
def test_unknown_reason(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, 99999)
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, 99999)
|
||||
received = self.vsc.received
|
||||
|
||||
# TODO: Should this fail instead?
|
||||
|
|
@ -2237,11 +2216,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
# TODO: verify behavior
|
||||
@unittest.skip('poorly specified')
|
||||
def test_no_reason(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, 'x')
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, 'x')
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2257,11 +2235,10 @@ class ThreadSuspendEventTests(ThreadEventTest, unittest.TestCase):
|
|||
# TODO: verify behavior
|
||||
@unittest.skip('poorly specified')
|
||||
def test_str_reason(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.set_thread(thread)
|
||||
tid = self.send_event(10, '???')
|
||||
_, thread = self.set_thread('x')
|
||||
tid = self.send_event(thread.id, '???')
|
||||
received = self.vsc.received
|
||||
|
||||
# TODO: Should this fail instead?
|
||||
|
|
@ -2285,15 +2262,14 @@ class ThreadRunEventTests(ThreadEventTest, unittest.TestCase):
|
|||
return '{}\t{}'.format(threadid, reason)
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
self.pause(thread, *[
|
||||
_, thread = self.pause('x', *[
|
||||
# (pfid, func, file, line)
|
||||
(2, 'spam', 'abc.py', 10),
|
||||
(5, 'eggs', 'xyz.py', 2),
|
||||
])
|
||||
tid = self.send_event(10, '???')
|
||||
tid = self.send_event(thread.id, '???')
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [
|
||||
|
|
@ -2315,12 +2291,11 @@ class SendCurrExcTraceEventTests(PyDevdEventTest, unittest.TestCase):
|
|||
# TODO: Is this right?
|
||||
@unittest.skip('now a no-op')
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
exc = RuntimeError('something went wrong')
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
tid = self.set_thread(thread)
|
||||
tid, thread = self.set_thread('x')
|
||||
self.send_event(thread, exc, frame)
|
||||
received = self.vsc.received
|
||||
|
||||
|
|
@ -2352,21 +2327,20 @@ class SendCurrExcTraceProceededEventTests(PyDevdEventTest, unittest.TestCase):
|
|||
return str(threadid)
|
||||
|
||||
def test_basic(self):
|
||||
thread = (10, 'x')
|
||||
exc = RuntimeError('something went wrong')
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
#text = self.debugger_msgs.format_exception(thread[0], exc, frame)
|
||||
with self.launched():
|
||||
with self.hidden():
|
||||
#tid = self.set_thread(thread)
|
||||
#tid, thread = self.set_thread('x')
|
||||
#self.fix.send_event(CMD_SEND_CURR_EXCEPTION_TRACE, text)
|
||||
tid = self.error(thread, exc, frame)
|
||||
tid, thread = self.error('x', exc, frame)
|
||||
self.send_request('exceptionInfo', dict(
|
||||
threadId=tid,
|
||||
))
|
||||
before = self.vsc.received[-1]
|
||||
|
||||
self.send_event(10)
|
||||
self.send_event(thread.id)
|
||||
received = self.vsc.received
|
||||
|
||||
self.send_request('exceptionInfo', dict(
|
||||
|
|
@ -2387,16 +2361,16 @@ class GetExceptionBreakpointEventTests(PyDevdEventTest, unittest.TestCase):
|
|||
CMD = CMD_GET_BREAKPOINT_EXCEPTION
|
||||
EVENT = None
|
||||
|
||||
def pydevd_payload(self, thread, exc, frame):
|
||||
return self.debugger_msgs.format_exception(thread[0], exc, frame)
|
||||
def pydevd_payload(self, tid, exc, frame):
|
||||
return self.debugger_msgs.format_exception(tid, exc, frame)
|
||||
|
||||
def test_unsupported(self):
|
||||
thread = (10, 'x')
|
||||
ptid = 10
|
||||
exc = RuntimeError('something went wrong')
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
with self.launched():
|
||||
with self.assertRaises(UnsupportedPyDevdCommandError):
|
||||
self.send_event(thread, exc, frame)
|
||||
self.send_event(ptid, exc, frame)
|
||||
received = self.vsc.received
|
||||
|
||||
self.assert_vsc_received(received, [])
|
||||
|
|
@ -2413,8 +2387,7 @@ class ShowConsoleEventTests(PyDevdEventTest, unittest.TestCase):
|
|||
return self.debugger_msgs.format_frames(threadid, reason, *frames)
|
||||
|
||||
def test_unsupported(self):
|
||||
thread = (10, 'x')
|
||||
ptid, _ = thread
|
||||
ptid = 10
|
||||
frame = (2, 'spam', 'abc.py', 10) # (pfid, func, file, line)
|
||||
with self.launched():
|
||||
with self.assertRaises(UnsupportedPyDevdCommandError):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue