from ais_hub.parser.nmea_utils import ( classify_kind, compute_checksum, parse_sentence, split_lines, strip_eol, ) def test_checksum_roundtrip(): body = "AIVDM,1,1,,A,15M67FC000G?ufbE`FepT@3n00Sa,0" cs = compute_checksum(body) line = f"!{body}*{cs:02X}" s = parse_sentence(line) assert s is not None assert s.checksum_ok is True def test_parse_sentence_ais_ok(): body = "AIVDM,1,1,,A,15M67FC000G?ufbE`FepT@3n00Sa,0" line = f"!{body}*{compute_checksum(body):02X}" s = parse_sentence(line) assert s is not None assert s.start == "!" assert s.talker == "AIVDM" assert s.checksum_ok is True assert s.fields[0] == "1" assert s.fields[3] == "A" def test_parse_sentence_bad_checksum(): s = parse_sentence("!AIVDM,1,1,,A,15M67FC000G?ufbE`FepT@3n00Sa,0*00") assert s is not None assert s.checksum_ok is False def test_parse_sentence_empty_and_garbage(): assert parse_sentence("") is None assert parse_sentence(" ") is None assert parse_sentence("no-start-char") is None assert parse_sentence("!") is None def test_split_lines_mixed_eols(): chunk = b"!AIVDM,1,1,,A,x,0*2E\r\n$GPGGA,,,,,,0,,,,,,,,*56\n!BAD\r" lines = split_lines(chunk) assert len(lines) == 3 assert lines[0].startswith("!AIVDM") assert lines[1].startswith("$GPGGA") assert lines[2].startswith("!BAD") def test_strip_eol(): assert strip_eol("abc\r\n") == "abc" assert strip_eol("abc\n") == "abc" assert strip_eol("abc") == "abc" def test_classify_kind(): assert classify_kind("AIVDM", "!") == "ais" assert classify_kind("AIVDO", "!") == "ais" assert classify_kind("BSVDM", "!") == "ais" assert classify_kind("GPRMC", "$") == "gps" assert classify_kind("GNGGA", "$") == "gps" assert classify_kind("UNKNOWN", "$") == "other"