Upload ocm26400/test_computer_use.py with huggingface_hub
Browse files
ocm26400/test_computer_use.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Tests TDD — computer use réel (ShellTool, OCM-26400).
|
| 2 |
+
|
| 3 |
+
Valide l'exécution RÉELLE de commandes + la SÉCURITÉ (mode sûr sans shell=True :
|
| 4 |
+
injection neutralisée) + l'allowlist.
|
| 5 |
+
"""
|
| 6 |
+
from ocm26400.computer_use import ShellTool, safe_default_allowlist, GUITool
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def test_shell_runs_real_command():
|
| 10 |
+
"""echo réel -> retourne la sortie."""
|
| 11 |
+
out = ShellTool().query("echo hello_ocm")
|
| 12 |
+
assert "hello_ocm" in out
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def test_shell_safe_mode_neutralizes_injection():
|
| 16 |
+
"""raw=False (défaut) : $(...) n'est PAS interprété (pas de shell, pas d'injection).
|
| 17 |
+
|
| 18 |
+
En mode shell, 'echo $(whoami)' substituerait le nom d'utilisateur ; en mode sûr,
|
| 19 |
+
'$(whoami)' est imprimé LITTÉRALEMENT (shlex.split -> ['echo','$(whoami)'])."""
|
| 20 |
+
import getpass
|
| 21 |
+
out = ShellTool().query("echo $(whoami)")
|
| 22 |
+
assert "$(whoami)" in out # imprimé littéralement, pas substitué
|
| 23 |
+
user = getpass.getuser()
|
| 24 |
+
assert user not in out # le nom réel n'est PAS injecté
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def test_shell_allowlist_blocks_disallowed():
|
| 28 |
+
"""Allowlist restreint les binaires permis."""
|
| 29 |
+
tool = ShellTool(allowlist=["echo"])
|
| 30 |
+
assert "hello" in tool.query("echo hello")
|
| 31 |
+
blocked = tool.query("ls")
|
| 32 |
+
assert "bloqué" in blocked
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def test_shell_missing_command_returns_error():
|
| 36 |
+
out = ShellTool().query("ceci_n_existe_pas_123")
|
| 37 |
+
assert "introuvable" in out or "erreur" in out
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def test_safe_default_allowlist_is_readonly():
|
| 41 |
+
al = safe_default_allowlist()
|
| 42 |
+
assert "ls" in al and "echo" in al
|
| 43 |
+
assert "rm" not in al and "sudo" not in al
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def test_gui_tool_interface_present():
|
| 47 |
+
"""GUITool (computer-use GUI souris/clavier) : interface présente.
|
| 48 |
+
En headless, .available=False et les méthodes retournent un message gracieux (pas
|
| 49 |
+
de crash) — la capacité existe dans le code, l'exécution demande un display."""
|
| 50 |
+
gui = GUITool()
|
| 51 |
+
if not gui.available: # headless (cas ici)
|
| 52 |
+
for out in (gui.move_to(10, 20), gui.click(0, 0), gui.type_text("x"), gui.screenshot()):
|
| 53 |
+
assert isinstance(out, str) and ("indisponible" in out or "display" in out)
|
| 54 |
+
else: # si display présent : pas de crash
|
| 55 |
+
assert gui.available is True
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def test_gui_safe_text_allowlist():
|
| 59 |
+
"""Anti-injection clavier : seuls alphanumérique + ponctuation basique sont frappables."""
|
| 60 |
+
rx = GUITool._SAFE_TEXT
|
| 61 |
+
assert rx.match("hello world") # ok
|
| 62 |
+
assert rx.match("OCM-26400, c'est test!") # ok (ponctuation basique)
|
| 63 |
+
assert rx.match("abc;rm") is None # ';' interdit (anti-injection)
|
| 64 |
+
assert rx.match("$(whoami)") is None # substitution shell interdite
|
| 65 |
+
assert rx.match("a|b") is None # pipe interdit
|
| 66 |
+
assert rx.match("a\nb") is None # newline interdit
|