Skip to content
File

Blob: firmware/vendor/sctp-proto/src/queue/queue_test.rs

rust1161 lines
1use crate::error::{Error, Result};
2 
3use bytes::{Bytes, BytesMut};
4 
5///////////////////////////////////////////////////////////////////
6//payload_queue_test
7///////////////////////////////////////////////////////////////////
8use super::payload_queue::*;
9use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier};
10use crate::chunk::chunk_selective_ack::GapAckBlock;
11 
12fn make_payload(tsn: u32, n_bytes: usize) -> ChunkPayloadData {
13 ChunkPayloadData {
14 tsn,
15 user_data: {
16 let mut b = BytesMut::new();
17 b.resize(n_bytes, 0);
18 b.freeze()
19 },
20 ..Default::default()
21 }
22}
23 
24#[test]
25fn test_payload_queue_push_no_check() -> Result<()> {
26 let mut pq = PayloadQueue::new();
27 
28 pq.push_no_check(make_payload(0, 10));
29 assert_eq!(10, pq.get_num_bytes(), "total bytes mismatch");
30 assert_eq!(1, pq.len(), "item count mismatch");
31 pq.push_no_check(make_payload(1, 11));
32 assert_eq!(21, pq.get_num_bytes(), "total bytes mismatch");
33 assert_eq!(2, pq.len(), "item count mismatch");
34 pq.push_no_check(make_payload(2, 12));
35 assert_eq!(33, pq.get_num_bytes(), "total bytes mismatch");
36 assert_eq!(3, pq.len(), "item count mismatch");
37 
38 for i in 0..3 {
39 assert!(!pq.sorted.is_empty(), "should not be empty");
40 let c = pq.pop(i);
41 assert!(c.is_some(), "pop should succeed");
42 if let Some(c) = c {
43 assert_eq!(i, c.tsn, "TSN should match");
44 }
45 }
46 
47 assert_eq!(0, pq.get_num_bytes(), "total bytes mismatch");
48 assert_eq!(0, pq.len(), "item count mismatch");
49 
50 assert!(pq.sorted.is_empty(), "should be empty");
51 pq.push_no_check(make_payload(3, 13));
52 assert_eq!(13, pq.get_num_bytes(), "total bytes mismatch");
53 pq.push_no_check(make_payload(4, 14));
54 assert_eq!(27, pq.get_num_bytes(), "total bytes mismatch");
55 
56 for i in 3..5 {
57 assert!(!pq.sorted.is_empty(), "should not be empty");
58 let c = pq.pop(i);
59 assert!(c.is_some(), "pop should succeed");
60 if let Some(c) = c {
61 assert_eq!(i, c.tsn, "TSN should match");
62 }
63 }
64 
65 assert_eq!(0, pq.get_num_bytes(), "total bytes mismatch");
66 assert_eq!(0, pq.len(), "item count mismatch");
67 
68 Ok(())
69}
70 
71#[test]
72fn test_payload_queue_get_gap_ack_block() -> Result<()> {
73 let mut pq = PayloadQueue::new();
74 
75 pq.push(make_payload(1, 0), 0);
76 pq.push(make_payload(2, 0), 0);
77 pq.push(make_payload(3, 0), 0);
78 pq.push(make_payload(4, 0), 0);
79 pq.push(make_payload(5, 0), 0);
80 pq.push(make_payload(6, 0), 0);
81 
82 let gab1 = [GapAckBlock { start: 1, end: 6 }];
83 let gab2 = pq.get_gap_ack_blocks(0);
84 assert!(!gab2.is_empty());
85 assert_eq!(gab2.len(), 1);
86 
87 assert_eq!(gab1[0].start, gab2[0].start);
88 assert_eq!(gab1[0].end, gab2[0].end);
89 
90 pq.push(make_payload(8, 0), 0);
91 pq.push(make_payload(9, 0), 0);
92 
93 let gab1 = [
94 GapAckBlock { start: 1, end: 6 },
95 GapAckBlock { start: 8, end: 9 },
96 ];
97 let gab2 = pq.get_gap_ack_blocks(0);
98 assert!(!gab2.is_empty());
99 assert_eq!(gab2.len(), 2);
100 
101 assert_eq!(gab1[0].start, gab2[0].start);
102 assert_eq!(gab1[0].end, gab2[0].end);
103 assert_eq!(gab1[1].start, gab2[1].start);
104 assert_eq!(gab1[1].end, gab2[1].end);
105 
106 Ok(())
107}
108 
109#[test]
110fn test_payload_queue_get_last_tsn_received() -> Result<()> {
111 let mut pq = PayloadQueue::new();
112 
113 // empty queie should return false
114 let ok = pq.get_last_tsn_received();
115 assert!(ok.is_none(), "should be none");
116 
117 let ok = pq.push(make_payload(20, 0), 0);
118 assert!(ok, "should be true");
119 let tsn = pq.get_last_tsn_received();
120 assert!(tsn.is_some(), "should be false");
121 assert_eq!(Some(&20), tsn, "should match");
122 
123 // append should work
124 let ok = pq.push(make_payload(21, 0), 0);
125 assert!(ok, "should be true");
126 let tsn = pq.get_last_tsn_received();
127 assert!(tsn.is_some(), "should be false");
128 assert_eq!(Some(&21), tsn, "should match");
129 
130 // check if sorting applied
131 let ok = pq.push(make_payload(19, 0), 0);
132 assert!(ok, "should be true");
133 let tsn = pq.get_last_tsn_received();
134 assert!(tsn.is_some(), "should be false");
135 assert_eq!(Some(&21), tsn, "should match");
136 
137 Ok(())
138}
139 
140#[test]
141fn test_payload_queue_mark_all_to_retrasmit() -> Result<()> {
142 let mut pq = PayloadQueue::new();
143 
144 for i in 0..3 {
145 pq.push(make_payload(i + 1, 10), 0);
146 }
147 pq.mark_as_acked(2);
148 pq.mark_all_to_retrasmit();
149 
150 let c = pq.get(1);
151 assert!(c.is_some(), "should be true");
152 assert!(c.unwrap().retransmit, "should be marked as retransmit");
153 let c = pq.get(2);
154 assert!(c.is_some(), "should be true");
155 assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
156 let c = pq.get(3);
157 assert!(c.is_some(), "should be true");
158 assert!(c.unwrap().retransmit, "should be marked as retransmit");
159 
160 Ok(())
161}
162 
163#[test]
164fn test_payload_queue_reset_retransmit_flag_on_ack() -> Result<()> {
165 let mut pq = PayloadQueue::new();
166 
167 for i in 0..4 {
168 pq.push(make_payload(i + 1, 10), 0);
169 }
170 
171 pq.mark_all_to_retrasmit();
172 pq.mark_as_acked(2); // should cancel retransmission for TSN 2
173 pq.mark_as_acked(4); // should cancel retransmission for TSN 4
174 
175 let c = pq.get(1);
176 assert!(c.is_some(), "should be true");
177 assert!(c.unwrap().retransmit, "should be marked as retransmit");
178 let c = pq.get(2);
179 assert!(c.is_some(), "should be true");
180 assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
181 let c = pq.get(3);
182 assert!(c.is_some(), "should be true");
183 assert!(c.unwrap().retransmit, "should be marked as retransmit");
184 let c = pq.get(4);
185 assert!(c.is_some(), "should be true");
186 assert!(!c.unwrap().retransmit, "should NOT be marked as retransmit");
187 
188 Ok(())
189}
190 
191///////////////////////////////////////////////////////////////////
192//pending_queue_test
193///////////////////////////////////////////////////////////////////
194use super::pending_queue::*;
195 
196const NO_FRAGMENT: usize = 0;
197const FRAG_BEGIN: usize = 1;
198const FRAG_MIDDLE: usize = 2;
199const FRAG_END: usize = 3;
200 
201fn make_data_chunk(tsn: u32, unordered: bool, frag: usize) -> ChunkPayloadData {
202 let mut b = false;
203 let mut e = false;
204 
205 match frag {
206 NO_FRAGMENT => {
207 b = true;
208 e = true;
209 }
210 FRAG_BEGIN => {
211 b = true;
212 }
213 FRAG_END => e = true,
214 _ => {}
215 };
216 
217 ChunkPayloadData {
218 tsn,
219 unordered,
220 beginning_fragment: b,
221 ending_fragment: e,
222 user_data: {
223 let mut b = BytesMut::new();
224 b.resize(10, 0); // always 10 bytes
225 b.freeze()
226 },
227 ..Default::default()
228 }
229}
230 
231#[test]
232fn test_pending_base_queue_push_and_pop() -> Result<()> {
233 let mut pq = PendingBaseQueue::new();
234 pq.push_back(make_data_chunk(0, false, NO_FRAGMENT));
235 pq.push_back(make_data_chunk(1, false, NO_FRAGMENT));
236 pq.push_back(make_data_chunk(2, false, NO_FRAGMENT));
237 
238 for i in 0..3 {
239 let c = pq.get(i);
240 assert!(c.is_some(), "should not be none");
241 assert_eq!(i as u32, c.unwrap().tsn, "TSN should match");
242 }
243 
244 for i in 0..3 {
245 let c = pq.pop_front();
246 assert!(c.is_some(), "should not be none");
247 assert_eq!(i, c.unwrap().tsn, "TSN should match");
248 }
249 
250 pq.push_back(make_data_chunk(3, false, NO_FRAGMENT));
251 pq.push_back(make_data_chunk(4, false, NO_FRAGMENT));
252 
253 for i in 3..5 {
254 let c = pq.pop_front();
255 assert!(c.is_some(), "should not be none");
256 assert_eq!(i, c.unwrap().tsn, "TSN should match");
257 }
258 Ok(())
259}
260 
261#[test]
262fn test_pending_base_queue_out_of_bounce() -> Result<()> {
263 let mut pq = PendingBaseQueue::new();
264 assert!(pq.pop_front().is_none(), "should be none");
265 assert!(pq.front().is_none(), "should be none");
266 
267 pq.push_back(make_data_chunk(0, false, NO_FRAGMENT));
268 assert!(pq.get(1).is_none(), "should be none");
269 
270 Ok(())
271}
272 
273// NOTE: TSN is not used in pendingQueue in the actual usage.
274// Following tests use TSN field as a chunk ID.
275#[test]
276fn test_pending_queue_push_and_pop() -> Result<()> {
277 let mut pq = PendingQueue::new();
278 pq.push(make_data_chunk(0, false, NO_FRAGMENT));
279 assert_eq!(10, pq.get_num_bytes(), "total bytes mismatch");
280 pq.push(make_data_chunk(1, false, NO_FRAGMENT));
281 assert_eq!(20, pq.get_num_bytes(), "total bytes mismatch");
282 pq.push(make_data_chunk(2, false, NO_FRAGMENT));
283 assert_eq!(30, pq.get_num_bytes(), "total bytes mismatch");
284 
285 for i in 0..3 {
286 let c = pq.peek();
287 assert!(c.is_some(), "peek error");
288 let c = c.unwrap();
289 assert_eq!(i, c.tsn, "TSN should match");
290 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
291 
292 let result = pq.pop(beginning_fragment, unordered);
293 assert!(result.is_some(), "should not error: {}", i);
294 }
295 
296 assert_eq!(0, pq.get_num_bytes(), "total bytes mismatch");
297 
298 pq.push(make_data_chunk(3, false, NO_FRAGMENT));
299 assert_eq!(10, pq.get_num_bytes(), "total bytes mismatch");
300 pq.push(make_data_chunk(4, false, NO_FRAGMENT));
301 assert_eq!(20, pq.get_num_bytes(), "total bytes mismatch");
302 
303 for i in 3..5 {
304 let c = pq.peek();
305 assert!(c.is_some(), "peek error");
306 let c = c.unwrap();
307 assert_eq!(i, c.tsn, "TSN should match");
308 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
309 
310 let result = pq.pop(beginning_fragment, unordered);
311 assert!(result.is_some(), "should not error: {}", i);
312 }
313 
314 assert_eq!(0, pq.get_num_bytes(), "total bytes mismatch");
315 
316 Ok(())
317}
318 
319#[test]
320fn test_pending_queue_unordered_wins() -> Result<()> {
321 let mut pq = PendingQueue::new();
322 
323 pq.push(make_data_chunk(0, false, NO_FRAGMENT));
324 assert_eq!(10, pq.get_num_bytes(), "total bytes mismatch");
325 pq.push(make_data_chunk(1, true, NO_FRAGMENT));
326 assert_eq!(20, pq.get_num_bytes(), "total bytes mismatch");
327 pq.push(make_data_chunk(2, false, NO_FRAGMENT));
328 assert_eq!(30, pq.get_num_bytes(), "total bytes mismatch");
329 pq.push(make_data_chunk(3, true, NO_FRAGMENT));
330 assert_eq!(40, pq.get_num_bytes(), "total bytes mismatch");
331 
332 let c = pq.peek();
333 assert!(c.is_some(), "peek error");
334 let c = c.unwrap();
335 assert_eq!(1, c.tsn, "TSN should match");
336 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
337 let result = pq.pop(beginning_fragment, unordered);
338 assert!(result.is_some(), "should not error");
339 
340 let c = pq.peek();
341 assert!(c.is_some(), "peek error");
342 let c = c.unwrap();
343 assert_eq!(3, c.tsn, "TSN should match");
344 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
345 let result = pq.pop(beginning_fragment, unordered);
346 assert!(result.is_some(), "should not error");
347 
348 let c = pq.peek();
349 assert!(c.is_some(), "peek error");
350 let c = c.unwrap();
351 assert_eq!(0, c.tsn, "TSN should match");
352 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
353 let result = pq.pop(beginning_fragment, unordered);
354 assert!(result.is_some(), "should not error");
355 
356 let c = pq.peek();
357 assert!(c.is_some(), "peek error");
358 let c = c.unwrap();
359 assert_eq!(2, c.tsn, "TSN should match");
360 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
361 let result = pq.pop(beginning_fragment, unordered);
362 assert!(result.is_some(), "should not error");
363 
364 assert_eq!(0, pq.get_num_bytes(), "total bytes mismatch");
365 
366 Ok(())
367}
368 
369#[test]
370fn test_pending_queue_fragments() -> Result<()> {
371 let mut pq = PendingQueue::new();
372 pq.push(make_data_chunk(0, false, FRAG_BEGIN));
373 pq.push(make_data_chunk(1, false, FRAG_MIDDLE));
374 pq.push(make_data_chunk(2, false, FRAG_END));
375 pq.push(make_data_chunk(3, true, FRAG_BEGIN));
376 pq.push(make_data_chunk(4, true, FRAG_MIDDLE));
377 pq.push(make_data_chunk(5, true, FRAG_END));
378 
379 let expects = vec![3, 4, 5, 0, 1, 2];
380 
381 for exp in expects {
382 let c = pq.peek();
383 assert!(c.is_some(), "peek error");
384 let c = c.unwrap();
385 assert_eq!(exp, c.tsn, "TSN should match");
386 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
387 let result = pq.pop(beginning_fragment, unordered);
388 assert!(result.is_some(), "should not error: {}", exp);
389 }
390 
391 Ok(())
392}
393 
394// Once decided ordered or unordered, the decision should persist until
395// it pops a chunk with ending_fragment flags set to true.
396#[test]
397fn test_pending_queue_selection_persistence() -> Result<()> {
398 let mut pq = PendingQueue::new();
399 pq.push(make_data_chunk(0, false, FRAG_BEGIN));
400 
401 let c = pq.peek();
402 assert!(c.is_some(), "peek error");
403 let c = c.unwrap();
404 assert_eq!(0, c.tsn, "TSN should match");
405 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
406 let result = pq.pop(beginning_fragment, unordered);
407 assert!(result.is_some(), "should not error: {}", 0);
408 
409 pq.push(make_data_chunk(1, true, NO_FRAGMENT));
410 pq.push(make_data_chunk(2, false, FRAG_MIDDLE));
411 pq.push(make_data_chunk(3, false, FRAG_END));
412 
413 let expects = vec![2, 3, 1];
414 
415 for exp in expects {
416 let c = pq.peek();
417 assert!(c.is_some(), "peek error");
418 let c = c.unwrap();
419 assert_eq!(exp, c.tsn, "TSN should match");
420 let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
421 let result = pq.pop(beginning_fragment, unordered);
422 assert!(result.is_some(), "should not error: {}", exp);
423 }
424 
425 Ok(())
426}
427 
428///////////////////////////////////////////////////////////////////
429//reassembly_queue_test
430///////////////////////////////////////////////////////////////////
431use super::reassembly_queue::*;
432 
433#[test]
434fn test_reassembly_queue_ordered_fragments() -> Result<()> {
435 let mut rq = ReassemblyQueue::new(0, 65536);
436 
437 let org_ppi = PayloadProtocolIdentifier::Binary;
438 
439 let chunk = ChunkPayloadData {
440 payload_type: org_ppi,
441 beginning_fragment: true,
442 tsn: 1,
443 stream_sequence_number: 0,
444 user_data: Bytes::from_static(b"ABC"),
445 ..Default::default()
446 };
447 
448 let complete = rq.push(chunk).expect("chunk to be queued");
449 assert!(!complete, "chunk set should not be complete yet");
450 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
451 
452 let chunk = ChunkPayloadData {
453 payload_type: org_ppi,
454 ending_fragment: true,
455 tsn: 2,
456 stream_sequence_number: 0,
457 user_data: Bytes::from_static(b"DEFG"),
458 ..Default::default()
459 };
460 
461 let complete = rq.push(chunk).expect("chunk to be queued");
462 assert!(complete, "chunk set should be complete");
463 assert_eq!(7, rq.get_num_bytes(), "num bytes mismatch");
464 
465 let mut buf = vec![0u8; 16];
466 
467 if let Some(chunks) = rq.read() {
468 let n = chunks.read(&mut buf)?;
469 assert_eq!(7, n, "should received 7 bytes");
470 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
471 assert_eq!(chunks.ppi, org_ppi, "should have valid ppi");
472 assert_eq!(&buf[..n], b"ABCDEFG", "data should match");
473 } else {
474 panic!();
475 }
476 
477 Ok(())
478}
479 
480#[test]
481fn test_reassembly_queue_unordered_fragments() -> Result<()> {
482 let mut rq = ReassemblyQueue::new(0, 65536);
483 
484 let org_ppi = PayloadProtocolIdentifier::Binary;
485 
486 let chunk = ChunkPayloadData {
487 payload_type: org_ppi,
488 unordered: true,
489 beginning_fragment: true,
490 tsn: 1,
491 stream_sequence_number: 0,
492 user_data: Bytes::from_static(b"ABC"),
493 ..Default::default()
494 };
495 
496 let complete = rq.push(chunk).expect("chunk to be queued");
497 assert!(!complete, "chunk set should not be complete yet");
498 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
499 
500 let chunk = ChunkPayloadData {
501 payload_type: org_ppi,
502 unordered: true,
503 tsn: 2,
504 stream_sequence_number: 0,
505 user_data: Bytes::from_static(b"DEFG"),
506 ..Default::default()
507 };
508 
509 let complete = rq.push(chunk).expect("chunk to be queued");
510 assert!(!complete, "chunk set should not be complete yet");
511 assert_eq!(7, rq.get_num_bytes(), "num bytes mismatch");
512 
513 let chunk = ChunkPayloadData {
514 payload_type: org_ppi,
515 unordered: true,
516 ending_fragment: true,
517 tsn: 3,
518 stream_sequence_number: 0,
519 user_data: Bytes::from_static(b"H"),
520 ..Default::default()
521 };
522 
523 let complete = rq.push(chunk).expect("chunk to be queued");
524 assert!(complete, "chunk set should be complete");
525 assert_eq!(8, rq.get_num_bytes(), "num bytes mismatch");
526 
527 let mut buf = vec![0u8; 16];
528 
529 if let Some(chunks) = rq.read() {
530 let n = chunks.read(&mut buf)?;
531 assert_eq!(8, n, "should received 8 bytes");
532 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
533 assert_eq!(chunks.ppi, org_ppi, "should have valid ppi");
534 assert_eq!(&buf[..n], b"ABCDEFGH", "data should match");
535 } else {
536 panic!();
537 }
538 
539 Ok(())
540}
541 
542#[test]
543fn test_reassembly_queue_ordered_and_unordered_fragments() -> Result<()> {
544 let mut rq = ReassemblyQueue::new(0, 65536);
545 let org_ppi = PayloadProtocolIdentifier::Binary;
546 let chunk = ChunkPayloadData {
547 payload_type: org_ppi,
548 beginning_fragment: true,
549 ending_fragment: true,
550 tsn: 1,
551 stream_sequence_number: 0,
552 user_data: Bytes::from_static(b"ABC"),
553 ..Default::default()
554 };
555 
556 let complete = rq.push(chunk).expect("chunk to be queued");
557 assert!(complete, "chunk set should be complete");
558 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
559 
560 let chunk = ChunkPayloadData {
561 payload_type: org_ppi,
562 unordered: true,
563 beginning_fragment: true,
564 ending_fragment: true,
565 tsn: 2,
566 stream_sequence_number: 1,
567 user_data: Bytes::from_static(b"DEF"),
568 ..Default::default()
569 };
570 
571 let complete = rq.push(chunk).expect("chunk to be queued");
572 assert!(complete, "chunk set should be complete");
573 assert_eq!(6, rq.get_num_bytes(), "num bytes mismatch");
574 
575 //
576 // Now we have two complete chunks ready to read in the reassemblyQueue.
577 //
578 
579 let mut buf = vec![0u8; 16];
580 
581 // Should read unordered chunks first
582 if let Some(chunks) = rq.read() {
583 let n = chunks.read(&mut buf)?;
584 assert_eq!(3, n, "should received 3 bytes");
585 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
586 assert_eq!(chunks.ppi, org_ppi, "should have valid ppi");
587 assert_eq!(&buf[..n], b"DEF", "data should match");
588 } else {
589 panic!();
590 }
591 
592 // Next should read ordered chunks
593 if let Some(chunks) = rq.read() {
594 let n = chunks.read(&mut buf)?;
595 assert_eq!(3, n, "should received 3 bytes");
596 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
597 assert_eq!(chunks.ppi, org_ppi, "should have valid ppi");
598 assert_eq!(&buf[..n], b"ABC", "data should match");
599 } else {
600 panic!();
601 }
602 
603 Ok(())
604}
605 
606#[test]
607fn test_reassembly_queue_unordered_complete_skips_incomplete() -> Result<()> {
608 let mut rq = ReassemblyQueue::new(0, 65536);
609 
610 let org_ppi = PayloadProtocolIdentifier::Binary;
611 
612 let chunk = ChunkPayloadData {
613 payload_type: org_ppi,
614 unordered: true,
615 beginning_fragment: true,
616 tsn: 10,
617 stream_sequence_number: 0,
618 user_data: Bytes::from_static(b"IN"),
619 ..Default::default()
620 };
621 
622 let complete = rq.push(chunk).expect("chunk to be queued");
623 assert!(!complete, "chunk set should not be complete yet");
624 assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
625 
626 let chunk = ChunkPayloadData {
627 payload_type: org_ppi,
628 unordered: true,
629 ending_fragment: true,
630 tsn: 12, // <- incongiguous
631 stream_sequence_number: 1,
632 user_data: Bytes::from_static(b"COMPLETE"),
633 ..Default::default()
634 };
635 
636 let complete = rq.push(chunk).expect("chunk to be queued");
637 assert!(!complete, "chunk set should not be complete yet");
638 assert_eq!(10, rq.get_num_bytes(), "num bytes mismatch");
639 
640 let chunk = ChunkPayloadData {
641 payload_type: org_ppi,
642 unordered: true,
643 beginning_fragment: true,
644 ending_fragment: true,
645 tsn: 13,
646 stream_sequence_number: 1,
647 user_data: Bytes::from_static(b"GOOD"),
648 ..Default::default()
649 };
650 
651 let complete = rq.push(chunk).expect("chunk to be queued");
652 assert!(complete, "chunk set should be complete");
653 assert_eq!(14, rq.get_num_bytes(), "num bytes mismatch");
654 
655 //
656 // Now we have two complete chunks ready to read in the reassemblyQueue.
657 //
658 
659 let mut buf = vec![0u8; 16];
660 
661 // Should pick the one that has "GOOD"
662 if let Some(chunks) = rq.read() {
663 let n = chunks.read(&mut buf)?;
664 assert_eq!(4, n, "should receive 4 bytes");
665 assert_eq!(10, rq.get_num_bytes(), "num bytes mismatch");
666 assert_eq!(chunks.ppi, org_ppi, "should have valid ppi");
667 assert_eq!(&buf[..n], b"GOOD", "data should match");
668 } else {
669 panic!();
670 }
671 
672 Ok(())
673}
674 
675#[test]
676fn test_reassembly_queue_ignores_chunk_with_wrong_si() -> Result<()> {
677 let mut rq = ReassemblyQueue::new(123, 65536);
678 
679 let org_ppi = PayloadProtocolIdentifier::Binary;
680 
681 let chunk = ChunkPayloadData {
682 payload_type: org_ppi,
683 stream_identifier: 124,
684 beginning_fragment: true,
685 ending_fragment: true,
686 tsn: 10,
687 stream_sequence_number: 0,
688 user_data: Bytes::from_static(b"IN"),
689 ..Default::default()
690 };
691 
692 let complete = rq.push(chunk).expect("chunk to be queued");
693 assert!(!complete, "chunk should be ignored");
694 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
695 Ok(())
696}
697 
698#[test]
699fn test_reassembly_queue_ignores_chunk_with_stale_ssn() -> Result<()> {
700 let mut rq = ReassemblyQueue::new(0, 65536);
701 rq.next_ssn = 7; // forcibly set expected SSN to 7
702 
703 let org_ppi = PayloadProtocolIdentifier::Binary;
704 
705 let chunk = ChunkPayloadData {
706 payload_type: org_ppi,
707 beginning_fragment: true,
708 ending_fragment: true,
709 tsn: 10,
710 stream_sequence_number: 6, // <-- stale
711 user_data: Bytes::from_static(b"IN"),
712 ..Default::default()
713 };
714 
715 let complete = rq.push(chunk).expect("chunk to be queued");
716 assert!(!complete, "chunk should not be ignored");
717 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
718 
719 Ok(())
720}
721 
722#[test]
723fn test_reassembly_queue_should_fail_to_read_incomplete_chunk() -> Result<()> {
724 let mut rq = ReassemblyQueue::new(0, 65536);
725 
726 let org_ppi = PayloadProtocolIdentifier::Binary;
727 
728 let chunk = ChunkPayloadData {
729 payload_type: org_ppi,
730 beginning_fragment: true,
731 tsn: 123,
732 stream_sequence_number: 0,
733 user_data: Bytes::from_static(b"IN"),
734 ..Default::default()
735 };
736 
737 let complete = rq.push(chunk).expect("chunk to be queued");
738 assert!(!complete, "the set should not be complete");
739 assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
740 
741 let result = rq.read();
742 assert!(result.is_none(), "read() should not succeed");
743 assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
744 
745 Ok(())
746}
747 
748#[test]
749fn test_reassembly_queue_should_fail_to_read_if_the_nex_ssn_is_not_ready() -> Result<()> {
750 let mut rq = ReassemblyQueue::new(0, 65536);
751 
752 let org_ppi = PayloadProtocolIdentifier::Binary;
753 
754 let chunk = ChunkPayloadData {
755 payload_type: org_ppi,
756 beginning_fragment: true,
757 ending_fragment: true,
758 tsn: 123,
759 stream_sequence_number: 1,
760 user_data: Bytes::from_static(b"IN"),
761 ..Default::default()
762 };
763 
764 let complete = rq.push(chunk).expect("chunk to be queued");
765 assert!(complete, "the set should be complete");
766 assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
767 
768 let result = rq.read();
769 assert!(result.is_none(), "read() should not succeed");
770 assert_eq!(2, rq.get_num_bytes(), "num bytes mismatch");
771 
772 Ok(())
773}
774 
775#[test]
776fn test_reassembly_queue_detect_buffer_too_short() -> Result<()> {
777 let mut rq = ReassemblyQueue::new(0, 65536);
778 
779 let org_ppi = PayloadProtocolIdentifier::Binary;
780 
781 let chunk = ChunkPayloadData {
782 payload_type: org_ppi,
783 beginning_fragment: true,
784 ending_fragment: true,
785 tsn: 123,
786 stream_sequence_number: 0,
787 user_data: Bytes::from_static(b"0123456789"),
788 ..Default::default()
789 };
790 
791 let complete = rq.push(chunk).expect("chunk to be queued");
792 assert!(complete, "the set should be complete");
793 assert_eq!(10, rq.get_num_bytes(), "num bytes mismatch");
794 
795 let mut buf = vec![0u8; 8]; // <- passing buffer too short
796 if let Some(chunks) = rq.read() {
797 let result = chunks.read(&mut buf);
798 assert!(result.is_err(), "read() should not succeed");
799 if let Err(err) = result {
800 assert_eq!(Error::ErrShortBuffer, err, "read() should not succeed");
801 }
802 assert_eq!(0, rq.get_num_bytes(), "num bytes mismatch");
803 } else {
804 panic!();
805 }
806 
807 Ok(())
808}
809 
810#[test]
811fn test_reassembly_queue_forward_tsn_for_ordered_framents() -> Result<()> {
812 let mut rq = ReassemblyQueue::new(0, 65536);
813 
814 let org_ppi = PayloadProtocolIdentifier::Binary;
815 
816 let ssn_complete = 5u16;
817 let ssn_dropped = 6u16;
818 
819 let chunk = ChunkPayloadData {
820 payload_type: org_ppi,
821 beginning_fragment: true,
822 ending_fragment: true,
823 tsn: 10,
824 stream_sequence_number: ssn_complete,
825 user_data: Bytes::from_static(b"123"),
826 ..Default::default()
827 };
828 
829 let complete = rq.push(chunk).expect("chunk to be queued");
830 assert!(complete, "chunk set should be complete");
831 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
832 
833 let chunk = ChunkPayloadData {
834 payload_type: org_ppi,
835 beginning_fragment: true,
836 tsn: 11,
837 stream_sequence_number: ssn_dropped,
838 user_data: Bytes::from_static(b"ABC"),
839 ..Default::default()
840 };
841 
842 let complete = rq.push(chunk).expect("chunk to be queued");
843 assert!(!complete, "chunk set should not be complete yet");
844 assert_eq!(6, rq.get_num_bytes(), "num bytes mismatch");
845 
846 let chunk = ChunkPayloadData {
847 payload_type: org_ppi,
848 tsn: 12,
849 stream_sequence_number: ssn_dropped,
850 user_data: Bytes::from_static(b"DEF"),
851 ..Default::default()
852 };
853 
854 let complete = rq.push(chunk).expect("chunk to be queued");
855 assert!(!complete, "chunk set should not be complete yet");
856 assert_eq!(9, rq.get_num_bytes(), "num bytes mismatch");
857 
858 rq.forward_tsn_for_ordered(ssn_dropped);
859 
860 assert_eq!(1, rq.ordered.len(), "there should be one chunk left");
861 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
862 
863 Ok(())
864}
865 
866#[test]
867fn test_reassembly_queue_forward_tsn_for_unordered_framents() -> Result<()> {
868 let mut rq = ReassemblyQueue::new(0, 65536);
869 
870 let org_ppi = PayloadProtocolIdentifier::Binary;
871 
872 let ssn_dropped = 6u16;
873 let ssn_kept = 7u16;
874 
875 let chunk = ChunkPayloadData {
876 payload_type: org_ppi,
877 unordered: true,
878 beginning_fragment: true,
879 tsn: 11,
880 stream_sequence_number: ssn_dropped,
881 user_data: Bytes::from_static(b"ABC"),
882 ..Default::default()
883 };
884 
885 let complete = rq.push(chunk).expect("chunk to be queued");
886 assert!(!complete, "chunk set should not be complete yet");
887 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
888 
889 let chunk = ChunkPayloadData {
890 payload_type: org_ppi,
891 unordered: true,
892 tsn: 12,
893 stream_sequence_number: ssn_dropped,
894 user_data: Bytes::from_static(b"DEF"),
895 ..Default::default()
896 };
897 
898 let complete = rq.push(chunk).expect("chunk to be queued");
899 assert!(!complete, "chunk set should not be complete yet");
900 assert_eq!(6, rq.get_num_bytes(), "num bytes mismatch");
901 
902 let chunk = ChunkPayloadData {
903 payload_type: org_ppi,
904 unordered: true,
905 tsn: 14,
906 beginning_fragment: true,
907 stream_sequence_number: ssn_kept,
908 user_data: Bytes::from_static(b"SOS"),
909 ..Default::default()
910 };
911 
912 let complete = rq.push(chunk).expect("chunk to be queued");
913 assert!(!complete, "chunk set should not be complete yet");
914 assert_eq!(9, rq.get_num_bytes(), "num bytes mismatch");
915 
916 // At this point, there are 3 chunks in the rq.unorderedChunks.
917 // This call should remove chunks with tsn equals to 13 or older.
918 rq.forward_tsn_for_unordered(13);
919 
920 // As a result, there should be one chunk (tsn=14)
921 assert_eq!(
922 1,
923 rq.unordered_chunks.len(),
924 "there should be one chunk kept"
925 );
926 assert_eq!(3, rq.get_num_bytes(), "num bytes mismatch");
927 
928 Ok(())
929}
930 
931#[test]
932fn test_chunk_set_empty_chunk_set() -> Result<()> {
933 let cset = Chunks::new(0, PayloadProtocolIdentifier::default(), vec![]);
934 assert!(!cset.is_complete(), "empty chunkSet cannot be complete");
935 Ok(())
936}
937 
938#[test]
939fn test_chunk_set_push_dup_chunks_to_chunk_set() -> Result<()> {
940 let mut cset = Chunks::new(0, PayloadProtocolIdentifier::default(), vec![]);
941 cset.push(ChunkPayloadData {
942 tsn: 100,
943 beginning_fragment: true,
944 ..Default::default()
945 });
946 let complete = cset.push(ChunkPayloadData {
947 tsn: 100,
948 ending_fragment: true,
949 ..Default::default()
950 });
951 assert!(!complete, "chunk with dup TSN is not complete");
952 assert_eq!(1, cset.chunks.len(), "chunk with dup TSN should be ignored");
953 Ok(())
954}
955 
956#[test]
957fn test_chunk_set_incomplete_chunk_set_no_beginning() -> Result<()> {
958 let cset = Chunks::new(0, PayloadProtocolIdentifier::default(), vec![]);
959 assert!(
960 !cset.is_complete(),
961 "chunkSet not starting with B=1 cannot be complete"
962 );
963 Ok(())
964}
965 
966#[test]
967fn test_chunk_set_incomplete_chunk_set_no_contiguous_tsn() -> Result<()> {
968 let cset = Chunks::new(
969 0,
970 PayloadProtocolIdentifier::default(),
971 vec![
972 ChunkPayloadData {
973 tsn: 100,
974 beginning_fragment: true,
975 ..Default::default()
976 },
977 ChunkPayloadData {
978 tsn: 101,
979 ..Default::default()
980 },
981 ChunkPayloadData {
982 tsn: 103,
983 ending_fragment: true,
984 ..Default::default()
985 },
986 ],
987 );
988 assert!(
989 !cset.is_complete(),
990 "chunkSet not starting with incontiguous tsn cannot be complete"
991 );
992 Ok(())
993}
994 
995#[test]
996fn test_reassembly_queue_ssn_overflow() -> Result<()> {
997 let mut rq = ReassemblyQueue::new(0, 65536);
998 let org_ppi = PayloadProtocolIdentifier::Binary;
999 
1000 for stream_sequence_number in 0..=u16::MAX {
1001 let chunk = ChunkPayloadData {
1002 payload_type: org_ppi,
1003 beginning_fragment: true,
1004 ending_fragment: true,
1005 tsn: 10,
1006 stream_sequence_number,
1007 user_data: Bytes::from_static(b"123"),
1008 ..Default::default()
1009 };
1010 assert!(rq.push(chunk).expect("chunk to be queued"));
1011 assert!(rq.read().is_some());
1012 }
1013 
1014 Ok(())
1015}
1016 
1017#[test]
1018fn test_reassembly_queue_ssn_overflow_in_forward_tsn_for_ordered() -> Result<()> {
1019 let mut rq = ReassemblyQueue::new(0, 65536);
1020 let org_ppi = PayloadProtocolIdentifier::Binary;
1021 
1022 for stream_sequence_number in 0..u16::MAX {
1023 let chunk = ChunkPayloadData {
1024 payload_type: org_ppi,
1025 beginning_fragment: true,
1026 ending_fragment: true,
1027 tsn: 10,
1028 stream_sequence_number,
1029 user_data: Bytes::from_static(b"123"),
1030 ..Default::default()
1031 };
1032 assert!(rq.push(chunk).expect("chunk to be queued"));
1033 assert!(rq.read().is_some());
1034 }
1035 rq.forward_tsn_for_ordered(u16::MAX);
1036 
1037 Ok(())
1038}
1039 
1040#[test]
1041fn test_chunk_set_wrap() {
1042 let cset = Chunks::new(
1043 0,
1044 PayloadProtocolIdentifier::default(),
1045 vec![
1046 ChunkPayloadData {
1047 tsn: u32::MAX - 1,
1048 beginning_fragment: true,
1049 ..Default::default()
1050 },
1051 ChunkPayloadData {
1052 tsn: u32::MAX,
1053 ..Default::default()
1054 },
1055 ChunkPayloadData {
1056 tsn: 0,
1057 ending_fragment: true,
1058 ..Default::default()
1059 },
1060 ],
1061 );
1062 
1063 assert!(
1064 cset.is_complete(),
1065 "chunkSet with wrapping TSNs is not complete"
1066 );
1067}
1068 
1069#[test]
1070fn test_reassembly_queue_wrap_find_complete() {
1071 let mut rq = ReassemblyQueue::new(0, 65535);
1072 
1073 assert!(
1074 rq.push(ChunkPayloadData {
1075 tsn: u32::MAX - 1,
1076 unordered: true,
1077 beginning_fragment: true,
1078 ..Default::default()
1079 })
1080 .is_ok()
1081 );
1082 assert!(
1083 rq.push(ChunkPayloadData {
1084 tsn: u32::MAX,
1085 unordered: true,
1086 ..Default::default()
1087 })
1088 .is_ok()
1089 );
1090 assert!(
1091 rq.push(ChunkPayloadData {
1092 tsn: 0,
1093 unordered: true,
1094 ending_fragment: true,
1095 ..Default::default()
1096 })
1097 .is_ok()
1098 );
1099 
1100 assert_eq!(
1101 rq.unordered.len(),
1102 1,
1103 "chunkSet with wrapping TSNs is not complete"
1104 );
1105}
1106 
1107#[test]
1108fn test_reassembly_queue_max_message_size() {
1109 let mut rq = ReassemblyQueue::new(0, 65536);
1110 rq.max_message_size = 15;
1111 
1112 assert_eq!(
1113 rq.push(ChunkPayloadData {
1114 tsn: 100,
1115 beginning_fragment: true,
1116 unordered: true,
1117 user_data: Bytes::from_owner([0; 5]),
1118 ..Default::default()
1119 }),
1120 Ok(false)
1121 );
1122 assert_eq!(
1123 rq.push(ChunkPayloadData {
1124 tsn: 102,
1125 ending_fragment: true,
1126 unordered: true,
1127 user_data: Bytes::from_owner([0; 5]),
1128 ..Default::default()
1129 }),
1130 Ok(false)
1131 );
1132 assert_eq!(
1133 rq.push(ChunkPayloadData {
1134 tsn: 103,
1135 beginning_fragment: true,
1136 unordered: true,
1137 user_data: Bytes::from_owner([0; 5]),
1138 ..Default::default()
1139 }),
1140 Ok(false)
1141 );
1142 assert_eq!(
1143 rq.push(ChunkPayloadData {
1144 tsn: 104,
1145 unordered: true,
1146 user_data: Bytes::from_owner([0; 5]),
1147 ..Default::default()
1148 }),
1149 Ok(false)
1150 );
1151 assert_eq!(
1152 rq.push(ChunkPayloadData {
1153 tsn: 101,
1154 unordered: true,
1155 user_data: Bytes::from_owner([0; 5]),
1156 ..Default::default()
1157 }),
1158 Ok(true)
1159 );
1160}