blob: e47e5b17f8cf2873d7e7dc4fc751458493a359a8 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
15 *
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.
26 */
27
28#include <string>
29
30#include "talk/app/webrtc/fakeportallocatorfactory.h"
31#include "talk/app/webrtc/jsepsessiondescription.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032#include "talk/app/webrtc/mediastreaminterface.h"
33#include "talk/app/webrtc/peerconnectioninterface.h"
34#include "talk/app/webrtc/test/fakeconstraints.h"
35#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
36#include "talk/app/webrtc/test/testsdpstrings.h"
wu@webrtc.org967bfff2013-09-19 05:49:50 +000037#include "talk/app/webrtc/videosource.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000038#include "talk/base/gunit.h"
39#include "talk/base/scoped_ptr.h"
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +000040#include "talk/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041#include "talk/base/sslstreamadapter.h"
42#include "talk/base/stringutils.h"
43#include "talk/base/thread.h"
44#include "talk/media/base/fakevideocapturer.h"
mallinath@webrtc.org1112c302013-09-23 20:34:45 +000045#include "talk/media/sctp/sctpdataengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046#include "talk/session/media/mediasession.h"
47
48static const char kStreamLabel1[] = "local_stream_1";
49static const char kStreamLabel2[] = "local_stream_2";
50static const char kStreamLabel3[] = "local_stream_3";
51static const int kDefaultStunPort = 3478;
52static const char kStunAddressOnly[] = "stun:address";
53static const char kStunInvalidPort[] = "stun:address:-1";
54static const char kStunAddressPortAndMore1[] = "stun:address:port:more";
55static const char kStunAddressPortAndMore2[] = "stun:address:port more";
56static const char kTurnIceServerUri[] = "turn:user@turn.example.org";
57static const char kTurnUsername[] = "user";
58static const char kTurnPassword[] = "password";
59static const char kTurnHostname[] = "turn.example.org";
60static const uint32 kTimeout = 5000U;
61
62#define MAYBE_SKIP_TEST(feature) \
63 if (!(feature())) { \
64 LOG(LS_INFO) << "Feature disabled... skipping"; \
65 return; \
66 }
67
68using talk_base::scoped_ptr;
69using talk_base::scoped_refptr;
70using webrtc::AudioSourceInterface;
71using webrtc::AudioTrackInterface;
72using webrtc::DataBuffer;
73using webrtc::DataChannelInterface;
74using webrtc::FakeConstraints;
75using webrtc::FakePortAllocatorFactory;
76using webrtc::IceCandidateInterface;
77using webrtc::MediaStreamInterface;
78using webrtc::MediaStreamTrackInterface;
79using webrtc::MockCreateSessionDescriptionObserver;
80using webrtc::MockDataChannelObserver;
81using webrtc::MockSetSessionDescriptionObserver;
82using webrtc::MockStatsObserver;
83using webrtc::PeerConnectionInterface;
84using webrtc::PeerConnectionObserver;
85using webrtc::PortAllocatorFactoryInterface;
86using webrtc::SdpParseError;
87using webrtc::SessionDescriptionInterface;
88using webrtc::VideoSourceInterface;
89using webrtc::VideoTrackInterface;
90
91namespace {
92
93// Gets the first ssrc of given content type from the ContentInfo.
94bool GetFirstSsrc(const cricket::ContentInfo* content_info, int* ssrc) {
95 if (!content_info || !ssrc) {
96 return false;
97 }
98 const cricket::MediaContentDescription* media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000099 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100 content_info->description);
101 if (!media_desc || media_desc->streams().empty()) {
102 return false;
103 }
104 *ssrc = media_desc->streams().begin()->first_ssrc();
105 return true;
106}
107
108void SetSsrcToZero(std::string* sdp) {
109 const char kSdpSsrcAtribute[] = "a=ssrc:";
110 const char kSdpSsrcAtributeZero[] = "a=ssrc:0";
111 size_t ssrc_pos = 0;
112 while ((ssrc_pos = sdp->find(kSdpSsrcAtribute, ssrc_pos)) !=
113 std::string::npos) {
114 size_t end_ssrc = sdp->find(" ", ssrc_pos);
115 sdp->replace(ssrc_pos, end_ssrc - ssrc_pos, kSdpSsrcAtributeZero);
116 ssrc_pos = end_ssrc;
117 }
118}
119
120class MockPeerConnectionObserver : public PeerConnectionObserver {
121 public:
122 MockPeerConnectionObserver()
123 : renegotiation_needed_(false),
124 ice_complete_(false) {
125 }
126 ~MockPeerConnectionObserver() {
127 }
128 void SetPeerConnectionInterface(PeerConnectionInterface* pc) {
129 pc_ = pc;
130 if (pc) {
131 state_ = pc_->signaling_state();
132 }
133 }
134 virtual void OnError() {}
135 virtual void OnSignalingChange(
136 PeerConnectionInterface::SignalingState new_state) {
137 EXPECT_EQ(pc_->signaling_state(), new_state);
138 state_ = new_state;
139 }
140 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
141 virtual void OnStateChange(StateType state_changed) {
142 if (pc_.get() == NULL)
143 return;
144 switch (state_changed) {
145 case kSignalingState:
146 // OnSignalingChange and OnStateChange(kSignalingState) should always
147 // be called approximately simultaneously. To ease testing, we require
148 // that they always be called in that order. This check verifies
149 // that OnSignalingChange has just been called.
150 EXPECT_EQ(pc_->signaling_state(), state_);
151 break;
152 case kIceState:
153 ADD_FAILURE();
154 break;
155 default:
156 ADD_FAILURE();
157 break;
158 }
159 }
160 virtual void OnAddStream(MediaStreamInterface* stream) {
161 last_added_stream_ = stream;
162 }
163 virtual void OnRemoveStream(MediaStreamInterface* stream) {
164 last_removed_stream_ = stream;
165 }
166 virtual void OnRenegotiationNeeded() {
167 renegotiation_needed_ = true;
168 }
169 virtual void OnDataChannel(DataChannelInterface* data_channel) {
170 last_datachannel_ = data_channel;
171 }
172
173 virtual void OnIceConnectionChange(
174 PeerConnectionInterface::IceConnectionState new_state) {
175 EXPECT_EQ(pc_->ice_connection_state(), new_state);
176 }
177 virtual void OnIceGatheringChange(
178 PeerConnectionInterface::IceGatheringState new_state) {
179 EXPECT_EQ(pc_->ice_gathering_state(), new_state);
180 }
181 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
mallinath@webrtc.org68cbd012014-01-22 00:16:46 +0000182
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000183 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew,
184 pc_->ice_gathering_state());
185
186 std::string sdp;
187 EXPECT_TRUE(candidate->ToString(&sdp));
188 EXPECT_LT(0u, sdp.size());
189 last_candidate_.reset(webrtc::CreateIceCandidate(candidate->sdp_mid(),
190 candidate->sdp_mline_index(), sdp, NULL));
191 EXPECT_TRUE(last_candidate_.get() != NULL);
192 }
193 // TODO(bemasc): Remove this once callers transition to OnSignalingChange.
194 virtual void OnIceComplete() {
195 ice_complete_ = true;
196 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
197 // be called approximately simultaneously. For ease of testing, this
198 // check additionally requires that they be called in the above order.
199 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
200 pc_->ice_gathering_state());
201 }
202
203 // Returns the label of the last added stream.
204 // Empty string if no stream have been added.
205 std::string GetLastAddedStreamLabel() {
206 if (last_added_stream_.get())
207 return last_added_stream_->label();
208 return "";
209 }
210 std::string GetLastRemovedStreamLabel() {
211 if (last_removed_stream_.get())
212 return last_removed_stream_->label();
213 return "";
214 }
215
216 scoped_refptr<PeerConnectionInterface> pc_;
217 PeerConnectionInterface::SignalingState state_;
218 scoped_ptr<IceCandidateInterface> last_candidate_;
219 scoped_refptr<DataChannelInterface> last_datachannel_;
220 bool renegotiation_needed_;
221 bool ice_complete_;
222
223 private:
224 scoped_refptr<MediaStreamInterface> last_added_stream_;
225 scoped_refptr<MediaStreamInterface> last_removed_stream_;
226};
227
228} // namespace
229class PeerConnectionInterfaceTest : public testing::Test {
230 protected:
231 virtual void SetUp() {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000232 talk_base::InitializeSSL(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 pc_factory_ = webrtc::CreatePeerConnectionFactory(
234 talk_base::Thread::Current(), talk_base::Thread::Current(), NULL, NULL,
235 NULL);
236 ASSERT_TRUE(pc_factory_.get() != NULL);
237 }
238
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000239 virtual void TearDown() {
240 talk_base::CleanupSSL();
241 }
242
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243 void CreatePeerConnection() {
244 CreatePeerConnection("", "", NULL);
245 }
246
247 void CreatePeerConnection(webrtc::MediaConstraintsInterface* constraints) {
248 CreatePeerConnection("", "", constraints);
249 }
250
251 void CreatePeerConnection(const std::string& uri,
252 const std::string& password,
253 webrtc::MediaConstraintsInterface* constraints) {
254 PeerConnectionInterface::IceServer server;
255 PeerConnectionInterface::IceServers servers;
256 server.uri = uri;
257 server.password = password;
258 servers.push_back(server);
259
260 port_allocator_factory_ = FakePortAllocatorFactory::Create();
261 pc_ = pc_factory_->CreatePeerConnection(servers, constraints,
262 port_allocator_factory_.get(),
263 NULL,
264 &observer_);
265 ASSERT_TRUE(pc_.get() != NULL);
266 observer_.SetPeerConnectionInterface(pc_.get());
267 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
268 }
269
270 void CreatePeerConnectionWithDifferentConfigurations() {
271 CreatePeerConnection(kStunAddressOnly, "", NULL);
272 EXPECT_EQ(1u, port_allocator_factory_->stun_configs().size());
273 EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
274 EXPECT_EQ("address",
275 port_allocator_factory_->stun_configs()[0].server.hostname());
276 EXPECT_EQ(kDefaultStunPort,
277 port_allocator_factory_->stun_configs()[0].server.port());
278
279 CreatePeerConnection(kStunInvalidPort, "", NULL);
280 EXPECT_EQ(0u, port_allocator_factory_->stun_configs().size());
281 EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
282
283 CreatePeerConnection(kStunAddressPortAndMore1, "", NULL);
284 EXPECT_EQ(0u, port_allocator_factory_->stun_configs().size());
285 EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
286
287 CreatePeerConnection(kStunAddressPortAndMore2, "", NULL);
288 EXPECT_EQ(0u, port_allocator_factory_->stun_configs().size());
289 EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
290
291 CreatePeerConnection(kTurnIceServerUri, kTurnPassword, NULL);
292 EXPECT_EQ(1u, port_allocator_factory_->stun_configs().size());
293 EXPECT_EQ(1u, port_allocator_factory_->turn_configs().size());
294 EXPECT_EQ(kTurnUsername,
295 port_allocator_factory_->turn_configs()[0].username);
296 EXPECT_EQ(kTurnPassword,
297 port_allocator_factory_->turn_configs()[0].password);
298 EXPECT_EQ(kTurnHostname,
299 port_allocator_factory_->turn_configs()[0].server.hostname());
300 EXPECT_EQ(kTurnHostname,
301 port_allocator_factory_->stun_configs()[0].server.hostname());
302 }
303
304 void ReleasePeerConnection() {
305 pc_ = NULL;
306 observer_.SetPeerConnectionInterface(NULL);
307 }
308
309 void AddStream(const std::string& label) {
310 // Create a local stream.
311 scoped_refptr<MediaStreamInterface> stream(
312 pc_factory_->CreateLocalMediaStream(label));
313 scoped_refptr<VideoSourceInterface> video_source(
314 pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer(), NULL));
315 scoped_refptr<VideoTrackInterface> video_track(
316 pc_factory_->CreateVideoTrack(label + "v0", video_source));
317 stream->AddTrack(video_track.get());
318 EXPECT_TRUE(pc_->AddStream(stream, NULL));
319 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
320 observer_.renegotiation_needed_ = false;
321 }
322
323 void AddVoiceStream(const std::string& label) {
324 // Create a local stream.
325 scoped_refptr<MediaStreamInterface> stream(
326 pc_factory_->CreateLocalMediaStream(label));
327 scoped_refptr<AudioTrackInterface> audio_track(
328 pc_factory_->CreateAudioTrack(label + "a0", NULL));
329 stream->AddTrack(audio_track.get());
330 EXPECT_TRUE(pc_->AddStream(stream, NULL));
331 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
332 observer_.renegotiation_needed_ = false;
333 }
334
335 void AddAudioVideoStream(const std::string& stream_label,
336 const std::string& audio_track_label,
337 const std::string& video_track_label) {
338 // Create a local stream.
339 scoped_refptr<MediaStreamInterface> stream(
340 pc_factory_->CreateLocalMediaStream(stream_label));
341 scoped_refptr<AudioTrackInterface> audio_track(
342 pc_factory_->CreateAudioTrack(
343 audio_track_label, static_cast<AudioSourceInterface*>(NULL)));
344 stream->AddTrack(audio_track.get());
345 scoped_refptr<VideoTrackInterface> video_track(
346 pc_factory_->CreateVideoTrack(video_track_label, NULL));
347 stream->AddTrack(video_track.get());
348 EXPECT_TRUE(pc_->AddStream(stream, NULL));
349 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
350 observer_.renegotiation_needed_ = false;
351 }
352
353 bool DoCreateOfferAnswer(SessionDescriptionInterface** desc, bool offer) {
354 talk_base::scoped_refptr<MockCreateSessionDescriptionObserver>
355 observer(new talk_base::RefCountedObject<
356 MockCreateSessionDescriptionObserver>());
357 if (offer) {
358 pc_->CreateOffer(observer, NULL);
359 } else {
360 pc_->CreateAnswer(observer, NULL);
361 }
362 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
363 *desc = observer->release_desc();
364 return observer->result();
365 }
366
367 bool DoCreateOffer(SessionDescriptionInterface** desc) {
368 return DoCreateOfferAnswer(desc, true);
369 }
370
371 bool DoCreateAnswer(SessionDescriptionInterface** desc) {
372 return DoCreateOfferAnswer(desc, false);
373 }
374
375 bool DoSetSessionDescription(SessionDescriptionInterface* desc, bool local) {
376 talk_base::scoped_refptr<MockSetSessionDescriptionObserver>
377 observer(new talk_base::RefCountedObject<
378 MockSetSessionDescriptionObserver>());
379 if (local) {
380 pc_->SetLocalDescription(observer, desc);
381 } else {
382 pc_->SetRemoteDescription(observer, desc);
383 }
384 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
385 return observer->result();
386 }
387
388 bool DoSetLocalDescription(SessionDescriptionInterface* desc) {
389 return DoSetSessionDescription(desc, true);
390 }
391
392 bool DoSetRemoteDescription(SessionDescriptionInterface* desc) {
393 return DoSetSessionDescription(desc, false);
394 }
395
396 // Calls PeerConnection::GetStats and check the return value.
397 // It does not verify the values in the StatReports since a RTCP packet might
398 // be required.
399 bool DoGetStats(MediaStreamTrackInterface* track) {
400 talk_base::scoped_refptr<MockStatsObserver> observer(
401 new talk_base::RefCountedObject<MockStatsObserver>());
402 if (!pc_->GetStats(observer, track))
403 return false;
404 EXPECT_TRUE_WAIT(observer->called(), kTimeout);
405 return observer->called();
406 }
407
408 void InitiateCall() {
409 CreatePeerConnection();
410 // Create a local stream with audio&video tracks.
411 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
412 CreateOfferReceiveAnswer();
413 }
414
415 // Verify that RTP Header extensions has been negotiated for audio and video.
416 void VerifyRemoteRtpHeaderExtensions() {
417 const cricket::MediaContentDescription* desc =
418 cricket::GetFirstAudioContentDescription(
419 pc_->remote_description()->description());
420 ASSERT_TRUE(desc != NULL);
421 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
422
423 desc = cricket::GetFirstVideoContentDescription(
424 pc_->remote_description()->description());
425 ASSERT_TRUE(desc != NULL);
426 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
427 }
428
429 void CreateOfferAsRemoteDescription() {
430 talk_base::scoped_ptr<SessionDescriptionInterface> offer;
431 EXPECT_TRUE(DoCreateOffer(offer.use()));
432 std::string sdp;
433 EXPECT_TRUE(offer->ToString(&sdp));
434 SessionDescriptionInterface* remote_offer =
435 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
436 sdp, NULL);
437 EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
438 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
439 }
440
441 void CreateAnswerAsLocalDescription() {
442 scoped_ptr<SessionDescriptionInterface> answer;
443 EXPECT_TRUE(DoCreateAnswer(answer.use()));
444
445 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
446 // audio codec change, even if the parameter has nothing to do with
447 // receiving. Not all parameters are serialized to SDP.
448 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
449 // the SessionDescription, it is necessary to do that here to in order to
450 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
451 // https://code.google.com/p/webrtc/issues/detail?id=1356
452 std::string sdp;
453 EXPECT_TRUE(answer->ToString(&sdp));
454 SessionDescriptionInterface* new_answer =
455 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
456 sdp, NULL);
457 EXPECT_TRUE(DoSetLocalDescription(new_answer));
458 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
459 }
460
461 void CreatePrAnswerAsLocalDescription() {
462 scoped_ptr<SessionDescriptionInterface> answer;
463 EXPECT_TRUE(DoCreateAnswer(answer.use()));
464
465 std::string sdp;
466 EXPECT_TRUE(answer->ToString(&sdp));
467 SessionDescriptionInterface* pr_answer =
468 webrtc::CreateSessionDescription(SessionDescriptionInterface::kPrAnswer,
469 sdp, NULL);
470 EXPECT_TRUE(DoSetLocalDescription(pr_answer));
471 EXPECT_EQ(PeerConnectionInterface::kHaveLocalPrAnswer, observer_.state_);
472 }
473
474 void CreateOfferReceiveAnswer() {
475 CreateOfferAsLocalDescription();
476 std::string sdp;
477 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
478 CreateAnswerAsRemoteDescription(sdp);
479 }
480
481 void CreateOfferAsLocalDescription() {
482 talk_base::scoped_ptr<SessionDescriptionInterface> offer;
483 ASSERT_TRUE(DoCreateOffer(offer.use()));
484 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
485 // audio codec change, even if the parameter has nothing to do with
486 // receiving. Not all parameters are serialized to SDP.
487 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
488 // the SessionDescription, it is necessary to do that here to in order to
489 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
490 // https://code.google.com/p/webrtc/issues/detail?id=1356
491 std::string sdp;
492 EXPECT_TRUE(offer->ToString(&sdp));
493 SessionDescriptionInterface* new_offer =
494 webrtc::CreateSessionDescription(
495 SessionDescriptionInterface::kOffer,
496 sdp, NULL);
497
498 EXPECT_TRUE(DoSetLocalDescription(new_offer));
499 EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer, observer_.state_);
mallinath@webrtc.org68cbd012014-01-22 00:16:46 +0000500 // Wait for the ice_complete message, so that SDP will have candidates.
501 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 }
503
504 void CreateAnswerAsRemoteDescription(const std::string& offer) {
505 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
506 SessionDescriptionInterface::kAnswer);
507 EXPECT_TRUE(answer->Initialize(offer, NULL));
508 EXPECT_TRUE(DoSetRemoteDescription(answer));
509 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
510 }
511
512 void CreatePrAnswerAndAnswerAsRemoteDescription(const std::string& offer) {
513 webrtc::JsepSessionDescription* pr_answer =
514 new webrtc::JsepSessionDescription(
515 SessionDescriptionInterface::kPrAnswer);
516 EXPECT_TRUE(pr_answer->Initialize(offer, NULL));
517 EXPECT_TRUE(DoSetRemoteDescription(pr_answer));
518 EXPECT_EQ(PeerConnectionInterface::kHaveRemotePrAnswer, observer_.state_);
519 webrtc::JsepSessionDescription* answer =
520 new webrtc::JsepSessionDescription(
521 SessionDescriptionInterface::kAnswer);
522 EXPECT_TRUE(answer->Initialize(offer, NULL));
523 EXPECT_TRUE(DoSetRemoteDescription(answer));
524 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
525 }
526
527 // Help function used for waiting until a the last signaled remote stream has
528 // the same label as |stream_label|. In a few of the tests in this file we
529 // answer with the same session description as we offer and thus we can
530 // check if OnAddStream have been called with the same stream as we offer to
531 // send.
532 void WaitAndVerifyOnAddStream(const std::string& stream_label) {
533 EXPECT_EQ_WAIT(stream_label, observer_.GetLastAddedStreamLabel(), kTimeout);
534 }
535
536 // Creates an offer and applies it as a local session description.
537 // Creates an answer with the same SDP an the offer but removes all lines
538 // that start with a:ssrc"
539 void CreateOfferReceiveAnswerWithoutSsrc() {
540 CreateOfferAsLocalDescription();
541 std::string sdp;
542 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
543 SetSsrcToZero(&sdp);
544 CreateAnswerAsRemoteDescription(sdp);
545 }
546
547 scoped_refptr<FakePortAllocatorFactory> port_allocator_factory_;
548 scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
549 scoped_refptr<PeerConnectionInterface> pc_;
550 MockPeerConnectionObserver observer_;
551};
552
553TEST_F(PeerConnectionInterfaceTest,
554 CreatePeerConnectionWithDifferentConfigurations) {
555 CreatePeerConnectionWithDifferentConfigurations();
556}
557
558TEST_F(PeerConnectionInterfaceTest, AddStreams) {
559 CreatePeerConnection();
560 AddStream(kStreamLabel1);
561 AddVoiceStream(kStreamLabel2);
562 ASSERT_EQ(2u, pc_->local_streams()->count());
563
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000564 // Test we can add multiple local streams to one peerconnection.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 scoped_refptr<MediaStreamInterface> stream(
566 pc_factory_->CreateLocalMediaStream(kStreamLabel3));
567 scoped_refptr<AudioTrackInterface> audio_track(
568 pc_factory_->CreateAudioTrack(
569 kStreamLabel3, static_cast<AudioSourceInterface*>(NULL)));
570 stream->AddTrack(audio_track.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000571 EXPECT_TRUE(pc_->AddStream(stream, NULL));
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000572 EXPECT_EQ(3u, pc_->local_streams()->count());
573
574 // Remove the third stream.
575 pc_->RemoveStream(pc_->local_streams()->at(2));
576 EXPECT_EQ(2u, pc_->local_streams()->count());
577
578 // Remove the second stream.
579 pc_->RemoveStream(pc_->local_streams()->at(1));
580 EXPECT_EQ(1u, pc_->local_streams()->count());
581
582 // Remove the first stream.
583 pc_->RemoveStream(pc_->local_streams()->at(0));
584 EXPECT_EQ(0u, pc_->local_streams()->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585}
586
587TEST_F(PeerConnectionInterfaceTest, RemoveStream) {
588 CreatePeerConnection();
589 AddStream(kStreamLabel1);
590 ASSERT_EQ(1u, pc_->local_streams()->count());
591 pc_->RemoveStream(pc_->local_streams()->at(0));
592 EXPECT_EQ(0u, pc_->local_streams()->count());
593}
594
595TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) {
596 InitiateCall();
597 WaitAndVerifyOnAddStream(kStreamLabel1);
598 VerifyRemoteRtpHeaderExtensions();
599}
600
601TEST_F(PeerConnectionInterfaceTest, CreateOfferReceivePrAnswerAndAnswer) {
602 CreatePeerConnection();
603 AddStream(kStreamLabel1);
604 CreateOfferAsLocalDescription();
605 std::string offer;
606 EXPECT_TRUE(pc_->local_description()->ToString(&offer));
607 CreatePrAnswerAndAnswerAsRemoteDescription(offer);
608 WaitAndVerifyOnAddStream(kStreamLabel1);
609}
610
611TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreateAnswer) {
612 CreatePeerConnection();
613 AddStream(kStreamLabel1);
614
615 CreateOfferAsRemoteDescription();
616 CreateAnswerAsLocalDescription();
617
618 WaitAndVerifyOnAddStream(kStreamLabel1);
619}
620
621TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreatePrAnswerAndAnswer) {
622 CreatePeerConnection();
623 AddStream(kStreamLabel1);
624
625 CreateOfferAsRemoteDescription();
626 CreatePrAnswerAsLocalDescription();
627 CreateAnswerAsLocalDescription();
628
629 WaitAndVerifyOnAddStream(kStreamLabel1);
630}
631
632TEST_F(PeerConnectionInterfaceTest, Renegotiate) {
633 InitiateCall();
634 ASSERT_EQ(1u, pc_->remote_streams()->count());
635 pc_->RemoveStream(pc_->local_streams()->at(0));
636 CreateOfferReceiveAnswer();
637 EXPECT_EQ(0u, pc_->remote_streams()->count());
638 AddStream(kStreamLabel1);
639 CreateOfferReceiveAnswer();
640}
641
642// Tests that after negotiating an audio only call, the respondent can perform a
643// renegotiation that removes the audio stream.
644TEST_F(PeerConnectionInterfaceTest, RenegotiateAudioOnly) {
645 CreatePeerConnection();
646 AddVoiceStream(kStreamLabel1);
647 CreateOfferAsRemoteDescription();
648 CreateAnswerAsLocalDescription();
649
650 ASSERT_EQ(1u, pc_->remote_streams()->count());
651 pc_->RemoveStream(pc_->local_streams()->at(0));
652 CreateOfferReceiveAnswer();
653 EXPECT_EQ(0u, pc_->remote_streams()->count());
654}
655
656// Test that candidates are generated and that we can parse our own candidates.
657TEST_F(PeerConnectionInterfaceTest, IceCandidates) {
658 CreatePeerConnection();
659
660 EXPECT_FALSE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
661 // SetRemoteDescription takes ownership of offer.
662 SessionDescriptionInterface* offer = NULL;
663 AddStream(kStreamLabel1);
664 EXPECT_TRUE(DoCreateOffer(&offer));
665 EXPECT_TRUE(DoSetRemoteDescription(offer));
666
667 // SetLocalDescription takes ownership of answer.
668 SessionDescriptionInterface* answer = NULL;
669 EXPECT_TRUE(DoCreateAnswer(&answer));
670 EXPECT_TRUE(DoSetLocalDescription(answer));
671
672 EXPECT_TRUE_WAIT(observer_.last_candidate_.get() != NULL, kTimeout);
673 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
674
675 EXPECT_TRUE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
676}
677
678// Test that the CreateOffer and CreatAnswer will fail if the track labels are
679// not unique.
680TEST_F(PeerConnectionInterfaceTest, CreateOfferAnswerWithInvalidStream) {
681 CreatePeerConnection();
682 // Create a regular offer for the CreateAnswer test later.
683 SessionDescriptionInterface* offer = NULL;
684 EXPECT_TRUE(DoCreateOffer(&offer));
685 EXPECT_TRUE(offer != NULL);
686 delete offer;
687 offer = NULL;
688
689 // Create a local stream with audio&video tracks having same label.
690 AddAudioVideoStream(kStreamLabel1, "track_label", "track_label");
691
692 // Test CreateOffer
693 EXPECT_FALSE(DoCreateOffer(&offer));
694
695 // Test CreateAnswer
696 SessionDescriptionInterface* answer = NULL;
697 EXPECT_FALSE(DoCreateAnswer(&answer));
698}
699
700// Test that we will get different SSRCs for each tracks in the offer and answer
701// we created.
702TEST_F(PeerConnectionInterfaceTest, SsrcInOfferAnswer) {
703 CreatePeerConnection();
704 // Create a local stream with audio&video tracks having different labels.
705 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
706
707 // Test CreateOffer
708 scoped_ptr<SessionDescriptionInterface> offer;
709 EXPECT_TRUE(DoCreateOffer(offer.use()));
710 int audio_ssrc = 0;
711 int video_ssrc = 0;
712 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(offer->description()),
713 &audio_ssrc));
714 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(offer->description()),
715 &video_ssrc));
716 EXPECT_NE(audio_ssrc, video_ssrc);
717
718 // Test CreateAnswer
719 EXPECT_TRUE(DoSetRemoteDescription(offer.release()));
720 scoped_ptr<SessionDescriptionInterface> answer;
721 EXPECT_TRUE(DoCreateAnswer(answer.use()));
722 audio_ssrc = 0;
723 video_ssrc = 0;
724 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(answer->description()),
725 &audio_ssrc));
726 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(answer->description()),
727 &video_ssrc));
728 EXPECT_NE(audio_ssrc, video_ssrc);
729}
730
731// Test that we can specify a certain track that we want statistics about.
732TEST_F(PeerConnectionInterfaceTest, GetStatsForSpecificTrack) {
733 InitiateCall();
734 ASSERT_LT(0u, pc_->remote_streams()->count());
735 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetAudioTracks().size());
736 scoped_refptr<MediaStreamTrackInterface> remote_audio =
737 pc_->remote_streams()->at(0)->GetAudioTracks()[0];
738 EXPECT_TRUE(DoGetStats(remote_audio));
739
740 // Remove the stream. Since we are sending to our selves the local
741 // and the remote stream is the same.
742 pc_->RemoveStream(pc_->local_streams()->at(0));
743 // Do a re-negotiation.
744 CreateOfferReceiveAnswer();
745
746 ASSERT_EQ(0u, pc_->remote_streams()->count());
747
748 // Test that we still can get statistics for the old track. Even if it is not
749 // sent any longer.
750 EXPECT_TRUE(DoGetStats(remote_audio));
751}
752
753// Test that we can get stats on a video track.
754TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
755 InitiateCall();
756 ASSERT_LT(0u, pc_->remote_streams()->count());
757 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetVideoTracks().size());
758 scoped_refptr<MediaStreamTrackInterface> remote_video =
759 pc_->remote_streams()->at(0)->GetVideoTracks()[0];
760 EXPECT_TRUE(DoGetStats(remote_video));
761}
762
763// Test that we don't get statistics for an invalid track.
764TEST_F(PeerConnectionInterfaceTest, GetStatsForInvalidTrack) {
765 InitiateCall();
766 scoped_refptr<AudioTrackInterface> unknown_audio_track(
767 pc_factory_->CreateAudioTrack("unknown track", NULL));
768 EXPECT_FALSE(DoGetStats(unknown_audio_track));
769}
770
771// This test setup two RTP data channels in loop back.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772TEST_F(PeerConnectionInterfaceTest, TestDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 FakeConstraints constraints;
774 constraints.SetAllowRtpDataChannels();
775 CreatePeerConnection(&constraints);
776 scoped_refptr<DataChannelInterface> data1 =
777 pc_->CreateDataChannel("test1", NULL);
778 scoped_refptr<DataChannelInterface> data2 =
779 pc_->CreateDataChannel("test2", NULL);
780 ASSERT_TRUE(data1 != NULL);
781 talk_base::scoped_ptr<MockDataChannelObserver> observer1(
782 new MockDataChannelObserver(data1));
783 talk_base::scoped_ptr<MockDataChannelObserver> observer2(
784 new MockDataChannelObserver(data2));
785
786 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
787 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
788 std::string data_to_send1 = "testing testing";
789 std::string data_to_send2 = "testing something else";
790 EXPECT_FALSE(data1->Send(DataBuffer(data_to_send1)));
791
792 CreateOfferReceiveAnswer();
793 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
794 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
795
796 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
797 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
798 EXPECT_TRUE(data1->Send(DataBuffer(data_to_send1)));
799 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
800
801 EXPECT_EQ_WAIT(data_to_send1, observer1->last_message(), kTimeout);
802 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
803
804 data1->Close();
805 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
806 CreateOfferReceiveAnswer();
807 EXPECT_FALSE(observer1->IsOpen());
808 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
809 EXPECT_TRUE(observer2->IsOpen());
810
811 data_to_send2 = "testing something else again";
812 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
813
814 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
815}
816
817// This test verifies that sendnig binary data over RTP data channels should
818// fail.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000819TEST_F(PeerConnectionInterfaceTest, TestSendBinaryOnRtpDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000820 FakeConstraints constraints;
821 constraints.SetAllowRtpDataChannels();
822 CreatePeerConnection(&constraints);
823 scoped_refptr<DataChannelInterface> data1 =
824 pc_->CreateDataChannel("test1", NULL);
825 scoped_refptr<DataChannelInterface> data2 =
826 pc_->CreateDataChannel("test2", NULL);
827 ASSERT_TRUE(data1 != NULL);
828 talk_base::scoped_ptr<MockDataChannelObserver> observer1(
829 new MockDataChannelObserver(data1));
830 talk_base::scoped_ptr<MockDataChannelObserver> observer2(
831 new MockDataChannelObserver(data2));
832
833 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
834 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
835
836 CreateOfferReceiveAnswer();
837 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
838 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
839
840 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
841 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
842
843 talk_base::Buffer buffer("test", 4);
844 EXPECT_FALSE(data1->Send(DataBuffer(buffer, true)));
845}
846
847// This test setup a RTP data channels in loop back and test that a channel is
848// opened even if the remote end answer with a zero SSRC.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000849TEST_F(PeerConnectionInterfaceTest, TestSendOnlyDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000850 FakeConstraints constraints;
851 constraints.SetAllowRtpDataChannels();
852 CreatePeerConnection(&constraints);
853 scoped_refptr<DataChannelInterface> data1 =
854 pc_->CreateDataChannel("test1", NULL);
855 talk_base::scoped_ptr<MockDataChannelObserver> observer1(
856 new MockDataChannelObserver(data1));
857
858 CreateOfferReceiveAnswerWithoutSsrc();
859
860 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
861
862 data1->Close();
863 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
864 CreateOfferReceiveAnswerWithoutSsrc();
865 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
866 EXPECT_FALSE(observer1->IsOpen());
867}
868
869// This test that if a data channel is added in an answer a receive only channel
870// channel is created.
871TEST_F(PeerConnectionInterfaceTest, TestReceiveOnlyDataChannel) {
872 FakeConstraints constraints;
873 constraints.SetAllowRtpDataChannels();
874 CreatePeerConnection(&constraints);
875
876 std::string offer_label = "offer_channel";
877 scoped_refptr<DataChannelInterface> offer_channel =
878 pc_->CreateDataChannel(offer_label, NULL);
879
880 CreateOfferAsLocalDescription();
881
882 // Replace the data channel label in the offer and apply it as an answer.
883 std::string receive_label = "answer_channel";
884 std::string sdp;
885 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
886 talk_base::replace_substrs(offer_label.c_str(), offer_label.length(),
887 receive_label.c_str(), receive_label.length(),
888 &sdp);
889 CreateAnswerAsRemoteDescription(sdp);
890
891 // Verify that a new incoming data channel has been created and that
892 // it is open but can't we written to.
893 ASSERT_TRUE(observer_.last_datachannel_ != NULL);
894 DataChannelInterface* received_channel = observer_.last_datachannel_;
895 EXPECT_EQ(DataChannelInterface::kConnecting, received_channel->state());
896 EXPECT_EQ(receive_label, received_channel->label());
897 EXPECT_FALSE(received_channel->Send(DataBuffer("something")));
898
899 // Verify that the channel we initially offered has been rejected.
900 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
901
902 // Do another offer / answer exchange and verify that the data channel is
903 // opened.
904 CreateOfferReceiveAnswer();
905 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, received_channel->state(),
906 kTimeout);
907}
908
909// This test that no data channel is returned if a reliable channel is
910// requested.
911// TODO(perkj): Remove this test once reliable channels are implemented.
912TEST_F(PeerConnectionInterfaceTest, CreateReliableRtpDataChannelShouldFail) {
913 FakeConstraints constraints;
914 constraints.SetAllowRtpDataChannels();
915 CreatePeerConnection(&constraints);
916
917 std::string label = "test";
918 webrtc::DataChannelInit config;
919 config.reliable = true;
920 scoped_refptr<DataChannelInterface> channel =
921 pc_->CreateDataChannel(label, &config);
922 EXPECT_TRUE(channel == NULL);
923}
924
925// This tests that a SCTP data channel is returned using different
926// DataChannelInit configurations.
927TEST_F(PeerConnectionInterfaceTest, CreateSctpDataChannel) {
928 FakeConstraints constraints;
929 constraints.SetAllowDtlsSctpDataChannels();
930 CreatePeerConnection(&constraints);
931
932 webrtc::DataChannelInit config;
933
934 scoped_refptr<DataChannelInterface> channel =
935 pc_->CreateDataChannel("1", &config);
936 EXPECT_TRUE(channel != NULL);
937 EXPECT_TRUE(channel->reliable());
938
939 config.ordered = false;
940 channel = pc_->CreateDataChannel("2", &config);
941 EXPECT_TRUE(channel != NULL);
942 EXPECT_TRUE(channel->reliable());
943
944 config.ordered = true;
945 config.maxRetransmits = 0;
946 channel = pc_->CreateDataChannel("3", &config);
947 EXPECT_TRUE(channel != NULL);
948 EXPECT_FALSE(channel->reliable());
949
950 config.maxRetransmits = -1;
951 config.maxRetransmitTime = 0;
952 channel = pc_->CreateDataChannel("4", &config);
953 EXPECT_TRUE(channel != NULL);
954 EXPECT_FALSE(channel->reliable());
955}
956
957// This tests that no data channel is returned if both maxRetransmits and
958// maxRetransmitTime are set for SCTP data channels.
959TEST_F(PeerConnectionInterfaceTest,
960 CreateSctpDataChannelShouldFailForInvalidConfig) {
961 FakeConstraints constraints;
962 constraints.SetAllowDtlsSctpDataChannels();
963 CreatePeerConnection(&constraints);
964
965 std::string label = "test";
966 webrtc::DataChannelInit config;
967 config.maxRetransmits = 0;
968 config.maxRetransmitTime = 0;
969
970 scoped_refptr<DataChannelInterface> channel =
971 pc_->CreateDataChannel(label, &config);
972 EXPECT_TRUE(channel == NULL);
973}
974
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975// The test verifies that creating a SCTP data channel with an id already in use
976// or out of range should fail.
977TEST_F(PeerConnectionInterfaceTest,
978 CreateSctpDataChannelWithInvalidIdShouldFail) {
979 FakeConstraints constraints;
980 constraints.SetAllowDtlsSctpDataChannels();
981 CreatePeerConnection(&constraints);
982
983 webrtc::DataChannelInit config;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000984 scoped_refptr<DataChannelInterface> channel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000985
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000986 config.id = 1;
987 channel = pc_->CreateDataChannel("1", &config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988 EXPECT_TRUE(channel != NULL);
989 EXPECT_EQ(1, channel->id());
990
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000991 channel = pc_->CreateDataChannel("x", &config);
992 EXPECT_TRUE(channel == NULL);
993
994 config.id = cricket::kMaxSctpSid;
995 channel = pc_->CreateDataChannel("max", &config);
996 EXPECT_TRUE(channel != NULL);
997 EXPECT_EQ(config.id, channel->id());
998
999 config.id = cricket::kMaxSctpSid + 1;
1000 channel = pc_->CreateDataChannel("x", &config);
1001 EXPECT_TRUE(channel == NULL);
1002}
1003
1004// This test that a data channel closes when a PeerConnection is deleted/closed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005TEST_F(PeerConnectionInterfaceTest, DataChannelCloseWhenPeerConnectionClose) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001006 FakeConstraints constraints;
1007 constraints.SetAllowRtpDataChannels();
1008 CreatePeerConnection(&constraints);
1009
1010 scoped_refptr<DataChannelInterface> data1 =
1011 pc_->CreateDataChannel("test1", NULL);
1012 scoped_refptr<DataChannelInterface> data2 =
1013 pc_->CreateDataChannel("test2", NULL);
1014 ASSERT_TRUE(data1 != NULL);
1015 talk_base::scoped_ptr<MockDataChannelObserver> observer1(
1016 new MockDataChannelObserver(data1));
1017 talk_base::scoped_ptr<MockDataChannelObserver> observer2(
1018 new MockDataChannelObserver(data2));
1019
1020 CreateOfferReceiveAnswer();
1021 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1022 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1023
1024 ReleasePeerConnection();
1025 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1026 EXPECT_EQ(DataChannelInterface::kClosed, data2->state());
1027}
1028
1029// This test that data channels can be rejected in an answer.
1030TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
1031 FakeConstraints constraints;
1032 constraints.SetAllowRtpDataChannels();
1033 CreatePeerConnection(&constraints);
1034
1035 scoped_refptr<DataChannelInterface> offer_channel(
1036 pc_->CreateDataChannel("offer_channel", NULL));
1037
1038 CreateOfferAsLocalDescription();
1039
1040 // Create an answer where the m-line for data channels are rejected.
1041 std::string sdp;
1042 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
1043 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
1044 SessionDescriptionInterface::kAnswer);
1045 EXPECT_TRUE(answer->Initialize(sdp, NULL));
1046 cricket::ContentInfo* data_info =
1047 answer->description()->GetContentByName("data");
1048 data_info->rejected = true;
1049
1050 DoSetRemoteDescription(answer);
1051 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1052}
1053
1054// Test that we can create a session description from an SDP string from
1055// FireFox, use it as a remote session description, generate an answer and use
1056// the answer as a local description.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001057TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001058 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1059 FakeConstraints constraints;
1060 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1061 true);
1062 CreatePeerConnection(&constraints);
1063 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1064 SessionDescriptionInterface* desc =
1065 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1066 webrtc::kFireFoxSdpOffer);
1067 EXPECT_TRUE(DoSetSessionDescription(desc, false));
1068 CreateAnswerAsLocalDescription();
1069 ASSERT_TRUE(pc_->local_description() != NULL);
1070 ASSERT_TRUE(pc_->remote_description() != NULL);
1071
1072 const cricket::ContentInfo* content =
1073 cricket::GetFirstAudioContent(pc_->local_description()->description());
1074 ASSERT_TRUE(content != NULL);
1075 EXPECT_FALSE(content->rejected);
1076
1077 content =
1078 cricket::GetFirstVideoContent(pc_->local_description()->description());
1079 ASSERT_TRUE(content != NULL);
1080 EXPECT_FALSE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001081#ifdef HAVE_SCTP
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001082 content =
1083 cricket::GetFirstDataContent(pc_->local_description()->description());
1084 ASSERT_TRUE(content != NULL);
1085 EXPECT_TRUE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001086#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087}
1088
1089// Test that we can create an audio only offer and receive an answer with a
1090// limited set of audio codecs and receive an updated offer with more audio
1091// codecs, where the added codecs are not supported.
1092TEST_F(PeerConnectionInterfaceTest, ReceiveUpdatedAudioOfferWithBadCodecs) {
1093 CreatePeerConnection();
1094 AddVoiceStream("audio_label");
1095 CreateOfferAsLocalDescription();
1096
1097 SessionDescriptionInterface* answer =
1098 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
1099 webrtc::kAudioSdp);
1100 EXPECT_TRUE(DoSetSessionDescription(answer, false));
1101
1102 SessionDescriptionInterface* updated_offer =
1103 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1104 webrtc::kAudioSdpWithUnsupportedCodecs);
1105 EXPECT_TRUE(DoSetSessionDescription(updated_offer, false));
1106 CreateAnswerAsLocalDescription();
1107}
1108
1109// Test that PeerConnection::Close changes the states to closed and all remote
1110// tracks change state to ended.
1111TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) {
1112 // Initialize a PeerConnection and negotiate local and remote session
1113 // description.
1114 InitiateCall();
1115 ASSERT_EQ(1u, pc_->local_streams()->count());
1116 ASSERT_EQ(1u, pc_->remote_streams()->count());
1117
1118 pc_->Close();
1119
1120 EXPECT_EQ(PeerConnectionInterface::kClosed, pc_->signaling_state());
1121 EXPECT_EQ(PeerConnectionInterface::kIceConnectionClosed,
1122 pc_->ice_connection_state());
1123 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
1124 pc_->ice_gathering_state());
1125
1126 EXPECT_EQ(1u, pc_->local_streams()->count());
1127 EXPECT_EQ(1u, pc_->remote_streams()->count());
1128
1129 scoped_refptr<MediaStreamInterface> remote_stream =
1130 pc_->remote_streams()->at(0);
1131 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1132 remote_stream->GetVideoTracks()[0]->state());
1133 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1134 remote_stream->GetAudioTracks()[0]->state());
1135}
1136
1137// Test that PeerConnection methods fails gracefully after
1138// PeerConnection::Close has been called.
1139TEST_F(PeerConnectionInterfaceTest, CloseAndTestMethods) {
1140 CreatePeerConnection();
1141 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1142 CreateOfferAsRemoteDescription();
1143 CreateAnswerAsLocalDescription();
1144
1145 ASSERT_EQ(1u, pc_->local_streams()->count());
1146 scoped_refptr<MediaStreamInterface> local_stream =
1147 pc_->local_streams()->at(0);
1148
1149 pc_->Close();
1150
1151 pc_->RemoveStream(local_stream);
1152 EXPECT_FALSE(pc_->AddStream(local_stream, NULL));
1153
1154 ASSERT_FALSE(local_stream->GetAudioTracks().empty());
1155 talk_base::scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender(
1156 pc_->CreateDtmfSender(local_stream->GetAudioTracks()[0]));
wu@webrtc.org66037362013-08-13 00:09:35 +00001157 EXPECT_TRUE(NULL == dtmf_sender); // local stream has been removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158
1159 EXPECT_TRUE(pc_->CreateDataChannel("test", NULL) == NULL);
1160
1161 EXPECT_TRUE(pc_->local_description() != NULL);
1162 EXPECT_TRUE(pc_->remote_description() != NULL);
1163
1164 talk_base::scoped_ptr<SessionDescriptionInterface> offer;
1165 EXPECT_TRUE(DoCreateOffer(offer.use()));
1166 talk_base::scoped_ptr<SessionDescriptionInterface> answer;
1167 EXPECT_TRUE(DoCreateAnswer(answer.use()));
1168
1169 std::string sdp;
1170 ASSERT_TRUE(pc_->remote_description()->ToString(&sdp));
1171 SessionDescriptionInterface* remote_offer =
1172 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1173 sdp, NULL);
1174 EXPECT_FALSE(DoSetRemoteDescription(remote_offer));
1175
1176 ASSERT_TRUE(pc_->local_description()->ToString(&sdp));
1177 SessionDescriptionInterface* local_offer =
1178 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1179 sdp, NULL);
1180 EXPECT_FALSE(DoSetLocalDescription(local_offer));
1181}
1182
1183// Test that GetStats can still be called after PeerConnection::Close.
1184TEST_F(PeerConnectionInterfaceTest, CloseAndGetStats) {
1185 InitiateCall();
1186 pc_->Close();
1187 DoGetStats(NULL);
1188}