OpenHands / tests /unit /test_docker_runtime.py
Backup-bdg's picture
Upload 964 files
51ff9e5 verified
raw
history blame
6.16 kB
from unittest.mock import MagicMock, patch
import pytest
from openhands.core.config import OpenHandsConfig
from openhands.events import EventStream
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
@pytest.fixture
def mock_docker_client():
with patch('docker.from_env') as mock_client:
container_mock = MagicMock()
container_mock.status = 'running'
container_mock.attrs = {
'Config': {
'Env': ['port=12345', 'VSCODE_PORT=54321'],
'ExposedPorts': {'12345/tcp': {}, '54321/tcp': {}},
}
}
mock_client.return_value.containers.get.return_value = container_mock
mock_client.return_value.containers.run.return_value = container_mock
# Mock version info for BuildKit check
mock_client.return_value.version.return_value = {
'Version': '20.10.0',
'Components': [{'Name': 'Engine', 'Version': '20.10.0'}],
} # Ensure version is >= 18.09
yield mock_client.return_value
@pytest.fixture
def config():
config = OpenHandsConfig()
config.sandbox.keep_runtime_alive = False
return config
@pytest.fixture
def event_stream():
return MagicMock(spec=EventStream)
@patch('openhands.runtime.impl.docker.docker_runtime.stop_all_containers')
def test_container_stopped_when_keep_runtime_alive_false(
mock_stop_containers, mock_docker_client, config, event_stream
):
# Arrange
runtime = DockerRuntime(config, event_stream, sid='test-sid')
runtime.container = mock_docker_client.containers.get.return_value
# Act
runtime.close()
# Assert
mock_stop_containers.assert_called_once_with('openhands-runtime-test-sid')
@patch('openhands.runtime.impl.docker.docker_runtime.stop_all_containers')
def test_container_not_stopped_when_keep_runtime_alive_true(
mock_stop_containers, mock_docker_client, config, event_stream
):
# Arrange
config.sandbox.keep_runtime_alive = True
runtime = DockerRuntime(config, event_stream, sid='test-sid')
runtime.container = mock_docker_client.containers.get.return_value
# Act
runtime.close()
# Assert
mock_stop_containers.assert_not_called()
def test_volumes_mode_extraction():
"""Test that the mount mode is correctly extracted from sandbox.volumes."""
import os
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
# Create a DockerRuntime instance with a mock config
runtime = DockerRuntime.__new__(DockerRuntime)
runtime.config = MagicMock()
runtime.config.sandbox.volumes = '/host/path:/container/path:ro'
runtime.config.workspace_mount_path = '/host/path'
runtime.config.workspace_mount_path_in_sandbox = '/container/path'
# Call the actual method that processes volumes
volumes = runtime._process_volumes()
# Assert that the mode was correctly set to 'ro'
assert volumes[os.path.abspath('/host/path')]['mode'] == 'ro'
# This test has been replaced by test_volumes_multiple_mounts
def test_volumes_multiple_mounts():
"""Test that multiple mounts in sandbox.volumes are correctly processed."""
import os
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
# Create a DockerRuntime instance with a mock config
runtime = DockerRuntime.__new__(DockerRuntime)
runtime.config = MagicMock()
runtime.config.runtime_mount = None
runtime.config.sandbox.volumes = (
'/host/path1:/container/path1,/host/path2:/container/path2:ro'
)
runtime.config.workspace_mount_path = '/host/path1'
runtime.config.workspace_mount_path_in_sandbox = '/container/path1'
# Call the actual method that processes volumes
volumes = runtime._process_volumes()
# Assert that both mounts were processed correctly
assert len(volumes) == 2
assert volumes[os.path.abspath('/host/path1')]['bind'] == '/container/path1'
assert volumes[os.path.abspath('/host/path1')]['mode'] == 'rw' # Default mode
assert volumes[os.path.abspath('/host/path2')]['bind'] == '/container/path2'
assert volumes[os.path.abspath('/host/path2')]['mode'] == 'ro' # Specified mode
def test_multiple_volumes():
"""Test that multiple volumes are correctly processed."""
import os
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
# Create a DockerRuntime instance with a mock config
runtime = DockerRuntime.__new__(DockerRuntime)
runtime.config = MagicMock()
runtime.config.sandbox.volumes = '/host/path1:/container/path1,/host/path2:/container/path2,/host/path3:/container/path3:ro'
runtime.config.workspace_mount_path = '/host/path1'
runtime.config.workspace_mount_path_in_sandbox = '/container/path1'
# Call the actual method that processes volumes
volumes = runtime._process_volumes()
# Assert that all mounts were processed correctly
assert len(volumes) == 3
assert volumes[os.path.abspath('/host/path1')]['bind'] == '/container/path1'
assert volumes[os.path.abspath('/host/path1')]['mode'] == 'rw'
assert volumes[os.path.abspath('/host/path2')]['bind'] == '/container/path2'
assert volumes[os.path.abspath('/host/path2')]['mode'] == 'rw'
assert volumes[os.path.abspath('/host/path3')]['bind'] == '/container/path3'
assert volumes[os.path.abspath('/host/path3')]['mode'] == 'ro'
def test_volumes_default_mode():
"""Test that the default mount mode (rw) is used when not specified in sandbox.volumes."""
import os
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
# Create a DockerRuntime instance with a mock config
runtime = DockerRuntime.__new__(DockerRuntime)
runtime.config = MagicMock()
runtime.config.sandbox.volumes = '/host/path:/container/path'
runtime.config.workspace_mount_path = '/host/path'
runtime.config.workspace_mount_path_in_sandbox = '/container/path'
# Call the actual method that processes volumes
volumes = runtime._process_volumes()
# Assert that the mode remains 'rw' (default)
assert volumes[os.path.abspath('/host/path')]['mode'] == 'rw'