Skip to main content
Glama
test_executable_lines.py7.12 kB
""" Unit tests for executable line validation. Tests the get_executable_lines and validate_file_and_line functions. """ import tempfile from pathlib import Path import pytest from mcp_debug_tool.utils import ( find_nearest_executable_line, get_executable_lines, validate_file_and_line, ) def test_get_executable_lines_simple(): """Test get_executable_lines with a simple script.""" code = """# Comment line x = 1 # Another comment y = 2 print(x + y) """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: executable = get_executable_lines(path) # Line 2 (x = 1), Line 5 (y = 2), Line 6 (print) should be executable assert 2 in executable assert 5 in executable assert 6 in executable # Line 1 (comment), Line 3 (comment), Line 4 (blank) should NOT be executable assert 1 not in executable assert 3 not in executable assert 4 not in executable finally: path.unlink() def test_get_executable_lines_with_function(): """Test get_executable_lines with function definition.""" code = """def greet(name): print(f"Hello, {name}") return name x = greet("World") """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: executable = get_executable_lines(path) # Function definition and body assert 1 in executable # def greet(name): assert 2 in executable # print(...) assert 3 in executable # return name assert 5 in executable # x = greet(...) finally: path.unlink() def test_get_executable_lines_with_control_flow(): """Test get_executable_lines with if/for statements.""" code = """x = 5 if x > 3: print("yes") else: print("no") for i in range(3): print(i) """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: executable = get_executable_lines(path) assert 1 in executable # x = 5 assert 2 in executable # if x > 3: assert 3 in executable # print("yes") # Note: 'else:' line (4) doesn't generate bytecode, so it's not executable assert 5 in executable # print("no") assert 7 in executable # for i in range(3): assert 8 in executable # print(i) finally: path.unlink() def test_get_executable_lines_empty_file(): """Test get_executable_lines with empty file.""" code = "" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: executable = get_executable_lines(path) assert len(executable) == 0 finally: path.unlink() def test_get_executable_lines_syntax_error(): """Test get_executable_lines with syntax error.""" code = """x = 1 def broken( # Missing closing parenthesis """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: executable = get_executable_lines(path) # Should return empty set on syntax error assert isinstance(executable, set) finally: path.unlink() def test_validate_file_and_line_executable(): """Test validate_file_and_line with executable line.""" code = """x = 1 # Comment y = 2 """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: # Line 1 (x = 1) is executable - should pass validate_file_and_line(path, 1, check_executable=True) # Line 3 (y = 2) is executable - should pass validate_file_and_line(path, 3, check_executable=True) finally: path.unlink() def test_validate_file_and_line_not_executable(): """Test validate_file_and_line with non-executable line.""" code = """x = 1 # Comment line y = 2 """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: # Line 2 (comment) is not executable - should raise ValueError with pytest.raises(ValueError, match="does not contain executable code"): validate_file_and_line(path, 2, check_executable=True) finally: path.unlink() def test_validate_file_and_line_blank_line(): """Test validate_file_and_line with blank line.""" code = """x = 1 y = 2 """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: # Line 2 (blank) is not executable - should raise ValueError with pytest.raises(ValueError, match="does not contain executable code"): validate_file_and_line(path, 2, check_executable=True) finally: path.unlink() def test_validate_file_and_line_skip_check(): """Test validate_file_and_line with check_executable=False.""" code = """x = 1 # Comment y = 2 """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: # With check_executable=False, even comment line should pass validate_file_and_line(path, 2, check_executable=False) finally: path.unlink() def test_find_nearest_executable_line(): """Test find_nearest_executable_line function.""" executable_lines = {1, 5, 10, 15, 20} # Exact match assert find_nearest_executable_line(5, executable_lines) == 5 # Between lines - should find closer one assert find_nearest_executable_line(3, executable_lines) == 1 assert find_nearest_executable_line(7, executable_lines) == 5 assert find_nearest_executable_line(8, executable_lines) == 10 # Before first line assert find_nearest_executable_line(0, executable_lines) == 1 # After last line assert find_nearest_executable_line(25, executable_lines) == 20 def test_find_nearest_executable_line_empty(): """Test find_nearest_executable_line with empty set.""" assert find_nearest_executable_line(5, set()) is None def test_validate_file_and_line_with_nearest_suggestion(): """Test that error message includes nearest executable line.""" code = """x = 1 # Comment # Another comment y = 2 """ with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write(code) f.flush() path = Path(f.name) try: # Line 2 (comment) - nearest should be line 1 or 4 with pytest.raises(ValueError, match="Nearest executable line"): validate_file_and_line(path, 2, check_executable=True) finally: path.unlink()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Kaina3/Debug-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server