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