8OI-508 / FS-515 regression coverage — ``debug_config.json`` schema
9bridge. :func:`_get_debug_domain_map` must normalise both the legacy v1
10``domains:`` and the current v2 ``DEBUG_LEVELS:`` shape into a single
11map shape; :func:`migrate_config` must upgrade v1 -> v2 in-place with a
12``.bk`` backup and be idempotent on already-v2 files. The
13``oct diag migrate-config`` CLI command must expose the same behaviour
14and print a helpful summary.
18- Verify legacy v1 ``domains:`` config normalises into v2 ``DEBUG_LEVELS``.
19- Verify ``migrate-config`` creates a ``.bk`` backup and is idempotent.
20- Verify ``validate-config`` emits a WARNING on legacy schema with a
21 ``migrate-config`` hint.
28 L3 — assertion details
33- Legacy ``domains:`` config normalises into a v2 ``DEBUG_LEVELS`` map.
34- Running migrate-config writes ``<path>.bk`` with the original content.
35- Running migrate-config twice is a no-op (no backup clobber).
36- ``validate-config`` emits a WARNING (not ERROR) on legacy schema and
37 references the ``migrate-config`` hint.
40from __future__
import annotations
43from pathlib
import Path
46from click.testing
import CliRunner
50 CURRENT_SCHEMA_VERSION,
51 _get_debug_domain_map,
58 "_schema_version":
"1.0",
60 "ALPHA": {
"level": 2,
"color":
"red"},
61 "BETA": {
"level": 3,
"color":
"blue"},
63 "global_settings": {
"mode":
"dev"},
66_LEGACY_SHORT = {
"domains": {
"TEST": 2}}
69 "_schema_version":
"2.0",
71 "ALPHA": {
"level": 2,
"color":
"red"},
73 "global_settings": {
"mode":
"dev"},
77def _write(path: Path, data: dict) -> Path:
78 path.write_text(json.dumps(data, indent=2), encoding=
"utf-8")
83 """v2 ``DEBUG_LEVELS`` → is_legacy is False."""
84 m, legacy = _get_debug_domain_map(_V2_FULL)
85 assert legacy
is False
86 assert m[
"ALPHA"][
"level"] == 2
90 """v1 ``domains`` → is_legacy is True; shape matches v2."""
91 m, legacy = _get_debug_domain_map(_LEGACY_FULL)
93 assert m[
"ALPHA"] == {
"level": 2,
"color":
"red"}
94 assert m[
"BETA"][
"color"] ==
"blue"
98 """v1 short form ``{"TEST": 2}`` → ``{"TEST": {"level": 2, "color": "default"}}``."""
99 m, legacy = _get_debug_domain_map(_LEGACY_SHORT)
100 assert legacy
is True
101 assert m[
"TEST"] == {
"level": 2,
"color":
"default"}
105 """OI-508: migrate writes v2 schema in-place and creates .bk backup."""
106 cfg =
_write(tmp_path /
"debug_config.json", _LEGACY_FULL)
107 original = cfg.read_text(encoding=
"utf-8")
108 result = migrate_config(cfg)
109 backup = cfg.with_suffix(
".json.bk")
111 assert result[
"_schema_version"] == CURRENT_SCHEMA_VERSION
112 assert "DEBUG_LEVELS" in result
and "domains" not in result
113 on_disk = json.loads(cfg.read_text(encoding=
"utf-8"))
114 assert on_disk[
"DEBUG_LEVELS"][
"ALPHA"][
"color"] ==
"red"
115 assert backup.read_text(encoding=
"utf-8") == original
119 """OI-508: running migrate on an already-v2 file is a no-op."""
120 cfg =
_write(tmp_path /
"debug_config.json", _V2_FULL)
121 before = cfg.read_text(encoding=
"utf-8")
123 after = cfg.read_text(encoding=
"utf-8")
124 assert before == after
125 assert not cfg.with_suffix(
".json.bk").exists()
129 """OI-508: dry_run returns the target shape without touching disk."""
130 cfg =
_write(tmp_path /
"debug_config.json", _LEGACY_FULL)
131 before = cfg.read_text(encoding=
"utf-8")
132 new = migrate_config(cfg, dry_run=
True)
133 assert new[
"_schema_version"] == CURRENT_SCHEMA_VERSION
134 assert cfg.read_text(encoding=
"utf-8") == before
135 assert not cfg.with_suffix(
".json.bk").exists()
139 """OI-508: legacy schema → WARNING with migration hint; no hard ERROR."""
140 (tmp_path /
"oc_diagnostics").mkdir()
141 _write(tmp_path /
"oc_diagnostics" /
"debug_config.json", _LEGACY_FULL)
142 issues = validate_config(tmp_path)
143 legacy_warnings = [i
for i
in issues
if "legacy v1 schema" in i]
144 assert legacy_warnings, issues
145 assert "migrate-config" in legacy_warnings[0]
146 assert not any(i.startswith(
"ERROR")
for i
in issues)
150 """OI-508: ``oct diag migrate-config PATH`` migrates an arbitrary file."""
151 cfg =
_write(tmp_path /
"legacy.json", {
"domains": {
"TEST": 2}})
153 result = runner.invoke(cli, [
"diag",
"migrate-config", str(cfg)])
154 assert result.exit_code == 0, result.output
155 on_disk = json.loads(cfg.read_text(encoding=
"utf-8"))
156 assert on_disk[
"_schema_version"] == CURRENT_SCHEMA_VERSION
157 assert on_disk[
"DEBUG_LEVELS"][
"TEST"][
"level"] == 2
158 assert cfg.with_suffix(
".json.bk").is_file()
test_get_debug_domain_map_v1_is_legacy()
test_cli_migrate_config_round_trip(Path tmp_path)
test_validate_config_warns_on_legacy_schema(Path tmp_path)
test_migrate_config_idempotent_on_v2(Path tmp_path)
test_migrate_config_dry_run_never_writes(Path tmp_path)
Path _write(Path path, dict data)
test_get_debug_domain_map_short_form_normalised()
test_get_debug_domain_map_v2_not_legacy()
test_migrate_config_upgrades_v1_to_v2(Path tmp_path)