"""Syslog messages read into their parts (#5999): RFC 5424, RFC 3164 with and without a hostname, a message with no PRI, and TCP framing (RFC 6587).""" from datetime import datetime, timezone from plugins.syslog.parse import MAX_MESSAGE, facility_name, frames, parse, severity_name def test_rfc5424_with_structured_data_and_a_zone(): m = parse(b'<165>1 2026-10-19T01:12:03.5+00:00 synnas kernel 1234 ID47 ' b'[exampleSDID@32473 iut="3" eventSource="App\\"lication"] nfsd: server not responding') assert (facility_name(m.facility), severity_name(m.severity)) == ("local4", "notice") assert m.sent_at == datetime(2026, 10, 19, 1, 12, 3, 500000, tzinfo=timezone.utc) assert (m.hostname, m.app, m.text) == ("synnas", "kernel", "nfsd: server not responding") def test_rfc5424_nil_fields_and_no_zone_keep_no_sent_time(): m = parse("<14>1 2026-10-19T01:12:03 - - - - - plain text") assert m.sent_at is None and (m.hostname, m.app, m.text) == ("", "", "plain text") def test_bsd_with_hostname_and_tag(): m = parse(b"<38>Oct 9 22:14:15 adm-nas sshd[4121]: Accepted publickey for admin") assert (m.facility, m.severity) == (4, 6) assert m.sent_at is None # no year, no zone: never trusted assert (m.hostname, m.app, m.text) == ("adm-nas", "sshd", "Accepted publickey for admin") def test_bsd_without_hostname_reads_the_tag(): m = parse("<30>Oct 19 01:12:03 rsyncd[881]: connect from 192.168.0.4") assert (m.hostname, m.app, m.text) == ("", "rsyncd", "connect from 192.168.0.4") def test_no_pri_is_user_notice_and_an_unknown_shape_is_kept_whole(): m = parse(b"something the device made up\n") assert (m.facility, m.severity) == (1, 5) assert m.text == "something the device made up" assert parse(b"<999>not a pri").text == "<999>not a pri" def test_a_long_message_is_cut_and_bad_bytes_kept_readable(): m = parse(b"<13>" + b"x" * (MAX_MESSAGE + 50)) assert len(m.text) == MAX_MESSAGE assert "�" in parse(b"<13>caf\xe9").text def test_frames_octet_counted_and_newline_ended_with_a_partial_left(): buf = bytearray(b"11 <13>hello 1<14>second line\n<15>third") assert frames(buf) == [b"<13>hello 1", b"<14>second line"] assert buf == bytearray(b"<15>third") buf += b" part\n" assert frames(buf) == [b"<15>third part"] and not buf def test_frames_waits_for_the_rest_of_a_counted_message(): buf = bytearray(b"20 <13>only part") assert frames(buf) == [] and buf == bytearray(b"20 <13>only part") def test_a_count_too_large_is_read_as_text(): buf = bytearray(b"9999999 is not a count\n") assert frames(buf) == [b"9999999 is not a count"]