stack: Telemetrie-Default nach Installationsform, Byte-Deckel und Session-Retention (schliesst #55)
Files changed: - .gitea/workflows/ci.yml - .gitignore - CHANGES.md - EVALS.md - INSTALL-MCP.md - INSTALL.md - VERSION - instructions/setup-instance.md - reports/CONTRACT.md - tools/CONTRACT.md - tools/chemenu/commands/doctor.py - tools/chemenu/config.py - tools/chemenu/mcp/server.py - tools/chemenu/telemetry/policy.py - tools/chemenu/telemetry/schema.py - tools/chemenu/telemetry/writer.py - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_doctor.py - tools/chemenu/tests/test_mcp_server.py - tools/chemenu/tests/test_telemetry_emit.py - tools/chemenu/tests/test_telemetry_policy.py - tools/chemenu/version.py
This commit is contained in:
1 parent
71446c0f29
commit
82a22eaa93
22 files changed
+801
-44
No files matched your search
@@ -0,0 +1,127 @@
|
||||
"""Telemetry policy: installation-form default, the two overrides that beat
|
||||
it, and the caching split between the filesystem-derived half and the
|
||||
always-live environment half."""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from chemenu.telemetry import policy
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clean_env(monkeypatch):
|
||||
for var in (policy.ENV_ENABLED, policy.ENV_MAX_SESSION_BYTES, policy.ENV_KEEP_SESSIONS):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
policy.reset_cache()
|
||||
yield
|
||||
policy.reset_cache()
|
||||
|
||||
|
||||
def _stamp(root: Path) -> None:
|
||||
(root / ".wikitool-release.json").write_text("{}", encoding="utf-8")
|
||||
|
||||
|
||||
def _config_file(root: Path, **fields) -> None:
|
||||
import json
|
||||
|
||||
(root / ".wikitool-telemetry.json").write_text(json.dumps(fields), encoding="utf-8")
|
||||
|
||||
|
||||
def test_a_dev_checkout_defaults_on(tmp_path):
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.enabled is True
|
||||
assert "dev checkout" in pol.reason
|
||||
|
||||
|
||||
def test_a_stamped_distribution_defaults_off(tmp_path):
|
||||
_stamp(tmp_path)
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.enabled is False
|
||||
assert "distributed instance" in pol.reason
|
||||
|
||||
|
||||
def test_the_config_file_overrides_the_form_default(tmp_path):
|
||||
_stamp(tmp_path)
|
||||
_config_file(tmp_path, enabled=True)
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.enabled is True
|
||||
assert ".wikitool-telemetry.json" in pol.reason
|
||||
|
||||
|
||||
def test_the_env_var_overrides_the_config_file_in_both_directions(tmp_path, monkeypatch):
|
||||
_config_file(tmp_path, enabled=True)
|
||||
monkeypatch.setenv(policy.ENV_ENABLED, "0")
|
||||
assert policy.resolve(tmp_path).enabled is False
|
||||
|
||||
_stamp(tmp_path)
|
||||
_config_file(tmp_path, enabled=False)
|
||||
monkeypatch.setenv(policy.ENV_ENABLED, "1")
|
||||
assert policy.resolve(tmp_path).enabled is True
|
||||
|
||||
|
||||
def test_default_caps(tmp_path):
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.max_session_bytes == policy.DEFAULT_MAX_SESSION_BYTES
|
||||
assert pol.keep_sessions == policy.DEFAULT_KEEP_SESSIONS
|
||||
|
||||
|
||||
def test_the_config_file_can_set_both_caps(tmp_path):
|
||||
_config_file(tmp_path, max_session_bytes=1024, keep_sessions=5)
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.max_session_bytes == 1024
|
||||
assert pol.keep_sessions == 5
|
||||
|
||||
|
||||
def test_env_caps_override_the_config_file(tmp_path, monkeypatch):
|
||||
_config_file(tmp_path, max_session_bytes=1024, keep_sessions=5)
|
||||
monkeypatch.setenv(policy.ENV_MAX_SESSION_BYTES, "2048")
|
||||
monkeypatch.setenv(policy.ENV_KEEP_SESSIONS, "9")
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.max_session_bytes == 2048
|
||||
assert pol.keep_sessions == 9
|
||||
|
||||
|
||||
def test_a_non_positive_or_unparsable_override_is_ignored(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv(policy.ENV_MAX_SESSION_BYTES, "0")
|
||||
monkeypatch.setenv(policy.ENV_KEEP_SESSIONS, "not-a-number")
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.max_session_bytes == policy.DEFAULT_MAX_SESSION_BYTES
|
||||
assert pol.keep_sessions == policy.DEFAULT_KEEP_SESSIONS
|
||||
|
||||
|
||||
def test_a_malformed_config_file_is_treated_as_absent(tmp_path):
|
||||
(tmp_path / ".wikitool-telemetry.json").write_text("{not json", encoding="utf-8")
|
||||
pol = policy.resolve(tmp_path)
|
||||
assert pol.enabled is True # falls through to the dev-checkout form default
|
||||
|
||||
|
||||
def test_the_filesystem_half_is_cached_per_root(tmp_path):
|
||||
"""Writing the stamp *after* the first resolve must not retroactively
|
||||
change the cached answer - `reset_cache()` is required to see it."""
|
||||
first = policy.resolve(tmp_path)
|
||||
assert first.enabled is True
|
||||
_stamp(tmp_path)
|
||||
still_cached = policy.resolve(tmp_path)
|
||||
assert still_cached.enabled is True
|
||||
policy.reset_cache()
|
||||
assert policy.resolve(tmp_path).enabled is False
|
||||
|
||||
|
||||
def test_the_env_override_is_always_live_even_with_a_cached_root(tmp_path, monkeypatch):
|
||||
"""The env var must never need a `reset_cache()` to take effect - only the
|
||||
filesystem-derived half is cached."""
|
||||
assert policy.resolve(tmp_path).enabled is True
|
||||
monkeypatch.setenv(policy.ENV_ENABLED, "0")
|
||||
assert policy.resolve(tmp_path).enabled is False
|
||||
monkeypatch.delenv(policy.ENV_ENABLED)
|
||||
assert policy.resolve(tmp_path).enabled is True
|
||||
|
||||
|
||||
def test_resolve_defaults_to_config_root(tmp_path, monkeypatch):
|
||||
from chemenu import config
|
||||
|
||||
monkeypatch.setattr(config, "ROOT", tmp_path)
|
||||
_stamp(tmp_path)
|
||||
assert policy.resolve().enabled is False
|
||||
Reference in new issue
Block a user