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