3
* Copyright 2011, Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
#include "talk/app/webrtc/jsepsessiondescription.h"
31
#include "talk/app/webrtc/webrtcsdp.h"
32
#include "talk/base/gunit.h"
33
#include "talk/base/logging.h"
34
#include "talk/base/scoped_ptr.h"
35
#include "talk/base/stringencode.h"
36
#include "talk/base/stringutils.h"
37
#include "talk/p2p/base/constants.h"
38
#include "talk/session/phone/mediasession.h"
40
typedef std::vector<cricket::Candidate> Candidates;
41
using cricket::AudioCodec;
42
using cricket::AudioContentDescription;
43
using cricket::ContentInfo;
44
using cricket::CryptoParams;
45
using cricket::ContentGroup;
46
using cricket::SessionDescription;
47
using cricket::StreamParams;
48
using cricket::VideoCodec;
49
using cricket::VideoContentDescription;
50
using webrtc::IceCandidateColletion;
51
using webrtc::IceCandidateInterface;
52
using webrtc::JsepIceCandidate;
53
using webrtc::JsepSessionDescription;
54
using webrtc::SessionDescriptionInterface;
56
// Reference sdp string
57
static const char kSdpFullString[] =
59
"o=- 0 0 IN IP4 127.0.0.1\r\n"
62
"m=audio 2345 RTP/AVPF 103 104\r\n"
63
"c=IN IP4 74.125.127.126\r\n"
64
"a=rtcp:2346 IN IP4 74.125.127.126\r\n"
65
"a=candidate:1 1 udp 1 127.0.0.1 1234 typ host name rtp_audio "
66
"network_name eth0 username user_rtp password password_rtp "
68
"a=candidate:1 2 udp 1 127.0.0.1 1235 typ host name rtcp_audio "
69
"network_name eth0 username user_rtcp password password_rtcp "
71
"a=candidate:1 1 udp 1 74.125.127.126 2345 typ srflx name rtp_audio "
72
"network_name eth0 username user_rtp_stun password password_rtp_stun "
74
"a=candidate:1 2 udp 1 74.125.127.126 2346 typ srflx name rtcp_audio "
75
"network_name eth0 username user_rtcp_stun password password_rtcp_stun "
77
"a=mid:audio_content_name\r\n"
79
"a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
80
"inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 \r\n"
81
"a=rtpmap:103 ISAC/16000\r\n"
82
"a=rtpmap:104 ISAC/32000\r\n"
83
"a=ssrc:1 cname:stream_1_cname\r\n"
84
"a=ssrc:1 mslabel:local_stream_1\r\n"
85
"a=ssrc:1 label:local_audio_1\r\n"
86
"a=ssrc:4 cname:stream_2_cname\r\n"
87
"a=ssrc:4 mslabel:local_stream_2\r\n"
88
"a=ssrc:4 label:local_audio_2\r\n"
89
"m=video 3457 RTP/AVPF 120\r\n"
90
"c=IN IP4 74.125.224.39\r\n"
91
"a=rtcp:3456 IN IP4 74.125.224.39\r\n"
92
"a=candidate:1 2 udp 1 127.0.0.1 1236 typ host name rtcp_video "
93
"network_name eth0 username user_video_rtcp password password_video_rtcp "
95
"a=candidate:1 1 udp 1 127.0.0.1 1237 typ host name rtp_video "
96
"network_name eth0 username user_video_rtp password password_video_rtp "
98
"a=candidate:1 2 udp 1 74.125.224.39 3456 typ relay name rtcp_video "
99
"network_name eth0 username user_video_rtcp_relay password "
100
"password_video_rtcp generation 0\r\n"
101
"a=candidate:1 1 udp 1 74.125.224.39 3457 typ relay name rtp_video "
102
"network_name eth0 username user_video_rtp_relay password "
103
"password_video_rtp generation 0\r\n"
104
"a=mid:video_content_name\r\n"
105
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
106
"inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32 \r\n"
107
"a=rtpmap:120 VP8/90000\r\n"
108
"a=ssrc:2 cname:stream_1_cname\r\n"
109
"a=ssrc:2 mslabel:local_stream_1\r\n"
110
"a=ssrc:2 label:local_video_1\r\n"
111
"a=ssrc:3 cname:stream_1_cname\r\n"
112
"a=ssrc:3 mslabel:local_stream_1\r\n"
113
"a=ssrc:3 label:local_video_2\r\n"
114
"a=ssrc:5 cname:stream_2_cname\r\n"
115
"a=ssrc:5 mslabel:local_stream_2\r\n"
116
"a=ssrc:5 label:local_video_3\r\n";
118
// SDP reference string without the candidates.
119
static const char kSdpString[] =
121
"o=- 0 0 IN IP4 127.0.0.1\r\n"
124
"m=audio 1 RTP/AVPF 103 104\r\n"
125
"a=mid:audio_content_name\r\n"
127
"a=crypto:1 AES_CM_128_HMAC_SHA1_32 "
128
"inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 \r\n"
129
"a=rtpmap:103 ISAC/16000\r\n"
130
"a=rtpmap:104 ISAC/32000\r\n"
131
"a=ssrc:1 cname:stream_1_cname\r\n"
132
"a=ssrc:1 mslabel:local_stream_1\r\n"
133
"a=ssrc:1 label:local_audio_1\r\n"
134
"a=ssrc:4 cname:stream_2_cname\r\n"
135
"a=ssrc:4 mslabel:local_stream_2\r\n"
136
"a=ssrc:4 label:local_audio_2\r\n"
137
"m=video 1 RTP/AVPF 120\r\n"
138
"a=mid:video_content_name\r\n"
139
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
140
"inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32 \r\n"
141
"a=rtpmap:120 VP8/90000\r\n"
142
"a=ssrc:2 cname:stream_1_cname\r\n"
143
"a=ssrc:2 mslabel:local_stream_1\r\n"
144
"a=ssrc:2 label:local_video_1\r\n"
145
"a=ssrc:3 cname:stream_1_cname\r\n"
146
"a=ssrc:3 mslabel:local_stream_1\r\n"
147
"a=ssrc:3 label:local_video_2\r\n"
148
"a=ssrc:5 cname:stream_2_cname\r\n"
149
"a=ssrc:5 mslabel:local_stream_2\r\n"
150
"a=ssrc:5 label:local_video_3\r\n";
152
// One candidate reference string.
153
static const char kSdpOneCandidate[] =
154
"a=candidate:1 1 udp 1 127.0.0.1 1234 typ host name rtp_audio network_name"
155
" eth0 username user_rtp password password_rtp generation 0\r\n";
157
// Candidates reference string.
158
static const char kSdpCandidates[] =
159
"a=candidate:1 1 udp 1 127.0.0.1 1234 typ host name rtp_audio network_name"
160
" eth0 username user_rtp password password_rtp generation 0\r\n"
161
"a=candidate:1 2 udp 1 127.0.0.1 1235 typ host name rtcp_audio "
162
"network_name eth0 username user_rtcp password password_rtcp "
164
"a=candidate:1 1 udp 1 74.125.127.126 2345 typ srflx name rtp_audio "
165
"network_name eth0 username user_rtp_stun password password_rtp_stun "
167
"a=candidate:1 2 udp 1 74.125.127.126 2346 typ srflx name rtcp_audio "
168
"network_name eth0 username user_rtcp_stun password password_rtcp_stun "
170
"a=candidate:1 2 udp 1 127.0.0.1 1236 typ host name rtcp_video "
171
"network_name eth0 username user_video_rtcp password password_video_rtcp "
173
"a=candidate:1 1 udp 1 127.0.0.1 1237 typ host name rtp_video "
174
"network_name eth0 username user_video_rtp password password_video_rtp "
176
"a=candidate:1 2 udp 1 74.125.224.39 3456 typ relay name rtcp_video "
177
"network_name eth0 username user_video_rtcp_relay password "
178
"password_video_rtcp generation 0\r\n"
179
"a=candidate:1 1 udp 1 74.125.224.39 3457 typ relay name rtp_video "
180
"network_name eth0 username user_video_rtp_relay password "
181
"password_video_rtp generation 0\r\n";
184
static const char kAudioContentName[] = "audio_content_name";
185
static const char kVideoContentName[] = "video_content_name";
188
static const char kStreamLabel1[] = "local_stream_1";
189
static const char kStream1Cname[] = "stream_1_cname";
190
static const char kAudioTrackLabel1[] = "local_audio_1";
191
static const uint32 kAudioTrack1Ssrc = 1;
192
static const char kVideoTrackLabel1[] = "local_video_1";
193
static const uint32 kVideoTrack1Ssrc = 2;
194
static const char kVideoTrackLabel2[] = "local_video_2";
195
static const uint32 kVideoTrack2Ssrc = 3;
198
static const char kStreamLabel2[] = "local_stream_2";
199
static const char kStream2Cname[] = "stream_2_cname";
200
static const char kAudioTrackLabel2[] = "local_audio_2";
201
static const uint32 kAudioTrack2Ssrc = 4;
202
static const char kVideoTrackLabel3[] = "local_video_3";
203
static const uint32 kVideoTrack3Ssrc = 5;
207
// Add some extra |newlines| to the |message| after |line|.
208
void InjectAfter(const std::string& line,
209
const std::string& newlines,
210
std::string* message) {
211
const std::string tmp = line + newlines;
212
talk_base::replace_substrs(line.c_str(), line.length(),
213
tmp.c_str(), tmp.length(), message);
218
class WebRtcSdpTest : public testing::Test {
221
// AudioContentDescription
222
talk_base::scoped_ptr<AudioContentDescription> audio(
223
new AudioContentDescription());
224
audio->set_rtcp_mux(true);
225
StreamParams audio_stream1;
226
audio_stream1.name = kAudioTrackLabel1;
227
audio_stream1.cname = kStream1Cname;
228
audio_stream1.sync_label = kStreamLabel1;
229
audio_stream1.ssrcs.push_back(kAudioTrack1Ssrc);
230
audio->AddStream(audio_stream1);
231
StreamParams audio_stream2;
232
audio_stream2.name = kAudioTrackLabel2;
233
audio_stream2.cname = kStream2Cname;
234
audio_stream2.sync_label = kStreamLabel2;
235
audio_stream2.ssrcs.push_back(kAudioTrack2Ssrc);
236
audio->AddStream(audio_stream2);
237
audio->AddCrypto(CryptoParams(1, "AES_CM_128_HMAC_SHA1_32",
238
"inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32", ""));
239
audio->AddCodec(AudioCodec(103, "ISAC", 16000, 0, 0, 0));
240
audio->AddCodec(AudioCodec(104, "ISAC", 32000, 0, 0, 0));
241
desc_.AddContent(kAudioContentName, cricket::NS_JINGLE_RTP,
244
// VideoContentDescription
245
talk_base::scoped_ptr<VideoContentDescription> video(
246
new VideoContentDescription());
247
StreamParams video_stream1;
248
video_stream1.name = kVideoTrackLabel1;
249
video_stream1.cname = kStream1Cname;
250
video_stream1.sync_label = kStreamLabel1;
251
video_stream1.ssrcs.push_back(kVideoTrack1Ssrc);
252
video->AddStream(video_stream1);
253
StreamParams video_stream2;
254
video_stream2.name = kVideoTrackLabel2;
255
video_stream2.cname = kStream1Cname;
256
video_stream2.sync_label = kStreamLabel1;
257
video_stream2.ssrcs.push_back(kVideoTrack2Ssrc);
258
video->AddStream(video_stream2);
259
StreamParams video_stream3;
260
video_stream3.name = kVideoTrackLabel3;
261
video_stream3.cname = kStream2Cname;
262
video_stream3.sync_label = kStreamLabel2;
263
video_stream3.ssrcs.push_back(kVideoTrack3Ssrc);
264
video->AddStream(video_stream3);
265
video->AddCrypto(CryptoParams(1, "AES_CM_128_HMAC_SHA1_80",
266
"inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32", ""));
267
video->AddCodec(VideoCodec(120, "VP8", 640, 480, 30, 0));
268
desc_.AddContent(kVideoContentName, cricket::NS_JINGLE_RTP,
273
talk_base::SocketAddress address("127.0.0.1", port++);
274
cricket::Candidate candidate1("rtp_audio", "udp", address, 1,
275
"user_rtp", "password_rtp", "local", "eth0", 0);
276
address.SetPort(port++);
277
cricket::Candidate candidate2("rtcp_audio", "udp", address, 1,
278
"user_rtcp", "password_rtcp", "local", "eth0", 0);
279
address.SetPort(port++);
280
cricket::Candidate candidate3("rtcp_video", "udp", address, 1,
281
"user_video_rtcp", "password_video_rtcp", "local", "eth0", 0);
282
address.SetPort(port++);
283
cricket::Candidate candidate4("rtp_video", "udp", address, 1,
284
"user_video_rtp", "password_video_rtp", "local", "eth0", 0);
287
int port_stun = 2345;
288
talk_base::SocketAddress address_stun("74.125.127.126", port_stun++);
289
cricket::Candidate candidate5("rtp_audio", "udp", address_stun, 1,
290
"user_rtp_stun", "password_rtp_stun", "stun", "eth0", 0);
291
address_stun.SetPort(port_stun++);
292
cricket::Candidate candidate6("rtcp_audio", "udp", address_stun, 1,
293
"user_rtcp_stun", "password_rtcp_stun", "stun", "eth0", 0);
296
int port_relay = 3456;
297
talk_base::SocketAddress address_relay("74.125.224.39", port_relay++);
298
cricket::Candidate candidate7("rtcp_video", "udp", address_relay, 1,
299
"user_video_rtcp_relay", "password_video_rtcp", "relay", "eth0", 0);
300
address_relay.SetPort(port_relay++);
301
cricket::Candidate candidate8("rtp_video", "udp", address_relay, 1,
302
"user_video_rtp_relay", "password_video_rtp", "relay", "eth0", 0);
305
candidates_.push_back(candidate1);
306
candidates_.push_back(candidate2);
307
candidates_.push_back(candidate5);
308
candidates_.push_back(candidate6);
311
candidates_.push_back(candidate3);
312
candidates_.push_back(candidate4);
313
candidates_.push_back(candidate7);
314
candidates_.push_back(candidate8);
316
jcandidate_.reset(new JsepIceCandidate("1", candidate1));
318
// Set up JsepSessionDescription.
319
jdesc_.SetDescription(desc_.Copy());
321
for (size_t i = 0; i< candidates_.size(); ++i) {
322
// In this test, the audio m line index will be 0, and the video m line
324
mline_index = (candidates_.at(i).name().find("video") !=
325
std::string::npos) ? 1 : 0;
326
JsepIceCandidate jice(talk_base::ToString<int>(mline_index),
328
jdesc_.AddCandidate(&jice);
332
bool CompareSessionDescription(const SessionDescription& desc1,
333
const SessionDescription& desc2) {
334
const ContentInfo* ac1 = GetFirstAudioContent(&desc1);
335
const AudioContentDescription* acd1 =
336
static_cast<const AudioContentDescription*>(ac1->description);
337
const ContentInfo* vc1 = GetFirstVideoContent(&desc1);
338
const VideoContentDescription* vcd1 =
339
static_cast<const VideoContentDescription*>(vc1->description);
341
const ContentInfo* ac2 = GetFirstAudioContent(&desc2);
342
const AudioContentDescription* acd2 =
343
static_cast<const AudioContentDescription*>(ac2->description);
344
const ContentInfo* vc2 = GetFirstVideoContent(&desc2);
345
const VideoContentDescription* vcd2 =
346
static_cast<const VideoContentDescription*>(vc2->description);
349
EXPECT_EQ(ac1->name, ac2->name);
350
EXPECT_EQ(vc1->name, vc2->name);
353
EXPECT_EQ(ac1->type, ac2->type);
354
EXPECT_EQ(vc1->type, vc2->type);
357
EXPECT_EQ(acd1->rtcp_mux(), acd2->rtcp_mux());
358
EXPECT_EQ(vcd1->rtcp_mux(), vcd2->rtcp_mux());
361
EXPECT_EQ(acd1->cryptos().size(), acd2->cryptos().size());
362
EXPECT_EQ(vcd1->cryptos().size(), vcd2->cryptos().size());
363
if (acd1->cryptos().size() != acd2->cryptos().size() ||
364
vcd1->cryptos().size() != vcd2->cryptos().size()) {
367
for (size_t i = 0; i< acd1->cryptos().size(); ++i) {
368
const CryptoParams c1 = acd1->cryptos().at(i);
369
const CryptoParams c2 = acd2->cryptos().at(i);
370
EXPECT_TRUE(c1.Matches(c2));
372
for (size_t i = 0; i< vcd1->cryptos().size(); ++i) {
373
const CryptoParams c1 = vcd1->cryptos().at(i);
374
const CryptoParams c2 = vcd2->cryptos().at(i);
375
EXPECT_TRUE(c1.Matches(c2));
379
EXPECT_EQ(acd1->codecs().size(), acd2->codecs().size());
380
if (acd1->codecs().size() != acd2->codecs().size())
382
EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
383
if (vcd1->codecs().size() != vcd2->codecs().size())
385
for (size_t i = 0; i< acd1->codecs().size(); ++i) {
386
const AudioCodec c1 = acd1->codecs().at(i);
387
const AudioCodec c2 = acd2->codecs().at(i);
388
EXPECT_TRUE(c1.Matches(c2));
390
for (size_t i = 0; i< vcd1->codecs().size(); ++i) {
391
const VideoCodec c1 = vcd1->codecs().at(i);
392
const VideoCodec c2 = vcd2->codecs().at(i);
393
EXPECT_TRUE(c1.Matches(c2));
394
EXPECT_EQ(c1.id, c2.id);
395
EXPECT_EQ(c1.width, c2.width);
396
EXPECT_EQ(c1.height, c2.height);
397
EXPECT_EQ(c1.framerate, c2.framerate);
401
EXPECT_EQ(acd1->streams(), acd2->streams());
402
EXPECT_EQ(vcd1->streams(), vcd2->streams());
405
const cricket::ContentGroups groups1 = desc1.groups();
406
const cricket::ContentGroups groups2 = desc2.groups();
407
EXPECT_EQ(groups1.size(), groups1.size());
408
if (groups1.size() != groups2.size()) {
411
for (size_t i = 0; i < groups1.size(); ++i) {
412
const cricket::ContentGroup group1 = groups1.at(i);
413
const cricket::ContentGroup group2 = groups2.at(i);
414
EXPECT_EQ(group1.semantics(), group2.semantics());
415
const std::set<std::string> content1 = group1.content_types();
416
const std::set<std::string> content2 = group2.content_types();
417
EXPECT_EQ(content1.size(), content2.size());
418
if (content1.size() != content2.size()) {
421
std::set<std::string>::const_iterator iter1 = content1.begin();
422
std::set<std::string>::const_iterator iter2 = content2.begin();
423
while (iter1 != content1.end()) {
424
EXPECT_EQ(*iter1++, *iter2++);
431
bool CompareCandidates(const Candidates& cs1, const Candidates& cs2) {
432
EXPECT_EQ(cs1.size(), cs2.size());
433
if (cs1.size() != cs2.size())
435
for (size_t i = 0; i< cs1.size(); ++i) {
436
const cricket::Candidate c1 = cs1.at(i);
437
const cricket::Candidate c2 = cs2.at(i);
438
EXPECT_TRUE(c1.IsEquivalent(c2));
443
bool CompareSessionDescriptionInterface(
444
const SessionDescriptionInterface& desci1,
445
const SessionDescriptionInterface& desci2) {
446
EXPECT_TRUE(CompareSessionDescription(*desci1.description(),
447
*desci2.description()));
448
if (desci1.number_of_mediasections() != desci2.number_of_mediasections())
450
for (size_t i = 0; i < desci1.number_of_mediasections(); ++i) {
451
const IceCandidateColletion* cc1 = desci1.candidates(i);
452
const IceCandidateColletion* cc2 = desci2.candidates(i);
453
if (cc1->count() != cc2->count())
455
for (size_t j = 0; j < cc1->count(); ++j) {
456
const IceCandidateInterface* c1 = cc1->at(j);
457
const IceCandidateInterface* c2 = cc2->at(j);
458
EXPECT_EQ(c1->label(), c2->label());
459
EXPECT_TRUE(c1->candidate().IsEquivalent(c2->candidate()));
465
bool ReplaceAndTryToParse(const char* search, const char* replace) {
466
JsepSessionDescription desc;
467
std::string sdp = kSdpFullString;
468
talk_base::replace_substrs(search, strlen(search), replace,
469
strlen(replace), &sdp);
470
return webrtc::SdpDeserialize(sdp, &desc);
474
SessionDescription desc_;
475
Candidates candidates_;
476
talk_base::scoped_ptr<IceCandidateInterface> jcandidate_;
477
JsepSessionDescription jdesc_;
480
TEST_F(WebRtcSdpTest, SerializeSessionDescriptionInterface) {
481
// JsepSessionDescription with desc and candidates.
482
std::string message = webrtc::SdpSerialize(jdesc_);
483
EXPECT_EQ(std::string(kSdpFullString), message);
486
TEST_F(WebRtcSdpTest, SerializeSessionDescriptionInterfaceEmpty) {
487
JsepSessionDescription jdesc_empty;
488
EXPECT_EQ("", webrtc::SdpSerialize(jdesc_empty));
491
TEST_F(WebRtcSdpTest, SerializeSessionDescriptionInterfaceWithoutCandidates) {
492
// JsepSessionDescription with desc but without candidates.
493
JsepSessionDescription jdesc_no_candidates;
494
jdesc_no_candidates.SetDescription(desc_.Copy());
495
std::string message = webrtc::SdpSerialize(jdesc_no_candidates);
496
EXPECT_EQ(std::string(kSdpString), message);
500
TEST_F(WebRtcSdpTest, SerializeSessionDescriptionInterfaceWithBundle) {
501
ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
502
group.AddContentName(kAudioContentName);
503
group.AddContentName(kVideoContentName);
504
desc_.AddGroup(group);
505
jdesc_.SetDescription(desc_.Copy());
506
std::string message = webrtc::SdpSerialize(jdesc_);
507
std::string sdp_with_bundle = kSdpFullString;
508
InjectAfter("t=0 0\r\n",
509
"a=group:BUNDLE audio_content_name video_content_name\r\n",
511
EXPECT_EQ(sdp_with_bundle, message);
514
TEST_F(WebRtcSdpTest, SerializeCandidates) {
515
std::string message = webrtc::SdpSerializeCandidate(*jcandidate_.get());
516
EXPECT_EQ(std::string(kSdpOneCandidate), message);
519
TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionInterface) {
520
JsepSessionDescription jdesc;
522
EXPECT_TRUE(webrtc::SdpDeserialize(kSdpFullString, &jdesc));
524
EXPECT_TRUE(CompareSessionDescriptionInterface(jdesc_, jdesc));
527
TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionInterfaceWithBundle) {
528
JsepSessionDescription jdesc_with_bundle;
529
std::string sdp_with_bundle = kSdpFullString;
530
InjectAfter("t=0 0\r\n",
531
"a=group:BUNDLE audio_content_name video_content_name\r\n",
533
EXPECT_TRUE(webrtc::SdpDeserialize(sdp_with_bundle, &jdesc_with_bundle));
534
ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
535
group.AddContentName(kAudioContentName);
536
group.AddContentName(kVideoContentName);
537
desc_.AddGroup(group);
538
jdesc_.SetDescription(desc_.Copy());
539
EXPECT_TRUE(CompareSessionDescriptionInterface(jdesc_, jdesc_with_bundle));
542
TEST_F(WebRtcSdpTest, SdpDeserializeCandidate) {
543
const std::string kDummyLabel = "dummy_label";
544
JsepIceCandidate jcandidate(kDummyLabel);
545
EXPECT_TRUE(SdpDeserializeCandidate(kSdpOneCandidate, &jcandidate));
546
EXPECT_EQ(kDummyLabel, jcandidate.label());
547
EXPECT_TRUE(jcandidate.candidate().IsEquivalent(jcandidate_->candidate()));
550
TEST_F(WebRtcSdpTest, DeserializeBrokenSdp) {
551
const char kSdpDestroyer[] = "!@#$%^&";
553
// Broken session description
554
EXPECT_EQ(false, ReplaceAndTryToParse("v=", kSdpDestroyer));
555
EXPECT_EQ(false, ReplaceAndTryToParse("o=", kSdpDestroyer));
556
EXPECT_EQ(false, ReplaceAndTryToParse("s=", kSdpDestroyer));
557
// Broken time description
558
EXPECT_EQ(false, ReplaceAndTryToParse("t=", kSdpDestroyer));
561
EXPECT_EQ(true, ReplaceAndTryToParse("a=group:BUNDLE audio video\r\n", ""));
562
EXPECT_EQ(true, ReplaceAndTryToParse("a=mid:audio\r\n", ""));
563
EXPECT_EQ(true, ReplaceAndTryToParse("a=mid:video\r\n", ""));
565
// Broken media description
566
EXPECT_EQ(true, ReplaceAndTryToParse("video 0 RTP/AVPF", kSdpDestroyer));