mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-25 21:36:52 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Graham Neubig <neubig@gmail.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
91 lines
3.3 KiB
Python
91 lines
3.3 KiB
Python
"""Test CLIRuntime class."""
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
import pytest
|
|
|
|
from openhands.core.config import OpenHandsConfig
|
|
from openhands.events import EventStream
|
|
|
|
# Mock LLMRegistry
|
|
from openhands.runtime.impl.cli.cli_runtime import CLIRuntime
|
|
from openhands.storage import get_file_store
|
|
|
|
|
|
# Create a mock LLMRegistry class
|
|
class MockLLMRegistry:
|
|
def __init__(self, config):
|
|
self.config = config
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_dir():
|
|
"""Create a temporary directory for testing."""
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
yield temp_dir
|
|
|
|
|
|
@pytest.fixture
|
|
def cli_runtime(temp_dir):
|
|
"""Create a CLIRuntime instance for testing."""
|
|
file_store = get_file_store('local', temp_dir)
|
|
event_stream = EventStream('test', file_store)
|
|
config = OpenHandsConfig()
|
|
config.workspace_base = temp_dir
|
|
llm_registry = MockLLMRegistry(config)
|
|
runtime = CLIRuntime(config, event_stream, llm_registry)
|
|
runtime._runtime_initialized = True # Skip initialization
|
|
return runtime
|
|
|
|
|
|
def test_sanitize_filename_valid_path(cli_runtime):
|
|
"""Test _sanitize_filename with a valid path."""
|
|
test_path = os.path.join(cli_runtime._workspace_path, 'test.txt')
|
|
sanitized_path = cli_runtime._sanitize_filename(test_path)
|
|
assert sanitized_path == os.path.realpath(test_path)
|
|
|
|
|
|
def test_sanitize_filename_relative_path(cli_runtime):
|
|
"""Test _sanitize_filename with a relative path."""
|
|
test_path = 'test.txt'
|
|
expected_path = os.path.join(cli_runtime._workspace_path, test_path)
|
|
sanitized_path = cli_runtime._sanitize_filename(test_path)
|
|
assert sanitized_path == os.path.realpath(expected_path)
|
|
|
|
|
|
def test_sanitize_filename_outside_workspace(cli_runtime):
|
|
"""Test _sanitize_filename with a path outside the workspace."""
|
|
test_path = '/tmp/test.txt' # Path outside workspace
|
|
with pytest.raises(PermissionError) as exc_info:
|
|
cli_runtime._sanitize_filename(test_path)
|
|
assert 'Invalid path:' in str(exc_info.value)
|
|
assert 'You can only work with files in' in str(exc_info.value)
|
|
|
|
|
|
def test_sanitize_filename_path_traversal(cli_runtime):
|
|
"""Test _sanitize_filename with path traversal attempt."""
|
|
test_path = os.path.join(cli_runtime._workspace_path, '..', 'test.txt')
|
|
with pytest.raises(PermissionError) as exc_info:
|
|
cli_runtime._sanitize_filename(test_path)
|
|
assert 'Invalid path traversal:' in str(exc_info.value)
|
|
assert 'Path resolves outside the workspace' in str(exc_info.value)
|
|
|
|
|
|
def test_sanitize_filename_absolute_path_with_dots(cli_runtime):
|
|
"""Test _sanitize_filename with absolute path containing dots."""
|
|
test_path = os.path.join(cli_runtime._workspace_path, 'subdir', '..', 'test.txt')
|
|
# Create the parent directory
|
|
os.makedirs(os.path.join(cli_runtime._workspace_path, 'subdir'), exist_ok=True)
|
|
sanitized_path = cli_runtime._sanitize_filename(test_path)
|
|
assert sanitized_path == os.path.join(cli_runtime._workspace_path, 'test.txt')
|
|
|
|
|
|
def test_sanitize_filename_nested_path(cli_runtime):
|
|
"""Test _sanitize_filename with a nested path."""
|
|
nested_dir = os.path.join(cli_runtime._workspace_path, 'dir1', 'dir2')
|
|
os.makedirs(nested_dir, exist_ok=True)
|
|
test_path = os.path.join(nested_dir, 'test.txt')
|
|
sanitized_path = cli_runtime._sanitize_filename(test_path)
|
|
assert sanitized_path == os.path.realpath(test_path)
|