From 6f588c753b6b4653d0d2958806df679cff674bab Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 19 May 2026 21:35:56 -0700 Subject: [PATCH] test(proxy_behavior): codify G3 (strict-import grep) as a pytest item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slice 6 of the management-endpoints behavior-pinning effort. Two new tests walk every .py file under tests/proxy_behavior/ and assert: * no ``from litellm.proxy.management_endpoints`` import — the suite is deliberately constrained to the HTTP boundary so it survives handler refactors; * no ``mock``/``patch`` on ``user_api_key_auth`` — mocking auth is the structural failure mode of the existing 11k-line mock suite, and the point of this harness is that the real auth layer runs. Codifying G3 as a CI test removes the "did someone forget to check the PR-description checklist" failure mode. Plan: https://www.notion.so/36643b8acdab8128a581ced0f6a4744d --- .../management/test_no_management_imports.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 tests/proxy_behavior/management/test_no_management_imports.py diff --git a/tests/proxy_behavior/management/test_no_management_imports.py b/tests/proxy_behavior/management/test_no_management_imports.py new file mode 100644 index 00000000000..f5409b8e372 --- /dev/null +++ b/tests/proxy_behavior/management/test_no_management_imports.py @@ -0,0 +1,64 @@ +"""Codify G3 (strict-import grep) as a test. + +The behavior-pinning suite asserts at the HTTP boundary against a real proxy +app. Two forbidden patterns: + +1. ``from litellm.proxy.management_endpoints`` — importing handler functions + directly turns the suite into unit tests of the handler module rather than + behavior tests of the API, and makes the suite brittle to refactors. + +2. ``mock``/``patch`` on ``user_api_key_auth`` — mocking auth is the + structural failure mode of today's mock-heavy suite. The whole point of the + real-DB harness is that auth runs. + +Running this as a pytest item means G3 is enforced by CI on every PR, not by +a checklist someone might forget. +""" + +import pathlib +import re + +import pytest + +REPO_ROOT = pathlib.Path(__file__).resolve().parents[3] +BEHAVIOR_DIR = REPO_ROOT / "tests" / "proxy_behavior" + +FORBIDDEN_IMPORT = re.compile(r"^\s*from\s+litellm\.proxy\.management_endpoints\b") +FORBIDDEN_AUTH_MOCK = re.compile( + r"(?:mock\.[A-Za-z_]+|patch[a-z_]*)\([^)]*user_api_key_auth" +) + +# This very file is the one place where the forbidden patterns appear as +# regex source; exclude it from its own scan so the test is self-checkable. +SELF = pathlib.Path(__file__).resolve() + + +def _iter_py_files(): + for path in BEHAVIOR_DIR.rglob("*.py"): + if path.resolve() == SELF: + continue + yield path + + +def test_no_management_endpoint_imports(): + violations = [] + for path in _iter_py_files(): + for lineno, line in enumerate(path.read_text().splitlines(), start=1): + if FORBIDDEN_IMPORT.search(line): + violations.append(f"{path.relative_to(REPO_ROOT)}:{lineno}: {line.strip()}") + assert not violations, ( + "tests/proxy_behavior/ must not import from litellm.proxy.management_endpoints " + "(G3 — assert at the HTTP boundary). Violations:\n " + "\n ".join(violations) + ) + + +def test_no_user_api_key_auth_mocking(): + violations = [] + for path in _iter_py_files(): + for lineno, line in enumerate(path.read_text().splitlines(), start=1): + if FORBIDDEN_AUTH_MOCK.search(line): + violations.append(f"{path.relative_to(REPO_ROOT)}:{lineno}: {line.strip()}") + assert not violations, ( + "tests/proxy_behavior/ must not mock user_api_key_auth (G3 — auth runs for " + "real). Violations:\n " + "\n ".join(violations) + )