Support bounded machine instruction step counts in MCP
This commit is contained in:
@@ -109,6 +109,10 @@ async def probe() -> None:
|
||||
after_dap = await call('session_status')
|
||||
if after_dap['phase'] != 'ready' or after_dap['session_id'] != status['session_id']:
|
||||
raise RuntimeError('DAP disconnect завершил MCP-owned MAME')
|
||||
stepped = await call('step_instruction', {'count': 3})
|
||||
if stepped['pc'] == location['pc'] or \
|
||||
(await call('session_status'))['running']:
|
||||
raise RuntimeError('Три машинных шага не остановились: ' + repr(stepped))
|
||||
source = str(ROOT / 'tests/hello/hello.c')
|
||||
before = await call('set_line_breakpoint', {'file': source, 'line': 62})
|
||||
points = await call('list_breakpoints')
|
||||
|
||||
@@ -55,6 +55,16 @@ class McpAdapterTests(unittest.TestCase):
|
||||
self.client.step_source('back')
|
||||
self.assertEqual(len(self.calls), before)
|
||||
|
||||
def test_machine_step_count_is_validated_before_rpc(self):
|
||||
before = len(self.calls)
|
||||
for count in (0, 65, True):
|
||||
with self.assertRaisesRegex(SessionError, '1..64'):
|
||||
self.client.step_instruction(count)
|
||||
self.assertEqual(len(self.calls), before)
|
||||
self.client.step_instruction(3)
|
||||
self.assertEqual(self.calls[-1][1], 'step')
|
||||
self.assertEqual(self.calls[-1][2]['count'], 3)
|
||||
|
||||
def test_press_key_releases_shift_after_snapshot_error(self):
|
||||
calls = []
|
||||
|
||||
|
||||
@@ -111,13 +111,16 @@ class StepBridge:
|
||||
def __init__(self, owner):
|
||||
self.owner = owner
|
||||
self.calls = []
|
||||
self.step_counts = []
|
||||
|
||||
def close(self): pass
|
||||
|
||||
def request(self, command, **arguments):
|
||||
self.calls.append(command)
|
||||
if command in ('step', 'step_over', 'step_out'):
|
||||
self.owner.index = min(self.owner.index + 1,
|
||||
count = arguments.get('count', 1) if command == 'step' else 1
|
||||
self.step_counts.append(count)
|
||||
self.owner.index = min(self.owner.index + count,
|
||||
len(self.owner.locations) - 1)
|
||||
return {'accepted': True}
|
||||
if command == 'snapshot':
|
||||
@@ -482,6 +485,21 @@ class ServerTests(unittest.TestCase):
|
||||
finally:
|
||||
controller.close()
|
||||
|
||||
def test_instruction_step_count_is_bounded_and_forwarded(self):
|
||||
session = StepSession()
|
||||
controller = SessionController(session)
|
||||
try:
|
||||
with self.assertRaisesRegex(SessionError, '1..64'):
|
||||
controller.call('step', {'count': 0, 'owner': 'mcp:test'})
|
||||
for bad in (65, 1.5, True):
|
||||
with self.assertRaisesRegex(SessionError, '1..64'):
|
||||
controller.call('step', {'count': bad, 'owner': 'mcp:test'})
|
||||
result = controller.call('step', {'count': 2, 'owner': 'mcp:test'})
|
||||
self.assertEqual(result['sources'][0]['line'], 4)
|
||||
self.assertEqual(session.bridge.step_counts, [2])
|
||||
finally:
|
||||
controller.close()
|
||||
|
||||
def test_source_step_preserves_user_breakpoint_on_same_line(self):
|
||||
session = StepSession()
|
||||
controller = SessionController(session)
|
||||
|
||||
Reference in New Issue
Block a user