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