Option C Tools
Loading...
Searching...
No Matches
test_quality_gate_sandbox.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_git/test_quality_gate_sandbox.py
4
5"""
6Purpose
7-------
8OI-517 regression coverage — ``oct git check --sandbox`` must route the
9optional pytest subprocess through :class:`oct.mcp.sandbox.SandboxExecutor`
10so the sanitised environment rules (``PYTHONPATH`` stripped, secret-named
11env vars stripped, output capped, 600s timeout) apply whenever tests are
12included in the quality gate.
13
14When ``--sandbox`` is absent, pytest must still run via the legacy
15``subprocess.run`` path (unchanged behaviour for existing CI).
16
17Responsibilities
18----------------
19- Verify ``sandbox=True`` routes pytest through ``SandboxExecutor``.
20- Verify ``sandbox=False`` uses ``subprocess.run`` directly.
21- Verify ``--sandbox`` CLI option threads through to ``run_quality_gate``.
22
23Diagnostics
24-----------
25Domain: GIT-TESTS
26Levels:
27 L2 — test lifecycle
28 L3 — assertion details
29 L4 — deep tracing
30
31Contracts
32---------
33- ``_run_test_pass(project_root, sandbox=True)`` goes through
34 :class:`SandboxExecutor`.
35- ``_run_test_pass(project_root)`` / ``sandbox=False`` uses
36 ``subprocess.run`` directly.
37- The CLI option ``--sandbox`` on ``oct git check`` threads through to
38 :func:`run_quality_gate`.
39"""
40
41from __future__ import annotations
42
43from dataclasses import dataclass
44from pathlib import Path
45
46import pytest
47from click.testing import CliRunner
48
49from oct.cli import cli
50from oct.git import quality_gate as qg
51
52
53@dataclass
55 returncode: int = 0
56 stdout: str = ""
57 stderr: str = ""
58
59
60def test_run_test_pass_default_uses_subprocess(tmp_path: Path, monkeypatch):
61 """OI-517: no sandbox flag → legacy subprocess.run path."""
62 calls = {"subprocess": 0, "sandbox": 0}
63
64 def _fake_subprocess_run(*args, **kwargs):
65 calls["subprocess"] += 1
66 return _FakeCompleted(returncode=0)
67
68 class _FakeExecutor:
69 def __init__(self, *a, **kw):
70 calls["sandbox"] += 1
71
72 def run(self, cmd, cwd, timeout): # noqa: ARG002
73 return _FakeCompleted(returncode=0)
74
75 monkeypatch.setattr(qg.subprocess, "run", _fake_subprocess_run)
76 monkeypatch.setattr("oct.mcp.sandbox.SandboxExecutor", _FakeExecutor)
77
78 qg._run_test_pass(tmp_path, sandbox=False)
79 assert calls["subprocess"] == 1
80 assert calls["sandbox"] == 0
81
82
83def test_run_test_pass_sandbox_uses_executor(tmp_path: Path, monkeypatch):
84 """OI-517: sandbox=True → SandboxExecutor.run replaces subprocess.run."""
85 calls = {"subprocess": 0, "sandbox_run": 0}
86
87 def _fake_subprocess_run(*args, **kwargs):
88 calls["subprocess"] += 1
89 return _FakeCompleted(returncode=0)
90
91 captured = {}
92
93 class _FakeSandboxResult:
94 def __init__(self, code):
95 self.exit_code = code
96 self.timed_out = False
97
98 class _FakeExecutor:
99 def __init__(self, *a, **kw):
100 pass
101
102 def run(self, cmd, cwd, timeout):
103 calls["sandbox_run"] += 1
104 captured["cmd"] = cmd
105 captured["cwd"] = cwd
106 captured["timeout"] = timeout
107 return _FakeSandboxResult(0)
108
109 monkeypatch.setattr(qg.subprocess, "run", _fake_subprocess_run)
110 monkeypatch.setattr("oct.mcp.sandbox.SandboxExecutor", _FakeExecutor)
111
112 qg._run_test_pass(tmp_path, sandbox=True)
113 assert calls["sandbox_run"] == 1
114 assert calls["subprocess"] == 0
115 assert captured["timeout"] == 600
116 assert "pytest" in captured["cmd"]
117
118
120 """OI-517: ``oct git check --sandbox --help`` parses; flag documented."""
121 runner = CliRunner()
122 result = runner.invoke(cli, ["git", "check", "--help"])
123 assert result.exit_code == 0
124 assert "--sandbox" in result.output
125 assert "MCP sandbox" in result.output
Definition cli.py:1
test_run_test_pass_default_uses_subprocess(Path tmp_path, monkeypatch)
test_run_test_pass_sandbox_uses_executor(Path tmp_path, monkeypatch)