114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
"""Unit tests for bootstrap configuration loading behavior."""
|
|
|
|
import importlib
|
|
from pathlib import Path
|
|
from unittest.mock import Mock
|
|
|
|
import yaml
|
|
|
|
from config.schema import (
|
|
BridgeConfig,
|
|
DeviceStatusConfig,
|
|
EventQueueConfig,
|
|
LoggingConfig,
|
|
MQTTConfig,
|
|
OdooConfig,
|
|
)
|
|
from core.bootstrap import get_mqtt_config, load_bridge_config
|
|
from exceptions import ConfigurationError
|
|
|
|
|
|
def _base_config() -> BridgeConfig:
|
|
return BridgeConfig(
|
|
mqtt=MQTTConfig(broker="yaml-broker", port=1883, client_id="bridge"),
|
|
odoo=OdooConfig(use_mock=True),
|
|
logging=LoggingConfig(),
|
|
event_queue=EventQueueConfig(),
|
|
device_status=DeviceStatusConfig(),
|
|
devices=[],
|
|
)
|
|
|
|
|
|
def test_load_bridge_config_returns_none_on_missing_main_config(monkeypatch):
|
|
bootstrap_module = importlib.import_module("core.bootstrap")
|
|
|
|
def fail_load_config(_path):
|
|
raise ConfigurationError("missing")
|
|
|
|
monkeypatch.setattr(bootstrap_module, "load_config", fail_load_config)
|
|
|
|
config = load_bridge_config("missing.yaml", Path("/tmp/no-active.yaml"), logger=None)
|
|
|
|
assert config is None
|
|
|
|
|
|
def test_load_bridge_config_merges_persisted_mqtt_and_devices(monkeypatch, tmp_path):
|
|
bootstrap_module = importlib.import_module("core.bootstrap")
|
|
|
|
active_path = tmp_path / "config-active.yaml"
|
|
active_path.write_text(
|
|
yaml.safe_dump(
|
|
{
|
|
"mqtt": {
|
|
"broker": "persisted-broker",
|
|
"port": 1884,
|
|
"username": "mqtt-user",
|
|
"password": "secret",
|
|
"client_id": "persisted-client",
|
|
"keepalive": 30,
|
|
"use_tls": True,
|
|
},
|
|
"devices": [
|
|
{
|
|
"device_id": "dev-1",
|
|
"mqtt_topic": "shelly/dev-1/status",
|
|
"parser_type": "shelly_pm",
|
|
"machine_name": "Machine 1",
|
|
"session_config": {
|
|
"standby_threshold_w": 5,
|
|
"working_threshold_w": 20,
|
|
"start_debounce_s": 3,
|
|
"stop_debounce_s": 15,
|
|
"message_timeout_s": 20,
|
|
"heartbeat_interval_s": 60,
|
|
},
|
|
}
|
|
],
|
|
}
|
|
)
|
|
)
|
|
|
|
expected_devices = [Mock(device_id="dev-1")]
|
|
monkeypatch.setattr(bootstrap_module, "load_config", lambda _path: _base_config())
|
|
monkeypatch.setattr(
|
|
bootstrap_module,
|
|
"load_devices_from_config",
|
|
lambda _path: expected_devices,
|
|
)
|
|
|
|
config = load_bridge_config("config.yaml", active_path, logger=None)
|
|
|
|
assert config is not None
|
|
assert config.devices == expected_devices
|
|
assert config.mqtt.broker == "persisted-broker"
|
|
assert config.mqtt.port == 1884
|
|
assert config.mqtt.use_tls is True
|
|
|
|
|
|
def test_get_mqtt_config_falls_back_to_environment(monkeypatch):
|
|
monkeypatch.setenv("MQTT_BROKER", "env-broker")
|
|
monkeypatch.setenv("MQTT_PORT", "1999")
|
|
monkeypatch.setenv("MQTT_USERNAME", "env-user")
|
|
monkeypatch.setenv("MQTT_PASSWORD", "env-password")
|
|
monkeypatch.setenv("MQTT_CLIENT_ID", "env-client")
|
|
monkeypatch.setenv("MQTT_USE_TLS", "true")
|
|
|
|
mqtt_config = get_mqtt_config(config=None)
|
|
|
|
assert mqtt_config.broker == "env-broker"
|
|
assert mqtt_config.port == 1999
|
|
assert mqtt_config.username == "env-user"
|
|
assert mqtt_config.password == "env-password"
|
|
assert mqtt_config.client_id == "env-client"
|
|
assert mqtt_config.use_tls is True
|