From 72825fa0a559f44fb4ea8843b52a5e69ed8ed132 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Thu, 5 Nov 2026 05:10:38 +0800 Subject: [PATCH] test: keep telemetry disabled in project CLI subprocesses Signed-off-by: Codex --- .../test_project_repository_ports.py | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/tests/cli_commands/test_project_repository_ports.py b/tests/cli_commands/test_project_repository_ports.py index bd3e8f3b1f..408814de8d 100644 --- a/tests/cli_commands/test_project_repository_ports.py +++ b/tests/cli_commands/test_project_repository_ports.py @@ -4,11 +4,71 @@ import os import subprocess import sys +import textwrap from pathlib import Path import pytest +def _project_cli_env() -> dict[str, str]: + env = {key: value for key, value in os.environ.items() if not key.startswith("LOOPX_")} + # Remove business overrides, but keep the suite's telemetry opt-out in children. + env["LOOPX_USAGE_PING"] = "0" + return env + + +@pytest.mark.parametrize("inherited_usage_ping", [None, "0", "1"]) +def test_project_cli_environment_disables_telemetry( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch, inherited_usage_ping: str | None +) -> None: + if inherited_usage_ping is None: + monkeypatch.delenv("LOOPX_USAGE_PING", raising=False) + else: + monkeypatch.setenv("LOOPX_USAGE_PING", inherited_usage_ping) + monkeypatch.setenv("LOOPX_USAGE_PING_ENDPOINT", "https://collector.invalid/events") + monkeypatch.setenv("LOOPX_RUNTIME_ROOT", str(tmp_path / "unwanted-runtime")) + # Other opt-outs must not mask losing LOOPX_USAGE_PING during filtering. + monkeypatch.delenv("DO_NOT_TRACK", raising=False) + monkeypatch.delenv("CI", raising=False) + env = _project_cli_env() + result = subprocess.run( + [sys.executable, "-c", textwrap.dedent(""" + import json + import os + import socket + import subprocess + from unittest.mock import patch + + # Fail closed: this probe cannot open a socket or launch a sender, + # even if a regression accidentally enables telemetry. + with ( + patch.object(socket, "socket", side_effect=AssertionError("network forbidden")) as network, + patch.object(subprocess, "Popen", side_effect=AssertionError("sender forbidden")) as sender, + patch("loopx.usage_ping.control") as control, + patch("loopx.usage_ping._detach") as detach, + ): + from loopx import usage_ping + ticket = usage_ping.begin("project") + usage_ping.finish(ticket, "project", 0) + assert ticket is None + control.assert_not_called() + detach.assert_not_called() + network.assert_not_called() + sender.assert_not_called() + print(json.dumps({k: v for k, v in os.environ.items() if k.startswith("LOOPX_")})) + """)], + cwd=tmp_path, + env=env, + capture_output=True, + text=True, + encoding="utf-8", + timeout=30, + check=False, + ) + assert result.returncode == 0, result.stderr + assert json.loads(result.stdout) == {"LOOPX_USAGE_PING": "0"} + + @pytest.mark.parametrize( ("scheme", "default_port", "other_port"), [("ssh", 22, 443), ("https", 443, 22), ("git", 9418, 80)], @@ -17,7 +77,7 @@ def test_project_cli_distinguishes_nondefault_repository_ports( tmp_path: Path, scheme: str, default_port: int, other_port: int ) -> None: registry = tmp_path / "registry.json" - env = {key: value for key, value in os.environ.items() if not key.startswith("LOOPX_")} + env = _project_cli_env() def run(*args: str) -> tuple[int, dict]: result = subprocess.run(