"""Unit tests for _expand_sample_to_metrics — sample dict → PluginMetric rows. No DB: PluginMetric objects are constructed in-memory, so we assert the (metric_name, resource_name) → value contract directly. """ from datetime import datetime, timezone from plugins.host_agent.routes import _expand_sample_to_metrics def _index(rows): return {(r.metric_name, r.resource_name): r.value for r in rows} def test_expand_emits_all_new_metric_families(): sample = { "ts": "2026-06-16T00:00:00+00:00", "cpu_pct": 12.5, "cpu_cores": [10.0, 15.0], "mem": {"total_bytes": 100, "available_bytes": 40, "swap_used_bytes": 5, "cached_bytes": 20, "buffers_bytes": 3}, "load": {"1m": 0.1, "5m": 0.2, "15m": 0.3}, "uptime_secs": 1000, "storage": [{"mount": "/", "total_bytes": 100, "used_bytes": 50}], "net": [{"iface": "eth0", "rx_bps": 1000.0, "tx_bps": 500.0}], "diskio": [{"device": "sda", "read_bps": 2000.0, "write_bps": 1000.0}], "temps": [{"label": "Package", "celsius": 45.0}, {"label": "Core0", "celsius": 50.0}], "psi": {"mem_some_avg10": 1.5, "cpu_some_avg10": 0.0}, } idx = _index(_expand_sample_to_metrics(sample, "alpha", datetime.now(timezone.utc))) # per-core CPU as sub-resources assert idx[("cpu_pct", "alpha:core0")] == 10.0 assert idx[("cpu_pct", "alpha:core1")] == 15.0 # richer memory assert idx[("mem_cached_bytes", "alpha")] == 20 assert idx[("mem_buffers_bytes", "alpha")] == 3 # network: per-iface + host total assert idx[("net_rx_bps", "alpha:net:eth0")] == 1000.0 assert idx[("net_rx_bps", "alpha")] == 1000.0 # disk I/O: per-device + host total assert idx[("disk_read_bps", "alpha:diskio:sda")] == 2000.0 assert idx[("disk_write_bps", "alpha")] == 1000.0 # temps: per-sensor + host max assert idx[("temp_c", "alpha:temp:Package")] == 45.0 assert idx[("temp_c_max", "alpha")] == 50.0 # PSI assert idx[("psi_mem_some_avg10", "alpha")] == 1.5 def test_expand_is_backcompat_with_old_agent_sample(): """An old agent (no new keys) must still expand cleanly to legacy metrics.""" sample = {"ts": "x", "cpu_pct": 5.0, "mem": {"total_bytes": 10, "available_bytes": 5}} rows = _expand_sample_to_metrics(sample, "h", datetime.now(timezone.utc)) names = {r.metric_name for r in rows} assert "cpu_pct" in names assert not any( n.startswith(("net_", "disk_read", "disk_write", "psi_", "temp_", "mem_cached")) for n in names )