diff options
Diffstat (limited to 'third_party/rust/webrtc-sdp/src/media_type_tests.rs')
-rw-r--r-- | third_party/rust/webrtc-sdp/src/media_type_tests.rs | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/third_party/rust/webrtc-sdp/src/media_type_tests.rs b/third_party/rust/webrtc-sdp/src/media_type_tests.rs new file mode 100644 index 0000000000..5e25cddb88 --- /dev/null +++ b/third_party/rust/webrtc-sdp/src/media_type_tests.rs @@ -0,0 +1,411 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use super::*; +use address::{AddressType, ExplicitlyTypedAddress}; +use attribute_type::{ + SdpAttributeFmtp, SdpAttributeFmtpParameters, SdpAttributePayloadType, SdpAttributeRtcpFb, + SdpAttributeRtcpFbType, +}; +use std::convert::TryFrom; + +pub fn create_dummy_media_section() -> SdpMedia { + let media_line = SdpMediaLine { + media: SdpMediaValue::Audio, + port: 9, + port_count: 0, + proto: SdpProtocolValue::RtpSavpf, + formats: SdpFormatList::Integers(Vec::new()), + }; + SdpMedia::new(media_line) +} + +// TODO is this useful outside of tests? +impl SdpFormatList { + fn len(&self) -> usize { + match *self { + SdpFormatList::Integers(ref x) => x.len(), + SdpFormatList::Strings(ref x) => x.len(), + } + } +} + +pub fn add_dummy_attributes(media: &mut SdpMedia) { + assert!(media + .add_attribute(SdpAttribute::Rtcpfb(SdpAttributeRtcpFb { + payload_type: SdpAttributePayloadType::Wildcard, + feedback_type: SdpAttributeRtcpFbType::Ack, + parameter: "".to_string(), + extra: "".to_string(), + },)) + .is_ok()); + assert!(media + .add_attribute(SdpAttribute::Fmtp(SdpAttributeFmtp { + payload_type: 1, + parameters: SdpAttributeFmtpParameters { + packetization_mode: 0, + level_asymmetry_allowed: false, + profile_level_id: 0x0042_0010, + max_fs: 0, + max_cpb: 0, + max_dpb: 0, + max_br: 0, + max_mbps: 0, + usedtx: false, + stereo: false, + useinbandfec: false, + cbr: false, + max_fr: 0, + maxplaybackrate: 48000, + maxaveragebitrate: 0, + ptime: 0, + minptime: 0, + maxptime: 0, + encodings: Vec::new(), + dtmf_tones: "".to_string(), + rtx: None, + unknown_tokens: Vec::new() + } + },)) + .is_ok()); + assert!(media + .add_attribute(SdpAttribute::Sctpmap(SdpAttributeSctpmap { + port: 5000, + channels: 2, + })) + .is_ok()); + assert!(media.add_attribute(SdpAttribute::BundleOnly).is_ok()); + assert!(media.add_attribute(SdpAttribute::SctpPort(5000)).is_ok()); + + assert!(media.get_attribute(SdpAttributeType::Rtpmap).is_some()); + assert!(media.get_attribute(SdpAttributeType::Rtcpfb).is_some()); + assert!(media.get_attribute(SdpAttributeType::Fmtp).is_some()); + assert!(media.get_attribute(SdpAttributeType::Sctpmap).is_some()); + assert!(media.get_attribute(SdpAttributeType::SctpPort).is_some()); + assert!(media.get_attribute(SdpAttributeType::BundleOnly).is_some()); +} + +fn check_parse(media_line_str: &str) -> SdpMediaLine { + if let Ok(SdpType::Media(media_line)) = parse_media(media_line_str) { + media_line + } else { + unreachable!() + } +} + +fn check_parse_and_serialize(media_line_str: &str) { + let parsed = check_parse(media_line_str); + assert_eq!(parsed.to_string(), media_line_str.to_string()); +} + +#[test] +fn test_get_set_port() { + let mut msection = create_dummy_media_section(); + assert_eq!(msection.get_port(), 9); + msection.set_port(2048); + assert_eq!(msection.get_port(), 2048); +} + +#[test] +fn test_add_codec() -> Result<(), SdpParserInternalError> { + let mut msection = create_dummy_media_section(); + msection.add_codec(SdpAttributeRtpmap::new(96, "foobar".to_string(), 1000))?; + assert_eq!(msection.get_formats().len(), 1); + assert!(msection.get_attribute(SdpAttributeType::Rtpmap).is_some()); + + let mut msection = create_dummy_media_section(); + msection.media.formats = SdpFormatList::Strings(Vec::new()); + msection.add_codec(SdpAttributeRtpmap::new(97, "boofar".to_string(), 1001))?; + assert_eq!(msection.get_formats().len(), 1); + assert!(msection.get_attribute(SdpAttributeType::Rtpmap).is_some()); + Ok(()) +} + +#[test] +fn test_remove_codecs() -> Result<(), SdpParserInternalError> { + let mut msection = create_dummy_media_section(); + msection.add_codec(SdpAttributeRtpmap::new(96, "foobar".to_string(), 1000))?; + assert_eq!(msection.get_formats().len(), 1); + assert!(msection.get_attribute(SdpAttributeType::Rtpmap).is_some()); + msection.remove_codecs(); + assert_eq!(msection.get_formats().len(), 0); + assert!(msection.get_attribute(SdpAttributeType::Rtpmap).is_none()); + + let mut msection = create_dummy_media_section(); + msection.media.formats = SdpFormatList::Strings(Vec::new()); + msection.add_codec(SdpAttributeRtpmap::new(97, "boofar".to_string(), 1001))?; + assert_eq!(msection.get_formats().len(), 1); + + add_dummy_attributes(&mut msection); + + msection.remove_codecs(); + assert_eq!(msection.get_formats().len(), 0); + assert!(msection.get_attribute(SdpAttributeType::Rtpmap).is_none()); + assert!(msection.get_attribute(SdpAttributeType::Rtcpfb).is_none()); + assert!(msection.get_attribute(SdpAttributeType::Fmtp).is_none()); + assert!(msection.get_attribute(SdpAttributeType::Sctpmap).is_none()); + assert!(msection.get_attribute(SdpAttributeType::SctpPort).is_none()); + Ok(()) +} + +#[test] +fn test_add_datachannel() -> Result<(), SdpParserInternalError> { + let mut msection = create_dummy_media_section(); + msection.add_datachannel("foo".to_string(), 5000, 256, 0)?; + assert_eq!(*msection.get_type(), SdpMediaValue::Application); + assert!(msection.get_attribute(SdpAttributeType::SctpPort).is_none()); + assert!(msection + .get_attribute(SdpAttributeType::MaxMessageSize) + .is_none()); + assert!(msection.get_attribute(SdpAttributeType::Sctpmap).is_some()); + match *msection.get_attribute(SdpAttributeType::Sctpmap).unwrap() { + SdpAttribute::Sctpmap(ref s) => { + assert_eq!(s.port, 5000); + assert_eq!(s.channels, 256); + } + _ => unreachable!(), + } + + let mut msection = create_dummy_media_section(); + msection.add_datachannel("foo".to_string(), 5000, 256, 1234)?; + assert_eq!(*msection.get_type(), SdpMediaValue::Application); + assert!(msection.get_attribute(SdpAttributeType::SctpPort).is_none()); + assert!(msection + .get_attribute(SdpAttributeType::MaxMessageSize) + .is_some()); + match *msection + .get_attribute(SdpAttributeType::MaxMessageSize) + .unwrap() + { + SdpAttribute::MaxMessageSize(m) => { + assert_eq!(m, 1234); + } + _ => unreachable!(), + } + + let mut msection = create_dummy_media_section(); + msection.media.proto = SdpProtocolValue::UdpDtlsSctp; + msection.add_datachannel("foo".to_string(), 5000, 256, 5678)?; + assert_eq!(*msection.get_type(), SdpMediaValue::Application); + assert!(msection.get_attribute(SdpAttributeType::Sctpmap).is_none()); + assert!(msection.get_attribute(SdpAttributeType::SctpPort).is_some()); + match *msection.get_attribute(SdpAttributeType::SctpPort).unwrap() { + SdpAttribute::SctpPort(s) => { + assert_eq!(s, 5000); + } + _ => unreachable!(), + } + assert!(msection + .get_attribute(SdpAttributeType::MaxMessageSize) + .is_some()); + match *msection + .get_attribute(SdpAttributeType::MaxMessageSize) + .unwrap() + { + SdpAttribute::MaxMessageSize(m) => { + assert_eq!(m, 5678); + } + _ => unreachable!(), + } + Ok(()) +} + +#[test] +fn test_parse_media_token() -> Result<(), SdpParserInternalError> { + let audio = parse_media_token("audio")?; + assert_eq!(audio, SdpMediaValue::Audio); + let video = parse_media_token("VIDEO")?; + assert_eq!(video, SdpMediaValue::Video); + let app = parse_media_token("aPplIcatIOn")?; + assert_eq!(app, SdpMediaValue::Application); + + assert!(parse_media_token("").is_err()); + assert!(parse_media_token("foobar").is_err()); + Ok(()) +} + +#[test] +fn test_parse_protocol_rtp_token() -> Result<(), SdpParserInternalError> { + fn parse_and_serialize_protocol_token( + token: &str, + result: SdpProtocolValue, + ) -> Result<(), SdpParserInternalError> { + let rtps = parse_protocol_token(token)?; + assert_eq!(rtps, result); + assert_eq!(rtps.to_string(), token.to_uppercase()); + Ok(()) + } + parse_and_serialize_protocol_token("rtp/avp", SdpProtocolValue::RtpAvp)?; + parse_and_serialize_protocol_token("rtp/avpf", SdpProtocolValue::RtpAvpf)?; + parse_and_serialize_protocol_token("rtp/savp", SdpProtocolValue::RtpSavp)?; + parse_and_serialize_protocol_token("rtp/savpf", SdpProtocolValue::RtpSavpf)?; + parse_and_serialize_protocol_token("udp/tls/rtp/savp", SdpProtocolValue::UdpTlsRtpSavp)?; + parse_and_serialize_protocol_token("udp/tls/rtp/savpf", SdpProtocolValue::UdpTlsRtpSavpf)?; + parse_and_serialize_protocol_token("TCP/dtls/rtp/savp", SdpProtocolValue::TcpDtlsRtpSavp)?; + parse_and_serialize_protocol_token("tcp/DTLS/rtp/savpf", SdpProtocolValue::TcpDtlsRtpSavpf)?; + + assert!(parse_protocol_token("").is_err()); + assert!(parse_protocol_token("foobar").is_err()); + Ok(()) +} + +#[test] +fn test_parse_protocol_sctp_token() -> Result<(), SdpParserInternalError> { + fn parse_and_serialize_protocol_token( + token: &str, + result: SdpProtocolValue, + ) -> Result<(), SdpParserInternalError> { + let rtps = parse_protocol_token(token)?; + assert_eq!(rtps, result); + assert_eq!(rtps.to_string(), token.to_uppercase()); + Ok(()) + } + parse_and_serialize_protocol_token("dtLs/ScTP", SdpProtocolValue::DtlsSctp)?; + parse_and_serialize_protocol_token("udp/DTLS/sctp", SdpProtocolValue::UdpDtlsSctp)?; + parse_and_serialize_protocol_token("tcp/dtls/SCTP", SdpProtocolValue::TcpDtlsSctp)?; + Ok(()) +} + +#[test] +fn test_media_works() { + check_parse_and_serialize("audio 9 UDP/TLS/RTP/SAVPF 109"); + check_parse_and_serialize("video 9 UDP/TLS/RTP/SAVPF 126"); + check_parse_and_serialize("application 9 DTLS/SCTP 5000"); + check_parse_and_serialize("application 9 UDP/DTLS/SCTP webrtc-datachannel"); + + check_parse_and_serialize("audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8"); + check_parse_and_serialize("audio 0 UDP/TLS/RTP/SAVPF 8"); + check_parse_and_serialize("audio 9/2 UDP/TLS/RTP/SAVPF 8"); +} + +#[test] +fn test_media_missing_token() { + assert!(parse_media("video 9 UDP/TLS/RTP/SAVPF").is_err()); +} + +#[test] +fn test_media_invalid_port_number() { + assert!(parse_media("video 75123 UDP/TLS/RTP/SAVPF 8").is_err()); +} + +#[test] +fn test_media_invalid_type() { + assert!(parse_media("invalid 9 UDP/TLS/RTP/SAVPF 8").is_err()); +} + +#[test] +fn test_media_invalid_port() { + assert!(parse_media("audio / UDP/TLS/RTP/SAVPF 8").is_err()); +} + +#[test] +fn test_media_invalid_transport() { + assert!(parse_media("audio 9 invalid/invalid 8").is_err()); +} + +#[test] +fn test_media_invalid_payload() { + assert!(parse_media("audio 9 UDP/TLS/RTP/SAVPF 300").is_err()); +} + +#[test] +fn test_media_vector_first_line_failure() { + let mut sdp_lines: Vec<SdpLine> = Vec::new(); + let line = SdpLine { + line_number: 0, + sdp_type: SdpType::Session("hello".to_string()), + text: "".to_owned(), + }; + sdp_lines.push(line); + assert!(parse_media_vector(&mut sdp_lines).is_err()); +} + +#[test] +fn test_media_vector_multiple_connections() { + let mut sdp_lines: Vec<SdpLine> = Vec::new(); + let media_line = SdpMediaLine { + media: SdpMediaValue::Audio, + port: 9, + port_count: 0, + proto: SdpProtocolValue::RtpSavpf, + formats: SdpFormatList::Integers(Vec::new()), + }; + let media = SdpLine { + line_number: 0, + sdp_type: SdpType::Media(media_line), + text: "".to_owned(), + }; + sdp_lines.push(media); + let c = SdpConnection { + address: ExplicitlyTypedAddress::try_from((AddressType::IpV4, "127.0.0.1")).unwrap(), + ttl: None, + amount: None, + }; + let c1 = SdpLine { + line_number: 1, + sdp_type: SdpType::Connection(c.clone()), + text: "".to_owned(), + }; + sdp_lines.push(c1); + let c2 = SdpLine { + line_number: 2, + sdp_type: SdpType::Connection(c), + text: "".to_owned(), + }; + sdp_lines.push(c2); + assert!(parse_media_vector(&mut sdp_lines).is_err()); +} + +#[test] +fn test_media_vector_invalid_types() { + let mut sdp_lines: Vec<SdpLine> = Vec::new(); + let media_line = SdpMediaLine { + media: SdpMediaValue::Audio, + port: 9, + port_count: 0, + proto: SdpProtocolValue::RtpSavpf, + formats: SdpFormatList::Integers(Vec::new()), + }; + let media = SdpLine { + line_number: 0, + sdp_type: SdpType::Media(media_line), + text: "".to_owned(), + }; + sdp_lines.push(media); + use SdpTiming; + let t = SdpTiming { start: 0, stop: 0 }; + let tline = SdpLine { + line_number: 1, + sdp_type: SdpType::Timing(t), + text: "".to_owned(), + }; + sdp_lines.push(tline); + assert!(parse_media_vector(&mut sdp_lines).is_err()); +} + +#[test] +fn test_media_vector_invalid_media_level_attribute() { + let mut sdp_lines: Vec<SdpLine> = Vec::new(); + let media_line = SdpMediaLine { + media: SdpMediaValue::Audio, + port: 9, + port_count: 0, + proto: SdpProtocolValue::RtpSavpf, + formats: SdpFormatList::Integers(Vec::new()), + }; + let media = SdpLine { + line_number: 0, + sdp_type: SdpType::Media(media_line), + text: "".to_owned(), + }; + sdp_lines.push(media); + let a = SdpAttribute::IceLite; + let aline = SdpLine { + line_number: 1, + sdp_type: SdpType::Attribute(a), + text: "".to_owned(), + }; + sdp_lines.push(aline); + assert!(parse_media_vector(&mut sdp_lines).is_err()); +} |