xref: /webrtc/sctp/src/chunk/chunk_test.rs (revision 6ac0fffd)
1 use super::*;
2 
3 ///////////////////////////////////////////////////////////////////
4 //chunk_type_test
5 ///////////////////////////////////////////////////////////////////
6 use super::chunk_type::*;
7 
8 #[test]
9 fn test_chunk_type_string() -> Result<()> {
10     let tests = vec![
11         (CT_PAYLOAD_DATA, "DATA"),
12         (CT_INIT, "INIT"),
13         (CT_INIT_ACK, "INIT-ACK"),
14         (CT_SACK, "SACK"),
15         (CT_HEARTBEAT, "HEARTBEAT"),
16         (CT_HEARTBEAT_ACK, "HEARTBEAT-ACK"),
17         (CT_ABORT, "ABORT"),
18         (CT_SHUTDOWN, "SHUTDOWN"),
19         (CT_SHUTDOWN_ACK, "SHUTDOWN-ACK"),
20         (CT_ERROR, "ERROR"),
21         (CT_COOKIE_ECHO, "COOKIE-ECHO"),
22         (CT_COOKIE_ACK, "COOKIE-ACK"),
23         (CT_ECNE, "ECNE"),
24         (CT_CWR, "CWR"),
25         (CT_SHUTDOWN_COMPLETE, "SHUTDOWN-COMPLETE"),
26         (CT_RECONFIG, "RECONFIG"),
27         (CT_FORWARD_TSN, "FORWARD-TSN"),
28         (ChunkType(255), "Unknown ChunkType: 255"),
29     ];
30 
31     for (ct, expected) in tests {
32         assert_eq!(
33             ct.to_string(),
34             expected,
35             "failed to stringify chunkType {}, expected {}",
36             ct,
37             expected
38         );
39     }
40 
41     Ok(())
42 }
43 
44 ///////////////////////////////////////////////////////////////////
45 //chunk_abort_test
46 ///////////////////////////////////////////////////////////////////
47 use super::chunk_abort::*;
48 use crate::error_cause::*;
49 
50 #[test]
51 fn test_abort_chunk_one_error_cause() -> Result<()> {
52     let abort1 = ChunkAbort {
53         error_causes: vec![ErrorCause {
54             code: PROTOCOL_VIOLATION,
55             ..Default::default()
56         }],
57     };
58 
59     let b = abort1.marshal()?;
60     let abort2 = ChunkAbort::unmarshal(&b)?;
61 
62     assert_eq!(1, abort2.error_causes.len(), "should have only one cause");
63     assert_eq!(
64         abort1.error_causes[0].error_cause_code(),
65         abort2.error_causes[0].error_cause_code(),
66         "errorCause code should match"
67     );
68 
69     Ok(())
70 }
71 
72 #[test]
73 fn test_abort_chunk_many_error_causes() -> Result<()> {
74     let abort1 = ChunkAbort {
75         error_causes: vec![
76             ErrorCause {
77                 code: INVALID_MANDATORY_PARAMETER,
78                 ..Default::default()
79             },
80             ErrorCause {
81                 code: UNRECOGNIZED_CHUNK_TYPE,
82                 ..Default::default()
83             },
84             ErrorCause {
85                 code: PROTOCOL_VIOLATION,
86                 ..Default::default()
87             },
88         ],
89     };
90 
91     let b = abort1.marshal()?;
92     let abort2 = ChunkAbort::unmarshal(&b)?;
93     assert_eq!(3, abort2.error_causes.len(), "should have only one cause");
94     for (i, error_cause) in abort1.error_causes.iter().enumerate() {
95         assert_eq!(
96             error_cause.error_cause_code(),
97             abort2.error_causes[i].error_cause_code(),
98             "errorCause code should match"
99         );
100     }
101 
102     Ok(())
103 }
104 
105 ///////////////////////////////////////////////////////////////////
106 //chunk_error_test
107 ///////////////////////////////////////////////////////////////////
108 use super::chunk_error::*;
109 use bytes::BufMut;
110 use lazy_static::lazy_static;
111 
112 const CHUNK_FLAGS: u8 = 0x00;
113 static ORG_UNRECOGNIZED_CHUNK: Bytes =
114     Bytes::from_static(&[0xc0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x3]);
115 
116 lazy_static! {
117     static ref RAW_IN: Bytes = {
118         let mut raw = BytesMut::new();
119         raw.put_u8(CT_ERROR.0);
120         raw.put_u8(CHUNK_FLAGS);
121         raw.extend(vec![0x00, 0x10, 0x00, 0x06, 0x00, 0x0c]);
122         raw.extend(ORG_UNRECOGNIZED_CHUNK.clone());
123         raw.freeze()
124     };
125 }
126 
127 #[test]
128 fn test_chunk_error_unrecognized_chunk_type_unmarshal() -> Result<()> {
129     let c = ChunkError::unmarshal(&RAW_IN)?;
130     assert_eq!(CT_ERROR, c.header().typ, "chunk type should be ERROR");
131     assert_eq!(1, c.error_causes.len(), "there should be on errorCause");
132 
133     let ec = &c.error_causes[0];
134     assert_eq!(
135         UNRECOGNIZED_CHUNK_TYPE,
136         ec.error_cause_code(),
137         "cause code should be unrecognizedChunkType"
138     );
139     assert_eq!(
140         ec.raw, ORG_UNRECOGNIZED_CHUNK,
141         "should have valid unrecognizedChunk"
142     );
143 
144     Ok(())
145 }
146 
147 #[test]
148 fn test_chunk_error_unrecognized_chunk_type_marshal() -> Result<()> {
149     let ec_unrecognized_chunk_type = ErrorCause {
150         code: UNRECOGNIZED_CHUNK_TYPE,
151         raw: ORG_UNRECOGNIZED_CHUNK.clone(),
152     };
153 
154     let ec = ChunkError {
155         error_causes: vec![ec_unrecognized_chunk_type],
156     };
157 
158     let raw = ec.marshal()?;
159     assert_eq!(raw, *RAW_IN, "unexpected serialization result");
160 
161     Ok(())
162 }
163 
164 #[test]
165 fn test_chunk_error_unrecognized_chunk_type_marshal_with_cause_value_being_nil() -> Result<()> {
166     let expected =
167         Bytes::from_static(&[CT_ERROR.0, CHUNK_FLAGS, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04]);
168     let ec_unrecognized_chunk_type = ErrorCause {
169         code: UNRECOGNIZED_CHUNK_TYPE,
170         ..Default::default()
171     };
172 
173     let ec = ChunkError {
174         error_causes: vec![ec_unrecognized_chunk_type],
175     };
176 
177     let raw = ec.marshal()?;
178     assert_eq!(raw, expected, "unexpected serialization result");
179 
180     Ok(())
181 }
182 
183 ///////////////////////////////////////////////////////////////////
184 //chunk_forward_tsn_test
185 ///////////////////////////////////////////////////////////////////
186 use super::chunk_forward_tsn::*;
187 
188 static CHUNK_FORWARD_TSN_BYTES: Bytes =
189     Bytes::from_static(&[0xc0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x3]);
190 
191 #[test]
192 fn test_chunk_forward_tsn_success() -> Result<()> {
193     let tests = vec![
194         CHUNK_FORWARD_TSN_BYTES.clone(),
195         Bytes::from_static(&[0xc0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5]),
196         Bytes::from_static(&[
197             0xc0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7,
198         ]),
199     ];
200 
201     for binary in tests {
202         let actual = ChunkForwardTsn::unmarshal(&binary)?;
203         let b = actual.marshal()?;
204         assert_eq!(binary, b, "test not equal");
205     }
206 
207     Ok(())
208 }
209 
210 #[test]
211 fn test_chunk_forward_tsn_unmarshal_failure() -> Result<()> {
212     let tests = vec![
213         ("chunk header to short", Bytes::from_static(&[0xc0])),
214         (
215             "missing New Cumulative TSN",
216             Bytes::from_static(&[0xc0, 0x0, 0x0, 0x4]),
217         ),
218         (
219             "missing stream sequence",
220             Bytes::from_static(&[
221                 0xc0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6,
222             ]),
223         ),
224     ];
225 
226     for (name, binary) in tests {
227         let result = ChunkForwardTsn::unmarshal(&binary);
228         assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
229     }
230 
231     Ok(())
232 }
233 
234 ///////////////////////////////////////////////////////////////////
235 //chunk_reconfig_test
236 ///////////////////////////////////////////////////////////////////
237 use super::chunk_reconfig::*;
238 
239 static TEST_CHUNK_RECONFIG_PARAM_A: Bytes = Bytes::from_static(&[
240     0x0, 0xd, 0x0, 0x16, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0,
241     0x5, 0x0, 0x6,
242 ]);
243 
244 static TEST_CHUNK_RECONFIG_PARAM_B: Bytes = Bytes::from_static(&[
245     0x0, 0xd, 0x0, 0x10, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3,
246 ]);
247 
248 static TEST_CHUNK_RECONFIG_RESPONCE: Bytes =
249     Bytes::from_static(&[0x0, 0x10, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1]);
250 
251 lazy_static! {
252     static ref TEST_CHUNK_RECONFIG_BYTES: Vec<Bytes> = {
253         let mut tests = vec![];
254         {
255             let mut test = BytesMut::new();
256             test.extend(vec![0x82, 0x0, 0x0, 0x1a]);
257             test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
258             tests.push(test.freeze());
259         }
260         {
261             let mut test = BytesMut::new();
262             test.extend(vec![0x82, 0x0, 0x0, 0x14]);
263             test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
264             tests.push(test.freeze());
265         }
266         {
267             let mut test = BytesMut::new();
268             test.extend(vec![0x82, 0x0, 0x0, 0x10]);
269             test.extend(TEST_CHUNK_RECONFIG_RESPONCE.clone());
270             tests.push(test.freeze());
271         }
272         {
273             let mut test = BytesMut::new();
274             test.extend(vec![0x82, 0x0, 0x0, 0x2c]);
275             test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
276             test.extend(vec![0u8; 2]);
277             test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
278             tests.push(test.freeze());
279         }
280         {
281             let mut test = BytesMut::new();
282             test.extend(vec![0x82, 0x0, 0x0, 0x2a]);
283             test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
284             test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
285             tests.push(test.freeze());
286         }
287 
288         tests
289     };
290 }
291 
292 #[test]
293 fn test_chunk_reconfig_success() -> Result<()> {
294     for (i, binary) in TEST_CHUNK_RECONFIG_BYTES.iter().enumerate() {
295         let actual = ChunkReconfig::unmarshal(binary)?;
296         let b = actual.marshal()?;
297         assert_eq!(*binary, b, "test {} not equal: {:?} vs {:?}", i, *binary, b);
298     }
299 
300     Ok(())
301 }
302 
303 #[test]
304 fn test_chunk_reconfig_unmarshal_failure() -> Result<()> {
305     let mut test = BytesMut::new();
306     test.extend(vec![0x82, 0x0, 0x0, 0x18]);
307     test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
308     test.extend(vec![0x0, 0xd, 0x0, 0x0]);
309     let tests = vec![
310         ("chunk header to short", Bytes::from_static(&[0x82])),
311         (
312             "missing parse param type (A)",
313             Bytes::from_static(&[0x82, 0x0, 0x0, 0x4]),
314         ),
315         (
316             "wrong param (A)",
317             Bytes::from_static(&[0x82, 0x0, 0x0, 0x8, 0x0, 0xd, 0x0, 0x0]),
318         ),
319         ("wrong param (B)", test.freeze()),
320     ];
321 
322     for (name, binary) in tests {
323         let result = ChunkReconfig::unmarshal(&binary);
324         assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
325     }
326 
327     Ok(())
328 }
329 
330 ///////////////////////////////////////////////////////////////////
331 //chunk_shutdown_test
332 ///////////////////////////////////////////////////////////////////
333 use super::chunk_shutdown::*;
334 
335 #[test]
336 fn test_chunk_shutdown_success() -> Result<()> {
337     let tests = vec![Bytes::from_static(&[
338         0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78,
339     ])];
340 
341     for binary in tests {
342         let actual = ChunkShutdown::unmarshal(&binary)?;
343         let b = actual.marshal()?;
344         assert_eq!(binary, b, "test not equal");
345     }
346 
347     Ok(())
348 }
349 
350 #[test]
351 fn test_chunk_shutdown_failure() -> Result<()> {
352     let tests = vec![
353         (
354             "length too short",
355             Bytes::from_static(&[0x07, 0x00, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78]),
356         ),
357         (
358             "length too long",
359             Bytes::from_static(&[0x07, 0x00, 0x00, 0x09, 0x12, 0x34, 0x56, 0x78]),
360         ),
361         (
362             "payload too short",
363             Bytes::from_static(&[0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56]),
364         ),
365         (
366             "payload too long",
367             Bytes::from_static(&[0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78, 0x9f]),
368         ),
369         (
370             "invalid type",
371             Bytes::from_static(&[0x08, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78]),
372         ),
373     ];
374 
375     for (name, binary) in tests {
376         let result = ChunkShutdown::unmarshal(&binary);
377         assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
378     }
379 
380     Ok(())
381 }
382 
383 ///////////////////////////////////////////////////////////////////
384 //chunk_shutdown_ack_test
385 ///////////////////////////////////////////////////////////////////
386 use super::chunk_shutdown_ack::*;
387 
388 #[test]
389 fn test_chunk_shutdown_ack_success() -> Result<()> {
390     let tests = vec![Bytes::from_static(&[0x08, 0x00, 0x00, 0x04])];
391 
392     for binary in tests {
393         let actual = ChunkShutdownAck::unmarshal(&binary)?;
394         let b = actual.marshal()?;
395         assert_eq!(binary, b, "test not equal");
396     }
397 
398     Ok(())
399 }
400 
401 #[test]
402 fn test_chunk_shutdown_ack_failure() -> Result<()> {
403     let tests = vec![
404         ("length too short", Bytes::from_static(&[0x08, 0x00, 0x00])),
405         (
406             "length too long",
407             Bytes::from_static(&[0x08, 0x00, 0x00, 0x04, 0x12]),
408         ),
409         (
410             "invalid type",
411             Bytes::from_static(&[0x0f, 0x00, 0x00, 0x04]),
412         ),
413     ];
414 
415     for (name, binary) in tests {
416         let result = ChunkShutdownAck::unmarshal(&binary);
417         assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
418     }
419 
420     Ok(())
421 }
422 
423 ///////////////////////////////////////////////////////////////////
424 //chunk_shutdown_complete_test
425 ///////////////////////////////////////////////////////////////////
426 use super::chunk_shutdown_complete::*;
427 
428 #[test]
429 fn test_chunk_shutdown_complete_success() -> Result<()> {
430     let tests = vec![Bytes::from_static(&[0x0e, 0x00, 0x00, 0x04])];
431 
432     for binary in tests {
433         let actual = ChunkShutdownComplete::unmarshal(&binary)?;
434         let b = actual.marshal()?;
435         assert_eq!(binary, b, "test not equal");
436     }
437 
438     Ok(())
439 }
440 
441 #[test]
442 fn test_chunk_shutdown_complete_failure() -> Result<()> {
443     let tests = vec![
444         ("length too short", Bytes::from_static(&[0x0e, 0x00, 0x00])),
445         (
446             "length too long",
447             Bytes::from_static(&[0x0e, 0x00, 0x00, 0x04, 0x12]),
448         ),
449         (
450             "invalid type",
451             Bytes::from_static(&[0x0f, 0x00, 0x00, 0x04]),
452         ),
453     ];
454 
455     for (name, binary) in tests {
456         let result = ChunkShutdownComplete::unmarshal(&binary);
457         assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
458     }
459 
460     Ok(())
461 }
462 
463 ///////////////////////////////////////////////////////////////////
464 //chunk_test
465 ///////////////////////////////////////////////////////////////////
466 use crate::chunk::chunk_init::*;
467 use crate::chunk::chunk_payload_data::*;
468 use crate::chunk::chunk_selective_ack::ChunkSelectiveAck;
469 use crate::packet::*;
470 use crate::param::param_outgoing_reset_request::ParamOutgoingResetRequest;
471 use crate::param::param_state_cookie::*;
472 
473 #[test]
474 fn test_init_chunk() -> Result<()> {
475     let raw_pkt = Bytes::from_static(&[
476         0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0x81, 0x46, 0x9d, 0xfc, 0x01, 0x00, 0x00,
477         0x56, 0x55, 0xb9, 0x64, 0xa5, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe8, 0x6d,
478         0x10, 0x30, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
479         0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x9f, 0xeb, 0xbb, 0x5c, 0x50, 0xc9, 0xbf, 0x75,
480         0x9c, 0xb1, 0x2c, 0x57, 0x4f, 0xa4, 0x5a, 0x51, 0xba, 0x60, 0x17, 0x78, 0x27, 0x94, 0x5c,
481         0x31, 0xe6, 0x5d, 0x5b, 0x09, 0x47, 0xe2, 0x22, 0x06, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
482         0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00,
483     ]);
484     let pkt = Packet::unmarshal(&raw_pkt)?;
485 
486     if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkInit>() {
487         assert_eq!(
488             c.initiate_tag, 1438213285,
489             "Unmarshal passed for SCTP packet, but got incorrect initiate tag exp: {} act: {}",
490             1438213285, c.initiate_tag
491         );
492         assert_eq!(c.advertised_receiver_window_credit, 131072, "Unmarshal passed for SCTP packet, but got incorrect advertisedReceiverWindowCredit exp: {} act: {}", 131072, c.advertised_receiver_window_credit);
493         assert_eq!(c.num_outbound_streams, 1024, "Unmarshal passed for SCTP packet, but got incorrect numOutboundStreams tag exp:{} act: {}", 1024, c.num_outbound_streams);
494         assert_eq!(
495             c.num_inbound_streams, 2048,
496             "Unmarshal passed for SCTP packet, but got incorrect numInboundStreams exp: {} act: {}",
497             2048, c.num_inbound_streams
498         );
499         assert_eq!(
500             c.initial_tsn, 3899461680u32,
501             "Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: {} act: {}",
502             3899461680u32, c.initial_tsn
503         );
504     } else {
505         assert!(false, "Failed to cast Chunk -> Init");
506     }
507 
508     Ok(())
509 }
510 
511 #[test]
512 fn test_init_ack() -> Result<()> {
513     let raw_pkt = Bytes::from_static(&[
514         0x13, 0x88, 0x13, 0x88, 0xce, 0x15, 0x79, 0xa2, 0x96, 0x19, 0xe8, 0xb2, 0x02, 0x00, 0x00,
515         0x1c, 0xeb, 0x81, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x50, 0xdf,
516         0x90, 0xd9, 0x00, 0x07, 0x00, 0x08, 0x94, 0x06, 0x2f, 0x93,
517     ]);
518     let pkt = Packet::unmarshal(&raw_pkt)?;
519     assert!(
520         pkt.chunks[0].as_any().downcast_ref::<ChunkInit>().is_some(),
521         "Failed to cast Chunk -> Init"
522     );
523 
524     Ok(())
525 }
526 
527 #[test]
528 fn test_chrome_chunk1_init() -> Result<()> {
529     let raw_pkt = Bytes::from_static(&[
530         0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb3, 0x45, 0xa2, 0x01, 0x00, 0x00,
531         0x56, 0xce, 0x15, 0x79, 0xa2, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x94, 0x57,
532         0x95, 0xc0, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
533         0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0xff, 0x5c, 0x49, 0x19, 0x4a, 0x94, 0xe8, 0x2a,
534         0xec, 0x58, 0x55, 0x62, 0x29, 0x1f, 0x8e, 0x23, 0xcd, 0x7c, 0xe8, 0x46, 0xba, 0x58, 0x1b,
535         0x3d, 0xab, 0xd7, 0x7e, 0x50, 0xf2, 0x41, 0xb1, 0x2e, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
536         0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00,
537     ]);
538     let pkt = Packet::unmarshal(&raw_pkt)?;
539     let raw_pkt2 = pkt.marshal()?;
540     assert_eq!(raw_pkt, raw_pkt2);
541 
542     Ok(())
543 }
544 
545 #[test]
546 fn test_chrome_chunk2_init_ack() -> Result<()> {
547     let raw_pkt = Bytes::from_static(&[
548         0x13, 0x88, 0x13, 0x88, 0xce, 0x15, 0x79, 0xa2, 0xb5, 0xdb, 0x2d, 0x93, 0x02, 0x00, 0x01,
549         0x90, 0x9b, 0xd5, 0xb3, 0x6f, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0xef, 0xb4,
550         0x72, 0x87, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
551         0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x2e, 0xf9, 0x9c, 0x10, 0x63, 0x72, 0xed, 0x0d,
552         0x33, 0xc2, 0xdc, 0x7f, 0x9f, 0xd7, 0xef, 0x1b, 0xc9, 0xc4, 0xa7, 0x41, 0x9a, 0x07, 0x68,
553         0x6b, 0x66, 0xfb, 0x6a, 0x4e, 0x32, 0x5d, 0xe4, 0x25, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
554         0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00, 0x00, 0x07, 0x01, 0x38, 0x4b,
555         0x41, 0x4d, 0x45, 0x2d, 0x42, 0x53, 0x44, 0x20, 0x31, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00,
556         0x9c, 0x1e, 0x49, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x42, 0x06, 0x00, 0x00, 0x00, 0x00,
557         0x00, 0x60, 0xea, 0x00, 0x00, 0xc4, 0x13, 0x3d, 0xe9, 0x86, 0xb1, 0x85, 0x75, 0xa2, 0x79,
558         0x15, 0xce, 0x9b, 0xd5, 0xb3, 0x6f, 0x20, 0xe0, 0x9f, 0x89, 0xe0, 0x27, 0x00, 0x00, 0x00,
559         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x9f, 0x89,
560         0xe0, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
561         0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
562         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x56, 0xce, 0x15, 0x79, 0xa2, 0x00,
563         0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x94, 0x57, 0x95, 0xc0, 0xc0, 0x00, 0x00, 0x04,
564         0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00,
565         0x24, 0xff, 0x5c, 0x49, 0x19, 0x4a, 0x94, 0xe8, 0x2a, 0xec, 0x58, 0x55, 0x62, 0x29, 0x1f,
566         0x8e, 0x23, 0xcd, 0x7c, 0xe8, 0x46, 0xba, 0x58, 0x1b, 0x3d, 0xab, 0xd7, 0x7e, 0x50, 0xf2,
567         0x41, 0xb1, 0x2e, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x06,
568         0x80, 0xc1, 0x00, 0x00, 0x02, 0x00, 0x01, 0x90, 0x9b, 0xd5, 0xb3, 0x6f, 0x00, 0x02, 0x00,
569         0x00, 0x04, 0x00, 0x08, 0x00, 0xef, 0xb4, 0x72, 0x87, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08,
570         0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x2e,
571         0xf9, 0x9c, 0x10, 0x63, 0x72, 0xed, 0x0d, 0x33, 0xc2, 0xdc, 0x7f, 0x9f, 0xd7, 0xef, 0x1b,
572         0xc9, 0xc4, 0xa7, 0x41, 0x9a, 0x07, 0x68, 0x6b, 0x66, 0xfb, 0x6a, 0x4e, 0x32, 0x5d, 0xe4,
573         0x25, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1,
574         0x00, 0x00, 0xca, 0x0c, 0x21, 0x11, 0xce, 0xf4, 0xfc, 0xb3, 0x66, 0x99, 0x4f, 0xdb, 0x4f,
575         0x95, 0x6b, 0x6f, 0x3b, 0xb1, 0xdb, 0x5a,
576     ]);
577     let pkt = Packet::unmarshal(&raw_pkt)?;
578     let raw_pkt2 = pkt.marshal()?;
579     assert_eq!(raw_pkt, raw_pkt2);
580 
581     Ok(())
582 }
583 
584 #[test]
585 fn test_init_marshal_unmarshal() -> Result<()> {
586     let mut p = Packet {
587         destination_port: 1,
588         source_port: 1,
589         verification_tag: 123,
590         chunks: vec![],
591     };
592 
593     let mut init_ack = ChunkInit {
594         is_ack: true,
595         initiate_tag: 123,
596         advertised_receiver_window_credit: 1024,
597         num_outbound_streams: 1,
598         num_inbound_streams: 1,
599         initial_tsn: 123,
600         params: vec![],
601     };
602 
603     let cookie = Box::new(ParamStateCookie::new());
604     init_ack.params.push(cookie);
605 
606     p.chunks.push(Box::new(init_ack));
607 
608     let raw_pkt = p.marshal()?;
609     let pkt = Packet::unmarshal(&raw_pkt)?;
610 
611     if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkInit>() {
612         assert_eq!(
613             c.initiate_tag, 123,
614             "Unmarshal passed for SCTP packet, but got incorrect initiate tag exp: {} act: {}",
615             123, c.initiate_tag
616         );
617         assert_eq!(c.advertised_receiver_window_credit, 1024, "Unmarshal passed for SCTP packet, but got incorrect advertisedReceiverWindowCredit exp: {} act: {}", 1024, c.advertised_receiver_window_credit);
618         assert_eq!(c.num_outbound_streams, 1, "Unmarshal passed for SCTP packet, but got incorrect numOutboundStreams tag exp:{} act: {}", 1, c.num_outbound_streams);
619         assert_eq!(
620             c.num_inbound_streams, 1,
621             "Unmarshal passed for SCTP packet, but got incorrect numInboundStreams exp: {} act: {}",
622             1, c.num_inbound_streams
623         );
624         assert_eq!(
625             c.initial_tsn, 123,
626             "Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: {} act: {}",
627             123, c.initial_tsn
628         );
629     } else {
630         assert!(false, "Failed to cast Chunk -> InitAck");
631     }
632 
633     Ok(())
634 }
635 
636 #[test]
637 fn test_payload_data_marshal_unmarshal() -> Result<()> {
638     let raw_pkt = Bytes::from_static(&[
639         0x13, 0x88, 0x13, 0x88, 0xfc, 0xd6, 0x3f, 0xc6, 0xbe, 0xfa, 0xdc, 0x52, 0x0a, 0x00, 0x00,
640         0x24, 0x9b, 0x28, 0x7e, 0x48, 0xa3, 0x7b, 0xc1, 0x83, 0xc4, 0x4b, 0x41, 0x04, 0xa4, 0xf7,
641         0xed, 0x4c, 0x93, 0x62, 0xc3, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642         0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1f, 0xa8, 0x79, 0xa1, 0xc7, 0x00, 0x01, 0x00, 0x00,
643         0x00, 0x00, 0x00, 0x32, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
644         0x00, 0x66, 0x6f, 0x6f, 0x00,
645     ]);
646     let pkt = Packet::unmarshal(&raw_pkt)?;
647     assert!(
648         pkt.chunks[1]
649             .as_any()
650             .downcast_ref::<ChunkPayloadData>()
651             .is_some(),
652         "Failed to cast Chunk -> PayloadData"
653     );
654     Ok(())
655 }
656 
657 #[test]
658 fn test_select_ack_chunk() -> Result<()> {
659     let raw_pkt = Bytes::from_static(&[
660         0x13, 0x88, 0x13, 0x88, 0xc2, 0x98, 0x98, 0x0f, 0x42, 0x31, 0xea, 0x78, 0x03, 0x00, 0x00,
661         0x14, 0x87, 0x73, 0xbd, 0xa4, 0x00, 0x01, 0xfe, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
662         0x00, 0x02,
663     ]);
664     let pkt = Packet::unmarshal(&raw_pkt)?;
665     assert!(
666         pkt.chunks[0]
667             .as_any()
668             .downcast_ref::<ChunkSelectiveAck>()
669             .is_some(),
670         "Failed to cast Chunk -> SelectiveAck"
671     );
672     Ok(())
673 }
674 
675 #[test]
676 fn test_reconfig_chunk() -> Result<()> {
677     let raw_pkt = Bytes::from_static(&[
678         0x13, 0x88, 0x13, 0x88, 0xb6, 0xa5, 0x12, 0xe5, 0x75, 0x3b, 0x12, 0xd3, 0x82, 0x0, 0x0,
679         0x16, 0x0, 0xd, 0x0, 0x12, 0x4e, 0x1c, 0xb9, 0xe6, 0x3a, 0x74, 0x8d, 0xff, 0x4e, 0x1c,
680         0xb9, 0xe6, 0x0, 0x1, 0x0, 0x0,
681     ]);
682     let pkt = Packet::unmarshal(&raw_pkt)?;
683     if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkReconfig>() {
684         assert!(c.param_a.is_some(), "param_a must not be none");
685         assert_eq!(
686             c.param_a
687                 .as_ref()
688                 .unwrap()
689                 .as_any()
690                 .downcast_ref::<ParamOutgoingResetRequest>()
691                 .unwrap()
692                 .stream_identifiers[0],
693             1,
694             "unexpected stream identifier"
695         );
696     } else {
697         assert!(false, "Failed to cast Chunk -> Reconfig");
698     }
699 
700     Ok(())
701 }
702 
703 #[test]
704 fn test_forward_tsn_chunk() -> Result<()> {
705     let mut raw_pkt = BytesMut::new();
706     raw_pkt.extend(vec![
707         0x13, 0x88, 0x13, 0x88, 0xb6, 0xa5, 0x12, 0xe5, 0x1f, 0x9d, 0xa0, 0xfb,
708     ]);
709     raw_pkt.extend(CHUNK_FORWARD_TSN_BYTES.clone());
710     let raw_pkt = raw_pkt.freeze();
711     let pkt = Packet::unmarshal(&raw_pkt)?;
712 
713     if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkForwardTsn>() {
714         assert_eq!(
715             c.new_cumulative_tsn, 3,
716             "unexpected New Cumulative TSN: {}",
717             c.new_cumulative_tsn
718         );
719     } else {
720         assert!(false, "Failed to cast Chunk -> Forward TSN");
721     }
722 
723     Ok(())
724 }
725 
726 #[test]
727 fn test_select_ack_chunk_followed_by_a_payload_data_chunk() -> Result<()> {
728     let raw_pkt = Bytes::from_static(&[
729         0x13, 0x88, 0x13, 0x88, 0xc2, 0x98, 0x98, 0x0f, 0x58, 0xcf, 0x38,
730         0xC0, // A SACK chunk follows.
731         0x03, 0x00, 0x00, 0x14, 0x87, 0x73, 0xbd, 0xa4, 0x00, 0x01, 0xfe, 0x74, 0x00, 0x01, 0x00,
732         0x00, 0x00, 0x02, 0x00, 0x02, // A payload data chunk follows.
733         0x00, 0x07, 0x00, 0x3B, 0xA4, 0x50, 0x7B, 0xC5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
734         0x33, 0x7B, 0x22, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x72, 0x65, 0x73, 0x69,
735         0x7A, 0x65, 0x22, 0x2C, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3A, 0x36, 0x36, 0x35,
736         0x2C, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3A, 0x34, 0x39, 0x39, 0x7D, 0x00,
737     ]);
738     let pkt = Packet::unmarshal(&raw_pkt)?;
739     assert!(
740         pkt.chunks[0]
741             .as_any()
742             .downcast_ref::<ChunkSelectiveAck>()
743             .is_some(),
744         "Failed to cast Chunk -> SelectiveAck"
745     );
746     assert!(
747         pkt.chunks[1]
748             .as_any()
749             .downcast_ref::<ChunkPayloadData>()
750             .is_some(),
751         "Failed to cast Chunk -> PayloadData"
752     );
753     Ok(())
754 }
755