diff --git a/tests/plugins/host_agent/test_agent_build_payload.py b/tests/plugins/host_agent/test_agent_build_payload.py new file mode 100644 index 0000000..15c779e --- /dev/null +++ b/tests/plugins/host_agent/test_agent_build_payload.py @@ -0,0 +1,55 @@ +from unittest.mock import patch +from plugins.host_agent import agent as a + + +def test_build_sample_shape(): + fake_mem = {"total_bytes": 100, "used_bytes": 40, + "available_bytes": 60, "swap_used_bytes": 0} + fake_load = {"1m": 0.1, "5m": 0.2, "15m": 0.3} + fake_storage = [{"mount": "/", "total_bytes": 1000, "used_bytes": 400}] + + with patch.object(a, "collect_cpu", return_value=12.5), \ + patch.object(a, "collect_memory", return_value=fake_mem), \ + patch.object(a, "collect_load", return_value=fake_load), \ + patch.object(a, "collect_uptime", return_value=1234), \ + patch.object(a, "collect_storage", return_value=fake_storage): + sample = a.build_sample(mounts=["/"]) + + assert sample["cpu_pct"] == 12.5 + assert sample["mem"]["used_bytes"] == 40 + assert sample["load"]["1m"] == 0.1 + assert sample["uptime_secs"] == 1234 + assert sample["storage"][0]["mount"] == "/" + assert "ts" in sample + # ISO-8601 UTC string + assert "T" in sample["ts"] + + +def test_build_sample_tolerates_collector_failure(): + # If a collector raises, the sample should still be built with None for that field. + def _boom(): + raise RuntimeError("no /proc") + + with patch.object(a, "collect_cpu", side_effect=_boom), \ + patch.object(a, "collect_memory", return_value={"total_bytes": 1, "used_bytes": 0, + "available_bytes": 1, "swap_used_bytes": 0}), \ + patch.object(a, "collect_load", return_value={"1m": 0.0, "5m": 0.0, "15m": 0.0}), \ + patch.object(a, "collect_uptime", return_value=0), \ + patch.object(a, "collect_storage", return_value=[]): + sample = a.build_sample(mounts=["/"]) + assert sample["cpu_pct"] is None + assert sample["mem"]["total_bytes"] == 1 + + +def test_build_payload_wraps_samples(): + metadata = {"kernel": "6.8", "distro": "Ubuntu", "arch": "x86_64"} + payload = a.build_payload( + samples=[{"ts": "2026-04-14T00:00:00+00:00", "cpu_pct": 5.0}], + hostname="myhost", + metadata=metadata, + ) + assert payload["agent_version"] == a.AGENT_VERSION + assert payload["hostname"] == "myhost" + assert payload["metadata"] == metadata + assert len(payload["samples"]) == 1 + assert payload["samples"][0]["cpu_pct"] == 5.0 diff --git a/tests/plugins/host_agent/test_agent_ring_buffer.py b/tests/plugins/host_agent/test_agent_ring_buffer.py new file mode 100644 index 0000000..f0d7a46 --- /dev/null +++ b/tests/plugins/host_agent/test_agent_ring_buffer.py @@ -0,0 +1,24 @@ +from plugins.host_agent.agent import RingBuffer + + +def test_ring_buffer_preserves_order(): + rb = RingBuffer(maxlen=3) + rb.push(1); rb.push(2); rb.push(3) + assert list(rb.drain()) == [1, 2, 3] + assert len(rb) == 0 + + +def test_ring_buffer_drops_oldest_when_full(): + rb = RingBuffer(maxlen=3) + for v in (1, 2, 3, 4, 5): + rb.push(v) + assert list(rb.drain()) == [3, 4, 5] + + +def test_ring_buffer_drain_clears_and_is_atomic(): + rb = RingBuffer(maxlen=5) + rb.push("a"); rb.push("b") + out = list(rb.drain()) + rb.push("c") + assert out == ["a", "b"] + assert list(rb.drain()) == ["c"]