@simbimbo/brainstem 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ from brainstem.adapters import (
2
+ RawInputAdapter,
3
+ SyslogRawInputAdapter,
4
+ build_raw_input_envelope,
5
+ get_raw_input_adapter,
6
+ list_raw_input_source_types,
7
+ register_raw_input_adapter,
8
+ )
9
+ import pytest
10
+ from brainstem.ingest import parse_file_line
11
+ from brainstem.ingest import parse_syslog_envelope
12
+ from brainstem.models import RawInputEnvelope
13
+
14
+
15
+ def test_syslog_adapter_registry_is_populated() -> None:
16
+ sources = list_raw_input_source_types()
17
+ assert "syslog" in sources
18
+ assert "file" in sources
19
+ assert isinstance(get_raw_input_adapter("syslog"), RawInputAdapter)
20
+
21
+
22
+ def test_file_adapter_builds_raw_envelope() -> None:
23
+ raw_line = "vpn tunnel dropped and recovered"
24
+ raw = build_raw_input_envelope(
25
+ "file",
26
+ raw_line,
27
+ tenant_id="client-a",
28
+ source_path="/tmp/sample.log",
29
+ )
30
+ assert isinstance(raw, RawInputEnvelope)
31
+ assert raw.source_type == "file"
32
+ assert raw.message_raw == raw_line
33
+ assert raw.metadata["raw_line"] == raw_line
34
+ assert raw.source_path == "/tmp/sample.log"
35
+
36
+
37
+ def test_syslog_adapter_builds_raw_envelope() -> None:
38
+ raw_line = "Mar 22 00:00:01 fw-01 charon: VPN tunnel dropped and recovered"
39
+ raw = build_raw_input_envelope(
40
+ "syslog",
41
+ raw_line,
42
+ tenant_id="client-a",
43
+ source_path="/var/log/syslog",
44
+ )
45
+ assert isinstance(raw, RawInputEnvelope)
46
+ assert raw.source_type == "syslog"
47
+ assert raw.host == "fw-01"
48
+ assert raw.service == "charon"
49
+ assert raw.message_raw == "VPN tunnel dropped and recovered"
50
+ assert raw.metadata["raw_line"] == raw_line
51
+ assert raw.source_path == "/var/log/syslog"
52
+
53
+
54
+ def test_file_adapter_parse_path() -> None:
55
+ raw = parse_file_line("first line", tenant_id="client-a", source_path="/tmp/file.log")
56
+ assert raw.message_raw == "first line"
57
+ assert raw.source_type == "file"
58
+ assert raw.metadata["raw_line"] == "first line"
59
+
60
+
61
+ def test_syslog_dispatch_is_used_by_ingest_parse_path() -> None:
62
+ class StubAdapter:
63
+ source_type = "syslog"
64
+ calls = 0
65
+
66
+ def parse_raw_input(self, payload, *, tenant_id: str, source_path: str = "") -> RawInputEnvelope:
67
+ StubAdapter.calls += 1
68
+ return RawInputEnvelope(
69
+ tenant_id=tenant_id,
70
+ source_type="syslog",
71
+ timestamp="2026-03-22T00:00:00Z",
72
+ message_raw="stub-message",
73
+ host="host",
74
+ service="service",
75
+ source_path=source_path,
76
+ )
77
+
78
+ original = get_raw_input_adapter("syslog")
79
+ try:
80
+ register_raw_input_adapter(StubAdapter())
81
+ raw = parse_syslog_envelope("ignored-line", tenant_id="client-a", source_path="/tmp/test.log")
82
+ assert raw.message_raw == "stub-message"
83
+ assert StubAdapter.calls == 1
84
+ finally:
85
+ if original is not None:
86
+ register_raw_input_adapter(original)
87
+ else:
88
+ # defensive: restore default adapter if registration state changed unexpectedly
89
+ register_raw_input_adapter(SyslogRawInputAdapter())
90
+
91
+
92
+ def test_unknown_source_type_raises_clear_error() -> None:
93
+ with pytest.raises(ValueError, match="unsupported source_type"):
94
+ build_raw_input_envelope("not-a-source", "payload", tenant_id="client-a")