Option C Tools
Loading...
Searching...
No Matches
test_migrate_config.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_diag/test_migrate_config.py
4
5"""
6Purpose
7-------
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.
15
16Responsibilities
17----------------
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.
22
23Diagnostics
24-----------
25Domain: DIAG-TESTS
26Levels:
27 L2 — test lifecycle
28 L3 — assertion details
29 L4 — deep tracing
30
31Contracts
32---------
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.
38"""
39
40from __future__ import annotations
41
42import json
43from pathlib import Path
44
45import pytest
46from click.testing import CliRunner
47
48from oct.cli import cli
49from oct.diag.oct_diag import (
50 CURRENT_SCHEMA_VERSION,
51 _get_debug_domain_map,
52 migrate_config,
53 validate_config,
54)
55
56
57_LEGACY_FULL = {
58 "_schema_version": "1.0",
59 "domains": {
60 "ALPHA": {"level": 2, "color": "red"},
61 "BETA": {"level": 3, "color": "blue"},
62 },
63 "global_settings": {"mode": "dev"},
64}
65
66_LEGACY_SHORT = {"domains": {"TEST": 2}}
67
68_V2_FULL = {
69 "_schema_version": "2.0",
70 "DEBUG_LEVELS": {
71 "ALPHA": {"level": 2, "color": "red"},
72 },
73 "global_settings": {"mode": "dev"},
74}
75
76
77def _write(path: Path, data: dict) -> Path:
78 path.write_text(json.dumps(data, indent=2), encoding="utf-8")
79 return path
80
81
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
87
88
90 """v1 ``domains`` → is_legacy is True; shape matches v2."""
91 m, legacy = _get_debug_domain_map(_LEGACY_FULL)
92 assert legacy is True
93 assert m["ALPHA"] == {"level": 2, "color": "red"}
94 assert m["BETA"]["color"] == "blue"
95
96
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"}
102
103
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")
110
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
116
117
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")
122 migrate_config(cfg)
123 after = cfg.read_text(encoding="utf-8")
124 assert before == after
125 assert not cfg.with_suffix(".json.bk").exists()
126
127
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()
136
137
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)
147
148
150 """OI-508: ``oct diag migrate-config PATH`` migrates an arbitrary file."""
151 cfg = _write(tmp_path / "legacy.json", {"domains": {"TEST": 2}})
152 runner = CliRunner()
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()
Definition cli.py:1
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_migrate_config_upgrades_v1_to_v2(Path tmp_path)