xref: /webrtc/sctp/src/queue/queue_test.rs (revision 5d8fe953)
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