mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
* tmp * tmp * merge main * feat: auto build image cache * remove plugins * use config file * update mamba setup shell * support agnostic sandbox image autobuild * remove config * Update .gitignore Co-authored-by: Xingyao Wang <xingyao6@illinois.edu> * Update opendevin/runtime/docker/ssh_box.py Co-authored-by: Xingyao Wang <xingyao6@illinois.edu> * update setup.sh * readd sudo * add sudo in dockerfile * remove export * move od-runtime dependencies to sandbox dockerfile * factor out re-build logic into a separate util file * tweak existing plugin to use OD specific sandbox * update testcase * attempt to fix unit test using image built in ghcr * use cache tag * try to fix unit tests * add unittest * add unittest * add some unittests * revert gh workflow changes * feat: optimize sandbox image naming rule * add pull latest image hint * add opendevin python hint and use mamba to install gcc * update docker image naming rule and fix mamba issue * Update opendevin/runtime/docker/ssh_box.py Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk> * fix: opendevin user use correct pip * fix lint issue * fix custom sandbox base image * rename test name * add skipif --------- Co-authored-by: Graham Neubig <neubig@gmail.com> Co-authored-by: Xingyao Wang <xingyao6@illinois.edu> Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk> Co-authored-by: Yufan Song <33971064+yufansong@users.noreply.github.com> Co-authored-by: tobitege <tobitege@gmx.de>
104 lines
3.9 KiB
Python
104 lines
3.9 KiB
Python
import pathlib
|
|
import tempfile
|
|
from unittest.mock import MagicMock, call, patch
|
|
|
|
import pytest
|
|
|
|
from opendevin.core.config import config
|
|
from opendevin.events.action import IPythonRunCellAction
|
|
from opendevin.events.observation import IPythonRunCellObservation
|
|
from opendevin.runtime.docker.ssh_box import DockerSSHBox
|
|
from opendevin.runtime.plugins import JupyterRequirement
|
|
from opendevin.runtime.server.runtime import ServerRuntime
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_dir(monkeypatch):
|
|
# get a temporary directory
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
pathlib.Path().mkdir(parents=True, exist_ok=True)
|
|
yield temp_dir
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_run_python_backticks():
|
|
# Create a mock event_stream
|
|
mock_event_stream = MagicMock()
|
|
|
|
test_code = "print('Hello, `World`!\n')"
|
|
|
|
# Mock the asynchronous sandbox execute method
|
|
mock_sandbox_execute = MagicMock()
|
|
mock_sandbox_execute.side_effect = [
|
|
(0, ''), # Initial call during DockerSSHBox initialization
|
|
(0, ''), # Initial call during DockerSSHBox initialization
|
|
(0, ''), # Initial call during DockerSSHBox initialization
|
|
(0, ''), # Write command
|
|
(0, test_code), # Execute command
|
|
]
|
|
|
|
# Set up the patches for the runtime and sandbox
|
|
with patch(
|
|
'opendevin.runtime.docker.ssh_box.DockerSSHBox.execute',
|
|
new=mock_sandbox_execute,
|
|
):
|
|
# Initialize the runtime with the mock event_stream
|
|
runtime = ServerRuntime(event_stream=mock_event_stream)
|
|
|
|
# Define the test action with a simple IPython command
|
|
action = IPythonRunCellAction(code=test_code)
|
|
|
|
# Call the run_ipython method with the test action
|
|
result = await runtime.run_action(action)
|
|
|
|
# Assert that the result is an instance of IPythonRunCellObservation
|
|
assert isinstance(result, IPythonRunCellObservation)
|
|
|
|
# Assert that the execute method was called with the correct commands
|
|
expected_write_command = (
|
|
"cat > /tmp/opendevin_jupyter_temp.py <<'EOL'\n" f'{test_code}\n' 'EOL'
|
|
)
|
|
expected_execute_command = 'cat /tmp/opendevin_jupyter_temp.py | execute_cli'
|
|
mock_sandbox_execute.assert_has_calls(
|
|
[
|
|
call('mkdir -p /tmp'),
|
|
call('git config --global user.name "OpenDevin"'),
|
|
call('git config --global user.email "opendevin@all-hands.dev"'),
|
|
call(expected_write_command),
|
|
call(expected_execute_command),
|
|
]
|
|
)
|
|
|
|
assert (
|
|
test_code == result.content
|
|
), f'The output should contain the expected print output, got: {result.content}'
|
|
|
|
|
|
def test_sandbox_jupyter_plugin_backticks(temp_dir):
|
|
# get a temporary directory
|
|
with patch.object(config, 'workspace_base', new=temp_dir), patch.object(
|
|
config, 'workspace_mount_path', new=temp_dir
|
|
), patch.object(config, 'run_as_devin', new='true'), patch.object(
|
|
config, 'sandbox_type', new='ssh'
|
|
):
|
|
for box in [DockerSSHBox()]:
|
|
box.init_plugins([JupyterRequirement])
|
|
test_code = "print('Hello, `World`!')"
|
|
expected_write_command = (
|
|
"cat > /tmp/opendevin_jupyter_temp.py <<'EOL'\n" f'{test_code}\n' 'EOL'
|
|
)
|
|
expected_execute_command = (
|
|
'cat /tmp/opendevin_jupyter_temp.py | execute_cli'
|
|
)
|
|
exit_code, output = box.execute(expected_write_command)
|
|
exit_code, output = box.execute(expected_execute_command)
|
|
print(output)
|
|
assert exit_code == 0, (
|
|
'The exit code should be 0 for ' + box.__class__.__name__
|
|
)
|
|
assert output.strip() == 'Hello, `World`!', (
|
|
'The output should be the same as the input for '
|
|
+ box.__class__.__name__
|
|
)
|
|
box.close()
|