test_validation_errors.py•4.58 kB
"""
Unit tests for validation error responses.
Tests that invalid input (bad file/line) returns structured error responses.
"""
from pathlib import Path
import sys
import pytest
from mcp_debug_tool.schemas import BreakpointRequest, ExecutionError, StartSessionRequest
from mcp_debug_tool.sessions import SessionManager
@pytest.fixture
def workspace_root(tmp_path):
"""Create a temporary workspace."""
return tmp_path
@pytest.fixture
def session_manager(workspace_root):
"""Create a session manager."""
return SessionManager(workspace_root)
@pytest.fixture
def valid_script(workspace_root):
"""Create a valid test script."""
script_path = workspace_root / "test_script.py"
script_path.write_text("""x = 1 # Line 1
y = 2 # Line 2
z = 3 # Line 3
""")
return script_path
class TestValidationErrors:
"""Tests for validation error handling."""
def test_invalid_file_returns_error(self, session_manager, workspace_root):
"""Test that non-existent file returns structured error."""
# Create session
create_request = StartSessionRequest(entry="nonexistent.py", pythonPath=sys.executable)
with pytest.raises(FileNotFoundError):
session_manager.create_session(create_request)
def test_invalid_line_too_high_returns_error(
self, session_manager, valid_script, workspace_root
):
"""Test that line number exceeding file length returns error."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=valid_script.relative_to(workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Try to set breakpoint beyond file length
bp_request = BreakpointRequest(
file=valid_script.relative_to(workspace_root).as_posix(),
line=1000, # File only has 3 lines
)
with pytest.raises(ValueError, match="exceeds file length"):
session_manager.run_to_breakpoint(session_id, bp_request)
# Clean up
session_manager.end_session(session_id)
def test_invalid_line_negative_rejected(self, session_manager, valid_script):
"""Test that negative line number is rejected by schema."""
with pytest.raises(ValueError):
BreakpointRequest(
file="test.py",
line=-1,
)
def test_invalid_line_zero_rejected(self, session_manager, valid_script):
"""Test that line 0 is rejected by schema."""
with pytest.raises(ValueError):
BreakpointRequest(
file="test.py",
line=0,
)
def test_path_escape_workspace_rejected(
self, session_manager, workspace_root, tmp_path
):
"""Test that paths escaping workspace are rejected."""
# Create a script outside workspace
outside_script = tmp_path.parent / "outside.py"
outside_script.write_text("x = 1")
# Try to create session with path outside workspace
create_request = StartSessionRequest(entry="../outside.py", pythonPath=sys.executable)
with pytest.raises(ValueError, match="escapes workspace"):
session_manager.create_session(create_request)
def test_validation_error_has_structured_format(
self, session_manager, valid_script, workspace_root
):
"""Test that validation errors can be converted to ExecutionError."""
# Create session
create_request = StartSessionRequest(
pythonPath=sys.executable,
entry=valid_script.relative_to(workspace_root).as_posix()
)
create_response = session_manager.create_session(create_request)
session_id = create_response.sessionId
# Try to set invalid breakpoint
bp_request = BreakpointRequest(
file=valid_script.relative_to(workspace_root).as_posix(),
line=1000,
)
try:
session_manager.run_to_breakpoint(session_id, bp_request)
assert False, "Should have raised ValueError"
except ValueError as e:
# Verify we can create ExecutionError from this
error = ExecutionError(
type="ValueError",
message=str(e),
)
assert error.type == "ValueError"
assert "exceeds file length" in error.message
# Clean up
session_manager.end_session(session_id)