1 use super::*;
2 
3 #[test]
4 fn test_source_description_unmarshal() {
5     let tests = vec![
6         (
7             "nil",
8             Bytes::from_static(&[]),
9             SourceDescription::default(),
10             Some(Error::PacketTooShort),
11         ),
12         (
13             "no chunks",
14             Bytes::from_static(&[
15                 // v=2, p=0, count=1, SDES, len=8
16                 0x80, 0xca, 0x00, 0x04,
17             ]),
18             SourceDescription::default(),
19             None,
20         ),
21         (
22             "missing type",
23             Bytes::from_static(&[
24                 // v=2, p=0, count=1, SDES, len=8
25                 0x81, 0xca, 0x00, 0x08, // ssrc=0x00000000
26                 0x00, 0x00, 0x00, 0x00,
27             ]),
28             SourceDescription::default(),
29             Some(Error::PacketTooShort),
30         ),
31         (
32             "bad cname length",
33             Bytes::from_static(&[
34                 // v=2, p=0, count=1, SDES, len=10
35                 0x81, 0xca, 0x00, 0x0a, // ssrc=0x00000000
36                 0x00, 0x00, 0x00, 0x00, // CNAME, len = 1
37                 0x01, 0x01,
38             ]),
39             SourceDescription::default(),
40             Some(Error::PacketTooShort),
41         ),
42         (
43             "short cname",
44             Bytes::from_static(&[
45                 // v=2, p=0, count=1, SDES, len=9
46                 0x81, 0xca, 0x00, 0x09, // ssrc=0x00000000
47                 0x00, 0x00, 0x00, 0x00, // CNAME, Missing length
48                 0x01,
49             ]),
50             SourceDescription::default(),
51             Some(Error::PacketTooShort),
52         ),
53         (
54             "no end",
55             Bytes::from_static(&[
56                 // v=2, p=0, count=1, SDES, len=11
57                 0x81, 0xca, 0x00, 0x0b, // ssrc=0x00000000
58                 0x00, 0x00, 0x00, 0x00, // CNAME, len=1, content=A
59                 0x01, 0x02, 0x41,
60                 // Missing END
61             ]),
62             SourceDescription::default(),
63             Some(Error::PacketTooShort),
64         ),
65         (
66             "bad octet count",
67             Bytes::from_static(&[
68                 // v=2, p=0, count=1, SDES, len=10
69                 0x81, 0xca, 0x00, 0x0a, // ssrc=0x00000000
70                 0x00, 0x00, 0x00, 0x00, // CNAME, len=1
71                 0x01, 0x01,
72             ]),
73             SourceDescription::default(),
74             Some(Error::PacketTooShort),
75         ),
76         (
77             "zero item chunk",
78             Bytes::from_static(&[
79                 // v=2, p=0, count=1, SDES, len=12
80                 0x81, 0xca, 0x00, 0x0c, // ssrc=0x01020304
81                 0x01, 0x02, 0x03, 0x04, // END + padding
82                 0x00, 0x00, 0x00, 0x00,
83             ]),
84             SourceDescription {
85                 chunks: vec![SourceDescriptionChunk {
86                     source: 0x01020304,
87                     items: vec![],
88                 }],
89             },
90             None,
91         ),
92         (
93             "wrong type",
94             Bytes::from_static(&[
95                 // v=2, p=0, count=1, SR, len=12
96                 0x81, 0xc8, 0x00, 0x0c, // ssrc=0x01020304
97                 0x01, 0x02, 0x03, 0x04, // END + padding
98                 0x00, 0x00, 0x00, 0x00,
99             ]),
100             SourceDescription::default(),
101             Some(Error::WrongType),
102         ),
103         (
104             "bad count in header",
105             Bytes::from_static(&[
106                 // v=2, p=0, count=1, SDES, len=12
107                 0x81, 0xca, 0x00, 0x0c,
108             ]),
109             SourceDescription::default(),
110             Some(Error::InvalidHeader),
111         ),
112         (
113             "empty string",
114             Bytes::from_static(&[
115                 // v=2, p=0, count=1, SDES, len=12
116                 0x81, 0xca, 0x00, 0x0c, // ssrc=0x01020304
117                 0x01, 0x02, 0x03, 0x04, // CNAME, len=0
118                 0x01, 0x00, // END + padding
119                 0x00, 0x00,
120             ]),
121             SourceDescription {
122                 chunks: vec![SourceDescriptionChunk {
123                     source: 0x01020304,
124                     items: vec![SourceDescriptionItem {
125                         sdes_type: SdesType::SdesCname,
126                         text: Bytes::from_static(b""),
127                     }],
128                 }],
129             },
130             None,
131         ),
132         (
133             "two items",
134             Bytes::from_static(&[
135                 // v=2, p=0, count=1, SDES, len=16
136                 0x81, 0xca, 0x00, 0x10, // ssrc=0x10000000
137                 0x10, 0x00, 0x00, 0x00, // CNAME, len=1, content=A
138                 0x01, 0x01, 0x41, // PHONE, len=1, content=B
139                 0x04, 0x01, 0x42, // END + padding
140                 0x00, 0x00,
141             ]),
142             SourceDescription {
143                 chunks: vec![SourceDescriptionChunk {
144                     source: 0x10000000,
145                     items: vec![
146                         SourceDescriptionItem {
147                             sdes_type: SdesType::SdesCname,
148                             text: Bytes::from_static(b"A"),
149                         },
150                         SourceDescriptionItem {
151                             sdes_type: SdesType::SdesPhone,
152                             text: Bytes::from_static(b"B"),
153                         },
154                     ],
155                 }],
156             },
157             None,
158         ),
159         (
160             "two chunks",
161             Bytes::from_static(&[
162                 // v=2, p=0, count=2, SDES, len=24
163                 0x82, 0xca, 0x00, 0x18, // ssrc=0x01020304
164                 0x01, 0x02, 0x03, 0x04,
165                 // Chunk 1
166                 // CNAME, len=1, content=A
167                 0x01, 0x01, 0x41, // END
168                 0x00, // Chunk 2
169                 // SSRC 0x05060708
170                 0x05, 0x06, 0x07, 0x08, // CNAME, len=3, content=BCD
171                 0x01, 0x03, 0x42, 0x43, 0x44, // END
172                 0x00, 0x00, 0x00,
173             ]),
174             SourceDescription {
175                 chunks: vec![
176                     SourceDescriptionChunk {
177                         source: 0x01020304,
178                         items: vec![SourceDescriptionItem {
179                             sdes_type: SdesType::SdesCname,
180                             text: Bytes::from_static(b"A"),
181                         }],
182                     },
183                     SourceDescriptionChunk {
184                         source: 0x05060708,
185                         items: vec![SourceDescriptionItem {
186                             sdes_type: SdesType::SdesCname,
187                             text: Bytes::from_static(b"BCD"),
188                         }],
189                     },
190                 ],
191             },
192             None,
193         ),
194     ];
195 
196     for (name, mut data, want, want_error) in tests {
197         let got = SourceDescription::unmarshal(&mut data);
198 
199         assert_eq!(
200             got.is_err(),
201             want_error.is_some(),
202             "Unmarshal {}: err = {:?}, want {:?}",
203             name,
204             got,
205             want_error
206         );
207 
208         if let Some(err) = want_error {
209             let got_err = got.err().unwrap();
210             assert_eq!(
211                 err, got_err,
212                 "Unmarshal {}: err = {:?}, want {:?}",
213                 name, got_err, err,
214             );
215         } else {
216             let actual = got.unwrap();
217             assert_eq!(
218                 actual, want,
219                 "Unmarshal {}: got {:?}, want {:?}",
220                 name, actual, want
221             );
222         }
223     }
224 }
225 
226 #[test]
227 fn test_source_description_roundtrip() {
228     let mut too_long_text = String::new();
229     for _ in 0..(1 << 8) {
230         too_long_text += "x";
231     }
232 
233     let mut too_many_chunks = vec![];
234     for _ in 0..(1 << 5) {
235         too_many_chunks.push(SourceDescriptionChunk::default());
236     }
237 
238     let tests = vec![
239         (
240             "valid",
241             SourceDescription {
242                 chunks: vec![
243                     SourceDescriptionChunk {
244                         source: 1,
245                         items: vec![SourceDescriptionItem {
246                             sdes_type: SdesType::SdesCname,
247                             text: Bytes::from_static(b"[email protected]"),
248                         }],
249                     },
250                     SourceDescriptionChunk {
251                         source: 2,
252                         items: vec![
253                             SourceDescriptionItem {
254                                 sdes_type: SdesType::SdesNote,
255                                 text: Bytes::from_static(b"some note"),
256                             },
257                             SourceDescriptionItem {
258                                 sdes_type: SdesType::SdesNote,
259                                 text: Bytes::from_static(b"another note"),
260                             },
261                         ],
262                     },
263                 ],
264             },
265             None,
266         ),
267         (
268             "item without type",
269             SourceDescription {
270                 chunks: vec![SourceDescriptionChunk {
271                     source: 1,
272                     items: vec![SourceDescriptionItem {
273                         sdes_type: SdesType::SdesEnd,
274                         text: Bytes::from_static(b"[email protected]"),
275                     }],
276                 }],
277             },
278             Some(Error::SdesMissingType),
279         ),
280         (
281             "zero items",
282             SourceDescription {
283                 chunks: vec![SourceDescriptionChunk {
284                     source: 1,
285                     items: vec![],
286                 }],
287             },
288             None,
289         ),
290         (
291             "email item",
292             SourceDescription {
293                 chunks: vec![SourceDescriptionChunk {
294                     source: 1,
295                     items: vec![SourceDescriptionItem {
296                         sdes_type: SdesType::SdesEmail,
297                         text: Bytes::from_static(b"[email protected]"),
298                     }],
299                 }],
300             },
301             None,
302         ),
303         (
304             "empty text",
305             SourceDescription {
306                 chunks: vec![SourceDescriptionChunk {
307                     source: 1,
308                     items: vec![SourceDescriptionItem {
309                         sdes_type: SdesType::SdesCname,
310                         text: Bytes::from_static(b""),
311                     }],
312                 }],
313             },
314             None,
315         ),
316         (
317             "text too long",
318             SourceDescription {
319                 chunks: vec![SourceDescriptionChunk {
320                     source: 1,
321                     items: vec![SourceDescriptionItem {
322                         sdes_type: SdesType::SdesCname,
323                         text: Bytes::copy_from_slice(too_long_text.as_bytes()),
324                     }],
325                 }],
326             },
327             Some(Error::SdesTextTooLong),
328         ),
329         (
330             "count overflow",
331             SourceDescription {
332                 chunks: too_many_chunks,
333             },
334             Some(Error::TooManyChunks),
335         ),
336     ];
337 
338     for (name, want, want_error) in tests {
339         let got = want.marshal();
340 
341         assert_eq!(
342             got.is_ok(),
343             want_error.is_none(),
344             "Marshal {}: err = {:?}, want {:?}",
345             name,
346             got,
347             want_error
348         );
349 
350         if let Some(err) = want_error {
351             let got_err = got.err().unwrap();
352             assert_eq!(
353                 err, got_err,
354                 "Unmarshal {} rr: err = {:?}, want {:?}",
355                 name, got_err, err,
356             );
357         } else {
358             let mut data = got.ok().unwrap();
359             let actual = SourceDescription::unmarshal(&mut data)
360                 .unwrap_or_else(|_| panic!("Unmarshal {}", name));
361 
362             assert_eq!(
363                 actual, want,
364                 "{} round trip: got {:?}, want {:?}",
365                 name, actual, want
366             )
367         }
368     }
369 }
370