AISE1_Project_Irina_Livio/tests/test_execution_engine.py
2026-05-26 06:31:02 +02:00

428 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pytest
import subprocess
from pathlib import Path
from unittest.mock import Mock, patch
from backend.managers.execution_engine import ExecutionEngine
# =========================================================
# FIXTURE
# =========================================================
@pytest.fixture()
def engine():
return ExecutionEngine()
# =========================================================
# BASIC TESTS (110)
# =========================================================
# ---------------------------------------------------------
# 1. Python-Datei wird korrekt ausgeführt
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_python_file_success(mock_run, engine, tmp_path):
file = tmp_path / "test.py"
file.write_text("print('hello')")
mock_run.return_value = Mock(
stdout="hello\n",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["rc"] == 0
assert "hello" in result["stdout"]
# ---------------------------------------------------------
# 2. Python-Datei mit Fehler
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_python_file_error(mock_run, engine, tmp_path):
file = tmp_path / "broken.py"
file.write_text("1/0")
mock_run.return_value = Mock(
stdout="",
stderr="ZeroDivisionError",
returncode=1
)
result = engine.run_code(file)
assert result["rc"] == 1
assert "ZeroDivisionError" in result["stderr"]
# ---------------------------------------------------------
# 3. LaTeX-Datei wird kompiliert
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_tex_file_success(mock_run, engine, tmp_path):
file = tmp_path / "doc.tex"
file.write_text("\\documentclass{article}")
mock_run.return_value = Mock(
stdout="PDF created",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["rc"] == 0
assert "PDF created" in result["stdout"]
# ---------------------------------------------------------
# 4. Unsupported File Type
# ---------------------------------------------------------
def test_run_unsupported_file(engine, tmp_path):
file = tmp_path / "test.js"
file.write_text("console.log('x')")
result = engine.run_code(file)
assert result["rc"] == 1
assert "Unsupported file type" in result["stderr"]
# ---------------------------------------------------------
# 5. Timeout wird behandelt
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_timeout(mock_run, engine, tmp_path):
file = tmp_path / "slow.py"
file.write_text("while True: pass")
mock_run.side_effect = subprocess.TimeoutExpired(
cmd=["py"],
timeout=30
)
result = engine.run_code(file)
assert result["rc"] == -1
assert "Timed out" in result["stderr"]
# ---------------------------------------------------------
# 6. Fehlender Interpreter
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_missing_interpreter(mock_run, engine, tmp_path):
file = tmp_path / "test.py"
file.write_text("print(1)")
mock_run.side_effect = FileNotFoundError("py not found")
result = engine.run_code(file)
assert result["rc"] == -1
assert "py not found" in result["stderr"]
# ---------------------------------------------------------
# 7. Allgemeine Exception
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_general_exception(mock_run, engine, tmp_path):
file = tmp_path / "test.py"
file.write_text("print(1)")
mock_run.side_effect = RuntimeError("unexpected")
result = engine.run_code(file)
assert result["rc"] == -1
assert "unexpected" in result["stderr"]
# ---------------------------------------------------------
# 8. subprocess.run wird mit cwd ausgeführt
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_uses_correct_cwd(mock_run, engine, tmp_path):
folder = tmp_path / "project"
folder.mkdir()
file = folder / "main.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
engine.run_code(file)
_, kwargs = mock_run.call_args
assert kwargs["cwd"] == folder.resolve()
# ---------------------------------------------------------
# 9. subprocess.run nutzt capture_output
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_capture_output_enabled(mock_run, engine, tmp_path):
file = tmp_path / "test.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
engine.run_code(file)
_, kwargs = mock_run.call_args
assert kwargs["capture_output"] is True
# ---------------------------------------------------------
# 10. subprocess.run nutzt text=True
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_text_mode_enabled(mock_run, engine, tmp_path):
file = tmp_path / "test.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
engine.run_code(file)
_, kwargs = mock_run.call_args
assert kwargs["text"] is True
# =========================================================
# EDGE CASE TESTS (1120)
# =========================================================
# ---------------------------------------------------------
# 11. Unicode Output
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_unicode_output(mock_run, engine, tmp_path):
file = tmp_path / "unicode.py"
file.write_text("print('🔥 Grüezi 世界')", encoding="utf-8")
mock_run.return_value = Mock(
stdout="🔥 Grüezi 世界\n",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert "🔥 Grüezi 世界" in result["stdout"]
# ---------------------------------------------------------
# 12. Leerer stdout/stderr
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_empty_output(mock_run, engine, tmp_path):
file = tmp_path / "empty.py"
file.write_text("x = 1")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["stdout"] == ""
assert result["stderr"] == ""
# ---------------------------------------------------------
# 13. Sehr langer stdout
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_large_output(mock_run, engine, tmp_path):
file = tmp_path / "large.py"
file.write_text("print('A')")
mock_run.return_value = Mock(
stdout="A" * 100000,
stderr="",
returncode=0
)
result = engine.run_code(file)
assert len(result["stdout"]) == 100000
# ---------------------------------------------------------
# 14. Dateiname mit Leerzeichen
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_filename_with_spaces(mock_run, engine, tmp_path):
file = tmp_path / "my script.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="ok",
stderr="",
returncode=0
)
engine.run_code(file)
args, _ = mock_run.call_args
assert "my script.py" in args[0]
# ---------------------------------------------------------
# 15. Dateiname mit Unicode
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_unicode_filename(mock_run, engine, tmp_path):
file = tmp_path / "🔥_test.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="ok",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["rc"] == 0
# ---------------------------------------------------------
# 16. .tex nutzt pdflatex
# ---------------------------------------------------------
@patch("subprocess.run")
def test_tex_uses_pdflatex(mock_run, engine, tmp_path):
file = tmp_path / "doc.tex"
file.write_text("x")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
engine.run_code(file)
args, _ = mock_run.call_args
assert args[0][0] == "pdflatex"
# ---------------------------------------------------------
# 17. .py nutzt py Interpreter
# ---------------------------------------------------------
@patch("subprocess.run")
def test_python_uses_py_interpreter(mock_run, engine, tmp_path):
file = tmp_path / "main.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
engine.run_code(file)
args, _ = mock_run.call_args
assert args[0][0] == "py"
# ---------------------------------------------------------
# 18. Relative Pfade funktionieren
# ---------------------------------------------------------
@patch("subprocess.run")
def test_relative_paths(mock_run, engine, tmp_path):
sub = tmp_path / "src"
sub.mkdir()
file = sub / "main.py"
file.write_text("print(1)")
mock_run.return_value = Mock(
stdout="ok",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["rc"] == 0
# ---------------------------------------------------------
# 19. Großgeschriebenes Suffix blockiert
# ---------------------------------------------------------
def test_uppercase_suffix_not_supported(engine, tmp_path):
file = tmp_path / "SCRIPT.PY"
file.write_text("print(1)")
result = engine.run_code(file)
assert result["rc"] == 1
# ---------------------------------------------------------
# 20. Leere Datei ausführen
# ---------------------------------------------------------
@patch("subprocess.run")
def test_run_empty_file(mock_run, engine, tmp_path):
file = tmp_path / "empty.py"
file.write_text("")
mock_run.return_value = Mock(
stdout="",
stderr="",
returncode=0
)
result = engine.run_code(file)
assert result["rc"] == 0