1 use super::*;
2 use crate::goodbye::Goodbye;
3 use crate::payload_feedbacks::picture_loss_indication::PictureLossIndication;
4 
5 // An RTCP packet from a packet dump
6 const REAL_PACKET: [u8; 116] = [
7     // Receiver Report (offset=0)
8     0x81, 0xc9, 0x0, 0x7, // v=2, p=0, count=1, RR, len=7
9     0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
10     0xbc, 0x5e, 0x9a, 0x40, // ssrc=0xbc5e9a40
11     0x0, 0x0, 0x0, 0x0, // fracLost=0, totalLost=0
12     0x0, 0x0, 0x46, 0xe1, // lastSeq=0x46e1
13     0x0, 0x0, 0x1, 0x11, // jitter=273
14     0x9, 0xf3, 0x64, 0x32, // lsr=0x9f36432
15     0x0, 0x2, 0x4a, 0x79, // delay=150137
16     // Source Description (offset=32)
17     0x81, 0xca, 0x0, 0xc, // v=2, p=0, count=1, SDES, len=12
18     0x90, 0x2f, 0x9e, 0x2e, // ssrc=0x902f9e2e
19     0x1, 0x26, // CNAME, len=38
20     0x7b, 0x39, 0x63, 0x30, 0x30, 0x65, 0x62, 0x39, 0x32, 0x2d, 0x31, 0x61, 0x66, 0x62, 0x2d, 0x39,
21     0x64, 0x34, 0x39, 0x2d, 0x61, 0x34, 0x37, 0x64, 0x2d, 0x39, 0x31, 0x66, 0x36, 0x34, 0x65, 0x65,
22     0x65, 0x36, 0x39, 0x66, 0x35, 0x7d, // text="{9c00eb92-1afb-9d49-a47d-91f64eee69f5}"
23     0x0, 0x0, 0x0, 0x0, // END + padding
24     // Goodbye (offset=84)
25     0x81, 0xcb, 0x0, 0x1, // v=2, p=0, count=1, BYE, len=1
26     0x90, 0x2f, 0x9e, 0x2e, // source=0x902f9e2e
27     0x81, 0xce, 0x0, 0x2, // Picture Loss Indication (offset=92)
28     0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e
29     0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e
30     0x85, 0xcd, 0x0, 0x2, // RapidResynchronizationRequest (offset=104)
31     0x90, 0x2f, 0x9e, 0x2e, // sender=0x902f9e2e
32     0x90, 0x2f, 0x9e, 0x2e, // media=0x902f9e2e
33 ];
34 
35 #[test]
36 fn test_read_eof() {
37     let mut short_header = Bytes::from_static(&[
38         0x81, 0xc9, // missing type & len
39     ]);
40     let result = unmarshal(&mut short_header);
41     assert!(result.is_err(), "missing type & len");
42 }
43 
44 #[test]
45 fn test_bad_compound() {
46     let mut bad_compound = Bytes::copy_from_slice(&REAL_PACKET[..34]);
47     let result = unmarshal(&mut bad_compound);
48     assert!(result.is_err(), "trailing data!");
49 
50     let mut bad_compound = Bytes::copy_from_slice(&REAL_PACKET[84..104]);
51     let p = unmarshal(&mut bad_compound).expect("Error unmarshalling packet");
52     let compound = CompoundPacket(p);
53 
54     // this should return an error,
55     // it violates the "must start with RR or SR" rule
56     match compound.validate() {
57         Ok(_) => panic!("validation should return an error"),
58 
59         Err(err) => {
60             let a = Error::BadFirstPacket;
61             assert_eq!(
62                 Error::BadFirstPacket,
63                 err,
64                 "Unmarshal(badcompound) err={:?}, want {:?}",
65                 err,
66                 a,
67             );
68         }
69     };
70 
71     let compound_len = compound.0.len();
72     assert_eq!(
73         compound_len, 2,
74         "Unmarshal(badcompound) len={}, want {}",
75         compound_len, 2
76     );
77 
78     if compound.0[0].as_any().downcast_ref::<Goodbye>().is_none() {
79         panic!("Unmarshal(badcompound), want Goodbye")
80     }
81 
82     if compound.0[1]
83         .as_any()
84         .downcast_ref::<PictureLossIndication>()
85         .is_none()
86     {
87         panic!("Unmarshal(badcompound), want PictureLossIndication")
88     }
89 }
90 
91 #[test]
92 fn test_valid_packet() {
93     let cname = SourceDescription {
94         chunks: vec![SourceDescriptionChunk {
95             source: 1234,
96             items: vec![SourceDescriptionItem {
97                 sdes_type: SdesType::SdesCname,
98                 text: Bytes::from_static(b"cname"),
99             }],
100         }],
101     };
102 
103     let tests: Vec<(&str, CompoundPacket, Option<Error>)> = vec![
104         (
105             "no cname",
106             CompoundPacket(vec![Box::new(SenderReport::default())]),
107             Some(Error::MissingCname),
108         ),
109         (
110             "SDES / no cname",
111             CompoundPacket(vec![
112                 Box::new(SenderReport::default()),
113                 Box::new(SourceDescription::default()),
114             ]),
115             Some(Error::MissingCname),
116         ),
117         (
118             "just SR",
119             CompoundPacket(vec![
120                 Box::new(SenderReport::default()),
121                 Box::new(cname.to_owned()),
122             ]),
123             None,
124         ),
125         (
126             "multiple SRs",
127             CompoundPacket(vec![
128                 Box::new(SenderReport::default()),
129                 Box::new(SenderReport::default()),
130                 Box::new(cname.clone()),
131             ]),
132             Some(Error::PacketBeforeCname),
133         ),
134         (
135             "just RR",
136             CompoundPacket(vec![
137                 Box::new(ReceiverReport::default()),
138                 Box::new(cname.clone()),
139             ]),
140             None,
141         ),
142         (
143             "multiple RRs",
144             CompoundPacket(vec![
145                 Box::new(ReceiverReport::default()),
146                 Box::new(cname.clone()),
147                 Box::new(ReceiverReport::default()),
148             ]),
149             None,
150         ),
151         (
152             "goodbye",
153             CompoundPacket(vec![
154                 Box::new(ReceiverReport::default()),
155                 Box::new(cname),
156                 Box::new(Goodbye::default()),
157             ]),
158             None,
159         ),
160     ];
161 
162     for (name, packet, error) in tests {
163         let result = packet.validate();
164         assert_eq!(result.is_ok(), error.is_none());
165         if let (Some(err), Err(got)) = (error, result) {
166             assert_eq!(err, got, "Valid({}) = {:?}, want {:?}", name, got, err);
167         }
168     }
169 }
170 
171 #[test]
172 fn test_cname() {
173     let cname = SourceDescription {
174         chunks: vec![SourceDescriptionChunk {
175             source: 1234,
176             items: vec![SourceDescriptionItem {
177                 sdes_type: SdesType::SdesCname,
178                 text: Bytes::from_static(b"cname"),
179             }],
180         }],
181     };
182 
183     let tests: Vec<(&str, CompoundPacket, Option<Error>, &str)> = vec![
184         (
185             "no cname",
186             CompoundPacket(vec![Box::new(SenderReport::default())]),
187             Some(Error::MissingCname),
188             "",
189         ),
190         (
191             "SDES / no cname",
192             CompoundPacket(vec![
193                 Box::new(SenderReport::default()),
194                 Box::new(SourceDescription::default()),
195             ]),
196             Some(Error::MissingCname),
197             "",
198         ),
199         (
200             "just SR",
201             CompoundPacket(vec![
202                 Box::new(SenderReport::default()),
203                 Box::new(cname.clone()),
204             ]),
205             None,
206             "cname",
207         ),
208         (
209             "multiple SRs",
210             CompoundPacket(vec![
211                 Box::new(SenderReport::default()),
212                 Box::new(SenderReport::default()),
213                 Box::new(cname.clone()),
214             ]),
215             Some(Error::PacketBeforeCname),
216             "",
217         ),
218         (
219             "just RR",
220             CompoundPacket(vec![
221                 Box::new(ReceiverReport::default()),
222                 Box::new(cname.clone()),
223             ]),
224             None,
225             "cname",
226         ),
227         (
228             "multiple RRs",
229             CompoundPacket(vec![
230                 Box::new(ReceiverReport::default()),
231                 Box::new(ReceiverReport::default()),
232                 Box::new(cname.clone()),
233             ]),
234             None,
235             "cname",
236         ),
237         (
238             "goodbye",
239             CompoundPacket(vec![
240                 Box::new(ReceiverReport::default()),
241                 Box::new(cname),
242                 Box::new(Goodbye::default()),
243             ]),
244             None,
245             "cname",
246         ),
247     ];
248 
249     for (name, compound_packet, want_error, text) in tests {
250         let err = compound_packet.validate();
251         assert_eq!(err.is_err(), want_error.is_some());
252         if let (Some(want), Err(err)) = (&want_error, err) {
253             assert_eq!(*want, err, "Valid({}) = {:?}, want {:?}", name, err, want);
254         }
255 
256         let name_result = compound_packet.cname();
257         assert_eq!(name_result.is_err(), want_error.is_some());
258 
259         match name_result {
260             Ok(e) => {
261                 assert_eq!(e, text, "CNAME({}) = {:?}, want {}", name, e, text,);
262             }
263 
264             Err(err) => {
265                 if let Some(want) = &want_error {
266                     assert_eq!(*want, err, "CNAME({}) = {:?}, want {:?}", name, err, want);
267                 }
268             }
269         }
270     }
271 }
272 
273 #[test]
274 fn test_compound_packet_roundtrip() {
275     let cname = SourceDescription {
276         chunks: vec![SourceDescriptionChunk {
277             source: 1234,
278             items: vec![SourceDescriptionItem {
279                 sdes_type: SdesType::SdesCname,
280                 text: Bytes::from_static(b"cname"),
281             }],
282         }],
283     };
284 
285     let tests = vec![
286         (
287             "goodbye",
288             CompoundPacket(vec![
289                 Box::new(ReceiverReport::default()),
290                 Box::new(cname),
291                 Box::new(Goodbye {
292                     sources: vec![1234],
293                     ..Default::default()
294                 }),
295             ]),
296             None,
297         ),
298         (
299             "no cname",
300             CompoundPacket(vec![Box::new(ReceiverReport::default())]),
301             Some(Error::MissingCname),
302         ),
303     ];
304 
305     for (name, packet, marshal_error) in tests {
306         let result = packet.marshal();
307         if let Some(err) = marshal_error {
308             if let Err(got) = result {
309                 assert_eq!(
310                     err, got,
311                     "marshal {} header: err = {}, want {}",
312                     name, got, err
313                 );
314             } else {
315                 panic!("want error in test {}", name);
316             }
317             continue;
318         } else {
319             assert!(result.is_ok(), "must no error in test {}", name);
320         }
321 
322         let data1 = result.unwrap();
323         let c = CompoundPacket::unmarshal(&mut data1.clone())
324             .unwrap_or_else(|_| panic!("unmarshal {} error", name));
325 
326         let data2 = c
327             .marshal()
328             .unwrap_or_else(|_| panic!("marshal {} error", name));
329 
330         assert_eq!(
331             data1, data2,
332             "Unmarshal(Marshal({:?})) = {:?}, want {:?}",
333             name, data1, data2
334         )
335     }
336 }
337