summaryrefslogtreecommitdiffstats
path: root/third_party/rust/webrtc-sdp/src/media_type_tests.rs
diff options
context:
space:
mode:
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.rs411
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());
+}