test: add CI, RingBuffer tests, core proptest, RAII lua fixtures
This commit is contained in:
96
crates/pipeview-core/tests/properties.rs
Normal file
96
crates/pipeview-core/tests/properties.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use proptest::prelude::*;
|
||||
|
||||
use pipeview_core::frame::Framer;
|
||||
use pipeview_core::frame::cobs::{CobsFramer, cobs_decode, cobs_encode};
|
||||
use pipeview_core::frame::length::{LengthConfig, LengthPrefixedFramer};
|
||||
use pipeview_core::protocol::Endian;
|
||||
use pipeview_core::protocol::ProtocolDecoder;
|
||||
use pipeview_core::protocol::hex::{HexConfig, HexDecoder};
|
||||
use pipeview_core::protocol::plot::{PlotConfig, PlotDecoder, SampleType};
|
||||
use pipeview_core::protocol::text::{TextDecoder, TextEncoding};
|
||||
|
||||
proptest! {
|
||||
#![proptest_config(ProptestConfig::with_cases(256))]
|
||||
|
||||
// ── COBS ─────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn cobs_roundtrip_any_payload(payload in prop::collection::vec(any::<u8>(), 0..512)) {
|
||||
let encoded = cobs_encode(&payload);
|
||||
let decoded = cobs_decode(&encoded).unwrap();
|
||||
prop_assert_eq!(&decoded, &payload);
|
||||
|
||||
let mut framer = CobsFramer::new(1024 * 1024);
|
||||
let mut wire = encoded;
|
||||
wire.push(0x00);
|
||||
let frames = framer.feed(&wire);
|
||||
prop_assert_eq!(frames.len(), 1);
|
||||
prop_assert_eq!(&frames[0], &payload);
|
||||
}
|
||||
|
||||
// ── Length-prefixed ──────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn length_roundtrip_any_payload(
|
||||
len_bytes in prop_oneof![Just(1usize), Just(2usize), Just(4usize)],
|
||||
little_endian in any::<bool>(),
|
||||
includes_self in any::<bool>(),
|
||||
payload in prop::collection::vec(any::<u8>(), 0..200)
|
||||
) {
|
||||
let endian = if little_endian { Endian::Little } else { Endian::Big };
|
||||
let raw_len = if includes_self {
|
||||
payload.len() + len_bytes
|
||||
} else {
|
||||
payload.len()
|
||||
};
|
||||
|
||||
let mut wire = Vec::with_capacity(len_bytes + payload.len());
|
||||
match (len_bytes, endian) {
|
||||
(1, _) => wire.push(raw_len as u8),
|
||||
(2, Endian::Big) => wire.extend_from_slice(&(raw_len as u16).to_be_bytes()),
|
||||
(2, Endian::Little) => wire.extend_from_slice(&(raw_len as u16).to_le_bytes()),
|
||||
(4, Endian::Big) => wire.extend_from_slice(&(raw_len as u32).to_be_bytes()),
|
||||
(4, Endian::Little) => wire.extend_from_slice(&(raw_len as u32).to_le_bytes()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
wire.extend_from_slice(&payload);
|
||||
|
||||
let config = LengthConfig {
|
||||
len_bytes,
|
||||
endian,
|
||||
length_includes_self: includes_self,
|
||||
max_payload: 1024 * 1024,
|
||||
};
|
||||
let mut framer = LengthPrefixedFramer::new(config);
|
||||
let frames = framer.feed(&wire);
|
||||
prop_assert_eq!(frames.len(), 1);
|
||||
prop_assert_eq!(&frames[0], &payload);
|
||||
}
|
||||
|
||||
// ── Protocol decoders never panic on arbitrary bytes ─────────────
|
||||
|
||||
#[test]
|
||||
fn plot_decode_arbitrary_bytes_never_panics(bytes in prop::collection::vec(any::<u8>(), 0..256)) {
|
||||
let decoder = PlotDecoder::new(PlotConfig {
|
||||
sample_type: SampleType::F32,
|
||||
endian: Endian::Little,
|
||||
channels: 2,
|
||||
format: pipeview_core::protocol::plot::PlotFormat::Interleaved,
|
||||
});
|
||||
let _ = decoder.decode(&bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_decode_arbitrary_bytes_never_panics(bytes in prop::collection::vec(any::<u8>(), 0..256)) {
|
||||
let decoder = HexDecoder::new(HexConfig::default());
|
||||
let decoded = decoder.decode(&bytes);
|
||||
prop_assert!(decoded.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn latin1_decode_arbitrary_bytes_never_panics(bytes in prop::collection::vec(any::<u8>(), 0..256)) {
|
||||
let decoder = TextDecoder::new(TextEncoding::Latin1);
|
||||
let decoded = decoder.decode(&bytes);
|
||||
prop_assert!(decoded.is_some());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user