blob: 6be590faf4d6a2b15165ab2ed3091cbf1f87c518 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwibergd1fe2812016-04-27 06:47:29 -070011#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012#include <string>
13
Henrik Kjellander15583c12016-02-10 10:53:12 +010014#include "webrtc/api/jsepicecandidate.h"
15#include "webrtc/api/jsepsessiondescription.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000016#include "webrtc/base/gunit.h"
17#include "webrtc/base/helpers.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000018#include "webrtc/base/ssladapter.h"
19#include "webrtc/base/stringencode.h"
kjellandera96e2d72016-02-04 23:52:28 -080020#include "webrtc/p2p/base/candidate.h"
kjellanderf4752772016-03-02 05:42:30 -080021#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/p2p/base/sessiondescription.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010023#include "webrtc/pc/mediasession.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000024
25using webrtc::IceCandidateCollection;
26using webrtc::IceCandidateInterface;
27using webrtc::JsepIceCandidate;
28using webrtc::JsepSessionDescription;
29using webrtc::SessionDescriptionInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
31static const char kCandidateUfrag[] = "ufrag";
32static const char kCandidatePwd[] = "pwd";
33static const char kCandidateUfragVoice[] = "ufrag_voice";
34static const char kCandidatePwdVoice[] = "pwd_voice";
35static const char kCandidateUfragVideo[] = "ufrag_video";
36static const char kCandidatePwdVideo[] = "pwd_video";
37
38// This creates a session description with both audio and video media contents.
39// In SDP this is described by two m lines, one audio and one video.
40static cricket::SessionDescription* CreateCricketSessionDescription() {
41 cricket::SessionDescription* desc(new cricket::SessionDescription());
42 // AudioContentDescription
kwibergd1fe2812016-04-27 06:47:29 -070043 std::unique_ptr<cricket::AudioContentDescription> audio(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044 new cricket::AudioContentDescription());
45
46 // VideoContentDescription
kwibergd1fe2812016-04-27 06:47:29 -070047 std::unique_ptr<cricket::VideoContentDescription> video(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048 new cricket::VideoContentDescription());
49
deadbeef67cf2c12016-04-13 10:07:16 -070050 audio->AddCodec(cricket::AudioCodec(103, "ISAC", 16000, 0, 0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 desc->AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP,
52 audio.release());
53
deadbeef67cf2c12016-04-13 10:07:16 -070054 video->AddCodec(cricket::VideoCodec(120, "VP8", 640, 480, 30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055 desc->AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP,
56 video.release());
57
deadbeef46eed762016-01-28 13:24:37 -080058 EXPECT_TRUE(desc->AddTransportInfo(cricket::TransportInfo(
59 cricket::CN_AUDIO,
60 cricket::TransportDescription(
61 std::vector<std::string>(), kCandidateUfragVoice, kCandidatePwdVoice,
62 cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, NULL))));
63 EXPECT_TRUE(desc->AddTransportInfo(cricket::TransportInfo(
64 cricket::CN_VIDEO,
65 cricket::TransportDescription(
66 std::vector<std::string>(), kCandidateUfragVideo, kCandidatePwdVideo,
67 cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, NULL))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 return desc;
69}
70
71class JsepSessionDescriptionTest : public testing::Test {
72 protected:
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073 virtual void SetUp() {
74 int port = 1234;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000075 rtc::SocketAddress address("127.0.0.1", port++);
guoweis@webrtc.org61c12472015-01-15 06:53:07 +000076 cricket::Candidate candidate(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
77 address, 1, "", "", "local", 0, "1");
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 candidate_ = candidate;
79 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000080 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081 const std::string session_version =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000082 rtc::ToString(rtc::CreateRandomId());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083 jsep_desc_.reset(new JsepSessionDescription("dummy"));
84 ASSERT_TRUE(jsep_desc_->Initialize(CreateCricketSessionDescription(),
85 session_id, session_version));
86 }
87
88 std::string Serialize(const SessionDescriptionInterface* desc) {
89 std::string sdp;
90 EXPECT_TRUE(desc->ToString(&sdp));
91 EXPECT_FALSE(sdp.empty());
92 return sdp;
93 }
94
95 SessionDescriptionInterface* DeSerialize(const std::string& sdp) {
96 JsepSessionDescription* desc(new JsepSessionDescription("dummy"));
97 EXPECT_TRUE(desc->Initialize(sdp, NULL));
98 return desc;
99 }
100
101 cricket::Candidate candidate_;
kwibergd1fe2812016-04-27 06:47:29 -0700102 std::unique_ptr<JsepSessionDescription> jsep_desc_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103};
104
105// Test that number_of_mediasections() returns the number of media contents in
106// a session description.
107TEST_F(JsepSessionDescriptionTest, CheckSessionDescription) {
108 EXPECT_EQ(2u, jsep_desc_->number_of_mediasections());
109}
110
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700111// Test that we can add a candidate to a session description without MID.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112TEST_F(JsepSessionDescriptionTest, AddCandidateWithoutMid) {
113 JsepIceCandidate jsep_candidate("", 0, candidate_);
114 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
115 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(0);
116 ASSERT_TRUE(ice_candidates != NULL);
117 EXPECT_EQ(1u, ice_candidates->count());
118 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
119 ASSERT_TRUE(ice_candidate != NULL);
120 candidate_.set_username(kCandidateUfragVoice);
121 candidate_.set_password(kCandidatePwdVoice);
122 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
123 EXPECT_EQ(0, ice_candidate->sdp_mline_index());
124 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
125}
126
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700127// Test that we can add and remove candidates to a session description with
128// MID. Removing candidates requires MID (transport_name).
129TEST_F(JsepSessionDescriptionTest, AddAndRemoveCandidatesWithMid) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 // mid and m-line index don't match, in this case mid is preferred.
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700131 std::string mid = "video";
132 JsepIceCandidate jsep_candidate(mid, 0, candidate_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
134 EXPECT_EQ(0u, jsep_desc_->candidates(0)->count());
135 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(1);
136 ASSERT_TRUE(ice_candidates != NULL);
137 EXPECT_EQ(1u, ice_candidates->count());
138 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
139 ASSERT_TRUE(ice_candidate != NULL);
140 candidate_.set_username(kCandidateUfragVideo);
141 candidate_.set_password(kCandidatePwdVideo);
142 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
143 // The mline index should have been updated according to mid.
144 EXPECT_EQ(1, ice_candidate->sdp_mline_index());
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700145
146 std::vector<cricket::Candidate> candidates(1, candidate_);
147 candidates[0].set_transport_name(mid);
148 EXPECT_EQ(1u, jsep_desc_->RemoveCandidates(candidates));
149 EXPECT_EQ(0u, jsep_desc_->candidates(0)->count());
150 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151}
152
153TEST_F(JsepSessionDescriptionTest, AddCandidateAlreadyHasUfrag) {
154 candidate_.set_username(kCandidateUfrag);
155 candidate_.set_password(kCandidatePwd);
156 JsepIceCandidate jsep_candidate("audio", 0, candidate_);
157 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
158 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(0);
159 ASSERT_TRUE(ice_candidates != NULL);
160 EXPECT_EQ(1u, ice_candidates->count());
161 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
162 ASSERT_TRUE(ice_candidate != NULL);
163 candidate_.set_username(kCandidateUfrag);
164 candidate_.set_password(kCandidatePwd);
165 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
166
167 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
168}
169
170// Test that we can not add a candidate if there is no corresponding media
171// content in the session description.
172TEST_F(JsepSessionDescriptionTest, AddBadCandidate) {
173 JsepIceCandidate bad_candidate1("", 55, candidate_);
174 EXPECT_FALSE(jsep_desc_->AddCandidate(&bad_candidate1));
175
176 JsepIceCandidate bad_candidate2("some weird mid", 0, candidate_);
177 EXPECT_FALSE(jsep_desc_->AddCandidate(&bad_candidate2));
178}
179
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000180// Tests that repeatedly adding the same candidate, with or without credentials,
181// does not increase the number of candidates in the description.
182TEST_F(JsepSessionDescriptionTest, AddCandidateDuplicates) {
183 JsepIceCandidate jsep_candidate("", 0, candidate_);
184 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
185 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
186
187 // Add the same candidate again. It should be ignored.
188 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
189 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
190
191 // Create a new candidate, identical except that the ufrag and pwd are now
192 // populated.
193 candidate_.set_username(kCandidateUfragVoice);
194 candidate_.set_password(kCandidatePwdVoice);
195 JsepIceCandidate jsep_candidate_with_credentials("", 0, candidate_);
196
197 // This should also be identified as redundant and ignored.
198 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate_with_credentials));
199 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
200}
201
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000202// Test that we can serialize a JsepSessionDescription and deserialize it again.
203TEST_F(JsepSessionDescriptionTest, SerializeDeserialize) {
204 std::string sdp = Serialize(jsep_desc_.get());
205
kwibergd1fe2812016-04-27 06:47:29 -0700206 std::unique_ptr<SessionDescriptionInterface> parsed_jsep_desc(
207 DeSerialize(sdp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208 EXPECT_EQ(2u, parsed_jsep_desc->number_of_mediasections());
209
210 std::string parsed_sdp = Serialize(parsed_jsep_desc.get());
211 EXPECT_EQ(sdp, parsed_sdp);
212}
213
214// Tests that we can serialize and deserialize a JsepSesssionDescription
215// with candidates.
216TEST_F(JsepSessionDescriptionTest, SerializeDeserializeWithCandidates) {
217 std::string sdp = Serialize(jsep_desc_.get());
218
219 // Add a candidate and check that the serialized result is different.
220 JsepIceCandidate jsep_candidate("audio", 0, candidate_);
221 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
222 std::string sdp_with_candidate = Serialize(jsep_desc_.get());
223 EXPECT_NE(sdp, sdp_with_candidate);
224
kwibergd1fe2812016-04-27 06:47:29 -0700225 std::unique_ptr<SessionDescriptionInterface> parsed_jsep_desc(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226 DeSerialize(sdp_with_candidate));
227 std::string parsed_sdp_with_candidate = Serialize(parsed_jsep_desc.get());
228
229 EXPECT_EQ(sdp_with_candidate, parsed_sdp_with_candidate);
230}