xref: /aosp_15_r20/external/webrtc/pc/webrtc_sdp_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2011 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
12*d9f75844SAndroid Build Coastguard Worker #include <string.h>
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
15*d9f75844SAndroid Build Coastguard Worker #include <map>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <sstream>
18*d9f75844SAndroid Build Coastguard Worker #include <string>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
23*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
24*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/str_replace.h"
25*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
26*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/crypto_params.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/jsep_session_description.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_transceiver_direction.h"
33*d9f75844SAndroid Build Coastguard Worker #include "media/base/codec.h"
34*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
35*d9f75844SAndroid Build Coastguard Worker #include "media/base/rid_description.h"
36*d9f75844SAndroid Build Coastguard Worker #include "media/base/stream_params.h"
37*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
38*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port.h"
39*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_description.h"
40*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_info.h"
41*d9f75844SAndroid Build Coastguard Worker #include "pc/media_protocol_names.h"
42*d9f75844SAndroid Build Coastguard Worker #include "pc/media_session.h"
43*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h"
44*d9f75844SAndroid Build Coastguard Worker #include "pc/simulcast_description.h"
45*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
46*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/message_digest.h"
47*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
48*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_fingerprint.h"
49*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
50*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
51*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
52*d9f75844SAndroid Build Coastguard Worker 
53*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
54*d9f75844SAndroid Build Coastguard Worker #include "pc/test/android_test_initializer.h"
55*d9f75844SAndroid Build Coastguard Worker #endif
56*d9f75844SAndroid Build Coastguard Worker #include "pc/webrtc_sdp.h"
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker using cricket::AudioCodec;
59*d9f75844SAndroid Build Coastguard Worker using cricket::AudioContentDescription;
60*d9f75844SAndroid Build Coastguard Worker using cricket::Candidate;
61*d9f75844SAndroid Build Coastguard Worker using cricket::ContentGroup;
62*d9f75844SAndroid Build Coastguard Worker using cricket::ContentInfo;
63*d9f75844SAndroid Build Coastguard Worker using cricket::CryptoParams;
64*d9f75844SAndroid Build Coastguard Worker using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
65*d9f75844SAndroid Build Coastguard Worker using cricket::ICE_CANDIDATE_COMPONENT_RTP;
66*d9f75844SAndroid Build Coastguard Worker using cricket::kFecSsrcGroupSemantics;
67*d9f75844SAndroid Build Coastguard Worker using cricket::LOCAL_PORT_TYPE;
68*d9f75844SAndroid Build Coastguard Worker using cricket::MediaProtocolType;
69*d9f75844SAndroid Build Coastguard Worker using cricket::RELAY_PORT_TYPE;
70*d9f75844SAndroid Build Coastguard Worker using cricket::RidDescription;
71*d9f75844SAndroid Build Coastguard Worker using cricket::RidDirection;
72*d9f75844SAndroid Build Coastguard Worker using cricket::SctpDataContentDescription;
73*d9f75844SAndroid Build Coastguard Worker using cricket::SessionDescription;
74*d9f75844SAndroid Build Coastguard Worker using cricket::SimulcastDescription;
75*d9f75844SAndroid Build Coastguard Worker using cricket::SimulcastLayer;
76*d9f75844SAndroid Build Coastguard Worker using cricket::StreamParams;
77*d9f75844SAndroid Build Coastguard Worker using cricket::STUN_PORT_TYPE;
78*d9f75844SAndroid Build Coastguard Worker using cricket::TransportDescription;
79*d9f75844SAndroid Build Coastguard Worker using cricket::TransportInfo;
80*d9f75844SAndroid Build Coastguard Worker using cricket::VideoCodec;
81*d9f75844SAndroid Build Coastguard Worker using cricket::VideoContentDescription;
82*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
83*d9f75844SAndroid Build Coastguard Worker using ::testing::Field;
84*d9f75844SAndroid Build Coastguard Worker using webrtc::IceCandidateCollection;
85*d9f75844SAndroid Build Coastguard Worker using webrtc::IceCandidateInterface;
86*d9f75844SAndroid Build Coastguard Worker using webrtc::JsepIceCandidate;
87*d9f75844SAndroid Build Coastguard Worker using webrtc::JsepSessionDescription;
88*d9f75844SAndroid Build Coastguard Worker using webrtc::RtpExtension;
89*d9f75844SAndroid Build Coastguard Worker using webrtc::RtpTransceiverDirection;
90*d9f75844SAndroid Build Coastguard Worker using webrtc::SdpParseError;
91*d9f75844SAndroid Build Coastguard Worker using webrtc::SdpType;
92*d9f75844SAndroid Build Coastguard Worker using webrtc::SessionDescriptionInterface;
93*d9f75844SAndroid Build Coastguard Worker 
94*d9f75844SAndroid Build Coastguard Worker typedef std::vector<AudioCodec> AudioCodecs;
95*d9f75844SAndroid Build Coastguard Worker typedef std::vector<Candidate> Candidates;
96*d9f75844SAndroid Build Coastguard Worker 
97*d9f75844SAndroid Build Coastguard Worker static const uint32_t kDefaultSctpPort = 5000;
98*d9f75844SAndroid Build Coastguard Worker static const uint16_t kUnusualSctpPort = 9556;
99*d9f75844SAndroid Build Coastguard Worker static const char kSessionTime[] = "t=0 0\r\n";
100*d9f75844SAndroid Build Coastguard Worker static const uint32_t kCandidatePriority = 2130706432U;  // pref = 1.0
101*d9f75844SAndroid Build Coastguard Worker static const char kAttributeIceUfragVoice[] = "a=ice-ufrag:ufrag_voice\r\n";
102*d9f75844SAndroid Build Coastguard Worker static const char kAttributeIcePwdVoice[] = "a=ice-pwd:pwd_voice\r\n";
103*d9f75844SAndroid Build Coastguard Worker static const char kAttributeIceUfragVideo[] = "a=ice-ufrag:ufrag_video\r\n";
104*d9f75844SAndroid Build Coastguard Worker static const char kAttributeIcePwdVideo[] = "a=ice-pwd:pwd_video\r\n";
105*d9f75844SAndroid Build Coastguard Worker static const uint32_t kCandidateGeneration = 2;
106*d9f75844SAndroid Build Coastguard Worker static const char kCandidateFoundation1[] = "a0+B/1";
107*d9f75844SAndroid Build Coastguard Worker static const char kCandidateFoundation2[] = "a0+B/2";
108*d9f75844SAndroid Build Coastguard Worker static const char kCandidateFoundation3[] = "a0+B/3";
109*d9f75844SAndroid Build Coastguard Worker static const char kCandidateFoundation4[] = "a0+B/4";
110*d9f75844SAndroid Build Coastguard Worker static const char kAttributeCryptoVoice[] =
111*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
112*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
113*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n";
114*d9f75844SAndroid Build Coastguard Worker static const char kAttributeCryptoVideo[] =
115*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
116*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n";
117*d9f75844SAndroid Build Coastguard Worker static const char kFingerprint[] =
118*d9f75844SAndroid Build Coastguard Worker     "a=fingerprint:sha-1 "
119*d9f75844SAndroid Build Coastguard Worker     "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n";
120*d9f75844SAndroid Build Coastguard Worker static const char kExtmapAllowMixed[] = "a=extmap-allow-mixed\r\n";
121*d9f75844SAndroid Build Coastguard Worker static const int kExtmapId = 1;
122*d9f75844SAndroid Build Coastguard Worker static const char kExtmapUri[] = "http://example.com/082005/ext.htm#ttime";
123*d9f75844SAndroid Build Coastguard Worker static const char kExtmap[] =
124*d9f75844SAndroid Build Coastguard Worker     "a=extmap:1 http://example.com/082005/ext.htm#ttime\r\n";
125*d9f75844SAndroid Build Coastguard Worker static const char kExtmapWithDirectionAndAttribute[] =
126*d9f75844SAndroid Build Coastguard Worker     "a=extmap:1/sendrecv http://example.com/082005/ext.htm#ttime a1 a2\r\n";
127*d9f75844SAndroid Build Coastguard Worker static const char kExtmapWithDirectionAndAttributeEncrypted[] =
128*d9f75844SAndroid Build Coastguard Worker     "a=extmap:1/sendrecv urn:ietf:params:rtp-hdrext:encrypt "
129*d9f75844SAndroid Build Coastguard Worker     "http://example.com/082005/ext.htm#ttime a1 a2\r\n";
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker static const uint8_t kIdentityDigest[] = {
132*d9f75844SAndroid Build Coastguard Worker     0x4A, 0xAD, 0xB9, 0xB1, 0x3F, 0x82, 0x18, 0x3B, 0x54, 0x02,
133*d9f75844SAndroid Build Coastguard Worker     0x12, 0xDF, 0x3E, 0x5D, 0x49, 0x6B, 0x19, 0xE5, 0x7C, 0xAB};
134*d9f75844SAndroid Build Coastguard Worker 
135*d9f75844SAndroid Build Coastguard Worker static const char kDtlsSctp[] = "DTLS/SCTP";
136*d9f75844SAndroid Build Coastguard Worker static const char kUdpDtlsSctp[] = "UDP/DTLS/SCTP";
137*d9f75844SAndroid Build Coastguard Worker static const char kTcpDtlsSctp[] = "TCP/DTLS/SCTP";
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker struct CodecParams {
140*d9f75844SAndroid Build Coastguard Worker   int max_ptime;
141*d9f75844SAndroid Build Coastguard Worker   int ptime;
142*d9f75844SAndroid Build Coastguard Worker   int min_ptime;
143*d9f75844SAndroid Build Coastguard Worker   int sprop_stereo;
144*d9f75844SAndroid Build Coastguard Worker   int stereo;
145*d9f75844SAndroid Build Coastguard Worker   int useinband;
146*d9f75844SAndroid Build Coastguard Worker   int maxaveragebitrate;
147*d9f75844SAndroid Build Coastguard Worker };
148*d9f75844SAndroid Build Coastguard Worker 
149*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): In these reference strings, use "a=fingerprint" by default
150*d9f75844SAndroid Build Coastguard Worker // instead of "a=crypto", and have an explicit test for adding "a=crypto".
151*d9f75844SAndroid Build Coastguard Worker // Currently it's the other way around.
152*d9f75844SAndroid Build Coastguard Worker 
153*d9f75844SAndroid Build Coastguard Worker // Reference sdp string
154*d9f75844SAndroid Build Coastguard Worker static const char kSdpFullString[] =
155*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
156*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
157*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
158*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
159*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
160*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
161*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
162*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
163*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
164*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
165*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
166*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
167*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
168*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
169*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
170*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
171*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
172*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
173*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
174*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
175*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
176*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
177*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
178*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
179*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
180*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
181*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
182*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
183*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
184*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
185*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
186*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
187*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
188*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
189*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
190*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n"
191*d9f75844SAndroid Build Coastguard Worker     "m=video 3457 RTP/SAVPF 120\r\n"
192*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.224.39\r\n"
193*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:3456 IN IP4 74.125.224.39\r\n"
194*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host "
195*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
196*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host "
197*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
198*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host "
199*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
200*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host "
201*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
202*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay "
203*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
204*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
205*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
206*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
207*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
208*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
209*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
210*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
211*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
212*d9f75844SAndroid Build Coastguard Worker     "a=ssrc-group:FEC 2 3\r\n"
213*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
214*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n"
215*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 cname:stream_1_cname\r\n"
216*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n";
217*d9f75844SAndroid Build Coastguard Worker 
218*d9f75844SAndroid Build Coastguard Worker // SDP reference string without the candidates.
219*d9f75844SAndroid Build Coastguard Worker static const char kSdpString[] =
220*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
221*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
222*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
223*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
224*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
225*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
226*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
227*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
228*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
229*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
230*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
231*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
232*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
233*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
234*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
235*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
236*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
237*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
238*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
239*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
240*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
241*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n"
242*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
243*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
244*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
245*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
246*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
247*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
248*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
249*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
250*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
251*d9f75844SAndroid Build Coastguard Worker     "a=ssrc-group:FEC 2 3\r\n"
252*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
253*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n"
254*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 cname:stream_1_cname\r\n"
255*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n";
256*d9f75844SAndroid Build Coastguard Worker 
257*d9f75844SAndroid Build Coastguard Worker // draft-ietf-mmusic-sctp-sdp-03
258*d9f75844SAndroid Build Coastguard Worker static const char kSdpSctpDataChannelString[] =
259*d9f75844SAndroid Build Coastguard Worker     "m=application 9 UDP/DTLS/SCTP 5000\r\n"
260*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
261*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_data\r\n"
262*d9f75844SAndroid Build Coastguard Worker     "a=ice-pwd:pwd_data\r\n"
263*d9f75844SAndroid Build Coastguard Worker     "a=mid:data_content_name\r\n"
264*d9f75844SAndroid Build Coastguard Worker     "a=sctpmap:5000 webrtc-datachannel 1024\r\n";
265*d9f75844SAndroid Build Coastguard Worker 
266*d9f75844SAndroid Build Coastguard Worker // draft-ietf-mmusic-sctp-sdp-12
267*d9f75844SAndroid Build Coastguard Worker // Note - this is invalid per draft-ietf-mmusic-sctp-sdp-26,
268*d9f75844SAndroid Build Coastguard Worker // since the separator after "sctp-port" needs to be a colon.
269*d9f75844SAndroid Build Coastguard Worker static const char kSdpSctpDataChannelStringWithSctpPort[] =
270*d9f75844SAndroid Build Coastguard Worker     "m=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n"
271*d9f75844SAndroid Build Coastguard Worker     "a=sctp-port 5000\r\n"
272*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
273*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_data\r\n"
274*d9f75844SAndroid Build Coastguard Worker     "a=ice-pwd:pwd_data\r\n"
275*d9f75844SAndroid Build Coastguard Worker     "a=mid:data_content_name\r\n";
276*d9f75844SAndroid Build Coastguard Worker 
277*d9f75844SAndroid Build Coastguard Worker // draft-ietf-mmusic-sctp-sdp-26
278*d9f75844SAndroid Build Coastguard Worker static const char kSdpSctpDataChannelStringWithSctpColonPort[] =
279*d9f75844SAndroid Build Coastguard Worker     "m=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n"
280*d9f75844SAndroid Build Coastguard Worker     "a=sctp-port:5000\r\n"
281*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
282*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_data\r\n"
283*d9f75844SAndroid Build Coastguard Worker     "a=ice-pwd:pwd_data\r\n"
284*d9f75844SAndroid Build Coastguard Worker     "a=mid:data_content_name\r\n";
285*d9f75844SAndroid Build Coastguard Worker 
286*d9f75844SAndroid Build Coastguard Worker static const char kSdpSctpDataChannelWithCandidatesString[] =
287*d9f75844SAndroid Build Coastguard Worker     "m=application 2345 UDP/DTLS/SCTP 5000\r\n"
288*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
289*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
290*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
291*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
292*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
293*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
294*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
295*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
296*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_data\r\n"
297*d9f75844SAndroid Build Coastguard Worker     "a=ice-pwd:pwd_data\r\n"
298*d9f75844SAndroid Build Coastguard Worker     "a=mid:data_content_name\r\n"
299*d9f75844SAndroid Build Coastguard Worker     "a=sctpmap:5000 webrtc-datachannel 1024\r\n";
300*d9f75844SAndroid Build Coastguard Worker 
301*d9f75844SAndroid Build Coastguard Worker static const char kSdpConferenceString[] =
302*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
303*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
304*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
305*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
306*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS\r\n"
307*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
308*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
309*d9f75844SAndroid Build Coastguard Worker     "a=x-google-flag:conference\r\n"
310*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
311*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
312*d9f75844SAndroid Build Coastguard Worker     "a=x-google-flag:conference\r\n";
313*d9f75844SAndroid Build Coastguard Worker 
314*d9f75844SAndroid Build Coastguard Worker static const char kSdpSessionString[] =
315*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
316*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
317*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
318*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
319*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream\r\n";
320*d9f75844SAndroid Build Coastguard Worker 
321*d9f75844SAndroid Build Coastguard Worker static const char kSdpAudioString[] =
322*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111\r\n"
323*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
324*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
325*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
326*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
327*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
328*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
329*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
330*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream audio_track_id_1\r\n";
331*d9f75844SAndroid Build Coastguard Worker 
332*d9f75844SAndroid Build Coastguard Worker static const char kSdpVideoString[] =
333*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
334*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
335*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
336*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
337*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
338*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
339*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
340*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
341*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 msid:local_stream video_track_id_1\r\n";
342*d9f75844SAndroid Build Coastguard Worker 
343*d9f75844SAndroid Build Coastguard Worker // Reference sdp string using bundle-only.
344*d9f75844SAndroid Build Coastguard Worker static const char kBundleOnlySdpFullString[] =
345*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
346*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
347*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
348*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
349*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
350*d9f75844SAndroid Build Coastguard Worker     "a=group:BUNDLE audio_content_name video_content_name\r\n"
351*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
352*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
353*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
354*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
355*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
356*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
357*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
358*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
359*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
360*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
361*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
362*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
363*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
364*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
365*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
366*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
367*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
368*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
369*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
370*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
371*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
372*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
373*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
374*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
375*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
376*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
377*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
378*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
379*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
380*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
381*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n"
382*d9f75844SAndroid Build Coastguard Worker     "m=video 0 RTP/SAVPF 120\r\n"
383*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
384*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
385*d9f75844SAndroid Build Coastguard Worker     "a=bundle-only\r\n"
386*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
387*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
388*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
389*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
390*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
391*d9f75844SAndroid Build Coastguard Worker     "a=ssrc-group:FEC 2 3\r\n"
392*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
393*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n"
394*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 cname:stream_1_cname\r\n"
395*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n";
396*d9f75844SAndroid Build Coastguard Worker 
397*d9f75844SAndroid Build Coastguard Worker // Plan B SDP reference string, with 2 streams, 2 audio tracks and 3 video
398*d9f75844SAndroid Build Coastguard Worker // tracks.
399*d9f75844SAndroid Build Coastguard Worker static const char kPlanBSdpFullString[] =
400*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
401*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
402*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
403*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
404*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
405*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1 local_stream_2\r\n"
406*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
407*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
408*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
409*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
410*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
411*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
412*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
413*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
414*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
415*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
416*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
417*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
418*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
419*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
420*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
421*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
422*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
423*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
424*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
425*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
426*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
427*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
428*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
429*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
430*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
431*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
432*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
433*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
434*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
435*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n"
436*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:4 cname:stream_2_cname\r\n"
437*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:4 msid:local_stream_2 audio_track_id_2\r\n"
438*d9f75844SAndroid Build Coastguard Worker     "m=video 3457 RTP/SAVPF 120\r\n"
439*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.224.39\r\n"
440*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:3456 IN IP4 74.125.224.39\r\n"
441*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host "
442*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
443*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host "
444*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
445*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host "
446*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
447*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host "
448*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
449*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay "
450*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
451*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
452*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
453*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
454*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
455*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
456*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
457*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
458*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
459*d9f75844SAndroid Build Coastguard Worker     "a=ssrc-group:FEC 2 3\r\n"
460*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
461*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 msid:local_stream_1 video_track_id_1\r\n"
462*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 cname:stream_1_cname\r\n"
463*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n"
464*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:5 cname:stream_2_cname\r\n"
465*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:5 msid:local_stream_2 video_track_id_2\r\n"
466*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:6 cname:stream_2_cname\r\n"
467*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:6 msid:local_stream_2 video_track_id_3\r\n";
468*d9f75844SAndroid Build Coastguard Worker 
469*d9f75844SAndroid Build Coastguard Worker // Unified Plan SDP reference string, with 2 streams, 2 audio tracks and 3 video
470*d9f75844SAndroid Build Coastguard Worker // tracks.
471*d9f75844SAndroid Build Coastguard Worker static const char kUnifiedPlanSdpFullString[] =
472*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
473*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
474*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
475*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
476*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
477*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
478*d9f75844SAndroid Build Coastguard Worker     // Audio track 1, stream 1 (with candidates).
479*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
480*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
481*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
482*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
483*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
484*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
485*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
486*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
487*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
488*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
489*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
490*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
491*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
492*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
493*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
494*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
495*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
496*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
497*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
498*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 audio_track_id_1\r\n"
499*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
500*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
501*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
502*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
503*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
504*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
505*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
506*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
507*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
508*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
509*d9f75844SAndroid Build Coastguard Worker     // Video track 1, stream 1 (with candidates).
510*d9f75844SAndroid Build Coastguard Worker     "m=video 3457 RTP/SAVPF 120\r\n"
511*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.224.39\r\n"
512*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:3456 IN IP4 74.125.224.39\r\n"
513*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host "
514*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
515*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host "
516*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
517*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host "
518*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
519*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host "
520*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
521*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay "
522*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
523*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
524*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
525*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
526*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
527*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 video_track_id_1\r\n"
528*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
529*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
530*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
531*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
532*d9f75844SAndroid Build Coastguard Worker     "a=ssrc-group:FEC 2 3\r\n"
533*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:2 cname:stream_1_cname\r\n"
534*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:3 cname:stream_1_cname\r\n"
535*d9f75844SAndroid Build Coastguard Worker     // Audio track 2, stream 2.
536*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
537*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
538*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
539*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice_2\r\na=ice-pwd:pwd_voice_2\r\n"
540*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name_2\r\n"
541*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 audio_track_id_2\r\n"
542*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
543*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
544*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
545*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
546*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
547*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
548*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
549*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
550*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
551*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:4 cname:stream_2_cname\r\n"
552*d9f75844SAndroid Build Coastguard Worker     // Video track 2, stream 2.
553*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
554*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
555*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
556*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video_2\r\na=ice-pwd:pwd_video_2\r\n"
557*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name_2\r\n"
558*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 video_track_id_2\r\n"
559*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
560*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
561*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
562*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
563*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:5 cname:stream_2_cname\r\n"
564*d9f75844SAndroid Build Coastguard Worker     // Video track 3, stream 2.
565*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
566*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
567*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
568*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video_3\r\na=ice-pwd:pwd_video_3\r\n"
569*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name_3\r\n"
570*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 video_track_id_3\r\n"
571*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
572*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
573*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
574*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
575*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:6 cname:stream_2_cname\r\n";
576*d9f75844SAndroid Build Coastguard Worker 
577*d9f75844SAndroid Build Coastguard Worker // Unified Plan SDP reference string:
578*d9f75844SAndroid Build Coastguard Worker // - audio track 1 has 1 a=msid lines
579*d9f75844SAndroid Build Coastguard Worker // - audio track 2 has 2 a=msid lines
580*d9f75844SAndroid Build Coastguard Worker // - audio track 3 has 1 a=msid line with the special "-" marker signifying that
581*d9f75844SAndroid Build Coastguard Worker //   there are 0 media stream ids.
582*d9f75844SAndroid Build Coastguard Worker // This Unified Plan SDP represents a SDP that signals the msid using both
583*d9f75844SAndroid Build Coastguard Worker // a=msid and a=ssrc msid semantics.
584*d9f75844SAndroid Build Coastguard Worker static const char kUnifiedPlanSdpFullStringWithSpecialMsid[] =
585*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
586*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
587*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
588*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
589*d9f75844SAndroid Build Coastguard Worker     "a=extmap-allow-mixed\r\n"
590*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
591*d9f75844SAndroid Build Coastguard Worker     // Audio track 1, with 1 stream id.
592*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
593*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
594*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
595*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
596*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
597*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
598*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
599*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
600*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
601*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
602*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
603*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
604*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
605*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
606*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
607*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
608*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
609*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
610*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
611*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
612*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 audio_track_id_1\r\n"
613*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
614*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
615*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
616*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
617*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
618*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
619*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
620*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
621*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 cname:stream_1_cname\r\n"
622*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1\r\n"
623*d9f75844SAndroid Build Coastguard Worker     // Audio track 2, with two stream ids.
624*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
625*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
626*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
627*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice_2\r\na=ice-pwd:pwd_voice_2\r\n"
628*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name_2\r\n"
629*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
630*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 audio_track_id_2\r\n"
631*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 audio_track_id_2\r\n"
632*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
633*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
634*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
635*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
636*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
637*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
638*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
639*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
640*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:4 cname:stream_1_cname\r\n"
641*d9f75844SAndroid Build Coastguard Worker     // The support for Plan B msid signaling only includes the
642*d9f75844SAndroid Build Coastguard Worker     // first media stream id "local_stream_1."
643*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:4 msid:local_stream_1 audio_track_id_2\r\n"
644*d9f75844SAndroid Build Coastguard Worker     // Audio track 3, with no stream ids.
645*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
646*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
647*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
648*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice_3\r\na=ice-pwd:pwd_voice_3\r\n"
649*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name_3\r\n"
650*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
651*d9f75844SAndroid Build Coastguard Worker     "a=msid:- audio_track_id_3\r\n"
652*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
653*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
654*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
655*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
656*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
657*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
658*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
659*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
660*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:7 cname:stream_2_cname\r\n"
661*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:7 msid:- audio_track_id_3\r\n";
662*d9f75844SAndroid Build Coastguard Worker 
663*d9f75844SAndroid Build Coastguard Worker // SDP string for unified plan without SSRCs
664*d9f75844SAndroid Build Coastguard Worker static const char kUnifiedPlanSdpFullStringNoSsrc[] =
665*d9f75844SAndroid Build Coastguard Worker     "v=0\r\n"
666*d9f75844SAndroid Build Coastguard Worker     "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
667*d9f75844SAndroid Build Coastguard Worker     "s=-\r\n"
668*d9f75844SAndroid Build Coastguard Worker     "t=0 0\r\n"
669*d9f75844SAndroid Build Coastguard Worker     "a=msid-semantic: WMS local_stream_1\r\n"
670*d9f75844SAndroid Build Coastguard Worker     // Audio track 1, stream 1 (with candidates).
671*d9f75844SAndroid Build Coastguard Worker     "m=audio 2345 RTP/SAVPF 111 103 104\r\n"
672*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.127.126\r\n"
673*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:2347 IN IP4 74.125.127.126\r\n"
674*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
675*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
676*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
677*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
678*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host "
679*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
680*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host "
681*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
682*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
683*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2346 "
684*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
685*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx "
686*d9f75844SAndroid Build Coastguard Worker     "raddr 192.168.1.5 rport 2348 "
687*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
688*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
689*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name\r\n"
690*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 audio_track_id_1\r\n"
691*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
692*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
693*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
694*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
695*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
696*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
697*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
698*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
699*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
700*d9f75844SAndroid Build Coastguard Worker     // Video track 1, stream 1 (with candidates).
701*d9f75844SAndroid Build Coastguard Worker     "m=video 3457 RTP/SAVPF 120\r\n"
702*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 74.125.224.39\r\n"
703*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:3456 IN IP4 74.125.224.39\r\n"
704*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host "
705*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
706*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host "
707*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
708*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host "
709*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
710*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host "
711*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
712*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay "
713*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
714*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay "
715*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n"
716*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video\r\na=ice-pwd:pwd_video\r\n"
717*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name\r\n"
718*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_1 video_track_id_1\r\n"
719*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
720*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
721*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
722*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
723*d9f75844SAndroid Build Coastguard Worker     // Audio track 2, stream 2.
724*d9f75844SAndroid Build Coastguard Worker     "m=audio 9 RTP/SAVPF 111 103 104\r\n"
725*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
726*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
727*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_voice_2\r\na=ice-pwd:pwd_voice_2\r\n"
728*d9f75844SAndroid Build Coastguard Worker     "a=mid:audio_content_name_2\r\n"
729*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 audio_track_id_2\r\n"
730*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
731*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-mux\r\n"
732*d9f75844SAndroid Build Coastguard Worker     "a=rtcp-rsize\r\n"
733*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
734*d9f75844SAndroid Build Coastguard Worker     "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
735*d9f75844SAndroid Build Coastguard Worker     "dummy_session_params\r\n"
736*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:111 opus/48000/2\r\n"
737*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:103 ISAC/16000\r\n"
738*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:104 ISAC/32000\r\n"
739*d9f75844SAndroid Build Coastguard Worker     // Video track 2, stream 2.
740*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
741*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
742*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
743*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video_2\r\na=ice-pwd:pwd_video_2\r\n"
744*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name_2\r\n"
745*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 video_track_id_2\r\n"
746*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
747*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
748*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
749*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n"
750*d9f75844SAndroid Build Coastguard Worker     // Video track 3, stream 2.
751*d9f75844SAndroid Build Coastguard Worker     "m=video 9 RTP/SAVPF 120\r\n"
752*d9f75844SAndroid Build Coastguard Worker     "c=IN IP4 0.0.0.0\r\n"
753*d9f75844SAndroid Build Coastguard Worker     "a=rtcp:9 IN IP4 0.0.0.0\r\n"
754*d9f75844SAndroid Build Coastguard Worker     "a=ice-ufrag:ufrag_video_3\r\na=ice-pwd:pwd_video_3\r\n"
755*d9f75844SAndroid Build Coastguard Worker     "a=mid:video_content_name_3\r\n"
756*d9f75844SAndroid Build Coastguard Worker     "a=msid:local_stream_2 video_track_id_3\r\n"
757*d9f75844SAndroid Build Coastguard Worker     "a=sendrecv\r\n"
758*d9f75844SAndroid Build Coastguard Worker     "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
759*d9f75844SAndroid Build Coastguard Worker     "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32\r\n"
760*d9f75844SAndroid Build Coastguard Worker     "a=rtpmap:120 VP8/90000\r\n";
761*d9f75844SAndroid Build Coastguard Worker 
762*d9f75844SAndroid Build Coastguard Worker // One candidate reference string as per W3c spec.
763*d9f75844SAndroid Build Coastguard Worker // candidate:<blah> not a=candidate:<blah>CRLF
764*d9f75844SAndroid Build Coastguard Worker static const char kRawCandidate[] =
765*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2";
766*d9f75844SAndroid Build Coastguard Worker // One candidate reference string.
767*d9f75844SAndroid Build Coastguard Worker static const char kSdpOneCandidate[] =
768*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
769*d9f75844SAndroid Build Coastguard Worker     "generation 2\r\n";
770*d9f75844SAndroid Build Coastguard Worker 
771*d9f75844SAndroid Build Coastguard Worker static const char kSdpTcpActiveCandidate[] =
772*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9 typ host "
773*d9f75844SAndroid Build Coastguard Worker     "tcptype active generation 2";
774*d9f75844SAndroid Build Coastguard Worker static const char kSdpTcpPassiveCandidate[] =
775*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9 typ host "
776*d9f75844SAndroid Build Coastguard Worker     "tcptype passive generation 2";
777*d9f75844SAndroid Build Coastguard Worker static const char kSdpTcpSOCandidate[] =
778*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9 typ host "
779*d9f75844SAndroid Build Coastguard Worker     "tcptype so generation 2";
780*d9f75844SAndroid Build Coastguard Worker static const char kSdpTcpInvalidCandidate[] =
781*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9 typ host "
782*d9f75844SAndroid Build Coastguard Worker     "tcptype invalid generation 2";
783*d9f75844SAndroid Build Coastguard Worker 
784*d9f75844SAndroid Build Coastguard Worker // One candidate reference string with IPV6 address.
785*d9f75844SAndroid Build Coastguard Worker static const char kRawIPV6Candidate[] =
786*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 udp 2130706432 "
787*d9f75844SAndroid Build Coastguard Worker     "abcd:abcd:abcd:abcd:abcd:abcd:abcd:abcd 1234 typ host generation 2";
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker // One candidate reference string.
790*d9f75844SAndroid Build Coastguard Worker static const char kSdpOneCandidateWithUfragPwd[] =
791*d9f75844SAndroid Build Coastguard Worker     "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host network_name"
792*d9f75844SAndroid Build Coastguard Worker     " eth0 ufrag user_rtp pwd password_rtp generation 2\r\n";
793*d9f75844SAndroid Build Coastguard Worker 
794*d9f75844SAndroid Build Coastguard Worker static const char kRawHostnameCandidate[] =
795*d9f75844SAndroid Build Coastguard Worker     "candidate:a0+B/1 1 udp 2130706432 a.test 1234 typ host generation 2";
796*d9f75844SAndroid Build Coastguard Worker 
797*d9f75844SAndroid Build Coastguard Worker // Session id and version
798*d9f75844SAndroid Build Coastguard Worker static const char kSessionId[] = "18446744069414584320";
799*d9f75844SAndroid Build Coastguard Worker static const char kSessionVersion[] = "18446462598732840960";
800*d9f75844SAndroid Build Coastguard Worker 
801*d9f75844SAndroid Build Coastguard Worker // ICE options.
802*d9f75844SAndroid Build Coastguard Worker static const char kIceOption1[] = "iceoption1";
803*d9f75844SAndroid Build Coastguard Worker static const char kIceOption2[] = "iceoption2";
804*d9f75844SAndroid Build Coastguard Worker static const char kIceOption3[] = "iceoption3";
805*d9f75844SAndroid Build Coastguard Worker 
806*d9f75844SAndroid Build Coastguard Worker // ICE ufrags/passwords.
807*d9f75844SAndroid Build Coastguard Worker static const char kUfragVoice[] = "ufrag_voice";
808*d9f75844SAndroid Build Coastguard Worker static const char kPwdVoice[] = "pwd_voice";
809*d9f75844SAndroid Build Coastguard Worker static const char kUfragVideo[] = "ufrag_video";
810*d9f75844SAndroid Build Coastguard Worker static const char kPwdVideo[] = "pwd_video";
811*d9f75844SAndroid Build Coastguard Worker static const char kUfragData[] = "ufrag_data";
812*d9f75844SAndroid Build Coastguard Worker static const char kPwdData[] = "pwd_data";
813*d9f75844SAndroid Build Coastguard Worker 
814*d9f75844SAndroid Build Coastguard Worker // Extra ufrags/passwords for extra unified plan m= sections.
815*d9f75844SAndroid Build Coastguard Worker static const char kUfragVoice2[] = "ufrag_voice_2";
816*d9f75844SAndroid Build Coastguard Worker static const char kPwdVoice2[] = "pwd_voice_2";
817*d9f75844SAndroid Build Coastguard Worker static const char kUfragVoice3[] = "ufrag_voice_3";
818*d9f75844SAndroid Build Coastguard Worker static const char kPwdVoice3[] = "pwd_voice_3";
819*d9f75844SAndroid Build Coastguard Worker static const char kUfragVideo2[] = "ufrag_video_2";
820*d9f75844SAndroid Build Coastguard Worker static const char kPwdVideo2[] = "pwd_video_2";
821*d9f75844SAndroid Build Coastguard Worker static const char kUfragVideo3[] = "ufrag_video_3";
822*d9f75844SAndroid Build Coastguard Worker static const char kPwdVideo3[] = "pwd_video_3";
823*d9f75844SAndroid Build Coastguard Worker 
824*d9f75844SAndroid Build Coastguard Worker // Content name
825*d9f75844SAndroid Build Coastguard Worker static const char kAudioContentName[] = "audio_content_name";
826*d9f75844SAndroid Build Coastguard Worker static const char kVideoContentName[] = "video_content_name";
827*d9f75844SAndroid Build Coastguard Worker static const char kDataContentName[] = "data_content_name";
828*d9f75844SAndroid Build Coastguard Worker 
829*d9f75844SAndroid Build Coastguard Worker // Extra content names for extra unified plan m= sections.
830*d9f75844SAndroid Build Coastguard Worker static const char kAudioContentName2[] = "audio_content_name_2";
831*d9f75844SAndroid Build Coastguard Worker static const char kAudioContentName3[] = "audio_content_name_3";
832*d9f75844SAndroid Build Coastguard Worker static const char kVideoContentName2[] = "video_content_name_2";
833*d9f75844SAndroid Build Coastguard Worker static const char kVideoContentName3[] = "video_content_name_3";
834*d9f75844SAndroid Build Coastguard Worker 
835*d9f75844SAndroid Build Coastguard Worker // MediaStream 1
836*d9f75844SAndroid Build Coastguard Worker static const char kStreamId1[] = "local_stream_1";
837*d9f75844SAndroid Build Coastguard Worker static const char kStream1Cname[] = "stream_1_cname";
838*d9f75844SAndroid Build Coastguard Worker static const char kAudioTrackId1[] = "audio_track_id_1";
839*d9f75844SAndroid Build Coastguard Worker static const uint32_t kAudioTrack1Ssrc = 1;
840*d9f75844SAndroid Build Coastguard Worker static const char kVideoTrackId1[] = "video_track_id_1";
841*d9f75844SAndroid Build Coastguard Worker static const uint32_t kVideoTrack1Ssrc1 = 2;
842*d9f75844SAndroid Build Coastguard Worker static const uint32_t kVideoTrack1Ssrc2 = 3;
843*d9f75844SAndroid Build Coastguard Worker 
844*d9f75844SAndroid Build Coastguard Worker // MediaStream 2
845*d9f75844SAndroid Build Coastguard Worker static const char kStreamId2[] = "local_stream_2";
846*d9f75844SAndroid Build Coastguard Worker static const char kStream2Cname[] = "stream_2_cname";
847*d9f75844SAndroid Build Coastguard Worker static const char kAudioTrackId2[] = "audio_track_id_2";
848*d9f75844SAndroid Build Coastguard Worker static const uint32_t kAudioTrack2Ssrc = 4;
849*d9f75844SAndroid Build Coastguard Worker static const char kVideoTrackId2[] = "video_track_id_2";
850*d9f75844SAndroid Build Coastguard Worker static const uint32_t kVideoTrack2Ssrc = 5;
851*d9f75844SAndroid Build Coastguard Worker static const char kVideoTrackId3[] = "video_track_id_3";
852*d9f75844SAndroid Build Coastguard Worker static const uint32_t kVideoTrack3Ssrc = 6;
853*d9f75844SAndroid Build Coastguard Worker static const char kAudioTrackId3[] = "audio_track_id_3";
854*d9f75844SAndroid Build Coastguard Worker static const uint32_t kAudioTrack3Ssrc = 7;
855*d9f75844SAndroid Build Coastguard Worker 
856*d9f75844SAndroid Build Coastguard Worker // Candidate
857*d9f75844SAndroid Build Coastguard Worker static const char kDummyMid[] = "dummy_mid";
858*d9f75844SAndroid Build Coastguard Worker static const int kDummyIndex = 123;
859*d9f75844SAndroid Build Coastguard Worker 
860*d9f75844SAndroid Build Coastguard Worker // Misc
861*d9f75844SAndroid Build Coastguard Worker static SdpType kDummyType = SdpType::kOffer;
862*d9f75844SAndroid Build Coastguard Worker 
863*d9f75844SAndroid Build Coastguard Worker // Helper functions
864*d9f75844SAndroid Build Coastguard Worker 
SdpDeserialize(const std::string & message,JsepSessionDescription * jdesc)865*d9f75844SAndroid Build Coastguard Worker static bool SdpDeserialize(const std::string& message,
866*d9f75844SAndroid Build Coastguard Worker                            JsepSessionDescription* jdesc) {
867*d9f75844SAndroid Build Coastguard Worker   return webrtc::SdpDeserialize(message, jdesc, NULL);
868*d9f75844SAndroid Build Coastguard Worker }
869*d9f75844SAndroid Build Coastguard Worker 
SdpDeserializeCandidate(const std::string & message,JsepIceCandidate * candidate)870*d9f75844SAndroid Build Coastguard Worker static bool SdpDeserializeCandidate(const std::string& message,
871*d9f75844SAndroid Build Coastguard Worker                                     JsepIceCandidate* candidate) {
872*d9f75844SAndroid Build Coastguard Worker   return webrtc::SdpDeserializeCandidate(message, candidate, NULL);
873*d9f75844SAndroid Build Coastguard Worker }
874*d9f75844SAndroid Build Coastguard Worker 
875*d9f75844SAndroid Build Coastguard Worker // Add some extra `newlines` to the `message` after `line`.
InjectAfter(const std::string & line,const std::string & newlines,std::string * message)876*d9f75844SAndroid Build Coastguard Worker static void InjectAfter(const std::string& line,
877*d9f75844SAndroid Build Coastguard Worker                         const std::string& newlines,
878*d9f75844SAndroid Build Coastguard Worker                         std::string* message) {
879*d9f75844SAndroid Build Coastguard Worker   absl::StrReplaceAll({{line, line + newlines}}, message);
880*d9f75844SAndroid Build Coastguard Worker }
881*d9f75844SAndroid Build Coastguard Worker 
Replace(const std::string & line,const std::string & newlines,std::string * message)882*d9f75844SAndroid Build Coastguard Worker static void Replace(const std::string& line,
883*d9f75844SAndroid Build Coastguard Worker                     const std::string& newlines,
884*d9f75844SAndroid Build Coastguard Worker                     std::string* message) {
885*d9f75844SAndroid Build Coastguard Worker   absl::StrReplaceAll({{line, newlines}}, message);
886*d9f75844SAndroid Build Coastguard Worker }
887*d9f75844SAndroid Build Coastguard Worker 
888*d9f75844SAndroid Build Coastguard Worker // Expect a parse failure on the line containing `bad_part` when attempting to
889*d9f75844SAndroid Build Coastguard Worker // parse `bad_sdp`.
ExpectParseFailure(const std::string & bad_sdp,const std::string & bad_part)890*d9f75844SAndroid Build Coastguard Worker static void ExpectParseFailure(const std::string& bad_sdp,
891*d9f75844SAndroid Build Coastguard Worker                                const std::string& bad_part) {
892*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription desc(kDummyType);
893*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
894*d9f75844SAndroid Build Coastguard Worker   bool ret = webrtc::SdpDeserialize(bad_sdp, &desc, &error);
895*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(ret);
896*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, error.line.find(bad_part.c_str()))
897*d9f75844SAndroid Build Coastguard Worker       << "Did not find " << bad_part << " in " << error.line;
898*d9f75844SAndroid Build Coastguard Worker }
899*d9f75844SAndroid Build Coastguard Worker 
900*d9f75844SAndroid Build Coastguard Worker // Expect fail to parse kSdpFullString if replace `good_part` with `bad_part`.
ExpectParseFailure(const char * good_part,const char * bad_part)901*d9f75844SAndroid Build Coastguard Worker static void ExpectParseFailure(const char* good_part, const char* bad_part) {
902*d9f75844SAndroid Build Coastguard Worker   std::string bad_sdp = kSdpFullString;
903*d9f75844SAndroid Build Coastguard Worker   Replace(good_part, bad_part, &bad_sdp);
904*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(bad_sdp, bad_part);
905*d9f75844SAndroid Build Coastguard Worker }
906*d9f75844SAndroid Build Coastguard Worker 
907*d9f75844SAndroid Build Coastguard Worker // Expect fail to parse kSdpFullString if add `newlines` after `injectpoint`.
ExpectParseFailureWithNewLines(const std::string & injectpoint,const std::string & newlines,const std::string & bad_part)908*d9f75844SAndroid Build Coastguard Worker static void ExpectParseFailureWithNewLines(const std::string& injectpoint,
909*d9f75844SAndroid Build Coastguard Worker                                            const std::string& newlines,
910*d9f75844SAndroid Build Coastguard Worker                                            const std::string& bad_part) {
911*d9f75844SAndroid Build Coastguard Worker   std::string bad_sdp = kSdpFullString;
912*d9f75844SAndroid Build Coastguard Worker   InjectAfter(injectpoint, newlines, &bad_sdp);
913*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(bad_sdp, bad_part);
914*d9f75844SAndroid Build Coastguard Worker }
915*d9f75844SAndroid Build Coastguard Worker 
ReplaceDirection(RtpTransceiverDirection direction,std::string * message)916*d9f75844SAndroid Build Coastguard Worker static void ReplaceDirection(RtpTransceiverDirection direction,
917*d9f75844SAndroid Build Coastguard Worker                              std::string* message) {
918*d9f75844SAndroid Build Coastguard Worker   std::string new_direction;
919*d9f75844SAndroid Build Coastguard Worker   switch (direction) {
920*d9f75844SAndroid Build Coastguard Worker     case RtpTransceiverDirection::kInactive:
921*d9f75844SAndroid Build Coastguard Worker       new_direction = "a=inactive";
922*d9f75844SAndroid Build Coastguard Worker       break;
923*d9f75844SAndroid Build Coastguard Worker     case RtpTransceiverDirection::kSendOnly:
924*d9f75844SAndroid Build Coastguard Worker       new_direction = "a=sendonly";
925*d9f75844SAndroid Build Coastguard Worker       break;
926*d9f75844SAndroid Build Coastguard Worker     case RtpTransceiverDirection::kRecvOnly:
927*d9f75844SAndroid Build Coastguard Worker       new_direction = "a=recvonly";
928*d9f75844SAndroid Build Coastguard Worker       break;
929*d9f75844SAndroid Build Coastguard Worker     case RtpTransceiverDirection::kSendRecv:
930*d9f75844SAndroid Build Coastguard Worker       new_direction = "a=sendrecv";
931*d9f75844SAndroid Build Coastguard Worker       break;
932*d9f75844SAndroid Build Coastguard Worker     case RtpTransceiverDirection::kStopped:
933*d9f75844SAndroid Build Coastguard Worker     default:
934*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
935*d9f75844SAndroid Build Coastguard Worker       new_direction = "a=sendrecv";
936*d9f75844SAndroid Build Coastguard Worker       break;
937*d9f75844SAndroid Build Coastguard Worker   }
938*d9f75844SAndroid Build Coastguard Worker   Replace("a=sendrecv", new_direction, message);
939*d9f75844SAndroid Build Coastguard Worker }
940*d9f75844SAndroid Build Coastguard Worker 
ReplaceRejected(bool audio_rejected,bool video_rejected,std::string * message)941*d9f75844SAndroid Build Coastguard Worker static void ReplaceRejected(bool audio_rejected,
942*d9f75844SAndroid Build Coastguard Worker                             bool video_rejected,
943*d9f75844SAndroid Build Coastguard Worker                             std::string* message) {
944*d9f75844SAndroid Build Coastguard Worker   if (audio_rejected) {
945*d9f75844SAndroid Build Coastguard Worker     Replace("m=audio 9", "m=audio 0", message);
946*d9f75844SAndroid Build Coastguard Worker     Replace(kAttributeIceUfragVoice, "", message);
947*d9f75844SAndroid Build Coastguard Worker     Replace(kAttributeIcePwdVoice, "", message);
948*d9f75844SAndroid Build Coastguard Worker   }
949*d9f75844SAndroid Build Coastguard Worker   if (video_rejected) {
950*d9f75844SAndroid Build Coastguard Worker     Replace("m=video 9", "m=video 0", message);
951*d9f75844SAndroid Build Coastguard Worker     Replace(kAttributeIceUfragVideo, "", message);
952*d9f75844SAndroid Build Coastguard Worker     Replace(kAttributeIcePwdVideo, "", message);
953*d9f75844SAndroid Build Coastguard Worker   }
954*d9f75844SAndroid Build Coastguard Worker }
955*d9f75844SAndroid Build Coastguard Worker 
956*d9f75844SAndroid Build Coastguard Worker // WebRtcSdpTest
957*d9f75844SAndroid Build Coastguard Worker 
958*d9f75844SAndroid Build Coastguard Worker class WebRtcSdpTest : public ::testing::Test {
959*d9f75844SAndroid Build Coastguard Worker  public:
WebRtcSdpTest()960*d9f75844SAndroid Build Coastguard Worker   WebRtcSdpTest() : jdesc_(kDummyType) {
961*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
962*d9f75844SAndroid Build Coastguard Worker     webrtc::InitializeAndroidObjects();
963*d9f75844SAndroid Build Coastguard Worker #endif
964*d9f75844SAndroid Build Coastguard Worker     // AudioContentDescription
965*d9f75844SAndroid Build Coastguard Worker     audio_desc_ = CreateAudioContentDescription();
966*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_stream;
967*d9f75844SAndroid Build Coastguard Worker     audio_stream.id = kAudioTrackId1;
968*d9f75844SAndroid Build Coastguard Worker     audio_stream.cname = kStream1Cname;
969*d9f75844SAndroid Build Coastguard Worker     audio_stream.set_stream_ids({kStreamId1});
970*d9f75844SAndroid Build Coastguard Worker     audio_stream.ssrcs.push_back(kAudioTrack1Ssrc);
971*d9f75844SAndroid Build Coastguard Worker     audio_desc_->AddStream(audio_stream);
972*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress audio_addr("74.125.127.126", 2345);
973*d9f75844SAndroid Build Coastguard Worker     audio_desc_->set_connection_address(audio_addr);
974*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp,
975*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_));
976*d9f75844SAndroid Build Coastguard Worker 
977*d9f75844SAndroid Build Coastguard Worker     // VideoContentDescription
978*d9f75844SAndroid Build Coastguard Worker     video_desc_ = CreateVideoContentDescription();
979*d9f75844SAndroid Build Coastguard Worker     StreamParams video_stream;
980*d9f75844SAndroid Build Coastguard Worker     video_stream.id = kVideoTrackId1;
981*d9f75844SAndroid Build Coastguard Worker     video_stream.cname = kStream1Cname;
982*d9f75844SAndroid Build Coastguard Worker     video_stream.set_stream_ids({kStreamId1});
983*d9f75844SAndroid Build Coastguard Worker     video_stream.ssrcs.push_back(kVideoTrack1Ssrc1);
984*d9f75844SAndroid Build Coastguard Worker     video_stream.ssrcs.push_back(kVideoTrack1Ssrc2);
985*d9f75844SAndroid Build Coastguard Worker     cricket::SsrcGroup ssrc_group(kFecSsrcGroupSemantics, video_stream.ssrcs);
986*d9f75844SAndroid Build Coastguard Worker     video_stream.ssrc_groups.push_back(ssrc_group);
987*d9f75844SAndroid Build Coastguard Worker     video_desc_->AddStream(video_stream);
988*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress video_addr("74.125.224.39", 3457);
989*d9f75844SAndroid Build Coastguard Worker     video_desc_->set_connection_address(video_addr);
990*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp,
991*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_));
992*d9f75844SAndroid Build Coastguard Worker 
993*d9f75844SAndroid Build Coastguard Worker     // TransportInfo
994*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
995*d9f75844SAndroid Build Coastguard Worker         kAudioContentName, TransportDescription(kUfragVoice, kPwdVoice)));
996*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
997*d9f75844SAndroid Build Coastguard Worker         kVideoContentName, TransportDescription(kUfragVideo, kPwdVideo)));
998*d9f75844SAndroid Build Coastguard Worker 
999*d9f75844SAndroid Build Coastguard Worker     // v4 host
1000*d9f75844SAndroid Build Coastguard Worker     int port = 1234;
1001*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress address("192.168.1.5", port++);
1002*d9f75844SAndroid Build Coastguard Worker     Candidate candidate1(ICE_CANDIDATE_COMPONENT_RTP, "udp", address,
1003*d9f75844SAndroid Build Coastguard Worker                          kCandidatePriority, "", "", LOCAL_PORT_TYPE,
1004*d9f75844SAndroid Build Coastguard Worker                          kCandidateGeneration, kCandidateFoundation1);
1005*d9f75844SAndroid Build Coastguard Worker     address.SetPort(port++);
1006*d9f75844SAndroid Build Coastguard Worker     Candidate candidate2(ICE_CANDIDATE_COMPONENT_RTCP, "udp", address,
1007*d9f75844SAndroid Build Coastguard Worker                          kCandidatePriority, "", "", LOCAL_PORT_TYPE,
1008*d9f75844SAndroid Build Coastguard Worker                          kCandidateGeneration, kCandidateFoundation1);
1009*d9f75844SAndroid Build Coastguard Worker     address.SetPort(port++);
1010*d9f75844SAndroid Build Coastguard Worker     Candidate candidate3(ICE_CANDIDATE_COMPONENT_RTCP, "udp", address,
1011*d9f75844SAndroid Build Coastguard Worker                          kCandidatePriority, "", "", LOCAL_PORT_TYPE,
1012*d9f75844SAndroid Build Coastguard Worker                          kCandidateGeneration, kCandidateFoundation1);
1013*d9f75844SAndroid Build Coastguard Worker     address.SetPort(port++);
1014*d9f75844SAndroid Build Coastguard Worker     Candidate candidate4(ICE_CANDIDATE_COMPONENT_RTP, "udp", address,
1015*d9f75844SAndroid Build Coastguard Worker                          kCandidatePriority, "", "", LOCAL_PORT_TYPE,
1016*d9f75844SAndroid Build Coastguard Worker                          kCandidateGeneration, kCandidateFoundation1);
1017*d9f75844SAndroid Build Coastguard Worker 
1018*d9f75844SAndroid Build Coastguard Worker     // v6 host
1019*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress v6_address("::1", port++);
1020*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate5(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
1021*d9f75844SAndroid Build Coastguard Worker                                   v6_address, kCandidatePriority, "", "",
1022*d9f75844SAndroid Build Coastguard Worker                                   cricket::LOCAL_PORT_TYPE,
1023*d9f75844SAndroid Build Coastguard Worker                                   kCandidateGeneration, kCandidateFoundation2);
1024*d9f75844SAndroid Build Coastguard Worker     v6_address.SetPort(port++);
1025*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate6(cricket::ICE_CANDIDATE_COMPONENT_RTCP, "udp",
1026*d9f75844SAndroid Build Coastguard Worker                                   v6_address, kCandidatePriority, "", "",
1027*d9f75844SAndroid Build Coastguard Worker                                   cricket::LOCAL_PORT_TYPE,
1028*d9f75844SAndroid Build Coastguard Worker                                   kCandidateGeneration, kCandidateFoundation2);
1029*d9f75844SAndroid Build Coastguard Worker     v6_address.SetPort(port++);
1030*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate7(cricket::ICE_CANDIDATE_COMPONENT_RTCP, "udp",
1031*d9f75844SAndroid Build Coastguard Worker                                   v6_address, kCandidatePriority, "", "",
1032*d9f75844SAndroid Build Coastguard Worker                                   cricket::LOCAL_PORT_TYPE,
1033*d9f75844SAndroid Build Coastguard Worker                                   kCandidateGeneration, kCandidateFoundation2);
1034*d9f75844SAndroid Build Coastguard Worker     v6_address.SetPort(port++);
1035*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate8(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
1036*d9f75844SAndroid Build Coastguard Worker                                   v6_address, kCandidatePriority, "", "",
1037*d9f75844SAndroid Build Coastguard Worker                                   cricket::LOCAL_PORT_TYPE,
1038*d9f75844SAndroid Build Coastguard Worker                                   kCandidateGeneration, kCandidateFoundation2);
1039*d9f75844SAndroid Build Coastguard Worker 
1040*d9f75844SAndroid Build Coastguard Worker     // stun
1041*d9f75844SAndroid Build Coastguard Worker     int port_stun = 2345;
1042*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress address_stun("74.125.127.126", port_stun++);
1043*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress rel_address_stun("192.168.1.5", port_stun++);
1044*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate9(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
1045*d9f75844SAndroid Build Coastguard Worker                                   address_stun, kCandidatePriority, "", "",
1046*d9f75844SAndroid Build Coastguard Worker                                   STUN_PORT_TYPE, kCandidateGeneration,
1047*d9f75844SAndroid Build Coastguard Worker                                   kCandidateFoundation3);
1048*d9f75844SAndroid Build Coastguard Worker     candidate9.set_related_address(rel_address_stun);
1049*d9f75844SAndroid Build Coastguard Worker 
1050*d9f75844SAndroid Build Coastguard Worker     address_stun.SetPort(port_stun++);
1051*d9f75844SAndroid Build Coastguard Worker     rel_address_stun.SetPort(port_stun++);
1052*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate10(cricket::ICE_CANDIDATE_COMPONENT_RTCP, "udp",
1053*d9f75844SAndroid Build Coastguard Worker                                    address_stun, kCandidatePriority, "", "",
1054*d9f75844SAndroid Build Coastguard Worker                                    STUN_PORT_TYPE, kCandidateGeneration,
1055*d9f75844SAndroid Build Coastguard Worker                                    kCandidateFoundation3);
1056*d9f75844SAndroid Build Coastguard Worker     candidate10.set_related_address(rel_address_stun);
1057*d9f75844SAndroid Build Coastguard Worker 
1058*d9f75844SAndroid Build Coastguard Worker     // relay
1059*d9f75844SAndroid Build Coastguard Worker     int port_relay = 3456;
1060*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress address_relay("74.125.224.39", port_relay++);
1061*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate11(cricket::ICE_CANDIDATE_COMPONENT_RTCP, "udp",
1062*d9f75844SAndroid Build Coastguard Worker                                    address_relay, kCandidatePriority, "", "",
1063*d9f75844SAndroid Build Coastguard Worker                                    cricket::RELAY_PORT_TYPE,
1064*d9f75844SAndroid Build Coastguard Worker                                    kCandidateGeneration, kCandidateFoundation4);
1065*d9f75844SAndroid Build Coastguard Worker     address_relay.SetPort(port_relay++);
1066*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate12(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
1067*d9f75844SAndroid Build Coastguard Worker                                    address_relay, kCandidatePriority, "", "",
1068*d9f75844SAndroid Build Coastguard Worker                                    RELAY_PORT_TYPE, kCandidateGeneration,
1069*d9f75844SAndroid Build Coastguard Worker                                    kCandidateFoundation4);
1070*d9f75844SAndroid Build Coastguard Worker 
1071*d9f75844SAndroid Build Coastguard Worker     // voice
1072*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate1);
1073*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate2);
1074*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate5);
1075*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate6);
1076*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate9);
1077*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate10);
1078*d9f75844SAndroid Build Coastguard Worker 
1079*d9f75844SAndroid Build Coastguard Worker     // video
1080*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate3);
1081*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate4);
1082*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate7);
1083*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate8);
1084*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate11);
1085*d9f75844SAndroid Build Coastguard Worker     candidates_.push_back(candidate12);
1086*d9f75844SAndroid Build Coastguard Worker 
1087*d9f75844SAndroid Build Coastguard Worker     jcandidate_.reset(
1088*d9f75844SAndroid Build Coastguard Worker         new JsepIceCandidate(std::string("audio_content_name"), 0, candidate1));
1089*d9f75844SAndroid Build Coastguard Worker 
1090*d9f75844SAndroid Build Coastguard Worker     // Set up JsepSessionDescription.
1091*d9f75844SAndroid Build Coastguard Worker     jdesc_.Initialize(desc_.Clone(), kSessionId, kSessionVersion);
1092*d9f75844SAndroid Build Coastguard Worker     std::string mline_id;
1093*d9f75844SAndroid Build Coastguard Worker     int mline_index = 0;
1094*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < candidates_.size(); ++i) {
1095*d9f75844SAndroid Build Coastguard Worker       // In this test, the audio m line index will be 0, and the video m line
1096*d9f75844SAndroid Build Coastguard Worker       // will be 1.
1097*d9f75844SAndroid Build Coastguard Worker       bool is_video = (i > 5);
1098*d9f75844SAndroid Build Coastguard Worker       mline_id = is_video ? "video_content_name" : "audio_content_name";
1099*d9f75844SAndroid Build Coastguard Worker       mline_index = is_video ? 1 : 0;
1100*d9f75844SAndroid Build Coastguard Worker       JsepIceCandidate jice(mline_id, mline_index, candidates_.at(i));
1101*d9f75844SAndroid Build Coastguard Worker       jdesc_.AddCandidate(&jice);
1102*d9f75844SAndroid Build Coastguard Worker     }
1103*d9f75844SAndroid Build Coastguard Worker   }
1104*d9f75844SAndroid Build Coastguard Worker 
RemoveVideoCandidates()1105*d9f75844SAndroid Build Coastguard Worker   void RemoveVideoCandidates() {
1106*d9f75844SAndroid Build Coastguard Worker     const IceCandidateCollection* video_candidates_collection =
1107*d9f75844SAndroid Build Coastguard Worker         jdesc_.candidates(1);
1108*d9f75844SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, video_candidates_collection);
1109*d9f75844SAndroid Build Coastguard Worker     std::vector<cricket::Candidate> video_candidates;
1110*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < video_candidates_collection->count(); ++i) {
1111*d9f75844SAndroid Build Coastguard Worker       cricket::Candidate c = video_candidates_collection->at(i)->candidate();
1112*d9f75844SAndroid Build Coastguard Worker       c.set_transport_name("video_content_name");
1113*d9f75844SAndroid Build Coastguard Worker       video_candidates.push_back(c);
1114*d9f75844SAndroid Build Coastguard Worker     }
1115*d9f75844SAndroid Build Coastguard Worker     jdesc_.RemoveCandidates(video_candidates);
1116*d9f75844SAndroid Build Coastguard Worker   }
1117*d9f75844SAndroid Build Coastguard Worker 
1118*d9f75844SAndroid Build Coastguard Worker   // Turns the existing reference description into a description using
1119*d9f75844SAndroid Build Coastguard Worker   // a=bundle-only. This means no transport attributes and a 0 port value on
1120*d9f75844SAndroid Build Coastguard Worker   // the m= sections not associated with the BUNDLE-tag.
MakeBundleOnlyDescription()1121*d9f75844SAndroid Build Coastguard Worker   void MakeBundleOnlyDescription() {
1122*d9f75844SAndroid Build Coastguard Worker     RemoveVideoCandidates();
1123*d9f75844SAndroid Build Coastguard Worker 
1124*d9f75844SAndroid Build Coastguard Worker     // And the rest of the transport attributes.
1125*d9f75844SAndroid Build Coastguard Worker     desc_.transport_infos()[1].description.ice_ufrag.clear();
1126*d9f75844SAndroid Build Coastguard Worker     desc_.transport_infos()[1].description.ice_pwd.clear();
1127*d9f75844SAndroid Build Coastguard Worker     desc_.transport_infos()[1].description.connection_role =
1128*d9f75844SAndroid Build Coastguard Worker         cricket::CONNECTIONROLE_NONE;
1129*d9f75844SAndroid Build Coastguard Worker 
1130*d9f75844SAndroid Build Coastguard Worker     // Set bundle-only flag.
1131*d9f75844SAndroid Build Coastguard Worker     desc_.contents()[1].bundle_only = true;
1132*d9f75844SAndroid Build Coastguard Worker 
1133*d9f75844SAndroid Build Coastguard Worker     // Add BUNDLE group.
1134*d9f75844SAndroid Build Coastguard Worker     ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1135*d9f75844SAndroid Build Coastguard Worker     group.AddContentName(kAudioContentName);
1136*d9f75844SAndroid Build Coastguard Worker     group.AddContentName(kVideoContentName);
1137*d9f75844SAndroid Build Coastguard Worker     desc_.AddGroup(group);
1138*d9f75844SAndroid Build Coastguard Worker 
1139*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1140*d9f75844SAndroid Build Coastguard Worker                                   jdesc_.session_version()));
1141*d9f75844SAndroid Build Coastguard Worker   }
1142*d9f75844SAndroid Build Coastguard Worker 
1143*d9f75844SAndroid Build Coastguard Worker   // Turns the existing reference description into a plan B description,
1144*d9f75844SAndroid Build Coastguard Worker   // with 2 audio tracks and 3 video tracks.
MakePlanBDescription()1145*d9f75844SAndroid Build Coastguard Worker   void MakePlanBDescription() {
1146*d9f75844SAndroid Build Coastguard Worker     audio_desc_ = new AudioContentDescription(*audio_desc_);
1147*d9f75844SAndroid Build Coastguard Worker     video_desc_ = new VideoContentDescription(*video_desc_);
1148*d9f75844SAndroid Build Coastguard Worker 
1149*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_track_2;
1150*d9f75844SAndroid Build Coastguard Worker     audio_track_2.id = kAudioTrackId2;
1151*d9f75844SAndroid Build Coastguard Worker     audio_track_2.cname = kStream2Cname;
1152*d9f75844SAndroid Build Coastguard Worker     audio_track_2.set_stream_ids({kStreamId2});
1153*d9f75844SAndroid Build Coastguard Worker     audio_track_2.ssrcs.push_back(kAudioTrack2Ssrc);
1154*d9f75844SAndroid Build Coastguard Worker     audio_desc_->AddStream(audio_track_2);
1155*d9f75844SAndroid Build Coastguard Worker 
1156*d9f75844SAndroid Build Coastguard Worker     StreamParams video_track_2;
1157*d9f75844SAndroid Build Coastguard Worker     video_track_2.id = kVideoTrackId2;
1158*d9f75844SAndroid Build Coastguard Worker     video_track_2.cname = kStream2Cname;
1159*d9f75844SAndroid Build Coastguard Worker     video_track_2.set_stream_ids({kStreamId2});
1160*d9f75844SAndroid Build Coastguard Worker     video_track_2.ssrcs.push_back(kVideoTrack2Ssrc);
1161*d9f75844SAndroid Build Coastguard Worker     video_desc_->AddStream(video_track_2);
1162*d9f75844SAndroid Build Coastguard Worker 
1163*d9f75844SAndroid Build Coastguard Worker     StreamParams video_track_3;
1164*d9f75844SAndroid Build Coastguard Worker     video_track_3.id = kVideoTrackId3;
1165*d9f75844SAndroid Build Coastguard Worker     video_track_3.cname = kStream2Cname;
1166*d9f75844SAndroid Build Coastguard Worker     video_track_3.set_stream_ids({kStreamId2});
1167*d9f75844SAndroid Build Coastguard Worker     video_track_3.ssrcs.push_back(kVideoTrack3Ssrc);
1168*d9f75844SAndroid Build Coastguard Worker     video_desc_->AddStream(video_track_3);
1169*d9f75844SAndroid Build Coastguard Worker 
1170*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kAudioContentName);
1171*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1172*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp,
1173*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_));
1174*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp,
1175*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_));
1176*d9f75844SAndroid Build Coastguard Worker 
1177*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1178*d9f75844SAndroid Build Coastguard Worker                                   jdesc_.session_version()));
1179*d9f75844SAndroid Build Coastguard Worker   }
1180*d9f75844SAndroid Build Coastguard Worker 
1181*d9f75844SAndroid Build Coastguard Worker   // Turns the existing reference description into a unified plan description,
1182*d9f75844SAndroid Build Coastguard Worker   // with 2 audio tracks and 3 video tracks.
MakeUnifiedPlanDescription(bool use_ssrcs=true)1183*d9f75844SAndroid Build Coastguard Worker   void MakeUnifiedPlanDescription(bool use_ssrcs = true) {
1184*d9f75844SAndroid Build Coastguard Worker     // Audio track 2.
1185*d9f75844SAndroid Build Coastguard Worker     AudioContentDescription* audio_desc_2 = CreateAudioContentDescription();
1186*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_track_2;
1187*d9f75844SAndroid Build Coastguard Worker     audio_track_2.id = kAudioTrackId2;
1188*d9f75844SAndroid Build Coastguard Worker     audio_track_2.set_stream_ids({kStreamId2});
1189*d9f75844SAndroid Build Coastguard Worker     if (use_ssrcs) {
1190*d9f75844SAndroid Build Coastguard Worker       audio_track_2.cname = kStream2Cname;
1191*d9f75844SAndroid Build Coastguard Worker       audio_track_2.ssrcs.push_back(kAudioTrack2Ssrc);
1192*d9f75844SAndroid Build Coastguard Worker     }
1193*d9f75844SAndroid Build Coastguard Worker     audio_desc_2->AddStream(audio_track_2);
1194*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp,
1195*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_2));
1196*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1197*d9f75844SAndroid Build Coastguard Worker         kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
1198*d9f75844SAndroid Build Coastguard Worker     // Video track 2, in stream 2.
1199*d9f75844SAndroid Build Coastguard Worker     VideoContentDescription* video_desc_2 = CreateVideoContentDescription();
1200*d9f75844SAndroid Build Coastguard Worker     StreamParams video_track_2;
1201*d9f75844SAndroid Build Coastguard Worker     video_track_2.id = kVideoTrackId2;
1202*d9f75844SAndroid Build Coastguard Worker     video_track_2.set_stream_ids({kStreamId2});
1203*d9f75844SAndroid Build Coastguard Worker     if (use_ssrcs) {
1204*d9f75844SAndroid Build Coastguard Worker       video_track_2.cname = kStream2Cname;
1205*d9f75844SAndroid Build Coastguard Worker       video_track_2.ssrcs.push_back(kVideoTrack2Ssrc);
1206*d9f75844SAndroid Build Coastguard Worker     }
1207*d9f75844SAndroid Build Coastguard Worker     video_desc_2->AddStream(video_track_2);
1208*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName2, MediaProtocolType::kRtp,
1209*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_2));
1210*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1211*d9f75844SAndroid Build Coastguard Worker         kVideoContentName2, TransportDescription(kUfragVideo2, kPwdVideo2)));
1212*d9f75844SAndroid Build Coastguard Worker 
1213*d9f75844SAndroid Build Coastguard Worker     // Video track 3, in stream 2.
1214*d9f75844SAndroid Build Coastguard Worker     VideoContentDescription* video_desc_3 = CreateVideoContentDescription();
1215*d9f75844SAndroid Build Coastguard Worker     StreamParams video_track_3;
1216*d9f75844SAndroid Build Coastguard Worker     video_track_3.id = kVideoTrackId3;
1217*d9f75844SAndroid Build Coastguard Worker     video_track_3.set_stream_ids({kStreamId2});
1218*d9f75844SAndroid Build Coastguard Worker     if (use_ssrcs) {
1219*d9f75844SAndroid Build Coastguard Worker       video_track_3.cname = kStream2Cname;
1220*d9f75844SAndroid Build Coastguard Worker       video_track_3.ssrcs.push_back(kVideoTrack3Ssrc);
1221*d9f75844SAndroid Build Coastguard Worker     }
1222*d9f75844SAndroid Build Coastguard Worker     video_desc_3->AddStream(video_track_3);
1223*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName3, MediaProtocolType::kRtp,
1224*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_3));
1225*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1226*d9f75844SAndroid Build Coastguard Worker         kVideoContentName3, TransportDescription(kUfragVideo3, kPwdVideo3)));
1227*d9f75844SAndroid Build Coastguard Worker     desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection);
1228*d9f75844SAndroid Build Coastguard Worker 
1229*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1230*d9f75844SAndroid Build Coastguard Worker                                   jdesc_.session_version()));
1231*d9f75844SAndroid Build Coastguard Worker   }
1232*d9f75844SAndroid Build Coastguard Worker 
1233*d9f75844SAndroid Build Coastguard Worker   // Creates an audio content description with no streams, and some default
1234*d9f75844SAndroid Build Coastguard Worker   // configuration.
CreateAudioContentDescription()1235*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* CreateAudioContentDescription() {
1236*d9f75844SAndroid Build Coastguard Worker     AudioContentDescription* audio = new AudioContentDescription();
1237*d9f75844SAndroid Build Coastguard Worker     audio->set_rtcp_mux(true);
1238*d9f75844SAndroid Build Coastguard Worker     audio->set_rtcp_reduced_size(true);
1239*d9f75844SAndroid Build Coastguard Worker     audio->AddCrypto(CryptoParams(
1240*d9f75844SAndroid Build Coastguard Worker         1, "AES_CM_128_HMAC_SHA1_32",
1241*d9f75844SAndroid Build Coastguard Worker         "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32",
1242*d9f75844SAndroid Build Coastguard Worker         "dummy_session_params"));
1243*d9f75844SAndroid Build Coastguard Worker     audio->set_protocol(cricket::kMediaProtocolSavpf);
1244*d9f75844SAndroid Build Coastguard Worker     audio->AddCodec(AudioCodec(111, "opus", 48000, 0, 2));
1245*d9f75844SAndroid Build Coastguard Worker     audio->AddCodec(AudioCodec(103, "ISAC", 16000, 0, 1));
1246*d9f75844SAndroid Build Coastguard Worker     audio->AddCodec(AudioCodec(104, "ISAC", 32000, 0, 1));
1247*d9f75844SAndroid Build Coastguard Worker     return audio;
1248*d9f75844SAndroid Build Coastguard Worker   }
1249*d9f75844SAndroid Build Coastguard Worker 
1250*d9f75844SAndroid Build Coastguard Worker   // Turns the existing reference description into a unified plan description,
1251*d9f75844SAndroid Build Coastguard Worker   // with 3 audio MediaContentDescriptions with special StreamParams that
1252*d9f75844SAndroid Build Coastguard Worker   // contain 0 or multiple stream ids: - audio track 1 has 1 media stream id -
1253*d9f75844SAndroid Build Coastguard Worker   // audio track 2 has 2 media stream ids - audio track 3 has 0 media stream ids
MakeUnifiedPlanDescriptionMultipleStreamIds(const int msid_signaling)1254*d9f75844SAndroid Build Coastguard Worker   void MakeUnifiedPlanDescriptionMultipleStreamIds(const int msid_signaling) {
1255*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1256*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(kVideoContentName);
1257*d9f75844SAndroid Build Coastguard Worker     RemoveVideoCandidates();
1258*d9f75844SAndroid Build Coastguard Worker 
1259*d9f75844SAndroid Build Coastguard Worker     // Audio track 2 has 2 media stream ids.
1260*d9f75844SAndroid Build Coastguard Worker     AudioContentDescription* audio_desc_2 = CreateAudioContentDescription();
1261*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_track_2;
1262*d9f75844SAndroid Build Coastguard Worker     audio_track_2.id = kAudioTrackId2;
1263*d9f75844SAndroid Build Coastguard Worker     audio_track_2.cname = kStream1Cname;
1264*d9f75844SAndroid Build Coastguard Worker     audio_track_2.set_stream_ids({kStreamId1, kStreamId2});
1265*d9f75844SAndroid Build Coastguard Worker     audio_track_2.ssrcs.push_back(kAudioTrack2Ssrc);
1266*d9f75844SAndroid Build Coastguard Worker     audio_desc_2->AddStream(audio_track_2);
1267*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp,
1268*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_2));
1269*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1270*d9f75844SAndroid Build Coastguard Worker         kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
1271*d9f75844SAndroid Build Coastguard Worker 
1272*d9f75844SAndroid Build Coastguard Worker     // Audio track 3 has no stream ids.
1273*d9f75844SAndroid Build Coastguard Worker     AudioContentDescription* audio_desc_3 = CreateAudioContentDescription();
1274*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_track_3;
1275*d9f75844SAndroid Build Coastguard Worker     audio_track_3.id = kAudioTrackId3;
1276*d9f75844SAndroid Build Coastguard Worker     audio_track_3.cname = kStream2Cname;
1277*d9f75844SAndroid Build Coastguard Worker     audio_track_3.set_stream_ids({});
1278*d9f75844SAndroid Build Coastguard Worker     audio_track_3.ssrcs.push_back(kAudioTrack3Ssrc);
1279*d9f75844SAndroid Build Coastguard Worker     audio_desc_3->AddStream(audio_track_3);
1280*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName3, MediaProtocolType::kRtp,
1281*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_3));
1282*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1283*d9f75844SAndroid Build Coastguard Worker         kAudioContentName3, TransportDescription(kUfragVoice3, kPwdVoice3)));
1284*d9f75844SAndroid Build Coastguard Worker     desc_.set_msid_signaling(msid_signaling);
1285*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1286*d9f75844SAndroid Build Coastguard Worker                                   jdesc_.session_version()));
1287*d9f75844SAndroid Build Coastguard Worker   }
1288*d9f75844SAndroid Build Coastguard Worker 
1289*d9f75844SAndroid Build Coastguard Worker   // Turns the existing reference description into a unified plan description
1290*d9f75844SAndroid Build Coastguard Worker   // with one audio MediaContentDescription that contains one StreamParams with
1291*d9f75844SAndroid Build Coastguard Worker   // 0 ssrcs.
MakeUnifiedPlanDescriptionNoSsrcSignaling()1292*d9f75844SAndroid Build Coastguard Worker   void MakeUnifiedPlanDescriptionNoSsrcSignaling() {
1293*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1294*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kAudioContentName);
1295*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(kVideoContentName);
1296*d9f75844SAndroid Build Coastguard Worker     RemoveVideoCandidates();
1297*d9f75844SAndroid Build Coastguard Worker 
1298*d9f75844SAndroid Build Coastguard Worker     AudioContentDescription* audio_desc = CreateAudioContentDescription();
1299*d9f75844SAndroid Build Coastguard Worker     StreamParams audio_track;
1300*d9f75844SAndroid Build Coastguard Worker     audio_track.id = kAudioTrackId1;
1301*d9f75844SAndroid Build Coastguard Worker     audio_track.set_stream_ids({kStreamId1});
1302*d9f75844SAndroid Build Coastguard Worker     audio_desc->AddStream(audio_track);
1303*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp,
1304*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc));
1305*d9f75844SAndroid Build Coastguard Worker 
1306*d9f75844SAndroid Build Coastguard Worker     // Enable signaling a=msid lines.
1307*d9f75844SAndroid Build Coastguard Worker     desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection);
1308*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1309*d9f75844SAndroid Build Coastguard Worker                                   jdesc_.session_version()));
1310*d9f75844SAndroid Build Coastguard Worker   }
1311*d9f75844SAndroid Build Coastguard Worker 
1312*d9f75844SAndroid Build Coastguard Worker   // Creates a video content description with no streams, and some default
1313*d9f75844SAndroid Build Coastguard Worker   // configuration.
CreateVideoContentDescription()1314*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* CreateVideoContentDescription() {
1315*d9f75844SAndroid Build Coastguard Worker     VideoContentDescription* video = new VideoContentDescription();
1316*d9f75844SAndroid Build Coastguard Worker     video->AddCrypto(CryptoParams(
1317*d9f75844SAndroid Build Coastguard Worker         1, "AES_CM_128_HMAC_SHA1_80",
1318*d9f75844SAndroid Build Coastguard Worker         "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32", ""));
1319*d9f75844SAndroid Build Coastguard Worker     video->set_protocol(cricket::kMediaProtocolSavpf);
1320*d9f75844SAndroid Build Coastguard Worker     video->AddCodec(
1321*d9f75844SAndroid Build Coastguard Worker         VideoCodec(120, JsepSessionDescription::kDefaultVideoCodecName));
1322*d9f75844SAndroid Build Coastguard Worker     return video;
1323*d9f75844SAndroid Build Coastguard Worker   }
1324*d9f75844SAndroid Build Coastguard Worker 
1325*d9f75844SAndroid Build Coastguard Worker   template <class MCD>
CompareMediaContentDescription(const MCD * cd1,const MCD * cd2)1326*d9f75844SAndroid Build Coastguard Worker   void CompareMediaContentDescription(const MCD* cd1, const MCD* cd2) {
1327*d9f75844SAndroid Build Coastguard Worker     // type
1328*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->type(), cd2->type());
1329*d9f75844SAndroid Build Coastguard Worker 
1330*d9f75844SAndroid Build Coastguard Worker     // content direction
1331*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->direction(), cd2->direction());
1332*d9f75844SAndroid Build Coastguard Worker 
1333*d9f75844SAndroid Build Coastguard Worker     // rtcp_mux
1334*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->rtcp_mux(), cd2->rtcp_mux());
1335*d9f75844SAndroid Build Coastguard Worker 
1336*d9f75844SAndroid Build Coastguard Worker     // rtcp_reduced_size
1337*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->rtcp_reduced_size(), cd2->rtcp_reduced_size());
1338*d9f75844SAndroid Build Coastguard Worker 
1339*d9f75844SAndroid Build Coastguard Worker     // cryptos
1340*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->cryptos().size(), cd2->cryptos().size());
1341*d9f75844SAndroid Build Coastguard Worker     if (cd1->cryptos().size() != cd2->cryptos().size()) {
1342*d9f75844SAndroid Build Coastguard Worker       ADD_FAILURE();
1343*d9f75844SAndroid Build Coastguard Worker       return;
1344*d9f75844SAndroid Build Coastguard Worker     }
1345*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < cd1->cryptos().size(); ++i) {
1346*d9f75844SAndroid Build Coastguard Worker       const CryptoParams c1 = cd1->cryptos().at(i);
1347*d9f75844SAndroid Build Coastguard Worker       const CryptoParams c2 = cd2->cryptos().at(i);
1348*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(c1.Matches(c2));
1349*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.key_params, c2.key_params);
1350*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.session_params, c2.session_params);
1351*d9f75844SAndroid Build Coastguard Worker     }
1352*d9f75844SAndroid Build Coastguard Worker 
1353*d9f75844SAndroid Build Coastguard Worker     // protocol
1354*d9f75844SAndroid Build Coastguard Worker     // Use an equivalence class here, for old and new versions of the
1355*d9f75844SAndroid Build Coastguard Worker     // protocol description.
1356*d9f75844SAndroid Build Coastguard Worker     if (cd1->protocol() == cricket::kMediaProtocolDtlsSctp ||
1357*d9f75844SAndroid Build Coastguard Worker         cd1->protocol() == cricket::kMediaProtocolUdpDtlsSctp ||
1358*d9f75844SAndroid Build Coastguard Worker         cd1->protocol() == cricket::kMediaProtocolTcpDtlsSctp) {
1359*d9f75844SAndroid Build Coastguard Worker       const bool cd2_is_also_dtls_sctp =
1360*d9f75844SAndroid Build Coastguard Worker           cd2->protocol() == cricket::kMediaProtocolDtlsSctp ||
1361*d9f75844SAndroid Build Coastguard Worker           cd2->protocol() == cricket::kMediaProtocolUdpDtlsSctp ||
1362*d9f75844SAndroid Build Coastguard Worker           cd2->protocol() == cricket::kMediaProtocolTcpDtlsSctp;
1363*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(cd2_is_also_dtls_sctp);
1364*d9f75844SAndroid Build Coastguard Worker     } else {
1365*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(cd1->protocol(), cd2->protocol());
1366*d9f75844SAndroid Build Coastguard Worker     }
1367*d9f75844SAndroid Build Coastguard Worker 
1368*d9f75844SAndroid Build Coastguard Worker     // codecs
1369*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->codecs(), cd2->codecs());
1370*d9f75844SAndroid Build Coastguard Worker 
1371*d9f75844SAndroid Build Coastguard Worker     // bandwidth
1372*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->bandwidth(), cd2->bandwidth());
1373*d9f75844SAndroid Build Coastguard Worker 
1374*d9f75844SAndroid Build Coastguard Worker     // streams
1375*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->streams(), cd2->streams());
1376*d9f75844SAndroid Build Coastguard Worker 
1377*d9f75844SAndroid Build Coastguard Worker     // extmap-allow-mixed
1378*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(cd1->extmap_allow_mixed_enum(), cd2->extmap_allow_mixed_enum());
1379*d9f75844SAndroid Build Coastguard Worker 
1380*d9f75844SAndroid Build Coastguard Worker     // extmap
1381*d9f75844SAndroid Build Coastguard Worker     ASSERT_EQ(cd1->rtp_header_extensions().size(),
1382*d9f75844SAndroid Build Coastguard Worker               cd2->rtp_header_extensions().size());
1383*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < cd1->rtp_header_extensions().size(); ++i) {
1384*d9f75844SAndroid Build Coastguard Worker       const RtpExtension ext1 = cd1->rtp_header_extensions().at(i);
1385*d9f75844SAndroid Build Coastguard Worker       const RtpExtension ext2 = cd2->rtp_header_extensions().at(i);
1386*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(ext1.uri, ext2.uri);
1387*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(ext1.id, ext2.id);
1388*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(ext1.encrypt, ext2.encrypt);
1389*d9f75844SAndroid Build Coastguard Worker     }
1390*d9f75844SAndroid Build Coastguard Worker   }
1391*d9f75844SAndroid Build Coastguard Worker 
CompareRidDescriptionIds(const std::vector<RidDescription> & rids,const std::vector<std::string> & ids)1392*d9f75844SAndroid Build Coastguard Worker   void CompareRidDescriptionIds(const std::vector<RidDescription>& rids,
1393*d9f75844SAndroid Build Coastguard Worker                                 const std::vector<std::string>& ids) {
1394*d9f75844SAndroid Build Coastguard Worker     // Order of elements does not matter, only equivalence of sets.
1395*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(rids.size(), ids.size());
1396*d9f75844SAndroid Build Coastguard Worker     for (const std::string& id : ids) {
1397*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1l, absl::c_count_if(rids, [id](const RidDescription& rid) {
1398*d9f75844SAndroid Build Coastguard Worker                   return rid.rid == id;
1399*d9f75844SAndroid Build Coastguard Worker                 }));
1400*d9f75844SAndroid Build Coastguard Worker     }
1401*d9f75844SAndroid Build Coastguard Worker   }
1402*d9f75844SAndroid Build Coastguard Worker 
CompareSimulcastDescription(const SimulcastDescription & simulcast1,const SimulcastDescription & simulcast2)1403*d9f75844SAndroid Build Coastguard Worker   void CompareSimulcastDescription(const SimulcastDescription& simulcast1,
1404*d9f75844SAndroid Build Coastguard Worker                                    const SimulcastDescription& simulcast2) {
1405*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(simulcast1.send_layers().size(), simulcast2.send_layers().size());
1406*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(simulcast1.receive_layers().size(),
1407*d9f75844SAndroid Build Coastguard Worker               simulcast2.receive_layers().size());
1408*d9f75844SAndroid Build Coastguard Worker   }
1409*d9f75844SAndroid Build Coastguard Worker 
CompareSctpDataContentDescription(const SctpDataContentDescription * dcd1,const SctpDataContentDescription * dcd2)1410*d9f75844SAndroid Build Coastguard Worker   void CompareSctpDataContentDescription(
1411*d9f75844SAndroid Build Coastguard Worker       const SctpDataContentDescription* dcd1,
1412*d9f75844SAndroid Build Coastguard Worker       const SctpDataContentDescription* dcd2) {
1413*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(dcd1->use_sctpmap(), dcd2->use_sctpmap());
1414*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(dcd1->port(), dcd2->port());
1415*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(dcd1->max_message_size(), dcd2->max_message_size());
1416*d9f75844SAndroid Build Coastguard Worker   }
1417*d9f75844SAndroid Build Coastguard Worker 
CompareSessionDescription(const SessionDescription & desc1,const SessionDescription & desc2)1418*d9f75844SAndroid Build Coastguard Worker   void CompareSessionDescription(const SessionDescription& desc1,
1419*d9f75844SAndroid Build Coastguard Worker                                  const SessionDescription& desc2) {
1420*d9f75844SAndroid Build Coastguard Worker     // Compare content descriptions.
1421*d9f75844SAndroid Build Coastguard Worker     if (desc1.contents().size() != desc2.contents().size()) {
1422*d9f75844SAndroid Build Coastguard Worker       ADD_FAILURE();
1423*d9f75844SAndroid Build Coastguard Worker       return;
1424*d9f75844SAndroid Build Coastguard Worker     }
1425*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < desc1.contents().size(); ++i) {
1426*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentInfo& c1 = desc1.contents().at(i);
1427*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentInfo& c2 = desc2.contents().at(i);
1428*d9f75844SAndroid Build Coastguard Worker       // ContentInfo properties.
1429*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.name, c2.name);
1430*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.type, c2.type);
1431*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.rejected, c2.rejected);
1432*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(c1.bundle_only, c2.bundle_only);
1433*d9f75844SAndroid Build Coastguard Worker 
1434*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(IsAudioContent(&c1), IsAudioContent(&c2));
1435*d9f75844SAndroid Build Coastguard Worker       if (IsAudioContent(&c1)) {
1436*d9f75844SAndroid Build Coastguard Worker         const AudioContentDescription* acd1 =
1437*d9f75844SAndroid Build Coastguard Worker             c1.media_description()->as_audio();
1438*d9f75844SAndroid Build Coastguard Worker         const AudioContentDescription* acd2 =
1439*d9f75844SAndroid Build Coastguard Worker             c2.media_description()->as_audio();
1440*d9f75844SAndroid Build Coastguard Worker         CompareMediaContentDescription<AudioContentDescription>(acd1, acd2);
1441*d9f75844SAndroid Build Coastguard Worker       }
1442*d9f75844SAndroid Build Coastguard Worker 
1443*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(IsVideoContent(&c1), IsVideoContent(&c2));
1444*d9f75844SAndroid Build Coastguard Worker       if (IsVideoContent(&c1)) {
1445*d9f75844SAndroid Build Coastguard Worker         const VideoContentDescription* vcd1 =
1446*d9f75844SAndroid Build Coastguard Worker             c1.media_description()->as_video();
1447*d9f75844SAndroid Build Coastguard Worker         const VideoContentDescription* vcd2 =
1448*d9f75844SAndroid Build Coastguard Worker             c2.media_description()->as_video();
1449*d9f75844SAndroid Build Coastguard Worker         CompareMediaContentDescription<VideoContentDescription>(vcd1, vcd2);
1450*d9f75844SAndroid Build Coastguard Worker       }
1451*d9f75844SAndroid Build Coastguard Worker 
1452*d9f75844SAndroid Build Coastguard Worker       ASSERT_EQ(IsDataContent(&c1), IsDataContent(&c2));
1453*d9f75844SAndroid Build Coastguard Worker       if (c1.media_description()->as_sctp()) {
1454*d9f75844SAndroid Build Coastguard Worker         ASSERT_TRUE(c2.media_description()->as_sctp());
1455*d9f75844SAndroid Build Coastguard Worker         const SctpDataContentDescription* scd1 =
1456*d9f75844SAndroid Build Coastguard Worker             c1.media_description()->as_sctp();
1457*d9f75844SAndroid Build Coastguard Worker         const SctpDataContentDescription* scd2 =
1458*d9f75844SAndroid Build Coastguard Worker             c2.media_description()->as_sctp();
1459*d9f75844SAndroid Build Coastguard Worker         CompareSctpDataContentDescription(scd1, scd2);
1460*d9f75844SAndroid Build Coastguard Worker       }
1461*d9f75844SAndroid Build Coastguard Worker 
1462*d9f75844SAndroid Build Coastguard Worker       CompareSimulcastDescription(
1463*d9f75844SAndroid Build Coastguard Worker           c1.media_description()->simulcast_description(),
1464*d9f75844SAndroid Build Coastguard Worker           c2.media_description()->simulcast_description());
1465*d9f75844SAndroid Build Coastguard Worker     }
1466*d9f75844SAndroid Build Coastguard Worker 
1467*d9f75844SAndroid Build Coastguard Worker     // group
1468*d9f75844SAndroid Build Coastguard Worker     const cricket::ContentGroups groups1 = desc1.groups();
1469*d9f75844SAndroid Build Coastguard Worker     const cricket::ContentGroups groups2 = desc2.groups();
1470*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(groups1.size(), groups1.size());
1471*d9f75844SAndroid Build Coastguard Worker     if (groups1.size() != groups2.size()) {
1472*d9f75844SAndroid Build Coastguard Worker       ADD_FAILURE();
1473*d9f75844SAndroid Build Coastguard Worker       return;
1474*d9f75844SAndroid Build Coastguard Worker     }
1475*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < groups1.size(); ++i) {
1476*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentGroup group1 = groups1.at(i);
1477*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentGroup group2 = groups2.at(i);
1478*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(group1.semantics(), group2.semantics());
1479*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentNames names1 = group1.content_names();
1480*d9f75844SAndroid Build Coastguard Worker       const cricket::ContentNames names2 = group2.content_names();
1481*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(names1.size(), names2.size());
1482*d9f75844SAndroid Build Coastguard Worker       if (names1.size() != names2.size()) {
1483*d9f75844SAndroid Build Coastguard Worker         ADD_FAILURE();
1484*d9f75844SAndroid Build Coastguard Worker         return;
1485*d9f75844SAndroid Build Coastguard Worker       }
1486*d9f75844SAndroid Build Coastguard Worker       cricket::ContentNames::const_iterator iter1 = names1.begin();
1487*d9f75844SAndroid Build Coastguard Worker       cricket::ContentNames::const_iterator iter2 = names2.begin();
1488*d9f75844SAndroid Build Coastguard Worker       while (iter1 != names1.end()) {
1489*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(*iter1++, *iter2++);
1490*d9f75844SAndroid Build Coastguard Worker       }
1491*d9f75844SAndroid Build Coastguard Worker     }
1492*d9f75844SAndroid Build Coastguard Worker 
1493*d9f75844SAndroid Build Coastguard Worker     // transport info
1494*d9f75844SAndroid Build Coastguard Worker     const cricket::TransportInfos transports1 = desc1.transport_infos();
1495*d9f75844SAndroid Build Coastguard Worker     const cricket::TransportInfos transports2 = desc2.transport_infos();
1496*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(transports1.size(), transports2.size());
1497*d9f75844SAndroid Build Coastguard Worker     if (transports1.size() != transports2.size()) {
1498*d9f75844SAndroid Build Coastguard Worker       ADD_FAILURE();
1499*d9f75844SAndroid Build Coastguard Worker       return;
1500*d9f75844SAndroid Build Coastguard Worker     }
1501*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < transports1.size(); ++i) {
1502*d9f75844SAndroid Build Coastguard Worker       const cricket::TransportInfo transport1 = transports1.at(i);
1503*d9f75844SAndroid Build Coastguard Worker       const cricket::TransportInfo transport2 = transports2.at(i);
1504*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(transport1.content_name, transport2.content_name);
1505*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(transport1.description.ice_ufrag,
1506*d9f75844SAndroid Build Coastguard Worker                 transport2.description.ice_ufrag);
1507*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(transport1.description.ice_pwd, transport2.description.ice_pwd);
1508*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(transport1.description.ice_mode,
1509*d9f75844SAndroid Build Coastguard Worker                 transport2.description.ice_mode);
1510*d9f75844SAndroid Build Coastguard Worker       if (transport1.description.identity_fingerprint) {
1511*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(*transport1.description.identity_fingerprint,
1512*d9f75844SAndroid Build Coastguard Worker                   *transport2.description.identity_fingerprint);
1513*d9f75844SAndroid Build Coastguard Worker       } else {
1514*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(transport1.description.identity_fingerprint.get(),
1515*d9f75844SAndroid Build Coastguard Worker                   transport2.description.identity_fingerprint.get());
1516*d9f75844SAndroid Build Coastguard Worker       }
1517*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(transport1.description.transport_options,
1518*d9f75844SAndroid Build Coastguard Worker                 transport2.description.transport_options);
1519*d9f75844SAndroid Build Coastguard Worker     }
1520*d9f75844SAndroid Build Coastguard Worker 
1521*d9f75844SAndroid Build Coastguard Worker     // global attributes
1522*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(desc1.msid_supported(), desc2.msid_supported());
1523*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(desc1.extmap_allow_mixed(), desc2.extmap_allow_mixed());
1524*d9f75844SAndroid Build Coastguard Worker   }
1525*d9f75844SAndroid Build Coastguard Worker 
CompareSessionDescription(const JsepSessionDescription & desc1,const JsepSessionDescription & desc2)1526*d9f75844SAndroid Build Coastguard Worker   bool CompareSessionDescription(const JsepSessionDescription& desc1,
1527*d9f75844SAndroid Build Coastguard Worker                                  const JsepSessionDescription& desc2) {
1528*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(desc1.session_id(), desc2.session_id());
1529*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(desc1.session_version(), desc2.session_version());
1530*d9f75844SAndroid Build Coastguard Worker     CompareSessionDescription(*desc1.description(), *desc2.description());
1531*d9f75844SAndroid Build Coastguard Worker     if (desc1.number_of_mediasections() != desc2.number_of_mediasections())
1532*d9f75844SAndroid Build Coastguard Worker       return false;
1533*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < desc1.number_of_mediasections(); ++i) {
1534*d9f75844SAndroid Build Coastguard Worker       const IceCandidateCollection* cc1 = desc1.candidates(i);
1535*d9f75844SAndroid Build Coastguard Worker       const IceCandidateCollection* cc2 = desc2.candidates(i);
1536*d9f75844SAndroid Build Coastguard Worker       if (cc1->count() != cc2->count()) {
1537*d9f75844SAndroid Build Coastguard Worker         ADD_FAILURE();
1538*d9f75844SAndroid Build Coastguard Worker         return false;
1539*d9f75844SAndroid Build Coastguard Worker       }
1540*d9f75844SAndroid Build Coastguard Worker       for (size_t j = 0; j < cc1->count(); ++j) {
1541*d9f75844SAndroid Build Coastguard Worker         const IceCandidateInterface* c1 = cc1->at(j);
1542*d9f75844SAndroid Build Coastguard Worker         const IceCandidateInterface* c2 = cc2->at(j);
1543*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(c1->sdp_mid(), c2->sdp_mid());
1544*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(c1->sdp_mline_index(), c2->sdp_mline_index());
1545*d9f75844SAndroid Build Coastguard Worker         EXPECT_TRUE(c1->candidate().IsEquivalent(c2->candidate()));
1546*d9f75844SAndroid Build Coastguard Worker       }
1547*d9f75844SAndroid Build Coastguard Worker     }
1548*d9f75844SAndroid Build Coastguard Worker     return true;
1549*d9f75844SAndroid Build Coastguard Worker   }
1550*d9f75844SAndroid Build Coastguard Worker 
1551*d9f75844SAndroid Build Coastguard Worker   // Disable the ice-ufrag and ice-pwd in given `sdp` message by replacing
1552*d9f75844SAndroid Build Coastguard Worker   // them with invalid keywords so that the parser will just ignore them.
RemoveCandidateUfragPwd(std::string * sdp)1553*d9f75844SAndroid Build Coastguard Worker   bool RemoveCandidateUfragPwd(std::string* sdp) {
1554*d9f75844SAndroid Build Coastguard Worker     absl::StrReplaceAll(
1555*d9f75844SAndroid Build Coastguard Worker         {{"a=ice-ufrag", "a=xice-ufrag"}, {"a=ice-pwd", "a=xice-pwd"}}, sdp);
1556*d9f75844SAndroid Build Coastguard Worker     return true;
1557*d9f75844SAndroid Build Coastguard Worker   }
1558*d9f75844SAndroid Build Coastguard Worker 
1559*d9f75844SAndroid Build Coastguard Worker   // Update the candidates in `jdesc` to use the given `ufrag` and `pwd`.
UpdateCandidateUfragPwd(JsepSessionDescription * jdesc,int mline_index,const std::string & ufrag,const std::string & pwd)1560*d9f75844SAndroid Build Coastguard Worker   bool UpdateCandidateUfragPwd(JsepSessionDescription* jdesc,
1561*d9f75844SAndroid Build Coastguard Worker                                int mline_index,
1562*d9f75844SAndroid Build Coastguard Worker                                const std::string& ufrag,
1563*d9f75844SAndroid Build Coastguard Worker                                const std::string& pwd) {
1564*d9f75844SAndroid Build Coastguard Worker     std::string content_name;
1565*d9f75844SAndroid Build Coastguard Worker     if (mline_index == 0) {
1566*d9f75844SAndroid Build Coastguard Worker       content_name = kAudioContentName;
1567*d9f75844SAndroid Build Coastguard Worker     } else if (mline_index == 1) {
1568*d9f75844SAndroid Build Coastguard Worker       content_name = kVideoContentName;
1569*d9f75844SAndroid Build Coastguard Worker     } else {
1570*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
1571*d9f75844SAndroid Build Coastguard Worker     }
1572*d9f75844SAndroid Build Coastguard Worker     TransportInfo transport_info(content_name,
1573*d9f75844SAndroid Build Coastguard Worker                                  TransportDescription(ufrag, pwd));
1574*d9f75844SAndroid Build Coastguard Worker     SessionDescription* desc =
1575*d9f75844SAndroid Build Coastguard Worker         const_cast<SessionDescription*>(jdesc->description());
1576*d9f75844SAndroid Build Coastguard Worker     desc->RemoveTransportInfoByName(content_name);
1577*d9f75844SAndroid Build Coastguard Worker     desc->AddTransportInfo(transport_info);
1578*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < jdesc_.number_of_mediasections(); ++i) {
1579*d9f75844SAndroid Build Coastguard Worker       const IceCandidateCollection* cc = jdesc_.candidates(i);
1580*d9f75844SAndroid Build Coastguard Worker       for (size_t j = 0; j < cc->count(); ++j) {
1581*d9f75844SAndroid Build Coastguard Worker         if (cc->at(j)->sdp_mline_index() == mline_index) {
1582*d9f75844SAndroid Build Coastguard Worker           const_cast<Candidate&>(cc->at(j)->candidate()).set_username(ufrag);
1583*d9f75844SAndroid Build Coastguard Worker           const_cast<Candidate&>(cc->at(j)->candidate()).set_password(pwd);
1584*d9f75844SAndroid Build Coastguard Worker         }
1585*d9f75844SAndroid Build Coastguard Worker       }
1586*d9f75844SAndroid Build Coastguard Worker     }
1587*d9f75844SAndroid Build Coastguard Worker     return true;
1588*d9f75844SAndroid Build Coastguard Worker   }
1589*d9f75844SAndroid Build Coastguard Worker 
AddIceOptions(const std::string & content_name,const std::vector<std::string> & transport_options)1590*d9f75844SAndroid Build Coastguard Worker   void AddIceOptions(const std::string& content_name,
1591*d9f75844SAndroid Build Coastguard Worker                      const std::vector<std::string>& transport_options) {
1592*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(desc_.GetTransportInfoByName(content_name) != NULL);
1593*d9f75844SAndroid Build Coastguard Worker     cricket::TransportInfo transport_info =
1594*d9f75844SAndroid Build Coastguard Worker         *(desc_.GetTransportInfoByName(content_name));
1595*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(content_name);
1596*d9f75844SAndroid Build Coastguard Worker     transport_info.description.transport_options = transport_options;
1597*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(transport_info);
1598*d9f75844SAndroid Build Coastguard Worker   }
1599*d9f75844SAndroid Build Coastguard Worker 
SetIceUfragPwd(const std::string & content_name,const std::string & ice_ufrag,const std::string & ice_pwd)1600*d9f75844SAndroid Build Coastguard Worker   void SetIceUfragPwd(const std::string& content_name,
1601*d9f75844SAndroid Build Coastguard Worker                       const std::string& ice_ufrag,
1602*d9f75844SAndroid Build Coastguard Worker                       const std::string& ice_pwd) {
1603*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(desc_.GetTransportInfoByName(content_name) != NULL);
1604*d9f75844SAndroid Build Coastguard Worker     cricket::TransportInfo transport_info =
1605*d9f75844SAndroid Build Coastguard Worker         *(desc_.GetTransportInfoByName(content_name));
1606*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(content_name);
1607*d9f75844SAndroid Build Coastguard Worker     transport_info.description.ice_ufrag = ice_ufrag;
1608*d9f75844SAndroid Build Coastguard Worker     transport_info.description.ice_pwd = ice_pwd;
1609*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(transport_info);
1610*d9f75844SAndroid Build Coastguard Worker   }
1611*d9f75844SAndroid Build Coastguard Worker 
AddFingerprint()1612*d9f75844SAndroid Build Coastguard Worker   void AddFingerprint() {
1613*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(kAudioContentName);
1614*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveTransportInfoByName(kVideoContentName);
1615*d9f75844SAndroid Build Coastguard Worker     rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
1616*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1617*d9f75844SAndroid Build Coastguard Worker         kAudioContentName,
1618*d9f75844SAndroid Build Coastguard Worker         TransportDescription(std::vector<std::string>(), kUfragVoice, kPwdVoice,
1619*d9f75844SAndroid Build Coastguard Worker                              cricket::ICEMODE_FULL,
1620*d9f75844SAndroid Build Coastguard Worker                              cricket::CONNECTIONROLE_NONE, &fingerprint)));
1621*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1622*d9f75844SAndroid Build Coastguard Worker         kVideoContentName,
1623*d9f75844SAndroid Build Coastguard Worker         TransportDescription(std::vector<std::string>(), kUfragVideo, kPwdVideo,
1624*d9f75844SAndroid Build Coastguard Worker                              cricket::ICEMODE_FULL,
1625*d9f75844SAndroid Build Coastguard Worker                              cricket::CONNECTIONROLE_NONE, &fingerprint)));
1626*d9f75844SAndroid Build Coastguard Worker   }
1627*d9f75844SAndroid Build Coastguard Worker 
AddExtmap(bool encrypted)1628*d9f75844SAndroid Build Coastguard Worker   void AddExtmap(bool encrypted) {
1629*d9f75844SAndroid Build Coastguard Worker     audio_desc_ = new AudioContentDescription(*audio_desc_);
1630*d9f75844SAndroid Build Coastguard Worker     video_desc_ = new VideoContentDescription(*video_desc_);
1631*d9f75844SAndroid Build Coastguard Worker     audio_desc_->AddRtpHeaderExtension(
1632*d9f75844SAndroid Build Coastguard Worker         RtpExtension(kExtmapUri, kExtmapId, encrypted));
1633*d9f75844SAndroid Build Coastguard Worker     video_desc_->AddRtpHeaderExtension(
1634*d9f75844SAndroid Build Coastguard Worker         RtpExtension(kExtmapUri, kExtmapId, encrypted));
1635*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kAudioContentName);
1636*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1637*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp,
1638*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_));
1639*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp,
1640*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_));
1641*d9f75844SAndroid Build Coastguard Worker   }
1642*d9f75844SAndroid Build Coastguard Worker 
RemoveCryptos()1643*d9f75844SAndroid Build Coastguard Worker   void RemoveCryptos() {
1644*d9f75844SAndroid Build Coastguard Worker     audio_desc_->set_cryptos(std::vector<CryptoParams>());
1645*d9f75844SAndroid Build Coastguard Worker     video_desc_->set_cryptos(std::vector<CryptoParams>());
1646*d9f75844SAndroid Build Coastguard Worker   }
1647*d9f75844SAndroid Build Coastguard Worker 
1648*d9f75844SAndroid Build Coastguard Worker   // Removes everything in StreamParams from the session description that is
1649*d9f75844SAndroid Build Coastguard Worker   // used for a=ssrc lines.
RemoveSsrcSignalingFromStreamParams()1650*d9f75844SAndroid Build Coastguard Worker   void RemoveSsrcSignalingFromStreamParams() {
1651*d9f75844SAndroid Build Coastguard Worker     for (cricket::ContentInfo& content_info :
1652*d9f75844SAndroid Build Coastguard Worker          jdesc_.description()->contents()) {
1653*d9f75844SAndroid Build Coastguard Worker       // With Unified Plan there should be one StreamParams per m= section.
1654*d9f75844SAndroid Build Coastguard Worker       StreamParams& stream =
1655*d9f75844SAndroid Build Coastguard Worker           content_info.media_description()->mutable_streams()[0];
1656*d9f75844SAndroid Build Coastguard Worker       stream.ssrcs.clear();
1657*d9f75844SAndroid Build Coastguard Worker       stream.ssrc_groups.clear();
1658*d9f75844SAndroid Build Coastguard Worker       stream.cname.clear();
1659*d9f75844SAndroid Build Coastguard Worker     }
1660*d9f75844SAndroid Build Coastguard Worker   }
1661*d9f75844SAndroid Build Coastguard Worker 
1662*d9f75844SAndroid Build Coastguard Worker   // Removes all a=ssrc lines from the SDP string, except for the
1663*d9f75844SAndroid Build Coastguard Worker   // "a=ssrc:... cname:..." lines.
RemoveSsrcMsidLinesFromSdpString(std::string * sdp_string)1664*d9f75844SAndroid Build Coastguard Worker   void RemoveSsrcMsidLinesFromSdpString(std::string* sdp_string) {
1665*d9f75844SAndroid Build Coastguard Worker     const char kAttributeSsrc[] = "a=ssrc";
1666*d9f75844SAndroid Build Coastguard Worker     const char kAttributeCname[] = "cname";
1667*d9f75844SAndroid Build Coastguard Worker     size_t ssrc_line_pos = sdp_string->find(kAttributeSsrc);
1668*d9f75844SAndroid Build Coastguard Worker     while (ssrc_line_pos != std::string::npos) {
1669*d9f75844SAndroid Build Coastguard Worker       size_t beg_line_pos = sdp_string->rfind('\n', ssrc_line_pos);
1670*d9f75844SAndroid Build Coastguard Worker       size_t end_line_pos = sdp_string->find('\n', ssrc_line_pos);
1671*d9f75844SAndroid Build Coastguard Worker       size_t cname_pos = sdp_string->find(kAttributeCname, ssrc_line_pos);
1672*d9f75844SAndroid Build Coastguard Worker       if (cname_pos == std::string::npos || cname_pos > end_line_pos) {
1673*d9f75844SAndroid Build Coastguard Worker         // Only erase a=ssrc lines that don't contain "cname".
1674*d9f75844SAndroid Build Coastguard Worker         sdp_string->erase(beg_line_pos, end_line_pos - beg_line_pos);
1675*d9f75844SAndroid Build Coastguard Worker         ssrc_line_pos = sdp_string->find(kAttributeSsrc, beg_line_pos);
1676*d9f75844SAndroid Build Coastguard Worker       } else {
1677*d9f75844SAndroid Build Coastguard Worker         // Skip the "a=ssrc:... cname" line and find the next "a=ssrc" line.
1678*d9f75844SAndroid Build Coastguard Worker         ssrc_line_pos = sdp_string->find(kAttributeSsrc, end_line_pos);
1679*d9f75844SAndroid Build Coastguard Worker       }
1680*d9f75844SAndroid Build Coastguard Worker     }
1681*d9f75844SAndroid Build Coastguard Worker   }
1682*d9f75844SAndroid Build Coastguard Worker 
1683*d9f75844SAndroid Build Coastguard Worker   // Removes all a=ssrc lines from the SDP string.
RemoveSsrcLinesFromSdpString(std::string * sdp_string)1684*d9f75844SAndroid Build Coastguard Worker   void RemoveSsrcLinesFromSdpString(std::string* sdp_string) {
1685*d9f75844SAndroid Build Coastguard Worker     const char kAttributeSsrc[] = "a=ssrc";
1686*d9f75844SAndroid Build Coastguard Worker     while (sdp_string->find(kAttributeSsrc) != std::string::npos) {
1687*d9f75844SAndroid Build Coastguard Worker       size_t pos_ssrc_attribute = sdp_string->find(kAttributeSsrc);
1688*d9f75844SAndroid Build Coastguard Worker       size_t beg_line_pos = sdp_string->rfind('\n', pos_ssrc_attribute);
1689*d9f75844SAndroid Build Coastguard Worker       size_t end_line_pos = sdp_string->find('\n', pos_ssrc_attribute);
1690*d9f75844SAndroid Build Coastguard Worker       sdp_string->erase(beg_line_pos, end_line_pos - beg_line_pos);
1691*d9f75844SAndroid Build Coastguard Worker     }
1692*d9f75844SAndroid Build Coastguard Worker   }
1693*d9f75844SAndroid Build Coastguard Worker 
TestSerializeDirection(RtpTransceiverDirection direction)1694*d9f75844SAndroid Build Coastguard Worker   bool TestSerializeDirection(RtpTransceiverDirection direction) {
1695*d9f75844SAndroid Build Coastguard Worker     audio_desc_->set_direction(direction);
1696*d9f75844SAndroid Build Coastguard Worker     video_desc_->set_direction(direction);
1697*d9f75844SAndroid Build Coastguard Worker     std::string new_sdp = kSdpFullString;
1698*d9f75844SAndroid Build Coastguard Worker     ReplaceDirection(direction, &new_sdp);
1699*d9f75844SAndroid Build Coastguard Worker 
1700*d9f75844SAndroid Build Coastguard Worker     if (!jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1701*d9f75844SAndroid Build Coastguard Worker                            jdesc_.session_version())) {
1702*d9f75844SAndroid Build Coastguard Worker       return false;
1703*d9f75844SAndroid Build Coastguard Worker     }
1704*d9f75844SAndroid Build Coastguard Worker     std::string message = webrtc::SdpSerialize(jdesc_);
1705*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_sdp, message);
1706*d9f75844SAndroid Build Coastguard Worker     return true;
1707*d9f75844SAndroid Build Coastguard Worker   }
1708*d9f75844SAndroid Build Coastguard Worker 
TestSerializeRejected(bool audio_rejected,bool video_rejected)1709*d9f75844SAndroid Build Coastguard Worker   bool TestSerializeRejected(bool audio_rejected, bool video_rejected) {
1710*d9f75844SAndroid Build Coastguard Worker     audio_desc_ = new AudioContentDescription(*audio_desc_);
1711*d9f75844SAndroid Build Coastguard Worker     video_desc_ = new VideoContentDescription(*video_desc_);
1712*d9f75844SAndroid Build Coastguard Worker 
1713*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kAudioContentName);
1714*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1715*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp, audio_rejected,
1716*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_));
1717*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp, video_rejected,
1718*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_));
1719*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(kAudioContentName, audio_rejected ? "" : kUfragVoice,
1720*d9f75844SAndroid Build Coastguard Worker                    audio_rejected ? "" : kPwdVoice);
1721*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(kVideoContentName, video_rejected ? "" : kUfragVideo,
1722*d9f75844SAndroid Build Coastguard Worker                    video_rejected ? "" : kPwdVideo);
1723*d9f75844SAndroid Build Coastguard Worker 
1724*d9f75844SAndroid Build Coastguard Worker     std::string new_sdp = kSdpString;
1725*d9f75844SAndroid Build Coastguard Worker     ReplaceRejected(audio_rejected, video_rejected, &new_sdp);
1726*d9f75844SAndroid Build Coastguard Worker 
1727*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jdesc_no_candidates(kDummyType);
1728*d9f75844SAndroid Build Coastguard Worker     MakeDescriptionWithoutCandidates(&jdesc_no_candidates);
1729*d9f75844SAndroid Build Coastguard Worker     std::string message = webrtc::SdpSerialize(jdesc_no_candidates);
1730*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_sdp, message);
1731*d9f75844SAndroid Build Coastguard Worker     return true;
1732*d9f75844SAndroid Build Coastguard Worker   }
1733*d9f75844SAndroid Build Coastguard Worker 
AddSctpDataChannel(bool use_sctpmap)1734*d9f75844SAndroid Build Coastguard Worker   void AddSctpDataChannel(bool use_sctpmap) {
1735*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<SctpDataContentDescription> data(
1736*d9f75844SAndroid Build Coastguard Worker         new SctpDataContentDescription());
1737*d9f75844SAndroid Build Coastguard Worker     sctp_desc_ = data.get();
1738*d9f75844SAndroid Build Coastguard Worker     sctp_desc_->set_use_sctpmap(use_sctpmap);
1739*d9f75844SAndroid Build Coastguard Worker     sctp_desc_->set_protocol(cricket::kMediaProtocolUdpDtlsSctp);
1740*d9f75844SAndroid Build Coastguard Worker     sctp_desc_->set_port(kDefaultSctpPort);
1741*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
1742*d9f75844SAndroid Build Coastguard Worker                      std::move(data));
1743*d9f75844SAndroid Build Coastguard Worker     desc_.AddTransportInfo(TransportInfo(
1744*d9f75844SAndroid Build Coastguard Worker         kDataContentName, TransportDescription(kUfragData, kPwdData)));
1745*d9f75844SAndroid Build Coastguard Worker   }
1746*d9f75844SAndroid Build Coastguard Worker 
TestDeserializeDirection(RtpTransceiverDirection direction)1747*d9f75844SAndroid Build Coastguard Worker   bool TestDeserializeDirection(RtpTransceiverDirection direction) {
1748*d9f75844SAndroid Build Coastguard Worker     std::string new_sdp = kSdpFullString;
1749*d9f75844SAndroid Build Coastguard Worker     ReplaceDirection(direction, &new_sdp);
1750*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription new_jdesc(kDummyType);
1751*d9f75844SAndroid Build Coastguard Worker 
1752*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(SdpDeserialize(new_sdp, &new_jdesc));
1753*d9f75844SAndroid Build Coastguard Worker 
1754*d9f75844SAndroid Build Coastguard Worker     audio_desc_->set_direction(direction);
1755*d9f75844SAndroid Build Coastguard Worker     video_desc_->set_direction(direction);
1756*d9f75844SAndroid Build Coastguard Worker     if (!jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
1757*d9f75844SAndroid Build Coastguard Worker                            jdesc_.session_version())) {
1758*d9f75844SAndroid Build Coastguard Worker       return false;
1759*d9f75844SAndroid Build Coastguard Worker     }
1760*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(CompareSessionDescription(jdesc_, new_jdesc));
1761*d9f75844SAndroid Build Coastguard Worker     return true;
1762*d9f75844SAndroid Build Coastguard Worker   }
1763*d9f75844SAndroid Build Coastguard Worker 
TestDeserializeRejected(bool audio_rejected,bool video_rejected)1764*d9f75844SAndroid Build Coastguard Worker   bool TestDeserializeRejected(bool audio_rejected, bool video_rejected) {
1765*d9f75844SAndroid Build Coastguard Worker     std::string new_sdp = kSdpString;
1766*d9f75844SAndroid Build Coastguard Worker     ReplaceRejected(audio_rejected, video_rejected, &new_sdp);
1767*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription new_jdesc(SdpType::kOffer);
1768*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(SdpDeserialize(new_sdp, &new_jdesc));
1769*d9f75844SAndroid Build Coastguard Worker 
1770*d9f75844SAndroid Build Coastguard Worker     audio_desc_ = new AudioContentDescription(*audio_desc_);
1771*d9f75844SAndroid Build Coastguard Worker     video_desc_ = new VideoContentDescription(*video_desc_);
1772*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kAudioContentName);
1773*d9f75844SAndroid Build Coastguard Worker     desc_.RemoveContentByName(kVideoContentName);
1774*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kAudioContentName, MediaProtocolType::kRtp, audio_rejected,
1775*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(audio_desc_));
1776*d9f75844SAndroid Build Coastguard Worker     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp, video_rejected,
1777*d9f75844SAndroid Build Coastguard Worker                      absl::WrapUnique(video_desc_));
1778*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(kAudioContentName, audio_rejected ? "" : kUfragVoice,
1779*d9f75844SAndroid Build Coastguard Worker                    audio_rejected ? "" : kPwdVoice);
1780*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(kVideoContentName, video_rejected ? "" : kUfragVideo,
1781*d9f75844SAndroid Build Coastguard Worker                    video_rejected ? "" : kPwdVideo);
1782*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jdesc_no_candidates(kDummyType);
1783*d9f75844SAndroid Build Coastguard Worker     if (!jdesc_no_candidates.Initialize(desc_.Clone(), jdesc_.session_id(),
1784*d9f75844SAndroid Build Coastguard Worker                                         jdesc_.session_version())) {
1785*d9f75844SAndroid Build Coastguard Worker       return false;
1786*d9f75844SAndroid Build Coastguard Worker     }
1787*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(CompareSessionDescription(jdesc_no_candidates, new_jdesc));
1788*d9f75844SAndroid Build Coastguard Worker     return true;
1789*d9f75844SAndroid Build Coastguard Worker   }
1790*d9f75844SAndroid Build Coastguard Worker 
TestDeserializeExtmap(bool session_level,bool media_level,bool encrypted)1791*d9f75844SAndroid Build Coastguard Worker   void TestDeserializeExtmap(bool session_level,
1792*d9f75844SAndroid Build Coastguard Worker                              bool media_level,
1793*d9f75844SAndroid Build Coastguard Worker                              bool encrypted) {
1794*d9f75844SAndroid Build Coastguard Worker     AddExtmap(encrypted);
1795*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription new_jdesc(SdpType::kOffer);
1796*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(new_jdesc.Initialize(desc_.Clone(), jdesc_.session_id(),
1797*d9f75844SAndroid Build Coastguard Worker                                      jdesc_.session_version()));
1798*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jdesc_with_extmap(SdpType::kOffer);
1799*d9f75844SAndroid Build Coastguard Worker     std::string sdp_with_extmap = kSdpString;
1800*d9f75844SAndroid Build Coastguard Worker     if (session_level) {
1801*d9f75844SAndroid Build Coastguard Worker       InjectAfter(kSessionTime,
1802*d9f75844SAndroid Build Coastguard Worker                   encrypted ? kExtmapWithDirectionAndAttributeEncrypted
1803*d9f75844SAndroid Build Coastguard Worker                             : kExtmapWithDirectionAndAttribute,
1804*d9f75844SAndroid Build Coastguard Worker                   &sdp_with_extmap);
1805*d9f75844SAndroid Build Coastguard Worker     }
1806*d9f75844SAndroid Build Coastguard Worker     if (media_level) {
1807*d9f75844SAndroid Build Coastguard Worker       InjectAfter(kAttributeIcePwdVoice,
1808*d9f75844SAndroid Build Coastguard Worker                   encrypted ? kExtmapWithDirectionAndAttributeEncrypted
1809*d9f75844SAndroid Build Coastguard Worker                             : kExtmapWithDirectionAndAttribute,
1810*d9f75844SAndroid Build Coastguard Worker                   &sdp_with_extmap);
1811*d9f75844SAndroid Build Coastguard Worker       InjectAfter(kAttributeIcePwdVideo,
1812*d9f75844SAndroid Build Coastguard Worker                   encrypted ? kExtmapWithDirectionAndAttributeEncrypted
1813*d9f75844SAndroid Build Coastguard Worker                             : kExtmapWithDirectionAndAttribute,
1814*d9f75844SAndroid Build Coastguard Worker                   &sdp_with_extmap);
1815*d9f75844SAndroid Build Coastguard Worker     }
1816*d9f75844SAndroid Build Coastguard Worker     // The extmap can't be present at the same time in both session level and
1817*d9f75844SAndroid Build Coastguard Worker     // media level.
1818*d9f75844SAndroid Build Coastguard Worker     if (session_level && media_level) {
1819*d9f75844SAndroid Build Coastguard Worker       SdpParseError error;
1820*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(
1821*d9f75844SAndroid Build Coastguard Worker           webrtc::SdpDeserialize(sdp_with_extmap, &jdesc_with_extmap, &error));
1822*d9f75844SAndroid Build Coastguard Worker       EXPECT_NE(std::string::npos, error.description.find("a=extmap"));
1823*d9f75844SAndroid Build Coastguard Worker     } else {
1824*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(SdpDeserialize(sdp_with_extmap, &jdesc_with_extmap));
1825*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(CompareSessionDescription(jdesc_with_extmap, new_jdesc));
1826*d9f75844SAndroid Build Coastguard Worker     }
1827*d9f75844SAndroid Build Coastguard Worker   }
1828*d9f75844SAndroid Build Coastguard Worker 
VerifyCodecParameter(const cricket::CodecParameterMap & params,const std::string & name,int expected_value)1829*d9f75844SAndroid Build Coastguard Worker   void VerifyCodecParameter(const cricket::CodecParameterMap& params,
1830*d9f75844SAndroid Build Coastguard Worker                             const std::string& name,
1831*d9f75844SAndroid Build Coastguard Worker                             int expected_value) {
1832*d9f75844SAndroid Build Coastguard Worker     cricket::CodecParameterMap::const_iterator found = params.find(name);
1833*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(found != params.end());
1834*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(found->second, rtc::ToString(expected_value));
1835*d9f75844SAndroid Build Coastguard Worker   }
1836*d9f75844SAndroid Build Coastguard Worker 
TestDeserializeCodecParams(const CodecParams & params,JsepSessionDescription * jdesc_output)1837*d9f75844SAndroid Build Coastguard Worker   void TestDeserializeCodecParams(const CodecParams& params,
1838*d9f75844SAndroid Build Coastguard Worker                                   JsepSessionDescription* jdesc_output) {
1839*d9f75844SAndroid Build Coastguard Worker     std::string sdp =
1840*d9f75844SAndroid Build Coastguard Worker         "v=0\r\n"
1841*d9f75844SAndroid Build Coastguard Worker         "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
1842*d9f75844SAndroid Build Coastguard Worker         "s=-\r\n"
1843*d9f75844SAndroid Build Coastguard Worker         "t=0 0\r\n"
1844*d9f75844SAndroid Build Coastguard Worker         // Include semantics for WebRTC Media Streams since it is supported by
1845*d9f75844SAndroid Build Coastguard Worker         // this parser, and will be added to the SDP when serializing a session
1846*d9f75844SAndroid Build Coastguard Worker         // description.
1847*d9f75844SAndroid Build Coastguard Worker         "a=msid-semantic: WMS\r\n"
1848*d9f75844SAndroid Build Coastguard Worker         // Pl type 111 preferred.
1849*d9f75844SAndroid Build Coastguard Worker         "m=audio 9 RTP/SAVPF 111 104 103 105\r\n"
1850*d9f75844SAndroid Build Coastguard Worker         // Pltype 111 listed before 103 and 104 in the map.
1851*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:111 opus/48000/2\r\n"
1852*d9f75844SAndroid Build Coastguard Worker         // Pltype 103 listed before 104.
1853*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:103 ISAC/16000\r\n"
1854*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:104 ISAC/32000\r\n"
1855*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:105 telephone-event/8000\r\n"
1856*d9f75844SAndroid Build Coastguard Worker         "a=fmtp:105 0-15,66,70\r\n"
1857*d9f75844SAndroid Build Coastguard Worker         "a=fmtp:111 ";
1858*d9f75844SAndroid Build Coastguard Worker     std::ostringstream os;
1859*d9f75844SAndroid Build Coastguard Worker     os << "minptime=" << params.min_ptime << "; stereo=" << params.stereo
1860*d9f75844SAndroid Build Coastguard Worker        << "; sprop-stereo=" << params.sprop_stereo
1861*d9f75844SAndroid Build Coastguard Worker        << "; useinbandfec=" << params.useinband
1862*d9f75844SAndroid Build Coastguard Worker        << "; maxaveragebitrate=" << params.maxaveragebitrate
1863*d9f75844SAndroid Build Coastguard Worker        << "\r\n"
1864*d9f75844SAndroid Build Coastguard Worker           "a=ptime:"
1865*d9f75844SAndroid Build Coastguard Worker        << params.ptime
1866*d9f75844SAndroid Build Coastguard Worker        << "\r\n"
1867*d9f75844SAndroid Build Coastguard Worker           "a=maxptime:"
1868*d9f75844SAndroid Build Coastguard Worker        << params.max_ptime << "\r\n";
1869*d9f75844SAndroid Build Coastguard Worker     sdp += os.str();
1870*d9f75844SAndroid Build Coastguard Worker 
1871*d9f75844SAndroid Build Coastguard Worker     os.clear();
1872*d9f75844SAndroid Build Coastguard Worker     os.str("");
1873*d9f75844SAndroid Build Coastguard Worker     // Pl type 100 preferred.
1874*d9f75844SAndroid Build Coastguard Worker     os << "m=video 9 RTP/SAVPF 99 95 96\r\n"
1875*d9f75844SAndroid Build Coastguard Worker           "a=rtpmap:96 VP9/90000\r\n"  // out-of-order wrt the m= line.
1876*d9f75844SAndroid Build Coastguard Worker           "a=rtpmap:99 VP8/90000\r\n"
1877*d9f75844SAndroid Build Coastguard Worker           "a=rtpmap:95 RTX/90000\r\n"
1878*d9f75844SAndroid Build Coastguard Worker           "a=fmtp:95 apt=99;\r\n";
1879*d9f75844SAndroid Build Coastguard Worker     sdp += os.str();
1880*d9f75844SAndroid Build Coastguard Worker 
1881*d9f75844SAndroid Build Coastguard Worker     // Deserialize
1882*d9f75844SAndroid Build Coastguard Worker     SdpParseError error;
1883*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(webrtc::SdpDeserialize(sdp, jdesc_output, &error));
1884*d9f75844SAndroid Build Coastguard Worker 
1885*d9f75844SAndroid Build Coastguard Worker     const AudioContentDescription* acd =
1886*d9f75844SAndroid Build Coastguard Worker         GetFirstAudioContentDescription(jdesc_output->description());
1887*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(acd);
1888*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(acd->codecs().empty());
1889*d9f75844SAndroid Build Coastguard Worker     cricket::AudioCodec opus = acd->codecs()[0];
1890*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ("opus", opus.name);
1891*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(111, opus.id);
1892*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(opus.params, "minptime", params.min_ptime);
1893*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(opus.params, "stereo", params.stereo);
1894*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(opus.params, "sprop-stereo", params.sprop_stereo);
1895*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(opus.params, "useinbandfec", params.useinband);
1896*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(opus.params, "maxaveragebitrate",
1897*d9f75844SAndroid Build Coastguard Worker                          params.maxaveragebitrate);
1898*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < acd->codecs().size(); ++i) {
1899*d9f75844SAndroid Build Coastguard Worker       cricket::AudioCodec codec = acd->codecs()[i];
1900*d9f75844SAndroid Build Coastguard Worker       VerifyCodecParameter(codec.params, "ptime", params.ptime);
1901*d9f75844SAndroid Build Coastguard Worker       VerifyCodecParameter(codec.params, "maxptime", params.max_ptime);
1902*d9f75844SAndroid Build Coastguard Worker     }
1903*d9f75844SAndroid Build Coastguard Worker 
1904*d9f75844SAndroid Build Coastguard Worker     cricket::AudioCodec dtmf = acd->codecs()[3];
1905*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ("telephone-event", dtmf.name);
1906*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(105, dtmf.id);
1907*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(3u,
1908*d9f75844SAndroid Build Coastguard Worker               dtmf.params.size());  // ptime and max_ptime count as parameters.
1909*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(dtmf.params.begin()->first, "");
1910*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(dtmf.params.begin()->second, "0-15,66,70");
1911*d9f75844SAndroid Build Coastguard Worker 
1912*d9f75844SAndroid Build Coastguard Worker     const VideoContentDescription* vcd =
1913*d9f75844SAndroid Build Coastguard Worker         GetFirstVideoContentDescription(jdesc_output->description());
1914*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(vcd);
1915*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(vcd->codecs().empty());
1916*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec vp8 = vcd->codecs()[0];
1917*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ("VP8", vp8.name);
1918*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(99, vp8.id);
1919*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec rtx = vcd->codecs()[1];
1920*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ("RTX", rtx.name);
1921*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(95, rtx.id);
1922*d9f75844SAndroid Build Coastguard Worker     VerifyCodecParameter(rtx.params, "apt", vp8.id);
1923*d9f75844SAndroid Build Coastguard Worker     // VP9 is listed last in the m= line so should come after VP8 and RTX.
1924*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec vp9 = vcd->codecs()[2];
1925*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ("VP9", vp9.name);
1926*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(96, vp9.id);
1927*d9f75844SAndroid Build Coastguard Worker   }
1928*d9f75844SAndroid Build Coastguard Worker 
TestDeserializeRtcpFb(JsepSessionDescription * jdesc_output,bool use_wildcard)1929*d9f75844SAndroid Build Coastguard Worker   void TestDeserializeRtcpFb(JsepSessionDescription* jdesc_output,
1930*d9f75844SAndroid Build Coastguard Worker                              bool use_wildcard) {
1931*d9f75844SAndroid Build Coastguard Worker     std::string sdp_session_and_audio =
1932*d9f75844SAndroid Build Coastguard Worker         "v=0\r\n"
1933*d9f75844SAndroid Build Coastguard Worker         "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
1934*d9f75844SAndroid Build Coastguard Worker         "s=-\r\n"
1935*d9f75844SAndroid Build Coastguard Worker         "t=0 0\r\n"
1936*d9f75844SAndroid Build Coastguard Worker         // Include semantics for WebRTC Media Streams since it is supported by
1937*d9f75844SAndroid Build Coastguard Worker         // this parser, and will be added to the SDP when serializing a session
1938*d9f75844SAndroid Build Coastguard Worker         // description.
1939*d9f75844SAndroid Build Coastguard Worker         "a=msid-semantic: WMS\r\n"
1940*d9f75844SAndroid Build Coastguard Worker         "m=audio 9 RTP/SAVPF 111\r\n"
1941*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:111 opus/48000/2\r\n";
1942*d9f75844SAndroid Build Coastguard Worker     std::string sdp_video =
1943*d9f75844SAndroid Build Coastguard Worker         "m=video 3457 RTP/SAVPF 101\r\n"
1944*d9f75844SAndroid Build Coastguard Worker         "a=rtpmap:101 VP8/90000\r\n"
1945*d9f75844SAndroid Build Coastguard Worker         "a=rtcp-fb:101 goog-lntf\r\n"
1946*d9f75844SAndroid Build Coastguard Worker         "a=rtcp-fb:101 nack\r\n"
1947*d9f75844SAndroid Build Coastguard Worker         "a=rtcp-fb:101 nack pli\r\n"
1948*d9f75844SAndroid Build Coastguard Worker         "a=rtcp-fb:101 goog-remb\r\n";
1949*d9f75844SAndroid Build Coastguard Worker     std::ostringstream os;
1950*d9f75844SAndroid Build Coastguard Worker     os << sdp_session_and_audio;
1951*d9f75844SAndroid Build Coastguard Worker     os << "a=rtcp-fb:" << (use_wildcard ? "*" : "111") << " nack\r\n";
1952*d9f75844SAndroid Build Coastguard Worker     os << sdp_video;
1953*d9f75844SAndroid Build Coastguard Worker     os << "a=rtcp-fb:" << (use_wildcard ? "*" : "101") << " ccm fir\r\n";
1954*d9f75844SAndroid Build Coastguard Worker     std::string sdp = os.str();
1955*d9f75844SAndroid Build Coastguard Worker     // Deserialize
1956*d9f75844SAndroid Build Coastguard Worker     SdpParseError error;
1957*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(webrtc::SdpDeserialize(sdp, jdesc_output, &error));
1958*d9f75844SAndroid Build Coastguard Worker     const AudioContentDescription* acd =
1959*d9f75844SAndroid Build Coastguard Worker         GetFirstAudioContentDescription(jdesc_output->description());
1960*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(acd);
1961*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(acd->codecs().empty());
1962*d9f75844SAndroid Build Coastguard Worker     cricket::AudioCodec opus = acd->codecs()[0];
1963*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(111, opus.id);
1964*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(opus.HasFeedbackParam(cricket::FeedbackParam(
1965*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamNack, cricket::kParamValueEmpty)));
1966*d9f75844SAndroid Build Coastguard Worker 
1967*d9f75844SAndroid Build Coastguard Worker     const VideoContentDescription* vcd =
1968*d9f75844SAndroid Build Coastguard Worker         GetFirstVideoContentDescription(jdesc_output->description());
1969*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(vcd);
1970*d9f75844SAndroid Build Coastguard Worker     ASSERT_FALSE(vcd->codecs().empty());
1971*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec vp8 = vcd->codecs()[0];
1972*d9f75844SAndroid Build Coastguard Worker     EXPECT_STREQ(webrtc::JsepSessionDescription::kDefaultVideoCodecName,
1973*d9f75844SAndroid Build Coastguard Worker                  vp8.name.c_str());
1974*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(101, vp8.id);
1975*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp8.HasFeedbackParam(cricket::FeedbackParam(
1976*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamLntf, cricket::kParamValueEmpty)));
1977*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp8.HasFeedbackParam(cricket::FeedbackParam(
1978*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamNack, cricket::kParamValueEmpty)));
1979*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp8.HasFeedbackParam(cricket::FeedbackParam(
1980*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamNack, cricket::kRtcpFbNackParamPli)));
1981*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp8.HasFeedbackParam(cricket::FeedbackParam(
1982*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamRemb, cricket::kParamValueEmpty)));
1983*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp8.HasFeedbackParam(cricket::FeedbackParam(
1984*d9f75844SAndroid Build Coastguard Worker         cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir)));
1985*d9f75844SAndroid Build Coastguard Worker   }
1986*d9f75844SAndroid Build Coastguard Worker 
1987*d9f75844SAndroid Build Coastguard Worker   // Two SDP messages can mean the same thing but be different strings, e.g.
1988*d9f75844SAndroid Build Coastguard Worker   // some of the lines can be serialized in different order.
1989*d9f75844SAndroid Build Coastguard Worker   // However, a deserialized description can be compared field by field and has
1990*d9f75844SAndroid Build Coastguard Worker   // no order. If deserializer has already been tested, serializing then
1991*d9f75844SAndroid Build Coastguard Worker   // deserializing and comparing JsepSessionDescription will test
1992*d9f75844SAndroid Build Coastguard Worker   // the serializer sufficiently.
TestSerialize(const JsepSessionDescription & jdesc)1993*d9f75844SAndroid Build Coastguard Worker   void TestSerialize(const JsepSessionDescription& jdesc) {
1994*d9f75844SAndroid Build Coastguard Worker     std::string message = webrtc::SdpSerialize(jdesc);
1995*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jdesc_output_des(kDummyType);
1996*d9f75844SAndroid Build Coastguard Worker     SdpParseError error;
1997*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(webrtc::SdpDeserialize(message, &jdesc_output_des, &error));
1998*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output_des));
1999*d9f75844SAndroid Build Coastguard Worker   }
2000*d9f75844SAndroid Build Coastguard Worker 
2001*d9f75844SAndroid Build Coastguard Worker   // Calling 'Initialize' with a copy of the inner SessionDescription will
2002*d9f75844SAndroid Build Coastguard Worker   // create a copy of the JsepSessionDescription without candidates. The
2003*d9f75844SAndroid Build Coastguard Worker   // 'connection address' field, previously set from the candidates, must also
2004*d9f75844SAndroid Build Coastguard Worker   // be reset.
MakeDescriptionWithoutCandidates(JsepSessionDescription * jdesc)2005*d9f75844SAndroid Build Coastguard Worker   void MakeDescriptionWithoutCandidates(JsepSessionDescription* jdesc) {
2006*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress audio_addr("0.0.0.0", 9);
2007*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress video_addr("0.0.0.0", 9);
2008*d9f75844SAndroid Build Coastguard Worker     audio_desc_->set_connection_address(audio_addr);
2009*d9f75844SAndroid Build Coastguard Worker     video_desc_->set_connection_address(video_addr);
2010*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(jdesc->Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2011*d9f75844SAndroid Build Coastguard Worker   }
2012*d9f75844SAndroid Build Coastguard Worker 
2013*d9f75844SAndroid Build Coastguard Worker  protected:
2014*d9f75844SAndroid Build Coastguard Worker   SessionDescription desc_;
2015*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* audio_desc_;
2016*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* video_desc_;
2017*d9f75844SAndroid Build Coastguard Worker   SctpDataContentDescription* sctp_desc_;
2018*d9f75844SAndroid Build Coastguard Worker   Candidates candidates_;
2019*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jcandidate_;
2020*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_;
2021*d9f75844SAndroid Build Coastguard Worker };
2022*d9f75844SAndroid Build Coastguard Worker 
TestMismatch(const std::string & string1,const std::string & string2)2023*d9f75844SAndroid Build Coastguard Worker void TestMismatch(const std::string& string1, const std::string& string2) {
2024*d9f75844SAndroid Build Coastguard Worker   int position = 0;
2025*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < string1.length() && i < string2.length(); ++i) {
2026*d9f75844SAndroid Build Coastguard Worker     if (string1.c_str()[i] != string2.c_str()[i]) {
2027*d9f75844SAndroid Build Coastguard Worker       position = static_cast<int>(i);
2028*d9f75844SAndroid Build Coastguard Worker       break;
2029*d9f75844SAndroid Build Coastguard Worker     }
2030*d9f75844SAndroid Build Coastguard Worker   }
2031*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, position) << "Strings mismatch at the " << position
2032*d9f75844SAndroid Build Coastguard Worker                          << " character\n"
2033*d9f75844SAndroid Build Coastguard Worker                             " 1: "
2034*d9f75844SAndroid Build Coastguard Worker                          << string1.substr(position, 20)
2035*d9f75844SAndroid Build Coastguard Worker                          << "\n"
2036*d9f75844SAndroid Build Coastguard Worker                             " 2: "
2037*d9f75844SAndroid Build Coastguard Worker                          << string2.substr(position, 20) << "\n";
2038*d9f75844SAndroid Build Coastguard Worker }
2039*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescription)2040*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescription) {
2041*d9f75844SAndroid Build Coastguard Worker   // SessionDescription with desc and candidates.
2042*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2043*d9f75844SAndroid Build Coastguard Worker   TestMismatch(std::string(kSdpFullString), message);
2044*d9f75844SAndroid Build Coastguard Worker }
2045*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionEmpty)2046*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionEmpty) {
2047*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_empty(kDummyType);
2048*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("", webrtc::SdpSerialize(jdesc_empty));
2049*d9f75844SAndroid Build Coastguard Worker }
2050*d9f75844SAndroid Build Coastguard Worker 
2051*d9f75844SAndroid Build Coastguard Worker // This tests serialization of SDP with a=crypto and a=fingerprint, as would be
2052*d9f75844SAndroid Build Coastguard Worker // the case in a DTLS offer.
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithFingerprint)2053*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithFingerprint) {
2054*d9f75844SAndroid Build Coastguard Worker   AddFingerprint();
2055*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_fingerprint(kDummyType);
2056*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jdesc_with_fingerprint);
2057*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_with_fingerprint);
2058*d9f75844SAndroid Build Coastguard Worker 
2059*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fingerprint = kSdpString;
2060*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_fingerprint);
2061*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_fingerprint);
2062*d9f75844SAndroid Build Coastguard Worker 
2063*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fingerprint, message);
2064*d9f75844SAndroid Build Coastguard Worker }
2065*d9f75844SAndroid Build Coastguard Worker 
2066*d9f75844SAndroid Build Coastguard Worker // This tests serialization of SDP with a=fingerprint with no a=crypto, as would
2067*d9f75844SAndroid Build Coastguard Worker // be the case in a DTLS answer.
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithFingerprintNoCryptos)2068*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithFingerprintNoCryptos) {
2069*d9f75844SAndroid Build Coastguard Worker   AddFingerprint();
2070*d9f75844SAndroid Build Coastguard Worker   RemoveCryptos();
2071*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_fingerprint(kDummyType);
2072*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jdesc_with_fingerprint);
2073*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_with_fingerprint);
2074*d9f75844SAndroid Build Coastguard Worker 
2075*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fingerprint = kSdpString;
2076*d9f75844SAndroid Build Coastguard Worker   Replace(kAttributeCryptoVoice, "", &sdp_with_fingerprint);
2077*d9f75844SAndroid Build Coastguard Worker   Replace(kAttributeCryptoVideo, "", &sdp_with_fingerprint);
2078*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_fingerprint);
2079*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_fingerprint);
2080*d9f75844SAndroid Build Coastguard Worker 
2081*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fingerprint, message);
2082*d9f75844SAndroid Build Coastguard Worker }
2083*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithoutCandidates)2084*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithoutCandidates) {
2085*d9f75844SAndroid Build Coastguard Worker   // JsepSessionDescription with desc but without candidates.
2086*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_no_candidates(kDummyType);
2087*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jdesc_no_candidates);
2088*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_no_candidates);
2089*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kSdpString), message);
2090*d9f75844SAndroid Build Coastguard Worker }
2091*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithBundles)2092*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithBundles) {
2093*d9f75844SAndroid Build Coastguard Worker   ContentGroup group1(cricket::GROUP_TYPE_BUNDLE);
2094*d9f75844SAndroid Build Coastguard Worker   group1.AddContentName(kAudioContentName);
2095*d9f75844SAndroid Build Coastguard Worker   group1.AddContentName(kVideoContentName);
2096*d9f75844SAndroid Build Coastguard Worker   desc_.AddGroup(group1);
2097*d9f75844SAndroid Build Coastguard Worker   ContentGroup group2(cricket::GROUP_TYPE_BUNDLE);
2098*d9f75844SAndroid Build Coastguard Worker   group2.AddContentName(kAudioContentName2);
2099*d9f75844SAndroid Build Coastguard Worker   desc_.AddGroup(group2);
2100*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2101*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2102*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2103*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bundle = kSdpFullString;
2104*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime,
2105*d9f75844SAndroid Build Coastguard Worker               "a=group:BUNDLE audio_content_name video_content_name\r\n"
2106*d9f75844SAndroid Build Coastguard Worker               "a=group:BUNDLE audio_content_name_2\r\n",
2107*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bundle);
2108*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_bundle, message);
2109*d9f75844SAndroid Build Coastguard Worker }
2110*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithBandwidth)2111*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithBandwidth) {
2112*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
2113*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth(100 * 1000 + 755);  // Integer division will drop the 755.
2114*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth_type("AS");
2115*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
2116*d9f75844SAndroid Build Coastguard Worker   acd->set_bandwidth(555);
2117*d9f75844SAndroid Build Coastguard Worker   acd->set_bandwidth_type("TIAS");
2118*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2119*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2120*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2121*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpFullString;
2122*d9f75844SAndroid Build Coastguard Worker   InjectAfter("c=IN IP4 74.125.224.39\r\n", "b=AS:100\r\n",
2123*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2124*d9f75844SAndroid Build Coastguard Worker   InjectAfter("c=IN IP4 74.125.127.126\r\n", "b=TIAS:555\r\n",
2125*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2126*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_bandwidth, message);
2127*d9f75844SAndroid Build Coastguard Worker }
2128*d9f75844SAndroid Build Coastguard Worker 
2129*d9f75844SAndroid Build Coastguard Worker // Should default to b=AS if bandwidth_type isn't set.
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithMissingBandwidthType)2130*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithMissingBandwidthType) {
2131*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
2132*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth(100 * 1000);
2133*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2134*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2135*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2136*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpFullString;
2137*d9f75844SAndroid Build Coastguard Worker   InjectAfter("c=IN IP4 74.125.224.39\r\n", "b=AS:100\r\n",
2138*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2139*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_bandwidth, message);
2140*d9f75844SAndroid Build Coastguard Worker }
2141*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithIceOptions)2142*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithIceOptions) {
2143*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> transport_options;
2144*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption1);
2145*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption3);
2146*d9f75844SAndroid Build Coastguard Worker   AddIceOptions(kAudioContentName, transport_options);
2147*d9f75844SAndroid Build Coastguard Worker   transport_options.clear();
2148*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption2);
2149*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption3);
2150*d9f75844SAndroid Build Coastguard Worker   AddIceOptions(kVideoContentName, transport_options);
2151*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2152*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2153*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2154*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_ice_options = kSdpFullString;
2155*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, "a=ice-options:iceoption1 iceoption3\r\n",
2156*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ice_options);
2157*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, "a=ice-options:iceoption2 iceoption3\r\n",
2158*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ice_options);
2159*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_ice_options, message);
2160*d9f75844SAndroid Build Coastguard Worker }
2161*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithRecvOnlyContent)2162*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithRecvOnlyContent) {
2163*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeDirection(RtpTransceiverDirection::kRecvOnly));
2164*d9f75844SAndroid Build Coastguard Worker }
2165*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithSendOnlyContent)2166*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithSendOnlyContent) {
2167*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeDirection(RtpTransceiverDirection::kSendOnly));
2168*d9f75844SAndroid Build Coastguard Worker }
2169*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithInactiveContent)2170*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithInactiveContent) {
2171*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeDirection(RtpTransceiverDirection::kInactive));
2172*d9f75844SAndroid Build Coastguard Worker }
2173*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithAudioRejected)2174*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithAudioRejected) {
2175*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeRejected(true, false));
2176*d9f75844SAndroid Build Coastguard Worker }
2177*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithVideoRejected)2178*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithVideoRejected) {
2179*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeRejected(false, true));
2180*d9f75844SAndroid Build Coastguard Worker }
2181*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithAudioVideoRejected)2182*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithAudioVideoRejected) {
2183*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestSerializeRejected(true, true));
2184*d9f75844SAndroid Build Coastguard Worker }
2185*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithSctpDataChannel)2186*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithSctpDataChannel) {
2187*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2188*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2189*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
2190*d9f75844SAndroid Build Coastguard Worker 
2191*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jsep_desc);
2192*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jsep_desc);
2193*d9f75844SAndroid Build Coastguard Worker 
2194*d9f75844SAndroid Build Coastguard Worker   std::string expected_sdp = kSdpString;
2195*d9f75844SAndroid Build Coastguard Worker   expected_sdp.append(kSdpSctpDataChannelString);
2196*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(message, expected_sdp);
2197*d9f75844SAndroid Build Coastguard Worker }
2198*d9f75844SAndroid Build Coastguard Worker 
MutateJsepSctpPort(JsepSessionDescription * jdesc,const SessionDescription & desc,int port)2199*d9f75844SAndroid Build Coastguard Worker void MutateJsepSctpPort(JsepSessionDescription* jdesc,
2200*d9f75844SAndroid Build Coastguard Worker                         const SessionDescription& desc,
2201*d9f75844SAndroid Build Coastguard Worker                         int port) {
2202*d9f75844SAndroid Build Coastguard Worker   // Take our pre-built session description and change the SCTP port.
2203*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
2204*d9f75844SAndroid Build Coastguard Worker   SctpDataContentDescription* dcdesc =
2205*d9f75844SAndroid Build Coastguard Worker       mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
2206*d9f75844SAndroid Build Coastguard Worker   dcdesc->set_port(port);
2207*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
2208*d9f75844SAndroid Build Coastguard Worker       jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion));
2209*d9f75844SAndroid Build Coastguard Worker }
2210*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeWithSctpDataChannelAndNewPort)2211*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeWithSctpDataChannelAndNewPort) {
2212*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2213*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2214*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
2215*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jsep_desc);
2216*d9f75844SAndroid Build Coastguard Worker 
2217*d9f75844SAndroid Build Coastguard Worker   const int kNewPort = 1234;
2218*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpPort(&jsep_desc, desc_, kNewPort);
2219*d9f75844SAndroid Build Coastguard Worker 
2220*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jsep_desc);
2221*d9f75844SAndroid Build Coastguard Worker 
2222*d9f75844SAndroid Build Coastguard Worker   std::string expected_sdp = kSdpString;
2223*d9f75844SAndroid Build Coastguard Worker   expected_sdp.append(kSdpSctpDataChannelString);
2224*d9f75844SAndroid Build Coastguard Worker 
2225*d9f75844SAndroid Build Coastguard Worker   absl::StrReplaceAll(
2226*d9f75844SAndroid Build Coastguard Worker       {{rtc::ToString(kDefaultSctpPort), rtc::ToString(kNewPort)}},
2227*d9f75844SAndroid Build Coastguard Worker       &expected_sdp);
2228*d9f75844SAndroid Build Coastguard Worker 
2229*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(expected_sdp, message);
2230*d9f75844SAndroid Build Coastguard Worker }
2231*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithExtmapAllowMixed)2232*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithExtmapAllowMixed) {
2233*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_extmap_allow_mixed(true);
2234*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
2235*d9f75844SAndroid Build Coastguard Worker }
2236*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeMediaContentDescriptionWithExtmapAllowMixed)2237*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeMediaContentDescriptionWithExtmapAllowMixed) {
2238*d9f75844SAndroid Build Coastguard Worker   cricket::MediaContentDescription* video_desc =
2239*d9f75844SAndroid Build Coastguard Worker       jdesc_.description()->GetContentDescriptionByName(kVideoContentName);
2240*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(video_desc);
2241*d9f75844SAndroid Build Coastguard Worker   cricket::MediaContentDescription* audio_desc =
2242*d9f75844SAndroid Build Coastguard Worker       jdesc_.description()->GetContentDescriptionByName(kAudioContentName);
2243*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(audio_desc);
2244*d9f75844SAndroid Build Coastguard Worker   video_desc->set_extmap_allow_mixed_enum(
2245*d9f75844SAndroid Build Coastguard Worker       cricket::MediaContentDescription::kMedia);
2246*d9f75844SAndroid Build Coastguard Worker   audio_desc->set_extmap_allow_mixed_enum(
2247*d9f75844SAndroid Build Coastguard Worker       cricket::MediaContentDescription::kMedia);
2248*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
2249*d9f75844SAndroid Build Coastguard Worker }
2250*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithExtmap)2251*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithExtmap) {
2252*d9f75844SAndroid Build Coastguard Worker   bool encrypted = false;
2253*d9f75844SAndroid Build Coastguard Worker   AddExtmap(encrypted);
2254*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription desc_with_extmap(kDummyType);
2255*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&desc_with_extmap);
2256*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(desc_with_extmap);
2257*d9f75844SAndroid Build Coastguard Worker 
2258*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_extmap = kSdpString;
2259*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:audio_content_name\r\n", kExtmap, &sdp_with_extmap);
2260*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:video_content_name\r\n", kExtmap, &sdp_with_extmap);
2261*d9f75844SAndroid Build Coastguard Worker 
2262*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_extmap, message);
2263*d9f75844SAndroid Build Coastguard Worker }
2264*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithExtmapEncrypted)2265*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithExtmapEncrypted) {
2266*d9f75844SAndroid Build Coastguard Worker   bool encrypted = true;
2267*d9f75844SAndroid Build Coastguard Worker   AddExtmap(encrypted);
2268*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription desc_with_extmap(kDummyType);
2269*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
2270*d9f75844SAndroid Build Coastguard Worker       desc_with_extmap.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2271*d9f75844SAndroid Build Coastguard Worker   TestSerialize(desc_with_extmap);
2272*d9f75844SAndroid Build Coastguard Worker }
2273*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeCandidates)2274*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeCandidates) {
2275*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerializeCandidate(*jcandidate_);
2276*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kRawCandidate), message);
2277*d9f75844SAndroid Build Coastguard Worker 
2278*d9f75844SAndroid Build Coastguard Worker   Candidate candidate_with_ufrag(candidates_.front());
2279*d9f75844SAndroid Build Coastguard Worker   candidate_with_ufrag.set_username("ABC");
2280*d9f75844SAndroid Build Coastguard Worker   jcandidate_.reset(new JsepIceCandidate(std::string("audio_content_name"), 0,
2281*d9f75844SAndroid Build Coastguard Worker                                          candidate_with_ufrag));
2282*d9f75844SAndroid Build Coastguard Worker   message = webrtc::SdpSerializeCandidate(*jcandidate_);
2283*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kRawCandidate) + " ufrag ABC", message);
2284*d9f75844SAndroid Build Coastguard Worker 
2285*d9f75844SAndroid Build Coastguard Worker   Candidate candidate_with_network_info(candidates_.front());
2286*d9f75844SAndroid Build Coastguard Worker   candidate_with_network_info.set_network_id(1);
2287*d9f75844SAndroid Build Coastguard Worker   jcandidate_.reset(new JsepIceCandidate(std::string("audio"), 0,
2288*d9f75844SAndroid Build Coastguard Worker                                          candidate_with_network_info));
2289*d9f75844SAndroid Build Coastguard Worker   message = webrtc::SdpSerializeCandidate(*jcandidate_);
2290*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kRawCandidate) + " network-id 1", message);
2291*d9f75844SAndroid Build Coastguard Worker   candidate_with_network_info.set_network_cost(999);
2292*d9f75844SAndroid Build Coastguard Worker   jcandidate_.reset(new JsepIceCandidate(std::string("audio"), 0,
2293*d9f75844SAndroid Build Coastguard Worker                                          candidate_with_network_info));
2294*d9f75844SAndroid Build Coastguard Worker   message = webrtc::SdpSerializeCandidate(*jcandidate_);
2295*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kRawCandidate) + " network-id 1 network-cost 999",
2296*d9f75844SAndroid Build Coastguard Worker             message);
2297*d9f75844SAndroid Build Coastguard Worker }
2298*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeHostnameCandidate)2299*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeHostnameCandidate) {
2300*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress address("a.test", 1234);
2301*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate(
2302*d9f75844SAndroid Build Coastguard Worker       cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp", address, kCandidatePriority,
2303*d9f75844SAndroid Build Coastguard Worker       "", "", LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation1);
2304*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(std::string("audio_content_name"), 0, candidate);
2305*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerializeCandidate(jcandidate);
2306*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kRawHostnameCandidate), message);
2307*d9f75844SAndroid Build Coastguard Worker }
2308*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeTcpCandidates)2309*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeTcpCandidates) {
2310*d9f75844SAndroid Build Coastguard Worker   Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "tcp",
2311*d9f75844SAndroid Build Coastguard Worker                       rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority,
2312*d9f75844SAndroid Build Coastguard Worker                       "", "", LOCAL_PORT_TYPE, kCandidateGeneration,
2313*d9f75844SAndroid Build Coastguard Worker                       kCandidateFoundation1);
2314*d9f75844SAndroid Build Coastguard Worker   candidate.set_tcptype(cricket::TCPTYPE_ACTIVE_STR);
2315*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jcandidate(
2316*d9f75844SAndroid Build Coastguard Worker       new JsepIceCandidate(std::string("audio_content_name"), 0, candidate));
2317*d9f75844SAndroid Build Coastguard Worker 
2318*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerializeCandidate(*jcandidate);
2319*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(kSdpTcpActiveCandidate), message);
2320*d9f75844SAndroid Build Coastguard Worker }
2321*d9f75844SAndroid Build Coastguard Worker 
2322*d9f75844SAndroid Build Coastguard Worker // Test serializing a TCP candidate that came in with a missing tcptype. This
2323*d9f75844SAndroid Build Coastguard Worker // shouldn't happen according to the spec, but our implementation has been
2324*d9f75844SAndroid Build Coastguard Worker // accepting this for quite some time, treating it as a passive candidate.
2325*d9f75844SAndroid Build Coastguard Worker //
2326*d9f75844SAndroid Build Coastguard Worker // So, we should be able to at least convert such candidates to and from SDP.
2327*d9f75844SAndroid Build Coastguard Worker // See: bugs.webrtc.org/11423
TEST_F(WebRtcSdpTest,ParseTcpCandidateWithoutTcptype)2328*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseTcpCandidateWithoutTcptype) {
2329*d9f75844SAndroid Build Coastguard Worker   std::string missing_tcptype =
2330*d9f75844SAndroid Build Coastguard Worker       "candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9999 typ host";
2331*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
2332*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(missing_tcptype, &jcandidate));
2333*d9f75844SAndroid Build Coastguard Worker 
2334*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(cricket::TCPTYPE_PASSIVE_STR),
2335*d9f75844SAndroid Build Coastguard Worker             jcandidate.candidate().tcptype());
2336*d9f75844SAndroid Build Coastguard Worker }
2337*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,ParseSslTcpCandidate)2338*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseSslTcpCandidate) {
2339*d9f75844SAndroid Build Coastguard Worker   std::string ssltcp =
2340*d9f75844SAndroid Build Coastguard Worker       "candidate:a0+B/1 1 ssltcp 2130706432 192.168.1.5 9999 typ host tcptype "
2341*d9f75844SAndroid Build Coastguard Worker       "passive";
2342*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
2343*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(ssltcp, &jcandidate));
2344*d9f75844SAndroid Build Coastguard Worker 
2345*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string("ssltcp"), jcandidate.candidate().protocol());
2346*d9f75844SAndroid Build Coastguard Worker }
2347*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionWithH264)2348*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithH264) {
2349*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec h264_codec("H264");
2350*d9f75844SAndroid Build Coastguard Worker   h264_codec.SetParam("profile-level-id", "42e01f");
2351*d9f75844SAndroid Build Coastguard Worker   h264_codec.SetParam("level-asymmetry-allowed", "1");
2352*d9f75844SAndroid Build Coastguard Worker   h264_codec.SetParam("packetization-mode", "1");
2353*d9f75844SAndroid Build Coastguard Worker   video_desc_->AddCodec(h264_codec);
2354*d9f75844SAndroid Build Coastguard Worker 
2355*d9f75844SAndroid Build Coastguard Worker   jdesc_.Initialize(desc_.Clone(), kSessionId, kSessionVersion);
2356*d9f75844SAndroid Build Coastguard Worker 
2357*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
2358*d9f75844SAndroid Build Coastguard Worker   size_t after_pt = message.find(" H264/90000");
2359*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(after_pt, std::string::npos);
2360*d9f75844SAndroid Build Coastguard Worker   size_t before_pt = message.rfind("a=rtpmap:", after_pt);
2361*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(before_pt, std::string::npos);
2362*d9f75844SAndroid Build Coastguard Worker   before_pt += strlen("a=rtpmap:");
2363*d9f75844SAndroid Build Coastguard Worker   std::string pt = message.substr(before_pt, after_pt - before_pt);
2364*d9f75844SAndroid Build Coastguard Worker   // TODO(hta): Check if payload type `pt` occurs in the m=video line.
2365*d9f75844SAndroid Build Coastguard Worker   std::string to_find = "a=fmtp:" + pt + " ";
2366*d9f75844SAndroid Build Coastguard Worker   size_t fmtp_pos = message.find(to_find);
2367*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(std::string::npos, fmtp_pos) << "Failed to find " << to_find;
2368*d9f75844SAndroid Build Coastguard Worker   size_t fmtp_endpos = message.find('\n', fmtp_pos);
2369*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(std::string::npos, fmtp_endpos);
2370*d9f75844SAndroid Build Coastguard Worker   std::string fmtp_value = message.substr(fmtp_pos, fmtp_endpos);
2371*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, fmtp_value.find("level-asymmetry-allowed=1"));
2372*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, fmtp_value.find("packetization-mode=1"));
2373*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, fmtp_value.find("profile-level-id=42e01f"));
2374*d9f75844SAndroid Build Coastguard Worker   // Check that there are no spaces after semicolons.
2375*d9f75844SAndroid Build Coastguard Worker   // https://bugs.webrtc.org/5793
2376*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string::npos, fmtp_value.find("; "));
2377*d9f75844SAndroid Build Coastguard Worker }
2378*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescription)2379*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescription) {
2380*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2381*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2382*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpFullString, &jdesc));
2383*d9f75844SAndroid Build Coastguard Worker   // Verify
2384*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc));
2385*d9f75844SAndroid Build Coastguard Worker }
2386*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutMline)2387*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutMline) {
2388*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2389*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithoutMline[] =
2390*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
2391*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
2392*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
2393*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
2394*d9f75844SAndroid Build Coastguard Worker       "a=msid-semantic: WMS local_stream_1 local_stream_2\r\n";
2395*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2396*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithoutMline, &jdesc));
2397*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, jdesc.description()->contents().size());
2398*d9f75844SAndroid Build Coastguard Worker }
2399*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutCarriageReturn)2400*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCarriageReturn) {
2401*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2402*d9f75844SAndroid Build Coastguard Worker   std::string sdp_without_carriage_return = kSdpFullString;
2403*d9f75844SAndroid Build Coastguard Worker   Replace("\r\n", "\n", &sdp_without_carriage_return);
2404*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2405*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_without_carriage_return, &jdesc));
2406*d9f75844SAndroid Build Coastguard Worker   // Verify
2407*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc));
2408*d9f75844SAndroid Build Coastguard Worker }
2409*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutCandidates)2410*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCandidates) {
2411*d9f75844SAndroid Build Coastguard Worker   // SessionDescription with desc but without candidates.
2412*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_no_candidates(kDummyType);
2413*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_no_candidates.Initialize(desc_.Clone(), kSessionId,
2414*d9f75844SAndroid Build Coastguard Worker                                              kSessionVersion));
2415*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription new_jdesc(kDummyType);
2416*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpString, &new_jdesc));
2417*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_no_candidates, new_jdesc));
2418*d9f75844SAndroid Build Coastguard Worker }
2419*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutRtpmap)2420*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutRtpmap) {
2421*d9f75844SAndroid Build Coastguard Worker   static const char kSdpNoRtpmapString[] =
2422*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
2423*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
2424*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
2425*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
2426*d9f75844SAndroid Build Coastguard Worker       "m=audio 49232 RTP/AVP 0 18 103\r\n"
2427*d9f75844SAndroid Build Coastguard Worker       // Codec that doesn't appear in the m= line will be ignored.
2428*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:104 ISAC/32000\r\n"
2429*d9f75844SAndroid Build Coastguard Worker       // The rtpmap line for static payload codec is optional.
2430*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:18 G729/8000\r\n"
2431*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:103 ISAC/16000\r\n";
2432*d9f75844SAndroid Build Coastguard Worker 
2433*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2434*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpNoRtpmapString, &jdesc));
2435*d9f75844SAndroid Build Coastguard Worker   cricket::AudioContentDescription* audio =
2436*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(jdesc.description());
2437*d9f75844SAndroid Build Coastguard Worker   AudioCodecs ref_codecs;
2438*d9f75844SAndroid Build Coastguard Worker   // The codecs in the AudioContentDescription should be in the same order as
2439*d9f75844SAndroid Build Coastguard Worker   // the payload types (<fmt>s) on the m= line.
2440*d9f75844SAndroid Build Coastguard Worker   ref_codecs.push_back(AudioCodec(0, "PCMU", 8000, 0, 1));
2441*d9f75844SAndroid Build Coastguard Worker   ref_codecs.push_back(AudioCodec(18, "G729", 8000, 0, 1));
2442*d9f75844SAndroid Build Coastguard Worker   ref_codecs.push_back(AudioCodec(103, "ISAC", 16000, 0, 1));
2443*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(ref_codecs, audio->codecs());
2444*d9f75844SAndroid Build Coastguard Worker }
2445*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutRtpmapButWithFmtp)2446*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutRtpmapButWithFmtp) {
2447*d9f75844SAndroid Build Coastguard Worker   static const char kSdpNoRtpmapString[] =
2448*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
2449*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
2450*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
2451*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
2452*d9f75844SAndroid Build Coastguard Worker       "m=audio 49232 RTP/AVP 18 103\r\n"
2453*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:18 annexb=yes\r\n"
2454*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:103 ISAC/16000\r\n";
2455*d9f75844SAndroid Build Coastguard Worker 
2456*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2457*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpNoRtpmapString, &jdesc));
2458*d9f75844SAndroid Build Coastguard Worker   cricket::AudioContentDescription* audio =
2459*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(jdesc.description());
2460*d9f75844SAndroid Build Coastguard Worker 
2461*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodec g729 = audio->codecs()[0];
2462*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("G729", g729.name);
2463*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(8000, g729.clockrate);
2464*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(18, g729.id);
2465*d9f75844SAndroid Build Coastguard Worker   cricket::CodecParameterMap::iterator found = g729.params.find("annexb");
2466*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != g729.params.end());
2467*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "yes");
2468*d9f75844SAndroid Build Coastguard Worker 
2469*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodec isac = audio->codecs()[1];
2470*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("ISAC", isac.name);
2471*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(103, isac.id);
2472*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(16000, isac.clockrate);
2473*d9f75844SAndroid Build Coastguard Worker }
2474*d9f75844SAndroid Build Coastguard Worker 
2475*d9f75844SAndroid Build Coastguard Worker // Ensure that we can deserialize SDP with a=fingerprint properly.
TEST_F(WebRtcSdpTest,DeserializeJsepSessionDescriptionWithFingerprint)2476*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeJsepSessionDescriptionWithFingerprint) {
2477*d9f75844SAndroid Build Coastguard Worker   // Add a DTLS a=fingerprint attribute to our session description.
2478*d9f75844SAndroid Build Coastguard Worker   AddFingerprint();
2479*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription new_jdesc(kDummyType);
2480*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(new_jdesc.Initialize(desc_.Clone(), jdesc_.session_id(),
2481*d9f75844SAndroid Build Coastguard Worker                                    jdesc_.session_version()));
2482*d9f75844SAndroid Build Coastguard Worker 
2483*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_fingerprint(kDummyType);
2484*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fingerprint = kSdpString;
2485*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_fingerprint);
2486*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_fingerprint);
2487*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_fingerprint, &jdesc_with_fingerprint));
2488*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_with_fingerprint, new_jdesc));
2489*d9f75844SAndroid Build Coastguard Worker }
2490*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithBundle)2491*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithBundle) {
2492*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_bundle(kDummyType);
2493*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bundle = kSdpFullString;
2494*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime,
2495*d9f75844SAndroid Build Coastguard Worker               "a=group:BUNDLE audio_content_name video_content_name\r\n",
2496*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bundle);
2497*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_bundle, &jdesc_with_bundle));
2498*d9f75844SAndroid Build Coastguard Worker   ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
2499*d9f75844SAndroid Build Coastguard Worker   group.AddContentName(kAudioContentName);
2500*d9f75844SAndroid Build Coastguard Worker   group.AddContentName(kVideoContentName);
2501*d9f75844SAndroid Build Coastguard Worker   desc_.AddGroup(group);
2502*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2503*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2504*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_bundle));
2505*d9f75844SAndroid Build Coastguard Worker }
2506*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithBandwidth)2507*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithBandwidth) {
2508*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_bandwidth(kDummyType);
2509*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpFullString;
2510*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:video_content_name\r\na=sendrecv\r\n", "b=AS:100\r\n",
2511*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2512*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:audio_content_name\r\na=sendrecv\r\n", "b=AS:50\r\n",
2513*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2514*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_bandwidth, &jdesc_with_bandwidth));
2515*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
2516*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth(100 * 1000);
2517*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
2518*d9f75844SAndroid Build Coastguard Worker   acd->set_bandwidth(50 * 1000);
2519*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2520*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2521*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_bandwidth));
2522*d9f75844SAndroid Build Coastguard Worker }
2523*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithTiasBandwidth)2524*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithTiasBandwidth) {
2525*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_bandwidth(kDummyType);
2526*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpFullString;
2527*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:video_content_name\r\na=sendrecv\r\n", "b=TIAS:100000\r\n",
2528*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2529*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:audio_content_name\r\na=sendrecv\r\n", "b=TIAS:50000\r\n",
2530*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
2531*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_bandwidth, &jdesc_with_bandwidth));
2532*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
2533*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth(100 * 1000);
2534*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
2535*d9f75844SAndroid Build Coastguard Worker   acd->set_bandwidth(50 * 1000);
2536*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2537*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2538*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_bandwidth));
2539*d9f75844SAndroid Build Coastguard Worker }
2540*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithUnknownBandwidthModifier)2541*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest,
2542*d9f75844SAndroid Build Coastguard Worker        DeserializeSessionDescriptionWithUnknownBandwidthModifier) {
2543*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_bandwidth(kDummyType);
2544*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpFullString;
2545*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:video_content_name\r\na=sendrecv\r\n",
2546*d9f75844SAndroid Build Coastguard Worker               "b=unknown:100000\r\n", &sdp_with_bandwidth);
2547*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:audio_content_name\r\na=sendrecv\r\n",
2548*d9f75844SAndroid Build Coastguard Worker               "b=unknown:50000\r\n", &sdp_with_bandwidth);
2549*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_bandwidth, &jdesc_with_bandwidth));
2550*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
2551*d9f75844SAndroid Build Coastguard Worker   vcd->set_bandwidth(-1);
2552*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
2553*d9f75844SAndroid Build Coastguard Worker   acd->set_bandwidth(-1);
2554*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2555*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2556*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_bandwidth));
2557*d9f75844SAndroid Build Coastguard Worker }
2558*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithIceOptions)2559*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithIceOptions) {
2560*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_ice_options(kDummyType);
2561*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_ice_options = kSdpFullString;
2562*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime, "a=ice-options:iceoption3\r\n",
2563*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ice_options);
2564*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, "a=ice-options:iceoption1\r\n",
2565*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ice_options);
2566*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, "a=ice-options:iceoption2\r\n",
2567*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ice_options);
2568*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_ice_options, &jdesc_with_ice_options));
2569*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> transport_options;
2570*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption3);
2571*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption1);
2572*d9f75844SAndroid Build Coastguard Worker   AddIceOptions(kAudioContentName, transport_options);
2573*d9f75844SAndroid Build Coastguard Worker   transport_options.clear();
2574*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption3);
2575*d9f75844SAndroid Build Coastguard Worker   transport_options.push_back(kIceOption2);
2576*d9f75844SAndroid Build Coastguard Worker   AddIceOptions(kVideoContentName, transport_options);
2577*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
2578*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
2579*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_ice_options));
2580*d9f75844SAndroid Build Coastguard Worker }
2581*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithUfragPwd)2582*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithUfragPwd) {
2583*d9f75844SAndroid Build Coastguard Worker   // Remove the original ice-ufrag and ice-pwd
2584*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_ufrag_pwd(kDummyType);
2585*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_ufrag_pwd = kSdpFullString;
2586*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(RemoveCandidateUfragPwd(&sdp_with_ufrag_pwd));
2587*d9f75844SAndroid Build Coastguard Worker   // Add session level ufrag and pwd
2588*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime,
2589*d9f75844SAndroid Build Coastguard Worker               "a=ice-pwd:session+level+icepwd\r\n"
2590*d9f75844SAndroid Build Coastguard Worker               "a=ice-ufrag:session+level+iceufrag\r\n",
2591*d9f75844SAndroid Build Coastguard Worker               &sdp_with_ufrag_pwd);
2592*d9f75844SAndroid Build Coastguard Worker   // Add media level ufrag and pwd for audio
2593*d9f75844SAndroid Build Coastguard Worker   InjectAfter(
2594*d9f75844SAndroid Build Coastguard Worker       "a=mid:audio_content_name\r\n",
2595*d9f75844SAndroid Build Coastguard Worker       "a=ice-pwd:media+level+icepwd\r\na=ice-ufrag:media+level+iceufrag\r\n",
2596*d9f75844SAndroid Build Coastguard Worker       &sdp_with_ufrag_pwd);
2597*d9f75844SAndroid Build Coastguard Worker   // Update the candidate ufrag and pwd to the expected ones.
2598*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(UpdateCandidateUfragPwd(&jdesc_, 0, "media+level+iceufrag",
2599*d9f75844SAndroid Build Coastguard Worker                                       "media+level+icepwd"));
2600*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(UpdateCandidateUfragPwd(&jdesc_, 1, "session+level+iceufrag",
2601*d9f75844SAndroid Build Coastguard Worker                                       "session+level+icepwd"));
2602*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_ufrag_pwd, &jdesc_with_ufrag_pwd));
2603*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_ufrag_pwd));
2604*d9f75844SAndroid Build Coastguard Worker }
2605*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithRecvOnlyContent)2606*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithRecvOnlyContent) {
2607*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeDirection(RtpTransceiverDirection::kRecvOnly));
2608*d9f75844SAndroid Build Coastguard Worker }
2609*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithSendOnlyContent)2610*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithSendOnlyContent) {
2611*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeDirection(RtpTransceiverDirection::kSendOnly));
2612*d9f75844SAndroid Build Coastguard Worker }
2613*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithInactiveContent)2614*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithInactiveContent) {
2615*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeDirection(RtpTransceiverDirection::kInactive));
2616*d9f75844SAndroid Build Coastguard Worker }
2617*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithRejectedAudio)2618*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithRejectedAudio) {
2619*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeRejected(true, false));
2620*d9f75844SAndroid Build Coastguard Worker }
2621*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithRejectedVideo)2622*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithRejectedVideo) {
2623*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeRejected(false, true));
2624*d9f75844SAndroid Build Coastguard Worker }
2625*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithRejectedAudioVideo)2626*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithRejectedAudioVideo) {
2627*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(TestDeserializeRejected(true, true));
2628*d9f75844SAndroid Build Coastguard Worker }
2629*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithExtmapAllowMixed)2630*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithExtmapAllowMixed) {
2631*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_extmap_allow_mixed(true);
2632*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_extmap_allow_mixed = kSdpFullString;
2633*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2634*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_deserialized(kDummyType);
2635*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(sdp_with_extmap_allow_mixed, &jdesc_deserialized));
2636*d9f75844SAndroid Build Coastguard Worker   // Verify
2637*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_deserialized));
2638*d9f75844SAndroid Build Coastguard Worker }
2639*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutExtmapAllowMixed)2640*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutExtmapAllowMixed) {
2641*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_extmap_allow_mixed(false);
2642*d9f75844SAndroid Build Coastguard Worker   std::string sdp_without_extmap_allow_mixed = kSdpFullString;
2643*d9f75844SAndroid Build Coastguard Worker   Replace(kExtmapAllowMixed, "", &sdp_without_extmap_allow_mixed);
2644*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2645*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_deserialized(kDummyType);
2646*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
2647*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(sdp_without_extmap_allow_mixed, &jdesc_deserialized));
2648*d9f75844SAndroid Build Coastguard Worker   // Verify
2649*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_deserialized));
2650*d9f75844SAndroid Build Coastguard Worker }
2651*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMediaContentDescriptionWithExtmapAllowMixed)2652*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMediaContentDescriptionWithExtmapAllowMixed) {
2653*d9f75844SAndroid Build Coastguard Worker   cricket::MediaContentDescription* video_desc =
2654*d9f75844SAndroid Build Coastguard Worker       jdesc_.description()->GetContentDescriptionByName(kVideoContentName);
2655*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(video_desc);
2656*d9f75844SAndroid Build Coastguard Worker   cricket::MediaContentDescription* audio_desc =
2657*d9f75844SAndroid Build Coastguard Worker       jdesc_.description()->GetContentDescriptionByName(kAudioContentName);
2658*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(audio_desc);
2659*d9f75844SAndroid Build Coastguard Worker   video_desc->set_extmap_allow_mixed_enum(
2660*d9f75844SAndroid Build Coastguard Worker       cricket::MediaContentDescription::kMedia);
2661*d9f75844SAndroid Build Coastguard Worker   audio_desc->set_extmap_allow_mixed_enum(
2662*d9f75844SAndroid Build Coastguard Worker       cricket::MediaContentDescription::kMedia);
2663*d9f75844SAndroid Build Coastguard Worker 
2664*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_extmap_allow_mixed = kSdpFullString;
2665*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:audio_content_name\r\n", kExtmapAllowMixed,
2666*d9f75844SAndroid Build Coastguard Worker               &sdp_with_extmap_allow_mixed);
2667*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:video_content_name\r\n", kExtmapAllowMixed,
2668*d9f75844SAndroid Build Coastguard Worker               &sdp_with_extmap_allow_mixed);
2669*d9f75844SAndroid Build Coastguard Worker 
2670*d9f75844SAndroid Build Coastguard Worker   // Deserialize
2671*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_deserialized(kDummyType);
2672*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_extmap_allow_mixed, &jdesc_deserialized));
2673*d9f75844SAndroid Build Coastguard Worker   // Verify
2674*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_deserialized));
2675*d9f75844SAndroid Build Coastguard Worker }
2676*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeCandidate)2677*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeCandidate) {
2678*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
2679*d9f75844SAndroid Build Coastguard Worker 
2680*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpOneCandidate;
2681*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2682*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
2683*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
2684*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(jcandidate_->candidate()));
2685*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, jcandidate.candidate().network_cost());
2686*d9f75844SAndroid Build Coastguard Worker 
2687*d9f75844SAndroid Build Coastguard Worker   // Candidate line without generation extension.
2688*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpOneCandidate;
2689*d9f75844SAndroid Build Coastguard Worker   Replace(" generation 2", "", &sdp);
2690*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2691*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
2692*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
2693*d9f75844SAndroid Build Coastguard Worker   Candidate expected = jcandidate_->candidate();
2694*d9f75844SAndroid Build Coastguard Worker   expected.set_generation(0);
2695*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(expected));
2696*d9f75844SAndroid Build Coastguard Worker 
2697*d9f75844SAndroid Build Coastguard Worker   // Candidate with network id and/or cost.
2698*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpOneCandidate;
2699*d9f75844SAndroid Build Coastguard Worker   Replace(" generation 2", " generation 2 network-id 2", &sdp);
2700*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2701*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
2702*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
2703*d9f75844SAndroid Build Coastguard Worker   expected = jcandidate_->candidate();
2704*d9f75844SAndroid Build Coastguard Worker   expected.set_network_id(2);
2705*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(expected));
2706*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, jcandidate.candidate().network_cost());
2707*d9f75844SAndroid Build Coastguard Worker   // Add network cost
2708*d9f75844SAndroid Build Coastguard Worker   Replace(" network-id 2", " network-id 2 network-cost 9", &sdp);
2709*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2710*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(expected));
2711*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(9, jcandidate.candidate().network_cost());
2712*d9f75844SAndroid Build Coastguard Worker 
2713*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpTcpActiveCandidate;
2714*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2715*d9f75844SAndroid Build Coastguard Worker   // Make a cricket::Candidate equivalent to kSdpTcpCandidate string.
2716*d9f75844SAndroid Build Coastguard Worker   Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "tcp",
2717*d9f75844SAndroid Build Coastguard Worker                       rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority,
2718*d9f75844SAndroid Build Coastguard Worker                       "", "", LOCAL_PORT_TYPE, kCandidateGeneration,
2719*d9f75844SAndroid Build Coastguard Worker                       kCandidateFoundation1);
2720*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jcandidate_template(
2721*d9f75844SAndroid Build Coastguard Worker       new JsepIceCandidate(std::string("audio_content_name"), 0, candidate));
2722*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
2723*d9f75844SAndroid Build Coastguard Worker       jcandidate.candidate().IsEquivalent(jcandidate_template->candidate()));
2724*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpTcpPassiveCandidate;
2725*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2726*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpTcpSOCandidate;
2727*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(sdp, &jcandidate));
2728*d9f75844SAndroid Build Coastguard Worker }
2729*d9f75844SAndroid Build Coastguard Worker 
2730*d9f75844SAndroid Build Coastguard Worker // This test verifies the deserialization of candidate-attribute
2731*d9f75844SAndroid Build Coastguard Worker // as per RFC 5245. Candidate-attribute will be of the format
2732*d9f75844SAndroid Build Coastguard Worker // candidate:<blah>. This format will be used when candidates
2733*d9f75844SAndroid Build Coastguard Worker // are trickled.
TEST_F(WebRtcSdpTest,DeserializeRawCandidateAttribute)2734*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeRawCandidateAttribute) {
2735*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
2736*d9f75844SAndroid Build Coastguard Worker 
2737*d9f75844SAndroid Build Coastguard Worker   std::string candidate_attribute = kRawCandidate;
2738*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2739*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
2740*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
2741*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(jcandidate_->candidate()));
2742*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, jcandidate.candidate().generation());
2743*d9f75844SAndroid Build Coastguard Worker 
2744*d9f75844SAndroid Build Coastguard Worker   // Candidate line without generation extension.
2745*d9f75844SAndroid Build Coastguard Worker   candidate_attribute = kRawCandidate;
2746*d9f75844SAndroid Build Coastguard Worker   Replace(" generation 2", "", &candidate_attribute);
2747*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2748*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
2749*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
2750*d9f75844SAndroid Build Coastguard Worker   Candidate expected = jcandidate_->candidate();
2751*d9f75844SAndroid Build Coastguard Worker   expected.set_generation(0);
2752*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(expected));
2753*d9f75844SAndroid Build Coastguard Worker 
2754*d9f75844SAndroid Build Coastguard Worker   // Candidate line without candidate:
2755*d9f75844SAndroid Build Coastguard Worker   candidate_attribute = kRawCandidate;
2756*d9f75844SAndroid Build Coastguard Worker   Replace("candidate:", "", &candidate_attribute);
2757*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2758*d9f75844SAndroid Build Coastguard Worker 
2759*d9f75844SAndroid Build Coastguard Worker   // Candidate line with IPV6 address.
2760*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(kRawIPV6Candidate, &jcandidate));
2761*d9f75844SAndroid Build Coastguard Worker 
2762*d9f75844SAndroid Build Coastguard Worker   // Candidate line with hostname address.
2763*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(kRawHostnameCandidate, &jcandidate));
2764*d9f75844SAndroid Build Coastguard Worker }
2765*d9f75844SAndroid Build Coastguard Worker 
2766*d9f75844SAndroid Build Coastguard Worker // This test verifies that the deserialization of an invalid candidate string
2767*d9f75844SAndroid Build Coastguard Worker // fails.
TEST_F(WebRtcSdpTest,DeserializeInvalidCandidiate)2768*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeInvalidCandidiate) {
2769*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
2770*d9f75844SAndroid Build Coastguard Worker 
2771*d9f75844SAndroid Build Coastguard Worker   std::string candidate_attribute = kRawCandidate;
2772*d9f75844SAndroid Build Coastguard Worker   candidate_attribute.replace(0, 1, "x");
2773*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2774*d9f75844SAndroid Build Coastguard Worker 
2775*d9f75844SAndroid Build Coastguard Worker   candidate_attribute = kSdpOneCandidate;
2776*d9f75844SAndroid Build Coastguard Worker   candidate_attribute.replace(0, 1, "x");
2777*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2778*d9f75844SAndroid Build Coastguard Worker 
2779*d9f75844SAndroid Build Coastguard Worker   candidate_attribute = kRawCandidate;
2780*d9f75844SAndroid Build Coastguard Worker   candidate_attribute.append("\r\n");
2781*d9f75844SAndroid Build Coastguard Worker   candidate_attribute.append(kRawCandidate);
2782*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(candidate_attribute, &jcandidate));
2783*d9f75844SAndroid Build Coastguard Worker 
2784*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(kSdpTcpInvalidCandidate, &jcandidate));
2785*d9f75844SAndroid Build Coastguard Worker }
2786*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannels)2787*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannels) {
2788*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2789*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2790*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2791*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2792*d9f75844SAndroid Build Coastguard Worker 
2793*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2794*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelString);
2795*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2796*d9f75844SAndroid Build Coastguard Worker 
2797*d9f75844SAndroid Build Coastguard Worker   // Verify with UDP/DTLS/SCTP (already in kSdpSctpDataChannelString).
2798*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2799*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2800*d9f75844SAndroid Build Coastguard Worker 
2801*d9f75844SAndroid Build Coastguard Worker   // Verify with DTLS/SCTP.
2802*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.replace(sdp_with_data.find(kUdpDtlsSctp), strlen(kUdpDtlsSctp),
2803*d9f75844SAndroid Build Coastguard Worker                         kDtlsSctp);
2804*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2805*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2806*d9f75844SAndroid Build Coastguard Worker 
2807*d9f75844SAndroid Build Coastguard Worker   // Verify with TCP/DTLS/SCTP.
2808*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.replace(sdp_with_data.find(kDtlsSctp), strlen(kDtlsSctp),
2809*d9f75844SAndroid Build Coastguard Worker                         kTcpDtlsSctp);
2810*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2811*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2812*d9f75844SAndroid Build Coastguard Worker }
2813*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelsWithSctpPort)2814*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithSctpPort) {
2815*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2816*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2817*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2818*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2819*d9f75844SAndroid Build Coastguard Worker 
2820*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2821*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelStringWithSctpPort);
2822*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2823*d9f75844SAndroid Build Coastguard Worker 
2824*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2825*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2826*d9f75844SAndroid Build Coastguard Worker }
2827*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelsWithSctpColonPort)2828*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithSctpColonPort) {
2829*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2830*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2831*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2832*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2833*d9f75844SAndroid Build Coastguard Worker 
2834*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2835*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelStringWithSctpColonPort);
2836*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2837*d9f75844SAndroid Build Coastguard Worker 
2838*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2839*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2840*d9f75844SAndroid Build Coastguard Worker }
2841*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelsButWrongMediaType)2842*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsButWrongMediaType) {
2843*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2844*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2845*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2846*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2847*d9f75844SAndroid Build Coastguard Worker 
2848*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpSessionString;
2849*d9f75844SAndroid Build Coastguard Worker   sdp += kSdpSctpDataChannelString;
2850*d9f75844SAndroid Build Coastguard Worker 
2851*d9f75844SAndroid Build Coastguard Worker   const char needle[] = "m=application ";
2852*d9f75844SAndroid Build Coastguard Worker   sdp.replace(sdp.find(needle), strlen(needle), "m=application:bogus ");
2853*d9f75844SAndroid Build Coastguard Worker 
2854*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2855*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output));
2856*d9f75844SAndroid Build Coastguard Worker 
2857*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, jdesc_output.description()->contents().size());
2858*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jdesc_output.description()->contents()[0].rejected);
2859*d9f75844SAndroid Build Coastguard Worker }
2860*d9f75844SAndroid Build Coastguard Worker 
2861*d9f75844SAndroid Build Coastguard Worker // Helper function to set the max-message-size parameter in the
2862*d9f75844SAndroid Build Coastguard Worker // SCTP data codec.
MutateJsepSctpMaxMessageSize(const SessionDescription & desc,int new_value,JsepSessionDescription * jdesc)2863*d9f75844SAndroid Build Coastguard Worker void MutateJsepSctpMaxMessageSize(const SessionDescription& desc,
2864*d9f75844SAndroid Build Coastguard Worker                                   int new_value,
2865*d9f75844SAndroid Build Coastguard Worker                                   JsepSessionDescription* jdesc) {
2866*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
2867*d9f75844SAndroid Build Coastguard Worker   SctpDataContentDescription* dcdesc =
2868*d9f75844SAndroid Build Coastguard Worker       mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
2869*d9f75844SAndroid Build Coastguard Worker   dcdesc->set_max_message_size(new_value);
2870*d9f75844SAndroid Build Coastguard Worker   jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion);
2871*d9f75844SAndroid Build Coastguard Worker }
2872*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelsWithMaxMessageSize)2873*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithMaxMessageSize) {
2874*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2875*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2876*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2877*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2878*d9f75844SAndroid Build Coastguard Worker 
2879*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelStringWithSctpColonPort);
2880*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append("a=max-message-size:12345\r\n");
2881*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpMaxMessageSize(desc_, 12345, &jdesc);
2882*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2883*d9f75844SAndroid Build Coastguard Worker 
2884*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2885*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2886*d9f75844SAndroid Build Coastguard Worker }
2887*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSdpWithSctpDataChannelWithMaxMessageSize)2888*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSdpWithSctpDataChannelWithMaxMessageSize) {
2889*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2890*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2891*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2892*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpMaxMessageSize(desc_, 12345, &jdesc);
2893*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc);
2894*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos,
2895*d9f75844SAndroid Build Coastguard Worker             message.find("\r\na=max-message-size:12345\r\n"));
2896*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2897*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(message, &jdesc_output));
2898*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2899*d9f75844SAndroid Build Coastguard Worker }
2900*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSdpWithSctpDataChannelWithDefaultMaxMessageSize)2901*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest,
2902*d9f75844SAndroid Build Coastguard Worker        SerializeSdpWithSctpDataChannelWithDefaultMaxMessageSize) {
2903*d9f75844SAndroid Build Coastguard Worker   // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6
2904*d9f75844SAndroid Build Coastguard Worker   // The default max message size is 64K.
2905*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2906*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2907*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2908*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpMaxMessageSize(desc_, 65536, &jdesc);
2909*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc);
2910*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string::npos, message.find("\r\na=max-message-size:"));
2911*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2912*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(message, &jdesc_output));
2913*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2914*d9f75844SAndroid Build Coastguard Worker }
2915*d9f75844SAndroid Build Coastguard Worker 
2916*d9f75844SAndroid Build Coastguard Worker // Test to check the behaviour if sctp-port is specified
2917*d9f75844SAndroid Build Coastguard Worker // on the m= line and in a=sctp-port.
TEST_F(WebRtcSdpTest,DeserializeSdpWithMultiSctpPort)2918*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithMultiSctpPort) {
2919*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2920*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2921*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2922*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
2923*d9f75844SAndroid Build Coastguard Worker 
2924*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2925*d9f75844SAndroid Build Coastguard Worker   // Append m= attributes
2926*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelString);
2927*d9f75844SAndroid Build Coastguard Worker   // Append a=sctp-port attribute
2928*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append("a=sctp-port 5000\r\n");
2929*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2930*d9f75844SAndroid Build Coastguard Worker 
2931*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp_with_data, &jdesc_output));
2932*d9f75844SAndroid Build Coastguard Worker }
2933*d9f75844SAndroid Build Coastguard Worker 
2934*d9f75844SAndroid Build Coastguard Worker // Test behavior if a=rtpmap occurs in an SCTP section.
TEST_F(WebRtcSdpTest,DeserializeSdpWithRtpmapAttribute)2935*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithRtpmapAttribute) {
2936*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2937*d9f75844SAndroid Build Coastguard Worker   // Append m= attributes
2938*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelString);
2939*d9f75844SAndroid Build Coastguard Worker   // Append a=rtpmap attribute
2940*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append("a=rtpmap:111 opus/48000/2\r\n");
2941*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2942*d9f75844SAndroid Build Coastguard Worker   // Correct behavior is to ignore the extra attribute.
2943*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2944*d9f75844SAndroid Build Coastguard Worker }
2945*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithStrangeApplicationProtocolNames)2946*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithStrangeApplicationProtocolNames) {
2947*d9f75844SAndroid Build Coastguard Worker   static const char* bad_strings[] = {
2948*d9f75844SAndroid Build Coastguard Worker       "DTLS/SCTPRTP/", "obviously-bogus",   "UDP/TL/RTSP/SAVPF",
2949*d9f75844SAndroid Build Coastguard Worker       "UDP/TL/RTSP/S", "DTLS/SCTP/RTP/FOO", "obviously-bogus/RTP/"};
2950*d9f75844SAndroid Build Coastguard Worker   for (auto proto : bad_strings) {
2951*d9f75844SAndroid Build Coastguard Worker     std::string sdp_with_data = kSdpString;
2952*d9f75844SAndroid Build Coastguard Worker     sdp_with_data.append("m=application 9 ");
2953*d9f75844SAndroid Build Coastguard Worker     sdp_with_data.append(proto);
2954*d9f75844SAndroid Build Coastguard Worker     sdp_with_data.append(" 47\r\n");
2955*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jdesc_output(kDummyType);
2956*d9f75844SAndroid Build Coastguard Worker     EXPECT_FALSE(SdpDeserialize(sdp_with_data, &jdesc_output))
2957*d9f75844SAndroid Build Coastguard Worker         << "Parsing should have failed on " << proto;
2958*d9f75844SAndroid Build Coastguard Worker   }
2959*d9f75844SAndroid Build Coastguard Worker }
2960*d9f75844SAndroid Build Coastguard Worker 
2961*d9f75844SAndroid Build Coastguard Worker // For crbug/344475.
TEST_F(WebRtcSdpTest,DeserializeSdpWithCorruptedSctpDataChannels)2962*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithCorruptedSctpDataChannels) {
2963*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2964*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelString);
2965*d9f75844SAndroid Build Coastguard Worker   // Remove the "\n" at the end.
2966*d9f75844SAndroid Build Coastguard Worker   sdp_with_data = sdp_with_data.substr(0, sdp_with_data.size() - 1);
2967*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2968*d9f75844SAndroid Build Coastguard Worker 
2969*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp_with_data, &jdesc_output));
2970*d9f75844SAndroid Build Coastguard Worker   // No crash is a pass.
2971*d9f75844SAndroid Build Coastguard Worker }
2972*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelAndUnusualPort)2973*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelAndUnusualPort) {
2974*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
2975*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2976*d9f75844SAndroid Build Coastguard Worker 
2977*d9f75844SAndroid Build Coastguard Worker   // First setup the expected JsepSessionDescription.
2978*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2979*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
2980*d9f75844SAndroid Build Coastguard Worker 
2981*d9f75844SAndroid Build Coastguard Worker   // Then get the deserialized JsepSessionDescription.
2982*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
2983*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelString);
2984*d9f75844SAndroid Build Coastguard Worker   absl::StrReplaceAll(
2985*d9f75844SAndroid Build Coastguard Worker       {{rtc::ToString(kDefaultSctpPort), rtc::ToString(kUnusualSctpPort)}},
2986*d9f75844SAndroid Build Coastguard Worker       &sdp_with_data);
2987*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
2988*d9f75844SAndroid Build Coastguard Worker 
2989*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
2990*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
2991*d9f75844SAndroid Build Coastguard Worker }
2992*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelAndUnusualPortInAttribute)2993*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest,
2994*d9f75844SAndroid Build Coastguard Worker        DeserializeSdpWithSctpDataChannelAndUnusualPortInAttribute) {
2995*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = false;
2996*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
2997*d9f75844SAndroid Build Coastguard Worker 
2998*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
2999*d9f75844SAndroid Build Coastguard Worker   MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
3000*d9f75844SAndroid Build Coastguard Worker 
3001*d9f75844SAndroid Build Coastguard Worker   // We need to test the deserialized JsepSessionDescription from
3002*d9f75844SAndroid Build Coastguard Worker   // kSdpSctpDataChannelStringWithSctpPort for
3003*d9f75844SAndroid Build Coastguard Worker   // draft-ietf-mmusic-sctp-sdp-07
3004*d9f75844SAndroid Build Coastguard Worker   // a=sctp-port
3005*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
3006*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelStringWithSctpPort);
3007*d9f75844SAndroid Build Coastguard Worker   absl::StrReplaceAll(
3008*d9f75844SAndroid Build Coastguard Worker       {{rtc::ToString(kDefaultSctpPort), rtc::ToString(kUnusualSctpPort)}},
3009*d9f75844SAndroid Build Coastguard Worker       &sdp_with_data);
3010*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3011*d9f75844SAndroid Build Coastguard Worker 
3012*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
3013*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
3014*d9f75844SAndroid Build Coastguard Worker }
3015*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithSctpDataChannelsAndBandwidth)3016*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsAndBandwidth) {
3017*d9f75844SAndroid Build Coastguard Worker   bool use_sctpmap = true;
3018*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(use_sctpmap);
3019*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
3020*d9f75844SAndroid Build Coastguard Worker   SctpDataContentDescription* dcd = GetFirstSctpDataContentDescription(&desc_);
3021*d9f75844SAndroid Build Coastguard Worker   dcd->set_bandwidth(100 * 1000);
3022*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));
3023*d9f75844SAndroid Build Coastguard Worker 
3024*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_bandwidth = kSdpString;
3025*d9f75844SAndroid Build Coastguard Worker   sdp_with_bandwidth.append(kSdpSctpDataChannelString);
3026*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=mid:data_content_name\r\n", "b=AS:100\r\n",
3027*d9f75844SAndroid Build Coastguard Worker               &sdp_with_bandwidth);
3028*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_bandwidth(kDummyType);
3029*d9f75844SAndroid Build Coastguard Worker 
3030*d9f75844SAndroid Build Coastguard Worker   // SCTP has congestion control, so we shouldn't limit the bandwidth
3031*d9f75844SAndroid Build Coastguard Worker   // as we do for RTP.
3032*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_bandwidth, &jdesc_with_bandwidth));
3033*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_with_bandwidth));
3034*d9f75844SAndroid Build Coastguard Worker }
3035*d9f75844SAndroid Build Coastguard Worker 
3036*d9f75844SAndroid Build Coastguard Worker class WebRtcSdpExtmapTest : public WebRtcSdpTest,
3037*d9f75844SAndroid Build Coastguard Worker                             public ::testing::WithParamInterface<bool> {};
3038*d9f75844SAndroid Build Coastguard Worker 
TEST_P(WebRtcSdpExtmapTest,DeserializeSessionDescriptionWithSessionLevelExtmap)3039*d9f75844SAndroid Build Coastguard Worker TEST_P(WebRtcSdpExtmapTest,
3040*d9f75844SAndroid Build Coastguard Worker        DeserializeSessionDescriptionWithSessionLevelExtmap) {
3041*d9f75844SAndroid Build Coastguard Worker   bool encrypted = GetParam();
3042*d9f75844SAndroid Build Coastguard Worker   TestDeserializeExtmap(true, false, encrypted);
3043*d9f75844SAndroid Build Coastguard Worker }
3044*d9f75844SAndroid Build Coastguard Worker 
TEST_P(WebRtcSdpExtmapTest,DeserializeSessionDescriptionWithMediaLevelExtmap)3045*d9f75844SAndroid Build Coastguard Worker TEST_P(WebRtcSdpExtmapTest, DeserializeSessionDescriptionWithMediaLevelExtmap) {
3046*d9f75844SAndroid Build Coastguard Worker   bool encrypted = GetParam();
3047*d9f75844SAndroid Build Coastguard Worker   TestDeserializeExtmap(false, true, encrypted);
3048*d9f75844SAndroid Build Coastguard Worker }
3049*d9f75844SAndroid Build Coastguard Worker 
TEST_P(WebRtcSdpExtmapTest,DeserializeSessionDescriptionWithInvalidExtmap)3050*d9f75844SAndroid Build Coastguard Worker TEST_P(WebRtcSdpExtmapTest, DeserializeSessionDescriptionWithInvalidExtmap) {
3051*d9f75844SAndroid Build Coastguard Worker   bool encrypted = GetParam();
3052*d9f75844SAndroid Build Coastguard Worker   TestDeserializeExtmap(true, true, encrypted);
3053*d9f75844SAndroid Build Coastguard Worker }
3054*d9f75844SAndroid Build Coastguard Worker 
3055*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(Encrypted,
3056*d9f75844SAndroid Build Coastguard Worker                          WebRtcSdpExtmapTest,
3057*d9f75844SAndroid Build Coastguard Worker                          ::testing::Values(false, true));
3058*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutEndLineBreak)3059*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutEndLineBreak) {
3060*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
3061*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpFullString;
3062*d9f75844SAndroid Build Coastguard Worker   sdp = sdp.substr(0, sdp.size() - 2);  // Remove \r\n at the end.
3063*d9f75844SAndroid Build Coastguard Worker   // Deserialize
3064*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
3065*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(webrtc::SdpDeserialize(sdp, &jdesc, &error));
3066*d9f75844SAndroid Build Coastguard Worker   const std::string lastline = "a=ssrc:3 msid:local_stream_1 video_track_id_1";
3067*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(lastline, error.line);
3068*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("Invalid SDP line.", error.description);
3069*d9f75844SAndroid Build Coastguard Worker }
3070*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeCandidateWithDifferentTransport)3071*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeCandidateWithDifferentTransport) {
3072*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
3073*d9f75844SAndroid Build Coastguard Worker   std::string new_sdp = kSdpOneCandidate;
3074*d9f75844SAndroid Build Coastguard Worker   Replace("udp", "unsupported_transport", &new_sdp);
3075*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserializeCandidate(new_sdp, &jcandidate));
3076*d9f75844SAndroid Build Coastguard Worker   new_sdp = kSdpOneCandidate;
3077*d9f75844SAndroid Build Coastguard Worker   Replace("udp", "uDP", &new_sdp);
3078*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserializeCandidate(new_sdp, &jcandidate));
3079*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
3080*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
3081*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(jcandidate_->candidate()));
3082*d9f75844SAndroid Build Coastguard Worker }
3083*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeCandidateWithUfragPwd)3084*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeCandidateWithUfragPwd) {
3085*d9f75844SAndroid Build Coastguard Worker   JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
3086*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3087*d9f75844SAndroid Build Coastguard Worker       SdpDeserializeCandidate(kSdpOneCandidateWithUfragPwd, &jcandidate));
3088*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyMid, jcandidate.sdp_mid());
3089*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kDummyIndex, jcandidate.sdp_mline_index());
3090*d9f75844SAndroid Build Coastguard Worker   Candidate ref_candidate = jcandidate_->candidate();
3091*d9f75844SAndroid Build Coastguard Worker   ref_candidate.set_username("user_rtp");
3092*d9f75844SAndroid Build Coastguard Worker   ref_candidate.set_password("password_rtp");
3093*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jcandidate.candidate().IsEquivalent(ref_candidate));
3094*d9f75844SAndroid Build Coastguard Worker }
3095*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithConferenceFlag)3096*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithConferenceFlag) {
3097*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
3098*d9f75844SAndroid Build Coastguard Worker 
3099*d9f75844SAndroid Build Coastguard Worker   // Deserialize
3100*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpConferenceString, &jdesc));
3101*d9f75844SAndroid Build Coastguard Worker 
3102*d9f75844SAndroid Build Coastguard Worker   // Verify
3103*d9f75844SAndroid Build Coastguard Worker   cricket::AudioContentDescription* audio =
3104*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(jdesc.description());
3105*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio->conference_mode());
3106*d9f75844SAndroid Build Coastguard Worker 
3107*d9f75844SAndroid Build Coastguard Worker   cricket::VideoContentDescription* video =
3108*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(jdesc.description());
3109*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video->conference_mode());
3110*d9f75844SAndroid Build Coastguard Worker }
3111*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeSdpWithConferenceFlag)3112*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSdpWithConferenceFlag) {
3113*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
3114*d9f75844SAndroid Build Coastguard Worker 
3115*d9f75844SAndroid Build Coastguard Worker   // We tested deserialization already above, so just test that if we serialize
3116*d9f75844SAndroid Build Coastguard Worker   // and deserialize the flag doesn't disappear.
3117*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpConferenceString, &jdesc));
3118*d9f75844SAndroid Build Coastguard Worker   std::string reserialized = webrtc::SdpSerialize(jdesc);
3119*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(reserialized, &jdesc));
3120*d9f75844SAndroid Build Coastguard Worker 
3121*d9f75844SAndroid Build Coastguard Worker   // Verify.
3122*d9f75844SAndroid Build Coastguard Worker   cricket::AudioContentDescription* audio =
3123*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstAudioContentDescription(jdesc.description());
3124*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(audio->conference_mode());
3125*d9f75844SAndroid Build Coastguard Worker 
3126*d9f75844SAndroid Build Coastguard Worker   cricket::VideoContentDescription* video =
3127*d9f75844SAndroid Build Coastguard Worker       cricket::GetFirstVideoContentDescription(jdesc.description());
3128*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(video->conference_mode());
3129*d9f75844SAndroid Build Coastguard Worker }
3130*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAndDeserializeRemoteNetEstimate)3131*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAndDeserializeRemoteNetEstimate) {
3132*d9f75844SAndroid Build Coastguard Worker   {
3133*d9f75844SAndroid Build Coastguard Worker     // By default remote estimates are disabled.
3134*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription dst(kDummyType);
3135*d9f75844SAndroid Build Coastguard Worker     SdpDeserialize(webrtc::SdpSerialize(jdesc_), &dst);
3136*d9f75844SAndroid Build Coastguard Worker     EXPECT_FALSE(cricket::GetFirstVideoContentDescription(dst.description())
3137*d9f75844SAndroid Build Coastguard Worker                      ->remote_estimate());
3138*d9f75844SAndroid Build Coastguard Worker   }
3139*d9f75844SAndroid Build Coastguard Worker   {
3140*d9f75844SAndroid Build Coastguard Worker     // When remote estimate is enabled, the setting is propagated via SDP.
3141*d9f75844SAndroid Build Coastguard Worker     cricket::GetFirstVideoContentDescription(jdesc_.description())
3142*d9f75844SAndroid Build Coastguard Worker         ->set_remote_estimate(true);
3143*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription dst(kDummyType);
3144*d9f75844SAndroid Build Coastguard Worker     SdpDeserialize(webrtc::SdpSerialize(jdesc_), &dst);
3145*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(cricket::GetFirstVideoContentDescription(dst.description())
3146*d9f75844SAndroid Build Coastguard Worker                     ->remote_estimate());
3147*d9f75844SAndroid Build Coastguard Worker   }
3148*d9f75844SAndroid Build Coastguard Worker }
3149*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeBrokenSdp)3150*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeBrokenSdp) {
3151*d9f75844SAndroid Build Coastguard Worker   const char kSdpDestroyer[] = "!@#$%^&";
3152*d9f75844SAndroid Build Coastguard Worker   const char kSdpEmptyType[] = " =candidate";
3153*d9f75844SAndroid Build Coastguard Worker   const char kSdpEqualAsPlus[] = "a+candidate";
3154*d9f75844SAndroid Build Coastguard Worker   const char kSdpSpaceAfterEqual[] = "a= candidate";
3155*d9f75844SAndroid Build Coastguard Worker   const char kSdpUpperType[] = "A=candidate";
3156*d9f75844SAndroid Build Coastguard Worker   const char kSdpEmptyLine[] = "";
3157*d9f75844SAndroid Build Coastguard Worker   const char kSdpMissingValue[] = "a=";
3158*d9f75844SAndroid Build Coastguard Worker 
3159*d9f75844SAndroid Build Coastguard Worker   const char kSdpBrokenFingerprint[] =
3160*d9f75844SAndroid Build Coastguard Worker       "a=fingerprint:sha-1 "
3161*d9f75844SAndroid Build Coastguard Worker       "4AAD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB";
3162*d9f75844SAndroid Build Coastguard Worker   const char kSdpExtraField[] =
3163*d9f75844SAndroid Build Coastguard Worker       "a=fingerprint:sha-1 "
3164*d9f75844SAndroid Build Coastguard Worker       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB XXX";
3165*d9f75844SAndroid Build Coastguard Worker   const char kSdpMissingSpace[] =
3166*d9f75844SAndroid Build Coastguard Worker       "a=fingerprint:sha-1"
3167*d9f75844SAndroid Build Coastguard Worker       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB";
3168*d9f75844SAndroid Build Coastguard Worker   // MD5 is not allowed in fingerprints.
3169*d9f75844SAndroid Build Coastguard Worker   const char kSdpMd5[] =
3170*d9f75844SAndroid Build Coastguard Worker       "a=fingerprint:md5 "
3171*d9f75844SAndroid Build Coastguard Worker       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B";
3172*d9f75844SAndroid Build Coastguard Worker 
3173*d9f75844SAndroid Build Coastguard Worker   // Broken session description
3174*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("v=", kSdpDestroyer);
3175*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("o=", kSdpDestroyer);
3176*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("s=-", kSdpDestroyer);
3177*d9f75844SAndroid Build Coastguard Worker   // Broken time description
3178*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("t=", kSdpDestroyer);
3179*d9f75844SAndroid Build Coastguard Worker 
3180*d9f75844SAndroid Build Coastguard Worker   // Broken media description
3181*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("m=audio", "c=IN IP4 74.125.224.39");
3182*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("m=video", kSdpDestroyer);
3183*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("m=", "c=IN IP4 74.125.224.39");
3184*d9f75844SAndroid Build Coastguard Worker 
3185*d9f75844SAndroid Build Coastguard Worker   // Invalid lines
3186*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=candidate", kSdpEmptyType);
3187*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=candidate", kSdpEqualAsPlus);
3188*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=candidate", kSdpSpaceAfterEqual);
3189*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=candidate", kSdpUpperType);
3190*d9f75844SAndroid Build Coastguard Worker 
3191*d9f75844SAndroid Build Coastguard Worker   // Bogus fingerprint replacing a=sendrev. We selected this attribute
3192*d9f75844SAndroid Build Coastguard Worker   // because it's orthogonal to what we are replacing and hence
3193*d9f75844SAndroid Build Coastguard Worker   // safe.
3194*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=sendrecv", kSdpBrokenFingerprint);
3195*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=sendrecv", kSdpExtraField);
3196*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=sendrecv", kSdpMissingSpace);
3197*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=sendrecv", kSdpMd5);
3198*d9f75844SAndroid Build Coastguard Worker 
3199*d9f75844SAndroid Build Coastguard Worker   // Empty Line
3200*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=rtcp:2347 IN IP4 74.125.127.126", kSdpEmptyLine);
3201*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=rtcp:2347 IN IP4 74.125.127.126", kSdpMissingValue);
3202*d9f75844SAndroid Build Coastguard Worker }
3203*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithInvalidAttributeValue)3204*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithInvalidAttributeValue) {
3205*d9f75844SAndroid Build Coastguard Worker   // ssrc
3206*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=ssrc:1", "a=ssrc:badvalue");
3207*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=ssrc-group:FEC 2 3", "a=ssrc-group:FEC badvalue 3");
3208*d9f75844SAndroid Build Coastguard Worker   // crypto
3209*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=crypto:1 ", "a=crypto:badvalue ");
3210*d9f75844SAndroid Build Coastguard Worker   // rtpmap
3211*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("a=rtpmap:111 ", "a=rtpmap:badvalue ");
3212*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("opus/48000/2", "opus/badvalue/2");
3213*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("opus/48000/2", "opus/48000/badvalue");
3214*d9f75844SAndroid Build Coastguard Worker   // candidate
3215*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("1 udp 2130706432", "badvalue udp 2130706432");
3216*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("1 udp 2130706432", "1 udp badvalue");
3217*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("192.168.1.5 1234", "192.168.1.5 badvalue");
3218*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("rport 2346", "rport badvalue");
3219*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("rport 2346 generation 2",
3220*d9f75844SAndroid Build Coastguard Worker                      "rport 2346 generation badvalue");
3221*d9f75844SAndroid Build Coastguard Worker   // m line
3222*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure("m=audio 2345 RTP/SAVPF 111 103 104",
3223*d9f75844SAndroid Build Coastguard Worker                      "m=audio 2345 RTP/SAVPF 111 badvalue 104");
3224*d9f75844SAndroid Build Coastguard Worker 
3225*d9f75844SAndroid Build Coastguard Worker   // bandwidth
3226*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n",
3227*d9f75844SAndroid Build Coastguard Worker                                  "b=AS:badvalue\r\n", "b=AS:badvalue");
3228*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n", "b=AS\r\n",
3229*d9f75844SAndroid Build Coastguard Worker                                  "b=AS");
3230*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n", "b=AS:\r\n",
3231*d9f75844SAndroid Build Coastguard Worker                                  "b=AS:");
3232*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n",
3233*d9f75844SAndroid Build Coastguard Worker                                  "b=AS:12:34\r\n", "b=AS:12:34");
3234*d9f75844SAndroid Build Coastguard Worker 
3235*d9f75844SAndroid Build Coastguard Worker   // rtcp-fb
3236*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n",
3237*d9f75844SAndroid Build Coastguard Worker                                  "a=rtcp-fb:badvalue nack\r\n",
3238*d9f75844SAndroid Build Coastguard Worker                                  "a=rtcp-fb:badvalue nack");
3239*d9f75844SAndroid Build Coastguard Worker   // extmap
3240*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines("a=mid:video_content_name\r\n",
3241*d9f75844SAndroid Build Coastguard Worker                                  "a=extmap:badvalue http://example.com\r\n",
3242*d9f75844SAndroid Build Coastguard Worker                                  "a=extmap:badvalue http://example.com");
3243*d9f75844SAndroid Build Coastguard Worker }
3244*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithReorderedPltypes)3245*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithReorderedPltypes) {
3246*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3247*d9f75844SAndroid Build Coastguard Worker 
3248*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithReorderedPlTypesString[] =
3249*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3250*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3251*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3252*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3253*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 104 103\r\n"  // Pl type 104 preferred.
3254*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"    // Pltype 111 listed before 103 and 104
3255*d9f75844SAndroid Build Coastguard Worker                                          // in the map.
3256*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:103 ISAC/16000\r\n"  // Pltype 103 listed before 104 in the map.
3257*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:104 ISAC/32000\r\n";
3258*d9f75844SAndroid Build Coastguard Worker 
3259*d9f75844SAndroid Build Coastguard Worker   // Deserialize
3260*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithReorderedPlTypesString, &jdesc_output));
3261*d9f75844SAndroid Build Coastguard Worker 
3262*d9f75844SAndroid Build Coastguard Worker   const AudioContentDescription* acd =
3263*d9f75844SAndroid Build Coastguard Worker       GetFirstAudioContentDescription(jdesc_output.description());
3264*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(acd);
3265*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(acd->codecs().empty());
3266*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("ISAC", acd->codecs()[0].name);
3267*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(32000, acd->codecs()[0].clockrate);
3268*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(104, acd->codecs()[0].id);
3269*d9f75844SAndroid Build Coastguard Worker }
3270*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSerializeCodecParams)3271*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSerializeCodecParams) {
3272*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3273*d9f75844SAndroid Build Coastguard Worker   CodecParams params;
3274*d9f75844SAndroid Build Coastguard Worker   params.max_ptime = 40;
3275*d9f75844SAndroid Build Coastguard Worker   params.ptime = 30;
3276*d9f75844SAndroid Build Coastguard Worker   params.min_ptime = 10;
3277*d9f75844SAndroid Build Coastguard Worker   params.sprop_stereo = 1;
3278*d9f75844SAndroid Build Coastguard Worker   params.stereo = 1;
3279*d9f75844SAndroid Build Coastguard Worker   params.useinband = 1;
3280*d9f75844SAndroid Build Coastguard Worker   params.maxaveragebitrate = 128000;
3281*d9f75844SAndroid Build Coastguard Worker   TestDeserializeCodecParams(params, &jdesc_output);
3282*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_output);
3283*d9f75844SAndroid Build Coastguard Worker }
3284*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSerializeRtcpFb)3285*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSerializeRtcpFb) {
3286*d9f75844SAndroid Build Coastguard Worker   const bool kUseWildcard = false;
3287*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3288*d9f75844SAndroid Build Coastguard Worker   TestDeserializeRtcpFb(&jdesc_output, kUseWildcard);
3289*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_output);
3290*d9f75844SAndroid Build Coastguard Worker }
3291*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSerializeRtcpFbWildcard)3292*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSerializeRtcpFbWildcard) {
3293*d9f75844SAndroid Build Coastguard Worker   const bool kUseWildcard = true;
3294*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3295*d9f75844SAndroid Build Coastguard Worker   TestDeserializeRtcpFb(&jdesc_output, kUseWildcard);
3296*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_output);
3297*d9f75844SAndroid Build Coastguard Worker }
3298*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeVideoFmtp)3299*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeVideoFmtp) {
3300*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3301*d9f75844SAndroid Build Coastguard Worker 
3302*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithFmtpString[] =
3303*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3304*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3305*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3306*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3307*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120\r\n"
3308*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:120 VP8/90000\r\n"
3309*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:120 x-google-min-bitrate=10;x-google-max-quantization=40\r\n";
3310*d9f75844SAndroid Build Coastguard Worker 
3311*d9f75844SAndroid Build Coastguard Worker   // Deserialize
3312*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
3313*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3314*d9f75844SAndroid Build Coastguard Worker       webrtc::SdpDeserialize(kSdpWithFmtpString, &jdesc_output, &error));
3315*d9f75844SAndroid Build Coastguard Worker 
3316*d9f75844SAndroid Build Coastguard Worker   const VideoContentDescription* vcd =
3317*d9f75844SAndroid Build Coastguard Worker       GetFirstVideoContentDescription(jdesc_output.description());
3318*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(vcd);
3319*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(vcd->codecs().empty());
3320*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec vp8 = vcd->codecs()[0];
3321*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("VP8", vp8.name);
3322*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(120, vp8.id);
3323*d9f75844SAndroid Build Coastguard Worker   cricket::CodecParameterMap::iterator found =
3324*d9f75844SAndroid Build Coastguard Worker       vp8.params.find("x-google-min-bitrate");
3325*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != vp8.params.end());
3326*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "10");
3327*d9f75844SAndroid Build Coastguard Worker   found = vp8.params.find("x-google-max-quantization");
3328*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != vp8.params.end());
3329*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "40");
3330*d9f75844SAndroid Build Coastguard Worker }
3331*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeVideoFmtpWithSprops)3332*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeVideoFmtpWithSprops) {
3333*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3334*d9f75844SAndroid Build Coastguard Worker 
3335*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithFmtpString[] =
3336*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3337*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3338*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3339*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3340*d9f75844SAndroid Build Coastguard Worker       "m=video 49170 RTP/AVP 98\r\n"
3341*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:98 H264/90000\r\n"
3342*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:98 profile-level-id=42A01E; "
3343*d9f75844SAndroid Build Coastguard Worker       "sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==\r\n";
3344*d9f75844SAndroid Build Coastguard Worker 
3345*d9f75844SAndroid Build Coastguard Worker   // Deserialize.
3346*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
3347*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3348*d9f75844SAndroid Build Coastguard Worker       webrtc::SdpDeserialize(kSdpWithFmtpString, &jdesc_output, &error));
3349*d9f75844SAndroid Build Coastguard Worker 
3350*d9f75844SAndroid Build Coastguard Worker   const VideoContentDescription* vcd =
3351*d9f75844SAndroid Build Coastguard Worker       GetFirstVideoContentDescription(jdesc_output.description());
3352*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(vcd);
3353*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(vcd->codecs().empty());
3354*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec h264 = vcd->codecs()[0];
3355*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("H264", h264.name);
3356*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(98, h264.id);
3357*d9f75844SAndroid Build Coastguard Worker   cricket::CodecParameterMap::const_iterator found =
3358*d9f75844SAndroid Build Coastguard Worker       h264.params.find("profile-level-id");
3359*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != h264.params.end());
3360*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "42A01E");
3361*d9f75844SAndroid Build Coastguard Worker   found = h264.params.find("sprop-parameter-sets");
3362*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != h264.params.end());
3363*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "Z0IACpZTBYmI,aMljiA==");
3364*d9f75844SAndroid Build Coastguard Worker }
3365*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeVideoFmtpWithSpace)3366*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeVideoFmtpWithSpace) {
3367*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3368*d9f75844SAndroid Build Coastguard Worker 
3369*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithFmtpString[] =
3370*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3371*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3372*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3373*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3374*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120\r\n"
3375*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:120 VP8/90000\r\n"
3376*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:120   x-google-min-bitrate=10;  x-google-max-quantization=40\r\n";
3377*d9f75844SAndroid Build Coastguard Worker 
3378*d9f75844SAndroid Build Coastguard Worker   // Deserialize
3379*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
3380*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3381*d9f75844SAndroid Build Coastguard Worker       webrtc::SdpDeserialize(kSdpWithFmtpString, &jdesc_output, &error));
3382*d9f75844SAndroid Build Coastguard Worker 
3383*d9f75844SAndroid Build Coastguard Worker   const VideoContentDescription* vcd =
3384*d9f75844SAndroid Build Coastguard Worker       GetFirstVideoContentDescription(jdesc_output.description());
3385*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(vcd);
3386*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(vcd->codecs().empty());
3387*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec vp8 = vcd->codecs()[0];
3388*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("VP8", vp8.name);
3389*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(120, vp8.id);
3390*d9f75844SAndroid Build Coastguard Worker   cricket::CodecParameterMap::iterator found =
3391*d9f75844SAndroid Build Coastguard Worker       vp8.params.find("x-google-min-bitrate");
3392*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != vp8.params.end());
3393*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "10");
3394*d9f75844SAndroid Build Coastguard Worker   found = vp8.params.find("x-google-max-quantization");
3395*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(found != vp8.params.end());
3396*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(found->second, "40");
3397*d9f75844SAndroid Build Coastguard Worker }
3398*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializePacketizationAttributeWithIllegalValue)3399*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializePacketizationAttributeWithIllegalValue) {
3400*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3401*d9f75844SAndroid Build Coastguard Worker 
3402*d9f75844SAndroid Build Coastguard Worker   const char kSdpWithPacketizationString[] =
3403*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3404*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3405*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3406*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3407*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
3408*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
3409*d9f75844SAndroid Build Coastguard Worker       "a=packetization:111 unknownpacketizationattributeforaudio\r\n"
3410*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120 121 122\r\n"
3411*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:120 VP8/90000\r\n"
3412*d9f75844SAndroid Build Coastguard Worker       "a=packetization:120 raw\r\n"
3413*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:121 VP9/90000\r\n"
3414*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:122 H264/90000\r\n"
3415*d9f75844SAndroid Build Coastguard Worker       "a=packetization:122 unknownpacketizationattributevalue\r\n";
3416*d9f75844SAndroid Build Coastguard Worker 
3417*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
3418*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(kSdpWithPacketizationString, &jdesc_output,
3419*d9f75844SAndroid Build Coastguard Worker                                      &error));
3420*d9f75844SAndroid Build Coastguard Worker 
3421*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd =
3422*d9f75844SAndroid Build Coastguard Worker       GetFirstAudioContentDescription(jdesc_output.description());
3423*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(acd);
3424*d9f75844SAndroid Build Coastguard Worker   ASSERT_THAT(acd->codecs(), testing::SizeIs(1));
3425*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodec opus = acd->codecs()[0];
3426*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(opus.name, "opus");
3427*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(opus.id, 111);
3428*d9f75844SAndroid Build Coastguard Worker 
3429*d9f75844SAndroid Build Coastguard Worker   const VideoContentDescription* vcd =
3430*d9f75844SAndroid Build Coastguard Worker       GetFirstVideoContentDescription(jdesc_output.description());
3431*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(vcd);
3432*d9f75844SAndroid Build Coastguard Worker   ASSERT_THAT(vcd->codecs(), testing::SizeIs(3));
3433*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec vp8 = vcd->codecs()[0];
3434*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp8.name, "VP8");
3435*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp8.id, 120);
3436*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp8.packetization, "raw");
3437*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec vp9 = vcd->codecs()[1];
3438*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp9.name, "VP9");
3439*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp9.id, 121);
3440*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(vp9.packetization, absl::nullopt);
3441*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodec h264 = vcd->codecs()[2];
3442*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(h264.name, "H264");
3443*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(h264.id, 122);
3444*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(h264.packetization, absl::nullopt);
3445*d9f75844SAndroid Build Coastguard Worker }
3446*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAudioFmtpWithUnknownParameter)3447*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAudioFmtpWithUnknownParameter) {
3448*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
3449*d9f75844SAndroid Build Coastguard Worker 
3450*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodecs codecs = acd->codecs();
3451*d9f75844SAndroid Build Coastguard Worker   codecs[0].params["unknown-future-parameter"] = "SomeFutureValue";
3452*d9f75844SAndroid Build Coastguard Worker   acd->set_codecs(codecs);
3453*d9f75844SAndroid Build Coastguard Worker 
3454*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3455*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3456*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3457*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fmtp = kSdpFullString;
3458*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=rtpmap:111 opus/48000/2\r\n",
3459*d9f75844SAndroid Build Coastguard Worker               "a=fmtp:111 unknown-future-parameter=SomeFutureValue\r\n",
3460*d9f75844SAndroid Build Coastguard Worker               &sdp_with_fmtp);
3461*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fmtp, message);
3462*d9f75844SAndroid Build Coastguard Worker }
3463*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAudioFmtpWithKnownFmtpParameter)3464*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAudioFmtpWithKnownFmtpParameter) {
3465*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
3466*d9f75844SAndroid Build Coastguard Worker 
3467*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodecs codecs = acd->codecs();
3468*d9f75844SAndroid Build Coastguard Worker   codecs[0].params["stereo"] = "1";
3469*d9f75844SAndroid Build Coastguard Worker   acd->set_codecs(codecs);
3470*d9f75844SAndroid Build Coastguard Worker 
3471*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3472*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3473*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3474*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fmtp = kSdpFullString;
3475*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=rtpmap:111 opus/48000/2\r\n", "a=fmtp:111 stereo=1\r\n",
3476*d9f75844SAndroid Build Coastguard Worker               &sdp_with_fmtp);
3477*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fmtp, message);
3478*d9f75844SAndroid Build Coastguard Worker }
3479*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAudioFmtpWithPTimeAndMaxPTime)3480*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAudioFmtpWithPTimeAndMaxPTime) {
3481*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
3482*d9f75844SAndroid Build Coastguard Worker 
3483*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodecs codecs = acd->codecs();
3484*d9f75844SAndroid Build Coastguard Worker   codecs[0].params["ptime"] = "20";
3485*d9f75844SAndroid Build Coastguard Worker   codecs[0].params["maxptime"] = "120";
3486*d9f75844SAndroid Build Coastguard Worker   acd->set_codecs(codecs);
3487*d9f75844SAndroid Build Coastguard Worker 
3488*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3489*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3490*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3491*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fmtp = kSdpFullString;
3492*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=rtpmap:104 ISAC/32000\r\n",
3493*d9f75844SAndroid Build Coastguard Worker               "a=maxptime:120\r\n"  // No comma here. String merging!
3494*d9f75844SAndroid Build Coastguard Worker               "a=ptime:20\r\n",
3495*d9f75844SAndroid Build Coastguard Worker               &sdp_with_fmtp);
3496*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fmtp, message);
3497*d9f75844SAndroid Build Coastguard Worker }
3498*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAudioFmtpWithTelephoneEvent)3499*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAudioFmtpWithTelephoneEvent) {
3500*d9f75844SAndroid Build Coastguard Worker   AudioContentDescription* acd = GetFirstAudioContentDescription(&desc_);
3501*d9f75844SAndroid Build Coastguard Worker 
3502*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodecs codecs = acd->codecs();
3503*d9f75844SAndroid Build Coastguard Worker   cricket::AudioCodec dtmf(105, "telephone-event", 8000, 0, 1);
3504*d9f75844SAndroid Build Coastguard Worker   dtmf.params[""] = "0-15";
3505*d9f75844SAndroid Build Coastguard Worker   codecs.push_back(dtmf);
3506*d9f75844SAndroid Build Coastguard Worker   acd->set_codecs(codecs);
3507*d9f75844SAndroid Build Coastguard Worker 
3508*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3509*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3510*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3511*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fmtp = kSdpFullString;
3512*d9f75844SAndroid Build Coastguard Worker   InjectAfter("m=audio 2345 RTP/SAVPF 111 103 104", " 105", &sdp_with_fmtp);
3513*d9f75844SAndroid Build Coastguard Worker   InjectAfter(
3514*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:104 ISAC/32000\r\n",
3515*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:105 telephone-event/8000\r\n"  // No comma here. String merging!
3516*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:105 0-15\r\n",
3517*d9f75844SAndroid Build Coastguard Worker       &sdp_with_fmtp);
3518*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fmtp, message);
3519*d9f75844SAndroid Build Coastguard Worker }
3520*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeVideoFmtp)3521*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeVideoFmtp) {
3522*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
3523*d9f75844SAndroid Build Coastguard Worker 
3524*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodecs codecs = vcd->codecs();
3525*d9f75844SAndroid Build Coastguard Worker   codecs[0].params["x-google-min-bitrate"] = "10";
3526*d9f75844SAndroid Build Coastguard Worker   vcd->set_codecs(codecs);
3527*d9f75844SAndroid Build Coastguard Worker 
3528*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3529*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3530*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3531*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_fmtp = kSdpFullString;
3532*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=rtpmap:120 VP8/90000\r\n",
3533*d9f75844SAndroid Build Coastguard Worker               "a=fmtp:120 x-google-min-bitrate=10\r\n", &sdp_with_fmtp);
3534*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_fmtp, message);
3535*d9f75844SAndroid Build Coastguard Worker }
3536*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeVideoPacketizationAttribute)3537*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeVideoPacketizationAttribute) {
3538*d9f75844SAndroid Build Coastguard Worker   VideoContentDescription* vcd = GetFirstVideoContentDescription(&desc_);
3539*d9f75844SAndroid Build Coastguard Worker 
3540*d9f75844SAndroid Build Coastguard Worker   cricket::VideoCodecs codecs = vcd->codecs();
3541*d9f75844SAndroid Build Coastguard Worker   codecs[0].packetization = "raw";
3542*d9f75844SAndroid Build Coastguard Worker   vcd->set_codecs(codecs);
3543*d9f75844SAndroid Build Coastguard Worker 
3544*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3545*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3546*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3547*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_packetization = kSdpFullString;
3548*d9f75844SAndroid Build Coastguard Worker   InjectAfter("a=rtpmap:120 VP8/90000\r\n", "a=packetization:120 raw\r\n",
3549*d9f75844SAndroid Build Coastguard Worker               &sdp_with_packetization);
3550*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_packetization, message);
3551*d9f75844SAndroid Build Coastguard Worker }
3552*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeAndSerializeSdpWithIceLite)3553*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeAndSerializeSdpWithIceLite) {
3554*d9f75844SAndroid Build Coastguard Worker   // Deserialize the baseline description, making sure it's ICE full.
3555*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_icelite(kDummyType);
3556*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_icelite = kSdpFullString;
3557*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_icelite, &jdesc_with_icelite));
3558*d9f75844SAndroid Build Coastguard Worker   cricket::SessionDescription* desc = jdesc_with_icelite.description();
3559*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* tinfo1 =
3560*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("audio_content_name");
3561*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEMODE_FULL, tinfo1->description.ice_mode);
3562*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* tinfo2 =
3563*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("video_content_name");
3564*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEMODE_FULL, tinfo2->description.ice_mode);
3565*d9f75844SAndroid Build Coastguard Worker 
3566*d9f75844SAndroid Build Coastguard Worker   // Add "a=ice-lite" and deserialize, making sure it's ICE lite.
3567*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime, "a=ice-lite\r\n", &sdp_with_icelite);
3568*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_icelite, &jdesc_with_icelite));
3569*d9f75844SAndroid Build Coastguard Worker   desc = jdesc_with_icelite.description();
3570*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* atinfo =
3571*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("audio_content_name");
3572*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEMODE_LITE, atinfo->description.ice_mode);
3573*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* vtinfo =
3574*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("video_content_name");
3575*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEMODE_LITE, vtinfo->description.ice_mode);
3576*d9f75844SAndroid Build Coastguard Worker 
3577*d9f75844SAndroid Build Coastguard Worker   // Now that we know deserialization works, we can use TestSerialize to test
3578*d9f75844SAndroid Build Coastguard Worker   // serialization.
3579*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_with_icelite);
3580*d9f75844SAndroid Build Coastguard Worker }
3581*d9f75844SAndroid Build Coastguard Worker 
3582*d9f75844SAndroid Build Coastguard Worker // Verifies that the candidates in the input SDP are parsed and serialized
3583*d9f75844SAndroid Build Coastguard Worker // correctly in the output SDP.
TEST_F(WebRtcSdpTest,RoundTripSdpWithSctpDataChannelsWithCandidates)3584*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, RoundTripSdpWithSctpDataChannelsWithCandidates) {
3585*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_data = kSdpString;
3586*d9f75844SAndroid Build Coastguard Worker   sdp_with_data.append(kSdpSctpDataChannelWithCandidatesString);
3587*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3588*d9f75844SAndroid Build Coastguard Worker 
3589*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
3590*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_data, webrtc::SdpSerialize(jdesc_output));
3591*d9f75844SAndroid Build Coastguard Worker }
3592*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeDtlsSetupAttribute)3593*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeDtlsSetupAttribute) {
3594*d9f75844SAndroid Build Coastguard Worker   AddFingerprint();
3595*d9f75844SAndroid Build Coastguard Worker   TransportInfo audio_transport_info =
3596*d9f75844SAndroid Build Coastguard Worker       *(desc_.GetTransportInfoByName(kAudioContentName));
3597*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_NONE,
3598*d9f75844SAndroid Build Coastguard Worker             audio_transport_info.description.connection_role);
3599*d9f75844SAndroid Build Coastguard Worker   audio_transport_info.description.connection_role =
3600*d9f75844SAndroid Build Coastguard Worker       cricket::CONNECTIONROLE_ACTIVE;
3601*d9f75844SAndroid Build Coastguard Worker 
3602*d9f75844SAndroid Build Coastguard Worker   TransportInfo video_transport_info =
3603*d9f75844SAndroid Build Coastguard Worker       *(desc_.GetTransportInfoByName(kVideoContentName));
3604*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_NONE,
3605*d9f75844SAndroid Build Coastguard Worker             video_transport_info.description.connection_role);
3606*d9f75844SAndroid Build Coastguard Worker   video_transport_info.description.connection_role =
3607*d9f75844SAndroid Build Coastguard Worker       cricket::CONNECTIONROLE_ACTIVE;
3608*d9f75844SAndroid Build Coastguard Worker 
3609*d9f75844SAndroid Build Coastguard Worker   desc_.RemoveTransportInfoByName(kAudioContentName);
3610*d9f75844SAndroid Build Coastguard Worker   desc_.RemoveTransportInfoByName(kVideoContentName);
3611*d9f75844SAndroid Build Coastguard Worker 
3612*d9f75844SAndroid Build Coastguard Worker   desc_.AddTransportInfo(audio_transport_info);
3613*d9f75844SAndroid Build Coastguard Worker   desc_.AddTransportInfo(video_transport_info);
3614*d9f75844SAndroid Build Coastguard Worker 
3615*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
3616*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
3617*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jdesc_);
3618*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_dtlssetup = kSdpFullString;
3619*d9f75844SAndroid Build Coastguard Worker 
3620*d9f75844SAndroid Build Coastguard Worker   // Fingerprint attribute is necessary to add DTLS setup attribute.
3621*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVoice, kFingerprint, &sdp_with_dtlssetup);
3622*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kAttributeIcePwdVideo, kFingerprint, &sdp_with_dtlssetup);
3623*d9f75844SAndroid Build Coastguard Worker   // Now adding `setup` attribute.
3624*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kFingerprint, "a=setup:active\r\n", &sdp_with_dtlssetup);
3625*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(sdp_with_dtlssetup, message);
3626*d9f75844SAndroid Build Coastguard Worker }
3627*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeDtlsSetupAttributeActpass)3628*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeDtlsSetupAttributeActpass) {
3629*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_dtlssetup(kDummyType);
3630*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_dtlssetup = kSdpFullString;
3631*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime, "a=setup:actpass\r\n", &sdp_with_dtlssetup);
3632*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_dtlssetup, &jdesc_with_dtlssetup));
3633*d9f75844SAndroid Build Coastguard Worker   cricket::SessionDescription* desc = jdesc_with_dtlssetup.description();
3634*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* atinfo =
3635*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("audio_content_name");
3636*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_ACTPASS,
3637*d9f75844SAndroid Build Coastguard Worker             atinfo->description.connection_role);
3638*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* vtinfo =
3639*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("video_content_name");
3640*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_ACTPASS,
3641*d9f75844SAndroid Build Coastguard Worker             vtinfo->description.connection_role);
3642*d9f75844SAndroid Build Coastguard Worker }
3643*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeDtlsSetupAttributeActive)3644*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeDtlsSetupAttributeActive) {
3645*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_dtlssetup(kDummyType);
3646*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_dtlssetup = kSdpFullString;
3647*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime, "a=setup:active\r\n", &sdp_with_dtlssetup);
3648*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_dtlssetup, &jdesc_with_dtlssetup));
3649*d9f75844SAndroid Build Coastguard Worker   cricket::SessionDescription* desc = jdesc_with_dtlssetup.description();
3650*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* atinfo =
3651*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("audio_content_name");
3652*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE,
3653*d9f75844SAndroid Build Coastguard Worker             atinfo->description.connection_role);
3654*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* vtinfo =
3655*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("video_content_name");
3656*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE,
3657*d9f75844SAndroid Build Coastguard Worker             vtinfo->description.connection_role);
3658*d9f75844SAndroid Build Coastguard Worker }
TEST_F(WebRtcSdpTest,DeserializeDtlsSetupAttributePassive)3659*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeDtlsSetupAttributePassive) {
3660*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_with_dtlssetup(kDummyType);
3661*d9f75844SAndroid Build Coastguard Worker   std::string sdp_with_dtlssetup = kSdpFullString;
3662*d9f75844SAndroid Build Coastguard Worker   InjectAfter(kSessionTime, "a=setup:passive\r\n", &sdp_with_dtlssetup);
3663*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_with_dtlssetup, &jdesc_with_dtlssetup));
3664*d9f75844SAndroid Build Coastguard Worker   cricket::SessionDescription* desc = jdesc_with_dtlssetup.description();
3665*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* atinfo =
3666*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("audio_content_name");
3667*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
3668*d9f75844SAndroid Build Coastguard Worker             atinfo->description.connection_role);
3669*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportInfo* vtinfo =
3670*d9f75844SAndroid Build Coastguard Worker       desc->GetTransportInfoByName("video_content_name");
3671*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
3672*d9f75844SAndroid Build Coastguard Worker             vtinfo->description.connection_role);
3673*d9f75844SAndroid Build Coastguard Worker }
3674*d9f75844SAndroid Build Coastguard Worker 
3675*d9f75844SAndroid Build Coastguard Worker // Verifies that the order of the serialized m-lines follows the order of the
3676*d9f75844SAndroid Build Coastguard Worker // ContentInfo in SessionDescription, and vise versa for deserialization.
TEST_F(WebRtcSdpTest,MediaContentOrderMaintainedRoundTrip)3677*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, MediaContentOrderMaintainedRoundTrip) {
3678*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
3679*d9f75844SAndroid Build Coastguard Worker   const std::string media_content_sdps[3] = {kSdpAudioString, kSdpVideoString,
3680*d9f75844SAndroid Build Coastguard Worker                                              kSdpSctpDataChannelString};
3681*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaType media_types[3] = {cricket::MEDIA_TYPE_AUDIO,
3682*d9f75844SAndroid Build Coastguard Worker                                              cricket::MEDIA_TYPE_VIDEO,
3683*d9f75844SAndroid Build Coastguard Worker                                              cricket::MEDIA_TYPE_DATA};
3684*d9f75844SAndroid Build Coastguard Worker 
3685*d9f75844SAndroid Build Coastguard Worker   // Verifies all 6 permutations.
3686*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < 6; ++i) {
3687*d9f75844SAndroid Build Coastguard Worker     size_t media_content_in_sdp[3];
3688*d9f75844SAndroid Build Coastguard Worker     // The index of the first media content.
3689*d9f75844SAndroid Build Coastguard Worker     media_content_in_sdp[0] = i / 2;
3690*d9f75844SAndroid Build Coastguard Worker     // The index of the second media content.
3691*d9f75844SAndroid Build Coastguard Worker     media_content_in_sdp[1] = (media_content_in_sdp[0] + i % 2 + 1) % 3;
3692*d9f75844SAndroid Build Coastguard Worker     // The index of the third media content.
3693*d9f75844SAndroid Build Coastguard Worker     media_content_in_sdp[2] = (media_content_in_sdp[0] + (i + 1) % 2 + 1) % 3;
3694*d9f75844SAndroid Build Coastguard Worker 
3695*d9f75844SAndroid Build Coastguard Worker     std::string sdp_string = kSdpSessionString;
3696*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < 3; ++i)
3697*d9f75844SAndroid Build Coastguard Worker       sdp_string += media_content_sdps[media_content_in_sdp[i]];
3698*d9f75844SAndroid Build Coastguard Worker 
3699*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(SdpDeserialize(sdp_string, &jdesc));
3700*d9f75844SAndroid Build Coastguard Worker     cricket::SessionDescription* desc = jdesc.description();
3701*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(3u, desc->contents().size());
3702*d9f75844SAndroid Build Coastguard Worker 
3703*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < 3; ++i) {
3704*d9f75844SAndroid Build Coastguard Worker       const cricket::MediaContentDescription* mdesc =
3705*d9f75844SAndroid Build Coastguard Worker           desc->contents()[i].media_description();
3706*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(media_types[media_content_in_sdp[i]], mdesc->type());
3707*d9f75844SAndroid Build Coastguard Worker     }
3708*d9f75844SAndroid Build Coastguard Worker 
3709*d9f75844SAndroid Build Coastguard Worker     std::string serialized_sdp = webrtc::SdpSerialize(jdesc);
3710*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(sdp_string, serialized_sdp);
3711*d9f75844SAndroid Build Coastguard Worker   }
3712*d9f75844SAndroid Build Coastguard Worker }
3713*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeBundleOnlyAttribute)3714*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeBundleOnlyAttribute) {
3715*d9f75844SAndroid Build Coastguard Worker   MakeBundleOnlyDescription();
3716*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3717*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
3718*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(kBundleOnlySdpFullString, &deserialized_description));
3719*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3720*d9f75844SAndroid Build Coastguard Worker }
3721*d9f75844SAndroid Build Coastguard Worker 
3722*d9f75844SAndroid Build Coastguard Worker // The semantics of "a=bundle-only" are only defined when it's used in
3723*d9f75844SAndroid Build Coastguard Worker // combination with a 0 port on the m= line. We should ignore it if used with a
3724*d9f75844SAndroid Build Coastguard Worker // nonzero port.
TEST_F(WebRtcSdpTest,IgnoreBundleOnlyWithNonzeroPort)3725*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, IgnoreBundleOnlyWithNonzeroPort) {
3726*d9f75844SAndroid Build Coastguard Worker   // Make the base bundle-only description but unset the bundle-only flag.
3727*d9f75844SAndroid Build Coastguard Worker   MakeBundleOnlyDescription();
3728*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->contents()[1].bundle_only = false;
3729*d9f75844SAndroid Build Coastguard Worker 
3730*d9f75844SAndroid Build Coastguard Worker   std::string modified_sdp = kBundleOnlySdpFullString;
3731*d9f75844SAndroid Build Coastguard Worker   Replace("m=video 0", "m=video 9", &modified_sdp);
3732*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3733*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(modified_sdp, &deserialized_description));
3734*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3735*d9f75844SAndroid Build Coastguard Worker }
3736*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeBundleOnlyAttribute)3737*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeBundleOnlyAttribute) {
3738*d9f75844SAndroid Build Coastguard Worker   MakeBundleOnlyDescription();
3739*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
3740*d9f75844SAndroid Build Coastguard Worker }
3741*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializePlanBSessionDescription)3742*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializePlanBSessionDescription) {
3743*d9f75844SAndroid Build Coastguard Worker   MakePlanBDescription();
3744*d9f75844SAndroid Build Coastguard Worker 
3745*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3746*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kPlanBSdpFullString, &deserialized_description));
3747*d9f75844SAndroid Build Coastguard Worker 
3748*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3749*d9f75844SAndroid Build Coastguard Worker }
3750*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializePlanBSessionDescription)3751*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializePlanBSessionDescription) {
3752*d9f75844SAndroid Build Coastguard Worker   MakePlanBDescription();
3753*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
3754*d9f75844SAndroid Build Coastguard Worker }
3755*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeUnifiedPlanSessionDescription)3756*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeUnifiedPlanSessionDescription) {
3757*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescription();
3758*d9f75844SAndroid Build Coastguard Worker 
3759*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3760*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3761*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(kUnifiedPlanSdpFullString, &deserialized_description));
3762*d9f75844SAndroid Build Coastguard Worker 
3763*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3764*d9f75844SAndroid Build Coastguard Worker }
3765*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeUnifiedPlanSessionDescription)3766*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeUnifiedPlanSessionDescription) {
3767*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescription();
3768*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
3769*d9f75844SAndroid Build Coastguard Worker }
3770*d9f75844SAndroid Build Coastguard Worker 
3771*d9f75844SAndroid Build Coastguard Worker // This tests deserializing a Unified Plan SDP that is compatible with both
3772*d9f75844SAndroid Build Coastguard Worker // Unified Plan and Plan B style SDP, meaning that it contains both "a=ssrc
3773*d9f75844SAndroid Build Coastguard Worker // msid" lines and "a=msid " lines. It tests the case for audio/video tracks
3774*d9f75844SAndroid Build Coastguard Worker // with no stream ids and multiple stream ids. For parsing this, the Unified
3775*d9f75844SAndroid Build Coastguard Worker // Plan a=msid lines should take priority, because the Plan B style a=ssrc msid
3776*d9f75844SAndroid Build Coastguard Worker // lines do not support multiple stream ids and no stream ids.
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionSpecialMsid)3777*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionSpecialMsid) {
3778*d9f75844SAndroid Build Coastguard Worker   // Create both msid lines for Plan B and Unified Plan support.
3779*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescriptionMultipleStreamIds(
3780*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingMediaSection |
3781*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingSsrcAttribute);
3782*d9f75844SAndroid Build Coastguard Worker 
3783*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3784*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kUnifiedPlanSdpFullStringWithSpecialMsid,
3785*d9f75844SAndroid Build Coastguard Worker                              &deserialized_description));
3786*d9f75844SAndroid Build Coastguard Worker 
3787*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3788*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::kMsidSignalingMediaSection |
3789*d9f75844SAndroid Build Coastguard Worker                 cricket::kMsidSignalingSsrcAttribute,
3790*d9f75844SAndroid Build Coastguard Worker             deserialized_description.description()->msid_signaling());
3791*d9f75844SAndroid Build Coastguard Worker }
3792*d9f75844SAndroid Build Coastguard Worker 
3793*d9f75844SAndroid Build Coastguard Worker // Tests the serialization of a Unified Plan SDP that is compatible for both
3794*d9f75844SAndroid Build Coastguard Worker // Unified Plan and Plan B style SDPs, meaning that it contains both "a=ssrc
3795*d9f75844SAndroid Build Coastguard Worker // msid" lines and "a=msid " lines. It tests the case for no stream ids and
3796*d9f75844SAndroid Build Coastguard Worker // multiple stream ids.
TEST_F(WebRtcSdpTest,SerializeSessionDescriptionSpecialMsid)3797*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSessionDescriptionSpecialMsid) {
3798*d9f75844SAndroid Build Coastguard Worker   // Create both msid lines for Plan B and Unified Plan support.
3799*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescriptionMultipleStreamIds(
3800*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingMediaSection |
3801*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingSsrcAttribute);
3802*d9f75844SAndroid Build Coastguard Worker   std::string serialized_sdp = webrtc::SdpSerialize(jdesc_);
3803*d9f75844SAndroid Build Coastguard Worker   // We explicitly test that the serialized SDP string is equal to the hard
3804*d9f75844SAndroid Build Coastguard Worker   // coded SDP string. This is necessary, because in the parser "a=msid" lines
3805*d9f75844SAndroid Build Coastguard Worker   // take priority over "a=ssrc msid" lines. This means if we just used
3806*d9f75844SAndroid Build Coastguard Worker   // TestSerialize(), it could serialize an SDP that omits "a=ssrc msid" lines,
3807*d9f75844SAndroid Build Coastguard Worker   // and still pass, because the deserialized version would be the same.
3808*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kUnifiedPlanSdpFullStringWithSpecialMsid, serialized_sdp);
3809*d9f75844SAndroid Build Coastguard Worker }
3810*d9f75844SAndroid Build Coastguard Worker 
3811*d9f75844SAndroid Build Coastguard Worker // Tests that a Unified Plan style SDP (does not contain "a=ssrc msid" lines
3812*d9f75844SAndroid Build Coastguard Worker // that signal stream IDs) is deserialized appropriately. It tests the case for
3813*d9f75844SAndroid Build Coastguard Worker // no stream ids and multiple stream ids.
TEST_F(WebRtcSdpTest,UnifiedPlanDeserializeSessionDescriptionSpecialMsid)3814*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, UnifiedPlanDeserializeSessionDescriptionSpecialMsid) {
3815*d9f75844SAndroid Build Coastguard Worker   // Only create a=msid lines for strictly Unified Plan stream ID support.
3816*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescriptionMultipleStreamIds(
3817*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingMediaSection);
3818*d9f75844SAndroid Build Coastguard Worker 
3819*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3820*d9f75844SAndroid Build Coastguard Worker   std::string unified_plan_sdp_string =
3821*d9f75844SAndroid Build Coastguard Worker       kUnifiedPlanSdpFullStringWithSpecialMsid;
3822*d9f75844SAndroid Build Coastguard Worker   RemoveSsrcMsidLinesFromSdpString(&unified_plan_sdp_string);
3823*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3824*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(unified_plan_sdp_string, &deserialized_description));
3825*d9f75844SAndroid Build Coastguard Worker 
3826*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3827*d9f75844SAndroid Build Coastguard Worker }
3828*d9f75844SAndroid Build Coastguard Worker 
3829*d9f75844SAndroid Build Coastguard Worker // Tests that a Unified Plan style SDP (does not contain "a=ssrc msid" lines
3830*d9f75844SAndroid Build Coastguard Worker // that signal stream IDs) is serialized appropriately. It tests the case for no
3831*d9f75844SAndroid Build Coastguard Worker // stream ids and multiple stream ids.
TEST_F(WebRtcSdpTest,UnifiedPlanSerializeSessionDescriptionSpecialMsid)3832*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, UnifiedPlanSerializeSessionDescriptionSpecialMsid) {
3833*d9f75844SAndroid Build Coastguard Worker   // Only create a=msid lines for strictly Unified Plan stream ID support.
3834*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescriptionMultipleStreamIds(
3835*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingMediaSection);
3836*d9f75844SAndroid Build Coastguard Worker 
3837*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
3838*d9f75844SAndroid Build Coastguard Worker }
3839*d9f75844SAndroid Build Coastguard Worker 
3840*d9f75844SAndroid Build Coastguard Worker // This tests that a Unified Plan SDP with no a=ssrc lines is
3841*d9f75844SAndroid Build Coastguard Worker // serialized/deserialized appropriately. In this case the
3842*d9f75844SAndroid Build Coastguard Worker // MediaContentDescription will contain a StreamParams object that doesn't have
3843*d9f75844SAndroid Build Coastguard Worker // any SSRCs. Vice versa, this will be created upon deserializing an SDP with no
3844*d9f75844SAndroid Build Coastguard Worker // SSRC lines.
TEST_F(WebRtcSdpTest,DeserializeUnifiedPlanSessionDescriptionNoSsrcSignaling)3845*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeUnifiedPlanSessionDescriptionNoSsrcSignaling) {
3846*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescription();
3847*d9f75844SAndroid Build Coastguard Worker   RemoveSsrcSignalingFromStreamParams();
3848*d9f75844SAndroid Build Coastguard Worker   std::string unified_plan_sdp_string = kUnifiedPlanSdpFullString;
3849*d9f75844SAndroid Build Coastguard Worker   RemoveSsrcLinesFromSdpString(&unified_plan_sdp_string);
3850*d9f75844SAndroid Build Coastguard Worker 
3851*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription deserialized_description(kDummyType);
3852*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3853*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(unified_plan_sdp_string, &deserialized_description));
3854*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, deserialized_description));
3855*d9f75844SAndroid Build Coastguard Worker }
3856*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeUnifiedPlanSessionDescriptionNoSsrcSignaling)3857*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeUnifiedPlanSessionDescriptionNoSsrcSignaling) {
3858*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescription();
3859*d9f75844SAndroid Build Coastguard Worker   RemoveSsrcSignalingFromStreamParams();
3860*d9f75844SAndroid Build Coastguard Worker 
3861*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
3862*d9f75844SAndroid Build Coastguard Worker }
3863*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,EmptyDescriptionHasNoMsidSignaling)3864*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, EmptyDescriptionHasNoMsidSignaling) {
3865*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
3866*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(kSdpSessionString, &jsep_desc));
3867*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, jsep_desc.description()->msid_signaling());
3868*d9f75844SAndroid Build Coastguard Worker }
3869*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DataChannelOnlyHasNoMsidSignaling)3870*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DataChannelOnlyHasNoMsidSignaling) {
3871*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
3872*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpSessionString;
3873*d9f75844SAndroid Build Coastguard Worker   sdp += kSdpSctpDataChannelString;
3874*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(sdp, &jsep_desc));
3875*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, jsep_desc.description()->msid_signaling());
3876*d9f75844SAndroid Build Coastguard Worker }
3877*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,PlanBHasSsrcAttributeMsidSignaling)3878*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, PlanBHasSsrcAttributeMsidSignaling) {
3879*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
3880*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(kPlanBSdpFullString, &jsep_desc));
3881*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::kMsidSignalingSsrcAttribute,
3882*d9f75844SAndroid Build Coastguard Worker             jsep_desc.description()->msid_signaling());
3883*d9f75844SAndroid Build Coastguard Worker }
3884*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,UnifiedPlanHasMediaSectionMsidSignaling)3885*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, UnifiedPlanHasMediaSectionMsidSignaling) {
3886*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
3887*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(kUnifiedPlanSdpFullString, &jsep_desc));
3888*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::kMsidSignalingMediaSection,
3889*d9f75844SAndroid Build Coastguard Worker             jsep_desc.description()->msid_signaling());
3890*d9f75844SAndroid Build Coastguard Worker }
3891*d9f75844SAndroid Build Coastguard Worker 
3892*d9f75844SAndroid Build Coastguard Worker const char kMediaSectionMsidLine[] = "a=msid:local_stream_1 audio_track_id_1";
3893*d9f75844SAndroid Build Coastguard Worker const char kSsrcAttributeMsidLine[] =
3894*d9f75844SAndroid Build Coastguard Worker     "a=ssrc:1 msid:local_stream_1 audio_track_id_1";
3895*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeOnlyMediaSectionMsid)3896*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeOnlyMediaSectionMsid) {
3897*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_msid_signaling(cricket::kMsidSignalingMediaSection);
3898*d9f75844SAndroid Build Coastguard Worker   std::string sdp = webrtc::SdpSerialize(jdesc_);
3899*d9f75844SAndroid Build Coastguard Worker 
3900*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, sdp.find(kMediaSectionMsidLine));
3901*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string::npos, sdp.find(kSsrcAttributeMsidLine));
3902*d9f75844SAndroid Build Coastguard Worker }
3903*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeOnlySsrcAttributeMsid)3904*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeOnlySsrcAttributeMsid) {
3905*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_msid_signaling(
3906*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingSsrcAttribute);
3907*d9f75844SAndroid Build Coastguard Worker   std::string sdp = webrtc::SdpSerialize(jdesc_);
3908*d9f75844SAndroid Build Coastguard Worker 
3909*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(std::string::npos, sdp.find(kMediaSectionMsidLine));
3910*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, sdp.find(kSsrcAttributeMsidLine));
3911*d9f75844SAndroid Build Coastguard Worker }
3912*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeBothMediaSectionAndSsrcAttributeMsid)3913*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeBothMediaSectionAndSsrcAttributeMsid) {
3914*d9f75844SAndroid Build Coastguard Worker   jdesc_.description()->set_msid_signaling(
3915*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingMediaSection |
3916*d9f75844SAndroid Build Coastguard Worker       cricket::kMsidSignalingSsrcAttribute);
3917*d9f75844SAndroid Build Coastguard Worker   std::string sdp = webrtc::SdpSerialize(jdesc_);
3918*d9f75844SAndroid Build Coastguard Worker 
3919*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, sdp.find(kMediaSectionMsidLine));
3920*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos, sdp.find(kSsrcAttributeMsidLine));
3921*d9f75844SAndroid Build Coastguard Worker }
3922*d9f75844SAndroid Build Coastguard Worker 
3923*d9f75844SAndroid Build Coastguard Worker // Regression test for integer overflow bug:
3924*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=648071
TEST_F(WebRtcSdpTest,DeserializeLargeBandwidthLimit)3925*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeLargeBandwidthLimit) {
3926*d9f75844SAndroid Build Coastguard Worker   // Bandwidth attribute is the max signed 32-bit int, which will get
3927*d9f75844SAndroid Build Coastguard Worker   // multiplied by 1000 and cause int overflow if not careful.
3928*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithLargeBandwidth[] =
3929*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3930*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3931*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3932*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3933*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120\r\n"
3934*d9f75844SAndroid Build Coastguard Worker       "b=AS:2147483647\r\n"
3935*d9f75844SAndroid Build Coastguard Worker       "foo=fail\r\n";
3936*d9f75844SAndroid Build Coastguard Worker 
3937*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(kSdpWithLargeBandwidth), "foo=fail");
3938*d9f75844SAndroid Build Coastguard Worker }
3939*d9f75844SAndroid Build Coastguard Worker 
3940*d9f75844SAndroid Build Coastguard Worker // Similar to the above, except that negative values are illegal, not just
3941*d9f75844SAndroid Build Coastguard Worker // error-prone as large values are.
3942*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=675361
TEST_F(WebRtcSdpTest,DeserializingNegativeBandwidthLimitFails)3943*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializingNegativeBandwidthLimitFails) {
3944*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithNegativeBandwidth[] =
3945*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3946*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3947*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3948*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3949*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120\r\n"
3950*d9f75844SAndroid Build Coastguard Worker       "b=AS:-1000\r\n";
3951*d9f75844SAndroid Build Coastguard Worker 
3952*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(kSdpWithNegativeBandwidth), "b=AS:-1000");
3953*d9f75844SAndroid Build Coastguard Worker }
3954*d9f75844SAndroid Build Coastguard Worker 
3955*d9f75844SAndroid Build Coastguard Worker // An exception to the above rule: a value of -1 for b=AS should just be
3956*d9f75844SAndroid Build Coastguard Worker // ignored, resulting in "kAutoBandwidth" in the deserialized object.
3957*d9f75844SAndroid Build Coastguard Worker // Applications historically may be using "b=AS:-1" to mean "no bandwidth
3958*d9f75844SAndroid Build Coastguard Worker // limit", but this is now what ommitting the attribute entirely will do, so
3959*d9f75844SAndroid Build Coastguard Worker // ignoring it will have the intended effect.
TEST_F(WebRtcSdpTest,BandwidthLimitOfNegativeOneIgnored)3960*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, BandwidthLimitOfNegativeOneIgnored) {
3961*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithBandwidthOfNegativeOne[] =
3962*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3963*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3964*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3965*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3966*d9f75844SAndroid Build Coastguard Worker       "m=video 3457 RTP/SAVPF 120\r\n"
3967*d9f75844SAndroid Build Coastguard Worker       "b=AS:-1\r\n";
3968*d9f75844SAndroid Build Coastguard Worker 
3969*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3970*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithBandwidthOfNegativeOne, &jdesc_output));
3971*d9f75844SAndroid Build Coastguard Worker   const VideoContentDescription* vcd =
3972*d9f75844SAndroid Build Coastguard Worker       GetFirstVideoContentDescription(jdesc_output.description());
3973*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(vcd);
3974*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::kAutoBandwidth, vcd->bandwidth());
3975*d9f75844SAndroid Build Coastguard Worker }
3976*d9f75844SAndroid Build Coastguard Worker 
3977*d9f75844SAndroid Build Coastguard Worker // Test that "ufrag"/"pwd" in the candidate line itself are ignored, and only
3978*d9f75844SAndroid Build Coastguard Worker // the "a=ice-ufrag"/"a=ice-pwd" attributes are used.
3979*d9f75844SAndroid Build Coastguard Worker // Regression test for:
3980*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=681286
TEST_F(WebRtcSdpTest,IceCredentialsInCandidateStringIgnored)3981*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, IceCredentialsInCandidateStringIgnored) {
3982*d9f75844SAndroid Build Coastguard Worker   // Important piece is "ufrag foo pwd bar".
3983*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithIceCredentialsInCandidateString[] =
3984*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
3985*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
3986*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
3987*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
3988*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
3989*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
3990*d9f75844SAndroid Build Coastguard Worker       "a=rtcp:9 IN IP4 0.0.0.0\r\n"
3991*d9f75844SAndroid Build Coastguard Worker       "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
3992*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
3993*d9f75844SAndroid Build Coastguard Worker       "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
3994*d9f75844SAndroid Build Coastguard Worker       "generation 2 ufrag foo pwd bar\r\n";
3995*d9f75844SAndroid Build Coastguard Worker 
3996*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
3997*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(
3998*d9f75844SAndroid Build Coastguard Worker       SdpDeserialize(kSdpWithIceCredentialsInCandidateString, &jdesc_output));
3999*d9f75844SAndroid Build Coastguard Worker   const IceCandidateCollection* candidates = jdesc_output.candidates(0);
4000*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(nullptr, candidates);
4001*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1U, candidates->count());
4002*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate c = candidates->at(0)->candidate();
4003*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("ufrag_voice", c.username());
4004*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("pwd_voice", c.password());
4005*d9f75844SAndroid Build Coastguard Worker }
4006*d9f75844SAndroid Build Coastguard Worker 
4007*d9f75844SAndroid Build Coastguard Worker // Test that attribute lines "a=ice-ufrag-something"/"a=ice-pwd-something" are
4008*d9f75844SAndroid Build Coastguard Worker // ignored, and only the "a=ice-ufrag"/"a=ice-pwd" attributes are used.
4009*d9f75844SAndroid Build Coastguard Worker // Regression test for:
4010*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/webrtc/issues/detail?id=9712
TEST_F(WebRtcSdpTest,AttributeWithPartialMatchingNameIsIgnored)4011*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, AttributeWithPartialMatchingNameIsIgnored) {
4012*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithFooIceCredentials[] =
4013*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4014*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4015*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4016*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4017*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4018*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4019*d9f75844SAndroid Build Coastguard Worker       "a=rtcp:9 IN IP4 0.0.0.0\r\n"
4020*d9f75844SAndroid Build Coastguard Worker       "a=ice-ufrag-something:foo\r\na=ice-pwd-something:bar\r\n"
4021*d9f75844SAndroid Build Coastguard Worker       "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
4022*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4023*d9f75844SAndroid Build Coastguard Worker       "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
4024*d9f75844SAndroid Build Coastguard Worker       "generation 2\r\n";
4025*d9f75844SAndroid Build Coastguard Worker 
4026*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4027*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithFooIceCredentials, &jdesc_output));
4028*d9f75844SAndroid Build Coastguard Worker   const IceCandidateCollection* candidates = jdesc_output.candidates(0);
4029*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(nullptr, candidates);
4030*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1U, candidates->count());
4031*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate c = candidates->at(0)->candidate();
4032*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("ufrag_voice", c.username());
4033*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("pwd_voice", c.password());
4034*d9f75844SAndroid Build Coastguard Worker }
4035*d9f75844SAndroid Build Coastguard Worker 
4036*d9f75844SAndroid Build Coastguard Worker // Test that SDP with an invalid port number in "a=candidate" lines is
4037*d9f75844SAndroid Build Coastguard Worker // rejected, without crashing.
4038*d9f75844SAndroid Build Coastguard Worker // Regression test for:
4039*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=677029
TEST_F(WebRtcSdpTest,DeserializeInvalidPortInCandidateAttribute)4040*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeInvalidPortInCandidateAttribute) {
4041*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithInvalidCandidatePort[] =
4042*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4043*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4044*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4045*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4046*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4047*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4048*d9f75844SAndroid Build Coastguard Worker       "a=rtcp:9 IN IP4 0.0.0.0\r\n"
4049*d9f75844SAndroid Build Coastguard Worker       "a=ice-ufrag:ufrag_voice\r\na=ice-pwd:pwd_voice\r\n"
4050*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4051*d9f75844SAndroid Build Coastguard Worker       "a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 12345678 typ host "
4052*d9f75844SAndroid Build Coastguard Worker       "generation 2 raddr 192.168.1.1 rport 87654321\r\n";
4053*d9f75844SAndroid Build Coastguard Worker 
4054*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4055*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(kSdpWithInvalidCandidatePort, &jdesc_output));
4056*d9f75844SAndroid Build Coastguard Worker }
4057*d9f75844SAndroid Build Coastguard Worker 
4058*d9f75844SAndroid Build Coastguard Worker // Test that "a=msid" with a missing track ID is rejected and doesn't crash.
4059*d9f75844SAndroid Build Coastguard Worker // Regression test for:
4060*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=686405
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithMissingTrackId)4061*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithMissingTrackId) {
4062*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingTrackId[] =
4063*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4064*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4065*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4066*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4067*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4068*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4069*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4070*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id \r\n";
4071*d9f75844SAndroid Build Coastguard Worker 
4072*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4073*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(kSdpWithMissingTrackId, &jdesc_output));
4074*d9f75844SAndroid Build Coastguard Worker }
4075*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithoutAppData)4076*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithoutAppData) {
4077*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingStreamId[] =
4078*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4079*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4080*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4081*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4082*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4083*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4084*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4085*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id\r\n";
4086*d9f75844SAndroid Build Coastguard Worker 
4087*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4088*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithMissingStreamId, &jdesc_output));
4089*d9f75844SAndroid Build Coastguard Worker }
4090*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithoutAppDataTwoStreams)4091*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithoutAppDataTwoStreams) {
4092*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingStreamId[] =
4093*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4094*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4095*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4096*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4097*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4098*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4099*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4100*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id\r\n"
4101*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id2\r\n";
4102*d9f75844SAndroid Build Coastguard Worker 
4103*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4104*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithMissingStreamId, &jdesc_output));
4105*d9f75844SAndroid Build Coastguard Worker }
4106*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithoutAppDataDuplicate)4107*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithoutAppDataDuplicate) {
4108*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingStreamId[] =
4109*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4110*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4111*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4112*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4113*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4114*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4115*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4116*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id\r\n"
4117*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id\r\n";
4118*d9f75844SAndroid Build Coastguard Worker 
4119*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4120*d9f75844SAndroid Build Coastguard Worker   // This is somewhat silly but accept it.
4121*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithMissingStreamId, &jdesc_output));
4122*d9f75844SAndroid Build Coastguard Worker }
4123*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithoutAppDataMixed)4124*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithoutAppDataMixed) {
4125*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingStreamId[] =
4126*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4127*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4128*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4129*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4130*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4131*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4132*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4133*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id\r\n"
4134*d9f75844SAndroid Build Coastguard Worker       "a=msid:stream_id track_id\r\n";
4135*d9f75844SAndroid Build Coastguard Worker 
4136*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4137*d9f75844SAndroid Build Coastguard Worker   // Mixing the syntax like this is not a good idea but we accept it
4138*d9f75844SAndroid Build Coastguard Worker   // and the result is the second track_id.
4139*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(kSdpWithMissingStreamId, &jdesc_output));
4140*d9f75844SAndroid Build Coastguard Worker }
4141*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeMsidAttributeWithMissingStreamId)4142*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeMsidAttributeWithMissingStreamId) {
4143*d9f75844SAndroid Build Coastguard Worker   static const char kSdpWithMissingStreamId[] =
4144*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4145*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4146*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4147*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4148*d9f75844SAndroid Build Coastguard Worker       "m=audio 9 RTP/SAVPF 111\r\n"
4149*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4150*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:111 opus/48000/2\r\n"
4151*d9f75844SAndroid Build Coastguard Worker       "a=msid: track_id\r\n";
4152*d9f75844SAndroid Build Coastguard Worker 
4153*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4154*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(kSdpWithMissingStreamId, &jdesc_output));
4155*d9f75844SAndroid Build Coastguard Worker }
4156*d9f75844SAndroid Build Coastguard Worker 
4157*d9f75844SAndroid Build Coastguard Worker // Tests that if both session-level address and media-level address exist, use
4158*d9f75844SAndroid Build Coastguard Worker // the media-level address.
TEST_F(WebRtcSdpTest,ParseConnectionData)4159*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseConnectionData) {
4160*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4161*d9f75844SAndroid Build Coastguard Worker 
4162*d9f75844SAndroid Build Coastguard Worker   // Sesssion-level address.
4163*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpFullString;
4164*d9f75844SAndroid Build Coastguard Worker   InjectAfter("s=-\r\n", "c=IN IP4 192.168.0.3\r\n", &sdp);
4165*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4166*d9f75844SAndroid Build Coastguard Worker 
4167*d9f75844SAndroid Build Coastguard Worker   const auto& content1 = jsep_desc.description()->contents()[0];
4168*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("74.125.127.126:2345",
4169*d9f75844SAndroid Build Coastguard Worker             content1.media_description()->connection_address().ToString());
4170*d9f75844SAndroid Build Coastguard Worker   const auto& content2 = jsep_desc.description()->contents()[1];
4171*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("74.125.224.39:3457",
4172*d9f75844SAndroid Build Coastguard Worker             content2.media_description()->connection_address().ToString());
4173*d9f75844SAndroid Build Coastguard Worker }
4174*d9f75844SAndroid Build Coastguard Worker 
4175*d9f75844SAndroid Build Coastguard Worker // Tests that the session-level connection address will be used if the media
4176*d9f75844SAndroid Build Coastguard Worker // level-addresses are not specified.
TEST_F(WebRtcSdpTest,ParseConnectionDataSessionLevelOnly)4177*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseConnectionDataSessionLevelOnly) {
4178*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4179*d9f75844SAndroid Build Coastguard Worker 
4180*d9f75844SAndroid Build Coastguard Worker   // Sesssion-level address.
4181*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4182*d9f75844SAndroid Build Coastguard Worker   InjectAfter("s=-\r\n", "c=IN IP4 192.168.0.3\r\n", &sdp);
4183*d9f75844SAndroid Build Coastguard Worker   // Remove the media level addresses.
4184*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 0.0.0.0\r\n", "", &sdp);
4185*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 0.0.0.0\r\n", "", &sdp);
4186*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4187*d9f75844SAndroid Build Coastguard Worker 
4188*d9f75844SAndroid Build Coastguard Worker   const auto& content1 = jsep_desc.description()->contents()[0];
4189*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("192.168.0.3:9",
4190*d9f75844SAndroid Build Coastguard Worker             content1.media_description()->connection_address().ToString());
4191*d9f75844SAndroid Build Coastguard Worker   const auto& content2 = jsep_desc.description()->contents()[1];
4192*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("192.168.0.3:9",
4193*d9f75844SAndroid Build Coastguard Worker             content2.media_description()->connection_address().ToString());
4194*d9f75844SAndroid Build Coastguard Worker }
4195*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,ParseConnectionDataIPv6)4196*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseConnectionDataIPv6) {
4197*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4198*d9f75844SAndroid Build Coastguard Worker 
4199*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4200*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4201*d9f75844SAndroid Build Coastguard Worker   Replace("m=audio 9 RTP/SAVPF 111 103 104\r\nc=IN IP4 0.0.0.0\r\n",
4202*d9f75844SAndroid Build Coastguard Worker           "m=audio 9 RTP/SAVPF 111 103 104\r\nc=IN IP6 "
4203*d9f75844SAndroid Build Coastguard Worker           "2001:0db8:85a3:0000:0000:8a2e:0370:7335\r\n",
4204*d9f75844SAndroid Build Coastguard Worker           &sdp);
4205*d9f75844SAndroid Build Coastguard Worker   Replace("m=video 9 RTP/SAVPF 120\r\nc=IN IP4 0.0.0.0\r\n",
4206*d9f75844SAndroid Build Coastguard Worker           "m=video 9 RTP/SAVPF 120\r\nc=IN IP6 "
4207*d9f75844SAndroid Build Coastguard Worker           "2001:0db8:85a3:0000:0000:8a2e:0370:7336\r\n",
4208*d9f75844SAndroid Build Coastguard Worker           &sdp);
4209*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4210*d9f75844SAndroid Build Coastguard Worker   const auto& content1 = jsep_desc.description()->contents()[0];
4211*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("[2001:db8:85a3::8a2e:370:7335]:9",
4212*d9f75844SAndroid Build Coastguard Worker             content1.media_description()->connection_address().ToString());
4213*d9f75844SAndroid Build Coastguard Worker   const auto& content2 = jsep_desc.description()->contents()[1];
4214*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("[2001:db8:85a3::8a2e:370:7336]:9",
4215*d9f75844SAndroid Build Coastguard Worker             content2.media_description()->connection_address().ToString());
4216*d9f75844SAndroid Build Coastguard Worker }
4217*d9f75844SAndroid Build Coastguard Worker 
4218*d9f75844SAndroid Build Coastguard Worker // Test that a c= line that contains a hostname connection address can be
4219*d9f75844SAndroid Build Coastguard Worker // parsed.
TEST_F(WebRtcSdpTest,ParseConnectionDataWithHostnameConnectionAddress)4220*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseConnectionDataWithHostnameConnectionAddress) {
4221*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4222*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4223*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4224*d9f75844SAndroid Build Coastguard Worker 
4225*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpString;
4226*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 0.0.0.0\r\n", "c=IN IP4 example.local\r\n", &sdp);
4227*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 0.0.0.0\r\n", "c=IN IP4 example.local\r\n", &sdp);
4228*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4229*d9f75844SAndroid Build Coastguard Worker 
4230*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(nullptr, jsep_desc.description());
4231*d9f75844SAndroid Build Coastguard Worker   const auto& content1 = jsep_desc.description()->contents()[0];
4232*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("example.local:9",
4233*d9f75844SAndroid Build Coastguard Worker             content1.media_description()->connection_address().ToString());
4234*d9f75844SAndroid Build Coastguard Worker   const auto& content2 = jsep_desc.description()->contents()[1];
4235*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("example.local:9",
4236*d9f75844SAndroid Build Coastguard Worker             content2.media_description()->connection_address().ToString());
4237*d9f75844SAndroid Build Coastguard Worker }
4238*d9f75844SAndroid Build Coastguard Worker 
4239*d9f75844SAndroid Build Coastguard Worker // Test that the invalid or unsupported connection data cannot be parsed.
TEST_F(WebRtcSdpTest,ParseConnectionDataFailure)4240*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseConnectionDataFailure) {
4241*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4242*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4243*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4244*d9f75844SAndroid Build Coastguard Worker 
4245*d9f75844SAndroid Build Coastguard Worker   // Unsupported multicast IPv4 address.
4246*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpFullString;
4247*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 74.125.224.39\r\n", "c=IN IP4 74.125.224.39/127\r\n", &sdp);
4248*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp, &jsep_desc));
4249*d9f75844SAndroid Build Coastguard Worker 
4250*d9f75844SAndroid Build Coastguard Worker   // Unsupported multicast IPv6 address.
4251*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpFullString;
4252*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 74.125.224.39\r\n", "c=IN IP6 ::1/3\r\n", &sdp);
4253*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp, &jsep_desc));
4254*d9f75844SAndroid Build Coastguard Worker 
4255*d9f75844SAndroid Build Coastguard Worker   // Mismatched address type.
4256*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpFullString;
4257*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 74.125.224.39\r\n", "c=IN IP6 74.125.224.39\r\n", &sdp);
4258*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp, &jsep_desc));
4259*d9f75844SAndroid Build Coastguard Worker 
4260*d9f75844SAndroid Build Coastguard Worker   sdp = kSdpFullString;
4261*d9f75844SAndroid Build Coastguard Worker   Replace("c=IN IP4 74.125.224.39\r\n",
4262*d9f75844SAndroid Build Coastguard Worker           "c=IN IP4 2001:0db8:85a3:0000:0000:8a2e:0370:7334\r\n", &sdp);
4263*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(SdpDeserialize(sdp, &jsep_desc));
4264*d9f75844SAndroid Build Coastguard Worker }
4265*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeAndDeserializeWithConnectionAddress)4266*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeAndDeserializeWithConnectionAddress) {
4267*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription expected_jsep(kDummyType);
4268*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&expected_jsep);
4269*d9f75844SAndroid Build Coastguard Worker   // Serialization.
4270*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(expected_jsep);
4271*d9f75844SAndroid Build Coastguard Worker   // Deserialization.
4272*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc(kDummyType);
4273*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(message, &jdesc));
4274*d9f75844SAndroid Build Coastguard Worker   auto audio_desc = jdesc.description()
4275*d9f75844SAndroid Build Coastguard Worker                         ->GetContentByName(kAudioContentName)
4276*d9f75844SAndroid Build Coastguard Worker                         ->media_description();
4277*d9f75844SAndroid Build Coastguard Worker   auto video_desc = jdesc.description()
4278*d9f75844SAndroid Build Coastguard Worker                         ->GetContentByName(kVideoContentName)
4279*d9f75844SAndroid Build Coastguard Worker                         ->media_description();
4280*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(audio_desc_->connection_address().ToString(),
4281*d9f75844SAndroid Build Coastguard Worker             audio_desc->connection_address().ToString());
4282*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(video_desc_->connection_address().ToString(),
4283*d9f75844SAndroid Build Coastguard Worker             video_desc->connection_address().ToString());
4284*d9f75844SAndroid Build Coastguard Worker }
4285*d9f75844SAndroid Build Coastguard Worker 
4286*d9f75844SAndroid Build Coastguard Worker // RFC4566 says "If a session has no meaningful name, the value "s= " SHOULD be
4287*d9f75844SAndroid Build Coastguard Worker // used (i.e., a single space as the session name)." So we should accept that.
TEST_F(WebRtcSdpTest,DeserializeEmptySessionName)4288*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeEmptySessionName) {
4289*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4290*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4291*d9f75844SAndroid Build Coastguard Worker   Replace("s=-\r\n", "s= \r\n", &sdp);
4292*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
4293*d9f75844SAndroid Build Coastguard Worker }
4294*d9f75844SAndroid Build Coastguard Worker 
4295*d9f75844SAndroid Build Coastguard Worker // Simulcast malformed input test for invalid format.
TEST_F(WebRtcSdpTest,DeserializeSimulcastNegative_EmptyAttribute)4296*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSimulcastNegative_EmptyAttribute) {
4297*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines(
4298*d9f75844SAndroid Build Coastguard Worker       "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n", "a=simulcast:\r\n",
4299*d9f75844SAndroid Build Coastguard Worker       "a=simulcast:");
4300*d9f75844SAndroid Build Coastguard Worker }
4301*d9f75844SAndroid Build Coastguard Worker 
4302*d9f75844SAndroid Build Coastguard Worker // Tests that duplicate simulcast entries in the SDP triggers a parse failure.
TEST_F(WebRtcSdpTest,DeserializeSimulcastNegative_DuplicateAttribute)4303*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSimulcastNegative_DuplicateAttribute) {
4304*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailureWithNewLines(
4305*d9f75844SAndroid Build Coastguard Worker       "a=ssrc:3 msid:local_stream_1 video_track_id_1\r\n",
4306*d9f75844SAndroid Build Coastguard Worker       "a=simulcast:send 1\r\na=simulcast:recv 2\r\n", "a=simulcast:");
4307*d9f75844SAndroid Build Coastguard Worker }
4308*d9f75844SAndroid Build Coastguard Worker 
4309*d9f75844SAndroid Build Coastguard Worker // Validates that deserialization uses the a=simulcast: attribute
TEST_F(WebRtcSdpTest,TestDeserializeSimulcastAttribute)4310*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeSimulcastAttribute) {
4311*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4312*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4313*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4314*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 send\r\n";
4315*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4 recv\r\n";
4316*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:5 recv\r\n";
4317*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:6 recv\r\n";
4318*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1,2;3 recv 4;5;6\r\n";
4319*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4320*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4321*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4322*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4323*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4324*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4325*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4326*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, media->simulcast_description().send_layers().size());
4327*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(3ul, media->simulcast_description().receive_layers().size());
4328*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4329*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4330*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "2", "3"});
4331*d9f75844SAndroid Build Coastguard Worker }
4332*d9f75844SAndroid Build Coastguard Worker 
4333*d9f75844SAndroid Build Coastguard Worker // Validates that deserialization removes rids that do not appear in SDP
TEST_F(WebRtcSdpTest,TestDeserializeSimulcastAttributeRemovesUnknownRids)4334*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeSimulcastAttributeRemovesUnknownRids) {
4335*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4336*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4337*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 send\r\n";
4338*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4 recv\r\n";
4339*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1,2;3 recv 4;5,6\r\n";
4340*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4341*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4342*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4343*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4344*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4345*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4346*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4347*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4348*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().size());
4349*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.receive_layers().size());
4350*d9f75844SAndroid Build Coastguard Worker 
4351*d9f75844SAndroid Build Coastguard Worker   std::vector<SimulcastLayer> all_send_layers =
4352*d9f75844SAndroid Build Coastguard Worker       simulcast.send_layers().GetAllLayers();
4353*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, all_send_layers.size());
4354*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0,
4355*d9f75844SAndroid Build Coastguard Worker             absl::c_count_if(all_send_layers, [](const SimulcastLayer& layer) {
4356*d9f75844SAndroid Build Coastguard Worker               return layer.rid == "2";
4357*d9f75844SAndroid Build Coastguard Worker             }));
4358*d9f75844SAndroid Build Coastguard Worker 
4359*d9f75844SAndroid Build Coastguard Worker   std::vector<SimulcastLayer> all_receive_layers =
4360*d9f75844SAndroid Build Coastguard Worker       simulcast.receive_layers().GetAllLayers();
4361*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1ul, all_receive_layers.size());
4362*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("4", all_receive_layers[0].rid);
4363*d9f75844SAndroid Build Coastguard Worker 
4364*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4365*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4366*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "3"});
4367*d9f75844SAndroid Build Coastguard Worker }
4368*d9f75844SAndroid Build Coastguard Worker 
4369*d9f75844SAndroid Build Coastguard Worker // Validates that Simulcast removes rids that appear in both send and receive.
TEST_F(WebRtcSdpTest,TestDeserializeSimulcastAttributeRemovesDuplicateSendReceive)4370*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest,
4371*d9f75844SAndroid Build Coastguard Worker        TestDeserializeSimulcastAttributeRemovesDuplicateSendReceive) {
4372*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4373*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4374*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4375*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 send\r\n";
4376*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4 recv\r\n";
4377*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1;2;3 recv 2;4\r\n";
4378*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4379*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4380*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4381*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4382*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4383*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4384*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4385*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4386*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().size());
4387*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.receive_layers().size());
4388*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().GetAllLayers().size());
4389*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.receive_layers().GetAllLayers().size());
4390*d9f75844SAndroid Build Coastguard Worker 
4391*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4392*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4393*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "3"});
4394*d9f75844SAndroid Build Coastguard Worker }
4395*d9f75844SAndroid Build Coastguard Worker 
4396*d9f75844SAndroid Build Coastguard Worker // Ignores empty rid line.
TEST_F(WebRtcSdpTest,TestDeserializeIgnoresEmptyRidLines)4397*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeIgnoresEmptyRidLines) {
4398*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4399*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4400*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4401*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid\r\n";   // Should ignore this line.
4402*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:\r\n";  // Should ignore this line.
4403*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1;2\r\n";
4404*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4405*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4406*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4407*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4408*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4409*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4410*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4411*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4412*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(simulcast.receive_layers().empty());
4413*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().size());
4414*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().GetAllLayers().size());
4415*d9f75844SAndroid Build Coastguard Worker 
4416*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4417*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4418*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "2"});
4419*d9f75844SAndroid Build Coastguard Worker }
4420*d9f75844SAndroid Build Coastguard Worker 
4421*d9f75844SAndroid Build Coastguard Worker // Ignores malformed rid lines.
TEST_F(WebRtcSdpTest,TestDeserializeIgnoresMalformedRidLines)4422*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeIgnoresMalformedRidLines) {
4423*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4424*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send pt=\r\n";              // Should ignore this line.
4425*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 receive\r\n";               // Should ignore this line.
4426*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 max-width=720;pt=120\r\n";  // Should ignore this line.
4427*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4\r\n";                       // Should ignore this line.
4428*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:5 send\r\n";
4429*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1,2,3;4,5\r\n";
4430*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4431*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4432*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4433*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4434*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4435*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4436*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4437*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4438*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(simulcast.receive_layers().empty());
4439*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.send_layers().size());
4440*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.send_layers().GetAllLayers().size());
4441*d9f75844SAndroid Build Coastguard Worker 
4442*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4443*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4444*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"5"});
4445*d9f75844SAndroid Build Coastguard Worker }
4446*d9f75844SAndroid Build Coastguard Worker 
4447*d9f75844SAndroid Build Coastguard Worker // Removes RIDs that specify a different format than the m= section.
TEST_F(WebRtcSdpTest,TestDeserializeRemovesRidsWithInvalidCodec)4448*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeRemovesRidsWithInvalidCodec) {
4449*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4450*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send pt=121,120\r\n";  // Should remove 121 and keep RID.
4451*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send pt=121\r\n";      // Should remove RID altogether.
4452*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1;2\r\n";
4453*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4454*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4455*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4456*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4457*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4458*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4459*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4460*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4461*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(simulcast.receive_layers().empty());
4462*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.send_layers().size());
4463*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.send_layers().GetAllLayers().size());
4464*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("1", simulcast.send_layers()[0][0].rid);
4465*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, media->streams().size());
4466*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4467*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, rids.size());
4468*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ("1", rids[0].rid);
4469*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, rids[0].payload_types.size());
4470*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(120, rids[0].payload_types[0]);
4471*d9f75844SAndroid Build Coastguard Worker }
4472*d9f75844SAndroid Build Coastguard Worker 
4473*d9f75844SAndroid Build Coastguard Worker // Ignores duplicate rid lines
TEST_F(WebRtcSdpTest,TestDeserializeIgnoresDuplicateRidLines)4474*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeIgnoresDuplicateRidLines) {
4475*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4476*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4477*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4478*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4479*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 send\r\n";
4480*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4 recv\r\n";
4481*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1,2;3 recv 4\r\n";
4482*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4483*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4484*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4485*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4486*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4487*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4488*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4489*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4490*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().size());
4491*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.receive_layers().size());
4492*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().GetAllLayers().size());
4493*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1ul, simulcast.receive_layers().GetAllLayers().size());
4494*d9f75844SAndroid Build Coastguard Worker 
4495*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4496*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4497*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "3"});
4498*d9f75844SAndroid Build Coastguard Worker }
4499*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,TestDeserializeRidSendDirection)4500*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeRidSendDirection) {
4501*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4502*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 recv\r\n";
4503*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 recv\r\n";
4504*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1;2\r\n";
4505*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4506*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4507*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4508*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4509*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4510*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4511*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->HasSimulcast());
4512*d9f75844SAndroid Build Coastguard Worker }
4513*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,TestDeserializeRidRecvDirection)4514*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeRidRecvDirection) {
4515*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4516*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4517*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4518*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:recv 1;2\r\n";
4519*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4520*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4521*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4522*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4523*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4524*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4525*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->HasSimulcast());
4526*d9f75844SAndroid Build Coastguard Worker }
4527*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,TestDeserializeIgnoresWrongRidDirectionLines)4528*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, TestDeserializeIgnoresWrongRidDirectionLines) {
4529*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kUnifiedPlanSdpFullStringNoSsrc;
4530*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:1 send\r\n";
4531*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:2 send\r\n";
4532*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:3 send\r\n";
4533*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:4 recv\r\n";
4534*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:5 recv\r\n";
4535*d9f75844SAndroid Build Coastguard Worker   sdp += "a=rid:6 recv\r\n";
4536*d9f75844SAndroid Build Coastguard Worker   sdp += "a=simulcast:send 1;5;3 recv 4;2;6\r\n";
4537*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4538*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4539*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4540*d9f75844SAndroid Build Coastguard Worker   const cricket::ContentInfos& contents = output.description()->contents();
4541*d9f75844SAndroid Build Coastguard Worker   const cricket::MediaContentDescription* media =
4542*d9f75844SAndroid Build Coastguard Worker       contents.back().media_description();
4543*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(media->HasSimulcast());
4544*d9f75844SAndroid Build Coastguard Worker   const SimulcastDescription& simulcast = media->simulcast_description();
4545*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().size());
4546*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.receive_layers().size());
4547*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.send_layers().GetAllLayers().size());
4548*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2ul, simulcast.receive_layers().GetAllLayers().size());
4549*d9f75844SAndroid Build Coastguard Worker 
4550*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(media->streams().empty());
4551*d9f75844SAndroid Build Coastguard Worker   const std::vector<RidDescription>& rids = media->streams()[0].rids();
4552*d9f75844SAndroid Build Coastguard Worker   CompareRidDescriptionIds(rids, {"1", "3"});
4553*d9f75844SAndroid Build Coastguard Worker }
4554*d9f75844SAndroid Build Coastguard Worker 
4555*d9f75844SAndroid Build Coastguard Worker // Simulcast serialization integration test.
4556*d9f75844SAndroid Build Coastguard Worker // This test will serialize and deserialize the description and compare.
4557*d9f75844SAndroid Build Coastguard Worker // More detailed tests for parsing simulcast can be found in
4558*d9f75844SAndroid Build Coastguard Worker // unit tests for SdpSerializer.
TEST_F(WebRtcSdpTest,SerializeSimulcast_ComplexSerialization)4559*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeSimulcast_ComplexSerialization) {
4560*d9f75844SAndroid Build Coastguard Worker   MakeUnifiedPlanDescription(/* use_ssrcs = */ false);
4561*d9f75844SAndroid Build Coastguard Worker   auto description = jdesc_.description();
4562*d9f75844SAndroid Build Coastguard Worker   auto media = description->GetContentDescriptionByName(kVideoContentName3);
4563*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(media->streams().size(), 1ul);
4564*d9f75844SAndroid Build Coastguard Worker   StreamParams& send_stream = media->mutable_streams()[0];
4565*d9f75844SAndroid Build Coastguard Worker   std::vector<RidDescription> send_rids;
4566*d9f75844SAndroid Build Coastguard Worker   send_rids.push_back(RidDescription("1", RidDirection::kSend));
4567*d9f75844SAndroid Build Coastguard Worker   send_rids.push_back(RidDescription("2", RidDirection::kSend));
4568*d9f75844SAndroid Build Coastguard Worker   send_rids.push_back(RidDescription("3", RidDirection::kSend));
4569*d9f75844SAndroid Build Coastguard Worker   send_rids.push_back(RidDescription("4", RidDirection::kSend));
4570*d9f75844SAndroid Build Coastguard Worker   send_stream.set_rids(send_rids);
4571*d9f75844SAndroid Build Coastguard Worker   std::vector<RidDescription> receive_rids;
4572*d9f75844SAndroid Build Coastguard Worker   receive_rids.push_back(RidDescription("5", RidDirection::kReceive));
4573*d9f75844SAndroid Build Coastguard Worker   receive_rids.push_back(RidDescription("6", RidDirection::kReceive));
4574*d9f75844SAndroid Build Coastguard Worker   receive_rids.push_back(RidDescription("7", RidDirection::kReceive));
4575*d9f75844SAndroid Build Coastguard Worker   media->set_receive_rids(receive_rids);
4576*d9f75844SAndroid Build Coastguard Worker 
4577*d9f75844SAndroid Build Coastguard Worker   SimulcastDescription& simulcast = media->simulcast_description();
4578*d9f75844SAndroid Build Coastguard Worker   simulcast.send_layers().AddLayerWithAlternatives(
4579*d9f75844SAndroid Build Coastguard Worker       {SimulcastLayer("2", false), SimulcastLayer("1", true)});
4580*d9f75844SAndroid Build Coastguard Worker   simulcast.send_layers().AddLayerWithAlternatives(
4581*d9f75844SAndroid Build Coastguard Worker       {SimulcastLayer("4", false), SimulcastLayer("3", false)});
4582*d9f75844SAndroid Build Coastguard Worker   simulcast.receive_layers().AddLayer({SimulcastLayer("5", false)});
4583*d9f75844SAndroid Build Coastguard Worker   simulcast.receive_layers().AddLayer({SimulcastLayer("6", false)});
4584*d9f75844SAndroid Build Coastguard Worker   simulcast.receive_layers().AddLayer({SimulcastLayer("7", false)});
4585*d9f75844SAndroid Build Coastguard Worker 
4586*d9f75844SAndroid Build Coastguard Worker   TestSerialize(jdesc_);
4587*d9f75844SAndroid Build Coastguard Worker }
4588*d9f75844SAndroid Build Coastguard Worker 
4589*d9f75844SAndroid Build Coastguard Worker // Test that the content name is empty if the media section does not have an
4590*d9f75844SAndroid Build Coastguard Worker // a=mid line.
TEST_F(WebRtcSdpTest,ParseNoMid)4591*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseNoMid) {
4592*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4593*d9f75844SAndroid Build Coastguard Worker   Replace("a=mid:audio_content_name\r\n", "", &sdp);
4594*d9f75844SAndroid Build Coastguard Worker   Replace("a=mid:video_content_name\r\n", "", &sdp);
4595*d9f75844SAndroid Build Coastguard Worker 
4596*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4597*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4598*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4599*d9f75844SAndroid Build Coastguard Worker 
4600*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(output.description()->contents(),
4601*d9f75844SAndroid Build Coastguard Worker               ElementsAre(Field("name", &cricket::ContentInfo::name, ""),
4602*d9f75844SAndroid Build Coastguard Worker                           Field("name", &cricket::ContentInfo::name, "")));
4603*d9f75844SAndroid Build Coastguard Worker }
4604*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,SerializeWithDefaultSctpProtocol)4605*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SerializeWithDefaultSctpProtocol) {
4606*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(false);  // Don't use sctpmap
4607*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jsep_desc(kDummyType);
4608*d9f75844SAndroid Build Coastguard Worker   MakeDescriptionWithoutCandidates(&jsep_desc);
4609*d9f75844SAndroid Build Coastguard Worker   std::string message = webrtc::SdpSerialize(jsep_desc);
4610*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(std::string::npos,
4611*d9f75844SAndroid Build Coastguard Worker             message.find(cricket::kMediaProtocolUdpDtlsSctp));
4612*d9f75844SAndroid Build Coastguard Worker }
4613*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeWithAllSctpProtocols)4614*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeWithAllSctpProtocols) {
4615*d9f75844SAndroid Build Coastguard Worker   AddSctpDataChannel(false);
4616*d9f75844SAndroid Build Coastguard Worker   std::string protocols[] = {cricket::kMediaProtocolDtlsSctp,
4617*d9f75844SAndroid Build Coastguard Worker                              cricket::kMediaProtocolUdpDtlsSctp,
4618*d9f75844SAndroid Build Coastguard Worker                              cricket::kMediaProtocolTcpDtlsSctp};
4619*d9f75844SAndroid Build Coastguard Worker   for (const auto& protocol : protocols) {
4620*d9f75844SAndroid Build Coastguard Worker     sctp_desc_->set_protocol(protocol);
4621*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jsep_desc(kDummyType);
4622*d9f75844SAndroid Build Coastguard Worker     MakeDescriptionWithoutCandidates(&jsep_desc);
4623*d9f75844SAndroid Build Coastguard Worker     std::string message = webrtc::SdpSerialize(jsep_desc);
4624*d9f75844SAndroid Build Coastguard Worker     EXPECT_NE(std::string::npos, message.find(protocol));
4625*d9f75844SAndroid Build Coastguard Worker     JsepSessionDescription jsep_output(kDummyType);
4626*d9f75844SAndroid Build Coastguard Worker     SdpParseError error;
4627*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(webrtc::SdpDeserialize(message, &jsep_output, &error));
4628*d9f75844SAndroid Build Coastguard Worker   }
4629*d9f75844SAndroid Build Coastguard Worker }
4630*d9f75844SAndroid Build Coastguard Worker 
4631*d9f75844SAndroid Build Coastguard Worker // According to https://tools.ietf.org/html/rfc5576#section-6.1, the CNAME
4632*d9f75844SAndroid Build Coastguard Worker // attribute is mandatory, but we relax that restriction.
TEST_F(WebRtcSdpTest,DeserializeSessionDescriptionWithoutCname)4633*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCname) {
4634*d9f75844SAndroid Build Coastguard Worker   std::string sdp_without_cname = kSdpFullString;
4635*d9f75844SAndroid Build Coastguard Worker   Replace("a=ssrc:1 cname:stream_1_cname\r\n", "", &sdp_without_cname);
4636*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription new_jdesc(kDummyType);
4637*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp_without_cname, &new_jdesc));
4638*d9f75844SAndroid Build Coastguard Worker 
4639*d9f75844SAndroid Build Coastguard Worker   audio_desc_->mutable_streams()[0].cname = "";
4640*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(),
4641*d9f75844SAndroid Build Coastguard Worker                                 jdesc_.session_version()));
4642*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CompareSessionDescription(jdesc_, new_jdesc));
4643*d9f75844SAndroid Build Coastguard Worker }
4644*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DeserializeSdpWithUnsupportedMediaType)4645*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DeserializeSdpWithUnsupportedMediaType) {
4646*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpSessionString;
4647*d9f75844SAndroid Build Coastguard Worker   sdp +=
4648*d9f75844SAndroid Build Coastguard Worker       "m=bogus 9 RTP/SAVPF 0 8\r\n"
4649*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4650*d9f75844SAndroid Build Coastguard Worker       "a=mid:bogusmid\r\n";
4651*d9f75844SAndroid Build Coastguard Worker   sdp +=
4652*d9f75844SAndroid Build Coastguard Worker       "m=audio/something 9 RTP/SAVPF 0 8\r\n"
4653*d9f75844SAndroid Build Coastguard Worker       "c=IN IP4 0.0.0.0\r\n"
4654*d9f75844SAndroid Build Coastguard Worker       "a=mid:somethingmid\r\n";
4655*d9f75844SAndroid Build Coastguard Worker 
4656*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4657*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output));
4658*d9f75844SAndroid Build Coastguard Worker 
4659*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, jdesc_output.description()->contents().size());
4660*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(nullptr, jdesc_output.description()
4661*d9f75844SAndroid Build Coastguard Worker                          ->contents()[0]
4662*d9f75844SAndroid Build Coastguard Worker                          .media_description()
4663*d9f75844SAndroid Build Coastguard Worker                          ->as_unsupported());
4664*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(nullptr, jdesc_output.description()
4665*d9f75844SAndroid Build Coastguard Worker                          ->contents()[1]
4666*d9f75844SAndroid Build Coastguard Worker                          .media_description()
4667*d9f75844SAndroid Build Coastguard Worker                          ->as_unsupported());
4668*d9f75844SAndroid Build Coastguard Worker 
4669*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jdesc_output.description()->contents()[0].rejected);
4670*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(jdesc_output.description()->contents()[1].rejected);
4671*d9f75844SAndroid Build Coastguard Worker 
4672*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(jdesc_output.description()->contents()[0].name, "bogusmid");
4673*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(jdesc_output.description()->contents()[1].name, "somethingmid");
4674*d9f75844SAndroid Build Coastguard Worker }
4675*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,MediaTypeProtocolMismatch)4676*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, MediaTypeProtocolMismatch) {
4677*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4678*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4679*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4680*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4681*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n";
4682*d9f75844SAndroid Build Coastguard Worker 
4683*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(sdp + "m=audio 9 UDP/DTLS/SCTP 120\r\n"),
4684*d9f75844SAndroid Build Coastguard Worker                      "m=audio");
4685*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(sdp + "m=video 9 UDP/DTLS/SCTP 120\r\n"),
4686*d9f75844SAndroid Build Coastguard Worker                      "m=video");
4687*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(sdp + "m=video 9 SOMETHING 120\r\n"),
4688*d9f75844SAndroid Build Coastguard Worker                      "m=video");
4689*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(sdp + "m=application 9 SOMETHING 120\r\n"),
4690*d9f75844SAndroid Build Coastguard Worker                      "m=application");
4691*d9f75844SAndroid Build Coastguard Worker }
4692*d9f75844SAndroid Build Coastguard Worker 
4693*d9f75844SAndroid Build Coastguard Worker // Regression test for:
4694*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/chromium/issues/detail?id=1171965
TEST_F(WebRtcSdpTest,SctpPortInUnsupportedContent)4695*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, SctpPortInUnsupportedContent) {
4696*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4697*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4698*d9f75844SAndroid Build Coastguard Worker       "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
4699*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4700*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4701*d9f75844SAndroid Build Coastguard Worker       "m=o 1 DTLS/SCTP 5000\r\n"
4702*d9f75844SAndroid Build Coastguard Worker       "a=sctp-port\r\n";
4703*d9f75844SAndroid Build Coastguard Worker 
4704*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4705*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output));
4706*d9f75844SAndroid Build Coastguard Worker }
4707*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,IllegalMidCharacterValue)4708*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, IllegalMidCharacterValue) {
4709*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4710*d9f75844SAndroid Build Coastguard Worker   // [ is an illegal token value.
4711*d9f75844SAndroid Build Coastguard Worker   Replace("a=mid:", "a=mid:[]", &sdp);
4712*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(std::string(sdp), "a=mid:[]");
4713*d9f75844SAndroid Build Coastguard Worker }
4714*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,MaxChannels)4715*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, MaxChannels) {
4716*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4717*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4718*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
4719*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4720*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4721*d9f75844SAndroid Build Coastguard Worker       "m=audio 49232 RTP/AVP 108\r\n"
4722*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 ISAC/16000/512\r\n";
4723*d9f75844SAndroid Build Coastguard Worker 
4724*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(sdp, "a=rtpmap:108 ISAC/16000/512");
4725*d9f75844SAndroid Build Coastguard Worker }
4726*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DuplicateAudioRtpmapWithConflict)4727*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DuplicateAudioRtpmapWithConflict) {
4728*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4729*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4730*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
4731*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4732*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4733*d9f75844SAndroid Build Coastguard Worker       "m=audio 49232 RTP/AVP 108\r\n"
4734*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 ISAC/16000\r\n"
4735*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 G711/16000\r\n";
4736*d9f75844SAndroid Build Coastguard Worker 
4737*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(sdp, "a=rtpmap:108 G711/16000");
4738*d9f75844SAndroid Build Coastguard Worker }
4739*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,DuplicateVideoRtpmapWithConflict)4740*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, DuplicateVideoRtpmapWithConflict) {
4741*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4742*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4743*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
4744*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4745*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4746*d9f75844SAndroid Build Coastguard Worker       "m=video 49232 RTP/AVP 108\r\n"
4747*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 VP8/90000\r\n"
4748*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 VP9/90000\r\n";
4749*d9f75844SAndroid Build Coastguard Worker 
4750*d9f75844SAndroid Build Coastguard Worker   ExpectParseFailure(sdp, "a=rtpmap:108 VP9/90000");
4751*d9f75844SAndroid Build Coastguard Worker }
4752*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,FmtpBeforeRtpMap)4753*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, FmtpBeforeRtpMap) {
4754*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4755*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4756*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
4757*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4758*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4759*d9f75844SAndroid Build Coastguard Worker       "m=video 49232 RTP/AVP 108\r\n"
4760*d9f75844SAndroid Build Coastguard Worker       "a=fmtp:108 profile-level=1\r\n"
4761*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:108 VP9/90000\r\n";
4762*d9f75844SAndroid Build Coastguard Worker 
4763*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4764*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output));
4765*d9f75844SAndroid Build Coastguard Worker }
4766*d9f75844SAndroid Build Coastguard Worker 
TEST_F(WebRtcSdpTest,StaticallyAssignedPayloadTypeWithDifferentCasing)4767*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, StaticallyAssignedPayloadTypeWithDifferentCasing) {
4768*d9f75844SAndroid Build Coastguard Worker   std::string sdp =
4769*d9f75844SAndroid Build Coastguard Worker       "v=0\r\n"
4770*d9f75844SAndroid Build Coastguard Worker       "o=- 11 22 IN IP4 127.0.0.1\r\n"
4771*d9f75844SAndroid Build Coastguard Worker       "s=-\r\n"
4772*d9f75844SAndroid Build Coastguard Worker       "t=0 0\r\n"
4773*d9f75844SAndroid Build Coastguard Worker       "m=audio 49232 RTP/AVP 18\r\n"
4774*d9f75844SAndroid Build Coastguard Worker       // Casing differs from statically assigned type, this should
4775*d9f75844SAndroid Build Coastguard Worker       // still be accepted.
4776*d9f75844SAndroid Build Coastguard Worker       "a=rtpmap:18 g729/8000\r\n";
4777*d9f75844SAndroid Build Coastguard Worker 
4778*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription jdesc_output(kDummyType);
4779*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output));
4780*d9f75844SAndroid Build Coastguard Worker }
4781*d9f75844SAndroid Build Coastguard Worker 
4782*d9f75844SAndroid Build Coastguard Worker // This tests parsing of SDP with unknown ssrc-specific attributes.
TEST_F(WebRtcSdpTest,ParseIgnoreUnknownSsrcSpecificAttribute)4783*d9f75844SAndroid Build Coastguard Worker TEST_F(WebRtcSdpTest, ParseIgnoreUnknownSsrcSpecificAttribute) {
4784*d9f75844SAndroid Build Coastguard Worker   std::string sdp = kSdpString;
4785*d9f75844SAndroid Build Coastguard Worker   sdp += "a=ssrc:1 mslabel:something\r\n";
4786*d9f75844SAndroid Build Coastguard Worker 
4787*d9f75844SAndroid Build Coastguard Worker   JsepSessionDescription output(kDummyType);
4788*d9f75844SAndroid Build Coastguard Worker   SdpParseError error;
4789*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
4790*d9f75844SAndroid Build Coastguard Worker }
4791