libaprs-engine 0.1.4

Protocol-first APRS engine core primitives
Documentation
use libaprs_engine::{parse_packet, AprsData};

#[test]
fn valid_fixture_corpus_parses_without_losing_raw_bytes() {
    for (index, line) in include_str!("fixtures/valid.aprs").lines().enumerate() {
        let packet = line.as_bytes();
        let parsed = parse_packet(packet).unwrap_or_else(|err| {
            panic!("valid fixture line {} failed: {err:?}", index + 1);
        });

        assert_eq!(parsed.raw().as_bytes(), packet);
        assert!(!matches!(parsed.aprs_data(), AprsData::Malformed { .. }));
    }
}

#[test]
fn malformed_fixture_corpus_fails_closed_at_codec_boundary() {
    for (index, line) in include_str!("fixtures/malformed.aprs").lines().enumerate() {
        let packet = line.as_bytes();
        assert!(
            parse_packet(packet).is_err(),
            "malformed fixture line {} unexpectedly parsed",
            index + 1
        );
    }
}

#[test]
fn byte_fuzz_inputs_never_panic_and_preserve_successful_raw_bytes() {
    let mut state = 0x5eed_u32;
    for len in 0..=128 {
        for _ in 0..32 {
            let mut input = Vec::with_capacity(len);
            for _ in 0..len {
                state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
                input.push((state >> 24) as u8);
            }

            if let Ok(parsed) = parse_packet(&input) {
                assert_eq!(parsed.raw().as_bytes(), input.as_slice());
            }
        }
    }
}

#[test]
fn structured_fuzz_preserves_payload_and_never_panics() {
    let payloads: [&[u8]; 8] = [
        b">status",
        b"!4903.50N/07201.75W-ok",
        b"T#001,111,222,033,044,055,10101010",
        b"\xff\xfe\xfd",
        b"",
        b"~opaque",
        b"$GPGGA,1",
        b"}SRC>APRS:>nested",
    ];

    for payload in payloads {
        let mut packet = b"N0CALL>APRS:".to_vec();
        packet.extend_from_slice(payload);
        let parsed = parse_packet(&packet);
        if payload.is_empty() {
            assert!(parsed.is_err());
        } else {
            let parsed = parsed.expect("structured packet should parse");
            assert_eq!(parsed.payload(), payload);
        }
    }
}