mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
test: cover sandbox executor requirements flow
This commit is contained in:
parent
35e001a380
commit
68858d8d8e
2 changed files with 132 additions and 1 deletions
12
.github/workflows/codspeed.yml
vendored
12
.github/workflows/codspeed.yml
vendored
|
|
@ -43,4 +43,14 @@ jobs:
|
|||
uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4.12.1
|
||||
with:
|
||||
mode: simulation
|
||||
run: uv run --frozen --group ci pytest tests/benchmarks/ --codspeed
|
||||
run: >
|
||||
env PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
|
||||
uv run --frozen
|
||||
--with pytest==8.3.5
|
||||
--with pytest-asyncio==1.2.0
|
||||
--with pytest-codspeed==4.3.0
|
||||
pytest
|
||||
-p pytest_asyncio.plugin
|
||||
-p pytest_codspeed.plugin
|
||||
tests/benchmarks/
|
||||
--codspeed
|
||||
|
|
|
|||
121
tests/test_litellm/llms/litellm_proxy/test_sandbox_executor.py
Normal file
121
tests/test_litellm/llms/litellm_proxy/test_sandbox_executor.py
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import sys
|
||||
import types
|
||||
from types import SimpleNamespace
|
||||
|
||||
from litellm.llms.litellm_proxy.skills.sandbox_executor import SkillsSandboxExecutor
|
||||
|
||||
|
||||
class _FakeSandboxSession:
|
||||
last_instance = None
|
||||
install_exit_code = 0
|
||||
install_stdout = ""
|
||||
install_stderr = ""
|
||||
exec_exit_code = 0
|
||||
exec_stdout = "ok"
|
||||
exec_stderr = ""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
self.copy_to_runtime_calls = []
|
||||
self.run_calls = []
|
||||
self.copied_contents = {}
|
||||
type(self).last_instance = self
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def copy_to_runtime(self, local_path, sandbox_path):
|
||||
self.copy_to_runtime_calls.append((local_path, sandbox_path))
|
||||
with open(local_path, "rb") as f:
|
||||
self.copied_contents[sandbox_path] = f.read()
|
||||
|
||||
def run(self, code):
|
||||
self.run_calls.append(code)
|
||||
if "pip', 'install', '-r'" in code:
|
||||
return SimpleNamespace(
|
||||
exit_code=self.install_exit_code,
|
||||
stdout=self.install_stdout,
|
||||
stderr=self.install_stderr,
|
||||
)
|
||||
return SimpleNamespace(
|
||||
exit_code=self.exec_exit_code,
|
||||
stdout=self.exec_stdout,
|
||||
stderr=self.exec_stderr,
|
||||
)
|
||||
|
||||
|
||||
def _install_fake_sandbox(monkeypatch, session_cls=_FakeSandboxSession):
|
||||
fake_module = types.SimpleNamespace(SandboxSession=session_cls)
|
||||
monkeypatch.setitem(sys.modules, "llm_sandbox", fake_module)
|
||||
|
||||
|
||||
def test_execute_installs_inline_requirements_file(monkeypatch):
|
||||
_install_fake_sandbox(monkeypatch)
|
||||
executor = SkillsSandboxExecutor()
|
||||
monkeypatch.setattr(executor, "_collect_generated_files", lambda *args, **kwargs: [])
|
||||
|
||||
requirements = "git+https://example.com/repo.git#egg=foo\n-r extra.txt\n-e ./pkg\n"
|
||||
result = executor.execute(
|
||||
code="print('hello')",
|
||||
skill_files={"pkg/__init__.py": b""},
|
||||
requirements=requirements,
|
||||
)
|
||||
|
||||
assert result["success"] is True
|
||||
|
||||
created_session = _FakeSandboxSession.last_instance
|
||||
assert created_session.copied_contents["/sandbox/.litellm_requirements.txt"] == requirements.encode("utf-8")
|
||||
assert "pip', 'install', '-r', '.litellm_requirements.txt'" in created_session.run_calls[0]
|
||||
assert "os.chdir('/sandbox')" in created_session.run_calls[1]
|
||||
|
||||
|
||||
def test_execute_uses_skill_requirements_txt(monkeypatch):
|
||||
_install_fake_sandbox(monkeypatch)
|
||||
executor = SkillsSandboxExecutor()
|
||||
monkeypatch.setattr(executor, "_collect_generated_files", lambda *args, **kwargs: [])
|
||||
|
||||
result = executor.execute(
|
||||
code="print('hello')",
|
||||
skill_files={"requirements.txt": b"requests==2.32.3\n", "main.py": b"print('x')"},
|
||||
)
|
||||
|
||||
assert result["success"] is True
|
||||
|
||||
created_session = _FakeSandboxSession.last_instance
|
||||
copied_paths = {sandbox_path for _, sandbox_path in created_session.copy_to_runtime_calls}
|
||||
assert "/sandbox/requirements.txt" in copied_paths
|
||||
assert "/sandbox/.litellm_requirements.txt" not in copied_paths
|
||||
assert "pip', 'install', '-r', 'requirements.txt'" in created_session.run_calls[0]
|
||||
|
||||
|
||||
def test_execute_returns_install_failure(monkeypatch):
|
||||
class _FailingSandboxSession(_FakeSandboxSession):
|
||||
install_exit_code = 1
|
||||
install_stdout = "pip output"
|
||||
install_stderr = "install failed"
|
||||
last_instance = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
type(self).last_instance = self
|
||||
|
||||
_install_fake_sandbox(monkeypatch, session_cls=_FailingSandboxSession)
|
||||
executor = SkillsSandboxExecutor()
|
||||
monkeypatch.setattr(executor, "_collect_generated_files", lambda *args, **kwargs: [])
|
||||
|
||||
result = executor.execute(
|
||||
code="print('hello')",
|
||||
skill_files={"main.py": b"print('x')"},
|
||||
requirements="package==1.0.0\n",
|
||||
)
|
||||
|
||||
assert result == {
|
||||
"success": False,
|
||||
"output": "pip output",
|
||||
"error": "install failed",
|
||||
"files": [],
|
||||
}
|
||||
assert len(_FailingSandboxSession.last_instance.run_calls) == 1
|
||||
Loading…
Add table
Reference in a new issue