Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / app / webrtc / peerconnectionendtoend_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2013, 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 "talk/app/webrtc/test/peerconnectiontestwrapper.h"
29 #include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
30 #include "webrtc/base/gunit.h"
31 #include "webrtc/base/logging.h"
32 #include "webrtc/base/ssladapter.h"
33 #include "webrtc/base/sslstreamadapter.h"
34 #include "webrtc/base/stringencode.h"
35 #include "webrtc/base/stringutils.h"
36
37 #define MAYBE_SKIP_TEST(feature)                    \
38   if (!(feature())) {                               \
39     LOG(LS_INFO) << "Feature disabled... skipping"; \
40     return;                                         \
41   }
42
43 using webrtc::DataChannelInterface;
44 using webrtc::FakeConstraints;
45 using webrtc::MediaConstraintsInterface;
46 using webrtc::MediaStreamInterface;
47 using webrtc::PeerConnectionInterface;
48
49 namespace {
50
51 const char kExternalGiceUfrag[] = "1234567890123456";
52 const char kExternalGicePwd[] = "123456789012345678901234";
53 const size_t kMaxWait = 10000;
54
55 void RemoveLinesFromSdp(const std::string& line_start,
56                                std::string* sdp) {
57   const char kSdpLineEnd[] = "\r\n";
58   size_t ssrc_pos = 0;
59   while ((ssrc_pos = sdp->find(line_start, ssrc_pos)) !=
60       std::string::npos) {
61     size_t end_ssrc = sdp->find(kSdpLineEnd, ssrc_pos);
62     sdp->erase(ssrc_pos, end_ssrc - ssrc_pos + strlen(kSdpLineEnd));
63   }
64 }
65
66 // Add |newlines| to the |message| after |line|.
67 void InjectAfter(const std::string& line,
68                  const std::string& newlines,
69                  std::string* message) {
70   const std::string tmp = line + newlines;
71   rtc::replace_substrs(line.c_str(), line.length(),
72                              tmp.c_str(), tmp.length(), message);
73 }
74
75 void Replace(const std::string& line,
76              const std::string& newlines,
77              std::string* message) {
78   rtc::replace_substrs(line.c_str(), line.length(),
79                              newlines.c_str(), newlines.length(), message);
80 }
81
82 void UseExternalSdes(std::string* sdp) {
83   // Remove current crypto specification.
84   RemoveLinesFromSdp("a=crypto", sdp);
85   RemoveLinesFromSdp("a=fingerprint", sdp);
86   // Add external crypto.
87   const char kAudioSdes[] =
88       "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
89       "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR\r\n";
90   const char kVideoSdes[] =
91       "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
92       "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj\r\n";
93   const char kDataSdes[] =
94       "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
95       "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj\r\n";
96   InjectAfter("a=mid:audio\r\n", kAudioSdes, sdp);
97   InjectAfter("a=mid:video\r\n", kVideoSdes, sdp);
98   InjectAfter("a=mid:data\r\n", kDataSdes, sdp);
99 }
100
101 void UseGice(std::string* sdp) {
102   InjectAfter("t=0 0\r\n", "a=ice-options:google-ice\r\n", sdp);
103
104   std::string ufragline = "a=ice-ufrag:";
105   std::string pwdline = "a=ice-pwd:";
106   RemoveLinesFromSdp(ufragline, sdp);
107   RemoveLinesFromSdp(pwdline, sdp);
108   ufragline.append(kExternalGiceUfrag);
109   ufragline.append("\r\n");
110   pwdline.append(kExternalGicePwd);
111   pwdline.append("\r\n");
112   const std::string ufrag_pwd = ufragline + pwdline;
113
114   InjectAfter("a=mid:audio\r\n", ufrag_pwd, sdp);
115   InjectAfter("a=mid:video\r\n", ufrag_pwd, sdp);
116   InjectAfter("a=mid:data\r\n", ufrag_pwd, sdp);
117 }
118
119 void RemoveBundle(std::string* sdp) {
120   RemoveLinesFromSdp("a=group:BUNDLE", sdp);
121 }
122
123 }  // namespace
124
125 class PeerConnectionEndToEndTest
126     : public sigslot::has_slots<>,
127       public testing::Test {
128  public:
129   typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
130       DataChannelList;
131
132   PeerConnectionEndToEndTest()
133       : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
134                     "caller")),
135         callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
136                     "callee")) {
137     rtc::InitializeSSL(NULL);
138   }
139
140   void CreatePcs() {
141     CreatePcs(NULL);
142   }
143
144   void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
145     EXPECT_TRUE(caller_->CreatePc(pc_constraints));
146     EXPECT_TRUE(callee_->CreatePc(pc_constraints));
147     PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
148
149     caller_->SignalOnDataChannel.connect(
150         this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
151     callee_->SignalOnDataChannel.connect(
152         this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
153   }
154
155   void GetAndAddUserMedia() {
156     FakeConstraints audio_constraints;
157     FakeConstraints video_constraints;
158     GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
159   }
160
161   void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
162                           bool video, FakeConstraints video_constraints) {
163     caller_->GetAndAddUserMedia(audio, audio_constraints,
164                                 video, video_constraints);
165     callee_->GetAndAddUserMedia(audio, audio_constraints,
166                                 video, video_constraints);
167   }
168
169   void Negotiate() {
170     caller_->CreateOffer(NULL);
171   }
172
173   void WaitForCallEstablished() {
174     caller_->WaitForCallEstablished();
175     callee_->WaitForCallEstablished();
176   }
177
178   void WaitForConnection() {
179     caller_->WaitForConnection();
180     callee_->WaitForConnection();
181   }
182
183   void SetupLegacySdpConverter() {
184     caller_->SignalOnSdpCreated.connect(
185       this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
186     callee_->SignalOnSdpCreated.connect(
187       this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
188   }
189
190   void ConvertToLegacySdp(std::string* sdp) {
191     UseExternalSdes(sdp);
192     UseGice(sdp);
193     RemoveBundle(sdp);
194     LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
195   }
196
197   void SetupGiceConverter() {
198     caller_->SignalOnIceCandidateCreated.connect(
199       this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
200     callee_->SignalOnIceCandidateCreated.connect(
201       this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
202   }
203
204   void AddGiceCredsToCandidate(std::string* sdp) {
205     std::string gice_creds = " username ";
206     gice_creds.append(kExternalGiceUfrag);
207     gice_creds.append(" password ");
208     gice_creds.append(kExternalGicePwd);
209     gice_creds.append("\r\n");
210     Replace("\r\n", gice_creds, sdp);
211     LOG(LS_INFO) << "AddGiceCredsToCandidate: " << *sdp;
212   }
213
214   void OnCallerAddedDataChanel(DataChannelInterface* dc) {
215     caller_signaled_data_channels_.push_back(dc);
216   }
217
218   void OnCalleeAddedDataChannel(DataChannelInterface* dc) {
219     callee_signaled_data_channels_.push_back(dc);
220   }
221
222   // Tests that |dc1| and |dc2| can send to and receive from each other.
223   void TestDataChannelSendAndReceive(
224       DataChannelInterface* dc1, DataChannelInterface* dc2) {
225     rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer(
226         new webrtc::MockDataChannelObserver(dc1));
227
228     rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
229         new webrtc::MockDataChannelObserver(dc2));
230
231     static const std::string kDummyData = "abcdefg";
232     webrtc::DataBuffer buffer(kDummyData);
233     EXPECT_TRUE(dc1->Send(buffer));
234     EXPECT_EQ_WAIT(kDummyData, dc2_observer->last_message(), kMaxWait);
235
236     EXPECT_TRUE(dc2->Send(buffer));
237     EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait);
238
239     EXPECT_EQ(1U, dc1_observer->received_message_count());
240     EXPECT_EQ(1U, dc2_observer->received_message_count());
241   }
242
243   void WaitForDataChannelsToOpen(DataChannelInterface* local_dc,
244                                  const DataChannelList& remote_dc_list,
245                                  size_t remote_dc_index) {
246     EXPECT_EQ_WAIT(DataChannelInterface::kOpen, local_dc->state(), kMaxWait);
247
248     EXPECT_TRUE_WAIT(remote_dc_list.size() > remote_dc_index, kMaxWait);
249     EXPECT_EQ_WAIT(DataChannelInterface::kOpen,
250                    remote_dc_list[remote_dc_index]->state(),
251                    kMaxWait);
252     EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id());
253   }
254
255   void CloseDataChannels(DataChannelInterface* local_dc,
256                          const DataChannelList& remote_dc_list,
257                          size_t remote_dc_index) {
258     local_dc->Close();
259     EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait);
260     EXPECT_EQ_WAIT(DataChannelInterface::kClosed,
261                    remote_dc_list[remote_dc_index]->state(),
262                    kMaxWait);
263   }
264
265   ~PeerConnectionEndToEndTest() {
266     rtc::CleanupSSL();
267   }
268
269  protected:
270   rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
271   rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
272   DataChannelList caller_signaled_data_channels_;
273   DataChannelList callee_signaled_data_channels_;
274 };
275
276 // Disable for TSan v2, see
277 // https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
278 #if !defined(THREAD_SANITIZER)
279
280 TEST_F(PeerConnectionEndToEndTest, Call) {
281   CreatePcs();
282   GetAndAddUserMedia();
283   Negotiate();
284   WaitForCallEstablished();
285 }
286
287 // Disabled per b/14899892
288 TEST_F(PeerConnectionEndToEndTest, DISABLED_CallWithLegacySdp) {
289   FakeConstraints pc_constraints;
290   pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
291                               false);
292   CreatePcs(&pc_constraints);
293   SetupLegacySdpConverter();
294   SetupGiceConverter();
295   GetAndAddUserMedia();
296   Negotiate();
297   WaitForCallEstablished();
298 }
299
300 // Verifies that a DataChannel created before the negotiation can transition to
301 // "OPEN" and transfer data.
302 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
303   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
304
305   CreatePcs();
306
307   webrtc::DataChannelInit init;
308   rtc::scoped_refptr<DataChannelInterface> caller_dc(
309       caller_->CreateDataChannel("data", init));
310   rtc::scoped_refptr<DataChannelInterface> callee_dc(
311       callee_->CreateDataChannel("data", init));
312
313   Negotiate();
314   WaitForConnection();
315
316   WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
317   WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
318
319   TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
320   TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
321
322   CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
323   CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
324 }
325
326 // Verifies that a DataChannel created after the negotiation can transition to
327 // "OPEN" and transfer data.
328 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelAfterNegotiate) {
329   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
330
331   CreatePcs();
332
333   webrtc::DataChannelInit init;
334
335   // This DataChannel is for creating the data content in the negotiation.
336   rtc::scoped_refptr<DataChannelInterface> dummy(
337       caller_->CreateDataChannel("data", init));
338   Negotiate();
339   WaitForConnection();
340
341   // Creates new DataChannels after the negotiation and verifies their states.
342   rtc::scoped_refptr<DataChannelInterface> caller_dc(
343       caller_->CreateDataChannel("hello", init));
344   rtc::scoped_refptr<DataChannelInterface> callee_dc(
345       callee_->CreateDataChannel("hello", init));
346
347   WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
348   WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
349
350   TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
351   TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
352
353   CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
354   CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
355 }
356
357 // Verifies that DataChannel IDs are even/odd based on the DTLS roles.
358 TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
359   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
360
361   CreatePcs();
362
363   webrtc::DataChannelInit init;
364   rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
365       caller_->CreateDataChannel("data", init));
366   rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
367       callee_->CreateDataChannel("data", init));
368
369   Negotiate();
370   WaitForConnection();
371
372   EXPECT_EQ(1U, caller_dc_1->id() % 2);
373   EXPECT_EQ(0U, callee_dc_1->id() % 2);
374
375   rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
376       caller_->CreateDataChannel("data", init));
377   rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
378       callee_->CreateDataChannel("data", init));
379
380   EXPECT_EQ(1U, caller_dc_2->id() % 2);
381   EXPECT_EQ(0U, callee_dc_2->id() % 2);
382 }
383
384 // Verifies that the message is received by the right remote DataChannel when
385 // there are multiple DataChannels.
386 TEST_F(PeerConnectionEndToEndTest,
387        MessageTransferBetweenTwoPairsOfDataChannels) {
388   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
389
390   CreatePcs();
391
392   webrtc::DataChannelInit init;
393
394   rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
395       caller_->CreateDataChannel("data", init));
396   rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
397       caller_->CreateDataChannel("data", init));
398
399   Negotiate();
400   WaitForConnection();
401   WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
402   WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
403
404   rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
405       new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
406
407   rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
408       new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
409
410   const std::string message_1 = "hello 1";
411   const std::string message_2 = "hello 2";
412
413   caller_dc_1->Send(webrtc::DataBuffer(message_1));
414   EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
415
416   caller_dc_2->Send(webrtc::DataBuffer(message_2));
417   EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
418
419   EXPECT_EQ(1U, dc_1_observer->received_message_count());
420   EXPECT_EQ(1U, dc_2_observer->received_message_count());
421 }
422 #endif // if !defined(THREAD_SANITIZER)