struct Rng(u64);
impl Rng {
fn new(seed: u64) -> Self {
Rng(seed | 1)
}
fn next_u64(&mut self) -> u64 {
let mut x = self.0;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
self.0 = x;
x.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
fn bytes(&mut self, len: usize) -> Vec<u8> {
(0..len).map(|_| (self.next_u64() & 0xFF) as u8).collect()
}
}
fn sweep(mut f: impl FnMut(&[u8])) {
for seed in 0..256u64 {
let mut rng = Rng::new(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15));
for len in [0usize, 1, 2, 3, 4, 7, 12, 16, 47, 188, 200, 512] {
f(&rng.bytes(len));
}
}
}
#[cfg(any(feature = "rtsp", feature = "webrtc"))]
#[test]
fn rtp_parsers_never_panic() {
use arcly_stream::protocol::rtp::{AacDepacketizer, H264Depacketizer, RtpHeader};
let aac = AacDepacketizer::new();
sweep(|b| {
let _ = RtpHeader::parse(b);
let _ = aac.push(b);
if b.len() >= 2 {
let _ = AacDepacketizer::with_lengths(b[0], b[1]).push(b);
}
});
let mut depack = H264Depacketizer::new();
let mut seq = 0u16;
sweep(|b| {
if !b.is_empty() {
let _ = depack.push(b, b[0] & 1 == 0, b.len() as u32, seq);
seq = seq.wrapping_add(1);
}
});
}
#[cfg(feature = "srt")]
#[test]
fn srt_parsers_never_panic() {
use arcly_stream::protocol::srt::{SrtHandshake, SrtPacket, TsDemuxer};
sweep(|b| {
let _ = SrtPacket::parse(b);
let _ = SrtHandshake::parse(b);
});
let mut demux = TsDemuxer::new();
sweep(|b| {
let _ = demux.push(b);
});
}
#[cfg(feature = "rtsp")]
#[test]
fn rtsp_parsers_never_panic() {
use arcly_stream::protocol::rtsp::{InterleavedFrame, RtspRequest, RtspResponse, Sdp};
sweep(|b| {
let _ = InterleavedFrame::parse(b);
let text = String::from_utf8_lossy(b);
let _ = RtspRequest::parse(&text);
let _ = RtspResponse::parse(&text, String::new());
let _ = Sdp::parse(&text);
});
}
#[cfg(feature = "codec-aac")]
#[test]
fn aac_adts_parser_never_panics() {
use arcly_stream::codec::parse_adts;
sweep(|b| {
let _ = parse_adts(b);
});
}