1ffe74184SMartin Algesten use crate::error::{Error, Result};
2ffe74184SMartin Algesten
3ffe74184SMartin Algesten use bytes::{Bytes, BytesMut};
4ffe74184SMartin Algesten
5ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
6ffe74184SMartin Algesten //payload_queue_test
7ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
8ffe74184SMartin Algesten use super::payload_queue::*;
9ffe74184SMartin Algesten use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier};
10ffe74184SMartin Algesten use crate::chunk::chunk_selective_ack::GapAckBlock;
11ffe74184SMartin Algesten
make_payload(tsn: u32, n_bytes: usize) -> ChunkPayloadData12ffe74184SMartin Algesten fn make_payload(tsn: u32, n_bytes: usize) -> ChunkPayloadData {
13ffe74184SMartin Algesten ChunkPayloadData {
14ffe74184SMartin Algesten tsn,
15ffe74184SMartin Algesten user_data: {
16ffe74184SMartin Algesten let mut b = BytesMut::new();
17ffe74184SMartin Algesten b.resize(n_bytes, 0);
18ffe74184SMartin Algesten b.freeze()
19ffe74184SMartin Algesten },
20ffe74184SMartin Algesten ..Default::default()
21ffe74184SMartin Algesten }
22ffe74184SMartin Algesten }
23ffe74184SMartin Algesten
24ffe74184SMartin Algesten #[test]
test_payload_queue_push_no_check() -> Result<()>25ffe74184SMartin Algesten fn test_payload_queue_push_no_check() -> Result<()> {
26ffe74184SMartin Algesten let mut pq = PayloadQueue::new(Arc::new(AtomicUsize::new(0)));
27ffe74184SMartin Algesten
28ffe74184SMartin Algesten pq.push_no_check(make_payload(0, 10));
2983f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 10, "total bytes mismatch");
3083f2d1bbSVincent Esche assert_eq!(pq.len(), 1, "item count mismatch");
31ffe74184SMartin Algesten pq.push_no_check(make_payload(1, 11));
3283f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 21, "total bytes mismatch");
3383f2d1bbSVincent Esche assert_eq!(pq.len(), 2, "item count mismatch");
34ffe74184SMartin Algesten pq.push_no_check(make_payload(2, 12));
3583f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 33, "total bytes mismatch");
3683f2d1bbSVincent Esche assert_eq!(pq.len(), 3, "item count mismatch");
37ffe74184SMartin Algesten
38ffe74184SMartin Algesten for i in 0..3 {
39ffe74184SMartin Algesten assert!(!pq.sorted.is_empty(), "should not be empty");
40ffe74184SMartin Algesten let c = pq.pop(i);
41ffe74184SMartin Algesten assert!(c.is_some(), "pop should succeed");
42ffe74184SMartin Algesten if let Some(c) = c {
4383f2d1bbSVincent Esche assert_eq!(c.tsn, i, "TSN should match");
44ffe74184SMartin Algesten }
45ffe74184SMartin Algesten }
46ffe74184SMartin Algesten
4783f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 0, "total bytes mismatch");
4883f2d1bbSVincent Esche assert_eq!(pq.len(), 0, "item count mismatch");
49ffe74184SMartin Algesten
50ffe74184SMartin Algesten assert!(pq.sorted.is_empty(), "should be empty");
51ffe74184SMartin Algesten pq.push_no_check(make_payload(3, 13));
5283f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 13, "total bytes mismatch");
53ffe74184SMartin Algesten pq.push_no_check(make_payload(4, 14));
5483f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 27, "total bytes mismatch");
55ffe74184SMartin Algesten
56ffe74184SMartin Algesten for i in 3..5 {
57ffe74184SMartin Algesten assert!(!pq.sorted.is_empty(), "should not be empty");
58ffe74184SMartin Algesten let c = pq.pop(i);
59ffe74184SMartin Algesten assert!(c.is_some(), "pop should succeed");
60ffe74184SMartin Algesten if let Some(c) = c {
6183f2d1bbSVincent Esche assert_eq!(c.tsn, i, "TSN should match");
62ffe74184SMartin Algesten }
63ffe74184SMartin Algesten }
64ffe74184SMartin Algesten
6583f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 0, "total bytes mismatch");
6683f2d1bbSVincent Esche assert_eq!(pq.len(), 0, "item count mismatch");
67ffe74184SMartin Algesten
68ffe74184SMartin Algesten Ok(())
69ffe74184SMartin Algesten }
70ffe74184SMartin Algesten
71ffe74184SMartin Algesten #[test]
test_payload_queue_get_gap_ack_block() -> Result<()>72ffe74184SMartin Algesten fn test_payload_queue_get_gap_ack_block() -> Result<()> {
73ffe74184SMartin Algesten let mut pq = PayloadQueue::new(Arc::new(AtomicUsize::new(0)));
74ffe74184SMartin Algesten
75ffe74184SMartin Algesten pq.push(make_payload(1, 0), 0);
76ffe74184SMartin Algesten pq.push(make_payload(2, 0), 0);
77ffe74184SMartin Algesten pq.push(make_payload(3, 0), 0);
78ffe74184SMartin Algesten pq.push(make_payload(4, 0), 0);
79ffe74184SMartin Algesten pq.push(make_payload(5, 0), 0);
80ffe74184SMartin Algesten pq.push(make_payload(6, 0), 0);
81ffe74184SMartin Algesten
82ffe74184SMartin Algesten let gab1 = vec![GapAckBlock { start: 1, end: 6 }];
83ffe74184SMartin Algesten let gab2 = pq.get_gap_ack_blocks(0);
84ffe74184SMartin Algesten assert!(!gab2.is_empty());
85ffe74184SMartin Algesten assert_eq!(gab2.len(), 1);
86ffe74184SMartin Algesten
8783f2d1bbSVincent Esche assert_eq!(gab2[0].start, gab1[0].start);
8883f2d1bbSVincent Esche assert_eq!(gab2[0].end, gab1[0].end);
89ffe74184SMartin Algesten
90ffe74184SMartin Algesten pq.push(make_payload(8, 0), 0);
91ffe74184SMartin Algesten pq.push(make_payload(9, 0), 0);
92ffe74184SMartin Algesten
93ffe74184SMartin Algesten let gab1 = vec![
94ffe74184SMartin Algesten GapAckBlock { start: 1, end: 6 },
95ffe74184SMartin Algesten GapAckBlock { start: 8, end: 9 },
96ffe74184SMartin Algesten ];
97ffe74184SMartin Algesten let gab2 = pq.get_gap_ack_blocks(0);
98ffe74184SMartin Algesten assert!(!gab2.is_empty());
99ffe74184SMartin Algesten assert_eq!(gab2.len(), 2);
100ffe74184SMartin Algesten
10183f2d1bbSVincent Esche assert_eq!(gab2[0].start, gab1[0].start);
10283f2d1bbSVincent Esche assert_eq!(gab2[0].end, gab1[0].end);
10383f2d1bbSVincent Esche assert_eq!(gab2[1].start, gab1[1].start);
10483f2d1bbSVincent Esche assert_eq!(gab2[1].end, gab1[1].end);
105ffe74184SMartin Algesten
106ffe74184SMartin Algesten Ok(())
107ffe74184SMartin Algesten }
108ffe74184SMartin Algesten
109ffe74184SMartin Algesten #[test]
test_payload_queue_get_last_tsn_received() -> Result<()>110ffe74184SMartin Algesten fn test_payload_queue_get_last_tsn_received() -> Result<()> {
111ffe74184SMartin Algesten let mut pq = PayloadQueue::new(Arc::new(AtomicUsize::new(0)));
112ffe74184SMartin Algesten
113ffe74184SMartin Algesten // empty queie should return false
114ffe74184SMartin Algesten let ok = pq.get_last_tsn_received();
115ffe74184SMartin Algesten assert!(ok.is_none(), "should be none");
116ffe74184SMartin Algesten
117ffe74184SMartin Algesten let ok = pq.push(make_payload(20, 0), 0);
118ffe74184SMartin Algesten assert!(ok, "should be true");
119ffe74184SMartin Algesten let tsn = pq.get_last_tsn_received();
120ffe74184SMartin Algesten assert!(tsn.is_some(), "should be false");
12183f2d1bbSVincent Esche assert_eq!(tsn, Some(&20), "should match");
122ffe74184SMartin Algesten
123ffe74184SMartin Algesten // append should work
124ffe74184SMartin Algesten let ok = pq.push(make_payload(21, 0), 0);
125ffe74184SMartin Algesten assert!(ok, "should be true");
126ffe74184SMartin Algesten let tsn = pq.get_last_tsn_received();
127ffe74184SMartin Algesten assert!(tsn.is_some(), "should be false");
12883f2d1bbSVincent Esche assert_eq!(tsn, Some(&21), "should match");
129ffe74184SMartin Algesten
130ffe74184SMartin Algesten // check if sorting applied
131ffe74184SMartin Algesten let ok = pq.push(make_payload(19, 0), 0);
132ffe74184SMartin Algesten assert!(ok, "should be true");
133ffe74184SMartin Algesten let tsn = pq.get_last_tsn_received();
134ffe74184SMartin Algesten assert!(tsn.is_some(), "should be false");
13583f2d1bbSVincent Esche assert_eq!(tsn, Some(&21), "should match");
136ffe74184SMartin Algesten
137ffe74184SMartin Algesten Ok(())
138ffe74184SMartin Algesten }
139ffe74184SMartin Algesten
140ffe74184SMartin Algesten #[test]
test_payload_queue_mark_all_to_retrasmit() -> Result<()>141ffe74184SMartin Algesten fn test_payload_queue_mark_all_to_retrasmit() -> Result<()> {
142ffe74184SMartin Algesten let mut pq = PayloadQueue::new(Arc::new(AtomicUsize::new(0)));
143ffe74184SMartin Algesten
144ffe74184SMartin Algesten for i in 0..3 {
145ffe74184SMartin Algesten pq.push(make_payload(i + 1, 10), 0);
146ffe74184SMartin Algesten }
147ffe74184SMartin Algesten pq.mark_as_acked(2);
148ffe74184SMartin Algesten pq.mark_all_to_retrasmit();
149ffe74184SMartin Algesten
150ffe74184SMartin Algesten let c = pq.get(1);
151ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
152ffe74184SMartin Algesten assert!(c.unwrap().retransmit, "should be marked as retransmit");
153ffe74184SMartin Algesten let c = pq.get(2);
154ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
155ffe74184SMartin Algesten assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
156ffe74184SMartin Algesten let c = pq.get(3);
157ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
158ffe74184SMartin Algesten assert!(c.unwrap().retransmit, "should be marked as retransmit");
159ffe74184SMartin Algesten
160ffe74184SMartin Algesten Ok(())
161ffe74184SMartin Algesten }
162ffe74184SMartin Algesten
163ffe74184SMartin Algesten #[test]
test_payload_queue_reset_retransmit_flag_on_ack() -> Result<()>164ffe74184SMartin Algesten fn test_payload_queue_reset_retransmit_flag_on_ack() -> Result<()> {
165ffe74184SMartin Algesten let mut pq = PayloadQueue::new(Arc::new(AtomicUsize::new(0)));
166ffe74184SMartin Algesten
167ffe74184SMartin Algesten for i in 0..4 {
168ffe74184SMartin Algesten pq.push(make_payload(i + 1, 10), 0);
169ffe74184SMartin Algesten }
170ffe74184SMartin Algesten
171ffe74184SMartin Algesten pq.mark_all_to_retrasmit();
172ffe74184SMartin Algesten pq.mark_as_acked(2); // should cancel retransmission for TSN 2
173ffe74184SMartin Algesten pq.mark_as_acked(4); // should cancel retransmission for TSN 4
174ffe74184SMartin Algesten
175ffe74184SMartin Algesten let c = pq.get(1);
176ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
177ffe74184SMartin Algesten assert!(c.unwrap().retransmit, "should be marked as retransmit");
178ffe74184SMartin Algesten let c = pq.get(2);
179ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
180ffe74184SMartin Algesten assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
181ffe74184SMartin Algesten let c = pq.get(3);
182ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
183ffe74184SMartin Algesten assert!(c.unwrap().retransmit, "should be marked as retransmit");
184ffe74184SMartin Algesten let c = pq.get(4);
185ffe74184SMartin Algesten assert!(c.is_some(), "should be true");
186ffe74184SMartin Algesten assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
187ffe74184SMartin Algesten
188ffe74184SMartin Algesten Ok(())
189ffe74184SMartin Algesten }
190ffe74184SMartin Algesten
191ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
192ffe74184SMartin Algesten //pending_queue_test
193ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
194ffe74184SMartin Algesten use super::pending_queue::*;
195ffe74184SMartin Algesten
196ffe74184SMartin Algesten const NO_FRAGMENT: usize = 0;
197ffe74184SMartin Algesten const FRAG_BEGIN: usize = 1;
198ffe74184SMartin Algesten const FRAG_MIDDLE: usize = 2;
199ffe74184SMartin Algesten const FRAG_END: usize = 3;
200ffe74184SMartin Algesten
make_data_chunk(tsn: u32, unordered: bool, frag: usize) -> ChunkPayloadData201ffe74184SMartin Algesten fn make_data_chunk(tsn: u32, unordered: bool, frag: usize) -> ChunkPayloadData {
202ffe74184SMartin Algesten let mut b = false;
203ffe74184SMartin Algesten let mut e = false;
204ffe74184SMartin Algesten
205ffe74184SMartin Algesten match frag {
206ffe74184SMartin Algesten NO_FRAGMENT => {
207ffe74184SMartin Algesten b = true;
208ffe74184SMartin Algesten e = true;
209ffe74184SMartin Algesten }
210ffe74184SMartin Algesten FRAG_BEGIN => {
211ffe74184SMartin Algesten b = true;
212ffe74184SMartin Algesten }
213ffe74184SMartin Algesten FRAG_END => e = true,
214ffe74184SMartin Algesten _ => {}
215ffe74184SMartin Algesten };
216ffe74184SMartin Algesten
217ffe74184SMartin Algesten ChunkPayloadData {
218ffe74184SMartin Algesten tsn,
219ffe74184SMartin Algesten unordered,
220ffe74184SMartin Algesten beginning_fragment: b,
221ffe74184SMartin Algesten ending_fragment: e,
222ffe74184SMartin Algesten user_data: {
223ffe74184SMartin Algesten let mut b = BytesMut::new();
224ffe74184SMartin Algesten b.resize(10, 0); // always 10 bytes
225ffe74184SMartin Algesten b.freeze()
226ffe74184SMartin Algesten },
227ffe74184SMartin Algesten ..Default::default()
228ffe74184SMartin Algesten }
229ffe74184SMartin Algesten }
230ffe74184SMartin Algesten
231ffe74184SMartin Algesten #[test]
test_pending_base_queue_push_and_pop() -> Result<()>232ffe74184SMartin Algesten fn test_pending_base_queue_push_and_pop() -> Result<()> {
233ffe74184SMartin Algesten let mut pq = PendingBaseQueue::new();
234ffe74184SMartin Algesten pq.push_back(make_data_chunk(0, false, NO_FRAGMENT));
235ffe74184SMartin Algesten pq.push_back(make_data_chunk(1, false, NO_FRAGMENT));
236ffe74184SMartin Algesten pq.push_back(make_data_chunk(2, false, NO_FRAGMENT));
237ffe74184SMartin Algesten
238ffe74184SMartin Algesten for i in 0..3 {
239ffe74184SMartin Algesten let c = pq.get(i);
240ffe74184SMartin Algesten assert!(c.is_some(), "should not be none");
24183f2d1bbSVincent Esche assert_eq!(c.unwrap().tsn, i as u32, "TSN should match");
242ffe74184SMartin Algesten }
243ffe74184SMartin Algesten
244ffe74184SMartin Algesten for i in 0..3 {
245ffe74184SMartin Algesten let c = pq.pop_front();
246ffe74184SMartin Algesten assert!(c.is_some(), "should not be none");
24783f2d1bbSVincent Esche assert_eq!(c.unwrap().tsn, i, "TSN should match");
248ffe74184SMartin Algesten }
249ffe74184SMartin Algesten
250ffe74184SMartin Algesten pq.push_back(make_data_chunk(3, false, NO_FRAGMENT));
251ffe74184SMartin Algesten pq.push_back(make_data_chunk(4, false, NO_FRAGMENT));
252ffe74184SMartin Algesten
253ffe74184SMartin Algesten for i in 3..5 {
254ffe74184SMartin Algesten let c = pq.pop_front();
255ffe74184SMartin Algesten assert!(c.is_some(), "should not be none");
25683f2d1bbSVincent Esche assert_eq!(c.unwrap().tsn, i, "TSN should match");
257ffe74184SMartin Algesten }
258ffe74184SMartin Algesten Ok(())
259ffe74184SMartin Algesten }
260ffe74184SMartin Algesten
261ffe74184SMartin Algesten #[test]
test_pending_base_queue_out_of_bounce() -> Result<()>262ffe74184SMartin Algesten fn test_pending_base_queue_out_of_bounce() -> Result<()> {
263ffe74184SMartin Algesten let mut pq = PendingBaseQueue::new();
264ffe74184SMartin Algesten assert!(pq.pop_front().is_none(), "should be none");
265ffe74184SMartin Algesten assert!(pq.get(0).is_none(), "should be none");
266ffe74184SMartin Algesten
267ffe74184SMartin Algesten pq.push_back(make_data_chunk(0, false, NO_FRAGMENT));
268ffe74184SMartin Algesten assert!(pq.get(1).is_none(), "should be none");
269ffe74184SMartin Algesten
270ffe74184SMartin Algesten Ok(())
271ffe74184SMartin Algesten }
272ffe74184SMartin Algesten
273ffe74184SMartin Algesten // NOTE: TSN is not used in pendingQueue in the actual usage.
274ffe74184SMartin Algesten // Following tests use TSN field as a chunk ID.
275daaf05d1SMoritz Borcherding #[tokio::test]
test_pending_queue_push_and_pop() -> Result<()>276daaf05d1SMoritz Borcherding async fn test_pending_queue_push_and_pop() -> Result<()> {
277ffe74184SMartin Algesten let pq = PendingQueue::new();
278daaf05d1SMoritz Borcherding pq.push(make_data_chunk(0, false, NO_FRAGMENT)).await;
27983f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 10, "total bytes mismatch");
280daaf05d1SMoritz Borcherding pq.push(make_data_chunk(1, false, NO_FRAGMENT)).await;
28183f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 20, "total bytes mismatch");
282daaf05d1SMoritz Borcherding pq.push(make_data_chunk(2, false, NO_FRAGMENT)).await;
28383f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 30, "total bytes mismatch");
284ffe74184SMartin Algesten
285ffe74184SMartin Algesten for i in 0..3 {
2860acb5a49SAnton Kaliaev let c = pq.peek();
287ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
288ffe74184SMartin Algesten let c = c.unwrap();
28983f2d1bbSVincent Esche assert_eq!(c.tsn, i, "TSN should match");
290ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
291ffe74184SMartin Algesten
2920acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
293*5d8fe953SJoão Oliveira assert!(result.is_some(), "should not error: {i}");
294ffe74184SMartin Algesten }
295ffe74184SMartin Algesten
29683f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 0, "total bytes mismatch");
297ffe74184SMartin Algesten
298daaf05d1SMoritz Borcherding pq.push(make_data_chunk(3, false, NO_FRAGMENT)).await;
29983f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 10, "total bytes mismatch");
300daaf05d1SMoritz Borcherding pq.push(make_data_chunk(4, false, NO_FRAGMENT)).await;
30183f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 20, "total bytes mismatch");
302ffe74184SMartin Algesten
303ffe74184SMartin Algesten for i in 3..5 {
3040acb5a49SAnton Kaliaev let c = pq.peek();
305ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
306ffe74184SMartin Algesten let c = c.unwrap();
30783f2d1bbSVincent Esche assert_eq!(c.tsn, i, "TSN should match");
308ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
309ffe74184SMartin Algesten
3100acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
311*5d8fe953SJoão Oliveira assert!(result.is_some(), "should not error: {i}");
312ffe74184SMartin Algesten }
313ffe74184SMartin Algesten
31483f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 0, "total bytes mismatch");
315ffe74184SMartin Algesten
316ffe74184SMartin Algesten Ok(())
317ffe74184SMartin Algesten }
318ffe74184SMartin Algesten
319daaf05d1SMoritz Borcherding #[tokio::test]
test_pending_queue_unordered_wins() -> Result<()>320daaf05d1SMoritz Borcherding async fn test_pending_queue_unordered_wins() -> Result<()> {
321ffe74184SMartin Algesten let pq = PendingQueue::new();
322ffe74184SMartin Algesten
323daaf05d1SMoritz Borcherding pq.push(make_data_chunk(0, false, NO_FRAGMENT)).await;
324ffe74184SMartin Algesten assert_eq!(10, pq.get_num_bytes(), "total bytes mismatch");
325daaf05d1SMoritz Borcherding pq.push(make_data_chunk(1, true, NO_FRAGMENT)).await;
326ffe74184SMartin Algesten assert_eq!(20, pq.get_num_bytes(), "total bytes mismatch");
327daaf05d1SMoritz Borcherding pq.push(make_data_chunk(2, false, NO_FRAGMENT)).await;
328ffe74184SMartin Algesten assert_eq!(30, pq.get_num_bytes(), "total bytes mismatch");
329daaf05d1SMoritz Borcherding pq.push(make_data_chunk(3, true, NO_FRAGMENT)).await;
330ffe74184SMartin Algesten assert_eq!(40, pq.get_num_bytes(), "total bytes mismatch");
331ffe74184SMartin Algesten
3320acb5a49SAnton Kaliaev let c = pq.peek();
333ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
334ffe74184SMartin Algesten let c = c.unwrap();
33583f2d1bbSVincent Esche assert_eq!(c.tsn, 1, "TSN should match");
336ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
3370acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
338ffe74184SMartin Algesten assert!(result.is_some(), "should not error");
339ffe74184SMartin Algesten
3400acb5a49SAnton Kaliaev let c = pq.peek();
341ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
342ffe74184SMartin Algesten let c = c.unwrap();
34383f2d1bbSVincent Esche assert_eq!(c.tsn, 3, "TSN should match");
344ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
3450acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
346ffe74184SMartin Algesten assert!(result.is_some(), "should not error");
347ffe74184SMartin Algesten
3480acb5a49SAnton Kaliaev let c = pq.peek();
349ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
350ffe74184SMartin Algesten let c = c.unwrap();
35183f2d1bbSVincent Esche assert_eq!(c.tsn, 0, "TSN should match");
352ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
3530acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
354ffe74184SMartin Algesten assert!(result.is_some(), "should not error");
355ffe74184SMartin Algesten
3560acb5a49SAnton Kaliaev let c = pq.peek();
357ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
358ffe74184SMartin Algesten let c = c.unwrap();
35983f2d1bbSVincent Esche assert_eq!(c.tsn, 2, "TSN should match");
360ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
3610acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
362ffe74184SMartin Algesten assert!(result.is_some(), "should not error");
363ffe74184SMartin Algesten
36483f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 0, "total bytes mismatch");
365ffe74184SMartin Algesten
366ffe74184SMartin Algesten Ok(())
367ffe74184SMartin Algesten }
368ffe74184SMartin Algesten
369daaf05d1SMoritz Borcherding #[tokio::test]
test_pending_queue_fragments() -> Result<()>370daaf05d1SMoritz Borcherding async fn test_pending_queue_fragments() -> Result<()> {
371ffe74184SMartin Algesten let pq = PendingQueue::new();
372daaf05d1SMoritz Borcherding pq.push(make_data_chunk(0, false, FRAG_BEGIN)).await;
373daaf05d1SMoritz Borcherding pq.push(make_data_chunk(1, false, FRAG_MIDDLE)).await;
374daaf05d1SMoritz Borcherding pq.push(make_data_chunk(2, false, FRAG_END)).await;
375daaf05d1SMoritz Borcherding pq.push(make_data_chunk(3, true, FRAG_BEGIN)).await;
376daaf05d1SMoritz Borcherding pq.push(make_data_chunk(4, true, FRAG_MIDDLE)).await;
377daaf05d1SMoritz Borcherding pq.push(make_data_chunk(5, true, FRAG_END)).await;
378ffe74184SMartin Algesten
379ffe74184SMartin Algesten let expects = vec![3, 4, 5, 0, 1, 2];
380ffe74184SMartin Algesten
381ffe74184SMartin Algesten for exp in expects {
3820acb5a49SAnton Kaliaev let c = pq.peek();
383ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
384ffe74184SMartin Algesten let c = c.unwrap();
38583f2d1bbSVincent Esche assert_eq!(c.tsn, exp, "TSN should match");
386ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
3870acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
388*5d8fe953SJoão Oliveira assert!(result.is_some(), "should not error: {exp}");
389ffe74184SMartin Algesten }
390ffe74184SMartin Algesten
391ffe74184SMartin Algesten Ok(())
392ffe74184SMartin Algesten }
393ffe74184SMartin Algesten
394ffe74184SMartin Algesten // Once decided ordered or unordered, the decision should persist until
395ffe74184SMartin Algesten // it pops a chunk with ending_fragment flags set to true.
396daaf05d1SMoritz Borcherding #[tokio::test]
test_pending_queue_selection_persistence() -> Result<()>397daaf05d1SMoritz Borcherding async fn test_pending_queue_selection_persistence() -> Result<()> {
398ffe74184SMartin Algesten let pq = PendingQueue::new();
399daaf05d1SMoritz Borcherding pq.push(make_data_chunk(0, false, FRAG_BEGIN)).await;
400ffe74184SMartin Algesten
4010acb5a49SAnton Kaliaev let c = pq.peek();
402ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
403ffe74184SMartin Algesten let c = c.unwrap();
40483f2d1bbSVincent Esche assert_eq!(c.tsn, 0, "TSN should match");
405ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
4060acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
407ffe74184SMartin Algesten assert!(result.is_some(), "should not error: {}", 0);
408ffe74184SMartin Algesten
409daaf05d1SMoritz Borcherding pq.push(make_data_chunk(1, true, NO_FRAGMENT)).await;
410daaf05d1SMoritz Borcherding pq.push(make_data_chunk(2, false, FRAG_MIDDLE)).await;
411daaf05d1SMoritz Borcherding pq.push(make_data_chunk(3, false, FRAG_END)).await;
412ffe74184SMartin Algesten
413ffe74184SMartin Algesten let expects = vec![2, 3, 1];
414ffe74184SMartin Algesten
415ffe74184SMartin Algesten for exp in expects {
4160acb5a49SAnton Kaliaev let c = pq.peek();
417ffe74184SMartin Algesten assert!(c.is_some(), "peek error");
418ffe74184SMartin Algesten let c = c.unwrap();
41983f2d1bbSVincent Esche assert_eq!(c.tsn, exp, "TSN should match");
420ffe74184SMartin Algesten let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
4210acb5a49SAnton Kaliaev let result = pq.pop(beginning_fragment, unordered);
422*5d8fe953SJoão Oliveira assert!(result.is_some(), "should not error: {exp}");
423ffe74184SMartin Algesten }
424ffe74184SMartin Algesten
425ffe74184SMartin Algesten Ok(())
426ffe74184SMartin Algesten }
427ffe74184SMartin Algesten
4284b638fa6SAnton Kaliaev #[tokio::test]
test_pending_queue_append() -> Result<()>4294b638fa6SAnton Kaliaev async fn test_pending_queue_append() -> Result<()> {
4304b638fa6SAnton Kaliaev let pq = PendingQueue::new();
4314b638fa6SAnton Kaliaev pq.append(vec![
4324b638fa6SAnton Kaliaev make_data_chunk(0, false, NO_FRAGMENT),
4334b638fa6SAnton Kaliaev make_data_chunk(1, false, NO_FRAGMENT),
4344b638fa6SAnton Kaliaev make_data_chunk(3, false, NO_FRAGMENT),
435daaf05d1SMoritz Borcherding ])
436daaf05d1SMoritz Borcherding .await;
43783f2d1bbSVincent Esche assert_eq!(pq.get_num_bytes(), 30, "total bytes mismatch");
43883f2d1bbSVincent Esche assert_eq!(pq.len(), 3, "len mismatch");
4394b638fa6SAnton Kaliaev
4404b638fa6SAnton Kaliaev Ok(())
4414b638fa6SAnton Kaliaev }
4424b638fa6SAnton Kaliaev
443ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
444ffe74184SMartin Algesten //reassembly_queue_test
445ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
446ffe74184SMartin Algesten use super::reassembly_queue::*;
447ffe74184SMartin Algesten use std::sync::atomic::AtomicUsize;
448ffe74184SMartin Algesten use std::sync::Arc;
449ffe74184SMartin Algesten
450ffe74184SMartin Algesten #[test]
test_reassembly_queue_ordered_fragments() -> Result<()>451ffe74184SMartin Algesten fn test_reassembly_queue_ordered_fragments() -> Result<()> {
452ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
453ffe74184SMartin Algesten
454ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
455ffe74184SMartin Algesten
456ffe74184SMartin Algesten let chunk = ChunkPayloadData {
457ffe74184SMartin Algesten payload_type: org_ppi,
458ffe74184SMartin Algesten beginning_fragment: true,
459ffe74184SMartin Algesten tsn: 1,
460ffe74184SMartin Algesten stream_sequence_number: 0,
461ffe74184SMartin Algesten user_data: Bytes::from_static(b"ABC"),
462ffe74184SMartin Algesten ..Default::default()
463ffe74184SMartin Algesten };
464ffe74184SMartin Algesten
465ffe74184SMartin Algesten let complete = rq.push(chunk);
466ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
46783f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
468ffe74184SMartin Algesten
469ffe74184SMartin Algesten let chunk = ChunkPayloadData {
470ffe74184SMartin Algesten payload_type: org_ppi,
471ffe74184SMartin Algesten ending_fragment: true,
472ffe74184SMartin Algesten tsn: 2,
473ffe74184SMartin Algesten stream_sequence_number: 0,
474ffe74184SMartin Algesten user_data: Bytes::from_static(b"DEFG"),
475ffe74184SMartin Algesten ..Default::default()
476ffe74184SMartin Algesten };
477ffe74184SMartin Algesten
478ffe74184SMartin Algesten let complete = rq.push(chunk);
479ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
480ffe74184SMartin Algesten assert_eq!(7, rq.get_num_bytes(), "num bytes mismatch");
481ffe74184SMartin Algesten
482ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
483ffe74184SMartin Algesten
484ffe74184SMartin Algesten let (n, ppi) = rq.read(&mut buf)?;
48583f2d1bbSVincent Esche assert_eq!(n, 7, "should received 7 bytes");
48683f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
487ffe74184SMartin Algesten assert_eq!(ppi, org_ppi, "should have valid ppi");
488ffe74184SMartin Algesten assert_eq!(&buf[..n], b"ABCDEFG", "data should match");
489ffe74184SMartin Algesten
490ffe74184SMartin Algesten Ok(())
491ffe74184SMartin Algesten }
492ffe74184SMartin Algesten
493ffe74184SMartin Algesten #[test]
test_reassembly_queue_unordered_fragments() -> Result<()>494ffe74184SMartin Algesten fn test_reassembly_queue_unordered_fragments() -> Result<()> {
495ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
496ffe74184SMartin Algesten
497ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
498ffe74184SMartin Algesten
499ffe74184SMartin Algesten let chunk = ChunkPayloadData {
500ffe74184SMartin Algesten payload_type: org_ppi,
501ffe74184SMartin Algesten unordered: true,
502ffe74184SMartin Algesten beginning_fragment: true,
503ffe74184SMartin Algesten tsn: 1,
504ffe74184SMartin Algesten stream_sequence_number: 0,
505ffe74184SMartin Algesten user_data: Bytes::from_static(b"ABC"),
506ffe74184SMartin Algesten ..Default::default()
507ffe74184SMartin Algesten };
508ffe74184SMartin Algesten
509ffe74184SMartin Algesten let complete = rq.push(chunk);
510ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
51183f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
512ffe74184SMartin Algesten
513ffe74184SMartin Algesten let chunk = ChunkPayloadData {
514ffe74184SMartin Algesten payload_type: org_ppi,
515ffe74184SMartin Algesten unordered: true,
516ffe74184SMartin Algesten tsn: 2,
517ffe74184SMartin Algesten stream_sequence_number: 0,
518ffe74184SMartin Algesten user_data: Bytes::from_static(b"DEFG"),
519ffe74184SMartin Algesten ..Default::default()
520ffe74184SMartin Algesten };
521ffe74184SMartin Algesten
522ffe74184SMartin Algesten let complete = rq.push(chunk);
523ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
52483f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 7, "num bytes mismatch");
525ffe74184SMartin Algesten
526ffe74184SMartin Algesten let chunk = ChunkPayloadData {
527ffe74184SMartin Algesten payload_type: org_ppi,
528ffe74184SMartin Algesten unordered: true,
529ffe74184SMartin Algesten ending_fragment: true,
530ffe74184SMartin Algesten tsn: 3,
531ffe74184SMartin Algesten stream_sequence_number: 0,
532ffe74184SMartin Algesten user_data: Bytes::from_static(b"H"),
533ffe74184SMartin Algesten ..Default::default()
534ffe74184SMartin Algesten };
535ffe74184SMartin Algesten
536ffe74184SMartin Algesten let complete = rq.push(chunk);
537ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
53883f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 8, "num bytes mismatch");
539ffe74184SMartin Algesten
540ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
541ffe74184SMartin Algesten
542ffe74184SMartin Algesten let (n, ppi) = rq.read(&mut buf)?;
54383f2d1bbSVincent Esche assert_eq!(n, 8, "should received 8 bytes");
54483f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
545ffe74184SMartin Algesten assert_eq!(ppi, org_ppi, "should have valid ppi");
546ffe74184SMartin Algesten assert_eq!(&buf[..n], b"ABCDEFGH", "data should match");
547ffe74184SMartin Algesten
548ffe74184SMartin Algesten Ok(())
549ffe74184SMartin Algesten }
550ffe74184SMartin Algesten
551ffe74184SMartin Algesten #[test]
test_reassembly_queue_ordered_and_unordered_fragments() -> Result<()>552ffe74184SMartin Algesten fn test_reassembly_queue_ordered_and_unordered_fragments() -> Result<()> {
553ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
554ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
555ffe74184SMartin Algesten let chunk = ChunkPayloadData {
556ffe74184SMartin Algesten payload_type: org_ppi,
557ffe74184SMartin Algesten beginning_fragment: true,
558ffe74184SMartin Algesten ending_fragment: true,
559ffe74184SMartin Algesten tsn: 1,
560ffe74184SMartin Algesten stream_sequence_number: 0,
561ffe74184SMartin Algesten user_data: Bytes::from_static(b"ABC"),
562ffe74184SMartin Algesten ..Default::default()
563ffe74184SMartin Algesten };
564ffe74184SMartin Algesten
565ffe74184SMartin Algesten let complete = rq.push(chunk);
566ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
56783f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
568ffe74184SMartin Algesten
569ffe74184SMartin Algesten let chunk = ChunkPayloadData {
570ffe74184SMartin Algesten payload_type: org_ppi,
571ffe74184SMartin Algesten unordered: true,
572ffe74184SMartin Algesten beginning_fragment: true,
573ffe74184SMartin Algesten ending_fragment: true,
574ffe74184SMartin Algesten tsn: 2,
575ffe74184SMartin Algesten stream_sequence_number: 1,
576ffe74184SMartin Algesten user_data: Bytes::from_static(b"DEF"),
577ffe74184SMartin Algesten ..Default::default()
578ffe74184SMartin Algesten };
579ffe74184SMartin Algesten
580ffe74184SMartin Algesten let complete = rq.push(chunk);
581ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
58283f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 6, "num bytes mismatch");
583ffe74184SMartin Algesten
584ffe74184SMartin Algesten //
585ffe74184SMartin Algesten // Now we have two complete chunks ready to read in the reassemblyQueue.
586ffe74184SMartin Algesten //
587ffe74184SMartin Algesten
588ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
589ffe74184SMartin Algesten
590ffe74184SMartin Algesten // Should read unordered chunks first
591ffe74184SMartin Algesten let (n, ppi) = rq.read(&mut buf)?;
59283f2d1bbSVincent Esche assert_eq!(n, 3, "should received 3 bytes");
59383f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
594ffe74184SMartin Algesten assert_eq!(ppi, org_ppi, "should have valid ppi");
595ffe74184SMartin Algesten assert_eq!(&buf[..n], b"DEF", "data should match");
596ffe74184SMartin Algesten
597ffe74184SMartin Algesten // Next should read ordered chunks
598ffe74184SMartin Algesten let (n, ppi) = rq.read(&mut buf)?;
59983f2d1bbSVincent Esche assert_eq!(n, 3, "should received 3 bytes");
60083f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
601ffe74184SMartin Algesten assert_eq!(ppi, org_ppi, "should have valid ppi");
602ffe74184SMartin Algesten assert_eq!(&buf[..n], b"ABC", "data should match");
603ffe74184SMartin Algesten
604ffe74184SMartin Algesten Ok(())
605ffe74184SMartin Algesten }
606ffe74184SMartin Algesten
607ffe74184SMartin Algesten #[test]
test_reassembly_queue_unordered_complete_skips_incomplete() -> Result<()>608ffe74184SMartin Algesten fn test_reassembly_queue_unordered_complete_skips_incomplete() -> Result<()> {
609ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
610ffe74184SMartin Algesten
611ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
612ffe74184SMartin Algesten
613ffe74184SMartin Algesten let chunk = ChunkPayloadData {
614ffe74184SMartin Algesten payload_type: org_ppi,
615ffe74184SMartin Algesten unordered: true,
616ffe74184SMartin Algesten beginning_fragment: true,
617ffe74184SMartin Algesten tsn: 10,
618ffe74184SMartin Algesten stream_sequence_number: 0,
619ffe74184SMartin Algesten user_data: Bytes::from_static(b"IN"),
620ffe74184SMartin Algesten ..Default::default()
621ffe74184SMartin Algesten };
622ffe74184SMartin Algesten
623ffe74184SMartin Algesten let complete = rq.push(chunk);
624ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
625ffe74184SMartin Algesten assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
626ffe74184SMartin Algesten
627ffe74184SMartin Algesten let chunk = ChunkPayloadData {
628ffe74184SMartin Algesten payload_type: org_ppi,
629ffe74184SMartin Algesten unordered: true,
630ffe74184SMartin Algesten ending_fragment: true,
631ffe74184SMartin Algesten tsn: 12, // <- incongiguous
632ffe74184SMartin Algesten stream_sequence_number: 1,
633ffe74184SMartin Algesten user_data: Bytes::from_static(b"COMPLETE"),
634ffe74184SMartin Algesten ..Default::default()
635ffe74184SMartin Algesten };
636ffe74184SMartin Algesten
637ffe74184SMartin Algesten let complete = rq.push(chunk);
638ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
63983f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 10, "num bytes mismatch");
640ffe74184SMartin Algesten
641ffe74184SMartin Algesten let chunk = ChunkPayloadData {
642ffe74184SMartin Algesten payload_type: org_ppi,
643ffe74184SMartin Algesten unordered: true,
644ffe74184SMartin Algesten beginning_fragment: true,
645ffe74184SMartin Algesten ending_fragment: true,
646ffe74184SMartin Algesten tsn: 13,
647ffe74184SMartin Algesten stream_sequence_number: 1,
648ffe74184SMartin Algesten user_data: Bytes::from_static(b"GOOD"),
649ffe74184SMartin Algesten ..Default::default()
650ffe74184SMartin Algesten };
651ffe74184SMartin Algesten
652ffe74184SMartin Algesten let complete = rq.push(chunk);
653ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
65483f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 14, "num bytes mismatch");
655ffe74184SMartin Algesten
656ffe74184SMartin Algesten //
657ffe74184SMartin Algesten // Now we have two complete chunks ready to read in the reassemblyQueue.
658ffe74184SMartin Algesten //
659ffe74184SMartin Algesten
660ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
661ffe74184SMartin Algesten
662ffe74184SMartin Algesten // Should pick the one that has "GOOD"
663ffe74184SMartin Algesten let (n, ppi) = rq.read(&mut buf)?;
66483f2d1bbSVincent Esche assert_eq!(n, 4, "should receive 4 bytes");
66583f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 10, "num bytes mismatch");
666ffe74184SMartin Algesten assert_eq!(ppi, org_ppi, "should have valid ppi");
667ffe74184SMartin Algesten assert_eq!(&buf[..n], b"GOOD", "data should match");
668ffe74184SMartin Algesten
669ffe74184SMartin Algesten Ok(())
670ffe74184SMartin Algesten }
671ffe74184SMartin Algesten
672ffe74184SMartin Algesten #[test]
test_reassembly_queue_ignores_chunk_with_wrong_si() -> Result<()>673ffe74184SMartin Algesten fn test_reassembly_queue_ignores_chunk_with_wrong_si() -> Result<()> {
674ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(123);
675ffe74184SMartin Algesten
676ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
677ffe74184SMartin Algesten
678ffe74184SMartin Algesten let chunk = ChunkPayloadData {
679ffe74184SMartin Algesten payload_type: org_ppi,
680ffe74184SMartin Algesten stream_identifier: 124,
681ffe74184SMartin Algesten beginning_fragment: true,
682ffe74184SMartin Algesten ending_fragment: true,
683ffe74184SMartin Algesten tsn: 10,
684ffe74184SMartin Algesten stream_sequence_number: 0,
685ffe74184SMartin Algesten user_data: Bytes::from_static(b"IN"),
686ffe74184SMartin Algesten ..Default::default()
687ffe74184SMartin Algesten };
688ffe74184SMartin Algesten
689ffe74184SMartin Algesten let complete = rq.push(chunk);
690ffe74184SMartin Algesten assert!(!complete, "chunk should be ignored");
69183f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
692ffe74184SMartin Algesten Ok(())
693ffe74184SMartin Algesten }
694ffe74184SMartin Algesten
695ffe74184SMartin Algesten #[test]
test_reassembly_queue_ignores_chunk_with_stale_ssn() -> Result<()>696ffe74184SMartin Algesten fn test_reassembly_queue_ignores_chunk_with_stale_ssn() -> Result<()> {
697ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
698ffe74184SMartin Algesten rq.next_ssn = 7; // forcibly set expected SSN to 7
699ffe74184SMartin Algesten
700ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
701ffe74184SMartin Algesten
702ffe74184SMartin Algesten let chunk = ChunkPayloadData {
703ffe74184SMartin Algesten payload_type: org_ppi,
704ffe74184SMartin Algesten beginning_fragment: true,
705ffe74184SMartin Algesten ending_fragment: true,
706ffe74184SMartin Algesten tsn: 10,
707ffe74184SMartin Algesten stream_sequence_number: 6, // <-- stale
708ffe74184SMartin Algesten user_data: Bytes::from_static(b"IN"),
709ffe74184SMartin Algesten ..Default::default()
710ffe74184SMartin Algesten };
711ffe74184SMartin Algesten
712ffe74184SMartin Algesten let complete = rq.push(chunk);
713ffe74184SMartin Algesten assert!(!complete, "chunk should not be ignored");
71483f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
715ffe74184SMartin Algesten
716ffe74184SMartin Algesten Ok(())
717ffe74184SMartin Algesten }
718ffe74184SMartin Algesten
719ffe74184SMartin Algesten #[test]
test_reassembly_queue_should_fail_to_read_incomplete_chunk() -> Result<()>720ffe74184SMartin Algesten fn test_reassembly_queue_should_fail_to_read_incomplete_chunk() -> Result<()> {
721ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
722ffe74184SMartin Algesten
723ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
724ffe74184SMartin Algesten
725ffe74184SMartin Algesten let chunk = ChunkPayloadData {
726ffe74184SMartin Algesten payload_type: org_ppi,
727ffe74184SMartin Algesten beginning_fragment: true,
728ffe74184SMartin Algesten tsn: 123,
729ffe74184SMartin Algesten stream_sequence_number: 0,
730ffe74184SMartin Algesten user_data: Bytes::from_static(b"IN"),
731ffe74184SMartin Algesten ..Default::default()
732ffe74184SMartin Algesten };
733ffe74184SMartin Algesten
734ffe74184SMartin Algesten let complete = rq.push(chunk);
735ffe74184SMartin Algesten assert!(!complete, "the set should not be complete");
73683f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 2, "num bytes mismatch");
737ffe74184SMartin Algesten
738ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
739ffe74184SMartin Algesten let result = rq.read(&mut buf);
740ffe74184SMartin Algesten assert!(result.is_err(), "read() should not succeed");
74183f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 2, "num bytes mismatch");
742ffe74184SMartin Algesten
743ffe74184SMartin Algesten Ok(())
744ffe74184SMartin Algesten }
745ffe74184SMartin Algesten
746ffe74184SMartin Algesten #[test]
test_reassembly_queue_should_fail_to_read_if_the_nex_ssn_is_not_ready() -> Result<()>747ffe74184SMartin Algesten fn test_reassembly_queue_should_fail_to_read_if_the_nex_ssn_is_not_ready() -> Result<()> {
748ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
749ffe74184SMartin Algesten
750ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
751ffe74184SMartin Algesten
752ffe74184SMartin Algesten let chunk = ChunkPayloadData {
753ffe74184SMartin Algesten payload_type: org_ppi,
754ffe74184SMartin Algesten beginning_fragment: true,
755ffe74184SMartin Algesten ending_fragment: true,
756ffe74184SMartin Algesten tsn: 123,
757ffe74184SMartin Algesten stream_sequence_number: 1,
758ffe74184SMartin Algesten user_data: Bytes::from_static(b"IN"),
759ffe74184SMartin Algesten ..Default::default()
760ffe74184SMartin Algesten };
761ffe74184SMartin Algesten
762ffe74184SMartin Algesten let complete = rq.push(chunk);
763ffe74184SMartin Algesten assert!(complete, "the set should be complete");
76483f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 2, "num bytes mismatch");
765ffe74184SMartin Algesten
766ffe74184SMartin Algesten let mut buf = vec![0u8; 16];
767ffe74184SMartin Algesten let result = rq.read(&mut buf);
768ffe74184SMartin Algesten assert!(result.is_err(), "read() should not succeed");
76983f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 2, "num bytes mismatch");
770ffe74184SMartin Algesten
771ffe74184SMartin Algesten Ok(())
772ffe74184SMartin Algesten }
773ffe74184SMartin Algesten
774ffe74184SMartin Algesten #[test]
test_reassembly_queue_detect_buffer_too_short() -> Result<()>775ffe74184SMartin Algesten fn test_reassembly_queue_detect_buffer_too_short() -> Result<()> {
776ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
777ffe74184SMartin Algesten
778ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
779ffe74184SMartin Algesten
780ffe74184SMartin Algesten let chunk = ChunkPayloadData {
781ffe74184SMartin Algesten payload_type: org_ppi,
782ffe74184SMartin Algesten beginning_fragment: true,
783ffe74184SMartin Algesten ending_fragment: true,
784ffe74184SMartin Algesten tsn: 123,
785ffe74184SMartin Algesten stream_sequence_number: 0,
786ffe74184SMartin Algesten user_data: Bytes::from_static(b"0123456789"),
787ffe74184SMartin Algesten ..Default::default()
788ffe74184SMartin Algesten };
789ffe74184SMartin Algesten
790ffe74184SMartin Algesten let complete = rq.push(chunk);
791ffe74184SMartin Algesten assert!(complete, "the set should be complete");
79283f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 10, "num bytes mismatch");
793ffe74184SMartin Algesten
794ffe74184SMartin Algesten let mut buf = vec![0u8; 8]; // <- passing buffer too short
795ffe74184SMartin Algesten let result = rq.read(&mut buf);
796ffe74184SMartin Algesten assert!(result.is_err(), "read() should not succeed");
797ffe74184SMartin Algesten if let Err(err) = result {
79883f2d1bbSVincent Esche assert_eq!(err, Error::ErrShortBuffer, "read() should not succeed");
799ffe74184SMartin Algesten }
80083f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 0, "num bytes mismatch");
801ffe74184SMartin Algesten
802ffe74184SMartin Algesten Ok(())
803ffe74184SMartin Algesten }
804ffe74184SMartin Algesten
805ffe74184SMartin Algesten #[test]
test_reassembly_queue_forward_tsn_for_ordered_framents() -> Result<()>806ffe74184SMartin Algesten fn test_reassembly_queue_forward_tsn_for_ordered_framents() -> Result<()> {
807ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
808ffe74184SMartin Algesten
809ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
810ffe74184SMartin Algesten
811ffe74184SMartin Algesten let ssn_complete = 5u16;
812ffe74184SMartin Algesten let ssn_dropped = 6u16;
813ffe74184SMartin Algesten
814ffe74184SMartin Algesten let chunk = ChunkPayloadData {
815ffe74184SMartin Algesten payload_type: org_ppi,
816ffe74184SMartin Algesten beginning_fragment: true,
817ffe74184SMartin Algesten ending_fragment: true,
818ffe74184SMartin Algesten tsn: 10,
819ffe74184SMartin Algesten stream_sequence_number: ssn_complete,
820ffe74184SMartin Algesten user_data: Bytes::from_static(b"123"),
821ffe74184SMartin Algesten ..Default::default()
822ffe74184SMartin Algesten };
823ffe74184SMartin Algesten
824ffe74184SMartin Algesten let complete = rq.push(chunk);
825ffe74184SMartin Algesten assert!(complete, "chunk set should be complete");
82683f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
827ffe74184SMartin Algesten
828ffe74184SMartin Algesten let chunk = ChunkPayloadData {
829ffe74184SMartin Algesten payload_type: org_ppi,
830ffe74184SMartin Algesten beginning_fragment: true,
831ffe74184SMartin Algesten tsn: 11,
832ffe74184SMartin Algesten stream_sequence_number: ssn_dropped,
833ffe74184SMartin Algesten user_data: Bytes::from_static(b"ABC"),
834ffe74184SMartin Algesten ..Default::default()
835ffe74184SMartin Algesten };
836ffe74184SMartin Algesten
837ffe74184SMartin Algesten let complete = rq.push(chunk);
838ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
83983f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 6, "num bytes mismatch");
840ffe74184SMartin Algesten
841ffe74184SMartin Algesten let chunk = ChunkPayloadData {
842ffe74184SMartin Algesten payload_type: org_ppi,
843ffe74184SMartin Algesten tsn: 12,
844ffe74184SMartin Algesten stream_sequence_number: ssn_dropped,
845ffe74184SMartin Algesten user_data: Bytes::from_static(b"DEF"),
846ffe74184SMartin Algesten ..Default::default()
847ffe74184SMartin Algesten };
848ffe74184SMartin Algesten
849ffe74184SMartin Algesten let complete = rq.push(chunk);
850ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
85183f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 9, "num bytes mismatch");
852ffe74184SMartin Algesten
853ffe74184SMartin Algesten rq.forward_tsn_for_ordered(ssn_dropped);
854ffe74184SMartin Algesten
85583f2d1bbSVincent Esche assert_eq!(rq.ordered.len(), 1, "there should be one chunk left");
85683f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
857ffe74184SMartin Algesten
858ffe74184SMartin Algesten Ok(())
859ffe74184SMartin Algesten }
860ffe74184SMartin Algesten
861ffe74184SMartin Algesten #[test]
test_reassembly_queue_forward_tsn_for_unordered_framents() -> Result<()>862ffe74184SMartin Algesten fn test_reassembly_queue_forward_tsn_for_unordered_framents() -> Result<()> {
863ffe74184SMartin Algesten let mut rq = ReassemblyQueue::new(0);
864ffe74184SMartin Algesten
865ffe74184SMartin Algesten let org_ppi = PayloadProtocolIdentifier::Binary;
866ffe74184SMartin Algesten
867ffe74184SMartin Algesten let ssn_dropped = 6u16;
868ffe74184SMartin Algesten let ssn_kept = 7u16;
869ffe74184SMartin Algesten
870ffe74184SMartin Algesten let chunk = ChunkPayloadData {
871ffe74184SMartin Algesten payload_type: org_ppi,
872ffe74184SMartin Algesten unordered: true,
873ffe74184SMartin Algesten beginning_fragment: true,
874ffe74184SMartin Algesten tsn: 11,
875ffe74184SMartin Algesten stream_sequence_number: ssn_dropped,
876ffe74184SMartin Algesten user_data: Bytes::from_static(b"ABC"),
877ffe74184SMartin Algesten ..Default::default()
878ffe74184SMartin Algesten };
879ffe74184SMartin Algesten
880ffe74184SMartin Algesten let complete = rq.push(chunk);
881ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
88283f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
883ffe74184SMartin Algesten
884ffe74184SMartin Algesten let chunk = ChunkPayloadData {
885ffe74184SMartin Algesten payload_type: org_ppi,
886ffe74184SMartin Algesten unordered: true,
887ffe74184SMartin Algesten tsn: 12,
888ffe74184SMartin Algesten stream_sequence_number: ssn_dropped,
889ffe74184SMartin Algesten user_data: Bytes::from_static(b"DEF"),
890ffe74184SMartin Algesten ..Default::default()
891ffe74184SMartin Algesten };
892ffe74184SMartin Algesten
893ffe74184SMartin Algesten let complete = rq.push(chunk);
894ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
89583f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 6, "num bytes mismatch");
896ffe74184SMartin Algesten
897ffe74184SMartin Algesten let chunk = ChunkPayloadData {
898ffe74184SMartin Algesten payload_type: org_ppi,
899ffe74184SMartin Algesten unordered: true,
900ffe74184SMartin Algesten tsn: 14,
901ffe74184SMartin Algesten beginning_fragment: true,
902ffe74184SMartin Algesten stream_sequence_number: ssn_kept,
903ffe74184SMartin Algesten user_data: Bytes::from_static(b"SOS"),
904ffe74184SMartin Algesten ..Default::default()
905ffe74184SMartin Algesten };
906ffe74184SMartin Algesten
907ffe74184SMartin Algesten let complete = rq.push(chunk);
908ffe74184SMartin Algesten assert!(!complete, "chunk set should not be complete yet");
90983f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 9, "num bytes mismatch");
910ffe74184SMartin Algesten
911ffe74184SMartin Algesten // At this point, there are 3 chunks in the rq.unorderedChunks.
912ffe74184SMartin Algesten // This call should remove chunks with tsn equals to 13 or older.
913ffe74184SMartin Algesten rq.forward_tsn_for_unordered(13);
914ffe74184SMartin Algesten
915ffe74184SMartin Algesten // As a result, there should be one chunk (tsn=14)
916ffe74184SMartin Algesten assert_eq!(
917ffe74184SMartin Algesten rq.unordered_chunks.len(),
91883f2d1bbSVincent Esche 1,
919ffe74184SMartin Algesten "there should be one chunk kept"
920ffe74184SMartin Algesten );
92183f2d1bbSVincent Esche assert_eq!(rq.get_num_bytes(), 3, "num bytes mismatch");
922ffe74184SMartin Algesten
923ffe74184SMartin Algesten Ok(())
924ffe74184SMartin Algesten }
925ffe74184SMartin Algesten
926ffe74184SMartin Algesten #[test]
test_chunk_set_empty_chunk_set() -> Result<()>927ffe74184SMartin Algesten fn test_chunk_set_empty_chunk_set() -> Result<()> {
928ffe74184SMartin Algesten let cset = ChunkSet::new(0, PayloadProtocolIdentifier::default());
929ffe74184SMartin Algesten assert!(!cset.is_complete(), "empty chunkSet cannot be complete");
930ffe74184SMartin Algesten Ok(())
931ffe74184SMartin Algesten }
932ffe74184SMartin Algesten
933ffe74184SMartin Algesten #[test]
test_chunk_set_push_dup_chunks_to_chunk_set() -> Result<()>934ffe74184SMartin Algesten fn test_chunk_set_push_dup_chunks_to_chunk_set() -> Result<()> {
935ffe74184SMartin Algesten let mut cset = ChunkSet::new(0, PayloadProtocolIdentifier::default());
936ffe74184SMartin Algesten cset.push(ChunkPayloadData {
937ffe74184SMartin Algesten tsn: 100,
938ffe74184SMartin Algesten beginning_fragment: true,
939ffe74184SMartin Algesten ..Default::default()
940ffe74184SMartin Algesten });
941ffe74184SMartin Algesten let complete = cset.push(ChunkPayloadData {
942ffe74184SMartin Algesten tsn: 100,
943ffe74184SMartin Algesten ending_fragment: true,
944ffe74184SMartin Algesten ..Default::default()
945ffe74184SMartin Algesten });
946ffe74184SMartin Algesten assert!(!complete, "chunk with dup TSN is not complete");
94783f2d1bbSVincent Esche assert_eq!(cset.chunks.len(), 1, "chunk with dup TSN should be ignored");
948ffe74184SMartin Algesten Ok(())
949ffe74184SMartin Algesten }
950ffe74184SMartin Algesten
951ffe74184SMartin Algesten #[test]
test_chunk_set_incomplete_chunk_set_no_beginning() -> Result<()>952ffe74184SMartin Algesten fn test_chunk_set_incomplete_chunk_set_no_beginning() -> Result<()> {
953ffe74184SMartin Algesten let cset = ChunkSet {
954ffe74184SMartin Algesten ssn: 0,
955ffe74184SMartin Algesten ppi: PayloadProtocolIdentifier::default(),
956ffe74184SMartin Algesten chunks: vec![],
957ffe74184SMartin Algesten };
958ffe74184SMartin Algesten assert!(
959ffe74184SMartin Algesten !cset.is_complete(),
960ffe74184SMartin Algesten "chunkSet not starting with B=1 cannot be complete"
961ffe74184SMartin Algesten );
962ffe74184SMartin Algesten Ok(())
963ffe74184SMartin Algesten }
964ffe74184SMartin Algesten
965ffe74184SMartin Algesten #[test]
test_chunk_set_incomplete_chunk_set_no_contiguous_tsn() -> Result<()>966ffe74184SMartin Algesten fn test_chunk_set_incomplete_chunk_set_no_contiguous_tsn() -> Result<()> {
967ffe74184SMartin Algesten let cset = ChunkSet {
968ffe74184SMartin Algesten ssn: 0,
969ffe74184SMartin Algesten ppi: PayloadProtocolIdentifier::default(),
970ffe74184SMartin Algesten chunks: vec![
971ffe74184SMartin Algesten ChunkPayloadData {
972ffe74184SMartin Algesten tsn: 100,
973ffe74184SMartin Algesten beginning_fragment: true,
974ffe74184SMartin Algesten ..Default::default()
975ffe74184SMartin Algesten },
976ffe74184SMartin Algesten ChunkPayloadData {
977ffe74184SMartin Algesten tsn: 101,
978ffe74184SMartin Algesten ..Default::default()
979ffe74184SMartin Algesten },
980ffe74184SMartin Algesten ChunkPayloadData {
981ffe74184SMartin Algesten tsn: 103,
982ffe74184SMartin Algesten ending_fragment: true,
983ffe74184SMartin Algesten ..Default::default()
984ffe74184SMartin Algesten },
985ffe74184SMartin Algesten ],
986ffe74184SMartin Algesten };
987ffe74184SMartin Algesten assert!(
988ffe74184SMartin Algesten !cset.is_complete(),
989ffe74184SMartin Algesten "chunkSet not starting with incontiguous tsn cannot be complete"
990ffe74184SMartin Algesten );
991ffe74184SMartin Algesten Ok(())
992ffe74184SMartin Algesten }
993