Sweep finding #12. load_config merges the sibling config.local.yaml and dispatcher.cfg binds at import, so the suite inherited whatever this deployment had configured. With `classifier.mode: local_encoder` in the overlay -- the setting this deployment actually runs -- nine tests failed with assertions like `assert 'local_encoder' == 'local_llm'`: five in test_classifier_backoff, three in test_gaming_mode, one in test_classifier_modes_dispatch. Reproduced both directions on the same tree before the fix: overlay absent 1523 passed, overlay present 9 failed. So a deployment that had configured anything could not run its own tests clean, and the failures looked like regressions rather than a fixture problem -- which is the expensive part. `ROUTER_IGNORE_LOCAL_CONFIG` makes load_config skip the overlay, and tests/conftest.py sets it as a module-level statement rather than a fixture: it has to happen before the first `import dispatcher` in any test module, and pytest imports conftest first. An explicit `include_overlay` parameter goes with it, because the blanket env var broke the five tests in test_config.py that exercise overlay merging on their own tmp files -- behaviour that is the thing under test, not an accident of the developer's machine. Those now opt in. The default stays None, meaning "consult the environment", so the production path is unchanged. Verified after the fix: 1613 pass with the real overlay in place and 1613 pass without it, identically. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
97 lines
3.9 KiB
Python
97 lines
3.9 KiB
Python
"""The suite must not read whichever config.local.yaml this machine has.
|
|
|
|
`load_config` merges the sibling overlay and `dispatcher.cfg` binds at
|
|
import, so before conftest.py set ROUTER_IGNORE_LOCAL_CONFIG the whole suite
|
|
inherited the deployment's settings. With `classifier.mode: local_encoder`
|
|
in the overlay -- what this deployment actually runs -- nine tests failed
|
|
with assertions like `assert 'local_encoder' == 'local_llm'`. Reproduced
|
|
both directions on the same tree: overlay absent 1523 passed, overlay
|
|
present 9 failed.
|
|
|
|
The failures looked like regressions, which is the expensive part: a
|
|
deployment that had configured anything could not trust its own test run.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
import dispatcher
|
|
from config import load_config
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def test_the_env_guard_is_set_for_the_suite():
|
|
"""conftest.py sets this before anything imports dispatcher."""
|
|
assert os.environ.get("ROUTER_IGNORE_LOCAL_CONFIG")
|
|
|
|
|
|
def test_dispatcher_cfg_matches_config_yaml_not_the_overlay():
|
|
"""The classifier mode the suite sees is the one config.yaml declares.
|
|
|
|
This is the specific value that broke nine tests, so it is the one
|
|
asserted rather than a generic property.
|
|
"""
|
|
base = yaml.safe_load((ROOT / "config" / "config.yaml").read_text())
|
|
declared = (base.get("classifier") or {}).get("mode", "local_llm")
|
|
assert dispatcher.cfg.classifier.mode == declared
|
|
|
|
|
|
def test_a_real_overlay_on_disk_does_not_reach_the_suite():
|
|
"""If this deployment has an overlay, it is being ignored right now."""
|
|
overlay = ROOT / "config" / "config.local.yaml"
|
|
if not overlay.exists():
|
|
return # nothing to prove on a clean checkout
|
|
local = yaml.safe_load(overlay.read_text()) or {}
|
|
overridden = (local.get("classifier") or {}).get("mode")
|
|
if overridden is None:
|
|
return
|
|
base = yaml.safe_load((ROOT / "config" / "config.yaml").read_text())
|
|
declared = (base.get("classifier") or {}).get("mode", "local_llm")
|
|
if overridden == declared:
|
|
return # the overlay agrees; nothing to distinguish
|
|
assert dispatcher.cfg.classifier.mode == declared, (
|
|
"the machine's config.local.yaml is leaking into the test suite"
|
|
)
|
|
|
|
|
|
def test_include_overlay_true_still_merges(tmp_path):
|
|
"""The opt-in exists so overlay behaviour itself stays testable."""
|
|
base = yaml.safe_load((ROOT / "config" / "config.yaml").read_text())
|
|
base_path = tmp_path / "config.yaml"
|
|
base_path.write_text(yaml.safe_dump(base, sort_keys=False))
|
|
(tmp_path / "config.local.yaml").write_text(
|
|
yaml.safe_dump({"logging": {"level": "error"}})
|
|
)
|
|
merged = load_config(str(base_path), include_overlay=True)
|
|
assert merged.logging.level == "error"
|
|
|
|
|
|
def test_include_overlay_false_ignores_it(tmp_path):
|
|
base = yaml.safe_load((ROOT / "config" / "config.yaml").read_text())
|
|
base_path = tmp_path / "config.yaml"
|
|
base_path.write_text(yaml.safe_dump(base, sort_keys=False))
|
|
(tmp_path / "config.local.yaml").write_text(
|
|
yaml.safe_dump({"logging": {"level": "error"}})
|
|
)
|
|
assert load_config(str(base_path), include_overlay=False).logging.level != "error"
|
|
|
|
|
|
def test_the_default_follows_the_env_var(tmp_path, monkeypatch):
|
|
"""include_overlay=None consults the environment, which is how the
|
|
production path keeps merging while the suite does not."""
|
|
base = yaml.safe_load((ROOT / "config" / "config.yaml").read_text())
|
|
base_path = tmp_path / "config.yaml"
|
|
base_path.write_text(yaml.safe_dump(base, sort_keys=False))
|
|
(tmp_path / "config.local.yaml").write_text(
|
|
yaml.safe_dump({"logging": {"level": "error"}})
|
|
)
|
|
monkeypatch.delenv("ROUTER_IGNORE_LOCAL_CONFIG", raising=False)
|
|
assert load_config(str(base_path)).logging.level == "error"
|
|
monkeypatch.setenv("ROUTER_IGNORE_LOCAL_CONFIG", "1")
|
|
assert load_config(str(base_path)).logging.level != "error"
|