Nothing to see here, move along meow
1use lancer_core::packet_ring::{PacketRingReader, PacketRingWriter};
2use proptest::prelude::*;
3
4const RING_SIZE: usize = 32768;
5const SLOT_SIZE: u32 = 2048;
6
7fn make_ring() -> Vec<u8> {
8 vec![0u8; RING_SIZE]
9}
10
11#[test]
12fn push_pop_single_packet() {
13 let mut ring = make_ring();
14 let base = ring.as_mut_ptr();
15 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
16 let reader = unsafe { PacketRingReader::attach(base, RING_SIZE) };
17
18 let data = b"hello world";
19 assert!(writer.try_push(data));
20
21 let mut buf = [0u8; 2048];
22 let len = reader.try_pop(&mut buf).expect("should pop");
23 assert_eq!(len, data.len());
24 assert_eq!(&buf[..len], data);
25}
26
27#[test]
28fn empty_ring_returns_none() {
29 let mut ring = make_ring();
30 let base = ring.as_mut_ptr();
31 let _writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
32 let reader = unsafe { PacketRingReader::attach(base, RING_SIZE) };
33
34 let mut buf = [0u8; 2048];
35 assert!(reader.try_pop(&mut buf).is_none());
36}
37
38#[test]
39fn full_ring_returns_false() {
40 let mut ring = make_ring();
41 let base = ring.as_mut_ptr();
42 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
43
44 let slot_count = (RING_SIZE as u32 - 64) / SLOT_SIZE;
45 let capacity = slot_count - 1;
46
47 let data = [0xAA; 100];
48 let pushed = (0..capacity + 10)
49 .take_while(|_| writer.try_push(&data))
50 .count();
51 assert_eq!(pushed, capacity as usize);
52}
53
54#[test]
55fn wraparound_preserves_data() {
56 let mut ring = make_ring();
57 let base = ring.as_mut_ptr();
58 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
59 let reader = unsafe { PacketRingReader::attach(base, RING_SIZE) };
60
61 let slot_count = (RING_SIZE as u32 - 64) / SLOT_SIZE;
62 let capacity = slot_count - 1;
63
64 (0..capacity * 3).for_each(|i| {
65 let val = (i % 256) as u8;
66 let data = [val; 64];
67 assert!(writer.try_push(&data), "push failed at iteration {i}");
68
69 let mut buf = [0u8; 2048];
70 let len = reader.try_pop(&mut buf).expect("pop failed");
71 assert_eq!(len, 64);
72 assert!(buf[..64].iter().all(|&b| b == val));
73 });
74}
75
76proptest! {
77 #[test]
78 fn push_n_pop_n_integrity(
79 packets in prop::collection::vec(
80 prop::collection::vec(1u8..=255, 1..=1024),
81 1..=14
82 )
83 ) {
84 let mut ring = make_ring();
85 let base = ring.as_mut_ptr();
86 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
87 let reader = unsafe { PacketRingReader::attach(base, RING_SIZE) };
88
89 packets.iter().for_each(|pkt| {
90 assert!(writer.try_push(pkt));
91 });
92
93 packets.iter().for_each(|expected| {
94 let mut buf = [0u8; 2048];
95 let len = reader.try_pop(&mut buf).expect("should pop");
96 assert_eq!(len, expected.len());
97 assert_eq!(&buf[..len], expected.as_slice());
98 });
99
100 let mut buf = [0u8; 2048];
101 assert!(reader.try_pop(&mut buf).is_none());
102 }
103
104 #[test]
105 fn interleaved_push_pop(
106 packets in prop::collection::vec(
107 prop::collection::vec(1u8..=255, 1..=512),
108 1..=50
109 )
110 ) {
111 let mut ring = make_ring();
112 let base = ring.as_mut_ptr();
113 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
114 let reader = unsafe { PacketRingReader::attach(base, RING_SIZE) };
115
116 packets.iter().for_each(|pkt| {
117 assert!(writer.try_push(pkt));
118 let mut buf = [0u8; 2048];
119 let len = reader.try_pop(&mut buf).expect("should pop");
120 assert_eq!(len, pkt.len());
121 assert_eq!(&buf[..len], pkt.as_slice());
122 });
123 }
124}
125
126#[test]
127fn reject_empty_data() {
128 let mut ring = make_ring();
129 let base = ring.as_mut_ptr();
130 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
131 assert!(!writer.try_push(&[]));
132}
133
134#[test]
135fn reject_oversized_data() {
136 let mut ring = make_ring();
137 let base = ring.as_mut_ptr();
138 let writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
139 let big = [0u8; 2047];
140 assert!(!writer.try_push(&big));
141}
142
143#[test]
144fn attach_with_tiny_length_disables_ring() {
145 let mut ring = make_ring();
146 let base = ring.as_mut_ptr();
147 let _writer = unsafe { PacketRingWriter::init(base, RING_SIZE, SLOT_SIZE) };
148 let reader = unsafe { PacketRingReader::attach(base, 32) };
149
150 let mut buf = [0u8; 2048];
151 assert!(reader.try_pop(&mut buf).is_none());
152}
153
154#[test]
155fn attach_with_zero_slot_count_disables_ring() {
156 let mut buf_data = vec![0u8; 256];
157 let base = buf_data.as_mut_ptr();
158 unsafe {
159 core::ptr::write_volatile(base.add(8) as *mut u32, 0);
160 core::ptr::write_volatile(base.add(12) as *mut u32, 64);
161 }
162 let reader = unsafe { PacketRingReader::attach(base, 256) };
163
164 let mut buf = [0u8; 256];
165 assert!(reader.try_pop(&mut buf).is_none());
166}
167
168#[test]
169fn attach_with_bad_slot_size_disables_ring() {
170 let mut buf_data = vec![0u8; 256];
171 let base = buf_data.as_mut_ptr();
172 unsafe {
173 core::ptr::write_volatile(base.add(8) as *mut u32, 4);
174 core::ptr::write_volatile(base.add(12) as *mut u32, 1);
175 }
176 let reader = unsafe { PacketRingReader::attach(base, 256) };
177
178 let mut buf = [0u8; 256];
179 assert!(reader.try_pop(&mut buf).is_none());
180}
181
182#[test]
183fn attach_rejects_length_overflow() {
184 let mut ring = vec![0u8; 4096];
185 let base = ring.as_mut_ptr();
186 let _writer = unsafe { PacketRingWriter::init(base, 4096, 128) };
187 let reader = unsafe { PacketRingReader::attach(base, 100) };
188
189 let mut buf = [0u8; 256];
190 assert!(reader.try_pop(&mut buf).is_none());
191}