blob: 7da7cc81398e02ac7c0bb60ee2155333ba98451a [file] [log] [blame]
wu@webrtc.org364f2042013-11-20 21:49:41 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2013 Google Inc.
wu@webrtc.org364f2042013-11-20 21:49:41 +00004 *
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
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000028#include "talk/app/webrtc/test/peerconnectiontestwrapper.h"
henrike@webrtc.orgd968dd02014-08-13 18:39:43 +000029#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000030#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"
wu@webrtc.org364f2042013-11-20 21:49:41 +000036
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +000037#define MAYBE_SKIP_TEST(feature) \
38 if (!(feature())) { \
39 LOG(LS_INFO) << "Feature disabled... skipping"; \
40 return; \
41 }
42
43using webrtc::DataChannelInterface;
wu@webrtc.org364f2042013-11-20 21:49:41 +000044using webrtc::FakeConstraints;
45using webrtc::MediaConstraintsInterface;
46using webrtc::MediaStreamInterface;
47using webrtc::PeerConnectionInterface;
48
49namespace {
50
pthatcherfa301802015-08-11 04:12:56 -070051const char kExternalGiceUfrag[] = "1234567890123456";
52const char kExternalGicePwd[] = "123456789012345678901234";
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +000053const size_t kMaxWait = 10000;
wu@webrtc.org364f2042013-11-20 21:49:41 +000054
55void 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|.
67void InjectAfter(const std::string& line,
68 const std::string& newlines,
69 std::string* message) {
70 const std::string tmp = line + newlines;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000071 rtc::replace_substrs(line.c_str(), line.length(),
wu@webrtc.org364f2042013-11-20 21:49:41 +000072 tmp.c_str(), tmp.length(), message);
73}
74
75void Replace(const std::string& line,
76 const std::string& newlines,
77 std::string* message) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000078 rtc::replace_substrs(line.c_str(), line.length(),
wu@webrtc.org364f2042013-11-20 21:49:41 +000079 newlines.c_str(), newlines.length(), message);
80}
81
82void 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
pthatcherfa301802015-08-11 04:12:56 -0700101void 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
wu@webrtc.org364f2042013-11-20 21:49:41 +0000119void RemoveBundle(std::string* sdp) {
120 RemoveLinesFromSdp("a=group:BUNDLE", sdp);
121}
122
123} // namespace
124
125class PeerConnectionEndToEndTest
126 : public sigslot::has_slots<>,
127 public testing::Test {
128 public:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000129 typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000130 DataChannelList;
131
wu@webrtc.org364f2042013-11-20 21:49:41 +0000132 PeerConnectionEndToEndTest()
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000133 : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
wu@webrtc.org364f2042013-11-20 21:49:41 +0000134 "caller")),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000135 callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
wu@webrtc.org364f2042013-11-20 21:49:41 +0000136 "callee")) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000137 }
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());
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000147
148 caller_->SignalOnDataChannel.connect(
149 this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
150 callee_->SignalOnDataChannel.connect(
151 this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
wu@webrtc.org364f2042013-11-20 21:49:41 +0000152 }
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
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000177 void WaitForConnection() {
178 caller_->WaitForConnection();
179 callee_->WaitForConnection();
180 }
181
pthatcherfa301802015-08-11 04:12:56 -0700182 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
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000213 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) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000224 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000225 new webrtc::MockDataChannelObserver(dc1));
226
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000227 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000228 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
wu@webrtc.org364f2042013-11-20 21:49:41 +0000264 protected:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000265 rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
266 rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000267 DataChannelList caller_signaled_data_channels_;
268 DataChannelList callee_signaled_data_channels_;
wu@webrtc.org364f2042013-11-20 21:49:41 +0000269};
270
wu@webrtc.orgb43202d2013-11-22 19:14:25 +0000271// Disable for TSan v2, see
272// https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
273#if !defined(THREAD_SANITIZER)
274
henrik.lundin@webrtc.org0b44b582015-03-23 19:47:53 +0000275// Flaky on Windows. Disabled per issue 4464.
276#ifdef WEBRTC_WIN
277#define MAYBE_Call DISABLED_Call
278#else
279#define MAYBE_Call Call
280#endif
281TEST_F(PeerConnectionEndToEndTest, MAYBE_Call) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000282 CreatePcs();
283 GetAndAddUserMedia();
284 Negotiate();
285 WaitForCallEstablished();
286}
287
buildbot@webrtc.orgda510c52014-05-13 22:30:56 +0000288// Disabled per b/14899892
289TEST_F(PeerConnectionEndToEndTest, DISABLED_CallWithLegacySdp) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000290 FakeConstraints pc_constraints;
291 pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
292 false);
293 CreatePcs(&pc_constraints);
pthatcherfa301802015-08-11 04:12:56 -0700294 SetupLegacySdpConverter();
295 SetupGiceConverter();
wu@webrtc.org364f2042013-11-20 21:49:41 +0000296 GetAndAddUserMedia();
297 Negotiate();
298 WaitForCallEstablished();
299}
wu@webrtc.orgb43202d2013-11-22 19:14:25 +0000300
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000301// Verifies that a DataChannel created before the negotiation can transition to
302// "OPEN" and transfer data.
303TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000304 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000305
306 CreatePcs();
307
308 webrtc::DataChannelInit init;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000309 rtc::scoped_refptr<DataChannelInterface> caller_dc(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000310 caller_->CreateDataChannel("data", init));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000311 rtc::scoped_refptr<DataChannelInterface> callee_dc(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000312 callee_->CreateDataChannel("data", init));
313
314 Negotiate();
315 WaitForConnection();
316
317 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
318 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
319
320 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
321 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
322
323 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
324 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
325}
326
327// Verifies that a DataChannel created after the negotiation can transition to
328// "OPEN" and transfer data.
henrik.lundin@webrtc.org22362672014-11-03 13:38:50 +0000329#if defined(MEMORY_SANITIZER)
330// Fails under MemorySanitizer:
331// See https://code.google.com/p/webrtc/issues/detail?id=3980.
332#define MAYBE_CreateDataChannelAfterNegotiate DISABLED_CreateDataChannelAfterNegotiate
333#else
334#define MAYBE_CreateDataChannelAfterNegotiate CreateDataChannelAfterNegotiate
335#endif
336TEST_F(PeerConnectionEndToEndTest, MAYBE_CreateDataChannelAfterNegotiate) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000337 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000338
339 CreatePcs();
340
341 webrtc::DataChannelInit init;
342
343 // This DataChannel is for creating the data content in the negotiation.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000344 rtc::scoped_refptr<DataChannelInterface> dummy(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000345 caller_->CreateDataChannel("data", init));
346 Negotiate();
347 WaitForConnection();
348
349 // Creates new DataChannels after the negotiation and verifies their states.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000350 rtc::scoped_refptr<DataChannelInterface> caller_dc(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000351 caller_->CreateDataChannel("hello", init));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000352 rtc::scoped_refptr<DataChannelInterface> callee_dc(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000353 callee_->CreateDataChannel("hello", init));
354
355 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
356 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
357
358 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
359 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
360
361 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
362 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
363}
364
365// Verifies that DataChannel IDs are even/odd based on the DTLS roles.
366TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000367 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000368
369 CreatePcs();
370
371 webrtc::DataChannelInit init;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000372 rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000373 caller_->CreateDataChannel("data", init));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000374 rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000375 callee_->CreateDataChannel("data", init));
376
377 Negotiate();
378 WaitForConnection();
379
380 EXPECT_EQ(1U, caller_dc_1->id() % 2);
381 EXPECT_EQ(0U, callee_dc_1->id() % 2);
382
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000383 rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000384 caller_->CreateDataChannel("data", init));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000385 rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000386 callee_->CreateDataChannel("data", init));
387
388 EXPECT_EQ(1U, caller_dc_2->id() % 2);
389 EXPECT_EQ(0U, callee_dc_2->id() % 2);
390}
391
392// Verifies that the message is received by the right remote DataChannel when
393// there are multiple DataChannels.
394TEST_F(PeerConnectionEndToEndTest,
395 MessageTransferBetweenTwoPairsOfDataChannels) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000396 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000397
398 CreatePcs();
399
400 webrtc::DataChannelInit init;
401
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000402 rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000403 caller_->CreateDataChannel("data", init));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000404 rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000405 caller_->CreateDataChannel("data", init));
406
407 Negotiate();
408 WaitForConnection();
409 WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
410 WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
411
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000412 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000413 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
414
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000415 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
jiayl@webrtc.org1a6c6282014-06-12 21:59:29 +0000416 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
417
418 const std::string message_1 = "hello 1";
419 const std::string message_2 = "hello 2";
420
421 caller_dc_1->Send(webrtc::DataBuffer(message_1));
422 EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
423
424 caller_dc_2->Send(webrtc::DataBuffer(message_2));
425 EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
426
427 EXPECT_EQ(1U, dc_1_observer->received_message_count());
428 EXPECT_EQ(1U, dc_2_observer->received_message_count());
429}
wu@webrtc.orgb43202d2013-11-22 19:14:25 +0000430#endif // if !defined(THREAD_SANITIZER)