🎉 Initial commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
"""Config loading + validation tests (IMPLEMENTATION_PLAN §4.1)."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from opcda_diagnozer.config import ConfigError, load_config
|
||||
|
||||
EXAMPLE = Path(__file__).resolve().parents[1] / "config.example.yaml"
|
||||
|
||||
|
||||
def _write(tmp_path: Path, text: str) -> Path:
|
||||
p = tmp_path / "config.yaml"
|
||||
p.write_text(text, encoding="utf-8")
|
||||
return p
|
||||
|
||||
|
||||
def test_example_config_loads() -> None:
|
||||
config = load_config(EXAMPLE)
|
||||
assert config.opc.server == "Matrikon.OPC.Simulation.1"
|
||||
assert config.opc.host == "CONTROL-HOST01"
|
||||
assert len(config.tags) == 2
|
||||
assert config.tags[0].name == "Channel1.Device1.Counter"
|
||||
assert config.tags[0].expect_change is True
|
||||
assert config.tags[1].expect_change is False
|
||||
assert config.poll.interval_s == 1.0
|
||||
assert config.poll.timeout_ms == 5000
|
||||
assert config.latency.warn_ms == 1000
|
||||
assert config.report.eventlog.min_severity == "WARN"
|
||||
assert config.report.jsonl.dir == "C:/ProgramData/OPCDA-Diagnozer/logs"
|
||||
|
||||
|
||||
def test_missing_file_is_actionable() -> None:
|
||||
with pytest.raises(ConfigError, match="not found"):
|
||||
load_config("no-such-config.yaml")
|
||||
|
||||
|
||||
def test_missing_opc_section_is_actionable(tmp_path: Path) -> None:
|
||||
p = _write(tmp_path, "tags:\n - name: t\n")
|
||||
with pytest.raises(ConfigError, match=r"opc: missing required key 'server'"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_unknown_key_rejected(tmp_path: Path) -> None:
|
||||
p = _write(tmp_path, "opc:\n server: X\n typo_key: 1\ntags:\n - name: t\n")
|
||||
with pytest.raises(ConfigError, match="typo_key"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_unknown_top_level_section_rejected(tmp_path: Path) -> None:
|
||||
p = _write(tmp_path, "opc:\n server: X\ntags:\n - name: t\nnonsense: {}\n")
|
||||
with pytest.raises(ConfigError, match="nonsense"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_empty_tags_rejected(tmp_path: Path) -> None:
|
||||
p = _write(tmp_path, "opc:\n server: X\ntags: []\n")
|
||||
with pytest.raises(ConfigError, match="at least one tag"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_duplicate_tags_rejected(tmp_path: Path) -> None:
|
||||
p = _write(tmp_path, "opc:\n server: X\ntags:\n - name: a\n - name: a\n")
|
||||
with pytest.raises(ConfigError, match="duplicate"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_latency_threshold_order_rejected(tmp_path: Path) -> None:
|
||||
p = _write(
|
||||
tmp_path,
|
||||
"opc:\n server: X\ntags:\n - name: t\n"
|
||||
"latency:\n warn_ms: 5000\n critical_ms: 1000\n",
|
||||
)
|
||||
with pytest.raises(ConfigError, match="warn_ms"):
|
||||
load_config(p)
|
||||
|
||||
|
||||
def test_hard_hang_must_exceed_timeout(tmp_path: Path) -> None:
|
||||
p = _write(
|
||||
tmp_path,
|
||||
"opc:\n server: X\ntags:\n - name: t\n"
|
||||
"poll:\n timeout_ms: 5000\n hard_hang_s: 4\n",
|
||||
)
|
||||
with pytest.raises(ConfigError, match="hard_hang_s"):
|
||||
load_config(p)
|
||||
Reference in New Issue
Block a user