Update To 11.40.268.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   }
138
139   void CreatePcs() {
140     CreatePcs(NULL);
141   }
142
143   void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
144     EXPECT_TRUE(caller_->CreatePc(pc_constraints));
145     EXPECT_TRUE(callee_->CreatePc(pc_constraints));
146     PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
147
148     caller_->SignalOnDataChannel.connect(
149         this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
150     callee_->SignalOnDataChannel.connect(
151         this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
152   }
153
154   void GetAndAddUserMedia() {
155     FakeConstraints audio_constraints;
156     FakeConstraints video_constraints;
157     GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
158   }
159
160   void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
161                           bool video, FakeConstraints video_constraints) {
162     caller_->GetAndAddUserMedia(audio, audio_constraints,
163                                 video, video_constraints);
164     callee_->GetAndAddUserMedia(audio, audio_constraints,
165                                 video, video_constraints);
166   }
167
168   void Negotiate() {
169     caller_->CreateOffer(NULL);
170   }
171
172   void WaitForCallEstablished() {
173     caller_->WaitForCallEstablished();
174     callee_->WaitForCallEstablished();
175   }
176
177   void WaitForConnection() {
178     caller_->WaitForConnection();
179     callee_->WaitForConnection();
180   }
181
182   void SetupLegacySdpConverter() {
183     caller_->SignalOnSdpCreated.connect(
184       this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
185     callee_->SignalOnSdpCreated.connect(
186       this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
187   }
188
189   void ConvertToLegacySdp(std::string* sdp) {
190     UseExternalSdes(sdp);
191     UseGice(sdp);
192     RemoveBundle(sdp);
193     LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
194   }
195
196   void SetupGiceConverter() {
197     caller_->SignalOnIceCandidateCreated.connect(
198       this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
199     callee_->SignalOnIceCandidateCreated.connect(
200       this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
201   }
202
203   void AddGiceCredsToCandidate(std::string* sdp) {
204     std::string gice_creds = " username ";
205     gice_creds.append(kExternalGiceUfrag);
206     gice_creds.append(" password ");
207     gice_creds.append(kExternalGicePwd);
208     gice_creds.append("\r\n");
209     Replace("\r\n", gice_creds, sdp);
210     LOG(LS_INFO) << "AddGiceCredsToCandidate: " << *sdp;
211   }
212
213   void OnCallerAddedDataChanel(DataChannelInterface* dc) {
214     caller_signaled_data_channels_.push_back(dc);
215   }
216
217   void OnCalleeAddedDataChannel(DataChannelInterface* dc) {
218     callee_signaled_data_channels_.push_back(dc);
219   }
220
221   // Tests that |dc1| and |dc2| can send to and receive from each other.
222   void TestDataChannelSendAndReceive(
223       DataChannelInterface* dc1, DataChannelInterface* dc2) {
224     rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer(
225         new webrtc::MockDataChannelObserver(dc1));
226
227     rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
228         new webrtc::MockDataChannelObserver(dc2));
229
230     static const std::string kDummyData = "abcdefg";
231     webrtc::DataBuffer buffer(kDummyData);
232     EXPECT_TRUE(dc1->Send(buffer));
233     EXPECT_EQ_WAIT(kDummyData, dc2_observer->last_message(), kMaxWait);
234
235     EXPECT_TRUE(dc2->Send(buffer));
236     EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait);
237
238     EXPECT_EQ(1U, dc1_observer->received_message_count());
239     EXPECT_EQ(1U, dc2_observer->received_message_count());
240   }
241
242   void WaitForDataChannelsToOpen(DataChannelInterface* local_dc,
243                                  const DataChannelList& remote_dc_list,
244                                  size_t remote_dc_index) {
245     EXPECT_EQ_WAIT(DataChannelInterface::kOpen, local_dc->state(), kMaxWait);
246
247     EXPECT_TRUE_WAIT(remote_dc_list.size() > remote_dc_index, kMaxWait);
248     EXPECT_EQ_WAIT(DataChannelInterface::kOpen,
249                    remote_dc_list[remote_dc_index]->state(),
250                    kMaxWait);
251     EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id());
252   }
253
254   void CloseDataChannels(DataChannelInterface* local_dc,
255                          const DataChannelList& remote_dc_list,
256                          size_t remote_dc_index) {
257     local_dc->Close();
258     EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait);
259     EXPECT_EQ_WAIT(DataChannelInterface::kClosed,
260                    remote_dc_list[remote_dc_index]->state(),
261                    kMaxWait);
262   }
263
264  protected:
265   rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
266   rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
267   DataChannelList caller_signaled_data_channels_;
268   DataChannelList callee_signaled_data_channels_;
269 };
270
271 // Disable for TSan v2, see
272 // https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
273 #if !defined(THREAD_SANITIZER)
274
275 TEST_F(PeerConnectionEndToEndTest, Call) {
276   CreatePcs();
277   GetAndAddUserMedia();
278   Negotiate();
279   WaitForCallEstablished();
280 }
281
282 // Disabled per b/14899892
283 TEST_F(PeerConnectionEndToEndTest, DISABLED_CallWithLegacySdp) {
284   FakeConstraints pc_constraints;
285   pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
286                               false);
287   CreatePcs(&pc_constraints);
288   SetupLegacySdpConverter();
289   SetupGiceConverter();
290   GetAndAddUserMedia();
291   Negotiate();
292   WaitForCallEstablished();
293 }
294
295 // Verifies that a DataChannel created before the negotiation can transition to
296 // "OPEN" and transfer data.
297 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
298   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
299
300   CreatePcs();
301
302   webrtc::DataChannelInit init;
303   rtc::scoped_refptr<DataChannelInterface> caller_dc(
304       caller_->CreateDataChannel("data", init));
305   rtc::scoped_refptr<DataChannelInterface> callee_dc(
306       callee_->CreateDataChannel("data", init));
307
308   Negotiate();
309   WaitForConnection();
310
311   WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
312   WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
313
314   TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
315   TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
316
317   CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
318   CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
319 }
320
321 // Verifies that a DataChannel created after the negotiation can transition to
322 // "OPEN" and transfer data.
323 #if defined(MEMORY_SANITIZER)
324 // Fails under MemorySanitizer:
325 // See https://code.google.com/p/webrtc/issues/detail?id=3980.
326 #define MAYBE_CreateDataChannelAfterNegotiate DISABLED_CreateDataChannelAfterNegotiate
327 #else
328 #define MAYBE_CreateDataChannelAfterNegotiate CreateDataChannelAfterNegotiate
329 #endif
330 TEST_F(PeerConnectionEndToEndTest, MAYBE_CreateDataChannelAfterNegotiate) {
331   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
332
333   CreatePcs();
334
335   webrtc::DataChannelInit init;
336
337   // This DataChannel is for creating the data content in the negotiation.
338   rtc::scoped_refptr<DataChannelInterface> dummy(
339       caller_->CreateDataChannel("data", init));
340   Negotiate();
341   WaitForConnection();
342
343   // Creates new DataChannels after the negotiation and verifies their states.
344   rtc::scoped_refptr<DataChannelInterface> caller_dc(
345       caller_->CreateDataChannel("hello", init));
346   rtc::scoped_refptr<DataChannelInterface> callee_dc(
347       callee_->CreateDataChannel("hello", init));
348
349   WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
350   WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
351
352   TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
353   TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
354
355   CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
356   CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
357 }
358
359 // Verifies that DataChannel IDs are even/odd based on the DTLS roles.
360 TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
361   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
362
363   CreatePcs();
364
365   webrtc::DataChannelInit init;
366   rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
367       caller_->CreateDataChannel("data", init));
368   rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
369       callee_->CreateDataChannel("data", init));
370
371   Negotiate();
372   WaitForConnection();
373
374   EXPECT_EQ(1U, caller_dc_1->id() % 2);
375   EXPECT_EQ(0U, callee_dc_1->id() % 2);
376
377   rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
378       caller_->CreateDataChannel("data", init));
379   rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
380       callee_->CreateDataChannel("data", init));
381
382   EXPECT_EQ(1U, caller_dc_2->id() % 2);
383   EXPECT_EQ(0U, callee_dc_2->id() % 2);
384 }
385
386 // Verifies that the message is received by the right remote DataChannel when
387 // there are multiple DataChannels.
388 TEST_F(PeerConnectionEndToEndTest,
389        MessageTransferBetweenTwoPairsOfDataChannels) {
390   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
391
392   CreatePcs();
393
394   webrtc::DataChannelInit init;
395
396   rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
397       caller_->CreateDataChannel("data", init));
398   rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
399       caller_->CreateDataChannel("data", init));
400
401   Negotiate();
402   WaitForConnection();
403   WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
404   WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
405
406   rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
407       new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
408
409   rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
410       new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
411
412   const std::string message_1 = "hello 1";
413   const std::string message_2 = "hello 2";
414
415   caller_dc_1->Send(webrtc::DataBuffer(message_1));
416   EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
417
418   caller_dc_2->Send(webrtc::DataBuffer(message_2));
419   EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
420
421   EXPECT_EQ(1U, dc_1_observer->received_message_count());
422   EXPECT_EQ(1U, dc_2_observer->received_message_count());
423 }
424 #endif // if !defined(THREAD_SANITIZER)